-Intel P-state driver
+Intel P-State driver
--------------------
-This driver provides an interface to control the P state selection for
-SandyBridge+ Intel processors. The driver can operate two different
-modes based on the processor model, legacy mode and Hardware P state (HWP)
-mode.
-
-In legacy mode, the Intel P-state implements two internal governors,
-performance and powersave, that differ from the general cpufreq governors of
-the same name (the general cpufreq governors implement target(), whereas the
-internal Intel P-state governors implement setpolicy()). The internal
-performance governor sets the max_perf_pct and min_perf_pct to 100; that is,
-the governor selects the highest available P state to maximize the performance
-of the core. The internal powersave governor selects the appropriate P state
-based on the current load on the CPU.
-
-In HWP mode P state selection is implemented in the processor
-itself. The driver provides the interfaces between the cpufreq core and
-the processor to control P state selection based on user preferences
-and reporting frequency to the cpufreq core. In this mode the
-internal Intel P-state governor code is disabled.
-
-In addition to the interfaces provided by the cpufreq core for
-controlling frequency the driver provides sysfs files for
-controlling P state selection. These files have been added to
-/sys/devices/system/cpu/intel_pstate/
-
- max_perf_pct: limits the maximum P state that will be requested by
- the driver stated as a percentage of the available performance. The
- available (P states) performance may be reduced by the no_turbo
+This driver provides an interface to control the P-State selection for the
+SandyBridge+ Intel processors.
+
+The following document explains P-States:
+http://events.linuxfoundation.org/sites/events/files/slides/LinuxConEurope_2015.pdf
+As stated in the document, P-State doesn’t exactly mean a frequency. However, for
+the sake of the relationship with cpufreq, P-State and frequency are used
+interchangeably.
+
+Understanding the cpufreq core governors and policies are important before
+discussing more details about the Intel P-State driver. Based on what callbacks
+a cpufreq driver provides to the cpufreq core, it can support two types of
+drivers:
+- with target_index() callback: In this mode, the drivers using cpufreq core
+simply provide the minimum and maximum frequency limits and an additional
+interface target_index() to set the current frequency. The cpufreq subsystem
+has a number of scaling governors ("performance", "powersave", "ondemand",
+etc.). Depending on which governor is in use, cpufreq core will call for
+transitions to a specific frequency using target_index() callback.
+- setpolicy() callback: In this mode, drivers do not provide target_index()
+callback, so cpufreq core can't request a transition to a specific frequency.
+The driver provides minimum and maximum frequency limits and callbacks to set a
+policy. The policy in cpufreq sysfs is referred to as the "scaling governor".
+The cpufreq core can request the driver to operate in any of the two policies:
+"performance: and "powersave". The driver decides which frequency to use based
+on the above policy selection considering minimum and maximum frequency limits.
+
+The Intel P-State driver falls under the latter category, which implements the
+setpolicy() callback. This driver decides what P-State to use based on the
+requested policy from the cpufreq core. If the processor is capable of
+selecting its next P-State internally, then the driver will offload this
+responsibility to the processor (aka HWP: Hardware P-States). If not, the
+driver implements algorithms to select the next P-State.
+
+Since these policies are implemented in the driver, they are not same as the
+cpufreq scaling governors implementation, even if they have the same name in
+the cpufreq sysfs (scaling_governors). For example the "performance" policy is
+similar to cpufreq’s "performance" governor, but "powersave" is completely
+different than the cpufreq "powersave" governor. The strategy here is similar
+to cpufreq "ondemand", where the requested P-State is related to the system load.
+
+Sysfs Interface
+
+In addition to the frequency-controlling interfaces provided by the cpufreq
+core, the driver provides its own sysfs files to control the P-State selection.
+These files have been added to /sys/devices/system/cpu/intel_pstate/.
+Any changes made to these files are applicable to all CPUs (even in a
+multi-package system).
+
+ max_perf_pct: Limits the maximum P-State that will be requested by
+ the driver. It states it as a percentage of the available performance. The
+ available (P-State) performance may be reduced by the no_turbo
setting described below.
- min_perf_pct: limits the minimum P state that will be requested by
- the driver stated as a percentage of the max (non-turbo)
+ min_perf_pct: Limits the minimum P-State that will be requested by
+ the driver. It states it as a percentage of the max (non-turbo)
performance level.
- no_turbo: limits the driver to selecting P states below the turbo
+ no_turbo: Limits the driver to selecting P-State below the turbo
frequency range.
- turbo_pct: displays the percentage of the total performance that
- is supported by hardware that is in the turbo range. This number
+ turbo_pct: Displays the percentage of the total performance that
+ is supported by hardware that is in the turbo range. This number
is independent of whether turbo has been disabled or not.
- num_pstates: displays the number of pstates that are supported
- by hardware. This number is independent of whether turbo has
+ num_pstates: Displays the number of P-States that are supported
+ by hardware. This number is independent of whether turbo has
been disabled or not.
+For example, if a system has these parameters:
+ Max 1 core turbo ratio: 0x21 (Max 1 core ratio is the maximum P-State)
+ Max non turbo ratio: 0x17
+ Minimum ratio : 0x08 (Here the ratio is called max efficiency ratio)
+
+Sysfs will show :
+ max_perf_pct:100, which corresponds to 1 core ratio
+ min_perf_pct:24, max_efficiency_ratio / max 1 Core ratio
+ no_turbo:0, turbo is not disabled
+ num_pstates:26 = (max 1 Core ratio - Max Efficiency Ratio + 1)
+ turbo_pct:39 = (max 1 core ratio - max non turbo ratio) / num_pstates
+
+Refer to "Intel® 64 and IA-32 Architectures Software Developer’s Manual
+Volume 3: System Programming Guide" to understand ratios.
+
+cpufreq sysfs for Intel P-State
+
+Since this driver registers with cpufreq, cpufreq sysfs is also presented.
+There are some important differences, which need to be considered.
+
+scaling_cur_freq: This displays the real frequency which was used during
+the last sample period instead of what is requested. Some other cpufreq driver,
+like acpi-cpufreq, displays what is requested (Some changes are on the
+way to fix this for acpi-cpufreq driver). The same is true for frequencies
+displayed at /proc/cpuinfo.
+
+scaling_governor: This displays current active policy. Since each CPU has a
+cpufreq sysfs, it is possible to set a scaling governor to each CPU. But this
+is not possible with Intel P-States, as there is one common policy for all
+CPUs. Here, the last requested policy will be applicable to all CPUs. It is
+suggested that one use the cpupower utility to change policy to all CPUs at the
+same time.
+
+scaling_setspeed: This attribute can never be used with Intel P-State.
+
+scaling_max_freq/scaling_min_freq: This interface can be used similarly to
+the max_perf_pct/min_perf_pct of Intel P-State sysfs. However since frequencies
+are converted to nearest possible P-State, this is prone to rounding errors.
+This method is not preferred to limit performance.
+
+affected_cpus: Not used
+related_cpus: Not used
+
For contemporary Intel processors, the frequency is controlled by the
-processor itself and the P-states exposed to software are related to
+processor itself and the P-State exposed to software is related to
performance levels. The idea that frequency can be set to a single
-frequency is fiction for Intel Core processors. Even if the scaling
-driver selects a single P state the actual frequency the processor
+frequency is fictional for Intel Core processors. Even if the scaling
+driver selects a single P-State, the actual frequency the processor
will run at is selected by the processor itself.
-For legacy mode debugfs files have also been added to allow tuning of
-the internal governor algorythm. These files are located at
-/sys/kernel/debug/pstate_snb/ These files are NOT present in HWP mode.
+Tuning Intel P-State driver
+
+When HWP mode is not used, debugfs files have also been added to allow the
+tuning of the internal governor algorithm. These files are located at
+/sys/kernel/debug/pstate_snb/. The algorithm uses a PID (Proportional
+Integral Derivative) controller. The PID tunable parameters are:
deadband
d_gain_pct
p_gain_pct
sample_rate_ms
setpoint
+
+To adjust these parameters, some understanding of driver implementation is
+necessary. There are some tweeks described here, but be very careful. Adjusting
+them requires expert level understanding of power and performance relationship.
+These limits are only useful when the "powersave" policy is active.
+
+-To make the system more responsive to load changes, sample_rate_ms can
+be adjusted (current default is 10ms).
+-To make the system use higher performance, even if the load is lower, setpoint
+can be adjusted to a lower number. This will also lead to faster ramp up time
+to reach the maximum P-State.
+If there are no derivative and integral coefficients, The next P-State will be
+equal to:
+ current P-State - ((setpoint - current cpu load) * p_gain_pct)
+
+For example, if the current PID parameters are (Which are defaults for the core
+processors like SandyBridge):
+ deadband = 0
+ d_gain_pct = 0
+ i_gain_pct = 0
+ p_gain_pct = 20
+ sample_rate_ms = 10
+ setpoint = 97
+
+If the current P-State = 0x08 and current load = 100, this will result in the
+next P-State = 0x08 - ((97 - 100) * 0.2) = 8.6 (rounded to 9). Here the P-State
+goes up by only 1. If during next sample interval the current load doesn't
+change and still 100, then P-State goes up by one again. This process will
+continue as long as the load is more than the setpoint until the maximum P-State
+is reached.
+
+For the same load at setpoint = 60, this will result in the next P-State
+= 0x08 - ((60 - 100) * 0.2) = 16
+So by changing the setpoint from 97 to 60, there is an increase of the
+next P-State from 9 to 16. So this will make processor execute at higher
+P-State for the same CPU load. If the load continues to be more than the
+setpoint during next sample intervals, then P-State will go up again till the
+maximum P-State is reached. But the ramp up time to reach the maximum P-State
+will be much faster when the setpoint is 60 compared to 97.
+
+Debugging Intel P-State driver
+
+Event tracing
+To debug P-State transition, the Linux event tracing interface can be used.
+There are two specific events, which can be enabled (Provided the kernel
+configs related to event tracing are enabled).
+
+# cd /sys/kernel/debug/tracing/
+# echo 1 > events/power/pstate_sample/enable
+# echo 1 > events/power/cpu_frequency/enable
+# cat trace
+gnome-terminal--4510 [001] ..s. 1177.680733: pstate_sample: core_busy=107
+ scaled=94 from=26 to=26 mperf=1143818 aperf=1230607 tsc=29838618
+ freq=2474476
+cat-5235 [002] ..s. 1177.681723: cpu_frequency: state=2900000 cpu_id=2
+
+
+Using ftrace
+
+If function level tracing is required, the Linux ftrace interface can be used.
+For example if we want to check how often a function to set a P-State is
+called, we can set ftrace filter to intel_pstate_set_pstate.
+
+# cd /sys/kernel/debug/tracing/
+# cat available_filter_functions | grep -i pstate
+intel_pstate_set_pstate
+intel_pstate_cpu_init
+...
+
+# echo intel_pstate_set_pstate > set_ftrace_filter
+# echo function > current_tracer
+# cat trace | head -15
+# tracer: function
+#
+# entries-in-buffer/entries-written: 80/80 #P:4
+#
+# _-----=> irqs-off
+# / _----=> need-resched
+# | / _---=> hardirq/softirq
+# || / _--=> preempt-depth
+# ||| / delay
+# TASK-PID CPU# |||| TIMESTAMP FUNCTION
+# | | | |||| | |
+ Xorg-3129 [000] ..s. 2537.644844: intel_pstate_set_pstate <-intel_pstate_timer_func
+ gnome-terminal--4510 [002] ..s. 2537.649844: intel_pstate_set_pstate <-intel_pstate_timer_func
+ gnome-shell-3409 [001] ..s. 2537.650850: intel_pstate_set_pstate <-intel_pstate_timer_func
+ <idle>-0 [000] ..s. 2537.654843: intel_pstate_set_pstate <-intel_pstate_timer_func
2.2 cpuinfo_transition_latency:
-------------------------------
-The cpuinfo_transition_latency field is 0. The PCC specification does
-not include a field to expose this value currently.
+The cpuinfo_transition_latency field is CPUFREQ_ETERNAL. The PCC specification
+does not include a field to expose this value currently.
2.3 cpuinfo_cur_freq:
---------------------
Definition: Specifies the syscon node controlling the cpu core
power domains.
+ - dynamic-power-coefficient
+ Usage: optional
+ Value type: <prop-encoded-array>
+ Definition: A u32 value that represents the running time dynamic
+ power coefficient in units of mW/MHz/uVolt^2. The
+ coefficient can either be calculated from power
+ measurements or derived by analysis.
+
+ The dynamic power consumption of the CPU is
+ proportional to the square of the Voltage (V) and
+ the clock frequency (f). The coefficient is used to
+ calculate the dynamic power as below -
+
+ Pdyn = dynamic-power-coefficient * V^2 * f
+
+ where voltage is in uV, frequency is in MHz.
+
Example 1 (dual-cluster big.LITTLE system 32-bit):
cpus {
--- /dev/null
+Binding for ST's CPUFreq driver
+===============================
+
+ST's CPUFreq driver attempts to read 'process' and 'version' attributes
+from the SoC, then supplies the OPP framework with 'prop' and 'supported
+hardware' information respectively. The framework is then able to read
+the DT and operate in the usual way.
+
+For more information about the expected DT format [See: ../opp/opp.txt].
+
+Frequency Scaling only
+----------------------
+
+No vendor specific driver required for this.
+
+Located in CPU's node:
+
+- operating-points : [See: ../power/opp.txt]
+
+Example [safe]
+--------------
+
+cpus {
+ cpu@0 {
+ /* kHz uV */
+ operating-points = <1500000 0
+ 1200000 0
+ 800000 0
+ 500000 0>;
+ };
+};
+
+Dynamic Voltage and Frequency Scaling (DVFS)
+--------------------------------------------
+
+This requires the ST CPUFreq driver to supply 'process' and 'version' info.
+
+Located in CPU's node:
+
+- operating-points-v2 : [See ../power/opp.txt]
+
+Example [unsafe]
+----------------
+
+cpus {
+ cpu@0 {
+ operating-points-v2 = <&cpu0_opp_table>;
+ };
+};
+
+cpu0_opp_table: opp_table {
+ compatible = "operating-points-v2";
+
+ /* ############################################################### */
+ /* # WARNING: Do not attempt to copy/replicate these nodes, # */
+ /* # they are only to be supplied by the bootloader !!! # */
+ /* ############################################################### */
+ opp0 {
+ /* Major Minor Substrate */
+ /* 2 all all */
+ opp-supported-hw = <0x00000004 0xffffffff 0xffffffff>;
+ opp-hz = /bits/ 64 <1500000000>;
+ clock-latency-ns = <10000000>;
+
+ opp-microvolt-pcode0 = <1200000>;
+ opp-microvolt-pcode1 = <1200000>;
+ opp-microvolt-pcode2 = <1200000>;
+ opp-microvolt-pcode3 = <1200000>;
+ opp-microvolt-pcode4 = <1170000>;
+ opp-microvolt-pcode5 = <1140000>;
+ opp-microvolt-pcode6 = <1100000>;
+ opp-microvolt-pcode7 = <1070000>;
+ };
+
+ opp1 {
+ /* Major Minor Substrate */
+ /* all all all */
+ opp-supported-hw = <0xffffffff 0xffffffff 0xffffffff>;
+ opp-hz = /bits/ 64 <1200000000>;
+ clock-latency-ns = <10000000>;
+
+ opp-microvolt-pcode0 = <1110000>;
+ opp-microvolt-pcode1 = <1150000>;
+ opp-microvolt-pcode2 = <1100000>;
+ opp-microvolt-pcode3 = <1080000>;
+ opp-microvolt-pcode4 = <1040000>;
+ opp-microvolt-pcode5 = <1020000>;
+ opp-microvolt-pcode6 = <980000>;
+ opp-microvolt-pcode7 = <930000>;
+ };
+};
phandle to a OPP table in their DT node. The OPP core will use this phandle to
find the operating points for the device.
-Devices may want to choose OPP tables at runtime and so can provide a list of
-phandles here. But only *one* of them should be chosen at runtime. This must be
-accompanied by a corresponding "operating-points-names" property, to uniquely
-identify the OPP tables.
-
If required, this can be extended for SoC vendor specfic bindings. Such bindings
should be documented as Documentation/devicetree/bindings/power/<vendor>-opp.txt
and should have a compatible description like: "operating-points-v2-<vendor>".
-Optional properties:
-- operating-points-names: Names of OPP tables (required if multiple OPP
- tables are present), to uniquely identify them. The same list must be present
- for all the CPUs which are sharing clock/voltage rails and hence the OPP
- tables.
-
* OPP Table Node
This describes the OPPs belonging to a device. This node can have following
Entries for multiple regulators must be present in the same order as
regulators are specified in device's DT node.
+- opp-microvolt-<name>: Named opp-microvolt property. This is exactly similar to
+ the above opp-microvolt property, but allows multiple voltage ranges to be
+ provided for the same OPP. At runtime, the platform can pick a <name> and
+ matching opp-microvolt-<name> property will be enabled for all OPPs. If the
+ platform doesn't pick a specific <name> or the <name> doesn't match with any
+ opp-microvolt-<name> properties, then opp-microvolt property shall be used, if
+ present.
+
- opp-microamp: The maximum current drawn by the device in microamperes
considering system specific parameters (such as transients, process, aging,
maximum operating temperature range etc.) as necessary. This may be used to
for few regulators, then this should be marked as zero for them. If it isn't
required for any regulator, then this property need not be present.
+- opp-microamp-<name>: Named opp-microamp property. Similar to
+ opp-microvolt-<name> property, but for microamp instead.
+
- clock-latency-ns: Specifies the maximum possible transition latency (in
nanoseconds) for switching to this OPP from any other OPP.
- opp-suspend: Marks the OPP to be used during device suspend. Only one OPP in
the table should have this.
+- opp-supported-hw: This enables us to select only a subset of OPPs from the
+ larger OPP table, based on what version of the hardware we are running on. We
+ still can't have multiple nodes with the same opp-hz value in OPP table.
+
+ It's an user defined array containing a hierarchy of hardware version numbers,
+ supported by the OPP. For example: a platform with hierarchy of three levels
+ of versions (A, B and C), this field should be like <X Y Z>, where X
+ corresponds to Version hierarchy A, Y corresponds to version hierarchy B and Z
+ corresponds to version hierarchy C.
+
+ Each level of hierarchy is represented by a 32 bit value, and so there can be
+ only 32 different supported version per hierarchy. i.e. 1 bit per version. A
+ value of 0xFFFFFFFF will enable the OPP for all versions for that hierarchy
+ level. And a value of 0x00000000 will disable the OPP completely, and so we
+ never want that to happen.
+
+ If 32 values aren't sufficient for a version hierarchy, than that version
+ hierarchy can be contained in multiple 32 bit values. i.e. <X Y Z1 Z2> in the
+ above example, Z1 & Z2 refer to the version hierarchy Z.
+
- status: Marks the node enabled/disabled.
Example 1: Single cluster Dual-core ARM cortex A9, switch DVFS states together.
compatible = "operating-points-v2";
opp-shared;
- opp00 {
+ opp@1000000000 {
opp-hz = /bits/ 64 <1000000000>;
opp-microvolt = <970000 975000 985000>;
opp-microamp = <70000>;
clock-latency-ns = <300000>;
opp-suspend;
};
- opp01 {
+ opp@1100000000 {
opp-hz = /bits/ 64 <1100000000>;
opp-microvolt = <980000 1000000 1010000>;
opp-microamp = <80000>;
clock-latency-ns = <310000>;
};
- opp02 {
+ opp@1200000000 {
opp-hz = /bits/ 64 <1200000000>;
opp-microvolt = <1025000>;
clock-latency-ns = <290000>;
* independently.
*/
- opp00 {
+ opp@1000000000 {
opp-hz = /bits/ 64 <1000000000>;
opp-microvolt = <970000 975000 985000>;
opp-microamp = <70000>;
clock-latency-ns = <300000>;
opp-suspend;
};
- opp01 {
+ opp@1100000000 {
opp-hz = /bits/ 64 <1100000000>;
opp-microvolt = <980000 1000000 1010000>;
opp-microamp = <80000>;
clock-latency-ns = <310000>;
};
- opp02 {
+ opp@1200000000 {
opp-hz = /bits/ 64 <1200000000>;
opp-microvolt = <1025000>;
opp-microamp = <90000;
compatible = "operating-points-v2";
opp-shared;
- opp00 {
+ opp@1000000000 {
opp-hz = /bits/ 64 <1000000000>;
opp-microvolt = <970000 975000 985000>;
opp-microamp = <70000>;
clock-latency-ns = <300000>;
opp-suspend;
};
- opp01 {
+ opp@1100000000 {
opp-hz = /bits/ 64 <1100000000>;
opp-microvolt = <980000 1000000 1010000>;
opp-microamp = <80000>;
clock-latency-ns = <310000>;
};
- opp02 {
+ opp@1200000000 {
opp-hz = /bits/ 64 <1200000000>;
opp-microvolt = <1025000>;
opp-microamp = <90000>;
compatible = "operating-points-v2";
opp-shared;
- opp10 {
+ opp@1300000000 {
opp-hz = /bits/ 64 <1300000000>;
opp-microvolt = <1045000 1050000 1055000>;
opp-microamp = <95000>;
clock-latency-ns = <400000>;
opp-suspend;
};
- opp11 {
+ opp@1400000000 {
opp-hz = /bits/ 64 <1400000000>;
opp-microvolt = <1075000>;
opp-microamp = <100000>;
clock-latency-ns = <400000>;
};
- opp12 {
+ opp@1500000000 {
opp-hz = /bits/ 64 <1500000000>;
opp-microvolt = <1010000 1100000 1110000>;
opp-microamp = <95000>;
compatible = "operating-points-v2";
opp-shared;
- opp00 {
+ opp@1000000000 {
opp-hz = /bits/ 64 <1000000000>;
opp-microvolt = <970000>, /* Supply 0 */
<960000>, /* Supply 1 */
/* OR */
- opp00 {
+ opp@1000000000 {
opp-hz = /bits/ 64 <1000000000>;
opp-microvolt = <970000 975000 985000>, /* Supply 0 */
<960000 965000 975000>, /* Supply 1 */
/* OR */
- opp00 {
+ opp@1000000000 {
opp-hz = /bits/ 64 <1000000000>;
opp-microvolt = <970000 975000 985000>, /* Supply 0 */
<960000 965000 975000>, /* Supply 1 */
};
};
-Example 5: Multiple OPP tables
+Example 5: opp-supported-hw
+(example: three level hierarchy of versions: cuts, substrate and process)
/ {
cpus {
...
cpu-supply = <&cpu_supply>
- operating-points-v2 = <&cpu0_opp_table_slow>, <&cpu0_opp_table_fast>;
- operating-points-names = "slow", "fast";
+ operating-points-v2 = <&cpu0_opp_table_slow>;
};
};
- cpu0_opp_table_slow: opp_table_slow {
+ opp_table {
compatible = "operating-points-v2";
status = "okay";
opp-shared;
- opp00 {
+ opp@600000000 {
+ /*
+ * Supports all substrate and process versions for 0xF
+ * cuts, i.e. only first four cuts.
+ */
+ opp-supported-hw = <0xF 0xFFFFFFFF 0xFFFFFFFF>
opp-hz = /bits/ 64 <600000000>;
+ opp-microvolt = <900000 915000 925000>;
...
};
- opp01 {
+ opp@800000000 {
+ /*
+ * Supports:
+ * - cuts: only one, 6th cut (represented by 6th bit).
+ * - substrate: supports 16 different substrate versions
+ * - process: supports 9 different process versions
+ */
+ opp-supported-hw = <0x20 0xff0000ff 0x0000f4f0>
opp-hz = /bits/ 64 <800000000>;
+ opp-microvolt = <900000 915000 925000>;
...
};
};
+};
+
+Example 6: opp-microvolt-<name>, opp-microamp-<name>:
+(example: device with two possible microvolt ranges: slow and fast)
- cpu0_opp_table_fast: opp_table_fast {
+/ {
+ cpus {
+ cpu@0 {
+ compatible = "arm,cortex-a7";
+ ...
+
+ operating-points-v2 = <&cpu0_opp_table>;
+ };
+ };
+
+ cpu0_opp_table: opp_table0 {
compatible = "operating-points-v2";
- status = "okay";
opp-shared;
- opp10 {
+ opp@1000000000 {
opp-hz = /bits/ 64 <1000000000>;
- ...
+ opp-microvolt-slow = <900000 915000 925000>;
+ opp-microvolt-fast = <970000 975000 985000>;
+ opp-microamp-slow = <70000>;
+ opp-microamp-fast = <71000>;
};
- opp11 {
- opp-hz = /bits/ 64 <1100000000>;
- ...
+ opp@1200000000 {
+ opp-hz = /bits/ 64 <1200000000>;
+ opp-microvolt-slow = <900000 915000 925000>, /* Supply vcc0 */
+ <910000 925000 935000>; /* Supply vcc1 */
+ opp-microvolt-fast = <970000 975000 985000>, /* Supply vcc0 */
+ <960000 965000 975000>; /* Supply vcc1 */
+ opp-microamp = <70000>; /* Will be used for both slow/fast */
};
};
};
It is important to remember that the driver's runtime_suspend() callback
may be executed right after the usage counter has been decremented, because
-user space may already have cuased the pm_runtime_allow() helper function
+user space may already have caused the pm_runtime_allow() helper function
unblocking the runtime PM of the device to run via sysfs, so the driver must
be prepared to cope with that.
- increment the device's usage counter, run pm_runtime_resume(dev) and
return its result
+ int pm_runtime_get_if_in_use(struct device *dev);
+ - return -EINVAL if 'power.disable_depth' is nonzero; otherwise, if the
+ runtime PM status is RPM_ACTIVE and the runtime PM usage counter is
+ nonzero, increment the counter and return 1; otherwise return 0 without
+ changing the counter
+
void pm_runtime_put_noidle(struct device *dev);
- decrement the device's usage counter
F: include/linux/timer*
F: kernel/time/*timer*
+POWER MANAGEMENT CORE
+M: "Rafael J. Wysocki" <rjw@rjwysocki.net>
+L: linux-pm@vger.kernel.org
+T: git git://git.kernel.org/pub/scm/linux/kernel/git/rafael/linux-pm
+S: Supported
+F: drivers/base/power/
+F: include/linux/pm.h
+F: include/linux/pm_*
+F: include/linux/powercap.h
+F: drivers/powercap/
+
POWER SUPPLY CLASS/SUBSYSTEM and DRIVERS
M: Sebastian Reichel <sre@kernel.org>
M: Dmitry Eremin-Solenikov <dbaryshkov@gmail.com>
compatible = "operating-points-v2";
opp-shared;
- opp00 {
+ opp@200000000 {
opp-hz = /bits/ 64 <200000000>;
opp-microvolt = <900000>;
clock-latency-ns = <200000>;
};
- opp01 {
+ opp@300000000 {
opp-hz = /bits/ 64 <300000000>;
opp-microvolt = <900000>;
clock-latency-ns = <200000>;
};
- opp02 {
+ opp@400000000 {
opp-hz = /bits/ 64 <400000000>;
opp-microvolt = <925000>;
clock-latency-ns = <200000>;
};
- opp03 {
+ opp@500000000 {
opp-hz = /bits/ 64 <500000000>;
opp-microvolt = <950000>;
clock-latency-ns = <200000>;
};
- opp04 {
+ opp@600000000 {
opp-hz = /bits/ 64 <600000000>;
opp-microvolt = <975000>;
clock-latency-ns = <200000>;
};
- opp05 {
+ opp@700000000 {
opp-hz = /bits/ 64 <700000000>;
opp-microvolt = <987500>;
clock-latency-ns = <200000>;
};
- opp06 {
+ opp@800000000 {
opp-hz = /bits/ 64 <800000000>;
opp-microvolt = <1000000>;
clock-latency-ns = <200000>;
opp-suspend;
};
- opp07 {
+ opp@900000000 {
opp-hz = /bits/ 64 <900000000>;
opp-microvolt = <1037500>;
clock-latency-ns = <200000>;
};
- opp08 {
+ opp@1000000000 {
opp-hz = /bits/ 64 <1000000000>;
opp-microvolt = <1087500>;
clock-latency-ns = <200000>;
};
- opp09 {
+ opp@1100000000 {
opp-hz = /bits/ 64 <1100000000>;
opp-microvolt = <1137500>;
clock-latency-ns = <200000>;
};
- opp10 {
+ opp@1200000000 {
opp-hz = /bits/ 64 <1200000000>;
opp-microvolt = <1187500>;
clock-latency-ns = <200000>;
};
- opp11 {
+ opp@1300000000 {
opp-hz = /bits/ 64 <1300000000>;
opp-microvolt = <1250000>;
clock-latency-ns = <200000>;
};
- opp12 {
+ opp@1400000000 {
opp-hz = /bits/ 64 <1400000000>;
opp-microvolt = <1287500>;
clock-latency-ns = <200000>;
};
- opp13 {
+ opp@1500000000 {
opp-hz = /bits/ 64 <1500000000>;
opp-microvolt = <1350000>;
clock-latency-ns = <200000>;
config X86_INTEL_LPSS
bool "Intel Low Power Subsystem Support"
- depends on ACPI
+ depends on X86 && ACPI
select COMMON_CLK
select PINCTRL
+ select IOSF_MBI
---help---
Select to build support for Intel Low Power Subsystem such as
found on Intel Lynxpoint PCH. Selecting this option enables
/*
- * iosf_mbi.h: Intel OnChip System Fabric MailBox access support
+ * Intel OnChip System Fabric MailBox access support
*/
#ifndef IOSF_MBI_SYMS_H
#define MBI_MASK_LO 0x000000FF
#define MBI_ENABLE 0xF0
+/* IOSF SB read/write opcodes */
+#define MBI_MMIO_READ 0x00
+#define MBI_MMIO_WRITE 0x01
+#define MBI_CFG_READ 0x04
+#define MBI_CFG_WRITE 0x05
+#define MBI_CR_READ 0x06
+#define MBI_CR_WRITE 0x07
+#define MBI_REG_READ 0x10
+#define MBI_REG_WRITE 0x11
+#define MBI_ESRAM_READ 0x12
+#define MBI_ESRAM_WRITE 0x13
+
/* Baytrail available units */
#define BT_MBI_UNIT_AUNIT 0x00
#define BT_MBI_UNIT_SMC 0x01
#define BT_MBI_UNIT_SATA 0xA3
#define BT_MBI_UNIT_PCIE 0xA6
-/* Baytrail read/write opcodes */
-#define BT_MBI_AUNIT_READ 0x10
-#define BT_MBI_AUNIT_WRITE 0x11
-#define BT_MBI_SMC_READ 0x10
-#define BT_MBI_SMC_WRITE 0x11
-#define BT_MBI_CPU_READ 0x10
-#define BT_MBI_CPU_WRITE 0x11
-#define BT_MBI_BUNIT_READ 0x10
-#define BT_MBI_BUNIT_WRITE 0x11
-#define BT_MBI_PMC_READ 0x06
-#define BT_MBI_PMC_WRITE 0x07
-#define BT_MBI_GFX_READ 0x00
-#define BT_MBI_GFX_WRITE 0x01
-#define BT_MBI_SMIO_READ 0x06
-#define BT_MBI_SMIO_WRITE 0x07
-#define BT_MBI_USB_READ 0x06
-#define BT_MBI_USB_WRITE 0x07
-#define BT_MBI_SATA_READ 0x00
-#define BT_MBI_SATA_WRITE 0x01
-#define BT_MBI_PCIE_READ 0x00
-#define BT_MBI_PCIE_WRITE 0x01
-
/* Quark available units */
#define QRK_MBI_UNIT_HBA 0x00
#define QRK_MBI_UNIT_HB 0x03
#define QRK_MBI_UNIT_RMU 0x04
#define QRK_MBI_UNIT_MM 0x05
-#define QRK_MBI_UNIT_MMESRAM 0x05
#define QRK_MBI_UNIT_SOC 0x31
-/* Quark read/write opcodes */
-#define QRK_MBI_HBA_READ 0x10
-#define QRK_MBI_HBA_WRITE 0x11
-#define QRK_MBI_HB_READ 0x10
-#define QRK_MBI_HB_WRITE 0x11
-#define QRK_MBI_RMU_READ 0x10
-#define QRK_MBI_RMU_WRITE 0x11
-#define QRK_MBI_MM_READ 0x10
-#define QRK_MBI_MM_WRITE 0x11
-#define QRK_MBI_MMESRAM_READ 0x12
-#define QRK_MBI_MMESRAM_WRITE 0x13
-#define QRK_MBI_SOC_READ 0x06
-#define QRK_MBI_SOC_WRITE 0x07
-
#if IS_ENABLED(CONFIG_IOSF_MBI)
bool iosf_mbi_available(void);
#include <asm/cpu_device_id.h>
#include <asm/iosf_mbi.h>
-/* Side band Interface port */
-#define PUNIT_PORT 0x04
/* Power gate status reg */
#define PWRGT_STATUS 0x61
/* Subsystem config/status Video processor */
seq_puts(seq_file, "\n\nPUNIT NORTH COMPLEX DEVICES :\n");
while (punit_devp->name) {
- status = iosf_mbi_read(PUNIT_PORT, BT_MBI_PMC_READ,
- punit_devp->reg,
- &punit_pwr_status);
+ status = iosf_mbi_read(BT_MBI_UNIT_PMC, MBI_REG_READ,
+ punit_devp->reg, &punit_pwr_status);
if (status) {
seq_printf(seq_file, "%9s : Read Failed\n",
punit_devp->name);
u32 reg = imr_id * IMR_NUM_REGS + idev->reg_base;
int ret;
- ret = iosf_mbi_read(QRK_MBI_UNIT_MM, QRK_MBI_MM_READ,
- reg++, &imr->addr_lo);
+ ret = iosf_mbi_read(QRK_MBI_UNIT_MM, MBI_REG_READ, reg++, &imr->addr_lo);
if (ret)
return ret;
- ret = iosf_mbi_read(QRK_MBI_UNIT_MM, QRK_MBI_MM_READ,
- reg++, &imr->addr_hi);
+ ret = iosf_mbi_read(QRK_MBI_UNIT_MM, MBI_REG_READ, reg++, &imr->addr_hi);
if (ret)
return ret;
- ret = iosf_mbi_read(QRK_MBI_UNIT_MM, QRK_MBI_MM_READ,
- reg++, &imr->rmask);
+ ret = iosf_mbi_read(QRK_MBI_UNIT_MM, MBI_REG_READ, reg++, &imr->rmask);
if (ret)
return ret;
- return iosf_mbi_read(QRK_MBI_UNIT_MM, QRK_MBI_MM_READ,
- reg++, &imr->wmask);
+ return iosf_mbi_read(QRK_MBI_UNIT_MM, MBI_REG_READ, reg++, &imr->wmask);
}
/**
local_irq_save(flags);
- ret = iosf_mbi_write(QRK_MBI_UNIT_MM, QRK_MBI_MM_WRITE, reg++,
- imr->addr_lo);
+ ret = iosf_mbi_write(QRK_MBI_UNIT_MM, MBI_REG_WRITE, reg++, imr->addr_lo);
if (ret)
goto failed;
- ret = iosf_mbi_write(QRK_MBI_UNIT_MM, QRK_MBI_MM_WRITE,
- reg++, imr->addr_hi);
+ ret = iosf_mbi_write(QRK_MBI_UNIT_MM, MBI_REG_WRITE, reg++, imr->addr_hi);
if (ret)
goto failed;
- ret = iosf_mbi_write(QRK_MBI_UNIT_MM, QRK_MBI_MM_WRITE,
- reg++, imr->rmask);
+ ret = iosf_mbi_write(QRK_MBI_UNIT_MM, MBI_REG_WRITE, reg++, imr->rmask);
if (ret)
goto failed;
- ret = iosf_mbi_write(QRK_MBI_UNIT_MM, QRK_MBI_MM_WRITE,
- reg++, imr->wmask);
+ ret = iosf_mbi_write(QRK_MBI_UNIT_MM, MBI_REG_WRITE, reg++, imr->wmask);
if (ret)
goto failed;
/* Lock bit must be set separately to addr_lo address bits. */
if (lock) {
imr->addr_lo |= IMR_LOCK;
- ret = iosf_mbi_write(QRK_MBI_UNIT_MM, QRK_MBI_MM_WRITE,
- reg - IMR_NUM_REGS, imr->addr_lo);
+ ret = iosf_mbi_write(QRK_MBI_UNIT_MM, MBI_REG_WRITE,
+ reg - IMR_NUM_REGS, imr->addr_lo);
if (ret)
goto failed;
}
bool
config ACPI_DEBUGGER
- bool "AML debugger interface (EXPERIMENTAL)"
+ bool "AML debugger interface"
select ACPI_DEBUG
help
- Enable in-kernel debugging of AML facilities: statistics, internal
- object dump, single step control method execution.
+ Enable in-kernel debugging of AML facilities: statistics,
+ internal object dump, single step control method execution.
This is still under development, currently enabling this only
results in the compilation of the ACPICA debugger files.
+if ACPI_DEBUGGER
+
+config ACPI_DEBUGGER_USER
+ tristate "Userspace debugger accessiblity"
+ depends on DEBUG_FS
+ help
+ Export /sys/kernel/debug/acpi/acpidbg for userspace utilities
+ to access the debugger functionalities.
+
+endif
+
config ACPI_SLEEP
bool
depends on SUSPEND || HIBERNATION
#
# ACPI Boot-Time Table Parsing
#
-obj-y += tables.o
+obj-$(CONFIG_ACPI) += tables.o
obj-$(CONFIG_X86) += blacklist.o
#
# ACPI Core Subsystem (Interpreter)
#
-obj-y += acpi.o \
+obj-$(CONFIG_ACPI) += acpi.o \
acpica/
# All the builtin files are in the "acpi." module_param namespace.
obj-$(CONFIG_ACPI_VIDEO) += video.o
obj-$(CONFIG_ACPI_PCI_SLOT) += pci_slot.o
obj-$(CONFIG_ACPI_PROCESSOR) += processor.o
-obj-y += container.o
+obj-$(CONFIG_ACPI) += container.o
obj-$(CONFIG_ACPI_THERMAL) += thermal.o
obj-$(CONFIG_ACPI_NFIT) += nfit.o
-obj-y += acpi_memhotplug.o
+obj-$(CONFIG_ACPI) += acpi_memhotplug.o
obj-$(CONFIG_ACPI_HOTPLUG_IOAPIC) += ioapic.o
obj-$(CONFIG_ACPI_BATTERY) += battery.o
obj-$(CONFIG_ACPI_SBS) += sbshc.o
obj-$(CONFIG_ACPI_CUSTOM_METHOD)+= custom_method.o
obj-$(CONFIG_ACPI_BGRT) += bgrt.o
obj-$(CONFIG_ACPI_CPPC_LIB) += cppc_acpi.o
+obj-$(CONFIG_ACPI_DEBUGGER_USER) += acpi_dbg.o
# processor has its own "processor." module_param namespace
processor-y := processor_driver.o
const struct apd_device_desc *dev_desc;
};
-#ifdef CONFIG_X86_AMD_PLATFORM_DEVICE
+#if defined(CONFIG_X86_AMD_PLATFORM_DEVICE) || defined(CONFIG_ARM64)
#define APD_ADDR(desc) ((unsigned long)&desc)
static int acpi_apd_setup(struct apd_private_data *pdata)
return 0;
}
+#ifdef CONFIG_X86_AMD_PLATFORM_DEVICE
static struct apd_device_desc cz_i2c_desc = {
.setup = acpi_apd_setup,
.fixed_clk_rate = 133000000,
.setup = acpi_apd_setup,
.fixed_clk_rate = 48000000,
};
+#endif
+
+#ifdef CONFIG_ARM64
+static struct apd_device_desc xgene_i2c_desc = {
+ .setup = acpi_apd_setup,
+ .fixed_clk_rate = 100000000,
+};
+#endif
#else
static const struct acpi_device_id acpi_apd_device_ids[] = {
/* Generic apd devices */
+#ifdef CONFIG_X86_AMD_PLATFORM_DEVICE
{ "AMD0010", APD_ADDR(cz_i2c_desc) },
{ "AMD0020", APD_ADDR(cz_uart_desc) },
{ "AMD0030", },
+#endif
+#ifdef CONFIG_ARM64
+ { "APMC0D0F", APD_ADDR(xgene_i2c_desc) },
+#endif
{ }
};
--- /dev/null
+/*
+ * ACPI AML interfacing support
+ *
+ * Copyright (C) 2015, Intel Corporation
+ * Authors: Lv Zheng <lv.zheng@intel.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+/* #define DEBUG */
+#define pr_fmt(fmt) "ACPI : AML: " fmt
+
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/wait.h>
+#include <linux/poll.h>
+#include <linux/sched.h>
+#include <linux/kthread.h>
+#include <linux/proc_fs.h>
+#include <linux/debugfs.h>
+#include <linux/circ_buf.h>
+#include <linux/acpi.h>
+#include "internal.h"
+
+#define ACPI_AML_BUF_ALIGN (sizeof (acpi_size))
+#define ACPI_AML_BUF_SIZE PAGE_SIZE
+
+#define circ_count(circ) \
+ (CIRC_CNT((circ)->head, (circ)->tail, ACPI_AML_BUF_SIZE))
+#define circ_count_to_end(circ) \
+ (CIRC_CNT_TO_END((circ)->head, (circ)->tail, ACPI_AML_BUF_SIZE))
+#define circ_space(circ) \
+ (CIRC_SPACE((circ)->head, (circ)->tail, ACPI_AML_BUF_SIZE))
+#define circ_space_to_end(circ) \
+ (CIRC_SPACE_TO_END((circ)->head, (circ)->tail, ACPI_AML_BUF_SIZE))
+
+#define ACPI_AML_OPENED 0x0001
+#define ACPI_AML_CLOSED 0x0002
+#define ACPI_AML_IN_USER 0x0004 /* user space is writing cmd */
+#define ACPI_AML_IN_KERN 0x0008 /* kernel space is reading cmd */
+#define ACPI_AML_OUT_USER 0x0010 /* user space is reading log */
+#define ACPI_AML_OUT_KERN 0x0020 /* kernel space is writing log */
+#define ACPI_AML_USER (ACPI_AML_IN_USER | ACPI_AML_OUT_USER)
+#define ACPI_AML_KERN (ACPI_AML_IN_KERN | ACPI_AML_OUT_KERN)
+#define ACPI_AML_BUSY (ACPI_AML_USER | ACPI_AML_KERN)
+#define ACPI_AML_OPEN (ACPI_AML_OPENED | ACPI_AML_CLOSED)
+
+struct acpi_aml_io {
+ wait_queue_head_t wait;
+ unsigned long flags;
+ unsigned long users;
+ struct mutex lock;
+ struct task_struct *thread;
+ char out_buf[ACPI_AML_BUF_SIZE] __aligned(ACPI_AML_BUF_ALIGN);
+ struct circ_buf out_crc;
+ char in_buf[ACPI_AML_BUF_SIZE] __aligned(ACPI_AML_BUF_ALIGN);
+ struct circ_buf in_crc;
+ acpi_osd_exec_callback function;
+ void *context;
+ unsigned long usages;
+};
+
+static struct acpi_aml_io acpi_aml_io;
+static bool acpi_aml_initialized;
+static struct file *acpi_aml_active_reader;
+static struct dentry *acpi_aml_dentry;
+
+static inline bool __acpi_aml_running(void)
+{
+ return acpi_aml_io.thread ? true : false;
+}
+
+static inline bool __acpi_aml_access_ok(unsigned long flag)
+{
+ /*
+ * The debugger interface is in opened state (OPENED && !CLOSED),
+ * then it is allowed to access the debugger buffers from either
+ * user space or the kernel space.
+ * In addition, for the kernel space, only the debugger thread
+ * (thread ID matched) is allowed to access.
+ */
+ if (!(acpi_aml_io.flags & ACPI_AML_OPENED) ||
+ (acpi_aml_io.flags & ACPI_AML_CLOSED) ||
+ !__acpi_aml_running())
+ return false;
+ if ((flag & ACPI_AML_KERN) &&
+ current != acpi_aml_io.thread)
+ return false;
+ return true;
+}
+
+static inline bool __acpi_aml_readable(struct circ_buf *circ, unsigned long flag)
+{
+ /*
+ * Another read is not in progress and there is data in buffer
+ * available for read.
+ */
+ if (!(acpi_aml_io.flags & flag) && circ_count(circ))
+ return true;
+ return false;
+}
+
+static inline bool __acpi_aml_writable(struct circ_buf *circ, unsigned long flag)
+{
+ /*
+ * Another write is not in progress and there is buffer space
+ * available for write.
+ */
+ if (!(acpi_aml_io.flags & flag) && circ_space(circ))
+ return true;
+ return false;
+}
+
+static inline bool __acpi_aml_busy(void)
+{
+ if (acpi_aml_io.flags & ACPI_AML_BUSY)
+ return true;
+ return false;
+}
+
+static inline bool __acpi_aml_opened(void)
+{
+ if (acpi_aml_io.flags & ACPI_AML_OPEN)
+ return true;
+ return false;
+}
+
+static inline bool __acpi_aml_used(void)
+{
+ return acpi_aml_io.usages ? true : false;
+}
+
+static inline bool acpi_aml_running(void)
+{
+ bool ret;
+
+ mutex_lock(&acpi_aml_io.lock);
+ ret = __acpi_aml_running();
+ mutex_unlock(&acpi_aml_io.lock);
+ return ret;
+}
+
+static bool acpi_aml_busy(void)
+{
+ bool ret;
+
+ mutex_lock(&acpi_aml_io.lock);
+ ret = __acpi_aml_busy();
+ mutex_unlock(&acpi_aml_io.lock);
+ return ret;
+}
+
+static bool acpi_aml_used(void)
+{
+ bool ret;
+
+ /*
+ * The usage count is prepared to avoid race conditions between the
+ * starts and the stops of the debugger thread.
+ */
+ mutex_lock(&acpi_aml_io.lock);
+ ret = __acpi_aml_used();
+ mutex_unlock(&acpi_aml_io.lock);
+ return ret;
+}
+
+static bool acpi_aml_kern_readable(void)
+{
+ bool ret;
+
+ mutex_lock(&acpi_aml_io.lock);
+ ret = !__acpi_aml_access_ok(ACPI_AML_IN_KERN) ||
+ __acpi_aml_readable(&acpi_aml_io.in_crc, ACPI_AML_IN_KERN);
+ mutex_unlock(&acpi_aml_io.lock);
+ return ret;
+}
+
+static bool acpi_aml_kern_writable(void)
+{
+ bool ret;
+
+ mutex_lock(&acpi_aml_io.lock);
+ ret = !__acpi_aml_access_ok(ACPI_AML_OUT_KERN) ||
+ __acpi_aml_writable(&acpi_aml_io.out_crc, ACPI_AML_OUT_KERN);
+ mutex_unlock(&acpi_aml_io.lock);
+ return ret;
+}
+
+static bool acpi_aml_user_readable(void)
+{
+ bool ret;
+
+ mutex_lock(&acpi_aml_io.lock);
+ ret = !__acpi_aml_access_ok(ACPI_AML_OUT_USER) ||
+ __acpi_aml_readable(&acpi_aml_io.out_crc, ACPI_AML_OUT_USER);
+ mutex_unlock(&acpi_aml_io.lock);
+ return ret;
+}
+
+static bool acpi_aml_user_writable(void)
+{
+ bool ret;
+
+ mutex_lock(&acpi_aml_io.lock);
+ ret = !__acpi_aml_access_ok(ACPI_AML_IN_USER) ||
+ __acpi_aml_writable(&acpi_aml_io.in_crc, ACPI_AML_IN_USER);
+ mutex_unlock(&acpi_aml_io.lock);
+ return ret;
+}
+
+static int acpi_aml_lock_write(struct circ_buf *circ, unsigned long flag)
+{
+ int ret = 0;
+
+ mutex_lock(&acpi_aml_io.lock);
+ if (!__acpi_aml_access_ok(flag)) {
+ ret = -EFAULT;
+ goto out;
+ }
+ if (!__acpi_aml_writable(circ, flag)) {
+ ret = -EAGAIN;
+ goto out;
+ }
+ acpi_aml_io.flags |= flag;
+out:
+ mutex_unlock(&acpi_aml_io.lock);
+ return ret;
+}
+
+static int acpi_aml_lock_read(struct circ_buf *circ, unsigned long flag)
+{
+ int ret = 0;
+
+ mutex_lock(&acpi_aml_io.lock);
+ if (!__acpi_aml_access_ok(flag)) {
+ ret = -EFAULT;
+ goto out;
+ }
+ if (!__acpi_aml_readable(circ, flag)) {
+ ret = -EAGAIN;
+ goto out;
+ }
+ acpi_aml_io.flags |= flag;
+out:
+ mutex_unlock(&acpi_aml_io.lock);
+ return ret;
+}
+
+static void acpi_aml_unlock_fifo(unsigned long flag, bool wakeup)
+{
+ mutex_lock(&acpi_aml_io.lock);
+ acpi_aml_io.flags &= ~flag;
+ if (wakeup)
+ wake_up_interruptible(&acpi_aml_io.wait);
+ mutex_unlock(&acpi_aml_io.lock);
+}
+
+static int acpi_aml_write_kern(const char *buf, int len)
+{
+ int ret;
+ struct circ_buf *crc = &acpi_aml_io.out_crc;
+ int n;
+ char *p;
+
+ ret = acpi_aml_lock_write(crc, ACPI_AML_OUT_KERN);
+ if (IS_ERR_VALUE(ret))
+ return ret;
+ /* sync tail before inserting logs */
+ smp_mb();
+ p = &crc->buf[crc->head];
+ n = min(len, circ_space_to_end(crc));
+ memcpy(p, buf, n);
+ /* sync head after inserting logs */
+ smp_wmb();
+ crc->head = (crc->head + n) & (ACPI_AML_BUF_SIZE - 1);
+ acpi_aml_unlock_fifo(ACPI_AML_OUT_KERN, true);
+ return n;
+}
+
+static int acpi_aml_readb_kern(void)
+{
+ int ret;
+ struct circ_buf *crc = &acpi_aml_io.in_crc;
+ char *p;
+
+ ret = acpi_aml_lock_read(crc, ACPI_AML_IN_KERN);
+ if (IS_ERR_VALUE(ret))
+ return ret;
+ /* sync head before removing cmds */
+ smp_rmb();
+ p = &crc->buf[crc->tail];
+ ret = (int)*p;
+ /* sync tail before inserting cmds */
+ smp_mb();
+ crc->tail = (crc->tail + 1) & (ACPI_AML_BUF_SIZE - 1);
+ acpi_aml_unlock_fifo(ACPI_AML_IN_KERN, true);
+ return ret;
+}
+
+/*
+ * acpi_aml_write_log() - Capture debugger output
+ * @msg: the debugger output
+ *
+ * This function should be used to implement acpi_os_printf() to filter out
+ * the debugger output and store the output into the debugger interface
+ * buffer. Return the size of stored logs or errno.
+ */
+static ssize_t acpi_aml_write_log(const char *msg)
+{
+ int ret = 0;
+ int count = 0, size = 0;
+
+ if (!acpi_aml_initialized)
+ return -ENODEV;
+ if (msg)
+ count = strlen(msg);
+ while (count > 0) {
+again:
+ ret = acpi_aml_write_kern(msg + size, count);
+ if (ret == -EAGAIN) {
+ ret = wait_event_interruptible(acpi_aml_io.wait,
+ acpi_aml_kern_writable());
+ /*
+ * We need to retry when the condition
+ * becomes true.
+ */
+ if (ret == 0)
+ goto again;
+ break;
+ }
+ if (IS_ERR_VALUE(ret))
+ break;
+ size += ret;
+ count -= ret;
+ }
+ return size > 0 ? size : ret;
+}
+
+/*
+ * acpi_aml_read_cmd() - Capture debugger input
+ * @msg: the debugger input
+ * @size: the size of the debugger input
+ *
+ * This function should be used to implement acpi_os_get_line() to capture
+ * the debugger input commands and store the input commands into the
+ * debugger interface buffer. Return the size of stored commands or errno.
+ */
+static ssize_t acpi_aml_read_cmd(char *msg, size_t count)
+{
+ int ret = 0;
+ int size = 0;
+
+ /*
+ * This is ensured by the running fact of the debugger thread
+ * unless a bug is introduced.
+ */
+ BUG_ON(!acpi_aml_initialized);
+ while (count > 0) {
+again:
+ /*
+ * Check each input byte to find the end of the command.
+ */
+ ret = acpi_aml_readb_kern();
+ if (ret == -EAGAIN) {
+ ret = wait_event_interruptible(acpi_aml_io.wait,
+ acpi_aml_kern_readable());
+ /*
+ * We need to retry when the condition becomes
+ * true.
+ */
+ if (ret == 0)
+ goto again;
+ }
+ if (IS_ERR_VALUE(ret))
+ break;
+ *(msg + size) = (char)ret;
+ size++;
+ count--;
+ if (ret == '\n') {
+ /*
+ * acpi_os_get_line() requires a zero terminated command
+ * string.
+ */
+ *(msg + size - 1) = '\0';
+ break;
+ }
+ }
+ return size > 0 ? size : ret;
+}
+
+static int acpi_aml_thread(void *unsed)
+{
+ acpi_osd_exec_callback function = NULL;
+ void *context;
+
+ mutex_lock(&acpi_aml_io.lock);
+ if (acpi_aml_io.function) {
+ acpi_aml_io.usages++;
+ function = acpi_aml_io.function;
+ context = acpi_aml_io.context;
+ }
+ mutex_unlock(&acpi_aml_io.lock);
+
+ if (function)
+ function(context);
+
+ mutex_lock(&acpi_aml_io.lock);
+ acpi_aml_io.usages--;
+ if (!__acpi_aml_used()) {
+ acpi_aml_io.thread = NULL;
+ wake_up(&acpi_aml_io.wait);
+ }
+ mutex_unlock(&acpi_aml_io.lock);
+
+ return 0;
+}
+
+/*
+ * acpi_aml_create_thread() - Create AML debugger thread
+ * @function: the debugger thread callback
+ * @context: the context to be passed to the debugger thread
+ *
+ * This function should be used to implement acpi_os_execute() which is
+ * used by the ACPICA debugger to create the debugger thread.
+ */
+static int acpi_aml_create_thread(acpi_osd_exec_callback function, void *context)
+{
+ struct task_struct *t;
+
+ mutex_lock(&acpi_aml_io.lock);
+ acpi_aml_io.function = function;
+ acpi_aml_io.context = context;
+ mutex_unlock(&acpi_aml_io.lock);
+
+ t = kthread_create(acpi_aml_thread, NULL, "aml");
+ if (IS_ERR(t)) {
+ pr_err("Failed to create AML debugger thread.\n");
+ return PTR_ERR(t);
+ }
+
+ mutex_lock(&acpi_aml_io.lock);
+ acpi_aml_io.thread = t;
+ acpi_set_debugger_thread_id((acpi_thread_id)(unsigned long)t);
+ wake_up_process(t);
+ mutex_unlock(&acpi_aml_io.lock);
+ return 0;
+}
+
+static int acpi_aml_wait_command_ready(bool single_step,
+ char *buffer, size_t length)
+{
+ acpi_status status;
+
+ if (single_step)
+ acpi_os_printf("\n%1c ", ACPI_DEBUGGER_EXECUTE_PROMPT);
+ else
+ acpi_os_printf("\n%1c ", ACPI_DEBUGGER_COMMAND_PROMPT);
+
+ status = acpi_os_get_line(buffer, length, NULL);
+ if (ACPI_FAILURE(status))
+ return -EINVAL;
+ return 0;
+}
+
+static int acpi_aml_notify_command_complete(void)
+{
+ return 0;
+}
+
+static int acpi_aml_open(struct inode *inode, struct file *file)
+{
+ int ret = 0;
+ acpi_status status;
+
+ mutex_lock(&acpi_aml_io.lock);
+ /*
+ * The debugger interface is being closed, no new user is allowed
+ * during this period.
+ */
+ if (acpi_aml_io.flags & ACPI_AML_CLOSED) {
+ ret = -EBUSY;
+ goto err_lock;
+ }
+ if ((file->f_flags & O_ACCMODE) != O_WRONLY) {
+ /*
+ * Only one reader is allowed to initiate the debugger
+ * thread.
+ */
+ if (acpi_aml_active_reader) {
+ ret = -EBUSY;
+ goto err_lock;
+ } else {
+ pr_debug("Opening debugger reader.\n");
+ acpi_aml_active_reader = file;
+ }
+ } else {
+ /*
+ * No writer is allowed unless the debugger thread is
+ * ready.
+ */
+ if (!(acpi_aml_io.flags & ACPI_AML_OPENED)) {
+ ret = -ENODEV;
+ goto err_lock;
+ }
+ }
+ if (acpi_aml_active_reader == file) {
+ pr_debug("Opening debugger interface.\n");
+ mutex_unlock(&acpi_aml_io.lock);
+
+ pr_debug("Initializing debugger thread.\n");
+ status = acpi_initialize_debugger();
+ if (ACPI_FAILURE(status)) {
+ pr_err("Failed to initialize debugger.\n");
+ ret = -EINVAL;
+ goto err_exit;
+ }
+ pr_debug("Debugger thread initialized.\n");
+
+ mutex_lock(&acpi_aml_io.lock);
+ acpi_aml_io.flags |= ACPI_AML_OPENED;
+ acpi_aml_io.out_crc.head = acpi_aml_io.out_crc.tail = 0;
+ acpi_aml_io.in_crc.head = acpi_aml_io.in_crc.tail = 0;
+ pr_debug("Debugger interface opened.\n");
+ }
+ acpi_aml_io.users++;
+err_lock:
+ if (IS_ERR_VALUE(ret)) {
+ if (acpi_aml_active_reader == file)
+ acpi_aml_active_reader = NULL;
+ }
+ mutex_unlock(&acpi_aml_io.lock);
+err_exit:
+ return ret;
+}
+
+static int acpi_aml_release(struct inode *inode, struct file *file)
+{
+ mutex_lock(&acpi_aml_io.lock);
+ acpi_aml_io.users--;
+ if (file == acpi_aml_active_reader) {
+ pr_debug("Closing debugger reader.\n");
+ acpi_aml_active_reader = NULL;
+
+ pr_debug("Closing debugger interface.\n");
+ acpi_aml_io.flags |= ACPI_AML_CLOSED;
+
+ /*
+ * Wake up all user space/kernel space blocked
+ * readers/writers.
+ */
+ wake_up_interruptible(&acpi_aml_io.wait);
+ mutex_unlock(&acpi_aml_io.lock);
+ /*
+ * Wait all user space/kernel space readers/writers to
+ * stop so that ACPICA command loop of the debugger thread
+ * should fail all its command line reads after this point.
+ */
+ wait_event(acpi_aml_io.wait, !acpi_aml_busy());
+
+ /*
+ * Then we try to terminate the debugger thread if it is
+ * not terminated.
+ */
+ pr_debug("Terminating debugger thread.\n");
+ acpi_terminate_debugger();
+ wait_event(acpi_aml_io.wait, !acpi_aml_used());
+ pr_debug("Debugger thread terminated.\n");
+
+ mutex_lock(&acpi_aml_io.lock);
+ acpi_aml_io.flags &= ~ACPI_AML_OPENED;
+ }
+ if (acpi_aml_io.users == 0) {
+ pr_debug("Debugger interface closed.\n");
+ acpi_aml_io.flags &= ~ACPI_AML_CLOSED;
+ }
+ mutex_unlock(&acpi_aml_io.lock);
+ return 0;
+}
+
+static int acpi_aml_read_user(char __user *buf, int len)
+{
+ int ret;
+ struct circ_buf *crc = &acpi_aml_io.out_crc;
+ int n;
+ char *p;
+
+ ret = acpi_aml_lock_read(crc, ACPI_AML_OUT_USER);
+ if (IS_ERR_VALUE(ret))
+ return ret;
+ /* sync head before removing logs */
+ smp_rmb();
+ p = &crc->buf[crc->tail];
+ n = min(len, circ_count_to_end(crc));
+ if (copy_to_user(buf, p, n)) {
+ ret = -EFAULT;
+ goto out;
+ }
+ /* sync tail after removing logs */
+ smp_mb();
+ crc->tail = (crc->tail + n) & (ACPI_AML_BUF_SIZE - 1);
+ ret = n;
+out:
+ acpi_aml_unlock_fifo(ACPI_AML_OUT_USER, !IS_ERR_VALUE(ret));
+ return ret;
+}
+
+static ssize_t acpi_aml_read(struct file *file, char __user *buf,
+ size_t count, loff_t *ppos)
+{
+ int ret = 0;
+ int size = 0;
+
+ if (!count)
+ return 0;
+ if (!access_ok(VERIFY_WRITE, buf, count))
+ return -EFAULT;
+
+ while (count > 0) {
+again:
+ ret = acpi_aml_read_user(buf + size, count);
+ if (ret == -EAGAIN) {
+ if (file->f_flags & O_NONBLOCK)
+ break;
+ else {
+ ret = wait_event_interruptible(acpi_aml_io.wait,
+ acpi_aml_user_readable());
+ /*
+ * We need to retry when the condition
+ * becomes true.
+ */
+ if (ret == 0)
+ goto again;
+ }
+ }
+ if (IS_ERR_VALUE(ret)) {
+ if (!acpi_aml_running())
+ ret = 0;
+ break;
+ }
+ if (ret) {
+ size += ret;
+ count -= ret;
+ *ppos += ret;
+ break;
+ }
+ }
+ return size > 0 ? size : ret;
+}
+
+static int acpi_aml_write_user(const char __user *buf, int len)
+{
+ int ret;
+ struct circ_buf *crc = &acpi_aml_io.in_crc;
+ int n;
+ char *p;
+
+ ret = acpi_aml_lock_write(crc, ACPI_AML_IN_USER);
+ if (IS_ERR_VALUE(ret))
+ return ret;
+ /* sync tail before inserting cmds */
+ smp_mb();
+ p = &crc->buf[crc->head];
+ n = min(len, circ_space_to_end(crc));
+ if (copy_from_user(p, buf, n)) {
+ ret = -EFAULT;
+ goto out;
+ }
+ /* sync head after inserting cmds */
+ smp_wmb();
+ crc->head = (crc->head + n) & (ACPI_AML_BUF_SIZE - 1);
+ ret = n;
+out:
+ acpi_aml_unlock_fifo(ACPI_AML_IN_USER, !IS_ERR_VALUE(ret));
+ return n;
+}
+
+static ssize_t acpi_aml_write(struct file *file, const char __user *buf,
+ size_t count, loff_t *ppos)
+{
+ int ret = 0;
+ int size = 0;
+
+ if (!count)
+ return 0;
+ if (!access_ok(VERIFY_READ, buf, count))
+ return -EFAULT;
+
+ while (count > 0) {
+again:
+ ret = acpi_aml_write_user(buf + size, count);
+ if (ret == -EAGAIN) {
+ if (file->f_flags & O_NONBLOCK)
+ break;
+ else {
+ ret = wait_event_interruptible(acpi_aml_io.wait,
+ acpi_aml_user_writable());
+ /*
+ * We need to retry when the condition
+ * becomes true.
+ */
+ if (ret == 0)
+ goto again;
+ }
+ }
+ if (IS_ERR_VALUE(ret)) {
+ if (!acpi_aml_running())
+ ret = 0;
+ break;
+ }
+ if (ret) {
+ size += ret;
+ count -= ret;
+ *ppos += ret;
+ }
+ }
+ return size > 0 ? size : ret;
+}
+
+static unsigned int acpi_aml_poll(struct file *file, poll_table *wait)
+{
+ int masks = 0;
+
+ poll_wait(file, &acpi_aml_io.wait, wait);
+ if (acpi_aml_user_readable())
+ masks |= POLLIN | POLLRDNORM;
+ if (acpi_aml_user_writable())
+ masks |= POLLOUT | POLLWRNORM;
+
+ return masks;
+}
+
+static const struct file_operations acpi_aml_operations = {
+ .read = acpi_aml_read,
+ .write = acpi_aml_write,
+ .poll = acpi_aml_poll,
+ .open = acpi_aml_open,
+ .release = acpi_aml_release,
+ .llseek = generic_file_llseek,
+};
+
+static const struct acpi_debugger_ops acpi_aml_debugger = {
+ .create_thread = acpi_aml_create_thread,
+ .read_cmd = acpi_aml_read_cmd,
+ .write_log = acpi_aml_write_log,
+ .wait_command_ready = acpi_aml_wait_command_ready,
+ .notify_command_complete = acpi_aml_notify_command_complete,
+};
+
+int __init acpi_aml_init(void)
+{
+ int ret = 0;
+
+ if (!acpi_debugfs_dir) {
+ ret = -ENOENT;
+ goto err_exit;
+ }
+
+ /* Initialize AML IO interface */
+ mutex_init(&acpi_aml_io.lock);
+ init_waitqueue_head(&acpi_aml_io.wait);
+ acpi_aml_io.out_crc.buf = acpi_aml_io.out_buf;
+ acpi_aml_io.in_crc.buf = acpi_aml_io.in_buf;
+ acpi_aml_dentry = debugfs_create_file("acpidbg",
+ S_IFREG | S_IRUGO | S_IWUSR,
+ acpi_debugfs_dir, NULL,
+ &acpi_aml_operations);
+ if (acpi_aml_dentry == NULL) {
+ ret = -ENODEV;
+ goto err_exit;
+ }
+ ret = acpi_register_debugger(THIS_MODULE, &acpi_aml_debugger);
+ if (ret)
+ goto err_fs;
+ acpi_aml_initialized = true;
+
+err_fs:
+ if (ret) {
+ debugfs_remove(acpi_aml_dentry);
+ acpi_aml_dentry = NULL;
+ }
+err_exit:
+ return ret;
+}
+
+void __exit acpi_aml_exit(void)
+{
+ if (acpi_aml_initialized) {
+ acpi_unregister_debugger(&acpi_aml_debugger);
+ if (acpi_aml_dentry) {
+ debugfs_remove(acpi_aml_dentry);
+ acpi_aml_dentry = NULL;
+ }
+ acpi_aml_initialized = false;
+ }
+}
+
+module_init(acpi_aml_init);
+module_exit(acpi_aml_exit);
+
+MODULE_AUTHOR("Lv Zheng");
+MODULE_DESCRIPTION("ACPI debugger userspace IO driver");
+MODULE_LICENSE("GPL");
#include <linux/clk-provider.h>
#include <linux/err.h>
#include <linux/io.h>
+#include <linux/mutex.h>
#include <linux/platform_device.h>
#include <linux/platform_data/clk-lpss.h>
#include <linux/pm_runtime.h>
#ifdef CONFIG_X86_INTEL_LPSS
+#include <asm/cpu_device_id.h>
+#include <asm/iosf_mbi.h>
+#include <asm/pmc_atom.h>
+
#define LPSS_ADDR(desc) ((unsigned long)&desc)
#define LPSS_CLK_SIZE 0x04
void (*setup)(struct lpss_private_data *pdata);
};
-static struct lpss_device_desc lpss_dma_desc = {
+static const struct lpss_device_desc lpss_dma_desc = {
.flags = LPSS_CLK,
};
u32 prv_reg_ctx[LPSS_PRV_REG_COUNT];
};
+/* LPSS run time quirks */
+static unsigned int lpss_quirks;
+
+/*
+ * LPSS_QUIRK_ALWAYS_POWER_ON: override power state for LPSS DMA device.
+ *
+ * The LPSS DMA controller has neither _PS0 nor _PS3 method. Moreover
+ * it can be powered off automatically whenever the last LPSS device goes down.
+ * In case of no power any access to the DMA controller will hang the system.
+ * The behaviour is reproduced on some HP laptops based on Intel BayTrail as
+ * well as on ASuS T100TA transformer.
+ *
+ * This quirk overrides power state of entire LPSS island to keep DMA powered
+ * on whenever we have at least one other device in use.
+ */
+#define LPSS_QUIRK_ALWAYS_POWER_ON BIT(0)
+
/* UART Component Parameter Register */
#define LPSS_UART_CPR 0xF4
#define LPSS_UART_CPR_AFCE BIT(4)
.setup = byt_i2c_setup,
};
-static struct lpss_device_desc bsw_spi_dev_desc = {
+static const struct lpss_device_desc bsw_spi_dev_desc = {
.flags = LPSS_CLK | LPSS_CLK_GATE | LPSS_CLK_DIVIDER | LPSS_SAVE_CTX
| LPSS_NO_D3_DELAY,
.prv_offset = 0x400,
.setup = lpss_deassert_reset,
};
+#define ICPU(model) { X86_VENDOR_INTEL, 6, model, X86_FEATURE_ANY, }
+
+static const struct x86_cpu_id lpss_cpu_ids[] = {
+ ICPU(0x37), /* Valleyview, Bay Trail */
+ ICPU(0x4c), /* Braswell, Cherry Trail */
+ {}
+};
+
#else
#define LPSS_ADDR(desc) (0UL)
{
unsigned int i;
+ for (i = 0; i < LPSS_PRV_REG_COUNT; i++) {
+ unsigned long offset = i * sizeof(u32);
+
+ __lpss_reg_write(pdata->prv_reg_ctx[i], pdata, offset);
+ dev_dbg(dev, "restoring 0x%08x to LPSS reg at offset 0x%02lx\n",
+ pdata->prv_reg_ctx[i], offset);
+ }
+}
+
+static void acpi_lpss_d3_to_d0_delay(struct lpss_private_data *pdata)
+{
/*
* The following delay is needed or the subsequent write operations may
* fail. The LPSS devices are actually PCI devices and the PCI spec
delay = 0;
msleep(delay);
+}
- for (i = 0; i < LPSS_PRV_REG_COUNT; i++) {
- unsigned long offset = i * sizeof(u32);
+static int acpi_lpss_activate(struct device *dev)
+{
+ struct lpss_private_data *pdata = acpi_driver_data(ACPI_COMPANION(dev));
+ int ret;
- __lpss_reg_write(pdata->prv_reg_ctx[i], pdata, offset);
- dev_dbg(dev, "restoring 0x%08x to LPSS reg at offset 0x%02lx\n",
- pdata->prv_reg_ctx[i], offset);
- }
+ ret = acpi_dev_runtime_resume(dev);
+ if (ret)
+ return ret;
+
+ acpi_lpss_d3_to_d0_delay(pdata);
+
+ /*
+ * This is called only on ->probe() stage where a device is either in
+ * known state defined by BIOS or most likely powered off. Due to this
+ * we have to deassert reset line to be sure that ->probe() will
+ * recognize the device.
+ */
+ if (pdata->dev_desc->flags & LPSS_SAVE_CTX)
+ lpss_deassert_reset(pdata);
+
+ return 0;
+}
+
+static void acpi_lpss_dismiss(struct device *dev)
+{
+ acpi_dev_runtime_suspend(dev);
}
#ifdef CONFIG_PM_SLEEP
if (ret)
return ret;
+ acpi_lpss_d3_to_d0_delay(pdata);
+
if (pdata->dev_desc->flags & LPSS_SAVE_CTX)
acpi_lpss_restore_ctx(dev, pdata);
}
#endif /* CONFIG_PM_SLEEP */
+/* IOSF SB for LPSS island */
+#define LPSS_IOSF_UNIT_LPIOEP 0xA0
+#define LPSS_IOSF_UNIT_LPIO1 0xAB
+#define LPSS_IOSF_UNIT_LPIO2 0xAC
+
+#define LPSS_IOSF_PMCSR 0x84
+#define LPSS_PMCSR_D0 0
+#define LPSS_PMCSR_D3hot 3
+#define LPSS_PMCSR_Dx_MASK GENMASK(1, 0)
+
+#define LPSS_IOSF_GPIODEF0 0x154
+#define LPSS_GPIODEF0_DMA1_D3 BIT(2)
+#define LPSS_GPIODEF0_DMA2_D3 BIT(3)
+#define LPSS_GPIODEF0_DMA_D3_MASK GENMASK(3, 2)
+
+static DEFINE_MUTEX(lpss_iosf_mutex);
+
+static void lpss_iosf_enter_d3_state(void)
+{
+ u32 value1 = 0;
+ u32 mask1 = LPSS_GPIODEF0_DMA_D3_MASK;
+ u32 value2 = LPSS_PMCSR_D3hot;
+ u32 mask2 = LPSS_PMCSR_Dx_MASK;
+ /*
+ * PMC provides an information about actual status of the LPSS devices.
+ * Here we read the values related to LPSS power island, i.e. LPSS
+ * devices, excluding both LPSS DMA controllers, along with SCC domain.
+ */
+ u32 func_dis, d3_sts_0, pmc_status, pmc_mask = 0xfe000ffe;
+ int ret;
+
+ ret = pmc_atom_read(PMC_FUNC_DIS, &func_dis);
+ if (ret)
+ return;
+
+ mutex_lock(&lpss_iosf_mutex);
+
+ ret = pmc_atom_read(PMC_D3_STS_0, &d3_sts_0);
+ if (ret)
+ goto exit;
+
+ /*
+ * Get the status of entire LPSS power island per device basis.
+ * Shutdown both LPSS DMA controllers if and only if all other devices
+ * are already in D3hot.
+ */
+ pmc_status = (~(d3_sts_0 | func_dis)) & pmc_mask;
+ if (pmc_status)
+ goto exit;
+
+ iosf_mbi_modify(LPSS_IOSF_UNIT_LPIO1, MBI_CFG_WRITE,
+ LPSS_IOSF_PMCSR, value2, mask2);
+
+ iosf_mbi_modify(LPSS_IOSF_UNIT_LPIO2, MBI_CFG_WRITE,
+ LPSS_IOSF_PMCSR, value2, mask2);
+
+ iosf_mbi_modify(LPSS_IOSF_UNIT_LPIOEP, MBI_CR_WRITE,
+ LPSS_IOSF_GPIODEF0, value1, mask1);
+exit:
+ mutex_unlock(&lpss_iosf_mutex);
+}
+
+static void lpss_iosf_exit_d3_state(void)
+{
+ u32 value1 = LPSS_GPIODEF0_DMA1_D3 | LPSS_GPIODEF0_DMA2_D3;
+ u32 mask1 = LPSS_GPIODEF0_DMA_D3_MASK;
+ u32 value2 = LPSS_PMCSR_D0;
+ u32 mask2 = LPSS_PMCSR_Dx_MASK;
+
+ mutex_lock(&lpss_iosf_mutex);
+
+ iosf_mbi_modify(LPSS_IOSF_UNIT_LPIOEP, MBI_CR_WRITE,
+ LPSS_IOSF_GPIODEF0, value1, mask1);
+
+ iosf_mbi_modify(LPSS_IOSF_UNIT_LPIO2, MBI_CFG_WRITE,
+ LPSS_IOSF_PMCSR, value2, mask2);
+
+ iosf_mbi_modify(LPSS_IOSF_UNIT_LPIO1, MBI_CFG_WRITE,
+ LPSS_IOSF_PMCSR, value2, mask2);
+
+ mutex_unlock(&lpss_iosf_mutex);
+}
+
static int acpi_lpss_runtime_suspend(struct device *dev)
{
struct lpss_private_data *pdata = acpi_driver_data(ACPI_COMPANION(dev));
if (pdata->dev_desc->flags & LPSS_SAVE_CTX)
acpi_lpss_save_ctx(dev, pdata);
- return acpi_dev_runtime_suspend(dev);
+ ret = acpi_dev_runtime_suspend(dev);
+
+ /*
+ * This call must be last in the sequence, otherwise PMC will return
+ * wrong status for devices being about to be powered off. See
+ * lpss_iosf_enter_d3_state() for further information.
+ */
+ if (lpss_quirks & LPSS_QUIRK_ALWAYS_POWER_ON && iosf_mbi_available())
+ lpss_iosf_enter_d3_state();
+
+ return ret;
}
static int acpi_lpss_runtime_resume(struct device *dev)
struct lpss_private_data *pdata = acpi_driver_data(ACPI_COMPANION(dev));
int ret;
+ /*
+ * This call is kept first to be in symmetry with
+ * acpi_lpss_runtime_suspend() one.
+ */
+ if (lpss_quirks & LPSS_QUIRK_ALWAYS_POWER_ON && iosf_mbi_available())
+ lpss_iosf_exit_d3_state();
+
ret = acpi_dev_runtime_resume(dev);
if (ret)
return ret;
+ acpi_lpss_d3_to_d0_delay(pdata);
+
if (pdata->dev_desc->flags & LPSS_SAVE_CTX)
acpi_lpss_restore_ctx(dev, pdata);
#endif /* CONFIG_PM */
static struct dev_pm_domain acpi_lpss_pm_domain = {
+#ifdef CONFIG_PM
+ .activate = acpi_lpss_activate,
+ .dismiss = acpi_lpss_dismiss,
+#endif
.ops = {
#ifdef CONFIG_PM
#ifdef CONFIG_PM_SLEEP
}
switch (action) {
- case BUS_NOTIFY_ADD_DEVICE:
+ case BUS_NOTIFY_BIND_DRIVER:
pdev->dev.pm_domain = &acpi_lpss_pm_domain;
+ break;
+ case BUS_NOTIFY_DRIVER_NOT_BOUND:
+ case BUS_NOTIFY_UNBOUND_DRIVER:
+ pdev->dev.pm_domain = NULL;
+ break;
+ case BUS_NOTIFY_ADD_DEVICE:
if (pdata->dev_desc->flags & LPSS_LTR)
return sysfs_create_group(&pdev->dev.kobj,
&lpss_attr_group);
case BUS_NOTIFY_DEL_DEVICE:
if (pdata->dev_desc->flags & LPSS_LTR)
sysfs_remove_group(&pdev->dev.kobj, &lpss_attr_group);
- pdev->dev.pm_domain = NULL;
break;
default:
break;
void __init acpi_lpss_init(void)
{
- if (!lpt_clk_init()) {
- bus_register_notifier(&platform_bus_type, &acpi_lpss_nb);
- acpi_scan_add_handler(&lpss_handler);
- }
+ const struct x86_cpu_id *id;
+ int ret;
+
+ ret = lpt_clk_init();
+ if (ret)
+ return;
+
+ id = x86_match_cpu(lpss_cpu_ids);
+ if (id)
+ lpss_quirks |= LPSS_QUIRK_ALWAYS_POWER_ON;
+
+ bus_register_notifier(&platform_bus_type, &acpi_lpss_nb);
+ acpi_scan_add_handler(&lpss_handler);
}
#else
*/
static int is_cmos_rtc_device(struct acpi_device *adev)
{
- struct acpi_device_id ids[] = {
+ static const struct acpi_device_id ids[] = {
{ "PNP0B00" },
{ "PNP0B01" },
{ "PNP0B02" },
static int disable_backlight_sysfs_if = -1;
module_param(disable_backlight_sysfs_if, int, 0444);
+#define REPORT_OUTPUT_KEY_EVENTS 0x01
+#define REPORT_BRIGHTNESS_KEY_EVENTS 0x02
+static int report_key_events = -1;
+module_param(report_key_events, int, 0644);
+MODULE_PARM_DESC(report_key_events,
+ "0: none, 1: output changes, 2: brightness changes, 3: all");
+
static bool device_id_scheme = false;
module_param(device_id_scheme, bool, 0444);
static bool only_lcd = false;
module_param(only_lcd, bool, 0444);
-static int register_count;
-static DEFINE_MUTEX(register_count_mutex);
+static DECLARE_COMPLETION(register_done);
+static DEFINE_MUTEX(register_done_mutex);
static struct mutex video_list_lock;
static struct list_head video_bus_head;
static int acpi_video_bus_add(struct acpi_device *device);
return 0;
}
+static int video_set_report_key_events(const struct dmi_system_id *id)
+{
+ if (report_key_events == -1)
+ report_key_events = (uintptr_t)id->driver_data;
+ return 0;
+}
+
static struct dmi_system_id video_dmi_table[] = {
/*
* Broken _BQC workaround http://bugzilla.kernel.org/show_bug.cgi?id=13121
DMI_MATCH(DMI_PRODUCT_NAME, "ESPRIMO Mobile M9410"),
},
},
+ /*
+ * Some machines report wrong key events on the acpi-bus, suppress
+ * key event reporting on these. Note this is only intended to work
+ * around events which are plain wrong. In some cases we get double
+ * events, in this case acpi-video is considered the canonical source
+ * and the events from the other source should be filtered. E.g.
+ * by calling acpi_video_handles_brightness_key_presses() from the
+ * vendor acpi/wmi driver or by using /lib/udev/hwdb.d/60-keyboard.hwdb
+ */
+ {
+ .callback = video_set_report_key_events,
+ .driver_data = (void *)((uintptr_t)REPORT_OUTPUT_KEY_EVENTS),
+ .ident = "Dell Vostro V131",
+ .matches = {
+ DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc."),
+ DMI_MATCH(DMI_PRODUCT_NAME, "Vostro V131"),
+ },
+ },
{}
};
/* Something vetoed the keypress. */
keycode = 0;
- if (keycode) {
+ if (keycode && (report_key_events & REPORT_OUTPUT_KEY_EVENTS)) {
input_report_key(input, keycode, 1);
input_sync(input);
input_report_key(input, keycode, 0);
acpi_notifier_call_chain(device, event, 0);
- if (keycode) {
+ if (keycode && (report_key_events & REPORT_BRIGHTNESS_KEY_EVENTS)) {
input_report_key(input, keycode, 1);
input_sync(input);
input_report_key(input, keycode, 0);
{
int ret = 0;
- mutex_lock(®ister_count_mutex);
- if (register_count) {
+ mutex_lock(®ister_done_mutex);
+ if (completion_done(®ister_done)) {
/*
* if the function of acpi_video_register is already called,
* don't register the acpi_vide_bus again and return no error.
* When the acpi_video_bus is loaded successfully, increase
* the counter reference.
*/
- register_count = 1;
+ complete(®ister_done);
leave:
- mutex_unlock(®ister_count_mutex);
+ mutex_unlock(®ister_done_mutex);
return ret;
}
EXPORT_SYMBOL(acpi_video_register);
void acpi_video_unregister(void)
{
- mutex_lock(®ister_count_mutex);
- if (register_count) {
+ mutex_lock(®ister_done_mutex);
+ if (completion_done(®ister_done)) {
acpi_bus_unregister_driver(&acpi_video_bus);
- register_count = 0;
+ reinit_completion(®ister_done);
}
- mutex_unlock(®ister_count_mutex);
+ mutex_unlock(®ister_done_mutex);
}
EXPORT_SYMBOL(acpi_video_unregister);
{
struct acpi_video_bus *video;
- mutex_lock(®ister_count_mutex);
- if (register_count) {
+ mutex_lock(®ister_done_mutex);
+ if (completion_done(®ister_done)) {
mutex_lock(&video_list_lock);
list_for_each_entry(video, &video_bus_head, entry)
acpi_video_bus_unregister_backlight(video);
mutex_unlock(&video_list_lock);
}
- mutex_unlock(®ister_count_mutex);
+ mutex_unlock(®ister_done_mutex);
+}
+
+bool acpi_video_handles_brightness_key_presses(void)
+{
+ bool have_video_busses;
+
+ wait_for_completion(®ister_done);
+ mutex_lock(&video_list_lock);
+ have_video_busses = !list_empty(&video_bus_head);
+ mutex_unlock(&video_list_lock);
+
+ return have_video_busses &&
+ (report_key_events & REPORT_BRIGHTNESS_KEY_EVENTS);
}
+EXPORT_SYMBOL(acpi_video_handles_brightness_key_presses);
/*
* This is kind of nasty. Hardware using Intel chipsets may require
exdump.o \
exfield.o \
exfldio.o \
+ exmisc.o \
exmutex.o \
exnames.o \
exoparg1.o \
exoparg3.o \
exoparg6.o \
exprep.o \
- exmisc.o \
exregion.o \
exresnte.o \
exresolv.o \
exstoren.o \
exstorob.o \
exsystem.o \
+ extrace.o \
exutils.o
acpi-y += \
dbfileio.o \
dbtest.o \
utcache.o \
- utfileio.o \
utprint.o \
uttrack.o \
utuuid.o
#ifndef _ACAPPS
#define _ACAPPS
+#include <stdio.h>
+
/* Common info for tool signons */
#define ACPICA_NAME "Intel ACPI Component Architecture"
acpi_os_printf (description);
#define ACPI_OPTION(name, description) \
- acpi_os_printf (" %-18s%s\n", name, description);
+ acpi_os_printf (" %-20s%s\n", name, description);
+
+/* Check for unexpected exceptions */
+
+#define ACPI_CHECK_STATUS(name, status, expected) \
+ if (status != expected) \
+ { \
+ acpi_os_printf ("Unexpected %s from %s (%s-%d)\n", \
+ acpi_format_exception (status), #name, _acpi_module_name, __LINE__); \
+ }
+
+/* Check for unexpected non-AE_OK errors */
+
+#define ACPI_CHECK_OK(name, status) ACPI_CHECK_STATUS (name, status, AE_OK);
#define FILE_SUFFIX_DISASSEMBLY "dsl"
#define FILE_SUFFIX_BINARY_TABLE ".dat" /* Needs the dot */
+/* acfileio */
+
+acpi_status
+ac_get_all_tables_from_file(char *filename,
+ u8 get_only_aml_tables,
+ struct acpi_new_table_desc **return_list_head);
+
+u8 ac_is_file_binary(FILE * file);
+
+acpi_status ac_validate_table_header(FILE * file, long table_offset);
+
+/* Values for get_only_aml_tables */
+
+#define ACPI_GET_ONLY_AML_TABLES TRUE
+#define ACPI_GET_ALL_TABLES FALSE
+
/*
* getopt
*/
*/
u32 cm_get_file_size(ACPI_FILE file);
-#ifndef ACPI_DUMP_APP
-/*
- * adisasm
- */
-acpi_status
-ad_aml_disassemble(u8 out_to_file,
- char *filename, char *prefix, char **out_filename);
-
-void ad_print_statistics(void);
-
-acpi_status ad_find_dsdt(u8 **dsdt_ptr, u32 *dsdt_length);
-
-void ad_dump_tables(void);
-
-acpi_status ad_get_local_tables(void);
-
-acpi_status
-ad_parse_table(struct acpi_table_header *table,
- acpi_owner_id * owner_id, u8 load_table, u8 external);
-
-acpi_status ad_display_tables(char *filename, struct acpi_table_header *table);
-
-acpi_status ad_display_statistics(void);
-
/*
* adwalk
*/
void
ad_write_table(struct acpi_table_header *table,
u32 length, char *table_name, char *oem_table_id);
-#endif
#endif /* _ACAPPS */
/*
* dbxface - external debugger interfaces
*/
-acpi_status
-acpi_db_single_step(struct acpi_walk_state *walk_state,
- union acpi_parse_object *op, u32 op_type);
+ACPI_DBR_DEPENDENT_RETURN_OK(acpi_status
+ acpi_db_single_step(struct acpi_walk_state
+ *walk_state,
+ union acpi_parse_object *op,
+ u32 op_type))
+ ACPI_DBR_DEPENDENT_RETURN_VOID(void
+ acpi_db_signal_break_point(struct
+ acpi_walk_state
+ *walk_state))
/*
* dbcmds - debug commands and output routines
void acpi_db_decode_and_display_object(char *target, char *output_type);
-void
-acpi_db_display_result_object(union acpi_operand_object *obj_desc,
- struct acpi_walk_state *walk_state);
+ACPI_DBR_DEPENDENT_RETURN_VOID(void
+ acpi_db_display_result_object(union
+ acpi_operand_object
+ *obj_desc,
+ struct
+ acpi_walk_state
+ *walk_state))
-acpi_status acpi_db_display_all_methods(char *display_count_arg);
+ acpi_status acpi_db_display_all_methods(char *display_count_arg);
void acpi_db_display_arguments(void);
void acpi_db_display_object_type(char *object_arg);
-void
-acpi_db_display_argument_object(union acpi_operand_object *obj_desc,
- struct acpi_walk_state *walk_state);
+ACPI_DBR_DEPENDENT_RETURN_VOID(void
+ acpi_db_display_argument_object(union
+ acpi_operand_object
+ *obj_desc,
+ struct
+ acpi_walk_state
+ *walk_state))
/*
* dbexec - debugger control method execution
acpi_status acpi_db_load_acpi_table(char *filename);
-acpi_status
-acpi_db_get_table_from_file(char *filename,
- struct acpi_table_header **table,
- u8 must_be_aml_table);
+acpi_status acpi_db_load_tables(struct acpi_new_table_desc *list_head);
/*
* dbhistry - debugger HISTORY command
void ACPI_SYSTEM_XFACE acpi_db_execute_thread(void *context);
-acpi_status acpi_db_user_commands(char prompt, union acpi_parse_object *op);
+acpi_status acpi_db_user_commands(void);
char *acpi_db_get_next_token(char *string,
char **next, acpi_object_type * return_type);
/*
* evhandler - Address space handling
*/
+union acpi_operand_object *acpi_ev_find_region_handler(acpi_adr_space_type
+ space_id,
+ union acpi_operand_object
+ *handler_obj);
+
u8
acpi_ev_has_default_handler(struct acpi_namespace_node *node,
acpi_adr_space_type space_id);
acpi_ev_detach_region(union acpi_operand_object *region_obj,
u8 acpi_ns_is_locked);
-acpi_status
+void acpi_ev_associate_reg_method(union acpi_operand_object *region_obj);
+
+void
acpi_ev_execute_reg_methods(struct acpi_namespace_node *node,
- acpi_adr_space_type space_id);
+ acpi_adr_space_type space_id, u32 function);
acpi_status
acpi_ev_execute_reg_method(union acpi_operand_object *region_obj, u32 function);
ACPI_INIT_GLOBAL(u32, acpi_gbl_startup_flags, 0);
ACPI_INIT_GLOBAL(u8, acpi_gbl_shutdown, TRUE);
+ACPI_INIT_GLOBAL(u8, acpi_gbl_early_initialization, TRUE);
/* Global handlers */
/* Initialization sequencing */
-ACPI_GLOBAL(u8, acpi_gbl_reg_methods_executed);
+ACPI_INIT_GLOBAL(u8, acpi_gbl_reg_methods_enabled, FALSE);
/* Misc */
#ifdef ACPI_DEBUGGER
ACPI_INIT_GLOBAL(u8, acpi_gbl_abort_method, FALSE);
-ACPI_INIT_GLOBAL(u8, acpi_gbl_method_executing, FALSE);
ACPI_INIT_GLOBAL(acpi_thread_id, acpi_gbl_db_thread_id, ACPI_INVALID_THREAD_ID);
ACPI_GLOBAL(u8, acpi_gbl_db_opt_no_ini_methods);
/* These buffers should all be the same size */
-ACPI_GLOBAL(char, acpi_gbl_db_line_buf[ACPI_DB_LINE_BUFFER_SIZE]);
ACPI_GLOBAL(char, acpi_gbl_db_parsed_buf[ACPI_DB_LINE_BUFFER_SIZE]);
ACPI_GLOBAL(char, acpi_gbl_db_scope_buf[ACPI_DB_LINE_BUFFER_SIZE]);
ACPI_GLOBAL(char, acpi_gbl_db_debug_filename[ACPI_DB_LINE_BUFFER_SIZE]);
ACPI_GLOBAL(u32, acpi_gbl_num_nodes);
ACPI_GLOBAL(u32, acpi_gbl_num_objects);
-ACPI_GLOBAL(acpi_mutex, acpi_gbl_db_command_ready);
-ACPI_GLOBAL(acpi_mutex, acpi_gbl_db_command_complete);
-
#endif /* ACPI_DEBUGGER */
/*****************************************************************************
#define ACPI_ROOT_ORIGIN_ALLOCATED (1)
#define ACPI_ROOT_ALLOW_RESIZE (2)
+/* List to manage incoming ACPI tables */
+
+struct acpi_new_table_desc {
+ struct acpi_table_header *table;
+ struct acpi_new_table_desc *next;
+};
+
/* Predefined table indexes */
#define ACPI_INVALID_TABLE_INDEX (0xFFFFFFFF)
/* Return object auto-repair info */
-typedef acpi_status(*acpi_object_converter) (union acpi_operand_object
+typedef acpi_status(*acpi_object_converter) (struct acpi_namespace_node * scope,
+ union acpi_operand_object
*original_object,
union acpi_operand_object
**converted_object);
struct acpi_reg_walk_info {
acpi_adr_space_type space_id;
+ u32 function;
u32 reg_run_count;
};
#define ACPI_PARSEOP_CLOSING_PAREN 0x10
#define ACPI_PARSEOP_COMPOUND 0x20
#define ACPI_PARSEOP_ASSIGNMENT 0x40
+#define ACPI_PARSEOP_ELSEIF 0x80
/*****************************************************************************
*
#define ACPI_HW_OPTIONAL_FUNCTION(addr) NULL
#endif
-/*
- * Some code only gets executed when the debugger is built in.
- * Note that this is entirely independent of whether the
- * DEBUG_PRINT stuff (set by ACPI_DEBUG_OUTPUT) is on, or not.
- */
-#ifdef ACPI_DEBUGGER
-#define ACPI_DEBUGGER_EXEC(a) a
-#else
-#define ACPI_DEBUGGER_EXEC(a)
-#endif
-
/*
* Macros used for ACPICA utilities only
*/
/* Object is not a package element */
#define ACPI_NOT_PACKAGE_ELEMENT ACPI_UINT32_MAX
+#define ACPI_ALL_PACKAGE_ELEMENTS (ACPI_UINT32_MAX-1)
/* Always emit warning message, not dependent on node flags */
union acpi_operand_object **return_object);
acpi_status
-acpi_ns_convert_to_unicode(union acpi_operand_object *original_object,
+acpi_ns_convert_to_unicode(struct acpi_namespace_node *scope,
+ union acpi_operand_object *original_object,
union acpi_operand_object **return_object);
acpi_status
-acpi_ns_convert_to_resource(union acpi_operand_object *original_object,
+acpi_ns_convert_to_resource(struct acpi_namespace_node *scope,
+ union acpi_operand_object *original_object,
union acpi_operand_object **return_object);
+acpi_status
+acpi_ns_convert_to_reference(struct acpi_namespace_node *scope,
+ union acpi_operand_object *original_object,
+ union acpi_operand_object **return_object);
+
/*
* nsdump - Namespace dump/print utilities
*/
#define AOPOBJ_AML_CONSTANT 0x01 /* Integer is an AML constant */
#define AOPOBJ_STATIC_POINTER 0x02 /* Data is part of an ACPI table, don't delete */
#define AOPOBJ_DATA_VALID 0x04 /* Object is initialized and data is valid */
-#define AOPOBJ_OBJECT_INITIALIZED 0x08 /* Region is initialized, _REG was run */
-#define AOPOBJ_SETUP_COMPLETE 0x10 /* Region setup is complete */
-#define AOPOBJ_INVALID 0x20 /* Host OS won't allow a Region address */
+#define AOPOBJ_OBJECT_INITIALIZED 0x08 /* Region is initialized */
+#define AOPOBJ_REG_CONNECTED 0x10 /* _REG was run */
+#define AOPOBJ_SETUP_COMPLETE 0x20 /* Region setup is complete */
+#define AOPOBJ_INVALID 0x40 /* Host OS won't allow a Region address */
/******************************************************************************
*
#define ARGP_BYTELIST_OP ARGP_LIST1 (ARGP_NAMESTRING)
#define ARGP_CONCAT_OP ARGP_LIST3 (ARGP_TERMARG, ARGP_TERMARG, ARGP_TARGET)
#define ARGP_CONCAT_RES_OP ARGP_LIST3 (ARGP_TERMARG, ARGP_TERMARG, ARGP_TARGET)
-#define ARGP_COND_REF_OF_OP ARGP_LIST2 (ARGP_SUPERNAME, ARGP_SUPERNAME)
+#define ARGP_COND_REF_OF_OP ARGP_LIST2 (ARGP_NAME_OR_REF,ARGP_TARGET)
#define ARGP_CONNECTFIELD_OP ARGP_LIST1 (ARGP_NAMESTRING)
#define ARGP_CONTINUE_OP ARG_NONE
#define ARGP_COPY_OP ARGP_LIST2 (ARGP_TERMARG, ARGP_SIMPLENAME)
#define ARGP_NAMEPATH_OP ARGP_LIST1 (ARGP_NAMESTRING)
#define ARGP_NOOP_OP ARG_NONE
#define ARGP_NOTIFY_OP ARGP_LIST2 (ARGP_SUPERNAME, ARGP_TERMARG)
+#define ARGP_OBJECT_TYPE_OP ARGP_LIST1 (ARGP_NAME_OR_REF)
#define ARGP_ONE_OP ARG_NONE
#define ARGP_ONES_OP ARG_NONE
#define ARGP_PACKAGE_OP ARGP_LIST3 (ARGP_PKGLENGTH, ARGP_BYTEDATA, ARGP_DATAOBJLIST)
#define ARGP_POWER_RES_OP ARGP_LIST5 (ARGP_PKGLENGTH, ARGP_NAME, ARGP_BYTEDATA, ARGP_WORDDATA, ARGP_OBJLIST)
#define ARGP_PROCESSOR_OP ARGP_LIST6 (ARGP_PKGLENGTH, ARGP_NAME, ARGP_BYTEDATA, ARGP_DWORDDATA, ARGP_BYTEDATA, ARGP_OBJLIST)
#define ARGP_QWORD_OP ARGP_LIST1 (ARGP_QWORDDATA)
-#define ARGP_REF_OF_OP ARGP_LIST1 (ARGP_SUPERNAME)
+#define ARGP_REF_OF_OP ARGP_LIST1 (ARGP_NAME_OR_REF)
#define ARGP_REGION_OP ARGP_LIST4 (ARGP_NAME, ARGP_BYTEDATA, ARGP_TERMARG, ARGP_TERMARG)
#define ARGP_RELEASE_OP ARGP_LIST1 (ARGP_SUPERNAME)
#define ARGP_RESERVEDFIELD_OP ARGP_LIST1 (ARGP_NAMESTRING)
#define ARGP_TO_HEX_STR_OP ARGP_LIST2 (ARGP_TERMARG, ARGP_TARGET)
#define ARGP_TO_INTEGER_OP ARGP_LIST2 (ARGP_TERMARG, ARGP_TARGET)
#define ARGP_TO_STRING_OP ARGP_LIST3 (ARGP_TERMARG, ARGP_TERMARG, ARGP_TARGET)
-#define ARGP_TYPE_OP ARGP_LIST1 (ARGP_SUPERNAME)
#define ARGP_UNLOAD_OP ARGP_LIST1 (ARGP_SUPERNAME)
#define ARGP_VAR_PACKAGE_OP ARGP_LIST3 (ARGP_PKGLENGTH, ARGP_TERMARG, ARGP_DATAOBJLIST)
#define ARGP_WAIT_OP ARGP_LIST2 (ARGP_SUPERNAME, ARGP_TERMARG)
#define ARGI_BUFFER_OP ARGI_LIST1 (ARGI_INTEGER)
#define ARGI_BYTE_OP ARGI_INVALID_OPCODE
#define ARGI_BYTELIST_OP ARGI_INVALID_OPCODE
-#define ARGI_CONCAT_OP ARGI_LIST3 (ARGI_COMPUTEDATA,ARGI_COMPUTEDATA, ARGI_TARGETREF)
+#define ARGI_CONCAT_OP ARGI_LIST3 (ARGI_ANYTYPE, ARGI_ANYTYPE, ARGI_TARGETREF)
#define ARGI_CONCAT_RES_OP ARGI_LIST3 (ARGI_BUFFER, ARGI_BUFFER, ARGI_TARGETREF)
#define ARGI_COND_REF_OF_OP ARGI_LIST2 (ARGI_OBJECT_REF, ARGI_TARGETREF)
#define ARGI_CONNECTFIELD_OP ARGI_INVALID_OPCODE
#define ARGI_NAMEPATH_OP ARGI_INVALID_OPCODE
#define ARGI_NOOP_OP ARG_NONE
#define ARGI_NOTIFY_OP ARGI_LIST2 (ARGI_DEVICE_REF, ARGI_INTEGER)
+#define ARGI_OBJECT_TYPE_OP ARGI_LIST1 (ARGI_ANYTYPE)
#define ARGI_ONE_OP ARG_NONE
#define ARGI_ONES_OP ARG_NONE
#define ARGI_PACKAGE_OP ARGI_LIST1 (ARGI_INTEGER)
#define ARGI_TO_HEX_STR_OP ARGI_LIST2 (ARGI_COMPUTEDATA,ARGI_FIXED_TARGET)
#define ARGI_TO_INTEGER_OP ARGI_LIST2 (ARGI_COMPUTEDATA,ARGI_FIXED_TARGET)
#define ARGI_TO_STRING_OP ARGI_LIST3 (ARGI_BUFFER, ARGI_INTEGER, ARGI_FIXED_TARGET)
-#define ARGI_TYPE_OP ARGI_LIST1 (ARGI_ANYTYPE)
#define ARGI_UNLOAD_OP ARGI_LIST1 (ARGI_DDBHANDLE)
#define ARGI_VAR_PACKAGE_OP ARGI_LIST1 (ARGI_INTEGER)
#define ARGI_WAIT_OP ARGI_LIST2 (ARGI_EVENT, ARGI_INTEGER)
acpi_status
acpi_ps_get_next_namepath(struct acpi_walk_state *walk_state,
struct acpi_parse_state *parser_state,
- union acpi_parse_object *arg, u8 method_call);
+ union acpi_parse_object *arg,
+ u8 possible_method_call);
+
+/* Values for u8 above */
+
+#define ACPI_NOT_METHOD_CALL FALSE
+#define ACPI_POSSIBLE_METHOD_CALL TRUE
acpi_status
acpi_ps_get_next_arg(struct acpi_walk_state *walk_state,
#if defined(ACPI_DEBUG_OUTPUT) || defined(ACPI_DEBUGGER)
-char *acpi_ut_get_mutex_name(u32 mutex_id);
+const char *acpi_ut_get_mutex_name(u32 mutex_id);
const char *acpi_ut_get_notify_name(u32 notify_value, acpi_object_type type);
#endif
-char *acpi_ut_get_type_name(acpi_object_type type);
+const char *acpi_ut_get_type_name(acpi_object_type type);
-char *acpi_ut_get_node_name(void *object);
+const char *acpi_ut_get_node_name(void *object);
-char *acpi_ut_get_descriptor_name(void *object);
+const char *acpi_ut_get_descriptor_name(void *object);
const char *acpi_ut_get_reference_name(union acpi_operand_object *object);
-char *acpi_ut_get_object_type_name(union acpi_operand_object *obj_desc);
+const char *acpi_ut_get_object_type_name(union acpi_operand_object *obj_desc);
-char *acpi_ut_get_region_name(u8 space_id);
+const char *acpi_ut_get_region_name(u8 space_id);
-char *acpi_ut_get_event_name(u32 event_id);
+const char *acpi_ut_get_event_name(u32 event_id);
char acpi_ut_hex_to_ascii_char(u64 integer, u32 position);
const char **method_names,
u8 method_count, u8 *out_values);
-/*
- * utfileio - file operations
- */
-#ifdef ACPI_APPLICATION
-acpi_status
-acpi_ut_read_table_from_file(char *filename, struct acpi_table_header **table);
-#endif
-
/*
* utids - device ID support
*/
acpi_ut_execute_UID(struct acpi_namespace_node *device_node,
struct acpi_pnp_device_id ** return_id);
-acpi_status
-acpi_ut_execute_SUB(struct acpi_namespace_node *device_node,
- struct acpi_pnp_device_id **return_id);
-
acpi_status
acpi_ut_execute_CID(struct acpi_namespace_node *device_node,
struct acpi_pnp_device_id_list ** return_cid_list);
#define AML_CREATE_WORD_FIELD_OP (u16) 0x8b
#define AML_CREATE_BYTE_FIELD_OP (u16) 0x8c
#define AML_CREATE_BIT_FIELD_OP (u16) 0x8d
-#define AML_TYPE_OP (u16) 0x8e
+#define AML_OBJECT_TYPE_OP (u16) 0x8e
#define AML_CREATE_QWORD_FIELD_OP (u16) 0x8f /* ACPI 2.0 */
#define AML_LAND_OP (u16) 0x90
#define AML_LOR_OP (u16) 0x91
#define ARGP_TERMLIST 0x0F
#define ARGP_WORDDATA 0x10
#define ARGP_QWORDDATA 0x11
-#define ARGP_SIMPLENAME 0x12
+#define ARGP_SIMPLENAME 0x12 /* name_string | local_term | arg_term */
+#define ARGP_NAME_OR_REF 0x13 /* For object_type only */
/*
* Resolved argument types for the AML Interpreter
acpi_status status;
node = ACPI_CAST_PTR(struct acpi_namespace_node, obj_handle);
- parent_path = acpi_ns_get_external_pathname(node);
+ parent_path = acpi_ns_get_normalized_pathname(node, TRUE);
if (!parent_path) {
return (AE_NO_MEMORY);
}
u32 debug_layer = 0;
u32 flags = 0;
- if (enable_arg) {
- acpi_ut_strupr(enable_arg);
- }
-
- if (once_arg) {
- acpi_ut_strupr(once_arg);
- }
+ acpi_ut_strupr(enable_arg);
+ acpi_ut_strupr(once_arg);
if (method_arg) {
if (acpi_db_trace_method_name) {
#include "acnamesp.h"
#include "acparser.h"
#include "acinterp.h"
+#include "acevents.h"
#include "acdebug.h"
#define _COMPONENT ACPI_CA_DEBUGGER
*
* FUNCTION: acpi_db_display_object_type
*
- * PARAMETERS: name - User entered NS node handle or name
+ * PARAMETERS: object_arg - User entered NS node handle
*
* RETURN: None
*
*
******************************************************************************/
-void acpi_db_display_object_type(char *name)
+void acpi_db_display_object_type(char *object_arg)
{
- struct acpi_namespace_node *node;
+ acpi_handle handle;
struct acpi_device_info *info;
acpi_status status;
u32 i;
- node = acpi_db_convert_to_node(name);
- if (!node) {
- return;
- }
+ handle = ACPI_TO_POINTER(strtoul(object_arg, NULL, 16));
- status = acpi_get_object_info(ACPI_CAST_PTR(acpi_handle, node), &info);
+ status = acpi_get_object_info(handle, &info);
if (ACPI_FAILURE(status)) {
acpi_os_printf("Could not get object info, %s\n",
acpi_format_exception(status));
return;
}
- if (info->valid & ACPI_VALID_ADR) {
- acpi_os_printf("ADR: %8.8X%8.8X, STA: %8.8X, Flags: %X\n",
- ACPI_FORMAT_UINT64(info->address),
- info->current_status, info->flags);
- }
- if (info->valid & ACPI_VALID_SXDS) {
- acpi_os_printf("S1D-%2.2X S2D-%2.2X S3D-%2.2X S4D-%2.2X\n",
- info->highest_dstates[0],
- info->highest_dstates[1],
- info->highest_dstates[2],
- info->highest_dstates[3]);
- }
- if (info->valid & ACPI_VALID_SXWS) {
- acpi_os_printf
- ("S0W-%2.2X S1W-%2.2X S2W-%2.2X S3W-%2.2X S4W-%2.2X\n",
- info->lowest_dstates[0], info->lowest_dstates[1],
- info->lowest_dstates[2], info->lowest_dstates[3],
- info->lowest_dstates[4]);
- }
+ acpi_os_printf("ADR: %8.8X%8.8X, STA: %8.8X, Flags: %X\n",
+ ACPI_FORMAT_UINT64(info->address),
+ info->current_status, info->flags);
+
+ acpi_os_printf("S1D-%2.2X S2D-%2.2X S3D-%2.2X S4D-%2.2X\n",
+ info->highest_dstates[0], info->highest_dstates[1],
+ info->highest_dstates[2], info->highest_dstates[3]);
+
+ acpi_os_printf("S0W-%2.2X S1W-%2.2X S2W-%2.2X S3W-%2.2X S4W-%2.2X\n",
+ info->lowest_dstates[0], info->lowest_dstates[1],
+ info->lowest_dstates[2], info->lowest_dstates[3],
+ info->lowest_dstates[4]);
if (info->valid & ACPI_VALID_HID) {
acpi_os_printf("HID: %s\n", info->hardware_id.string);
acpi_os_printf("UID: %s\n", info->unique_id.string);
}
- if (info->valid & ACPI_VALID_SUB) {
- acpi_os_printf("SUB: %s\n", info->subsystem_id.string);
- }
-
if (info->valid & ACPI_VALID_CID) {
for (i = 0; i < info->compatible_id_list.count; i++) {
acpi_os_printf("CID %u: %s\n", i,
struct acpi_walk_state *walk_state)
{
+#ifndef ACPI_APPLICATION
+ if (acpi_gbl_db_thread_id != acpi_os_get_thread_id()) {
+ return;
+ }
+#endif
+
/* Only display if single stepping */
if (!acpi_gbl_cm_single_step) {
struct acpi_walk_state *walk_state)
{
+#ifndef ACPI_APPLICATION
+ if (acpi_gbl_db_thread_id != acpi_os_get_thread_id()) {
+ return;
+ }
+#endif
+
if (!acpi_gbl_cm_single_step) {
return;
}
if (obj_desc) {
for (i = 0; i < ACPI_ARRAY_LENGTH(acpi_gbl_space_id_list); i++) {
space_id = acpi_gbl_space_id_list[i];
- handler_obj = obj_desc->device.handler;
acpi_os_printf(ACPI_PREDEFINED_PREFIX,
acpi_ut_get_region_name((u8)space_id),
space_id);
- while (handler_obj) {
- if (acpi_gbl_space_id_list[i] ==
- handler_obj->address_space.space_id) {
- acpi_os_printf
- (ACPI_HANDLER_PRESENT_STRING,
- (handler_obj->address_space.
- handler_flags &
- ACPI_ADDR_HANDLER_DEFAULT_INSTALLED)
- ? "Default" : "User",
- handler_obj->address_space.
- handler);
-
- goto found_handler;
- }
+ handler_obj =
+ acpi_ev_find_region_handler(space_id,
+ obj_desc->common_notify.
+ handler);
+ if (handler_obj) {
+ acpi_os_printf(ACPI_HANDLER_PRESENT_STRING,
+ (handler_obj->address_space.
+ handler_flags &
+ ACPI_ADDR_HANDLER_DEFAULT_INSTALLED)
+ ? "Default" : "User",
+ handler_obj->address_space.
+ handler);
- handler_obj = handler_obj->address_space.next;
+ goto found_handler;
}
/* There is no handler for this space_id */
/* Find all handlers for user-defined space_IDs */
- handler_obj = obj_desc->device.handler;
+ handler_obj = obj_desc->common_notify.handler;
while (handler_obj) {
if (handler_obj->address_space.space_id >=
ACPI_USER_REGION_BEGIN) {
return (AE_OK);
}
- pathname = acpi_ns_get_external_pathname(node);
+ pathname = acpi_ns_get_normalized_pathname(node, TRUE);
if (!pathname) {
return (AE_OK);
}
/* Display all handlers associated with this device */
- handler_obj = obj_desc->device.handler;
+ handler_obj = obj_desc->common_notify.handler;
while (handler_obj) {
acpi_os_printf(ACPI_PREDEFINED_PREFIX,
acpi_ut_get_region_name((u8)handler_obj->
#include "accommon.h"
#include "acdebug.h"
#include "actables.h"
+#include <stdio.h>
+#ifdef ACPI_APPLICATION
+#include "acapps.h"
+#endif
#define _COMPONENT ACPI_CA_DEBUGGER
ACPI_MODULE_NAME("dbfileio")
}
#endif
-#ifdef ACPI_APPLICATION
-#include "acapps.h"
-
-/*******************************************************************************
- *
- * FUNCTION: ae_local_load_table
- *
- * PARAMETERS: table - pointer to a buffer containing the entire
- * table to be loaded
- *
- * RETURN: Status
- *
- * DESCRIPTION: This function is called to load a table from the caller's
- * buffer. The buffer must contain an entire ACPI Table including
- * a valid header. The header fields will be verified, and if it
- * is determined that the table is invalid, the call will fail.
- *
- ******************************************************************************/
-
-static acpi_status ae_local_load_table(struct acpi_table_header *table)
-{
- acpi_status status = AE_OK;
-
- ACPI_FUNCTION_TRACE(ae_local_load_table);
-
-#if 0
-/* struct acpi_table_desc table_info; */
-
- if (!table) {
- return_ACPI_STATUS(AE_BAD_PARAMETER);
- }
-
- table_info.pointer = table;
- status = acpi_tb_recognize_table(&table_info, ACPI_TABLE_ALL);
- if (ACPI_FAILURE(status)) {
- return_ACPI_STATUS(status);
- }
-
- /* Install the new table into the local data structures */
-
- status = acpi_tb_init_table_descriptor(&table_info);
- if (ACPI_FAILURE(status)) {
- if (status == AE_ALREADY_EXISTS) {
-
- /* Table already exists, no error */
-
- status = AE_OK;
- }
-
- /* Free table allocated by acpi_tb_get_table */
-
- acpi_tb_delete_single_table(&table_info);
- return_ACPI_STATUS(status);
- }
-#if (!defined (ACPI_NO_METHOD_EXECUTION) && !defined (ACPI_CONSTANT_EVAL_ONLY))
-
- status =
- acpi_ns_load_table(table_info.installed_desc, acpi_gbl_root_node);
- if (ACPI_FAILURE(status)) {
-
- /* Uninstall table and free the buffer */
-
- acpi_tb_delete_tables_by_type(ACPI_TABLE_ID_DSDT);
- return_ACPI_STATUS(status);
- }
-#endif
-#endif
-
- return_ACPI_STATUS(status);
-}
-#endif
-
/*******************************************************************************
*
- * FUNCTION: acpi_db_get_table_from_file
+ * FUNCTION: acpi_db_load_tables
*
- * PARAMETERS: filename - File where table is located
- * return_table - Where a pointer to the table is returned
+ * PARAMETERS: list_head - List of ACPI tables to load
*
* RETURN: Status
*
- * DESCRIPTION: Load an ACPI table from a file
+ * DESCRIPTION: Load ACPI tables from a previously constructed table list.
*
******************************************************************************/
-acpi_status
-acpi_db_get_table_from_file(char *filename,
- struct acpi_table_header **return_table,
- u8 must_be_aml_file)
+acpi_status acpi_db_load_tables(struct acpi_new_table_desc *list_head)
{
-#ifdef ACPI_APPLICATION
acpi_status status;
+ struct acpi_new_table_desc *table_list_head;
struct acpi_table_header *table;
- u8 is_aml_table = TRUE;
-
- status = acpi_ut_read_table_from_file(filename, &table);
- if (ACPI_FAILURE(status)) {
- return (status);
- }
-
- if (must_be_aml_file) {
- is_aml_table = acpi_ut_is_aml_table(table);
- if (!is_aml_table) {
- ACPI_EXCEPTION((AE_INFO, AE_OK,
- "Input for -e is not an AML table: "
- "\"%4.4s\" (must be DSDT/SSDT)",
- table->signature));
- return (AE_TYPE);
- }
- }
- if (is_aml_table) {
+ /* Load all ACPI tables in the list */
- /* Attempt to recognize and install the table */
+ table_list_head = list_head;
+ while (table_list_head) {
+ table = table_list_head->table;
- status = ae_local_load_table(table);
+ status = acpi_load_table(table);
if (ACPI_FAILURE(status)) {
if (status == AE_ALREADY_EXISTS) {
acpi_os_printf
return (status);
}
- acpi_tb_print_table_header(0, table);
-
fprintf(stderr,
"Acpi table [%4.4s] successfully installed and loaded\n",
table->signature);
- }
- acpi_gbl_acpi_hardware_present = FALSE;
- if (return_table) {
- *return_table = table;
+ table_list_head = table_list_head->next;
}
-#endif /* ACPI_APPLICATION */
return (AE_OK);
}
#include "accommon.h"
#include "acdebug.h"
+#ifdef ACPI_APPLICATION
+#include "acapps.h"
+#endif
+
#define _COMPONENT ACPI_CA_DEBUGGER
ACPI_MODULE_NAME("dbinput")
static u32 acpi_db_match_command(char *user_command);
-static void acpi_db_single_thread(void);
-
static void acpi_db_display_command_info(char *command, u8 display_all);
static void acpi_db_display_help(char *command);
/* Uppercase the actual command */
- if (acpi_gbl_db_args[0]) {
- acpi_ut_strupr(acpi_gbl_db_args[0]);
- }
+ acpi_ut_strupr(acpi_gbl_db_args[0]);
count = i;
if (count) {
acpi_db_close_debug_file();
break;
- case CMD_LOAD:
+ case CMD_LOAD:{
+ struct acpi_new_table_desc *list_head = NULL;
- status =
- acpi_db_get_table_from_file(acpi_gbl_db_args[1], NULL,
- FALSE);
+ status =
+ ac_get_all_tables_from_file(acpi_gbl_db_args[1],
+ ACPI_GET_ALL_TABLES,
+ &list_head);
+ if (ACPI_SUCCESS(status)) {
+ acpi_db_load_tables(list_head);
+ }
+ }
break;
case CMD_OPEN:
void ACPI_SYSTEM_XFACE acpi_db_execute_thread(void *context)
{
- acpi_status status = AE_OK;
- acpi_status Mstatus;
-
- while (status != AE_CTRL_TERMINATE && !acpi_gbl_db_terminate_loop) {
- acpi_gbl_method_executing = FALSE;
- acpi_gbl_step_to_next_call = FALSE;
-
- Mstatus = acpi_os_acquire_mutex(acpi_gbl_db_command_ready,
- ACPI_WAIT_FOREVER);
- if (ACPI_FAILURE(Mstatus)) {
- return;
- }
-
- status =
- acpi_db_command_dispatch(acpi_gbl_db_line_buf, NULL, NULL);
- acpi_os_release_mutex(acpi_gbl_db_command_complete);
- }
+ (void)acpi_db_user_commands();
acpi_gbl_db_threads_terminated = TRUE;
}
-/*******************************************************************************
- *
- * FUNCTION: acpi_db_single_thread
- *
- * PARAMETERS: None
- *
- * RETURN: None
- *
- * DESCRIPTION: Debugger execute thread. Waits for a command line, then
- * simply dispatches it.
- *
- ******************************************************************************/
-
-static void acpi_db_single_thread(void)
-{
-
- acpi_gbl_method_executing = FALSE;
- acpi_gbl_step_to_next_call = FALSE;
-
- (void)acpi_db_command_dispatch(acpi_gbl_db_line_buf, NULL, NULL);
-}
-
/*******************************************************************************
*
* FUNCTION: acpi_db_user_commands
*
- * PARAMETERS: prompt - User prompt (depends on mode)
- * op - Current executing parse op
+ * PARAMETERS: None
*
* RETURN: None
*
*
******************************************************************************/
-acpi_status acpi_db_user_commands(char prompt, union acpi_parse_object *op)
+acpi_status acpi_db_user_commands(void)
{
acpi_status status = AE_OK;
while (!acpi_gbl_db_terminate_loop) {
- /* Force output to console until a command is entered */
-
- acpi_db_set_output_destination(ACPI_DB_CONSOLE_OUTPUT);
-
- /* Different prompt if method is executing */
-
- if (!acpi_gbl_method_executing) {
- acpi_os_printf("%1c ", ACPI_DEBUGGER_COMMAND_PROMPT);
- } else {
- acpi_os_printf("%1c ", ACPI_DEBUGGER_EXECUTE_PROMPT);
- }
+ /* Wait the readiness of the command */
- /* Get the user input line */
-
- status = acpi_os_get_line(acpi_gbl_db_line_buf,
- ACPI_DB_LINE_BUFFER_SIZE, NULL);
+ status = acpi_os_wait_command_ready();
if (ACPI_FAILURE(status)) {
- ACPI_EXCEPTION((AE_INFO, status,
- "While parsing command line"));
- return (status);
+ break;
}
- /* Check for single or multithreaded debug */
+ /* Just call to the command line interpreter */
- if (acpi_gbl_debugger_configuration & DEBUGGER_MULTI_THREADED) {
- /*
- * Signal the debug thread that we have a command to execute,
- * and wait for the command to complete.
- */
- acpi_os_release_mutex(acpi_gbl_db_command_ready);
- if (ACPI_FAILURE(status)) {
- return (status);
- }
+ acpi_gbl_method_executing = FALSE;
+ acpi_gbl_step_to_next_call = FALSE;
- status =
- acpi_os_acquire_mutex(acpi_gbl_db_command_complete,
- ACPI_WAIT_FOREVER);
- if (ACPI_FAILURE(status)) {
- return (status);
- }
- } else {
- /* Just call to the command line interpreter */
+ (void)acpi_db_command_dispatch(acpi_gbl_db_line_buf, NULL,
+ NULL);
+
+ /* Notify the completion of the command */
- acpi_db_single_thread();
+ status = acpi_os_notify_command_complete();
+ if (ACPI_FAILURE(status)) {
+ break;
}
}
+ if (ACPI_FAILURE(status) && status != AE_CTRL_TERMINATE) {
+ ACPI_EXCEPTION((AE_INFO, status, "While parsing command line"));
+ }
return (status);
}
return (AE_OK);
}
- pathname = acpi_ns_get_external_pathname(node);
+ pathname = acpi_ns_get_normalized_pathname(node, TRUE);
if (!pathname) {
return (AE_OK);
}
acpi_gbl_node_type_count[i],
acpi_gbl_obj_type_count[i]);
}
+
acpi_os_printf("%16.16s % 10ld% 10ld\n", "Misc/Unknown",
acpi_gbl_node_type_count_misc,
acpi_gbl_obj_type_count_misc);
return (AE_OK);
}
- pathname = acpi_ns_get_external_pathname(node);
+ pathname = acpi_ns_get_normalized_pathname(node, TRUE);
if (!pathname) {
return (AE_OK);
}
if (obj_desc->buffer.length > 16) {
acpi_os_printf("\n");
}
+
acpi_ut_debug_dump_buffer(ACPI_CAST_PTR
(u8,
obj_desc->buffer.pointer),
acpi_gbl_method_executing = TRUE;
status = AE_CTRL_TRUE;
- while (status == AE_CTRL_TRUE) {
- if (acpi_gbl_debugger_configuration == DEBUGGER_MULTI_THREADED) {
-
- /* Handshake with the front-end that gets user command lines */
-
- acpi_os_release_mutex(acpi_gbl_db_command_complete);
-
- status =
- acpi_os_acquire_mutex(acpi_gbl_db_command_ready,
- ACPI_WAIT_FOREVER);
- if (ACPI_FAILURE(status)) {
- return (status);
- }
- } else {
- /* Single threaded, we must get a command line ourselves */
-
- /* Force output to console until a command is entered */
- acpi_db_set_output_destination(ACPI_DB_CONSOLE_OUTPUT);
+ while (status == AE_CTRL_TRUE) {
- /* Different prompt if method is executing */
+ /* Notify the completion of the command */
- if (!acpi_gbl_method_executing) {
- acpi_os_printf("%1c ",
- ACPI_DEBUGGER_COMMAND_PROMPT);
- } else {
- acpi_os_printf("%1c ",
- ACPI_DEBUGGER_EXECUTE_PROMPT);
- }
+ status = acpi_os_notify_command_complete();
+ if (ACPI_FAILURE(status)) {
+ goto error_exit;
+ }
- /* Get the user input line */
+ /* Wait the readiness of the command */
- status = acpi_os_get_line(acpi_gbl_db_line_buf,
- ACPI_DB_LINE_BUFFER_SIZE,
- NULL);
- if (ACPI_FAILURE(status)) {
- ACPI_EXCEPTION((AE_INFO, status,
- "While parsing command line"));
- return (status);
- }
+ status = acpi_os_wait_command_ready();
+ if (ACPI_FAILURE(status)) {
+ goto error_exit;
}
status =
/* acpi_ut_acquire_mutex (ACPI_MTX_NAMESPACE); */
+error_exit:
+ if (ACPI_FAILURE(status) && status != AE_CTRL_TERMINATE) {
+ ACPI_EXCEPTION((AE_INFO, status,
+ "While parsing/handling command line"));
+ }
return (status);
}
+/*******************************************************************************
+ *
+ * FUNCTION: acpi_db_signal_break_point
+ *
+ * PARAMETERS: walk_state - Current walk
+ *
+ * RETURN: Status
+ *
+ * DESCRIPTION: Called for AML_BREAK_POINT_OP
+ *
+ ******************************************************************************/
+
+void acpi_db_signal_break_point(struct acpi_walk_state *walk_state)
+{
+
+#ifndef ACPI_APPLICATION
+ if (acpi_gbl_db_thread_id != acpi_os_get_thread_id()) {
+ return;
+ }
+#endif
+
+ /*
+ * Set the single-step flag. This will cause the debugger (if present)
+ * to break to the console within the AML debugger at the start of the
+ * next AML instruction.
+ */
+ acpi_gbl_cm_single_step = TRUE;
+ acpi_os_printf("**break** Executed AML BreakPoint opcode\n");
+}
+
/*******************************************************************************
*
* FUNCTION: acpi_db_single_step
/* These were created with one unit, grab it */
- status = acpi_os_acquire_mutex(acpi_gbl_db_command_complete,
- ACPI_WAIT_FOREVER);
- if (ACPI_FAILURE(status)) {
- acpi_os_printf("Could not get debugger mutex\n");
- return_ACPI_STATUS(status);
- }
-
- status = acpi_os_acquire_mutex(acpi_gbl_db_command_ready,
- ACPI_WAIT_FOREVER);
+ status = acpi_os_initialize_command_signals();
if (ACPI_FAILURE(status)) {
acpi_os_printf("Could not get debugger mutex\n");
return_ACPI_STATUS(status);
acpi_gbl_db_terminate_loop = TRUE;
if (acpi_gbl_debugger_configuration & DEBUGGER_MULTI_THREADED) {
- acpi_os_release_mutex(acpi_gbl_db_command_ready);
/* Wait the AML Debugger threads */
while (!acpi_gbl_db_threads_terminated) {
acpi_os_sleep(100);
}
+
+ acpi_os_terminate_command_signals();
}
if (acpi_gbl_db_buffer) {
extra_desc = acpi_ns_get_secondary_object(obj_desc);
node = obj_desc->buffer_field.node;
- ACPI_DEBUG_EXEC(acpi_ut_display_init_pathname(ACPI_TYPE_BUFFER_FIELD,
- node, NULL));
+ ACPI_DEBUG_EXEC(acpi_ut_display_init_pathname
+ (ACPI_TYPE_BUFFER_FIELD, node, NULL));
ACPI_DEBUG_PRINT((ACPI_DB_EXEC, "[%4.4s] BufferField Arg Init\n",
acpi_ut_get_node_name(node)));
ACPI_DEBUG_EXEC(acpi_ut_display_init_pathname
(ACPI_TYPE_REGION, node, NULL));
- ACPI_DEBUG_PRINT((ACPI_DB_EXEC, "[%4.4s] OpRegion Arg Init at AML %p\n",
+ ACPI_DEBUG_PRINT((ACPI_DB_EXEC,
+ "[%4.4s] OpRegion Arg Init at AML %p\n",
acpi_ut_get_node_name(node),
extra_desc->extra.aml_start));
#include "amlcode.h"
#include "acdispat.h"
#include "acinterp.h"
+#include "acdebug.h"
#define _COMPONENT ACPI_DISPATCHER
ACPI_MODULE_NAME("dscontrol")
case AML_BREAK_POINT_OP:
- /*
- * Set the single-step flag. This will cause the debugger (if present)
- * to break to the console within the AML debugger at the start of the
- * next AML instruction.
- */
- ACPI_DEBUGGER_EXEC(acpi_gbl_cm_single_step = TRUE);
- ACPI_DEBUGGER_EXEC(acpi_os_printf
- ("**break** Executed AML BreakPoint opcode\n"));
+ acpi_db_signal_break_point(walk_state);
/* Call to the OSL in case OS wants a piece of the action */
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 */
} 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.
+ * 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 "));
* insert the name into the namespace.
*/
acpi_dm_add_op_to_external_list(op, path, ACPI_TYPE_REGION, 0, 0);
+
status = acpi_ns_lookup(walk_state->scope_info, path, ACPI_TYPE_REGION,
ACPI_IMODE_LOAD_PASS1, ACPI_NS_SEARCH_PARENT,
walk_state, node);
/* Enter the name_string into the namespace */
- status =
- acpi_ns_lookup(walk_state->scope_info,
- arg->common.value.string, ACPI_TYPE_ANY,
- ACPI_IMODE_LOAD_PASS1, flags, walk_state,
- &node);
+ status = acpi_ns_lookup(walk_state->scope_info,
+ arg->common.value.string, ACPI_TYPE_ANY,
+ ACPI_IMODE_LOAD_PASS1, flags,
+ walk_state, &node);
if (ACPI_FAILURE(status)) {
ACPI_ERROR_NAMESPACE(arg->common.value.string, status);
return_ACPI_STATUS(status);
}
/*
- * Remember location in AML stream of the field unit opcode and operands --
- * since the buffer and index operands must be evaluated.
+ * Remember location in AML stream of the field unit opcode and operands
+ * -- since the buffer and index operands must be evaluated.
*/
second_desc = obj_desc->common.next_object;
second_desc->extra.aml_start = op->named.data;
switch (arg->common.aml_opcode) {
case AML_INT_RESERVEDFIELD_OP:
- position = (u64) info->field_bit_position
- + (u64) arg->common.value.size;
+ position = (u64)info->field_bit_position +
+ (u64)arg->common.value.size;
if (position > ACPI_UINT32_MAX) {
ACPI_ERROR((AE_INFO,
/* access_attribute (attrib_quick, attrib_byte, etc.) */
- info->attribute =
- (u8)((arg->common.value.integer >> 8) & 0xFF);
+ info->attribute = (u8)
+ ((arg->common.value.integer >> 8) & 0xFF);
/* access_length (for serial/buffer protocols) */
- info->access_length =
- (u8)((arg->common.value.integer >> 16) & 0xFF);
+ info->access_length = (u8)
+ ((arg->common.value.integer >> 16) & 0xFF);
break;
case AML_INT_CONNECTION_OP:
/* Keep track of bit position for the next field */
- position = (u64) info->field_bit_position
- + (u64) arg->common.value.size;
+ position = (u64)info->field_bit_position +
+ (u64)arg->common.value.size;
if (position > ACPI_UINT32_MAX) {
ACPI_ERROR((AE_INFO,
/*
* Use Info.data_register_node to store bank_field Op
- * It's safe because data_register_node will never be used when create bank field
- * We store aml_start and aml_length in the bank_field Op for late evaluation
- * Used in acpi_ex_prep_field_value(Info)
+ * It's safe because data_register_node will never be used when create
+ * bank field \we store aml_start and aml_length in the bank_field Op for
+ * late evaluation. Used in acpi_ex_prep_field_value(Info)
*
- * TBD: Or, should we add a field in struct acpi_create_field_info, like "void *ParentOp"?
+ * TBD: Or, should we add a field in struct acpi_create_field_info, like
+ * "void *ParentOp"?
*/
info.data_register_node = (struct acpi_namespace_node *)op;
/* Summary of objects initialized */
ACPI_DEBUG_PRINT_RAW((ACPI_DB_INIT,
- "Table [%4.4s:%8.8s] (id %.2X) - %4u Objects with %3u Devices, "
+ "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,
return_ACPI_STATUS(AE_NO_MEMORY);
}
- status =
- acpi_ds_init_aml_walk(walk_state, op, node,
- obj_desc->method.aml_start,
- obj_desc->method.aml_length, NULL, 0);
+ status = acpi_ds_init_aml_walk(walk_state, op, node,
+ obj_desc->method.aml_start,
+ obj_desc->method.aml_length, NULL, 0);
if (ACPI_FAILURE(status)) {
acpi_ds_delete_walk_state(walk_state);
acpi_ps_free_op(op);
&& (walk_state->thread->current_sync_level >
obj_desc->method.mutex->mutex.sync_level)) {
ACPI_ERROR((AE_INFO,
- "Cannot acquire Mutex for method [%4.4s], current SyncLevel is too large (%u)",
+ "Cannot acquire Mutex for method [%4.4s]"
+ ", current SyncLevel is too large (%u)",
acpi_ut_get_node_name(method_node),
walk_state->thread->current_sync_level));
obj_desc->method.mutex->mutex.thread_id =
walk_state->thread->thread_id;
- walk_state->thread->current_sync_level =
- obj_desc->method.sync_level;
+
+ /*
+ * Update the current sync_level only if this is not an auto-
+ * serialized method. In the auto case, we have to ignore
+ * the sync level for the method mutex (created for the
+ * auto-serialization) because we have no idea of what the
+ * sync level should be. Therefore, just ignore it.
+ */
+ if (!(obj_desc->method.info_flags &
+ ACPI_METHOD_IGNORE_SYNC_LEVEL)) {
+ walk_state->thread->current_sync_level =
+ obj_desc->method.sync_level;
+ }
} else {
obj_desc->method.mutex->mutex.
original_sync_level =
/* Init for new method, possibly wait on method mutex */
- status = acpi_ds_begin_method_execution(method_node, obj_desc,
- this_walk_state);
+ status =
+ acpi_ds_begin_method_execution(method_node, obj_desc,
+ this_walk_state);
if (ACPI_FAILURE(status)) {
return_ACPI_STATUS(status);
}
/* Begin method parse/execution. Create a new walk state */
- next_walk_state = acpi_ds_create_walk_state(obj_desc->method.owner_id,
- NULL, obj_desc, thread);
+ next_walk_state =
+ acpi_ds_create_walk_state(obj_desc->method.owner_id, NULL, obj_desc,
+ thread);
if (!next_walk_state) {
status = AE_NO_MEMORY;
goto cleanup;
info_flags & ACPI_METHOD_SERIALIZED_PENDING) {
if (walk_state) {
ACPI_INFO((AE_INFO,
- "Marking method %4.4s as Serialized because of AE_ALREADY_EXISTS error",
+ "Marking method %4.4s as Serialized "
+ "because of AE_ALREADY_EXISTS error",
walk_state->method_node->name.
ascii));
}
*/
method_desc->method.info_flags &=
~ACPI_METHOD_SERIALIZED_PENDING;
+
method_desc->method.info_flags |=
(ACPI_METHOD_SERIALIZED |
ACPI_METHOD_IGNORE_SYNC_LEVEL);
for (i = 0; i < ACPI_METHOD_NUM_ARGS; i++) {
ACPI_MOVE_32_TO_32(&walk_state->arguments[i].name,
NAMEOF_ARG_NTE);
+
walk_state->arguments[i].name.integer |= (i << 24);
walk_state->arguments[i].descriptor_type = ACPI_DESC_TYPE_NAMED;
walk_state->arguments[i].type = ACPI_TYPE_ANY;
if (!params) {
ACPI_DEBUG_PRINT((ACPI_DB_EXEC,
- "No param list passed to method\n"));
+ "No parameter list passed to method\n"));
return_ACPI_STATUS(AE_OK);
}
* Store the argument in the method/walk descriptor.
* Do not copy the arg in order to implement call by reference
*/
- status = acpi_ds_method_data_set_value(ACPI_REFCLASS_ARG, index,
- params[index],
- walk_state);
+ status =
+ acpi_ds_method_data_set_value(ACPI_REFCLASS_ARG, index,
+ params[index], walk_state);
if (ACPI_FAILURE(status)) {
return_ACPI_STATUS(status);
}
* do the indirect store
*/
if ((ACPI_GET_DESCRIPTOR_TYPE(current_obj_desc) ==
- ACPI_DESC_TYPE_OPERAND)
- && (current_obj_desc->common.type ==
- ACPI_TYPE_LOCAL_REFERENCE)
- && (current_obj_desc->reference.class ==
- ACPI_REFCLASS_REFOF)) {
+ ACPI_DESC_TYPE_OPERAND) &&
+ (current_obj_desc->common.type ==
+ ACPI_TYPE_LOCAL_REFERENCE) &&
+ (current_obj_desc->reference.class ==
+ ACPI_REFCLASS_REFOF)) {
ACPI_DEBUG_PRINT((ACPI_DB_EXEC,
"Arg (%p) is an ObjRef(Node), storing in node %p\n",
new_obj_desc,
if (new_obj_desc != obj_desc) {
acpi_ut_remove_reference(new_obj_desc);
}
+
return_ACPI_STATUS(status);
}
}
arg->common.node);
}
} else {
- status = acpi_ds_build_internal_object(walk_state, arg,
- &obj_desc->
- package.
- elements[i]);
+ status =
+ acpi_ds_build_internal_object(walk_state, arg,
+ &obj_desc->package.
+ elements[i]);
}
if (*obj_desc_ptr) {
}
ACPI_INFO((AE_INFO,
- "Actual Package length (%u) is larger than NumElements field (%u), truncated",
+ "Actual Package length (%u) is larger than "
+ "NumElements field (%u), truncated",
i, element_count));
} else if (i < element_count) {
/*
* Note: this is not an error, the package is padded out with NULLs.
*/
ACPI_DEBUG_PRINT((ACPI_DB_INFO,
- "Package List length (%u) smaller than NumElements count (%u), padded with null elements\n",
+ "Package List length (%u) smaller than NumElements "
+ "count (%u), padded with null elements\n",
i, element_count));
}
/* Build an internal object for the argument(s) */
- status = acpi_ds_build_internal_object(walk_state, op->common.value.arg,
- &obj_desc);
+ status =
+ acpi_ds_build_internal_object(walk_state, op->common.value.arg,
+ &obj_desc);
if (ACPI_FAILURE(status)) {
return_ACPI_STATUS(status);
}
* For field_flags, use LOCK_RULE = 0 (NO_LOCK),
* UPDATE_RULE = 0 (UPDATE_PRESERVE)
*/
- status = acpi_ex_prep_common_field_object(obj_desc, field_flags, 0,
- bit_offset, bit_count);
+ status =
+ acpi_ex_prep_common_field_object(obj_desc, field_flags, 0,
+ bit_offset, bit_count);
if (ACPI_FAILURE(status)) {
goto cleanup;
}
/* Resolve the operands */
- status = acpi_ex_resolve_operands(op->common.aml_opcode,
- ACPI_WALK_OPERANDS, walk_state);
+ status =
+ acpi_ex_resolve_operands(op->common.aml_opcode, ACPI_WALK_OPERANDS,
+ walk_state);
if (ACPI_FAILURE(status)) {
ACPI_ERROR((AE_INFO, "(%s) bad operand(s), status 0x%X",
acpi_ps_get_opcode_name(op->common.aml_opcode),
/* Resolve the length and address operands to numbers */
- status = acpi_ex_resolve_operands(op->common.aml_opcode,
- ACPI_WALK_OPERANDS, walk_state);
+ status =
+ acpi_ex_resolve_operands(op->common.aml_opcode, ACPI_WALK_OPERANDS,
+ walk_state);
if (ACPI_FAILURE(status)) {
return_ACPI_STATUS(status);
}
/* Now the address and length are valid for this opregion */
obj_desc->region.flags |= AOPOBJ_DATA_VALID;
-
return_ACPI_STATUS(status);
}
* Resolve the Signature string, oem_id string,
* and oem_table_id string operands
*/
- status = acpi_ex_resolve_operands(op->common.aml_opcode,
- ACPI_WALK_OPERANDS, walk_state);
+ status =
+ acpi_ex_resolve_operands(op->common.aml_opcode, ACPI_WALK_OPERANDS,
+ walk_state);
if (ACPI_FAILURE(status)) {
goto cleanup;
}
* we will use the return value
*/
if ((walk_state->control_state->common.state ==
- ACPI_CONTROL_PREDICATE_EXECUTING)
- && (walk_state->control_state->control.
- predicate_op == op)) {
+ ACPI_CONTROL_PREDICATE_EXECUTING) &&
+ (walk_state->control_state->control.predicate_op ==
+ op)) {
goto result_used;
}
break;
/* Get the entire name string from the AML stream */
- status =
- acpi_ex_get_name_string(ACPI_TYPE_ANY,
- arg->common.value.buffer,
- &name_string, &name_length);
+ status = acpi_ex_get_name_string(ACPI_TYPE_ANY,
+ arg->common.value.buffer,
+ &name_string, &name_length);
if (ACPI_FAILURE(status)) {
return_ACPI_STATUS(status);
*/
if ((walk_state->deferred_node) &&
(walk_state->deferred_node->type == ACPI_TYPE_BUFFER_FIELD)
- && (arg_index ==
- (u32) ((walk_state->opcode ==
- AML_CREATE_FIELD_OP) ? 3 : 2))) {
+ && (arg_index == (u32)
+ ((walk_state->opcode == AML_CREATE_FIELD_OP) ? 3 : 2))) {
obj_desc =
ACPI_CAST_PTR(union acpi_operand_object,
walk_state->deferred_node);
op_info =
acpi_ps_get_opcode_info(parent_op->common.
aml_opcode);
- if ((op_info->flags & AML_NSNODE)
- && (parent_op->common.aml_opcode !=
- AML_INT_METHODCALL_OP)
+
+ if ((op_info->flags & AML_NSNODE) &&
+ (parent_op->common.aml_opcode !=
+ AML_INT_METHODCALL_OP)
&& (parent_op->common.aml_opcode != AML_REGION_OP)
&& (parent_op->common.aml_opcode !=
AML_INT_NAMEPATH_OP)) {
if (ACPI_FAILURE(status)) {
return_ACPI_STATUS(status);
}
- ACPI_DEBUGGER_EXEC(acpi_db_display_argument_object
- (obj_desc, walk_state));
+
+ acpi_db_display_argument_object(obj_desc, walk_state);
} else {
/* Check for null name case */
return_ACPI_STATUS(AE_NOT_IMPLEMENTED);
}
- if ((op_info->flags & AML_HAS_RETVAL)
- || (arg->common.flags & ACPI_PARSEOP_IN_STACK)) {
+ if ((op_info->flags & AML_HAS_RETVAL) ||
+ (arg->common.flags & ACPI_PARSEOP_IN_STACK)) {
ACPI_DEBUG_PRINT((ACPI_DB_DISPATCH,
"Argument previously created, already stacked\n"));
- ACPI_DEBUGGER_EXEC(acpi_db_display_argument_object
- (walk_state->
- operands[walk_state->num_operands -
- 1], walk_state));
+ acpi_db_display_argument_object(walk_state->
+ operands[walk_state->
+ num_operands -
+ 1],
+ walk_state);
/*
* Use value that was already previously returned
return_ACPI_STATUS(status);
}
- ACPI_DEBUGGER_EXEC(acpi_db_display_argument_object
- (obj_desc, walk_state));
+ acpi_db_display_argument_object(obj_desc, walk_state);
}
return_ACPI_STATUS(AE_OK);
cleanup:
- ACPI_DEBUG_PRINT((ACPI_DB_EXEC, "Completed a predicate eval=%X Op=%p\n",
+ ACPI_DEBUG_PRINT((ACPI_DB_EXEC,
+ "Completed a predicate eval=%X Op=%p\n",
walk_state->control_state->common.value,
walk_state->op));
/* Break to debugger to display result */
- ACPI_DEBUGGER_EXEC(acpi_db_display_result_object
- (local_obj_desc, walk_state));
+ acpi_db_display_result_object(local_obj_desc, walk_state);
/*
* Delete the predicate result object (we know that
(walk_state->control_state->common.state ==
ACPI_CONTROL_CONDITIONAL_EXECUTING)) {
ACPI_DEBUG_PRINT((ACPI_DB_EXEC,
- "Exec predicate Op=%p State=%p\n", op,
- walk_state));
+ "Exec predicate Op=%p State=%p\n",
+ op, walk_state));
walk_state->control_state->common.state =
ACPI_CONTROL_PREDICATE_EXECUTING;
/* Call debugger for single step support (DEBUG build only) */
- ACPI_DEBUGGER_EXEC(status =
- acpi_db_single_step(walk_state, op, op_class));
- ACPI_DEBUGGER_EXEC(if (ACPI_FAILURE(status)) {
- return_ACPI_STATUS(status);}
- ) ;
+ status = acpi_db_single_step(walk_state, op, op_class);
+ if (ACPI_FAILURE(status)) {
+ return_ACPI_STATUS(status);
+ }
/* Decode the Opcode Class */
"Method Reference in a Package, Op=%p\n",
op));
- op->common.node =
- (struct acpi_namespace_node *)op->asl.value.
- arg->asl.node;
+ op->common.node = (struct acpi_namespace_node *)
+ op->asl.value.arg->asl.node;
acpi_ut_add_reference(op->asl.value.arg->asl.
node->object);
return_ACPI_STATUS(AE_OK);
* Put the Node on the object stack (Contains the ACPI Name
* of this object)
*/
- walk_state->operands[0] =
- (void *)op->common.parent->common.node;
+ walk_state->operands[0] = (void *)
+ op->common.parent->common.node;
walk_state->num_operands = 1;
status = acpi_ds_create_node(walk_state,
default:
ACPI_ERROR((AE_INFO,
- "Unimplemented opcode, class=0x%X type=0x%X Opcode=0x%X Op=%p",
+ "Unimplemented opcode, class=0x%X "
+ "type=0x%X Opcode=0x%X Op=%p",
op_class, op_type, op->common.aml_opcode,
op));
/* Break to debugger to display result */
- ACPI_DEBUGGER_EXEC(acpi_db_display_result_object
- (walk_state->result_obj, walk_state));
+ acpi_db_display_result_object(walk_state->result_obj,
+ walk_state);
/*
* Delete the result op if and only if:
status =
acpi_ex_create_region(op->named.data,
op->named.length,
- (acpi_adr_space_type) ((op->
- common.
- value.
- arg)->
- common.
- value.
- integer),
+ (acpi_adr_space_type)
+ ((op->common.value.arg)->
+ common.value.integer),
walk_state);
if (ACPI_FAILURE(status)) {
return_ACPI_STATUS(status);
* Executing a method: initialize the region and unlock
* the interpreter
*/
- status =
- acpi_ex_create_region(op->named.data,
- op->named.length,
- region_space,
- walk_state);
+ status = acpi_ex_create_region(op->named.data,
+ op->named.length,
+ region_space,
+ walk_state);
if (ACPI_FAILURE(status)) {
return_ACPI_STATUS(status);
}
length,
walk_state);
}
+
walk_state->operands[0] = NULL;
walk_state->num_operands = 0;
"Popped object type (%s)\n",
acpi_ut_get_type_name(scope_info->common.
value)));
+
acpi_ut_delete_generic_state(scope_info);
}
}
ACPI_SET_BIT(gpe_register_info->enable_for_run,
(u8)register_bit);
}
- gpe_register_info->enable_mask = gpe_register_info->enable_for_run;
+ gpe_register_info->enable_mask = gpe_register_info->enable_for_run;
return_ACPI_STATUS(AE_OK);
}
if (gpe_block->next) {
gpe_block->next->previous = gpe_block->previous;
}
+
acpi_os_release_lock(acpi_gbl_gpe_lock, flags);
}
ACPI_FREE(notify);
notify = next;
}
+
gpe_event_info->dispatch.notify_list = NULL;
gpe_event_info->flags &=
~ACPI_GPE_DISPATCH_MASK;
obj_desc = acpi_ns_get_attached_object(node);
if (obj_desc) {
- handler_obj = obj_desc->device.handler;
+ handler_obj = obj_desc->common_notify.handler;
/* Walk the linked list of handlers for this object */
/* Check if this Device already has a handler for this address space */
- next_handler_obj = obj_desc->device.handler;
- while (next_handler_obj) {
+ next_handler_obj =
+ acpi_ev_find_region_handler(handler_obj->address_space.
+ space_id,
+ obj_desc->common_notify.
+ handler);
+ if (next_handler_obj) {
/* Found a handler, is it for the same address space? */
- if (next_handler_obj->address_space.space_id ==
- handler_obj->address_space.space_id) {
- ACPI_DEBUG_PRINT((ACPI_DB_OPREGION,
- "Found handler for region [%s] in device %p(%p) "
- "handler %p\n",
- acpi_ut_get_region_name
- (handler_obj->address_space.
- space_id), obj_desc,
- next_handler_obj,
- handler_obj));
-
- /*
- * Since the object we found it on was a device, then it
- * means that someone has already installed a handler for
- * the branch of the namespace from this device on. Just
- * bail out telling the walk routine to not traverse this
- * branch. This preserves the scoping rule for handlers.
- */
- return (AE_CTRL_DEPTH);
- }
-
- /* Walk the linked list of handlers attached to this device */
-
- next_handler_obj = next_handler_obj->address_space.next;
+ ACPI_DEBUG_PRINT((ACPI_DB_OPREGION,
+ "Found handler for region [%s] in device %p(%p) handler %p\n",
+ acpi_ut_get_region_name(handler_obj->
+ address_space.
+ space_id),
+ obj_desc, next_handler_obj,
+ handler_obj));
+
+ /*
+ * Since the object we found it on was a device, then it means
+ * that someone has already installed a handler for the branch
+ * of the namespace from this device on. Just bail out telling
+ * the walk routine to not traverse this branch. This preserves
+ * the scoping rule for handlers.
+ */
+ return (AE_CTRL_DEPTH);
}
/*
return (status);
}
+/*******************************************************************************
+ *
+ * FUNCTION: acpi_ev_find_region_handler
+ *
+ * PARAMETERS: space_id - The address space ID
+ * handler_obj - Head of the handler object list
+ *
+ * RETURN: Matching handler object. NULL if space ID not matched
+ *
+ * DESCRIPTION: Search a handler object list for a match on the address
+ * space ID.
+ *
+ ******************************************************************************/
+
+union acpi_operand_object *acpi_ev_find_region_handler(acpi_adr_space_type
+ space_id,
+ union acpi_operand_object
+ *handler_obj)
+{
+
+ /* Walk the handler list for this device */
+
+ while (handler_obj) {
+
+ /* Same space_id indicates a handler is installed */
+
+ if (handler_obj->address_space.space_id == space_id) {
+ return (handler_obj);
+ }
+
+ /* Next handler object */
+
+ handler_obj = handler_obj->address_space.next;
+ }
+
+ return (NULL);
+}
+
/*******************************************************************************
*
* FUNCTION: acpi_ev_install_space_handler
{
union acpi_operand_object *obj_desc;
union acpi_operand_object *handler_obj;
- acpi_status status;
+ acpi_status status = AE_OK;
acpi_object_type type;
u8 flags = 0;
ACPI_FUNCTION_TRACE(ev_install_space_handler);
/*
- * This registration is valid for only the types below and the root. This
- * is where the default handlers get placed.
+ * This registration is valid for only the types below and the root.
+ * The root node is where the default handlers get installed.
*/
if ((node->type != ACPI_TYPE_DEVICE) &&
(node->type != ACPI_TYPE_PROCESSOR) &&
obj_desc = acpi_ns_get_attached_object(node);
if (obj_desc) {
/*
- * The attached device object already exists. Make sure the handler
- * is not already installed.
+ * The attached device object already exists. Now make sure
+ * the handler is not already installed.
*/
- handler_obj = obj_desc->device.handler;
-
- /* Walk the handler list for this device */
-
- while (handler_obj) {
-
- /* Same space_id indicates a handler already installed */
+ handler_obj = acpi_ev_find_region_handler(space_id,
+ obj_desc->
+ common_notify.
+ handler);
- if (handler_obj->address_space.space_id == space_id) {
- if (handler_obj->address_space.handler ==
- handler) {
- /*
- * It is (relatively) OK to attempt to install the SAME
- * handler twice. This can easily happen with the
- * PCI_Config space.
- */
- status = AE_SAME_HANDLER;
- goto unlock_and_exit;
- } else {
- /* A handler is already installed */
-
- status = AE_ALREADY_EXISTS;
- }
+ if (handler_obj) {
+ if (handler_obj->address_space.handler == handler) {
+ /*
+ * It is (relatively) OK to attempt to install the SAME
+ * handler twice. This can easily happen with the
+ * PCI_Config space.
+ */
+ status = AE_SAME_HANDLER;
goto unlock_and_exit;
- }
+ } else {
+ /* A handler is already installed */
- /* Walk the linked list of handlers */
+ status = AE_ALREADY_EXISTS;
+ }
- handler_obj = handler_obj->address_space.next;
+ goto unlock_and_exit;
}
} else {
ACPI_DEBUG_PRINT((ACPI_DB_OPREGION,
}
ACPI_DEBUG_PRINT((ACPI_DB_OPREGION,
- "Installing address handler for region %s(%X) on Device %4.4s %p(%p)\n",
+ "Installing address handler for region %s(%X) "
+ "on Device %4.4s %p(%p)\n",
acpi_ut_get_region_name(space_id), space_id,
acpi_ut_get_node_name(node), node, obj_desc));
/* Install at head of Device.address_space list */
- handler_obj->address_space.next = obj_desc->device.handler;
+ handler_obj->address_space.next = obj_desc->common_notify.handler;
/*
* The Device object is the first reference on the handler_obj.
* Each region that uses the handler adds a reference.
*/
- obj_desc->device.handler = handler_obj;
+ obj_desc->common_notify.handler = handler_obj;
/*
- * Walk the namespace finding all of the regions this
- * handler will manage.
+ * Walk the namespace finding all of the regions this handler will
+ * manage.
*
- * Start at the device and search the branch toward
- * the leaf nodes until either the leaf is encountered or
- * a device is detected that has an address handler of the
- * same type.
+ * Start at the device and search the branch toward the leaf nodes
+ * until either the leaf is encountered or a device is detected that
+ * has an address handler of the same type.
*
- * In either case, back up and search down the remainder
- * of the branch
+ * In either case, back up and search down the remainder of the branch
*/
- status = acpi_ns_walk_namespace(ACPI_TYPE_ANY, node, ACPI_UINT32_MAX,
- ACPI_NS_WALK_UNLOCK,
+ status = acpi_ns_walk_namespace(ACPI_TYPE_ANY, node,
+ ACPI_UINT32_MAX, ACPI_NS_WALK_UNLOCK,
acpi_ev_install_handler, NULL,
handler_obj, NULL);
u8 acpi_ev_is_notify_object(struct acpi_namespace_node *node)
{
+
switch (node->type) {
case ACPI_TYPE_DEVICE:
case ACPI_TYPE_PROCESSOR:
acpi_ut_get_notify_name(notify_value, ACPI_TYPE_ANY),
node));
- status = acpi_os_execute(OSL_NOTIFY_HANDLER, acpi_ev_notify_dispatch,
- info);
+ status = acpi_os_execute(OSL_NOTIFY_HANDLER,
+ acpi_ev_notify_dispatch, info);
if (ACPI_FAILURE(status)) {
acpi_ut_delete_generic_state(info);
}
if (acpi_ev_has_default_handler(acpi_gbl_root_node,
acpi_gbl_default_address_spaces
[i])) {
- status =
- acpi_ev_execute_reg_methods(acpi_gbl_root_node,
- acpi_gbl_default_address_spaces
- [i]);
+ acpi_ev_execute_reg_methods(acpi_gbl_root_node,
+ acpi_gbl_default_address_spaces
+ [i], ACPI_REG_CONNECT);
}
}
- acpi_gbl_reg_methods_executed = TRUE;
-
(void)acpi_ut_release_mutex(ACPI_MTX_NAMESPACE);
return_ACPI_STATUS(status);
}
* DESCRIPTION: Dispatch an address space or operation region access to
* a previously installed handler.
*
+ * NOTE: During early initialization, we always install the default region
+ * handlers for Memory, I/O and PCI_Config. This ensures that these operation
+ * region address spaces are always available as per the ACPI specification.
+ * This is especially needed in order to support the execution of
+ * module-level AML code during loading of the ACPI tables.
+ *
******************************************************************************/
acpi_status
ACPI_FUNCTION_TRACE(ev_attach_region);
+ /* Install the region's handler */
+
+ if (region_obj->region.handler) {
+ return_ACPI_STATUS(AE_ALREADY_EXISTS);
+ }
+
ACPI_DEBUG_PRINT((ACPI_DB_OPREGION,
"Adding Region [%4.4s] %p to address handler %p [%s]\n",
acpi_ut_get_node_name(region_obj->region.node),
region_obj->region.next = handler_obj->address_space.region_list;
handler_obj->address_space.region_list = region_obj;
+ region_obj->region.handler = handler_obj;
+ acpi_ut_add_reference(handler_obj);
- /* Install the region's handler */
+ return_ACPI_STATUS(AE_OK);
+}
- if (region_obj->region.handler) {
- return_ACPI_STATUS(AE_ALREADY_EXISTS);
+/*******************************************************************************
+ *
+ * FUNCTION: acpi_ev_associate_reg_method
+ *
+ * PARAMETERS: region_obj - Region object
+ *
+ * RETURN: Status
+ *
+ * DESCRIPTION: Find and associate _REG method to a region
+ *
+ ******************************************************************************/
+
+void acpi_ev_associate_reg_method(union acpi_operand_object *region_obj)
+{
+ acpi_name *reg_name_ptr = (acpi_name *) METHOD_NAME__REG;
+ struct acpi_namespace_node *method_node;
+ struct acpi_namespace_node *node;
+ union acpi_operand_object *region_obj2;
+ acpi_status status;
+
+ ACPI_FUNCTION_TRACE(ev_associate_reg_method);
+
+ region_obj2 = acpi_ns_get_secondary_object(region_obj);
+ if (!region_obj2) {
+ return_VOID;
}
- region_obj->region.handler = handler_obj;
- acpi_ut_add_reference(handler_obj);
+ node = region_obj->region.node->parent;
- return_ACPI_STATUS(AE_OK);
+ /* Find any "_REG" method associated with this region definition */
+
+ status =
+ acpi_ns_search_one_scope(*reg_name_ptr, node, ACPI_TYPE_METHOD,
+ &method_node);
+ if (ACPI_SUCCESS(status)) {
+ /*
+ * The _REG method is optional and there can be only one per region
+ * definition. This will be executed when the handler is attached
+ * or removed
+ */
+ region_obj2->extra.method_REG = method_node;
+ }
+
+ return_VOID;
}
/*******************************************************************************
return_ACPI_STATUS(AE_NOT_EXIST);
}
- if (region_obj2->extra.method_REG == NULL) {
+ if (region_obj2->extra.method_REG == NULL ||
+ region_obj->region.handler == NULL ||
+ !acpi_gbl_reg_methods_enabled) {
+ return_ACPI_STATUS(AE_OK);
+ }
+
+ /* _REG(DISCONNECT) should be paired with _REG(CONNECT) */
+
+ if ((function == ACPI_REG_CONNECT &&
+ region_obj->common.flags & AOPOBJ_REG_CONNECTED) ||
+ (function == ACPI_REG_DISCONNECT &&
+ !(region_obj->common.flags & AOPOBJ_REG_CONNECTED))) {
return_ACPI_STATUS(AE_OK);
}
status = acpi_ns_evaluate(info);
acpi_ut_remove_reference(args[1]);
+ if (ACPI_FAILURE(status)) {
+ goto cleanup2;
+ }
+
+ if (function == ACPI_REG_CONNECT) {
+ region_obj->common.flags |= AOPOBJ_REG_CONNECTED;
+ } else {
+ region_obj->common.flags &= ~AOPOBJ_REG_CONNECTED;
+ }
+
cleanup2:
acpi_ut_remove_reference(args[0]);
*
* PARAMETERS: node - Namespace node for the device
* space_id - The address space ID
+ * function - Passed to _REG: On (1) or Off (0)
*
- * RETURN: Status
+ * RETURN: None
*
* DESCRIPTION: Run all _REG methods for the input Space ID;
* Note: assumes namespace is locked, or system init time.
*
******************************************************************************/
-acpi_status
+void
acpi_ev_execute_reg_methods(struct acpi_namespace_node *node,
- acpi_adr_space_type space_id)
+ acpi_adr_space_type space_id, u32 function)
{
- acpi_status status;
struct acpi_reg_walk_info info;
ACPI_FUNCTION_TRACE(ev_execute_reg_methods);
info.space_id = space_id;
+ info.function = function;
info.reg_run_count = 0;
ACPI_DEBUG_PRINT_RAW((ACPI_DB_NAMES,
* regions and _REG methods. (i.e. handlers must be installed for all
* regions of this Space ID before we can run any _REG methods)
*/
- status = acpi_ns_walk_namespace(ACPI_TYPE_ANY, node, ACPI_UINT32_MAX,
- ACPI_NS_WALK_UNLOCK, acpi_ev_reg_run,
- NULL, &info, NULL);
+ (void)acpi_ns_walk_namespace(ACPI_TYPE_ANY, node, ACPI_UINT32_MAX,
+ ACPI_NS_WALK_UNLOCK, acpi_ev_reg_run, NULL,
+ &info, NULL);
/* Special case for EC: handle "orphan" _REG methods with no region */
info.reg_run_count,
acpi_ut_get_region_name(info.space_id)));
- return_ACPI_STATUS(status);
+ return_VOID;
}
/*******************************************************************************
}
info->reg_run_count++;
- status = acpi_ev_execute_reg_method(obj_desc, ACPI_REG_CONNECT);
+ status = acpi_ev_execute_reg_method(obj_desc, info->function);
return (status);
}
acpi_adr_space_type space_id;
struct acpi_namespace_node *node;
acpi_status status;
- struct acpi_namespace_node *method_node;
- acpi_name *reg_name_ptr = (acpi_name *) METHOD_NAME__REG;
- union acpi_operand_object *region_obj2;
ACPI_FUNCTION_TRACE_U32(ev_initialize_region, acpi_ns_locked);
return_ACPI_STATUS(AE_OK);
}
- region_obj2 = acpi_ns_get_secondary_object(region_obj);
- if (!region_obj2) {
- return_ACPI_STATUS(AE_NOT_EXIST);
- }
+ acpi_ev_associate_reg_method(region_obj);
+ region_obj->common.flags |= AOPOBJ_OBJECT_INITIALIZED;
node = region_obj->region.node->parent;
space_id = region_obj->region.space_id;
- /* Setup defaults */
-
- region_obj->region.handler = NULL;
- region_obj2->extra.method_REG = NULL;
- region_obj->common.flags &= ~(AOPOBJ_SETUP_COMPLETE);
- region_obj->common.flags |= AOPOBJ_OBJECT_INITIALIZED;
-
- /* Find any "_REG" method associated with this region definition */
-
- status =
- acpi_ns_search_one_scope(*reg_name_ptr, node, ACPI_TYPE_METHOD,
- &method_node);
- if (ACPI_SUCCESS(status)) {
- /*
- * The _REG method is optional and there can be only one per region
- * definition. This will be executed when the handler is attached
- * or removed
- */
- region_obj2->extra.method_REG = method_node;
- }
-
/*
* The following loop depends upon the root Node having no parent
- * ie: acpi_gbl_root_node->parent_entry being set to NULL
+ * ie: acpi_gbl_root_node->Parent being set to NULL
*/
while (node) {
switch (node->type) {
case ACPI_TYPE_DEVICE:
-
- handler_obj = obj_desc->device.handler;
- break;
-
case ACPI_TYPE_PROCESSOR:
-
- handler_obj = obj_desc->processor.handler;
- break;
-
case ACPI_TYPE_THERMAL:
- handler_obj = obj_desc->thermal_zone.handler;
+ handler_obj = obj_desc->common_notify.handler;
break;
case ACPI_TYPE_METHOD:
break;
}
- while (handler_obj) {
-
- /* Is this handler of the correct type? */
+ handler_obj =
+ acpi_ev_find_region_handler(space_id, handler_obj);
+ if (handler_obj) {
- if (handler_obj->address_space.space_id ==
- space_id) {
+ /* Found correct handler */
- /* Found correct handler */
+ ACPI_DEBUG_PRINT((ACPI_DB_OPREGION,
+ "Found handler %p for region %p in obj %p\n",
+ handler_obj, region_obj,
+ obj_desc));
- ACPI_DEBUG_PRINT((ACPI_DB_OPREGION,
- "Found handler %p for region %p in obj %p\n",
- handler_obj,
+ status =
+ acpi_ev_attach_region(handler_obj,
region_obj,
- obj_desc));
+ acpi_ns_locked);
+ /*
+ * Tell all users that this region is usable by
+ * running the _REG method
+ */
+ if (acpi_ns_locked) {
status =
- acpi_ev_attach_region(handler_obj,
- region_obj,
- acpi_ns_locked);
-
- /*
- * Tell all users that this region is usable by
- * running the _REG method
- */
- if (acpi_ns_locked) {
- status =
- acpi_ut_release_mutex
- (ACPI_MTX_NAMESPACE);
- if (ACPI_FAILURE(status)) {
- return_ACPI_STATUS
- (status);
- }
+ acpi_ut_release_mutex
+ (ACPI_MTX_NAMESPACE);
+ if (ACPI_FAILURE(status)) {
+ return_ACPI_STATUS(status);
}
+ }
+ status =
+ acpi_ev_execute_reg_method(region_obj,
+ ACPI_REG_CONNECT);
+
+ if (acpi_ns_locked) {
status =
- acpi_ev_execute_reg_method
- (region_obj, ACPI_REG_CONNECT);
-
- if (acpi_ns_locked) {
- status =
- acpi_ut_acquire_mutex
- (ACPI_MTX_NAMESPACE);
- if (ACPI_FAILURE(status)) {
- return_ACPI_STATUS
- (status);
- }
+ acpi_ut_acquire_mutex
+ (ACPI_MTX_NAMESPACE);
+ if (ACPI_FAILURE(status)) {
+ return_ACPI_STATUS(status);
}
-
- return_ACPI_STATUS(AE_OK);
}
- /* Try next handler in the list */
-
- handler_obj = handler_obj->address_space.next;
+ return_ACPI_STATUS(AE_OK);
}
}
ACPI_FUNCTION_TRACE(acpi_install_gpe_handler);
- status =
- acpi_ev_install_gpe_handler(gpe_device, gpe_number, type, FALSE,
- address, context);
+ status = acpi_ev_install_gpe_handler(gpe_device, gpe_number, type,
+ FALSE, address, context);
return_ACPI_STATUS(status);
}
ACPI_FUNCTION_TRACE(acpi_install_gpe_raw_handler);
- status = acpi_ev_install_gpe_handler(gpe_device, gpe_number, type, TRUE,
- address, context);
+ status = acpi_ev_install_gpe_handler(gpe_device, gpe_number, type,
+ TRUE, address, context);
return_ACPI_STATUS(status);
}
goto unlock_and_exit;
}
- /*
- * For the default space_IDs, (the IDs for which there are default region handlers
- * installed) Only execute the _REG methods if the global initialization _REG
- * methods have already been run (via acpi_initialize_objects). In other words,
- * we will defer the execution of the _REG methods for these space_IDs until
- * execution of acpi_initialize_objects. This is done because we need the handlers
- * for the default spaces (mem/io/pci/table) to be installed before we can run
- * any control methods (or _REG methods). There is known BIOS code that depends
- * on this.
- *
- * For all other space_IDs, we can safely execute the _REG methods immediately.
- * This means that for IDs like embedded_controller, this function should be called
- * only after acpi_enable_subsystem has been called.
- */
- switch (space_id) {
- case ACPI_ADR_SPACE_SYSTEM_MEMORY:
- case ACPI_ADR_SPACE_SYSTEM_IO:
- case ACPI_ADR_SPACE_PCI_CONFIG:
- case ACPI_ADR_SPACE_DATA_TABLE:
-
- if (!acpi_gbl_reg_methods_executed) {
-
- /* We will defer execution of the _REG methods for this space */
- goto unlock_and_exit;
- }
- break;
-
- default:
-
- break;
- }
-
/* Run all _REG methods for this address space */
- status = acpi_ev_execute_reg_methods(node, space_id);
+ acpi_ev_execute_reg_methods(node, space_id, ACPI_REG_CONNECT);
unlock_and_exit:
(void)acpi_ut_release_mutex(ACPI_MTX_NAMESPACE);
/* Find the address handler the user requested */
- handler_obj = obj_desc->device.handler;
- last_obj_ptr = &obj_desc->device.handler;
+ handler_obj = obj_desc->common_notify.handler;
+ last_obj_ptr = &obj_desc->common_notify.handler;
while (handler_obj) {
/* We have a handler, see if user requested this one */
}
/*
- * If the Region Address and Length have not been previously evaluated,
- * evaluate them now and save the results.
+ * If the Region Address and Length have not been previously
+ * evaluated, evaluate them now and save the results.
*/
if (!(obj_desc->common.flags & AOPOBJ_DATA_VALID)) {
status = acpi_ds_get_region_arguments(obj_desc);
}
/*
- * Copy the table from the buffer because the buffer could be modified
- * or even deleted in the future
+ * Copy the table from the buffer because the buffer could be
+ * modified or even deleted in the future
*/
table = ACPI_ALLOCATE(length);
if (!table) {
/* Copy the integer to the buffer, LSB first */
new_buf = return_desc->buffer.pointer;
- memcpy(new_buf,
- &obj_desc->integer.value, acpi_gbl_integer_byte_width);
+ memcpy(new_buf, &obj_desc->integer.value,
+ acpi_gbl_integer_byte_width);
break;
case ACPI_TYPE_STRING:
/* Get one hex digit, most significant digits first */
- string[k] =
- (u8) acpi_ut_hex_to_ascii_char(integer,
- ACPI_MUL_4(j));
+ string[k] = (u8)
+ acpi_ut_hex_to_ascii_char(integer, ACPI_MUL_4(j));
k++;
}
break;
/* Attach object to the Node */
- status =
- acpi_ns_attach_object((struct acpi_namespace_node *)walk_state->
- operands[0], obj_desc, ACPI_TYPE_EVENT);
+ status = acpi_ns_attach_object((struct acpi_namespace_node *)
+ walk_state->operands[0], obj_desc,
+ ACPI_TYPE_EVENT);
cleanup:
/*
* Remember location in AML stream of address & length
* operands since they need to be evaluated at run time.
*/
- region_obj2 = obj_desc->common.next_object;
+ region_obj2 = acpi_ns_get_secondary_object(obj_desc);
region_obj2->extra.aml_start = aml_start;
region_obj2->extra.aml_length = aml_length;
+ region_obj2->extra.method_REG = NULL;
if (walk_state->scope_info) {
region_obj2->extra.scope_node =
walk_state->scope_info->scope.node;
obj_desc->region.address = 0;
obj_desc->region.length = 0;
obj_desc->region.node = node;
+ obj_desc->region.handler = NULL;
+ obj_desc->common.flags &=
+ ~(AOPOBJ_SETUP_COMPLETE | AOPOBJ_REG_CONNECTED |
+ AOPOBJ_OBJECT_INITIALIZED);
/* Install the new region object in the parent Node */
* Disassemble the method flags. Split off the arg_count, Serialized
* flag, and sync_level for efficiency.
*/
- method_flags = (u8) operand[1]->integer.value;
-
- obj_desc->method.param_count =
- (u8) (method_flags & AML_METHOD_ARG_COUNT);
+ method_flags = (u8)operand[1]->integer.value;
+ obj_desc->method.param_count = (u8)
+ (method_flags & AML_METHOD_ARG_COUNT);
/*
* Get the sync_level. If method is serialized, a mutex will be
#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
/*******************************************************************************
*
* enabled if necessary.
*
******************************************************************************/
-
void
acpi_ex_do_debug_object(union acpi_operand_object *source_desc,
u32 level, u32 index)
return_VOID;
}
- /*
- * We will emit the current timer value (in microseconds) with each
- * debug output. Only need the lower 26 bits. This allows for 67
- * million microseconds or 67 seconds before rollover.
- */
- timer = ((u32)acpi_os_get_timer() / 10); /* (100 nanoseconds to microseconds) */
- timer &= 0x03FFFFFF;
+ /* Null string or newline -- don't emit the line header */
+
+ if (source_desc &&
+ (ACPI_GET_DESCRIPTOR_TYPE(source_desc) == ACPI_DESC_TYPE_OPERAND) &&
+ (source_desc->common.type == ACPI_TYPE_STRING)) {
+ if ((source_desc->string.length == 0) ||
+ ((source_desc->string.length == 1) &&
+ (*source_desc->string.pointer == '\n'))) {
+ acpi_os_printf("\n");
+ return_VOID;
+ }
+ }
/*
* Print line header as long as we are not in the middle of an
* object display
*/
if (!((level > 0) && index == 0)) {
- acpi_os_printf("[ACPI Debug %.8u] %*s", timer, level, " ");
+ if (acpi_gbl_display_debug_timer) {
+ /*
+ * We will emit the current timer value (in microseconds) with each
+ * debug output. Only need the lower 26 bits. This allows for 67
+ * million microseconds or 67 seconds before rollover.
+ *
+ * Convert 100 nanosecond units to microseconds
+ */
+ timer = ((u32)acpi_os_get_timer() / 10);
+ timer &= 0x03FFFFFF;
+
+ acpi_os_printf("[ACPI Debug T=0x%8.8X] %*s", timer,
+ level, " ");
+ } else {
+ acpi_os_printf("[ACPI Debug] %*s", level, " ");
+ }
}
/* Display the index for package output only */
}
if (ACPI_GET_DESCRIPTOR_TYPE(source_desc) == ACPI_DESC_TYPE_OPERAND) {
- acpi_os_printf("%s ",
- acpi_ut_get_object_type_name(source_desc));
+
+ /* No object type prefix needed for integers and strings */
+
+ if ((source_desc->common.type != ACPI_TYPE_INTEGER) &&
+ (source_desc->common.type != ACPI_TYPE_STRING)) {
+ acpi_os_printf("%s ",
+ acpi_ut_get_object_type_name
+ (source_desc));
+ }
if (!acpi_ut_valid_internal_object(source_desc)) {
acpi_os_printf("%p, Invalid Internal Object!\n",
}
} else if (ACPI_GET_DESCRIPTOR_TYPE(source_desc) ==
ACPI_DESC_TYPE_NAMED) {
- acpi_os_printf("%s: %p\n",
+ acpi_os_printf("%s (Node %p)\n",
acpi_ut_get_type_name(((struct
acpi_namespace_node *)
source_desc)->type),
case ACPI_TYPE_STRING:
- acpi_os_printf("[0x%.2X] \"%s\"\n",
- source_desc->string.length,
- source_desc->string.pointer);
+ acpi_os_printf("\"%s\"\n", source_desc->string.pointer);
break;
case ACPI_TYPE_PACKAGE:
- acpi_os_printf("[Contains 0x%.2X Elements]\n",
+ acpi_os_printf("(Contains 0x%.2X Elements):\n",
source_desc->package.count);
/* Output the entire contents of the package */
if (ACPI_GET_DESCRIPTOR_TYPE
(source_desc->reference.object) ==
ACPI_DESC_TYPE_NAMED) {
- acpi_ex_do_debug_object(((struct
- acpi_namespace_node *)
+
+ /* Reference object is a namespace node */
+
+ acpi_ex_do_debug_object(ACPI_CAST_PTR
+ (union
+ acpi_operand_object,
source_desc->reference.
- object)->object,
- level + 4, 0);
+ object), level + 4, 0);
} else {
object_desc = source_desc->reference.object;
value = source_desc->reference.value;
case ACPI_TYPE_PACKAGE:
acpi_os_printf("Package[%u] = ", value);
- acpi_ex_do_debug_object(*source_desc->
- reference.where,
- level + 4, 0);
+ if (!(*source_desc->reference.where)) {
+ acpi_os_printf
+ ("[Uninitialized Package Element]\n");
+ } else {
+ acpi_ex_do_debug_object
+ (*source_desc->reference.
+ where, level + 4, 0);
+ }
break;
default:
default:
- acpi_os_printf("%p\n", source_desc);
+ acpi_os_printf("(Descriptor %p)\n", source_desc);
break;
}
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);
- }
-}
if (next) {
acpi_os_printf("(%s %2.2X)",
acpi_ut_get_object_type_name
- (next), next->common.type);
+ (next),
+ next->address_space.space_id);
while (next->address_space.next) {
if ((next->common.type ==
acpi_os_printf("->%p(%s %2.2X)", next,
acpi_ut_get_object_type_name
(next),
- next->common.type);
+ next->address_space.
+ space_id);
if ((next == start) || (next == data)) {
acpi_os_printf
|| obj_desc->field.region_obj->region.space_id ==
ACPI_ADR_SPACE_IPMI)) {
/*
- * This is an SMBus, GSBus or IPMI read. We must create a buffer to hold
- * the data and then directly access the region handler.
+ * This is an SMBus, GSBus or IPMI read. We must create a buffer to
+ * hold the data and then directly access the region handler.
*
- * Note: SMBus and GSBus protocol value is passed in upper 16-bits of Function
+ * Note: SMBus and GSBus protocol value is passed in upper 16-bits
+ * of Function
*/
if (obj_desc->field.region_obj->region.space_id ==
ACPI_ADR_SPACE_SMBUS) {
} else if (obj_desc->field.region_obj->region.space_id ==
ACPI_ADR_SPACE_GSBUS) {
accessor_type = obj_desc->field.attribute;
- length = acpi_ex_get_serial_access_length(accessor_type,
- obj_desc->
- field.
- access_length);
+ length =
+ acpi_ex_get_serial_access_length(accessor_type,
+ obj_desc->field.
+ access_length);
/*
* Add additional 2 bytes for the generic_serial_bus data buffer:
*
- * Status; (Byte 0 of the data buffer)
- * Length; (Byte 1 of the data buffer)
- * Data[x-1]; (Bytes 2-x of the arbitrary length data buffer)
+ * Status; (Byte 0 of the data buffer)
+ * Length; (Byte 1 of the data buffer)
+ * Data[x-1]: (Bytes 2-x of the arbitrary length data buffer)
*/
length += 2;
function = ACPI_READ | (accessor_type << 16);
buffer_desc->
buffer.pointer),
function);
+
acpi_ex_release_global_lock(obj_desc->common_field.field_flags);
goto exit;
}
*/
length =
(acpi_size) ACPI_ROUND_BITS_UP_TO_BYTES(obj_desc->field.bit_length);
+
if (length > acpi_gbl_integer_byte_width) {
/* Field is too large for an Integer, create a Buffer instead */
/* Perform the write */
- status = acpi_ex_access_region(obj_desc, 0,
- (u64 *)buffer, ACPI_READ);
+ status =
+ acpi_ex_access_region(obj_desc, 0, (u64 *)buffer,
+ ACPI_READ);
+
acpi_ex_release_global_lock(obj_desc->common_field.field_flags);
if (ACPI_FAILURE(status)) {
acpi_ut_remove_reference(buffer_desc);
|| obj_desc->field.region_obj->region.space_id ==
ACPI_ADR_SPACE_IPMI)) {
/*
- * This is an SMBus, GSBus or IPMI write. We will bypass the entire field
- * mechanism and handoff the buffer directly to the handler. For
- * these address spaces, the buffer is bi-directional; on a write,
- * return data is returned in the same buffer.
+ * This is an SMBus, GSBus or IPMI write. We will bypass the entire
+ * field mechanism and handoff the buffer directly to the handler.
+ * For these address spaces, the buffer is bi-directional; on a
+ * write, return data is returned in the same buffer.
*
* Source must be a buffer of sufficient size:
- * ACPI_SMBUS_BUFFER_SIZE, ACPI_GSBUS_BUFFER_SIZE, or ACPI_IPMI_BUFFER_SIZE.
+ * ACPI_SMBUS_BUFFER_SIZE, ACPI_GSBUS_BUFFER_SIZE, or
+ * ACPI_IPMI_BUFFER_SIZE.
*
- * Note: SMBus and GSBus protocol type is passed in upper 16-bits of Function
+ * Note: SMBus and GSBus protocol type is passed in upper 16-bits
+ * of Function
*/
if (source_desc->common.type != ACPI_TYPE_BUFFER) {
ACPI_ERROR((AE_INFO,
- "SMBus/IPMI/GenericSerialBus write requires Buffer, found type %s",
+ "SMBus/IPMI/GenericSerialBus write requires "
+ "Buffer, found type %s",
acpi_ut_get_object_type_name(source_desc)));
return_ACPI_STATUS(AE_AML_OPERAND_TYPE);
} else if (obj_desc->field.region_obj->region.space_id ==
ACPI_ADR_SPACE_GSBUS) {
accessor_type = obj_desc->field.attribute;
- length = acpi_ex_get_serial_access_length(accessor_type,
- obj_desc->
- field.
- access_length);
+ length =
+ acpi_ex_get_serial_access_length(accessor_type,
+ obj_desc->field.
+ access_length);
/*
* Add additional 2 bytes for the generic_serial_bus data buffer:
*
- * Status; (Byte 0 of the data buffer)
- * Length; (Byte 1 of the data buffer)
- * Data[x-1]; (Bytes 2-x of the arbitrary length data buffer)
+ * Status; (Byte 0 of the data buffer)
+ * Length; (Byte 1 of the data buffer)
+ * Data[x-1]: (Bytes 2-x of the arbitrary length data buffer)
*/
length += 2;
function = ACPI_WRITE | (accessor_type << 16);
if (source_desc->buffer.length < length) {
ACPI_ERROR((AE_INFO,
- "SMBus/IPMI/GenericSerialBus write requires Buffer of length %u, found length %u",
+ "SMBus/IPMI/GenericSerialBus write requires "
+ "Buffer of length %u, found length %u",
length, source_desc->buffer.length));
return_ACPI_STATUS(AE_AML_BUFFER_LIMIT);
* Perform the write (returns status and perhaps data in the
* same buffer)
*/
- status = acpi_ex_access_region(obj_desc, 0,
- (u64 *) buffer, function);
+ status =
+ acpi_ex_access_region(obj_desc, 0, (u64 *)buffer, function);
acpi_ex_release_global_lock(obj_desc->common_field.field_flags);
*result_desc = buffer_desc;
}
ACPI_DEBUG_PRINT((ACPI_DB_BFIELD,
- "GPIO FieldWrite [FROM]: (%s:%X), Val %.8X [TO]: Pin %u Bits %u\n",
+ "GPIO FieldWrite [FROM]: (%s:%X), Val %.8X [TO]: Pin %u Bits %u\n",
acpi_ut_get_type_name(source_desc->common.
type),
source_desc->common.type,
/* Perform the write */
- status = acpi_ex_access_region(obj_desc, 0,
- (u64 *)buffer, ACPI_WRITE);
+ status =
+ acpi_ex_access_region(obj_desc, 0, (u64 *)buffer,
+ ACPI_WRITE);
acpi_ex_release_global_lock(obj_desc->common_field.field_flags);
return_ACPI_STATUS(status);
}
* byte, and a field with Dword access specified.
*/
ACPI_ERROR((AE_INFO,
- "Field [%4.4s] access width (%u bytes) too large for region [%4.4s] (length %u)",
+ "Field [%4.4s] access width (%u bytes) "
+ "too large for region [%4.4s] (length %u)",
acpi_ut_get_node_name(obj_desc->
common_field.node),
obj_desc->common_field.access_byte_width,
* exceeds region length, indicate an error
*/
ACPI_ERROR((AE_INFO,
- "Field [%4.4s] Base+Offset+Width %u+%u+%u is beyond end of region [%4.4s] (length %u)",
+ "Field [%4.4s] Base+Offset+Width %u+%u+%u "
+ "is beyond end of region [%4.4s] (length %u)",
acpi_ut_get_node_name(obj_desc->common_field.node),
obj_desc->common_field.base_byte_offset,
field_datum_byte_offset,
ACPI_ERROR((AE_INFO,
"Unknown UpdateRule value: 0x%X",
- (obj_desc->common_field.
- field_flags &
+ (obj_desc->common_field.field_flags &
AML_FIELD_UPDATE_RULE_MASK)));
return_ACPI_STATUS(AE_AML_OPERAND_VALUE);
}
}
ACPI_DEBUG_PRINT((ACPI_DB_BFIELD,
- "Mask %8.8X%8.8X, DatumOffset %X, Width %X, Value %8.8X%8.8X, MergedValue %8.8X%8.8X\n",
+ "Mask %8.8X%8.8X, DatumOffset %X, Width %X, "
+ "Value %8.8X%8.8X, MergedValue %8.8X%8.8X\n",
ACPI_FORMAT_UINT64(mask),
field_datum_byte_offset,
obj_desc->common_field.access_byte_width,
/* Write the merged value */
- status = acpi_ex_field_datum_io(obj_desc, field_datum_byte_offset,
- &merged_value, ACPI_WRITE);
+ status =
+ acpi_ex_field_datum_io(obj_desc, field_datum_byte_offset,
+ &merged_value, ACPI_WRITE);
return_ACPI_STATUS(status);
}
/* Get next input datum from the field */
field_offset += obj_desc->common_field.access_byte_width;
- status = acpi_ex_field_datum_io(obj_desc, field_offset,
- &raw_datum, ACPI_READ);
+ status =
+ acpi_ex_field_datum_io(obj_desc, field_offset, &raw_datum,
+ ACPI_READ);
if (ACPI_FAILURE(status)) {
return_ACPI_STATUS(status);
}
new_buffer = NULL;
required_length =
ACPI_ROUND_BITS_UP_TO_BYTES(obj_desc->common_field.bit_length);
+
/*
* We must have a buffer that is at least as long as the field
* we are writing to. This is because individual fields are
/* Write merged datum to the target field */
merged_datum &= mask;
- status = acpi_ex_write_with_update_rule(obj_desc, mask,
- merged_datum,
- field_offset);
+ status =
+ acpi_ex_write_with_update_rule(obj_desc, mask, merged_datum,
+ field_offset);
if (ACPI_FAILURE(status)) {
goto exit;
}
/* Write the last datum to the field */
merged_datum &= mask;
- status = acpi_ex_write_with_update_rule(obj_desc,
- mask, merged_datum,
- field_offset);
+ status =
+ acpi_ex_write_with_update_rule(obj_desc, mask, merged_datum,
+ field_offset);
exit:
/* Free temporary buffer if we used one */
default:
- ACPI_ERROR((AE_INFO, "Unknown Reference Class 0x%2.2X",
+ ACPI_ERROR((AE_INFO, "Invalid Reference Class 0x%2.2X",
obj_desc->reference.class));
- return_ACPI_STATUS(AE_AML_INTERNAL);
+ return_ACPI_STATUS(AE_AML_OPERAND_TYPE);
}
break;
union acpi_operand_object *local_operand1 = operand1;
union acpi_operand_object *return_desc;
char *new_buf;
+ const char *type_string;
acpi_status status;
ACPI_FUNCTION_TRACE(ex_do_concatenate);
break;
case ACPI_TYPE_STRING:
+ /*
+ * Per the ACPI spec, Concatenate only supports int/str/buf.
+ * However, we support all objects here as an extension.
+ * This improves the usefulness of the Printf() macro.
+ * 12/2015.
+ */
+ switch (operand1->common.type) {
+ case ACPI_TYPE_INTEGER:
+ case ACPI_TYPE_STRING:
+ case ACPI_TYPE_BUFFER:
+
+ status =
+ acpi_ex_convert_to_string(operand1, &local_operand1,
+ ACPI_IMPLICIT_CONVERT_HEX);
+ break;
+
+ default:
+ /*
+ * Just emit a string containing the object type.
+ */
+ type_string =
+ acpi_ut_get_type_name(operand1->common.type);
+
+ local_operand1 = acpi_ut_create_string_object(((acpi_size) strlen(type_string) + 9)); /* 9 For "[Object]" */
+ if (!local_operand1) {
+ status = AE_NO_MEMORY;
+ goto cleanup;
+ }
- status = acpi_ex_convert_to_string(operand1, &local_operand1,
- ACPI_IMPLICIT_CONVERT_HEX);
+ strcpy(local_operand1->string.pointer, "[");
+ strcat(local_operand1->string.pointer, type_string);
+ strcat(local_operand1->string.pointer, " Object]");
+ status = AE_OK;
+ break;
+ }
break;
case ACPI_TYPE_BUFFER:
/* Concatenate the strings */
strcpy(new_buf, operand0->string.pointer);
- strcpy(new_buf + operand0->string.length,
- local_operand1->string.pointer);
+ strcat(new_buf, local_operand1->string.pointer);
break;
case ACPI_TYPE_BUFFER:
case ACPI_TYPE_STRING:
- status = acpi_ex_convert_to_string(operand1, &local_operand1,
- ACPI_IMPLICIT_CONVERT_HEX);
+ status =
+ acpi_ex_convert_to_string(operand1, &local_operand1,
+ ACPI_IMPLICIT_CONVERT_HEX);
break;
case ACPI_TYPE_BUFFER:
if (obj_desc == acpi_gbl_global_lock_mutex) {
status = acpi_ev_acquire_global_lock(timeout);
} else {
- status = acpi_ex_system_wait_mutex(obj_desc->mutex.os_mutex,
- timeout);
+ status =
+ acpi_ex_system_wait_mutex(obj_desc->mutex.os_mutex,
+ timeout);
}
if (ACPI_FAILURE(status)) {
}
/*
- * Current sync level must be less than or equal to the sync level of the
- * mutex. This mechanism provides some deadlock prevention
+ * Current sync level must be less than or equal to the sync level
+ * of the mutex. This mechanism provides some deadlock prevention.
*/
if (walk_state->thread->current_sync_level > obj_desc->mutex.sync_level) {
ACPI_ERROR((AE_INFO,
- "Cannot acquire Mutex [%4.4s], current SyncLevel is too large (%u)",
+ "Cannot acquire Mutex [%4.4s], "
+ "current SyncLevel is too large (%u)",
acpi_ut_get_node_name(obj_desc->mutex.node),
walk_state->thread->current_sync_level));
return_ACPI_STATUS(AE_AML_MUTEX_ORDER);
}
- status = acpi_ex_acquire_mutex_object((u16) time_desc->integer.value,
+ ACPI_DEBUG_PRINT((ACPI_DB_EXEC,
+ "Acquiring: Mutex SyncLevel %u, Thread SyncLevel %u, "
+ "Depth %u TID %p\n",
+ obj_desc->mutex.sync_level,
+ walk_state->thread->current_sync_level,
+ obj_desc->mutex.acquisition_depth,
+ walk_state->thread));
+
+ status = acpi_ex_acquire_mutex_object((u16)time_desc->integer.value,
obj_desc,
walk_state->thread->thread_id);
+
if (ACPI_SUCCESS(status) && obj_desc->mutex.acquisition_depth == 1) {
/* Save Thread object, original/current sync levels */
acpi_ex_link_mutex(obj_desc, walk_state->thread);
}
+ ACPI_DEBUG_PRINT((ACPI_DB_EXEC,
+ "Acquired: Mutex SyncLevel %u, Thread SyncLevel %u, Depth %u\n",
+ obj_desc->mutex.sync_level,
+ walk_state->thread->current_sync_level,
+ obj_desc->mutex.acquisition_depth));
+
return_ACPI_STATUS(status);
}
acpi_ex_release_mutex(union acpi_operand_object *obj_desc,
struct acpi_walk_state *walk_state)
{
- acpi_status status = AE_OK;
u8 previous_sync_level;
struct acpi_thread_state *owner_thread;
+ acpi_status status = AE_OK;
ACPI_FUNCTION_TRACE(ex_release_mutex);
*/
if (obj_desc->mutex.sync_level != owner_thread->current_sync_level) {
ACPI_ERROR((AE_INFO,
- "Cannot release Mutex [%4.4s], SyncLevel mismatch: mutex %u current %u",
+ "Cannot release Mutex [%4.4s], SyncLevel mismatch: "
+ "mutex %u current %u",
acpi_ut_get_node_name(obj_desc->mutex.node),
obj_desc->mutex.sync_level,
walk_state->thread->current_sync_level));
previous_sync_level =
owner_thread->acquired_mutex_list->mutex.original_sync_level;
+ ACPI_DEBUG_PRINT((ACPI_DB_EXEC,
+ "Releasing: Object SyncLevel %u, Thread SyncLevel %u, "
+ "Prev SyncLevel %u, Depth %u TID %p\n",
+ obj_desc->mutex.sync_level,
+ walk_state->thread->current_sync_level,
+ previous_sync_level,
+ obj_desc->mutex.acquisition_depth,
+ walk_state->thread));
+
status = acpi_ex_release_mutex_object(obj_desc);
if (ACPI_FAILURE(status)) {
return_ACPI_STATUS(status);
owner_thread->current_sync_level = previous_sync_level;
}
+ ACPI_DEBUG_PRINT((ACPI_DB_EXEC,
+ "Released: Object SyncLevel %u, Thread SyncLevel, %u, "
+ "Prev SyncLevel %u, Depth %u\n",
+ obj_desc->mutex.sync_level,
+ walk_state->thread->current_sync_level,
+ previous_sync_level,
+ obj_desc->mutex.acquisition_depth));
+
return_ACPI_STATUS(status);
}
union acpi_operand_object *next = thread->acquired_mutex_list;
union acpi_operand_object *obj_desc;
- ACPI_FUNCTION_NAME(ex_release_all_mutexes);
+ ACPI_FUNCTION_TRACE(ex_release_all_mutexes);
/* Traverse the list of owned mutexes, releasing each one */
while (next) {
obj_desc = next;
- next = obj_desc->mutex.next;
-
- obj_desc->mutex.prev = NULL;
- obj_desc->mutex.next = NULL;
- obj_desc->mutex.acquisition_depth = 0;
-
ACPI_DEBUG_PRINT((ACPI_DB_EXEC,
- "Force-releasing held mutex: %p\n",
- obj_desc));
+ "Mutex [%4.4s] force-release, SyncLevel %u Depth %u\n",
+ obj_desc->mutex.node->name.ascii,
+ obj_desc->mutex.sync_level,
+ obj_desc->mutex.acquisition_depth));
/* Release the mutex, special case for Global Lock */
acpi_os_release_mutex(obj_desc->mutex.os_mutex);
}
- /* Mark mutex unowned */
-
- obj_desc->mutex.owner_thread = NULL;
- obj_desc->mutex.thread_id = 0;
-
/* Update Thread sync_level (Last mutex is the important one) */
thread->current_sync_level =
obj_desc->mutex.original_sync_level;
+
+ /* Mark mutex unowned */
+
+ next = obj_desc->mutex.next;
+
+ obj_desc->mutex.prev = NULL;
+ obj_desc->mutex.next = NULL;
+ obj_desc->mutex.acquisition_depth = 0;
+ obj_desc->mutex.owner_thread = NULL;
+ obj_desc->mutex.thread_id = 0;
}
+
+ return_VOID;
}
ACPI_FUNCTION_TRACE(ex_name_segment);
/*
- * If first character is a digit, then we know that we aren't looking at a
- * valid name segment
+ * If first character is a digit, then we know that we aren't looking
+ * at a valid name segment
*/
char_buf[0] = *aml_address;
case AML_TO_DECSTRING_OP: /* to_decimal_string (Data, Result) */
- status = acpi_ex_convert_to_string(operand[0], &return_desc,
- ACPI_EXPLICIT_CONVERT_DECIMAL);
+ status =
+ acpi_ex_convert_to_string(operand[0], &return_desc,
+ ACPI_EXPLICIT_CONVERT_DECIMAL);
if (return_desc == operand[0]) {
/* No conversion performed, add ref to handle return value */
+
acpi_ut_add_reference(return_desc);
}
break;
case AML_TO_HEXSTRING_OP: /* to_hex_string (Data, Result) */
- status = acpi_ex_convert_to_string(operand[0], &return_desc,
- ACPI_EXPLICIT_CONVERT_HEX);
+ status =
+ acpi_ex_convert_to_string(operand[0], &return_desc,
+ ACPI_EXPLICIT_CONVERT_HEX);
if (return_desc == operand[0]) {
/* No conversion performed, add ref to handle return value */
+
acpi_ut_add_reference(return_desc);
}
break;
if (return_desc == operand[0]) {
/* No conversion performed, add ref to handle return value */
+
acpi_ut_add_reference(return_desc);
}
break;
case AML_TO_INTEGER_OP: /* to_integer (Data, Result) */
- status = acpi_ex_convert_to_integer(operand[0], &return_desc,
- ACPI_ANY_BASE);
+ status =
+ acpi_ex_convert_to_integer(operand[0], &return_desc,
+ ACPI_ANY_BASE);
if (return_desc == operand[0]) {
/* No conversion performed, add ref to handle return value */
+
acpi_ut_add_reference(return_desc);
}
break;
status = acpi_ex_store(return_desc, operand[0], walk_state);
break;
- case AML_TYPE_OP: /* object_type (source_object) */
+ case AML_OBJECT_TYPE_OP: /* object_type (source_object) */
/*
* Note: The operand is not resolved at this point because we want to
* get the associated object, not its value. For example, we don't
/* Get the base object */
- status = acpi_ex_resolve_multiple(walk_state,
- operand[0], &type,
- &temp_desc);
+ status =
+ acpi_ex_resolve_multiple(walk_state, operand[0], &type,
+ &temp_desc);
if (ACPI_FAILURE(status)) {
goto cleanup;
}
default:
ACPI_ERROR((AE_INFO,
- "Operand must be Buffer/Integer/String/Package - found type %s",
+ "Operand must be Buffer/Integer/String/Package"
+ " - found type %s",
acpi_ut_get_type_name(type)));
+
status = AE_AML_OPERAND_TYPE;
goto cleanup;
}
"Unknown Index TargetType 0x%X in reference object %p",
operand[0]->reference.
target_type, operand[0]));
+
status = AE_AML_OPERAND_TYPE;
goto cleanup;
}
ACPI_ERROR((AE_INFO, "Unknown AML opcode 0x%X",
walk_state->opcode));
+
status = AE_AML_BAD_OPCODE;
goto cleanup;
}
ACPI_ERROR((AE_INFO, "Unknown AML opcode 0x%X",
walk_state->opcode));
+
status = AE_AML_BAD_OPCODE;
goto cleanup;
}
case AML_CONCAT_OP: /* Concatenate (Data1, Data2, Result) */
- status = acpi_ex_do_concatenate(operand[0], operand[1],
- &return_desc, walk_state);
+ status =
+ acpi_ex_do_concatenate(operand[0], operand[1], &return_desc,
+ walk_state);
break;
case AML_TO_STRING_OP: /* to_string (Buffer, Length, Result) (ACPI 2.0) */
/* concatenate_res_template (Buffer, Buffer, Result) (ACPI 2.0) */
- status = acpi_ex_concat_template(operand[0], operand[1],
- &return_desc, walk_state);
+ status =
+ acpi_ex_concat_template(operand[0], operand[1],
+ &return_desc, walk_state);
break;
case AML_INDEX_OP: /* Index (Source Index Result) */
ACPI_ERROR((AE_INFO, "Unknown AML opcode 0x%X",
walk_state->opcode));
+
status = AE_AML_BAD_OPCODE;
goto cleanup;
}
case AML_FATAL_OP: /* Fatal (fatal_type fatal_code fatal_arg) */
ACPI_DEBUG_PRINT((ACPI_DB_INFO,
- "FatalOp: Type %X Code %X Arg %X <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<\n",
- (u32) operand[0]->integer.value,
- (u32) operand[1]->integer.value,
- (u32) operand[2]->integer.value));
+ "FatalOp: Type %X Code %X Arg %X "
+ "<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<\n",
+ (u32)operand[0]->integer.value,
+ (u32)operand[1]->integer.value,
+ (u32)operand[2]->integer.value));
fatal = ACPI_ALLOCATE(sizeof(struct acpi_signal_fatal_info));
if (fatal) {
ACPI_ERROR((AE_INFO, "Unknown AML opcode 0x%X",
walk_state->opcode));
+
status = AE_AML_BAD_OPCODE;
goto cleanup;
}
/* Truncate request if larger than the actual String/Buffer */
else if ((index + length) > operand[0]->string.length) {
- length = (acpi_size) operand[0]->string.length -
+ length =
+ (acpi_size) operand[0]->string.length -
(acpi_size) index;
}
/* We have a buffer, copy the portion requested */
- memcpy(buffer, operand[0]->string.pointer + index,
- length);
+ memcpy(buffer,
+ operand[0]->string.pointer + index, length);
}
/* Set the length of the new String/Buffer */
ACPI_ERROR((AE_INFO, "Unknown AML opcode 0x%X",
walk_state->opcode));
+
status = AE_AML_BAD_OPCODE;
goto cleanup;
}
if (ACPI_FAILURE(status) || walk_state->result_obj) {
acpi_ut_remove_reference(return_desc);
walk_state->result_obj = NULL;
- }
+ } else {
+ /* Set the return object and exit */
- /* Set the return object and exit */
-
- else {
walk_state->result_obj = return_desc;
}
+
return_ACPI_STATUS(status);
}
ACPI_ERROR((AE_INFO, "Unknown AML opcode 0x%X",
walk_state->opcode));
+
status = AE_AML_BAD_OPCODE;
goto cleanup;
}
/******************************************************************************
*
- * Module Name: exprep - ACPI AML (p-code) execution - field prep utilities
+ * Module Name: exprep - ACPI AML field prep utilities
*
*****************************************************************************/
/* Round Field start offset and length to "minimal" byte boundaries */
field_byte_offset = ACPI_DIV_8(ACPI_ROUND_DOWN(field_bit_offset, 8));
- field_byte_end_offset = ACPI_DIV_8(ACPI_ROUND_UP(field_bit_length +
- field_bit_offset, 8));
+
+ field_byte_end_offset =
+ ACPI_DIV_8(ACPI_ROUND_UP(field_bit_length + field_bit_offset, 8));
+
field_byte_length = field_byte_end_offset - field_byte_offset;
ACPI_DEBUG_PRINT((ACPI_DB_BFIELD,
if (accesses <= 1) {
ACPI_DEBUG_PRINT((ACPI_DB_BFIELD,
- "Entire field can be accessed with one operation of size %u\n",
+ "Entire field can be accessed "
+ "with one operation of size %u\n",
access_byte_width));
return_VALUE(access_byte_width);
}
*/
ACPI_DEBUG_PRINT((ACPI_DB_BFIELD,
"Cannot access field in one operation, using width 8\n"));
+
return_VALUE(8);
}
#endif /* ACPI_UNDER_DEVELOPMENT */
/* Invalid field access type */
ACPI_ERROR((AE_INFO, "Unknown field access type 0x%X", access));
+
return_UINT32(0);
}
* For all other access types (Byte, Word, Dword, Qword), the Bitwidth is
* the same (equivalent) as the byte_alignment.
*/
- access_bit_width = acpi_ex_decode_field_access(obj_desc, field_flags,
- &byte_alignment);
+ access_bit_width =
+ acpi_ex_decode_field_access(obj_desc, field_flags, &byte_alignment);
if (!access_bit_width) {
return_ACPI_STATUS(AE_AML_OPERAND_VALUE);
}
access_byte_width);
ACPI_DEBUG_PRINT((ACPI_DB_BFIELD,
- "IndexField: BitOff %X, Off %X, Value %X, Gran %X, Index %p, Data %p\n",
+ "IndexField: BitOff %X, Off %X, Value %X, "
+ "Gran %X, Index %p, Data %p\n",
obj_desc->index_field.start_field_bit_offset,
obj_desc->index_field.base_byte_offset,
obj_desc->index_field.value,
* Store the constructed descriptor (obj_desc) into the parent Node,
* preserving the current type of that named_obj.
*/
- status = acpi_ns_attach_object(info->field_node, obj_desc,
- acpi_ns_get_type(info->field_node));
+ status =
+ acpi_ns_attach_object(info->field_node, obj_desc,
+ acpi_ns_get_type(info->field_node));
ACPI_DEBUG_PRINT((ACPI_DB_BFIELD,
"Set NamedObj %p [%4.4s], ObjDesc %p\n",
pci_register = (u16) (u32) address;
ACPI_DEBUG_PRINT((ACPI_DB_INFO,
- "Pci-Config %u (%u) Seg(%04x) Bus(%04x) Dev(%04x) Func(%04x) Reg(%04x)\n",
+ "Pci-Config %u (%u) Seg(%04x) Bus(%04x) "
+ "Dev(%04x) Func(%04x) Reg(%04x)\n",
function, bit_width, pci_id->segment, pci_id->bus,
pci_id->device, pci_id->function, pci_register));
case ACPI_READ:
*value = 0;
- status = acpi_os_read_pci_configuration(pci_id, pci_register,
- value, bit_width);
+ status =
+ acpi_os_read_pci_configuration(pci_id, pci_register, value,
+ bit_width);
break;
case ACPI_WRITE:
- status = acpi_os_write_pci_configuration(pci_id, pci_register,
- *value, bit_width);
+ status =
+ acpi_os_write_pci_configuration(pci_id, pci_register,
+ *value, bit_width);
break;
default:
/*
* Several object types require no further processing:
- * 1) Device/Thermal objects don't have a "real" subobject, return the Node
+ * 1) Device/Thermal objects don't have a "real" subobject, return Node
* 2) Method locals and arguments have a pseudo-Node
* 3) 10/2007: Added method type to assist with Package construction.
*/
* the package, can't dereference it
*/
ACPI_ERROR((AE_INFO,
- "Attempt to dereference an Index to NULL package element Idx=%p",
+ "Attempt to dereference an Index to "
+ "NULL package element Idx=%p",
stack_desc));
status = AE_AML_UNINITIALIZED_ELEMENT;
}
if (type == ACPI_TYPE_LOCAL_ALIAS) {
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((struct
+ acpi_namespace_node
+ *)obj_desc);
}
if (!obj_desc) {
* specification, a store to a constant is a noop.)
*/
if ((this_type == ACPI_TYPE_INTEGER) &&
- (((union acpi_operand_object *)object)->common.
- flags & AOPOBJ_AML_CONSTANT)) {
+ (((union acpi_operand_object *)object)->common.flags &
+ AOPOBJ_AML_CONSTANT)) {
return (AE_OK);
}
}
* thus, the attached object is always the aliased namespace node
*/
if (object_type == ACPI_TYPE_LOCAL_ALIAS) {
- obj_desc =
- acpi_ns_get_attached_object((struct
- acpi_namespace_node
- *)obj_desc);
+ obj_desc = acpi_ns_get_attached_object((struct
+ acpi_namespace_node
+ *)
+ obj_desc);
*stack_ptr = obj_desc;
object_type =
((struct acpi_namespace_node *)obj_desc)->
case ARGI_REF_OR_STRING: /* Can be a String or Reference */
if ((ACPI_GET_DESCRIPTOR_TYPE(obj_desc) ==
- ACPI_DESC_TYPE_OPERAND)
- && (obj_desc->common.type == ACPI_TYPE_STRING)) {
+ ACPI_DESC_TYPE_OPERAND) &&
+ (obj_desc->common.type == ACPI_TYPE_STRING)) {
/*
* String found - the string references a named object and
* must be resolved to a node
* But we can implicitly convert from a BUFFER or INTEGER
* aka - "Implicit Source Operand Conversion"
*/
- status = acpi_ex_convert_to_string(obj_desc, stack_ptr,
- ACPI_IMPLICIT_CONVERT_HEX);
+ status =
+ acpi_ex_convert_to_string(obj_desc, stack_ptr,
+ ACPI_IMPLICIT_CONVERT_HEX);
if (ACPI_FAILURE(status)) {
if (status == AE_TYPE) {
ACPI_ERROR((AE_INFO,
case ARGI_REGION_OR_BUFFER: /* Used by Load() only */
- /* Need an operand of type REGION or a BUFFER (which could be a resolved region field) */
-
+ /*
+ * Need an operand of type REGION or a BUFFER
+ * (which could be a resolved region field)
+ */
switch (obj_desc->common.type) {
case ACPI_TYPE_BUFFER:
case ACPI_TYPE_REGION:
if (acpi_gbl_enable_interpreter_slack) {
/*
- * Enable original behavior of Store(), allowing any and all
- * objects as the source operand. The ACPI spec does not
- * allow this, however.
+ * Enable original behavior of Store(), allowing any
+ * and all objects as the source operand. The ACPI
+ * spec does not allow this, however.
*/
break;
}
}
ACPI_ERROR((AE_INFO,
- "Needed Integer/Buffer/String/Package/Ref/Ddb], found [%s] %p",
+ "Needed Integer/Buffer/String/Package/Ref/Ddb]"
+ ", found [%s] %p",
acpi_ut_get_object_type_name
(obj_desc), obj_desc));
* Make sure that the original object was resolved to the
* required object type (Simple cases only).
*/
- status = acpi_ex_check_object_type(type_needed,
- (*stack_ptr)->common.type,
- *stack_ptr);
+ status =
+ acpi_ex_check_object_type(type_needed,
+ (*stack_ptr)->common.type,
+ *stack_ptr);
if (ACPI_FAILURE(status)) {
return_ACPI_STATUS(status);
}
case ACPI_TYPE_THERMAL:
ACPI_ERROR((AE_INFO,
- "Target must be [Buffer/Integer/String/Reference], found [%s] (%4.4s)",
+ "Target must be [Buffer/Integer/String/Reference]"
+ ", found [%s] (%4.4s)",
acpi_ut_get_type_name(node->type),
node->name.ascii));
* an implicit conversion, as per the ACPI specification.
* A direct store is performed instead.
*/
- status = acpi_ex_store_direct_to_node(source_desc, node,
- walk_state);
+ status =
+ acpi_ex_store_direct_to_node(source_desc, node,
+ walk_state);
break;
}
* store has been performed such that the node/object type
* has been changed.
*/
- status = acpi_ns_attach_object(node, new_desc,
- new_desc->common.type);
+ status =
+ acpi_ns_attach_object(node, new_desc,
+ new_desc->common.type);
ACPI_DEBUG_PRINT((ACPI_DB_EXEC,
"Store type [%s] into [%s] via Convert/Attach\n",
* operator. (Note, for this default case, all normal
* Store/Target operations exited above with an error).
*/
- status = acpi_ex_store_direct_to_node(source_desc, node,
- walk_state);
+ status =
+ acpi_ex_store_direct_to_node(source_desc, node, walk_state);
break;
}
/******************************************************************************
*
- * Module Name: exstorob - AML Interpreter object store support, store to object
+ * Module Name: exstorob - AML object store support, store to object
*
*****************************************************************************/
ACPI_FREE(target_desc->string.pointer);
}
- target_desc->string.pointer = ACPI_ALLOCATE_ZEROED((acpi_size)
- length + 1);
+ target_desc->string.pointer =
+ ACPI_ALLOCATE_ZEROED((acpi_size) length + 1);
+
if (!target_desc->string.pointer) {
return_ACPI_STATUS(AE_NO_MEMORY);
}
/* We must wait, so unlock the interpreter */
acpi_ex_exit_interpreter();
-
status = acpi_os_wait_semaphore(semaphore, 1, timeout);
ACPI_DEBUG_PRINT((ACPI_DB_EXEC,
/* We must wait, so unlock the interpreter */
acpi_ex_exit_interpreter();
-
status = acpi_os_acquire_mutex(mutex, timeout);
ACPI_DEBUG_PRINT((ACPI_DB_EXEC,
* (ACPI specifies 100 usec as max, but this gives some slack in
* order to support existing BIOSs)
*/
- ACPI_ERROR((AE_INFO, "Time parameter is too large (%u)",
- how_long));
+ ACPI_ERROR((AE_INFO,
+ "Time parameter is too large (%u)", how_long));
status = AE_AML_OPERAND_VALUE;
} else {
acpi_os_stall(how_long);
--- /dev/null
+/******************************************************************************
+ *
+ * Module Name: extrace - Support for interpreter execution tracing
+ *
+ *****************************************************************************/
+
+/*
+ * 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 "acnamesp.h"
+#include "acinterp.h"
+
+#define _COMPONENT ACPI_EXECUTER
+ACPI_MODULE_NAME("extrace")
+
+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
+
+/*******************************************************************************
+ *
+ * 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);
+ }
+}
if ((acpi_gbl_integer_byte_width == 4) &&
(obj_desc->integer.value > (u64)ACPI_UINT32_MAX)) {
/*
- * We are executing in a 32-bit ACPI table.
- * Truncate the value to 32 bits by zeroing out the upper 32-bit field
+ * We are executing in a 32-bit ACPI table. Truncate
+ * the value to 32 bits by zeroing out the upper 32-bit field
*/
obj_desc->integer.value &= (u64)ACPI_UINT32_MAX;
return (TRUE);
if (compressed_id > ACPI_UINT32_MAX) {
ACPI_WARNING((AE_INFO,
- "Expected EISAID is larger than 32 bits: 0x%8.8X%8.8X, truncating",
+ "Expected EISAID is larger than 32 bits: "
+ "0x%8.8X%8.8X, truncating",
ACPI_FORMAT_UINT64(compressed_id)));
}
/* Clear wake status (WAK_STS) */
- status =
- acpi_write((u64)ACPI_X_WAKE_STATUS, &acpi_gbl_FADT.sleep_status);
+ status = acpi_write((u64)ACPI_X_WAKE_STATUS,
+ &acpi_gbl_FADT.sleep_status);
if (ACPI_FAILURE(status)) {
return_ACPI_STATUS(status);
}
*/
register_bit = acpi_hw_get_gpe_register_bit(gpe_event_info);
- status = acpi_hw_write(register_bit,
- &gpe_register_info->status_address);
-
+ status =
+ acpi_hw_write(register_bit, &gpe_register_info->status_address);
return (status);
}
acpi_status status;
gpe_register_info->enable_mask = enable_mask;
+
status = acpi_hw_write(enable_mask, &gpe_register_info->enable_address);
return (status);
}
/* Clear wake status */
- status =
- acpi_write_bit_register(ACPI_BITREG_WAKE_STATUS, ACPI_CLEAR_STATUS);
+ status = acpi_write_bit_register(ACPI_BITREG_WAKE_STATUS,
+ ACPI_CLEAR_STATUS);
if (ACPI_FAILURE(status)) {
return_ACPI_STATUS(status);
}
* Evaluate the \_Sx namespace object containing the register values
* for this state
*/
- info->relative_pathname =
- ACPI_CAST_PTR(char, acpi_gbl_sleep_state_names[sleep_state]);
+ info->relative_pathname = ACPI_CAST_PTR(char,
+ acpi_gbl_sleep_state_names
+ [sleep_state]);
+
status = acpi_ns_evaluate(info);
if (ACPI_FAILURE(status)) {
- goto cleanup;
+ if (status == AE_NOT_FOUND) {
+
+ /* The _Sx states are optional, ignore NOT_FOUND */
+
+ goto final_cleanup;
+ }
+
+ goto warning_cleanup;
}
/* Must have a return object */
ACPI_ERROR((AE_INFO, "No Sleep State object returned from [%s]",
info->relative_pathname));
status = AE_AML_NO_RETURN_VALUE;
- goto cleanup;
+ goto warning_cleanup;
}
/* Return object must be of type Package */
ACPI_ERROR((AE_INFO,
"Sleep State return object is not a Package"));
status = AE_AML_OPERAND_TYPE;
- goto cleanup1;
+ goto return_value_cleanup;
}
/*
break;
}
-cleanup1:
+return_value_cleanup:
acpi_ut_remove_reference(info->return_object);
-cleanup:
+warning_cleanup:
if (ACPI_FAILURE(status)) {
ACPI_EXCEPTION((AE_INFO, status,
"While evaluating Sleep State [%s]",
info->relative_pathname));
}
+final_cleanup:
ACPI_FREE(info);
return_ACPI_STATUS(status);
}
/* Local prototypes */
#if (!ACPI_REDUCED_HARDWARE)
static acpi_status
-acpi_hw_set_firmware_waking_vectors(struct acpi_table_facs *facs,
- acpi_physical_address physical_address,
- acpi_physical_address physical_address64);
+acpi_hw_set_firmware_waking_vector(struct acpi_table_facs *facs,
+ acpi_physical_address physical_address,
+ acpi_physical_address physical_address64);
#endif
static acpi_status acpi_hw_sleep_dispatch(u8 sleep_state, u32 function_id);
/*
* These functions are removed for the ACPI_REDUCED_HARDWARE case:
- * acpi_set_firmware_waking_vectors
* acpi_set_firmware_waking_vector
- * acpi_set_firmware_waking_vector64
* acpi_enter_sleep_state_s4bios
*/
#if (!ACPI_REDUCED_HARDWARE)
/*******************************************************************************
*
- * FUNCTION: acpi_hw_set_firmware_waking_vectors
+ * FUNCTION: acpi_hw_set_firmware_waking_vector
*
* PARAMETERS: facs - Pointer to FACS table
* physical_address - 32-bit physical address of ACPI real mode
- * entry point.
+ * entry point
* physical_address64 - 64-bit physical address of ACPI protected
- * mode entry point.
+ * mode entry point
*
* RETURN: Status
*
******************************************************************************/
static acpi_status
-acpi_hw_set_firmware_waking_vectors(struct acpi_table_facs *facs,
- acpi_physical_address physical_address,
- acpi_physical_address physical_address64)
+acpi_hw_set_firmware_waking_vector(struct acpi_table_facs *facs,
+ acpi_physical_address physical_address,
+ acpi_physical_address physical_address64)
{
- ACPI_FUNCTION_TRACE(acpi_hw_set_firmware_waking_vectors);
+ ACPI_FUNCTION_TRACE(acpi_hw_set_firmware_waking_vector);
/*
/*******************************************************************************
*
- * FUNCTION: acpi_set_firmware_waking_vectors
+ * FUNCTION: acpi_set_firmware_waking_vector
*
* PARAMETERS: physical_address - 32-bit physical address of ACPI real mode
- * entry point.
+ * entry point
* physical_address64 - 64-bit physical address of ACPI protected
- * mode entry point.
+ * mode entry point
*
* RETURN: Status
*
******************************************************************************/
acpi_status
-acpi_set_firmware_waking_vectors(acpi_physical_address physical_address,
- acpi_physical_address physical_address64)
+acpi_set_firmware_waking_vector(acpi_physical_address physical_address,
+ acpi_physical_address physical_address64)
{
- ACPI_FUNCTION_TRACE(acpi_set_firmware_waking_vectors);
+ ACPI_FUNCTION_TRACE(acpi_set_firmware_waking_vector);
if (acpi_gbl_FACS) {
- (void)acpi_hw_set_firmware_waking_vectors(acpi_gbl_FACS,
- physical_address,
- physical_address64);
+ (void)acpi_hw_set_firmware_waking_vector(acpi_gbl_FACS,
+ physical_address,
+ physical_address64);
}
return_ACPI_STATUS(AE_OK);
}
-ACPI_EXPORT_SYMBOL(acpi_set_firmware_waking_vectors)
-
-/*******************************************************************************
- *
- * FUNCTION: acpi_set_firmware_waking_vector
- *
- * PARAMETERS: physical_address - 32-bit physical address of ACPI real mode
- * entry point.
- *
- * RETURN: Status
- *
- * DESCRIPTION: Sets the 32-bit firmware_waking_vector field of the FACS
- *
- ******************************************************************************/
-acpi_status acpi_set_firmware_waking_vector(u32 physical_address)
-{
- acpi_status status;
-
- ACPI_FUNCTION_TRACE(acpi_set_firmware_waking_vector);
-
- status = acpi_set_firmware_waking_vectors((acpi_physical_address)
- physical_address, 0);
-
- return_ACPI_STATUS(status);
-}
-
ACPI_EXPORT_SYMBOL(acpi_set_firmware_waking_vector)
-#if ACPI_MACHINE_WIDTH == 64
-/*******************************************************************************
- *
- * FUNCTION: acpi_set_firmware_waking_vector64
- *
- * PARAMETERS: physical_address - 64-bit physical address of ACPI protected
- * mode entry point.
- *
- * RETURN: Status
- *
- * DESCRIPTION: Sets the 64-bit X_firmware_waking_vector field of the FACS, if
- * it exists in the table. This function is intended for use with
- * 64-bit host operating systems.
- *
- ******************************************************************************/
-acpi_status acpi_set_firmware_waking_vector64(u64 physical_address)
-{
- acpi_status status;
-
- ACPI_FUNCTION_TRACE(acpi_set_firmware_waking_vector64);
-
- status = acpi_set_firmware_waking_vectors(0,
- (acpi_physical_address)
- physical_address);
-
- return_ACPI_STATUS(status);
-}
-
-ACPI_EXPORT_SYMBOL(acpi_set_firmware_waking_vector64)
-#endif
/*******************************************************************************
*
* FUNCTION: acpi_enter_sleep_state_s4bios
if (ACPI_FAILURE(status)) {
return_ACPI_STATUS(status);
}
+
} while (!in_value);
return_ACPI_STATUS(AE_OK);
/* Extract each buffer byte to create the integer */
for (i = 0; i < original_object->buffer.length; i++) {
- value |=
- ((u64)original_object->buffer.
- pointer[i] << (i * 8));
+ value |= ((u64)
+ original_object->buffer.pointer[i] << (i *
+ 8));
}
break;
return (AE_NO_MEMORY);
}
} else {
- status =
- acpi_ex_convert_to_string(original_object,
- &new_object,
- ACPI_IMPLICIT_CONVERT_HEX);
+ status = acpi_ex_convert_to_string(original_object,
+ &new_object,
+ ACPI_IMPLICIT_CONVERT_HEX);
if (ACPI_FAILURE(status)) {
return (status);
}
/* String-to-Buffer conversion. Simple data copy */
- new_object =
- acpi_ut_create_buffer_object(original_object->string.
- length);
+ new_object = acpi_ut_create_buffer_object
+ (original_object->string.length);
if (!new_object) {
return (AE_NO_MEMORY);
}
*
* FUNCTION: acpi_ns_convert_to_unicode
*
- * PARAMETERS: original_object - ASCII String Object to be converted
+ * PARAMETERS: scope - Namespace node for the method/object
+ * original_object - ASCII String Object to be converted
* return_object - Where the new converted object is returned
*
* RETURN: Status. AE_OK if conversion was successful.
******************************************************************************/
acpi_status
-acpi_ns_convert_to_unicode(union acpi_operand_object *original_object,
+acpi_ns_convert_to_unicode(struct acpi_namespace_node * scope,
+ union acpi_operand_object *original_object,
union acpi_operand_object **return_object)
{
union acpi_operand_object *new_object;
*
* FUNCTION: acpi_ns_convert_to_resource
*
- * PARAMETERS: original_object - Object to be converted
+ * PARAMETERS: scope - Namespace node for the method/object
+ * original_object - Object to be converted
* return_object - Where the new converted object is returned
*
* RETURN: Status. AE_OK if conversion was successful
******************************************************************************/
acpi_status
-acpi_ns_convert_to_resource(union acpi_operand_object *original_object,
+acpi_ns_convert_to_resource(struct acpi_namespace_node * scope,
+ union acpi_operand_object *original_object,
union acpi_operand_object **return_object)
{
union acpi_operand_object *new_object;
*return_object = new_object;
return (AE_OK);
}
+
+/*******************************************************************************
+ *
+ * FUNCTION: acpi_ns_convert_to_reference
+ *
+ * PARAMETERS: scope - Namespace node for the method/object
+ * original_object - Object to be converted
+ * return_object - Where the new converted object is returned
+ *
+ * RETURN: Status. AE_OK if conversion was successful
+ *
+ * DESCRIPTION: Attempt to convert a Integer object to a object_reference.
+ * Buffer.
+ *
+ ******************************************************************************/
+
+acpi_status
+acpi_ns_convert_to_reference(struct acpi_namespace_node * scope,
+ union acpi_operand_object *original_object,
+ union acpi_operand_object **return_object)
+{
+ union acpi_operand_object *new_object = NULL;
+ acpi_status status;
+ struct acpi_namespace_node *node;
+ union acpi_generic_state scope_info;
+ char *name;
+
+ ACPI_FUNCTION_NAME(ns_convert_to_reference);
+
+ /* Convert path into internal presentation */
+
+ status =
+ acpi_ns_internalize_name(original_object->string.pointer, &name);
+ if (ACPI_FAILURE(status)) {
+ return_ACPI_STATUS(status);
+ }
+
+ /* Find the namespace node */
+
+ scope_info.scope.node =
+ ACPI_CAST_PTR(struct acpi_namespace_node, scope);
+ status =
+ acpi_ns_lookup(&scope_info, name, ACPI_TYPE_ANY, ACPI_IMODE_EXECUTE,
+ ACPI_NS_SEARCH_PARENT | ACPI_NS_DONT_OPEN_SCOPE,
+ NULL, &node);
+ if (ACPI_FAILURE(status)) {
+
+ /* Check if we are resolving a named reference within a package */
+
+ ACPI_ERROR_NAMESPACE(original_object->string.pointer, status);
+ goto error_exit;
+ }
+
+ /* Create and init a new internal ACPI object */
+
+ new_object = acpi_ut_create_internal_object(ACPI_TYPE_LOCAL_REFERENCE);
+ if (!new_object) {
+ status = AE_NO_MEMORY;
+ goto error_exit;
+ }
+ new_object->reference.node = node;
+ new_object->reference.object = node->object;
+ new_object->reference.class = ACPI_REFCLASS_NAME;
+
+ /*
+ * Increase reference of the object if needed (the object is likely a
+ * null for device nodes).
+ */
+ acpi_ut_add_reference(node->object);
+
+error_exit:
+ ACPI_FREE(name);
+ *return_object = new_object;
+ return (AE_OK);
+}
acpi_os_printf
("(Pointer to ACPI Object type %.2X [UNKNOWN])\n",
obj_type);
+
bytes_to_dump = 32;
} else {
acpi_os_printf
("(Pointer to ACPI Object type %.2X [%s])\n",
obj_type, acpi_ut_get_type_name(obj_type));
+
bytes_to_dump =
sizeof(union acpi_operand_object);
}
*/
bytes_to_dump = obj_desc->string.length;
obj_desc = (void *)obj_desc->string.pointer;
+
acpi_os_printf("(Buffer/String pointer %p length %X)\n",
obj_desc, bytes_to_dump);
ACPI_DUMP_BUFFER(obj_desc, bytes_to_dump);
return (AE_OK);
}
- pathname = acpi_ns_get_external_pathname(node);
+ pathname = acpi_ns_get_normalized_pathname(node, TRUE);
path_indent = 1;
if (level <= max_level) {
/* Get the full pathname to the object, for use in warning messages */
- info->full_pathname = acpi_ns_get_external_pathname(info->node);
+ info->full_pathname = acpi_ns_get_normalized_pathname(info->node, TRUE);
if (!info->full_pathname) {
return_ACPI_STATUS(AE_NO_MEMORY);
}
/* Ignore error and move on to next device */
- char *scope_name = acpi_ns_get_external_pathname(info->node);
+ char *scope_name =
+ acpi_ns_get_normalized_pathname(device_node, TRUE);
ACPI_EXCEPTION((AE_INFO, status, "during %s._INI execution",
scope_name));
ACPI_DEBUG_PRINT((ACPI_DB_INFO,
"**** Completed Table Object Initialization\n"));
+ /*
+ * Execute any module-level code that was detected during the table load
+ * phase. Although illegal since ACPI 2.0, there are many machines that
+ * contain this type of code. Each block of detected executable AML code
+ * outside of any control method is wrapped with a temporary control
+ * method object and placed on a global list. The methods on this list
+ * are executed below.
+ *
+ * This case executes the module-level code for each table immediately
+ * after the table has been loaded. This provides compatibility with
+ * other ACPI implementations. Optionally, the execution can be deferred
+ * until later, see acpi_initialize_objects.
+ */
+ if (!acpi_gbl_group_module_level_code) {
+ acpi_ns_exec_module_code_list();
+ }
+
return_ACPI_STATUS(status);
}
/* This function does the real work */
status = acpi_ns_delete_subtree(handle);
-
return_ACPI_STATUS(status);
}
#endif
ACPI_FUNCTION_TRACE_PTR(ns_get_external_pathname, node);
name_buffer = acpi_ns_get_normalized_pathname(node, FALSE);
-
return_PTR(name_buffer);
}
ACPI_FUNCTION_ENTRY();
size = acpi_ns_build_normalized_path(node, NULL, 0, FALSE);
-
return (size);
}
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++) {
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;
/* Parse the AML */
- ACPI_DEBUG_PRINT((ACPI_DB_PARSE, "*PARSE* pass %u parse\n",
- pass_number));
+ ACPI_DEBUG_PRINT((ACPI_DB_PARSE,
+ "*PARSE* pass %u parse\n", pass_number));
status = acpi_ps_parse_aml(walk_state);
cleanup:
* performs another complete parse of the AML.
*/
ACPI_DEBUG_PRINT((ACPI_DB_PARSE, "**** Start pass 1\n"));
+
status = acpi_ns_one_complete_parse(ACPI_IMODE_LOAD_PASS1,
table_index, start_node);
if (ACPI_FAILURE(status)) {
/* First element is the (Integer) revision */
- status = acpi_ns_check_object_type(info, elements,
- ACPI_RTYPE_INTEGER, 0);
+ status =
+ acpi_ns_check_object_type(info, elements,
+ ACPI_RTYPE_INTEGER, 0);
if (ACPI_FAILURE(status)) {
return (status);
}
/* First element is the (Integer) count of subpackages to follow */
- status = acpi_ns_check_object_type(info, elements,
- ACPI_RTYPE_INTEGER, 0);
+ status =
+ acpi_ns_check_object_type(info, elements,
+ ACPI_RTYPE_INTEGER, 0);
if (ACPI_FAILURE(status)) {
return (status);
}
ACPI_NOT_PACKAGE_ELEMENT,
acpi_ns_convert_to_resource},
+ /* Object reference conversions */
+
+ {"_DEP", ACPI_RTYPE_STRING, ACPI_ALL_PACKAGE_ELEMENTS,
+ acpi_ns_convert_to_reference},
+
/* Unicode conversions */
{"_MLS", ACPI_RTYPE_STRING, 1,
"Missing expected return value"));
}
- status =
- predefined->object_converter(return_object, &new_object);
+ status = predefined->object_converter(info->node, return_object,
+ &new_object);
if (ACPI_FAILURE(status)) {
/* A fatal error occurred during a conversion */
/* Check if we can actually repair this name/type combination */
if ((return_btype & this_name->unexpected_btypes) &&
- (package_index == this_name->package_index)) {
+ (this_name->package_index ==
+ ACPI_ALL_PACKAGE_ELEMENTS
+ || package_index == this_name->package_index)) {
return (this_name);
}
return (NULL);
}
+
this_name++;
}
*dest = *source;
dest++;
}
+
source++;
}
ACPI_FUNCTION_NAME(ns_wrap_with_package);
/*
- * Create the new outer package and populate it. The new package will
- * have a single element, the lone sub-object.
+ * Create the new outer package and populate it. The new
+ * package will have a single element, the lone sub-object.
*/
pkg_obj_desc = acpi_ut_create_package_object(1);
if (!pkg_obj_desc) {
if (ACPI_COMPARE_NAME(node->name.ascii, this_name->name)) {
return (this_name);
}
+
this_name++;
}
/* We can only repair if we have exactly 5 BYTEs */
if (return_object->buffer.length != ACPI_FDE_BYTE_BUFFER_SIZE) {
- ACPI_WARN_PREDEFINED((AE_INFO, info->full_pathname,
+ ACPI_WARN_PREDEFINED((AE_INFO,
+ info->full_pathname,
info->node_flags,
"Incorrect return buffer length %u, expected %u",
return_object->buffer.length,
/* Expand each byte to a DWORD */
byte_buffer = return_object->buffer.pointer;
- dword_buffer =
- ACPI_CAST_PTR(u32, buffer_object->buffer.pointer);
+ dword_buffer = ACPI_CAST_PTR(u32,
+ buffer_object->buffer.pointer);
for (i = 0; i < ACPI_FDE_FIELD_COUNT; i++) {
*dword_buffer = (u32) *byte_buffer;
removing = FALSE;
if ((*outer_elements)->package.count == 0) {
- ACPI_WARN_PREDEFINED((AE_INFO, info->full_pathname,
+ ACPI_WARN_PREDEFINED((AE_INFO,
+ info->full_pathname,
info->node_flags,
"SubPackage[%u] - removing entry due to zero count",
i));
obj_desc = (*outer_elements)->package.elements[1]; /* Index1 = Type */
if ((u32)obj_desc->integer.value == 0) {
- ACPI_WARN_PREDEFINED((AE_INFO, info->full_pathname,
+ ACPI_WARN_PREDEFINED((AE_INFO,
+ info->full_pathname,
info->node_flags,
"SubPackage[%u] - removing entry due to invalid Type(0)",
i));
}
if (return_object->string.length == 0) {
- ACPI_WARN_PREDEFINED((AE_INFO, info->full_pathname,
- info->node_flags,
+ ACPI_WARN_PREDEFINED((AE_INFO,
+ info->full_pathname, info->node_flags,
"Invalid zero-length _HID or _CID string"));
/* Return AE_OK anyway, let driver handle it */
elements = (*outer_elements)->package.elements;
obj_desc = elements[1]; /* Index1 = power_dissipation */
- if ((u32) obj_desc->integer.value > previous_value) {
- ACPI_WARN_PREDEFINED((AE_INFO, info->full_pathname,
+ if ((u32)obj_desc->integer.value > previous_value) {
+ ACPI_WARN_PREDEFINED((AE_INFO,
+ info->full_pathname,
info->node_flags,
"SubPackage[%u,%u] - suspicious power dissipation values",
i - 1, i));
*dest = *source;
dest++;
}
+
source++;
}
if (ACPI_LV_NAMES & acpi_dbg_level) {
char *scope_name;
- scope_name = acpi_ns_get_external_pathname(parent_node);
+ scope_name = acpi_ns_get_normalized_pathname(parent_node, TRUE);
if (scope_name) {
ACPI_DEBUG_PRINT((ACPI_DB_NAMES,
"Searching %s (%p) For [%4.4s] (%s)\n",
info->fully_qualified = FALSE;
/*
- * For the internal name, the required length is 4 bytes per segment, plus
- * 1 each for root_prefix, multi_name_prefix_op, segment count, trailing null
- * (which is not really needed, but no there's harm in putting it there)
+ * For the internal name, the required length is 4 bytes per segment,
+ * plus 1 each for root_prefix, multi_name_prefix_op, segment count,
+ * trailing null (which is not really needed, but no there's harm in
+ * putting it there)
*
* strlen() + 1 covers the first name_seg, which has no path separator
*/
if (!prefix_node) {
*return_node = acpi_gbl_root_node;
}
+
return_ACPI_STATUS(AE_OK);
}
/* We have a valid device, invoke the user function */
- status = info->user_function(obj_handle, nesting_level, info->context,
- return_value);
+ status = info->user_function(obj_handle, nesting_level,
+ info->context, return_value);
return (status);
}
{
acpi_status status;
struct acpi_namespace_node *node;
- char *node_name;
+ const char *node_name;
/* Parameter validation */
struct acpi_pnp_device_id *source,
char *string_area)
{
-
/* Create the destination PNP_DEVICE_ID */
dest->string = string_area;
* namespace node and possibly by running several standard
* control methods (Such as in the case of a device.)
*
- * For Device and Processor objects, run the Device _HID, _UID, _CID, _SUB,
- * _CLS, _STA, _ADR, _sx_w, and _sx_d methods.
+ * For Device and Processor objects, run the Device _HID, _UID, _CID, _STA,
+ * _CLS, _ADR, _sx_w, and _sx_d methods.
*
* Note: Allocates the return buffer, must be freed by the caller.
*
+ * Note: This interface is intended to be used during the initial device
+ * discovery namespace traversal. Therefore, no complex methods can be
+ * executed, especially those that access operation regions. Therefore, do
+ * not add any additional methods that could cause problems in this area.
+ * this was the fate of the _SUB method which was found to cause such
+ * problems and was removed (11/2015).
+ *
******************************************************************************/
acpi_status
struct acpi_pnp_device_id_list *cid_list = NULL;
struct acpi_pnp_device_id *hid = NULL;
struct acpi_pnp_device_id *uid = NULL;
- struct acpi_pnp_device_id *sub = NULL;
struct acpi_pnp_device_id *cls = NULL;
char *next_id_string;
acpi_object_type type;
if ((type == ACPI_TYPE_DEVICE) || (type == ACPI_TYPE_PROCESSOR)) {
/*
* Get extra info for ACPI Device/Processor objects only:
- * Run the Device _HID, _UID, _SUB, _CID, and _CLS methods.
+ * Run the Device _HID, _UID, _CLS, and _CID methods.
*
* Note: none of these methods are required, so they may or may
* not be present for this device. The Info->Valid bitfield is used
valid |= ACPI_VALID_UID;
}
- /* Execute the Device._SUB method */
-
- status = acpi_ut_execute_SUB(node, &sub);
- if (ACPI_SUCCESS(status)) {
- info_size += sub->length;
- valid |= ACPI_VALID_SUB;
- }
-
/* Execute the Device._CID method */
status = acpi_ut_execute_CID(node, &cid_list);
}
/*
- * Copy the HID, UID, SUB, and CIDs to the return buffer.
- * The variable-length strings are copied to the reserved area
- * at the end of the buffer.
+ * Copy the HID, UID, and CIDs to the return buffer. The variable-length
+ * strings are copied to the reserved area at the end of the buffer.
*
* For HID and CID, check if the ID is a PCI Root Bridge.
*/
uid, next_id_string);
}
- if (sub) {
- next_id_string = acpi_ns_copy_device_id(&info->subsystem_id,
- sub, next_id_string);
- }
-
if (cid_list) {
info->compatible_id_list.count = cid_list->count;
info->compatible_id_list.list_size = cid_list->list_size;
if (uid) {
ACPI_FREE(uid);
}
- if (sub) {
- ACPI_FREE(sub);
- }
if (cid_list) {
ACPI_FREE(cid_list);
}
parser_state.aml += acpi_ps_get_opcode_size(opcode);
parser_state.pkg_end = acpi_ps_get_next_package_end(&parser_state);
path = acpi_ps_get_next_namestring(&parser_state);
+
method_flags = *parser_state.aml++;
aml_start = parser_state.aml;
aml_length = ACPI_PTR_DIFF(parser_state.pkg_end, aml_start);
return (AE_BAD_PARAMETER);
}
- /*
- * Special case for the predefined Root Node
- * (return type ANY)
- */
+ /* Special case for the predefined Root Node (return type ANY) */
+
if (handle == ACPI_ROOT_OBJECT) {
*ret_type = ACPI_TYPE_ANY;
return (AE_OK);
*/
if (ACPI_SUCCESS(status) &&
possible_method_call && (node->type == ACPI_TYPE_METHOD)) {
- if (walk_state->opcode == AML_UNLOAD_OP) {
+ if (GET_CURRENT_ARG_TYPE(walk_state->arg_types) ==
+ ARGP_SUPERNAME) {
/*
* acpi_ps_get_next_namestring has increased the AML pointer,
* so we need to restore the saved AML pointer for method call.
*
* PARAMETERS: walk_state - Current state
* parser_state - Current parser state object
- * arg_type - The argument type (AML_*_ARG)
+ * arg_type - The parser argument type (ARGP_*)
* return_arg - Where the next arg is returned
*
* RETURN: Status, and an op object containing the next argument.
if (!arg) {
return_ACPI_STATUS(AE_NO_MEMORY);
}
+
acpi_ps_get_next_simple_arg(parser_state, arg_type, arg);
break;
case ARGP_TARGET:
case ARGP_SUPERNAME:
case ARGP_SIMPLENAME:
+ case ARGP_NAME_OR_REF:
subop = acpi_ps_peek_opcode(parser_state);
if (subop == 0 ||
return_ACPI_STATUS(AE_NO_MEMORY);
}
- /* To support super_name arg of Unload */
+ /* super_name allows argument to be a method call */
- if (walk_state->opcode == AML_UNLOAD_OP) {
+ if (arg_type == ARGP_SUPERNAME) {
status =
acpi_ps_get_next_namepath(walk_state,
parser_state, arg,
- 1);
+ ACPI_POSSIBLE_METHOD_CALL);
/*
- * If the super_name arg of Unload is a method call,
- * we have restored the AML pointer, just free this Arg
+ * If the super_name argument is a method call, we have
+ * already restored the AML pointer, just free this Arg
*/
if (arg->common.aml_opcode ==
AML_INT_METHODCALL_OP) {
status =
acpi_ps_get_next_namepath(walk_state,
parser_state, arg,
- 0);
+ ACPI_NOT_METHOD_CALL);
}
} else {
/* Single complex argument, nothing returned */
case AML_INT_NAMEPATH_OP: /* AML_NAMESTRING_ARG */
- status =
- acpi_ps_get_next_namepath(walk_state,
- &(walk_state->parser_state), op,
- 1);
+ status = acpi_ps_get_next_namepath(walk_state,
+ &(walk_state->parser_state),
+ op,
+ ACPI_POSSIBLE_METHOD_CALL);
if (ACPI_FAILURE(status)) {
return_ACPI_STATUS(status);
}
/*
* Op is not a constant or string, append each argument to the Op
*/
- while (GET_CURRENT_ARG_TYPE(walk_state->arg_types)
- && !walk_state->arg_count) {
+ while (GET_CURRENT_ARG_TYPE(walk_state->arg_types) &&
+ !walk_state->arg_count) {
walk_state->aml = walk_state->parser_state.aml;
status =
/* Index Name Parser Args Interpreter Args ObjectType Class Type Flags */
/* 00 */ ACPI_OP("Zero", ARGP_ZERO_OP, ARGI_ZERO_OP, ACPI_TYPE_INTEGER,
- AML_CLASS_ARGUMENT, AML_TYPE_CONSTANT, AML_CONSTANT),
+ AML_CLASS_ARGUMENT, AML_TYPE_CONSTANT, AML_CONSTANT),
/* 01 */ ACPI_OP("One", ARGP_ONE_OP, ARGI_ONE_OP, ACPI_TYPE_INTEGER,
- AML_CLASS_ARGUMENT, AML_TYPE_CONSTANT, AML_CONSTANT),
+ AML_CLASS_ARGUMENT, AML_TYPE_CONSTANT, AML_CONSTANT),
/* 02 */ ACPI_OP("Alias", ARGP_ALIAS_OP, ARGI_ALIAS_OP,
- ACPI_TYPE_LOCAL_ALIAS, AML_CLASS_NAMED_OBJECT,
- AML_TYPE_NAMED_SIMPLE,
- AML_HAS_ARGS | AML_NSOBJECT | AML_NSOPCODE |
- AML_NSNODE | AML_NAMED),
+ ACPI_TYPE_LOCAL_ALIAS, AML_CLASS_NAMED_OBJECT,
+ AML_TYPE_NAMED_SIMPLE,
+ AML_HAS_ARGS | AML_NSOBJECT | AML_NSOPCODE |
+ AML_NSNODE | AML_NAMED),
/* 03 */ ACPI_OP("Name", ARGP_NAME_OP, ARGI_NAME_OP, ACPI_TYPE_ANY,
- AML_CLASS_NAMED_OBJECT, AML_TYPE_NAMED_COMPLEX,
- AML_HAS_ARGS | AML_NSOBJECT | AML_NSOPCODE |
- AML_NSNODE | AML_NAMED),
+ AML_CLASS_NAMED_OBJECT, AML_TYPE_NAMED_COMPLEX,
+ AML_HAS_ARGS | AML_NSOBJECT | AML_NSOPCODE |
+ AML_NSNODE | AML_NAMED),
/* 04 */ ACPI_OP("ByteConst", ARGP_BYTE_OP, ARGI_BYTE_OP,
- ACPI_TYPE_INTEGER, AML_CLASS_ARGUMENT,
- AML_TYPE_LITERAL, AML_CONSTANT),
+ ACPI_TYPE_INTEGER, AML_CLASS_ARGUMENT,
+ AML_TYPE_LITERAL, AML_CONSTANT),
/* 05 */ ACPI_OP("WordConst", ARGP_WORD_OP, ARGI_WORD_OP,
- ACPI_TYPE_INTEGER, AML_CLASS_ARGUMENT,
- AML_TYPE_LITERAL, AML_CONSTANT),
+ ACPI_TYPE_INTEGER, AML_CLASS_ARGUMENT,
+ AML_TYPE_LITERAL, AML_CONSTANT),
/* 06 */ ACPI_OP("DwordConst", ARGP_DWORD_OP, ARGI_DWORD_OP,
- ACPI_TYPE_INTEGER, AML_CLASS_ARGUMENT,
- AML_TYPE_LITERAL, AML_CONSTANT),
+ ACPI_TYPE_INTEGER, AML_CLASS_ARGUMENT,
+ AML_TYPE_LITERAL, AML_CONSTANT),
/* 07 */ ACPI_OP("String", ARGP_STRING_OP, ARGI_STRING_OP,
- ACPI_TYPE_STRING, AML_CLASS_ARGUMENT,
- AML_TYPE_LITERAL, AML_CONSTANT),
+ ACPI_TYPE_STRING, AML_CLASS_ARGUMENT,
+ AML_TYPE_LITERAL, AML_CONSTANT),
/* 08 */ ACPI_OP("Scope", ARGP_SCOPE_OP, ARGI_SCOPE_OP,
- ACPI_TYPE_LOCAL_SCOPE, AML_CLASS_NAMED_OBJECT,
- AML_TYPE_NAMED_NO_OBJ,
- AML_HAS_ARGS | AML_NSOBJECT | AML_NSOPCODE |
- AML_NSNODE | AML_NAMED),
+ ACPI_TYPE_LOCAL_SCOPE, AML_CLASS_NAMED_OBJECT,
+ AML_TYPE_NAMED_NO_OBJ,
+ AML_HAS_ARGS | AML_NSOBJECT | AML_NSOPCODE |
+ AML_NSNODE | AML_NAMED),
/* 09 */ ACPI_OP("Buffer", ARGP_BUFFER_OP, ARGI_BUFFER_OP,
- ACPI_TYPE_BUFFER, AML_CLASS_CREATE,
- AML_TYPE_CREATE_OBJECT,
- AML_HAS_ARGS | AML_DEFER | AML_CONSTANT),
+ ACPI_TYPE_BUFFER, AML_CLASS_CREATE,
+ AML_TYPE_CREATE_OBJECT,
+ AML_HAS_ARGS | AML_DEFER | AML_CONSTANT),
/* 0A */ ACPI_OP("Package", ARGP_PACKAGE_OP, ARGI_PACKAGE_OP,
- ACPI_TYPE_PACKAGE, AML_CLASS_CREATE,
- AML_TYPE_CREATE_OBJECT,
- AML_HAS_ARGS | AML_DEFER | AML_CONSTANT),
+ ACPI_TYPE_PACKAGE, AML_CLASS_CREATE,
+ AML_TYPE_CREATE_OBJECT,
+ AML_HAS_ARGS | AML_DEFER | AML_CONSTANT),
/* 0B */ ACPI_OP("Method", ARGP_METHOD_OP, ARGI_METHOD_OP,
- ACPI_TYPE_METHOD, AML_CLASS_NAMED_OBJECT,
- AML_TYPE_NAMED_COMPLEX,
- AML_HAS_ARGS | AML_NSOBJECT | AML_NSOPCODE |
- AML_NSNODE | AML_NAMED | AML_DEFER),
+ ACPI_TYPE_METHOD, AML_CLASS_NAMED_OBJECT,
+ AML_TYPE_NAMED_COMPLEX,
+ AML_HAS_ARGS | AML_NSOBJECT | AML_NSOPCODE |
+ AML_NSNODE | AML_NAMED | AML_DEFER),
/* 0C */ ACPI_OP("Local0", ARGP_LOCAL0, ARGI_LOCAL0,
- ACPI_TYPE_LOCAL_REFERENCE, AML_CLASS_ARGUMENT,
- AML_TYPE_LOCAL_VARIABLE, 0),
+ ACPI_TYPE_LOCAL_REFERENCE, AML_CLASS_ARGUMENT,
+ AML_TYPE_LOCAL_VARIABLE, 0),
/* 0D */ ACPI_OP("Local1", ARGP_LOCAL1, ARGI_LOCAL1,
- ACPI_TYPE_LOCAL_REFERENCE, AML_CLASS_ARGUMENT,
- AML_TYPE_LOCAL_VARIABLE, 0),
+ ACPI_TYPE_LOCAL_REFERENCE, AML_CLASS_ARGUMENT,
+ AML_TYPE_LOCAL_VARIABLE, 0),
/* 0E */ ACPI_OP("Local2", ARGP_LOCAL2, ARGI_LOCAL2,
- ACPI_TYPE_LOCAL_REFERENCE, AML_CLASS_ARGUMENT,
- AML_TYPE_LOCAL_VARIABLE, 0),
+ ACPI_TYPE_LOCAL_REFERENCE, AML_CLASS_ARGUMENT,
+ AML_TYPE_LOCAL_VARIABLE, 0),
/* 0F */ ACPI_OP("Local3", ARGP_LOCAL3, ARGI_LOCAL3,
- ACPI_TYPE_LOCAL_REFERENCE, AML_CLASS_ARGUMENT,
- AML_TYPE_LOCAL_VARIABLE, 0),
+ ACPI_TYPE_LOCAL_REFERENCE, AML_CLASS_ARGUMENT,
+ AML_TYPE_LOCAL_VARIABLE, 0),
/* 10 */ ACPI_OP("Local4", ARGP_LOCAL4, ARGI_LOCAL4,
- ACPI_TYPE_LOCAL_REFERENCE, AML_CLASS_ARGUMENT,
- AML_TYPE_LOCAL_VARIABLE, 0),
+ ACPI_TYPE_LOCAL_REFERENCE, AML_CLASS_ARGUMENT,
+ AML_TYPE_LOCAL_VARIABLE, 0),
/* 11 */ ACPI_OP("Local5", ARGP_LOCAL5, ARGI_LOCAL5,
- ACPI_TYPE_LOCAL_REFERENCE, AML_CLASS_ARGUMENT,
- AML_TYPE_LOCAL_VARIABLE, 0),
+ ACPI_TYPE_LOCAL_REFERENCE, AML_CLASS_ARGUMENT,
+ AML_TYPE_LOCAL_VARIABLE, 0),
/* 12 */ ACPI_OP("Local6", ARGP_LOCAL6, ARGI_LOCAL6,
- ACPI_TYPE_LOCAL_REFERENCE, AML_CLASS_ARGUMENT,
- AML_TYPE_LOCAL_VARIABLE, 0),
+ ACPI_TYPE_LOCAL_REFERENCE, AML_CLASS_ARGUMENT,
+ AML_TYPE_LOCAL_VARIABLE, 0),
/* 13 */ ACPI_OP("Local7", ARGP_LOCAL7, ARGI_LOCAL7,
- ACPI_TYPE_LOCAL_REFERENCE, AML_CLASS_ARGUMENT,
- AML_TYPE_LOCAL_VARIABLE, 0),
+ ACPI_TYPE_LOCAL_REFERENCE, AML_CLASS_ARGUMENT,
+ AML_TYPE_LOCAL_VARIABLE, 0),
/* 14 */ ACPI_OP("Arg0", ARGP_ARG0, ARGI_ARG0,
- ACPI_TYPE_LOCAL_REFERENCE, AML_CLASS_ARGUMENT,
- AML_TYPE_METHOD_ARGUMENT, 0),
+ ACPI_TYPE_LOCAL_REFERENCE, AML_CLASS_ARGUMENT,
+ AML_TYPE_METHOD_ARGUMENT, 0),
/* 15 */ ACPI_OP("Arg1", ARGP_ARG1, ARGI_ARG1,
- ACPI_TYPE_LOCAL_REFERENCE, AML_CLASS_ARGUMENT,
- AML_TYPE_METHOD_ARGUMENT, 0),
+ ACPI_TYPE_LOCAL_REFERENCE, AML_CLASS_ARGUMENT,
+ AML_TYPE_METHOD_ARGUMENT, 0),
/* 16 */ ACPI_OP("Arg2", ARGP_ARG2, ARGI_ARG2,
- ACPI_TYPE_LOCAL_REFERENCE, AML_CLASS_ARGUMENT,
- AML_TYPE_METHOD_ARGUMENT, 0),
+ ACPI_TYPE_LOCAL_REFERENCE, AML_CLASS_ARGUMENT,
+ AML_TYPE_METHOD_ARGUMENT, 0),
/* 17 */ ACPI_OP("Arg3", ARGP_ARG3, ARGI_ARG3,
- ACPI_TYPE_LOCAL_REFERENCE, AML_CLASS_ARGUMENT,
- AML_TYPE_METHOD_ARGUMENT, 0),
+ ACPI_TYPE_LOCAL_REFERENCE, AML_CLASS_ARGUMENT,
+ AML_TYPE_METHOD_ARGUMENT, 0),
/* 18 */ ACPI_OP("Arg4", ARGP_ARG4, ARGI_ARG4,
- ACPI_TYPE_LOCAL_REFERENCE, AML_CLASS_ARGUMENT,
- AML_TYPE_METHOD_ARGUMENT, 0),
+ ACPI_TYPE_LOCAL_REFERENCE, AML_CLASS_ARGUMENT,
+ AML_TYPE_METHOD_ARGUMENT, 0),
/* 19 */ ACPI_OP("Arg5", ARGP_ARG5, ARGI_ARG5,
- ACPI_TYPE_LOCAL_REFERENCE, AML_CLASS_ARGUMENT,
- AML_TYPE_METHOD_ARGUMENT, 0),
+ ACPI_TYPE_LOCAL_REFERENCE, AML_CLASS_ARGUMENT,
+ AML_TYPE_METHOD_ARGUMENT, 0),
/* 1A */ ACPI_OP("Arg6", ARGP_ARG6, ARGI_ARG6,
- ACPI_TYPE_LOCAL_REFERENCE, AML_CLASS_ARGUMENT,
- AML_TYPE_METHOD_ARGUMENT, 0),
+ ACPI_TYPE_LOCAL_REFERENCE, AML_CLASS_ARGUMENT,
+ AML_TYPE_METHOD_ARGUMENT, 0),
/* 1B */ ACPI_OP("Store", ARGP_STORE_OP, ARGI_STORE_OP, ACPI_TYPE_ANY,
- AML_CLASS_EXECUTE, AML_TYPE_EXEC_1A_1T_1R,
- AML_FLAGS_EXEC_1A_1T_1R),
+ AML_CLASS_EXECUTE, AML_TYPE_EXEC_1A_1T_1R,
+ AML_FLAGS_EXEC_1A_1T_1R),
/* 1C */ ACPI_OP("RefOf", ARGP_REF_OF_OP, ARGI_REF_OF_OP, ACPI_TYPE_ANY,
- AML_CLASS_EXECUTE, AML_TYPE_EXEC_1A_0T_1R,
- AML_FLAGS_EXEC_1A_0T_1R),
+ AML_CLASS_EXECUTE, AML_TYPE_EXEC_1A_0T_1R,
+ AML_FLAGS_EXEC_1A_0T_1R),
/* 1D */ ACPI_OP("Add", ARGP_ADD_OP, ARGI_ADD_OP, ACPI_TYPE_ANY,
- AML_CLASS_EXECUTE, AML_TYPE_EXEC_2A_1T_1R,
- AML_FLAGS_EXEC_2A_1T_1R | AML_MATH | AML_CONSTANT),
+ AML_CLASS_EXECUTE, AML_TYPE_EXEC_2A_1T_1R,
+ AML_FLAGS_EXEC_2A_1T_1R | AML_MATH | AML_CONSTANT),
/* 1E */ ACPI_OP("Concatenate", ARGP_CONCAT_OP, ARGI_CONCAT_OP,
- ACPI_TYPE_ANY, AML_CLASS_EXECUTE,
- AML_TYPE_EXEC_2A_1T_1R,
- AML_FLAGS_EXEC_2A_1T_1R | AML_CONSTANT),
+ ACPI_TYPE_ANY, AML_CLASS_EXECUTE,
+ AML_TYPE_EXEC_2A_1T_1R,
+ AML_FLAGS_EXEC_2A_1T_1R | AML_CONSTANT),
/* 1F */ ACPI_OP("Subtract", ARGP_SUBTRACT_OP, ARGI_SUBTRACT_OP,
- ACPI_TYPE_ANY, AML_CLASS_EXECUTE,
- AML_TYPE_EXEC_2A_1T_1R,
- AML_FLAGS_EXEC_2A_1T_1R | AML_MATH | AML_CONSTANT),
+ ACPI_TYPE_ANY, AML_CLASS_EXECUTE,
+ AML_TYPE_EXEC_2A_1T_1R,
+ AML_FLAGS_EXEC_2A_1T_1R | AML_MATH | AML_CONSTANT),
/* 20 */ ACPI_OP("Increment", ARGP_INCREMENT_OP, ARGI_INCREMENT_OP,
- ACPI_TYPE_ANY, AML_CLASS_EXECUTE,
- AML_TYPE_EXEC_1A_0T_1R,
- AML_FLAGS_EXEC_1A_0T_1R | AML_CONSTANT),
+ ACPI_TYPE_ANY, AML_CLASS_EXECUTE,
+ AML_TYPE_EXEC_1A_0T_1R,
+ AML_FLAGS_EXEC_1A_0T_1R | AML_CONSTANT),
/* 21 */ ACPI_OP("Decrement", ARGP_DECREMENT_OP, ARGI_DECREMENT_OP,
- ACPI_TYPE_ANY, AML_CLASS_EXECUTE,
- AML_TYPE_EXEC_1A_0T_1R,
- AML_FLAGS_EXEC_1A_0T_1R | AML_CONSTANT),
+ ACPI_TYPE_ANY, AML_CLASS_EXECUTE,
+ AML_TYPE_EXEC_1A_0T_1R,
+ AML_FLAGS_EXEC_1A_0T_1R | AML_CONSTANT),
/* 22 */ ACPI_OP("Multiply", ARGP_MULTIPLY_OP, ARGI_MULTIPLY_OP,
- ACPI_TYPE_ANY, AML_CLASS_EXECUTE,
- AML_TYPE_EXEC_2A_1T_1R,
- AML_FLAGS_EXEC_2A_1T_1R | AML_MATH | AML_CONSTANT),
+ ACPI_TYPE_ANY, AML_CLASS_EXECUTE,
+ AML_TYPE_EXEC_2A_1T_1R,
+ AML_FLAGS_EXEC_2A_1T_1R | AML_MATH | AML_CONSTANT),
/* 23 */ ACPI_OP("Divide", ARGP_DIVIDE_OP, ARGI_DIVIDE_OP,
- ACPI_TYPE_ANY, AML_CLASS_EXECUTE,
- AML_TYPE_EXEC_2A_2T_1R,
- AML_FLAGS_EXEC_2A_2T_1R | AML_CONSTANT),
+ ACPI_TYPE_ANY, AML_CLASS_EXECUTE,
+ AML_TYPE_EXEC_2A_2T_1R,
+ AML_FLAGS_EXEC_2A_2T_1R | AML_CONSTANT),
/* 24 */ ACPI_OP("ShiftLeft", ARGP_SHIFT_LEFT_OP, ARGI_SHIFT_LEFT_OP,
- ACPI_TYPE_ANY, AML_CLASS_EXECUTE,
- AML_TYPE_EXEC_2A_1T_1R,
- AML_FLAGS_EXEC_2A_1T_1R | AML_MATH | AML_CONSTANT),
+ ACPI_TYPE_ANY, AML_CLASS_EXECUTE,
+ AML_TYPE_EXEC_2A_1T_1R,
+ AML_FLAGS_EXEC_2A_1T_1R | AML_MATH | AML_CONSTANT),
/* 25 */ ACPI_OP("ShiftRight", ARGP_SHIFT_RIGHT_OP, ARGI_SHIFT_RIGHT_OP,
- ACPI_TYPE_ANY, AML_CLASS_EXECUTE,
- AML_TYPE_EXEC_2A_1T_1R,
- AML_FLAGS_EXEC_2A_1T_1R | AML_MATH | AML_CONSTANT),
+ ACPI_TYPE_ANY, AML_CLASS_EXECUTE,
+ AML_TYPE_EXEC_2A_1T_1R,
+ AML_FLAGS_EXEC_2A_1T_1R | AML_MATH | AML_CONSTANT),
/* 26 */ ACPI_OP("And", ARGP_BIT_AND_OP, ARGI_BIT_AND_OP, ACPI_TYPE_ANY,
- AML_CLASS_EXECUTE, AML_TYPE_EXEC_2A_1T_1R,
- AML_FLAGS_EXEC_2A_1T_1R | AML_MATH | AML_CONSTANT),
+ AML_CLASS_EXECUTE, AML_TYPE_EXEC_2A_1T_1R,
+ AML_FLAGS_EXEC_2A_1T_1R | AML_MATH | AML_CONSTANT),
/* 27 */ ACPI_OP("NAnd", ARGP_BIT_NAND_OP, ARGI_BIT_NAND_OP,
- ACPI_TYPE_ANY, AML_CLASS_EXECUTE,
- AML_TYPE_EXEC_2A_1T_1R,
- AML_FLAGS_EXEC_2A_1T_1R | AML_MATH | AML_CONSTANT),
+ ACPI_TYPE_ANY, AML_CLASS_EXECUTE,
+ AML_TYPE_EXEC_2A_1T_1R,
+ AML_FLAGS_EXEC_2A_1T_1R | AML_MATH | AML_CONSTANT),
/* 28 */ ACPI_OP("Or", ARGP_BIT_OR_OP, ARGI_BIT_OR_OP, ACPI_TYPE_ANY,
- AML_CLASS_EXECUTE, AML_TYPE_EXEC_2A_1T_1R,
- AML_FLAGS_EXEC_2A_1T_1R | AML_MATH | AML_CONSTANT),
+ AML_CLASS_EXECUTE, AML_TYPE_EXEC_2A_1T_1R,
+ AML_FLAGS_EXEC_2A_1T_1R | AML_MATH | AML_CONSTANT),
/* 29 */ ACPI_OP("NOr", ARGP_BIT_NOR_OP, ARGI_BIT_NOR_OP, ACPI_TYPE_ANY,
- AML_CLASS_EXECUTE, AML_TYPE_EXEC_2A_1T_1R,
- AML_FLAGS_EXEC_2A_1T_1R | AML_MATH | AML_CONSTANT),
+ AML_CLASS_EXECUTE, AML_TYPE_EXEC_2A_1T_1R,
+ AML_FLAGS_EXEC_2A_1T_1R | AML_MATH | AML_CONSTANT),
/* 2A */ ACPI_OP("XOr", ARGP_BIT_XOR_OP, ARGI_BIT_XOR_OP, ACPI_TYPE_ANY,
- AML_CLASS_EXECUTE, AML_TYPE_EXEC_2A_1T_1R,
- AML_FLAGS_EXEC_2A_1T_1R | AML_MATH | AML_CONSTANT),
+ AML_CLASS_EXECUTE, AML_TYPE_EXEC_2A_1T_1R,
+ AML_FLAGS_EXEC_2A_1T_1R | AML_MATH | AML_CONSTANT),
/* 2B */ ACPI_OP("Not", ARGP_BIT_NOT_OP, ARGI_BIT_NOT_OP, ACPI_TYPE_ANY,
- AML_CLASS_EXECUTE, AML_TYPE_EXEC_1A_1T_1R,
- AML_FLAGS_EXEC_1A_1T_1R | AML_CONSTANT),
+ AML_CLASS_EXECUTE, AML_TYPE_EXEC_1A_1T_1R,
+ AML_FLAGS_EXEC_1A_1T_1R | AML_CONSTANT),
/* 2C */ ACPI_OP("FindSetLeftBit", ARGP_FIND_SET_LEFT_BIT_OP,
- ARGI_FIND_SET_LEFT_BIT_OP, ACPI_TYPE_ANY,
- AML_CLASS_EXECUTE, AML_TYPE_EXEC_1A_1T_1R,
- AML_FLAGS_EXEC_1A_1T_1R | AML_CONSTANT),
+ ARGI_FIND_SET_LEFT_BIT_OP, ACPI_TYPE_ANY,
+ AML_CLASS_EXECUTE, AML_TYPE_EXEC_1A_1T_1R,
+ AML_FLAGS_EXEC_1A_1T_1R | AML_CONSTANT),
/* 2D */ ACPI_OP("FindSetRightBit", ARGP_FIND_SET_RIGHT_BIT_OP,
- ARGI_FIND_SET_RIGHT_BIT_OP, ACPI_TYPE_ANY,
- AML_CLASS_EXECUTE, AML_TYPE_EXEC_1A_1T_1R,
- AML_FLAGS_EXEC_1A_1T_1R | AML_CONSTANT),
+ ARGI_FIND_SET_RIGHT_BIT_OP, ACPI_TYPE_ANY,
+ AML_CLASS_EXECUTE, AML_TYPE_EXEC_1A_1T_1R,
+ AML_FLAGS_EXEC_1A_1T_1R | AML_CONSTANT),
/* 2E */ ACPI_OP("DerefOf", ARGP_DEREF_OF_OP, ARGI_DEREF_OF_OP,
- ACPI_TYPE_ANY, AML_CLASS_EXECUTE,
- AML_TYPE_EXEC_1A_0T_1R, AML_FLAGS_EXEC_1A_0T_1R),
+ ACPI_TYPE_ANY, AML_CLASS_EXECUTE,
+ AML_TYPE_EXEC_1A_0T_1R, AML_FLAGS_EXEC_1A_0T_1R),
/* 2F */ ACPI_OP("Notify", ARGP_NOTIFY_OP, ARGI_NOTIFY_OP,
- ACPI_TYPE_ANY, AML_CLASS_EXECUTE,
- AML_TYPE_EXEC_2A_0T_0R, AML_FLAGS_EXEC_2A_0T_0R),
+ ACPI_TYPE_ANY, AML_CLASS_EXECUTE,
+ AML_TYPE_EXEC_2A_0T_0R, AML_FLAGS_EXEC_2A_0T_0R),
/* 30 */ ACPI_OP("SizeOf", ARGP_SIZE_OF_OP, ARGI_SIZE_OF_OP,
- ACPI_TYPE_ANY, AML_CLASS_EXECUTE,
- AML_TYPE_EXEC_1A_0T_1R,
- AML_FLAGS_EXEC_1A_0T_1R | AML_NO_OPERAND_RESOLVE),
+ ACPI_TYPE_ANY, AML_CLASS_EXECUTE,
+ AML_TYPE_EXEC_1A_0T_1R,
+ AML_FLAGS_EXEC_1A_0T_1R | AML_NO_OPERAND_RESOLVE),
/* 31 */ ACPI_OP("Index", ARGP_INDEX_OP, ARGI_INDEX_OP, ACPI_TYPE_ANY,
- AML_CLASS_EXECUTE, AML_TYPE_EXEC_2A_1T_1R,
- AML_FLAGS_EXEC_2A_1T_1R),
+ AML_CLASS_EXECUTE, AML_TYPE_EXEC_2A_1T_1R,
+ AML_FLAGS_EXEC_2A_1T_1R),
/* 32 */ ACPI_OP("Match", ARGP_MATCH_OP, ARGI_MATCH_OP, ACPI_TYPE_ANY,
- AML_CLASS_EXECUTE, AML_TYPE_EXEC_6A_0T_1R,
- AML_FLAGS_EXEC_6A_0T_1R | AML_CONSTANT),
+ AML_CLASS_EXECUTE, AML_TYPE_EXEC_6A_0T_1R,
+ AML_FLAGS_EXEC_6A_0T_1R | AML_CONSTANT),
/* 33 */ ACPI_OP("CreateDWordField", ARGP_CREATE_DWORD_FIELD_OP,
- ARGI_CREATE_DWORD_FIELD_OP,
- ACPI_TYPE_BUFFER_FIELD, AML_CLASS_CREATE,
- AML_TYPE_CREATE_FIELD,
- AML_HAS_ARGS | AML_NSOBJECT | AML_NSNODE |
- AML_DEFER | AML_CREATE),
+ ARGI_CREATE_DWORD_FIELD_OP,
+ ACPI_TYPE_BUFFER_FIELD, AML_CLASS_CREATE,
+ AML_TYPE_CREATE_FIELD,
+ AML_HAS_ARGS | AML_NSOBJECT | AML_NSNODE |
+ AML_DEFER | AML_CREATE),
/* 34 */ ACPI_OP("CreateWordField", ARGP_CREATE_WORD_FIELD_OP,
- ARGI_CREATE_WORD_FIELD_OP,
- ACPI_TYPE_BUFFER_FIELD, AML_CLASS_CREATE,
- AML_TYPE_CREATE_FIELD,
- AML_HAS_ARGS | AML_NSOBJECT | AML_NSNODE |
- AML_DEFER | AML_CREATE),
+ ARGI_CREATE_WORD_FIELD_OP,
+ ACPI_TYPE_BUFFER_FIELD, AML_CLASS_CREATE,
+ AML_TYPE_CREATE_FIELD,
+ AML_HAS_ARGS | AML_NSOBJECT | AML_NSNODE |
+ AML_DEFER | AML_CREATE),
/* 35 */ ACPI_OP("CreateByteField", ARGP_CREATE_BYTE_FIELD_OP,
- ARGI_CREATE_BYTE_FIELD_OP,
- ACPI_TYPE_BUFFER_FIELD, AML_CLASS_CREATE,
- AML_TYPE_CREATE_FIELD,
- AML_HAS_ARGS | AML_NSOBJECT | AML_NSNODE |
- AML_DEFER | AML_CREATE),
+ ARGI_CREATE_BYTE_FIELD_OP,
+ ACPI_TYPE_BUFFER_FIELD, AML_CLASS_CREATE,
+ AML_TYPE_CREATE_FIELD,
+ AML_HAS_ARGS | AML_NSOBJECT | AML_NSNODE |
+ AML_DEFER | AML_CREATE),
/* 36 */ ACPI_OP("CreateBitField", ARGP_CREATE_BIT_FIELD_OP,
- ARGI_CREATE_BIT_FIELD_OP,
- ACPI_TYPE_BUFFER_FIELD, AML_CLASS_CREATE,
- AML_TYPE_CREATE_FIELD,
- AML_HAS_ARGS | AML_NSOBJECT | AML_NSNODE |
- AML_DEFER | AML_CREATE),
-/* 37 */ ACPI_OP("ObjectType", ARGP_TYPE_OP, ARGI_TYPE_OP,
- ACPI_TYPE_ANY, AML_CLASS_EXECUTE,
- AML_TYPE_EXEC_1A_0T_1R,
- AML_FLAGS_EXEC_1A_0T_1R | AML_NO_OPERAND_RESOLVE),
+ ARGI_CREATE_BIT_FIELD_OP,
+ ACPI_TYPE_BUFFER_FIELD, AML_CLASS_CREATE,
+ AML_TYPE_CREATE_FIELD,
+ AML_HAS_ARGS | AML_NSOBJECT | AML_NSNODE |
+ AML_DEFER | AML_CREATE),
+/* 37 */ ACPI_OP("ObjectType", ARGP_OBJECT_TYPE_OP, ARGI_OBJECT_TYPE_OP,
+ ACPI_TYPE_ANY, AML_CLASS_EXECUTE,
+ AML_TYPE_EXEC_1A_0T_1R,
+ AML_FLAGS_EXEC_1A_0T_1R | AML_NO_OPERAND_RESOLVE),
/* 38 */ ACPI_OP("LAnd", ARGP_LAND_OP, ARGI_LAND_OP, ACPI_TYPE_ANY,
- AML_CLASS_EXECUTE, AML_TYPE_EXEC_2A_0T_1R,
+ AML_CLASS_EXECUTE, AML_TYPE_EXEC_2A_0T_1R,
AML_FLAGS_EXEC_2A_0T_1R | AML_LOGICAL_NUMERIC |
AML_CONSTANT),
/* 39 */ ACPI_OP("LOr", ARGP_LOR_OP, ARGI_LOR_OP, ACPI_TYPE_ANY,
- AML_CLASS_EXECUTE, AML_TYPE_EXEC_2A_0T_1R,
- AML_FLAGS_EXEC_2A_0T_1R | AML_LOGICAL_NUMERIC |
+ AML_CLASS_EXECUTE, AML_TYPE_EXEC_2A_0T_1R,
+ AML_FLAGS_EXEC_2A_0T_1R | AML_LOGICAL_NUMERIC |
AML_CONSTANT),
/* 3A */ ACPI_OP("LNot", ARGP_LNOT_OP, ARGI_LNOT_OP, ACPI_TYPE_ANY,
- AML_CLASS_EXECUTE, AML_TYPE_EXEC_1A_0T_1R,
- AML_FLAGS_EXEC_1A_0T_1R | AML_CONSTANT),
+ AML_CLASS_EXECUTE, AML_TYPE_EXEC_1A_0T_1R,
+ AML_FLAGS_EXEC_1A_0T_1R | AML_CONSTANT),
/* 3B */ ACPI_OP("LEqual", ARGP_LEQUAL_OP, ARGI_LEQUAL_OP,
- ACPI_TYPE_ANY, AML_CLASS_EXECUTE,
- AML_TYPE_EXEC_2A_0T_1R,
- AML_FLAGS_EXEC_2A_0T_1R | AML_LOGICAL | AML_CONSTANT),
+ ACPI_TYPE_ANY, AML_CLASS_EXECUTE,
+ AML_TYPE_EXEC_2A_0T_1R,
+ AML_FLAGS_EXEC_2A_0T_1R | AML_LOGICAL | AML_CONSTANT),
/* 3C */ ACPI_OP("LGreater", ARGP_LGREATER_OP, ARGI_LGREATER_OP,
- ACPI_TYPE_ANY, AML_CLASS_EXECUTE,
- AML_TYPE_EXEC_2A_0T_1R,
- AML_FLAGS_EXEC_2A_0T_1R | AML_LOGICAL | AML_CONSTANT),
+ ACPI_TYPE_ANY, AML_CLASS_EXECUTE,
+ AML_TYPE_EXEC_2A_0T_1R,
+ AML_FLAGS_EXEC_2A_0T_1R | AML_LOGICAL | AML_CONSTANT),
/* 3D */ ACPI_OP("LLess", ARGP_LLESS_OP, ARGI_LLESS_OP, ACPI_TYPE_ANY,
- AML_CLASS_EXECUTE, AML_TYPE_EXEC_2A_0T_1R,
- AML_FLAGS_EXEC_2A_0T_1R | AML_LOGICAL | AML_CONSTANT),
+ AML_CLASS_EXECUTE, AML_TYPE_EXEC_2A_0T_1R,
+ AML_FLAGS_EXEC_2A_0T_1R | AML_LOGICAL | AML_CONSTANT),
/* 3E */ ACPI_OP("If", ARGP_IF_OP, ARGI_IF_OP, ACPI_TYPE_ANY,
- AML_CLASS_CONTROL, AML_TYPE_CONTROL, AML_HAS_ARGS),
+ AML_CLASS_CONTROL, AML_TYPE_CONTROL, AML_HAS_ARGS),
/* 3F */ ACPI_OP("Else", ARGP_ELSE_OP, ARGI_ELSE_OP, ACPI_TYPE_ANY,
- AML_CLASS_CONTROL, AML_TYPE_CONTROL, AML_HAS_ARGS),
+ AML_CLASS_CONTROL, AML_TYPE_CONTROL, AML_HAS_ARGS),
/* 40 */ ACPI_OP("While", ARGP_WHILE_OP, ARGI_WHILE_OP, ACPI_TYPE_ANY,
- AML_CLASS_CONTROL, AML_TYPE_CONTROL, AML_HAS_ARGS),
+ AML_CLASS_CONTROL, AML_TYPE_CONTROL, AML_HAS_ARGS),
/* 41 */ ACPI_OP("Noop", ARGP_NOOP_OP, ARGI_NOOP_OP, ACPI_TYPE_ANY,
- AML_CLASS_CONTROL, AML_TYPE_CONTROL, 0),
+ AML_CLASS_CONTROL, AML_TYPE_CONTROL, 0),
/* 42 */ ACPI_OP("Return", ARGP_RETURN_OP, ARGI_RETURN_OP,
- ACPI_TYPE_ANY, AML_CLASS_CONTROL,
- AML_TYPE_CONTROL, AML_HAS_ARGS),
+ ACPI_TYPE_ANY, AML_CLASS_CONTROL,
+ AML_TYPE_CONTROL, AML_HAS_ARGS),
/* 43 */ ACPI_OP("Break", ARGP_BREAK_OP, ARGI_BREAK_OP, ACPI_TYPE_ANY,
- AML_CLASS_CONTROL, AML_TYPE_CONTROL, 0),
+ AML_CLASS_CONTROL, AML_TYPE_CONTROL, 0),
/* 44 */ ACPI_OP("BreakPoint", ARGP_BREAK_POINT_OP, ARGI_BREAK_POINT_OP,
- ACPI_TYPE_ANY, AML_CLASS_CONTROL, AML_TYPE_CONTROL, 0),
+ ACPI_TYPE_ANY, AML_CLASS_CONTROL, AML_TYPE_CONTROL, 0),
/* 45 */ ACPI_OP("Ones", ARGP_ONES_OP, ARGI_ONES_OP, ACPI_TYPE_INTEGER,
- AML_CLASS_ARGUMENT, AML_TYPE_CONSTANT, AML_CONSTANT),
+ AML_CLASS_ARGUMENT, AML_TYPE_CONSTANT, AML_CONSTANT),
/* Prefixed opcodes (Two-byte opcodes with a prefix op) */
/* 46 */ ACPI_OP("Mutex", ARGP_MUTEX_OP, ARGI_MUTEX_OP, ACPI_TYPE_MUTEX,
- AML_CLASS_NAMED_OBJECT, AML_TYPE_NAMED_SIMPLE,
- AML_HAS_ARGS | AML_NSOBJECT | AML_NSOPCODE |
- AML_NSNODE | AML_NAMED),
+ AML_CLASS_NAMED_OBJECT, AML_TYPE_NAMED_SIMPLE,
+ AML_HAS_ARGS | AML_NSOBJECT | AML_NSOPCODE |
+ AML_NSNODE | AML_NAMED),
/* 47 */ ACPI_OP("Event", ARGP_EVENT_OP, ARGI_EVENT_OP, ACPI_TYPE_EVENT,
- AML_CLASS_NAMED_OBJECT, AML_TYPE_NAMED_SIMPLE,
- AML_NSOBJECT | AML_NSOPCODE | AML_NSNODE | AML_NAMED),
+ AML_CLASS_NAMED_OBJECT, AML_TYPE_NAMED_SIMPLE,
+ AML_NSOBJECT | AML_NSOPCODE | AML_NSNODE | AML_NAMED),
/* 48 */ ACPI_OP("CondRefOf", ARGP_COND_REF_OF_OP, ARGI_COND_REF_OF_OP,
- ACPI_TYPE_ANY, AML_CLASS_EXECUTE,
- AML_TYPE_EXEC_1A_1T_1R, AML_FLAGS_EXEC_1A_1T_1R),
+ ACPI_TYPE_ANY, AML_CLASS_EXECUTE,
+ AML_TYPE_EXEC_1A_1T_1R, AML_FLAGS_EXEC_1A_1T_1R),
/* 49 */ ACPI_OP("CreateField", ARGP_CREATE_FIELD_OP,
- ARGI_CREATE_FIELD_OP, ACPI_TYPE_BUFFER_FIELD,
- AML_CLASS_CREATE, AML_TYPE_CREATE_FIELD,
- AML_HAS_ARGS | AML_NSOBJECT | AML_NSNODE |
- AML_DEFER | AML_FIELD | AML_CREATE),
+ ARGI_CREATE_FIELD_OP, ACPI_TYPE_BUFFER_FIELD,
+ AML_CLASS_CREATE, AML_TYPE_CREATE_FIELD,
+ AML_HAS_ARGS | AML_NSOBJECT | AML_NSNODE |
+ AML_DEFER | AML_FIELD | AML_CREATE),
/* 4A */ ACPI_OP("Load", ARGP_LOAD_OP, ARGI_LOAD_OP, ACPI_TYPE_ANY,
- AML_CLASS_EXECUTE, AML_TYPE_EXEC_1A_1T_0R,
- AML_FLAGS_EXEC_1A_1T_0R),
+ AML_CLASS_EXECUTE, AML_TYPE_EXEC_1A_1T_0R,
+ AML_FLAGS_EXEC_1A_1T_0R),
/* 4B */ ACPI_OP("Stall", ARGP_STALL_OP, ARGI_STALL_OP, ACPI_TYPE_ANY,
- AML_CLASS_EXECUTE, AML_TYPE_EXEC_1A_0T_0R,
- AML_FLAGS_EXEC_1A_0T_0R),
+ AML_CLASS_EXECUTE, AML_TYPE_EXEC_1A_0T_0R,
+ AML_FLAGS_EXEC_1A_0T_0R),
/* 4C */ ACPI_OP("Sleep", ARGP_SLEEP_OP, ARGI_SLEEP_OP, ACPI_TYPE_ANY,
- AML_CLASS_EXECUTE, AML_TYPE_EXEC_1A_0T_0R,
- AML_FLAGS_EXEC_1A_0T_0R),
+ AML_CLASS_EXECUTE, AML_TYPE_EXEC_1A_0T_0R,
+ AML_FLAGS_EXEC_1A_0T_0R),
/* 4D */ ACPI_OP("Acquire", ARGP_ACQUIRE_OP, ARGI_ACQUIRE_OP,
- ACPI_TYPE_ANY, AML_CLASS_EXECUTE,
- AML_TYPE_EXEC_2A_0T_1R, AML_FLAGS_EXEC_2A_0T_1R),
+ ACPI_TYPE_ANY, AML_CLASS_EXECUTE,
+ AML_TYPE_EXEC_2A_0T_1R, AML_FLAGS_EXEC_2A_0T_1R),
/* 4E */ ACPI_OP("Signal", ARGP_SIGNAL_OP, ARGI_SIGNAL_OP,
- ACPI_TYPE_ANY, AML_CLASS_EXECUTE,
- AML_TYPE_EXEC_1A_0T_0R, AML_FLAGS_EXEC_1A_0T_0R),
+ ACPI_TYPE_ANY, AML_CLASS_EXECUTE,
+ AML_TYPE_EXEC_1A_0T_0R, AML_FLAGS_EXEC_1A_0T_0R),
/* 4F */ ACPI_OP("Wait", ARGP_WAIT_OP, ARGI_WAIT_OP, ACPI_TYPE_ANY,
- AML_CLASS_EXECUTE, AML_TYPE_EXEC_2A_0T_1R,
- AML_FLAGS_EXEC_2A_0T_1R),
+ AML_CLASS_EXECUTE, AML_TYPE_EXEC_2A_0T_1R,
+ AML_FLAGS_EXEC_2A_0T_1R),
/* 50 */ ACPI_OP("Reset", ARGP_RESET_OP, ARGI_RESET_OP, ACPI_TYPE_ANY,
- AML_CLASS_EXECUTE, AML_TYPE_EXEC_1A_0T_0R,
- AML_FLAGS_EXEC_1A_0T_0R),
+ AML_CLASS_EXECUTE, AML_TYPE_EXEC_1A_0T_0R,
+ AML_FLAGS_EXEC_1A_0T_0R),
/* 51 */ ACPI_OP("Release", ARGP_RELEASE_OP, ARGI_RELEASE_OP,
- ACPI_TYPE_ANY, AML_CLASS_EXECUTE,
- AML_TYPE_EXEC_1A_0T_0R, AML_FLAGS_EXEC_1A_0T_0R),
+ ACPI_TYPE_ANY, AML_CLASS_EXECUTE,
+ AML_TYPE_EXEC_1A_0T_0R, AML_FLAGS_EXEC_1A_0T_0R),
/* 52 */ ACPI_OP("FromBCD", ARGP_FROM_BCD_OP, ARGI_FROM_BCD_OP,
- ACPI_TYPE_ANY, AML_CLASS_EXECUTE,
- AML_TYPE_EXEC_1A_1T_1R,
- AML_FLAGS_EXEC_1A_1T_1R | AML_CONSTANT),
+ ACPI_TYPE_ANY, AML_CLASS_EXECUTE,
+ AML_TYPE_EXEC_1A_1T_1R,
+ AML_FLAGS_EXEC_1A_1T_1R | AML_CONSTANT),
/* 53 */ ACPI_OP("ToBCD", ARGP_TO_BCD_OP, ARGI_TO_BCD_OP, ACPI_TYPE_ANY,
- AML_CLASS_EXECUTE, AML_TYPE_EXEC_1A_1T_1R,
- AML_FLAGS_EXEC_1A_1T_1R | AML_CONSTANT),
+ AML_CLASS_EXECUTE, AML_TYPE_EXEC_1A_1T_1R,
+ AML_FLAGS_EXEC_1A_1T_1R | AML_CONSTANT),
/* 54 */ ACPI_OP("Unload", ARGP_UNLOAD_OP, ARGI_UNLOAD_OP,
- ACPI_TYPE_ANY, AML_CLASS_EXECUTE,
- AML_TYPE_EXEC_1A_0T_0R, AML_FLAGS_EXEC_1A_0T_0R),
+ ACPI_TYPE_ANY, AML_CLASS_EXECUTE,
+ AML_TYPE_EXEC_1A_0T_0R, AML_FLAGS_EXEC_1A_0T_0R),
/* 55 */ ACPI_OP("Revision", ARGP_REVISION_OP, ARGI_REVISION_OP,
- ACPI_TYPE_INTEGER, AML_CLASS_ARGUMENT,
- AML_TYPE_CONSTANT, 0),
+ ACPI_TYPE_INTEGER, AML_CLASS_ARGUMENT,
+ AML_TYPE_CONSTANT, 0),
/* 56 */ ACPI_OP("Debug", ARGP_DEBUG_OP, ARGI_DEBUG_OP,
- ACPI_TYPE_LOCAL_REFERENCE, AML_CLASS_ARGUMENT,
- AML_TYPE_CONSTANT, 0),
+ ACPI_TYPE_LOCAL_REFERENCE, AML_CLASS_ARGUMENT,
+ AML_TYPE_CONSTANT, 0),
/* 57 */ ACPI_OP("Fatal", ARGP_FATAL_OP, ARGI_FATAL_OP, ACPI_TYPE_ANY,
- AML_CLASS_EXECUTE, AML_TYPE_EXEC_3A_0T_0R,
- AML_FLAGS_EXEC_3A_0T_0R),
+ AML_CLASS_EXECUTE, AML_TYPE_EXEC_3A_0T_0R,
+ AML_FLAGS_EXEC_3A_0T_0R),
/* 58 */ ACPI_OP("OperationRegion", ARGP_REGION_OP, ARGI_REGION_OP,
- ACPI_TYPE_REGION, AML_CLASS_NAMED_OBJECT,
- AML_TYPE_NAMED_COMPLEX,
- AML_HAS_ARGS | AML_NSOBJECT | AML_NSOPCODE |
- AML_NSNODE | AML_NAMED | AML_DEFER),
+ ACPI_TYPE_REGION, AML_CLASS_NAMED_OBJECT,
+ AML_TYPE_NAMED_COMPLEX,
+ AML_HAS_ARGS | AML_NSOBJECT | AML_NSOPCODE |
+ AML_NSNODE | AML_NAMED | AML_DEFER),
/* 59 */ ACPI_OP("Field", ARGP_FIELD_OP, ARGI_FIELD_OP, ACPI_TYPE_ANY,
- AML_CLASS_NAMED_OBJECT, AML_TYPE_NAMED_FIELD,
+ AML_CLASS_NAMED_OBJECT, AML_TYPE_NAMED_FIELD,
AML_HAS_ARGS | AML_NSOBJECT | AML_NSOPCODE |
AML_FIELD),
/* 5A */ ACPI_OP("Device", ARGP_DEVICE_OP, ARGI_DEVICE_OP,
- ACPI_TYPE_DEVICE, AML_CLASS_NAMED_OBJECT,
- AML_TYPE_NAMED_NO_OBJ,
- AML_HAS_ARGS | AML_NSOBJECT | AML_NSOPCODE |
- AML_NSNODE | AML_NAMED),
+ ACPI_TYPE_DEVICE, AML_CLASS_NAMED_OBJECT,
+ AML_TYPE_NAMED_NO_OBJ,
+ AML_HAS_ARGS | AML_NSOBJECT | AML_NSOPCODE |
+ AML_NSNODE | AML_NAMED),
/* 5B */ ACPI_OP("Processor", ARGP_PROCESSOR_OP, ARGI_PROCESSOR_OP,
- ACPI_TYPE_PROCESSOR, AML_CLASS_NAMED_OBJECT,
- AML_TYPE_NAMED_SIMPLE,
- AML_HAS_ARGS | AML_NSOBJECT | AML_NSOPCODE |
- AML_NSNODE | AML_NAMED),
+ ACPI_TYPE_PROCESSOR, AML_CLASS_NAMED_OBJECT,
+ AML_TYPE_NAMED_SIMPLE,
+ AML_HAS_ARGS | AML_NSOBJECT | AML_NSOPCODE |
+ AML_NSNODE | AML_NAMED),
/* 5C */ ACPI_OP("PowerResource", ARGP_POWER_RES_OP, ARGI_POWER_RES_OP,
- ACPI_TYPE_POWER, AML_CLASS_NAMED_OBJECT,
- AML_TYPE_NAMED_SIMPLE,
- AML_HAS_ARGS | AML_NSOBJECT | AML_NSOPCODE |
- AML_NSNODE | AML_NAMED),
+ ACPI_TYPE_POWER, AML_CLASS_NAMED_OBJECT,
+ AML_TYPE_NAMED_SIMPLE,
+ AML_HAS_ARGS | AML_NSOBJECT | AML_NSOPCODE |
+ AML_NSNODE | AML_NAMED),
/* 5D */ ACPI_OP("ThermalZone", ARGP_THERMAL_ZONE_OP,
- ARGI_THERMAL_ZONE_OP, ACPI_TYPE_THERMAL,
- AML_CLASS_NAMED_OBJECT, AML_TYPE_NAMED_NO_OBJ,
- AML_HAS_ARGS | AML_NSOBJECT | AML_NSOPCODE |
- AML_NSNODE | AML_NAMED),
+ ARGI_THERMAL_ZONE_OP, ACPI_TYPE_THERMAL,
+ AML_CLASS_NAMED_OBJECT, AML_TYPE_NAMED_NO_OBJ,
+ AML_HAS_ARGS | AML_NSOBJECT | AML_NSOPCODE |
+ AML_NSNODE | AML_NAMED),
/* 5E */ ACPI_OP("IndexField", ARGP_INDEX_FIELD_OP, ARGI_INDEX_FIELD_OP,
- ACPI_TYPE_ANY, AML_CLASS_NAMED_OBJECT,
- AML_TYPE_NAMED_FIELD,
- AML_HAS_ARGS | AML_NSOBJECT | AML_NSOPCODE |
+ ACPI_TYPE_ANY, AML_CLASS_NAMED_OBJECT,
+ AML_TYPE_NAMED_FIELD,
+ AML_HAS_ARGS | AML_NSOBJECT | AML_NSOPCODE |
AML_FIELD),
/* 5F */ ACPI_OP("BankField", ARGP_BANK_FIELD_OP, ARGI_BANK_FIELD_OP,
- ACPI_TYPE_LOCAL_BANK_FIELD,
+ ACPI_TYPE_LOCAL_BANK_FIELD,
AML_CLASS_NAMED_OBJECT, AML_TYPE_NAMED_FIELD,
- AML_HAS_ARGS | AML_NSOBJECT | AML_NSOPCODE |
+ AML_HAS_ARGS | AML_NSOBJECT | AML_NSOPCODE |
AML_FIELD | AML_DEFER),
/* Internal opcodes that map to invalid AML opcodes */
/* 60 */ ACPI_OP("LNotEqual", ARGP_LNOTEQUAL_OP, ARGI_LNOTEQUAL_OP,
- ACPI_TYPE_ANY, AML_CLASS_INTERNAL,
- AML_TYPE_BOGUS, AML_HAS_ARGS | AML_CONSTANT),
+ ACPI_TYPE_ANY, AML_CLASS_INTERNAL,
+ AML_TYPE_BOGUS, AML_HAS_ARGS | AML_CONSTANT),
/* 61 */ ACPI_OP("LLessEqual", ARGP_LLESSEQUAL_OP, ARGI_LLESSEQUAL_OP,
- ACPI_TYPE_ANY, AML_CLASS_INTERNAL,
- AML_TYPE_BOGUS, AML_HAS_ARGS | AML_CONSTANT),
+ ACPI_TYPE_ANY, AML_CLASS_INTERNAL,
+ AML_TYPE_BOGUS, AML_HAS_ARGS | AML_CONSTANT),
/* 62 */ ACPI_OP("LGreaterEqual", ARGP_LGREATEREQUAL_OP,
- ARGI_LGREATEREQUAL_OP, ACPI_TYPE_ANY,
- AML_CLASS_INTERNAL, AML_TYPE_BOGUS,
- AML_HAS_ARGS | AML_CONSTANT),
+ ARGI_LGREATEREQUAL_OP, ACPI_TYPE_ANY,
+ AML_CLASS_INTERNAL, AML_TYPE_BOGUS,
+ AML_HAS_ARGS | AML_CONSTANT),
/* 63 */ ACPI_OP("-NamePath-", ARGP_NAMEPATH_OP, ARGI_NAMEPATH_OP,
- ACPI_TYPE_LOCAL_REFERENCE, AML_CLASS_ARGUMENT,
- AML_TYPE_LITERAL, AML_NSOBJECT | AML_NSNODE),
+ ACPI_TYPE_LOCAL_REFERENCE, AML_CLASS_ARGUMENT,
+ AML_TYPE_LITERAL, AML_NSOBJECT | AML_NSNODE),
/* 64 */ ACPI_OP("-MethodCall-", ARGP_METHODCALL_OP, ARGI_METHODCALL_OP,
- ACPI_TYPE_METHOD, AML_CLASS_METHOD_CALL,
- AML_TYPE_METHOD_CALL,
- AML_HAS_ARGS | AML_NSOBJECT | AML_NSNODE),
+ ACPI_TYPE_METHOD, AML_CLASS_METHOD_CALL,
+ AML_TYPE_METHOD_CALL,
+ AML_HAS_ARGS | AML_NSOBJECT | AML_NSNODE),
/* 65 */ ACPI_OP("-ByteList-", ARGP_BYTELIST_OP, ARGI_BYTELIST_OP,
- ACPI_TYPE_ANY, AML_CLASS_ARGUMENT,
- AML_TYPE_LITERAL, 0),
+ ACPI_TYPE_ANY, AML_CLASS_ARGUMENT,
+ AML_TYPE_LITERAL, 0),
/* 66 */ ACPI_OP("-ReservedField-", ARGP_RESERVEDFIELD_OP,
- ARGI_RESERVEDFIELD_OP, ACPI_TYPE_ANY,
- AML_CLASS_INTERNAL, AML_TYPE_BOGUS, 0),
+ ARGI_RESERVEDFIELD_OP, ACPI_TYPE_ANY,
+ AML_CLASS_INTERNAL, AML_TYPE_BOGUS, 0),
/* 67 */ ACPI_OP("-NamedField-", ARGP_NAMEDFIELD_OP, ARGI_NAMEDFIELD_OP,
- ACPI_TYPE_ANY, AML_CLASS_INTERNAL,
- AML_TYPE_BOGUS,
- AML_NSOBJECT | AML_NSOPCODE | AML_NSNODE | AML_NAMED),
+ ACPI_TYPE_ANY, AML_CLASS_INTERNAL,
+ AML_TYPE_BOGUS,
+ AML_NSOBJECT | AML_NSOPCODE | AML_NSNODE | AML_NAMED),
/* 68 */ ACPI_OP("-AccessField-", ARGP_ACCESSFIELD_OP,
- ARGI_ACCESSFIELD_OP, ACPI_TYPE_ANY,
- AML_CLASS_INTERNAL, AML_TYPE_BOGUS, 0),
+ ARGI_ACCESSFIELD_OP, ACPI_TYPE_ANY,
+ AML_CLASS_INTERNAL, AML_TYPE_BOGUS, 0),
/* 69 */ ACPI_OP("-StaticString", ARGP_STATICSTRING_OP,
- ARGI_STATICSTRING_OP, ACPI_TYPE_ANY,
- AML_CLASS_INTERNAL, AML_TYPE_BOGUS, 0),
+ ARGI_STATICSTRING_OP, ACPI_TYPE_ANY,
+ AML_CLASS_INTERNAL, AML_TYPE_BOGUS, 0),
/* 6A */ ACPI_OP("-Return Value-", ARG_NONE, ARG_NONE, ACPI_TYPE_ANY,
- AML_CLASS_RETURN_VALUE, AML_TYPE_RETURN,
- AML_HAS_ARGS | AML_HAS_RETVAL),
+ AML_CLASS_RETURN_VALUE, AML_TYPE_RETURN,
+ AML_HAS_ARGS | AML_HAS_RETVAL),
/* 6B */ ACPI_OP("-UNKNOWN_OP-", ARG_NONE, ARG_NONE, ACPI_TYPE_INVALID,
- AML_CLASS_UNKNOWN, AML_TYPE_BOGUS, AML_HAS_ARGS),
+ AML_CLASS_UNKNOWN, AML_TYPE_BOGUS, AML_HAS_ARGS),
/* 6C */ ACPI_OP("-ASCII_ONLY-", ARG_NONE, ARG_NONE, ACPI_TYPE_ANY,
- AML_CLASS_ASCII, AML_TYPE_BOGUS, AML_HAS_ARGS),
+ AML_CLASS_ASCII, AML_TYPE_BOGUS, AML_HAS_ARGS),
/* 6D */ ACPI_OP("-PREFIX_ONLY-", ARG_NONE, ARG_NONE, ACPI_TYPE_ANY,
- AML_CLASS_PREFIX, AML_TYPE_BOGUS, AML_HAS_ARGS),
+ AML_CLASS_PREFIX, AML_TYPE_BOGUS, AML_HAS_ARGS),
/* ACPI 2.0 opcodes */
/* 6E */ ACPI_OP("QwordConst", ARGP_QWORD_OP, ARGI_QWORD_OP,
- ACPI_TYPE_INTEGER, AML_CLASS_ARGUMENT,
- AML_TYPE_LITERAL, AML_CONSTANT),
+ ACPI_TYPE_INTEGER, AML_CLASS_ARGUMENT,
+ AML_TYPE_LITERAL, AML_CONSTANT),
/* 6F */ ACPI_OP("Package", /* Var */ ARGP_VAR_PACKAGE_OP,
ARGI_VAR_PACKAGE_OP, ACPI_TYPE_PACKAGE,
AML_CLASS_CREATE, AML_TYPE_CREATE_OBJECT,
AML_HAS_ARGS | AML_DEFER),
/* 70 */ ACPI_OP("ConcatenateResTemplate", ARGP_CONCAT_RES_OP,
- ARGI_CONCAT_RES_OP, ACPI_TYPE_ANY,
- AML_CLASS_EXECUTE, AML_TYPE_EXEC_2A_1T_1R,
- AML_FLAGS_EXEC_2A_1T_1R | AML_CONSTANT),
+ ARGI_CONCAT_RES_OP, ACPI_TYPE_ANY,
+ AML_CLASS_EXECUTE, AML_TYPE_EXEC_2A_1T_1R,
+ AML_FLAGS_EXEC_2A_1T_1R | AML_CONSTANT),
/* 71 */ ACPI_OP("Mod", ARGP_MOD_OP, ARGI_MOD_OP, ACPI_TYPE_ANY,
- AML_CLASS_EXECUTE, AML_TYPE_EXEC_2A_1T_1R,
- AML_FLAGS_EXEC_2A_1T_1R | AML_CONSTANT),
+ AML_CLASS_EXECUTE, AML_TYPE_EXEC_2A_1T_1R,
+ AML_FLAGS_EXEC_2A_1T_1R | AML_CONSTANT),
/* 72 */ ACPI_OP("CreateQWordField", ARGP_CREATE_QWORD_FIELD_OP,
- ARGI_CREATE_QWORD_FIELD_OP,
- ACPI_TYPE_BUFFER_FIELD, AML_CLASS_CREATE,
- AML_TYPE_CREATE_FIELD,
- AML_HAS_ARGS | AML_NSOBJECT | AML_NSNODE |
- AML_DEFER | AML_CREATE),
+ ARGI_CREATE_QWORD_FIELD_OP,
+ ACPI_TYPE_BUFFER_FIELD, AML_CLASS_CREATE,
+ AML_TYPE_CREATE_FIELD,
+ AML_HAS_ARGS | AML_NSOBJECT | AML_NSNODE |
+ AML_DEFER | AML_CREATE),
/* 73 */ ACPI_OP("ToBuffer", ARGP_TO_BUFFER_OP, ARGI_TO_BUFFER_OP,
- ACPI_TYPE_ANY, AML_CLASS_EXECUTE,
- AML_TYPE_EXEC_1A_1T_1R,
- AML_FLAGS_EXEC_1A_1T_1R | AML_CONSTANT),
+ ACPI_TYPE_ANY, AML_CLASS_EXECUTE,
+ AML_TYPE_EXEC_1A_1T_1R,
+ AML_FLAGS_EXEC_1A_1T_1R | AML_CONSTANT),
/* 74 */ ACPI_OP("ToDecimalString", ARGP_TO_DEC_STR_OP,
- ARGI_TO_DEC_STR_OP, ACPI_TYPE_ANY,
- AML_CLASS_EXECUTE, AML_TYPE_EXEC_1A_1T_1R,
- AML_FLAGS_EXEC_1A_1T_1R | AML_CONSTANT),
+ ARGI_TO_DEC_STR_OP, ACPI_TYPE_ANY,
+ AML_CLASS_EXECUTE, AML_TYPE_EXEC_1A_1T_1R,
+ AML_FLAGS_EXEC_1A_1T_1R | AML_CONSTANT),
/* 75 */ ACPI_OP("ToHexString", ARGP_TO_HEX_STR_OP, ARGI_TO_HEX_STR_OP,
- ACPI_TYPE_ANY, AML_CLASS_EXECUTE,
- AML_TYPE_EXEC_1A_1T_1R,
- AML_FLAGS_EXEC_1A_1T_1R | AML_CONSTANT),
+ ACPI_TYPE_ANY, AML_CLASS_EXECUTE,
+ AML_TYPE_EXEC_1A_1T_1R,
+ AML_FLAGS_EXEC_1A_1T_1R | AML_CONSTANT),
/* 76 */ ACPI_OP("ToInteger", ARGP_TO_INTEGER_OP, ARGI_TO_INTEGER_OP,
- ACPI_TYPE_ANY, AML_CLASS_EXECUTE,
- AML_TYPE_EXEC_1A_1T_1R,
- AML_FLAGS_EXEC_1A_1T_1R | AML_CONSTANT),
+ ACPI_TYPE_ANY, AML_CLASS_EXECUTE,
+ AML_TYPE_EXEC_1A_1T_1R,
+ AML_FLAGS_EXEC_1A_1T_1R | AML_CONSTANT),
/* 77 */ ACPI_OP("ToString", ARGP_TO_STRING_OP, ARGI_TO_STRING_OP,
- ACPI_TYPE_ANY, AML_CLASS_EXECUTE,
- AML_TYPE_EXEC_2A_1T_1R,
- AML_FLAGS_EXEC_2A_1T_1R | AML_CONSTANT),
+ ACPI_TYPE_ANY, AML_CLASS_EXECUTE,
+ AML_TYPE_EXEC_2A_1T_1R,
+ AML_FLAGS_EXEC_2A_1T_1R | AML_CONSTANT),
/* 78 */ ACPI_OP("CopyObject", ARGP_COPY_OP, ARGI_COPY_OP,
- ACPI_TYPE_ANY, AML_CLASS_EXECUTE,
- AML_TYPE_EXEC_1A_1T_1R, AML_FLAGS_EXEC_1A_1T_1R),
+ ACPI_TYPE_ANY, AML_CLASS_EXECUTE,
+ AML_TYPE_EXEC_1A_1T_1R, AML_FLAGS_EXEC_1A_1T_1R),
/* 79 */ ACPI_OP("Mid", ARGP_MID_OP, ARGI_MID_OP, ACPI_TYPE_ANY,
- AML_CLASS_EXECUTE, AML_TYPE_EXEC_3A_1T_1R,
- AML_FLAGS_EXEC_3A_1T_1R | AML_CONSTANT),
+ AML_CLASS_EXECUTE, AML_TYPE_EXEC_3A_1T_1R,
+ AML_FLAGS_EXEC_3A_1T_1R | AML_CONSTANT),
/* 7A */ ACPI_OP("Continue", ARGP_CONTINUE_OP, ARGI_CONTINUE_OP,
- ACPI_TYPE_ANY, AML_CLASS_CONTROL, AML_TYPE_CONTROL, 0),
+ ACPI_TYPE_ANY, AML_CLASS_CONTROL, AML_TYPE_CONTROL, 0),
/* 7B */ ACPI_OP("LoadTable", ARGP_LOAD_TABLE_OP, ARGI_LOAD_TABLE_OP,
- ACPI_TYPE_ANY, AML_CLASS_EXECUTE,
- AML_TYPE_EXEC_6A_0T_1R, AML_FLAGS_EXEC_6A_0T_1R),
+ ACPI_TYPE_ANY, AML_CLASS_EXECUTE,
+ AML_TYPE_EXEC_6A_0T_1R, AML_FLAGS_EXEC_6A_0T_1R),
/* 7C */ ACPI_OP("DataTableRegion", ARGP_DATA_REGION_OP,
- ARGI_DATA_REGION_OP, ACPI_TYPE_REGION,
- AML_CLASS_NAMED_OBJECT, AML_TYPE_NAMED_COMPLEX,
- AML_HAS_ARGS | AML_NSOBJECT | AML_NSOPCODE |
- AML_NSNODE | AML_NAMED | AML_DEFER),
+ ARGI_DATA_REGION_OP, ACPI_TYPE_REGION,
+ AML_CLASS_NAMED_OBJECT, AML_TYPE_NAMED_COMPLEX,
+ AML_HAS_ARGS | AML_NSOBJECT | AML_NSOPCODE |
+ AML_NSNODE | AML_NAMED | AML_DEFER),
/* 7D */ ACPI_OP("[EvalSubTree]", ARGP_SCOPE_OP, ARGI_SCOPE_OP,
- ACPI_TYPE_ANY, AML_CLASS_NAMED_OBJECT,
- AML_TYPE_NAMED_NO_OBJ,
- AML_HAS_ARGS | AML_NSOBJECT | AML_NSOPCODE |
+ ACPI_TYPE_ANY, AML_CLASS_NAMED_OBJECT,
+ AML_TYPE_NAMED_NO_OBJ,
+ AML_HAS_ARGS | AML_NSOBJECT | AML_NSOPCODE |
AML_NSNODE),
/* ACPI 3.0 opcodes */
/* 7E */ ACPI_OP("Timer", ARGP_TIMER_OP, ARGI_TIMER_OP, ACPI_TYPE_ANY,
- AML_CLASS_EXECUTE, AML_TYPE_EXEC_0A_0T_1R,
+ AML_CLASS_EXECUTE, AML_TYPE_EXEC_0A_0T_1R,
AML_FLAGS_EXEC_0A_0T_1R),
/* ACPI 5.0 opcodes */
}
/*
- * If the transfer to the new method method call worked, a new walk
- * state was created -- get it
+ * If the transfer to the new method method call worked
+ *, a new walk state was created -- get it
*/
walk_state = acpi_ds_get_current_walk_state(thread);
continue;
/* Check for possible multi-thread reentrancy problem */
if ((status == AE_ALREADY_EXISTS) &&
- (!(walk_state->method_desc->method.
- info_flags & ACPI_METHOD_SERIALIZED))) {
+ (!(walk_state->method_desc->method.info_flags &
+ ACPI_METHOD_SERIALIZED))) {
/*
* Method is not serialized and tried to create an object
* twice. The probable cause is that the method cannot
ACPI_FUNCTION_NAME(ps_free_op);
if (op->common.aml_opcode == AML_INT_RETURN_VALUE_OP) {
- ACPI_DEBUG_PRINT((ACPI_DB_ALLOCATIONS, "Free retval op: %p\n",
- op));
+ ACPI_DEBUG_PRINT((ACPI_DB_ALLOCATIONS,
+ "Free retval op: %p\n", op));
}
if (op->common.flags & ACPI_PARSEOP_GENERIC) {
if (op == subtree_root) {
return_VOID;
}
+
if (next) {
op = next;
} else {
/* Validate the Resource Type */
- if ((aml->address.resource_type > 2)
- && (aml->address.resource_type < 0xC0)) {
+ if ((aml->address.resource_type > 2) &&
+ (aml->address.resource_type < 0xC0)) {
return (FALSE);
}
ACPI_FUNCTION_ENTRY();
/*
- * The resource_source_index and resource_source are optional elements of some
- * Large-type resource descriptors.
+ * The resource_source_index and resource_source are optional elements of
+ * some Large-type resource descriptors.
*/
/*
- * If the length of the actual resource descriptor is greater than the ACPI
- * spec-defined minimum length, it means that a resource_source_index exists
- * and is followed by a (required) null terminated string. The string length
- * (including the null terminator) is the resource length minus the minimum
- * length, minus one byte for the resource_source_index itself.
+ * If the length of the actual resource descriptor is greater than the
+ * ACPI spec-defined minimum length, it means that a resource_source_index
+ * exists and is followed by a (required) null terminated string. The
+ * string length (including the null terminator) is the resource length
+ * minus the minimum length, minus one byte for the resource_source_index
+ * itself.
*/
if (resource_length > minimum_aml_resource_length) {
* 16-Bit Address Resource:
* Add the size of the optional resource_source info
*/
- total_size = (acpi_rs_length)
- (total_size +
- acpi_rs_struct_option_length(&resource->data.
- address16.
- resource_source));
+ total_size = (acpi_rs_length) (total_size +
+ acpi_rs_struct_option_length
+ (&resource->data.
+ address16.
+ resource_source));
break;
case ACPI_RESOURCE_TYPE_ADDRESS32:
* 32-Bit Address Resource:
* Add the size of the optional resource_source info
*/
- total_size = (acpi_rs_length)
- (total_size +
- acpi_rs_struct_option_length(&resource->data.
- address32.
- resource_source));
+ total_size = (acpi_rs_length) (total_size +
+ acpi_rs_struct_option_length
+ (&resource->data.
+ address32.
+ resource_source));
break;
case ACPI_RESOURCE_TYPE_ADDRESS64:
* 64-Bit Address Resource:
* Add the size of the optional resource_source info
*/
- total_size = (acpi_rs_length)
- (total_size +
- acpi_rs_struct_option_length(&resource->data.
- address64.
- resource_source));
+ total_size = (acpi_rs_length) (total_size +
+ acpi_rs_struct_option_length
+ (&resource->data.
+ address64.
+ resource_source));
break;
case ACPI_RESOURCE_TYPE_EXTENDED_IRQ:
* Add the size of each additional optional interrupt beyond the
* required 1 (4 bytes for each u32 interrupt number)
*/
- total_size = (acpi_rs_length)
- (total_size +
- ((resource->data.extended_irq.interrupt_count -
- 1) * 4) +
- /* Add the size of the optional resource_source info */
- acpi_rs_struct_option_length(&resource->data.
- extended_irq.
- resource_source));
+ total_size = (acpi_rs_length) (total_size +
+ ((resource->data.
+ extended_irq.
+ interrupt_count -
+ 1) * 4) +
+ /* Add the size of the optional resource_source info */
+ acpi_rs_struct_option_length
+ (&resource->data.
+ extended_irq.
+ resource_source));
break;
case ACPI_RESOURCE_TYPE_GPIO:
- total_size =
- (acpi_rs_length) (total_size +
- (resource->data.gpio.
- pin_table_length * 2) +
- resource->data.gpio.
- resource_source.string_length +
- resource->data.gpio.
- vendor_length);
+ total_size = (acpi_rs_length) (total_size +
+ (resource->data.gpio.
+ pin_table_length * 2) +
+ resource->data.gpio.
+ resource_source.
+ string_length +
+ resource->data.gpio.
+ vendor_length);
break;
acpi_gbl_resource_struct_sizes[resource_index] +
extra_struct_bytes;
}
- buffer_size = (u32)ACPI_ROUND_UP_TO_NATIVE_WORD(buffer_size);
+ buffer_size = (u32)ACPI_ROUND_UP_TO_NATIVE_WORD(buffer_size);
*size_needed += buffer_size;
ACPI_DEBUG_PRINT((ACPI_DB_RESOURCES,
/* Get the required length for the converted resource */
- status = acpi_rs_get_list_length(aml_buffer, aml_buffer_length,
- &list_size_needed);
+ status =
+ acpi_rs_get_list_length(aml_buffer, aml_buffer_length,
+ &list_size_needed);
if (status == AE_AML_NO_RESOURCE_END_TAG) {
status = AE_OK;
}
/* Get the required buffer length */
- status = acpi_rs_get_pci_routing_table_length(package_object,
- &buffer_size_needed);
+ status =
+ acpi_rs_get_pci_routing_table_length(package_object,
+ &buffer_size_needed);
if (ACPI_FAILURE(status)) {
return_ACPI_STATUS(status);
}
user_prt = ACPI_CAST_PTR(struct acpi_pci_routing_table, buffer);
/*
- * Fill in the Length field with the information we have at this point.
- * The minus four is to subtract the size of the u8 Source[4] member
- * because it is added below.
+ * Fill in the Length field with the information we have at this
+ * point. The minus four is to subtract the size of the u8
+ * Source[4] member because it is added below.
*/
user_prt->length = (sizeof(struct acpi_pci_routing_table) - 4);
(u8 *) output_buffer->pointer);
path_buffer.pointer = user_prt->source;
- status =
- acpi_ns_handle_to_pathname((acpi_handle)
- node,
- &path_buffer,
- FALSE);
+ status = acpi_ns_handle_to_pathname((acpi_handle) node, &path_buffer, FALSE);
/* +1 to include null terminator */
case ACPI_TYPE_INTEGER:
/*
- * If this is a number, then the Source Name is NULL, since the
- * entire buffer was zeroed out, we can leave this alone.
+ * If this is a number, then the Source Name is NULL, since
+ * the entire buffer was zeroed out, we can leave this alone.
*
* Add to the Length field the length of the u32 NULL
*/
/* Get the buffer size needed for the AML byte stream */
- status = acpi_rs_get_aml_length(resource_list->pointer,
- resource_list->length,
- &aml_size_needed);
+ status =
+ acpi_rs_get_aml_length(resource_list->pointer,
+ resource_list->length, &aml_size_needed);
ACPI_DEBUG_PRINT((ACPI_DB_INFO, "AmlSizeNeeded=%X, %s\n",
(u32)aml_size_needed, acpi_format_exception(status)));
static void acpi_rs_out_string(char *title, char *value)
{
+
acpi_os_printf("%27s : %s", title, value);
if (!*value) {
acpi_os_printf("[NULL NAMESTRING]");
static void acpi_rs_out_integer16(char *title, u16 value)
{
+
acpi_os_printf("%27s : %4.4X\n", title, value);
}
static void acpi_rs_out_integer32(char *title, u32 value)
{
+
acpi_os_printf("%27s : %8.8X\n", title, value);
}
static void acpi_rs_out_integer64(char *title, u64 value)
{
+
acpi_os_printf("%27s : %8.8X%8.8X\n", title, ACPI_FORMAT_UINT64(value));
}
static void acpi_rs_out_title(char *title)
{
+
acpi_os_printf("%27s : ", title);
}
for (i = 0; i < length; i++) {
acpi_os_printf("%X ", data[i]);
}
+
acpi_os_printf("\n");
}
/* Get the appropriate conversion info table */
aml_resource = ACPI_CAST_PTR(union aml_resource, aml);
+
if (acpi_ut_get_resource_type(aml) == ACPI_RESOURCE_NAME_SERIAL_BUS) {
if (aml_resource->common_serial_bus.type >
AML_RESOURCE_MAX_SERIALBUSTYPE) {
/* Perform final sanity check on the new AML resource descriptor */
- status = acpi_ut_validate_resource(NULL,
- ACPI_CAST_PTR(union
- aml_resource,
- aml), NULL);
+ status =
+ acpi_ut_validate_resource(NULL,
+ ACPI_CAST_PTR(union aml_resource,
+ aml), NULL);
if (ACPI_FAILURE(status)) {
return_ACPI_STATUS(status);
}
item_count = ACPI_GET8(source);
ACPI_SET8(destination, item_count);
- resource->length = resource->length +
- (info->value * item_count);
+ resource->length =
+ resource->length + (info->value * item_count);
break;
case ACPI_RSC_COUNT_GPIO_RES:
/* Round the resource struct length up to the next boundary (32 or 64) */
- resource->length =
- (u32) ACPI_ROUND_UP_TO_NATIVE_WORD(resource->length);
+ resource->length = (u32)
+ ACPI_ROUND_UP_TO_NATIVE_WORD(resource->length);
}
return_ACPI_STATUS(AE_OK);
}
item_count = ACPI_GET8(source);
ACPI_SET8(destination, item_count);
- aml_length =
- (u16) (aml_length +
- (info->value * (item_count - 1)));
+ aml_length = (u16)
+ (aml_length + (info->value * (item_count - 1)));
break;
case ACPI_RSC_COUNT16:
/*
* 16-bit encoded bitmask (IRQ macro)
*/
- temp16 = acpi_rs_encode_bitmask(source,
- *ACPI_ADD_PTR(u8,
- resource,
- info->
- value));
+ temp16 =
+ acpi_rs_encode_bitmask(source,
+ *ACPI_ADD_PTR(u8, resource,
+ info->value));
ACPI_MOVE_16_TO_16(destination, &temp16);
break;
ACPI_MOVE_16_TO_16(&aml->large_header.resource_length,
&resource_length);
} else {
- /* Small descriptor -- bits 2:0 of byte 0 contain the length */
-
+ /*
+ * Small descriptor -- bits 2:0 of byte 0 contain the length
+ * Clear any existing length, preserving descriptor type bits
+ */
aml->small_header.descriptor_type = (u8)
-
- /* Clear any existing length, preserving descriptor type bits */
- ((aml->small_header.
- descriptor_type & ~ACPI_RESOURCE_NAME_SMALL_LENGTH_MASK)
-
+ ((aml->small_header.descriptor_type &
+ ~ACPI_RESOURCE_NAME_SMALL_LENGTH_MASK)
| resource_length);
}
}
aml_resource_source = ACPI_ADD_PTR(u8, aml, minimum_length);
/*
- * resource_source is present if the length of the descriptor is longer than
- * the minimum length.
+ * resource_source is present if the length of the descriptor is longer
+ * than the minimum length.
*
* Note: Some resource descriptors will have an additional null, so
* we add 1 to the minimum length.
total_length =
(u32)strlen(ACPI_CAST_PTR(char, &aml_resource_source[1])) +
1;
+
total_length = (u32)ACPI_ROUND_UP_TO_NATIVE_WORD(total_length);
memset(resource_source->string_ptr, 0, total_length);
* Add the length of the string (+ 1 for null terminator) to the
* final descriptor length
*/
- descriptor_length +=
- ((acpi_rsdesc_size) resource_source->string_length + 1);
+ descriptor_length += ((acpi_rsdesc_size)
+ resource_source->string_length + 1);
}
/* Return the new total length of the AML descriptor */
/* Execute the method, no parameters */
- status = acpi_ut_evaluate_object(node, METHOD_NAME__PRT,
- ACPI_BTYPE_PACKAGE, &obj_desc);
+ status =
+ acpi_ut_evaluate_object(node, METHOD_NAME__PRT, ACPI_BTYPE_PACKAGE,
+ &obj_desc);
if (ACPI_FAILURE(status)) {
return_ACPI_STATUS(status);
}
/* Execute the method, no parameters */
- status = acpi_ut_evaluate_object(node, METHOD_NAME__CRS,
- ACPI_BTYPE_BUFFER, &obj_desc);
+ status =
+ acpi_ut_evaluate_object(node, METHOD_NAME__CRS, ACPI_BTYPE_BUFFER,
+ &obj_desc);
if (ACPI_FAILURE(status)) {
return_ACPI_STATUS(status);
}
/* Execute the method, no parameters */
- status = acpi_ut_evaluate_object(node, METHOD_NAME__PRS,
- ACPI_BTYPE_BUFFER, &obj_desc);
+ status =
+ acpi_ut_evaluate_object(node, METHOD_NAME__PRS, ACPI_BTYPE_BUFFER,
+ &obj_desc);
if (ACPI_FAILURE(status)) {
return_ACPI_STATUS(status);
}
/* Execute the method, no parameters */
- status = acpi_ut_evaluate_object(node, METHOD_NAME__AEI,
- ACPI_BTYPE_BUFFER, &obj_desc);
+ status =
+ acpi_ut_evaluate_object(node, METHOD_NAME__AEI, ACPI_BTYPE_BUFFER,
+ &obj_desc);
if (ACPI_FAILURE(status)) {
return_ACPI_STATUS(status);
}
/* Local macros for 16,32-bit to 64-bit conversion */
#define ACPI_COPY_FIELD(out, in, field) ((out)->field = (in)->field)
-#define ACPI_COPY_ADDRESS(out, in) \
+#define ACPI_COPY_ADDRESS(out, in) \
ACPI_COPY_FIELD(out, in, resource_type); \
ACPI_COPY_FIELD(out, in, producer_consumer); \
ACPI_COPY_FIELD(out, in, decode); \
table_desc->signature.ascii : "????",
ACPI_FORMAT_UINT64(table_desc->
address)));
+
goto invalidate_and_exit;
}
}
* need to be unregistered when they are unloaded, and slots in the
* root table list should be reused when empty.
*/
- if (acpi_gbl_root_table_list.tables[i].
- flags & ACPI_TABLE_IS_LOADED) {
+ if (acpi_gbl_root_table_list.tables[i].flags &
+ ACPI_TABLE_IS_LOADED) {
/* Table is still loaded, this is an error */
if (!isprint((int)*string)) {
*string = '?';
}
+
string++;
length--;
}
ACPI_BIOS_ERROR((AE_INFO,
"The DSDT has been corrupted or replaced - "
"old, new headers below"));
+
acpi_tb_print_table_header(0, &acpi_gbl_original_dsdt_header);
acpi_tb_print_table_header(0, acpi_gbl_DSDT);
}
acpi_os_unmap_memory(table, length);
-
return_ACPI_STATUS(AE_OK);
}
*
* PARAMETERS: signature - Sig string to be validated
*
- * RETURN: TRUE if signature is correct length and has valid characters
+ * RETURN: TRUE if signature is has 4 valid ACPI characters
*
* DESCRIPTION: Validate an ACPI table 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++) {
"(%4.4s:%8.8s) while loading table",
table->signature.ascii,
table->pointer->oem_table_id));
+
tables_failed++;
ACPI_DEBUG_PRINT_RAW((ACPI_DB_INIT,
if (!tables_failed) {
ACPI_INFO((AE_INFO,
- "%u ACPI AML tables successfully acquired and loaded",
+ "%u ACPI AML tables successfully acquired and loaded\n",
tables_loaded));
} else {
ACPI_ERROR((AE_INFO,
overlap_count++;
if (warn) { /* Optional warning message */
pathname =
- acpi_ns_get_external_pathname(range_info->
- region_node);
+ acpi_ns_get_normalized_pathname(range_info->
+ region_node,
+ TRUE);
ACPI_WARNING((AE_INFO,
"%s range 0x%8.8X%8.8X-0x%8.8X%8.8X conflicts with OpRegion 0x%8.8X%8.8X-0x%8.8X%8.8X (%s)",
ACPI_FUNCTION_ENTRY();
this_index = state->pkg.index;
- target_object = (union acpi_object *)
- &((union acpi_object *)(state->pkg.dest_object))->package.
- elements[this_index];
+ target_object = (union acpi_object *)&((union acpi_object *)
+ (state->pkg.dest_object))->
+ package.elements[this_index];
switch (object_type) {
case ACPI_COPY_TYPE_SIMPLE:
* Free space begins right after the first package
*/
info.length = ACPI_ROUND_UP_TO_NATIVE_WORD(sizeof(union acpi_object));
- info.free_space =
- buffer + ACPI_ROUND_UP_TO_NATIVE_WORD(sizeof(union acpi_object));
+ info.free_space = buffer +
+ ACPI_ROUND_UP_TO_NATIVE_WORD(sizeof(union acpi_object));
info.object_space = 0;
info.num_packages = 1;
external_object->type = internal_object->common.type;
external_object->package.count = internal_object->package.count;
- external_object->package.elements = ACPI_CAST_PTR(union acpi_object,
- info.free_space);
+ external_object->package.elements =
+ ACPI_CAST_PTR(union acpi_object, info.free_space);
/*
* Leave room for an array of ACPI_OBJECTS in the buffer
package_elements = package_object->package.elements;
/*
- * Recursive implementation. Probably ok, since nested external packages
- * as parameters should be very rare.
+ * Recursive implementation. Probably ok, since nested external
+ * packages as parameters should be very rare.
*/
for (i = 0; i < external_object->package.count; i++) {
status =
/*
* Build a simple object (no nested objects)
*/
- status =
- acpi_ut_copy_esimple_to_isimple(external_object,
- internal_object);
+ status = acpi_ut_copy_esimple_to_isimple(external_object,
+ internal_object);
}
return_ACPI_STATUS(status);
"PCC" /* 0x0A */
};
-char *acpi_ut_get_region_name(u8 space_id)
+const char *acpi_ut_get_region_name(u8 space_id)
{
if (space_id >= ACPI_USER_REGION_BEGIN) {
return ("InvalidSpaceId");
}
- return (ACPI_CAST_PTR(char, acpi_gbl_region_types[space_id]));
+ return (acpi_gbl_region_types[space_id]);
}
/*******************************************************************************
"RealTimeClock",
};
-char *acpi_ut_get_event_name(u32 event_id)
+const char *acpi_ut_get_event_name(u32 event_id)
{
if (event_id > ACPI_EVENT_MAX) {
return ("InvalidEventID");
}
- return (ACPI_CAST_PTR(char, acpi_gbl_event_types[event_id]));
+ return (acpi_gbl_event_types[event_id]);
}
/*******************************************************************************
*
* The type ACPI_TYPE_ANY (Untyped) is used as a "don't care" when searching;
* when stored in a table it really means that we have thus far seen no
- * evidence to indicate what type is actually going to be stored for this entry.
+ * evidence to indicate what type is actually going to be stored for this
+ & entry.
*/
static const char acpi_gbl_bad_type[] = "UNDEFINED";
/* 30 */ "Invalid"
};
-char *acpi_ut_get_type_name(acpi_object_type type)
+const char *acpi_ut_get_type_name(acpi_object_type type)
{
if (type > ACPI_TYPE_INVALID) {
- return (ACPI_CAST_PTR(char, acpi_gbl_bad_type));
+ return (acpi_gbl_bad_type);
}
- return (ACPI_CAST_PTR(char, acpi_gbl_ns_type_names[type]));
+ return (acpi_gbl_ns_type_names[type]);
}
-char *acpi_ut_get_object_type_name(union acpi_operand_object *obj_desc)
+const char *acpi_ut_get_object_type_name(union acpi_operand_object *obj_desc)
{
ACPI_FUNCTION_TRACE(ut_get_object_type_name);
*
******************************************************************************/
-char *acpi_ut_get_node_name(void *object)
+const char *acpi_ut_get_node_name(void *object)
{
struct acpi_namespace_node *node = (struct acpi_namespace_node *)object;
/* 15 */ "Node"
};
-char *acpi_ut_get_descriptor_name(void *object)
+const char *acpi_ut_get_descriptor_name(void *object)
{
if (!object) {
return ("Not a Descriptor");
}
- return (ACPI_CAST_PTR(char,
- acpi_gbl_desc_type_names[ACPI_GET_DESCRIPTOR_TYPE
- (object)]));
-
+ return (acpi_gbl_desc_type_names[ACPI_GET_DESCRIPTOR_TYPE(object)]);
}
/*******************************************************************************
/* Names for internal mutex objects, used for debug output */
-static char *acpi_gbl_mutex_names[ACPI_NUM_MUTEX] = {
+static const char *acpi_gbl_mutex_names[ACPI_NUM_MUTEX] = {
"ACPI_MTX_Interpreter",
"ACPI_MTX_Namespace",
"ACPI_MTX_Tables",
"ACPI_MTX_Memory",
};
-char *acpi_ut_get_mutex_name(u32 mutex_id)
+const char *acpi_ut_get_mutex_name(u32 mutex_id)
{
if (mutex_id > ACPI_MAX_MUTEX) {
acpi_ut_delete_object_desc(object->method.mutex);
object->method.mutex = NULL;
}
+
if (object->method.node) {
object->method.node = NULL;
}
}
/*
- * All sub-objects must have their reference count incremented also.
- * Different object types have different subobjects.
+ * All sub-objects must have their reference count incremented
+ * also. Different object types have different subobjects.
*/
switch (object->common.type) {
case ACPI_TYPE_DEVICE:
} else {
/* Convert path to external format */
- status = acpi_ns_externalize_name(ACPI_UINT32_MAX,
- internal_name, NULL, &name);
+ status =
+ acpi_ns_externalize_name(ACPI_UINT32_MAX, internal_name,
+ NULL, &name);
/* Print target name */
acpi_os_printf(ACPI_MSG_ERROR);
if (path) {
- status =
- acpi_ns_get_node(prefix_node, path, ACPI_NS_NO_UPSEARCH,
- &node);
+ status = acpi_ns_get_node(prefix_node, path,
+ ACPI_NS_NO_UPSEARCH, &node);
if (ACPI_FAILURE(status)) {
acpi_os_printf("[Could not get node by pathname]");
}
+++ /dev/null
-/*******************************************************************************
- *
- * Module Name: utfileio - simple file I/O routines
- *
- ******************************************************************************/
-
-/*
- * 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 "actables.h"
-#include "acapps.h"
-#include "errno.h"
-
-#ifdef ACPI_ASL_COMPILER
-#include "aslcompiler.h"
-#endif
-
-#define _COMPONENT ACPI_CA_DEBUGGER
-ACPI_MODULE_NAME("utfileio")
-
-#ifdef ACPI_APPLICATION
-/* Local prototypes */
-static acpi_status
-acpi_ut_check_text_mode_corruption(u8 *table,
- u32 table_length, u32 file_length);
-
-static acpi_status
-acpi_ut_read_table(FILE * fp,
- struct acpi_table_header **table, u32 *table_length);
-
-/*******************************************************************************
- *
- * FUNCTION: acpi_ut_check_text_mode_corruption
- *
- * PARAMETERS: table - Table buffer
- * table_length - Length of table from the table header
- * file_length - Length of the file that contains the table
- *
- * RETURN: Status
- *
- * DESCRIPTION: Check table for text mode file corruption where all linefeed
- * characters (LF) have been replaced by carriage return linefeed
- * pairs (CR/LF).
- *
- ******************************************************************************/
-
-static acpi_status
-acpi_ut_check_text_mode_corruption(u8 *table, u32 table_length, u32 file_length)
-{
- u32 i;
- u32 pairs = 0;
-
- if (table_length != file_length) {
- ACPI_WARNING((AE_INFO,
- "File length (0x%X) is not the same as the table length (0x%X)",
- file_length, table_length));
- }
-
- /* Scan entire table to determine if each LF has been prefixed with a CR */
-
- for (i = 1; i < file_length; i++) {
- if (table[i] == 0x0A) {
- if (table[i - 1] != 0x0D) {
-
- /* The LF does not have a preceding CR, table not corrupted */
-
- return (AE_OK);
- } else {
- /* Found a CR/LF pair */
-
- pairs++;
- }
- i++;
- }
- }
-
- if (!pairs) {
- return (AE_OK);
- }
-
- /*
- * Entire table scanned, each CR is part of a CR/LF pair --
- * meaning that the table was treated as a text file somewhere.
- *
- * NOTE: We can't "fix" the table, because any existing CR/LF pairs in the
- * original table are left untouched by the text conversion process --
- * meaning that we cannot simply replace CR/LF pairs with LFs.
- */
- acpi_os_printf("Table has been corrupted by text mode conversion\n");
- acpi_os_printf("All LFs (%u) were changed to CR/LF pairs\n", pairs);
- acpi_os_printf("Table cannot be repaired!\n");
- return (AE_BAD_VALUE);
-}
-
-/*******************************************************************************
- *
- * FUNCTION: acpi_ut_read_table
- *
- * PARAMETERS: fp - File that contains table
- * table - Return value, buffer with table
- * table_length - Return value, length of table
- *
- * RETURN: Status
- *
- * DESCRIPTION: Load the DSDT from the file pointer
- *
- ******************************************************************************/
-
-static acpi_status
-acpi_ut_read_table(FILE * fp,
- struct acpi_table_header **table, u32 *table_length)
-{
- struct acpi_table_header table_header;
- u32 actual;
- acpi_status status;
- u32 file_size;
- u8 standard_header = TRUE;
- s32 count;
-
- /* Get the file size */
-
- file_size = cm_get_file_size(fp);
- if (file_size == ACPI_UINT32_MAX) {
- return (AE_ERROR);
- }
-
- if (file_size < 4) {
- return (AE_BAD_HEADER);
- }
-
- /* Read the signature */
-
- fseek(fp, 0, SEEK_SET);
-
- count = fread(&table_header, 1, sizeof(struct acpi_table_header), fp);
- if (count != sizeof(struct acpi_table_header)) {
- acpi_os_printf("Could not read the table header\n");
- return (AE_BAD_HEADER);
- }
-
- /* The RSDP table does not have standard ACPI header */
-
- if (ACPI_VALIDATE_RSDP_SIG(table_header.signature)) {
- *table_length = file_size;
- standard_header = FALSE;
- } else {
-
-#if 0
- /* Validate the table header/length */
-
- status = acpi_tb_validate_table_header(&table_header);
- if (ACPI_FAILURE(status)) {
- acpi_os_printf("Table header is invalid!\n");
- return (status);
- }
-#endif
-
- /* File size must be at least as long as the Header-specified length */
-
- if (table_header.length > file_size) {
- acpi_os_printf
- ("TableHeader length [0x%X] greater than the input file size [0x%X]\n",
- table_header.length, file_size);
-
-#ifdef ACPI_ASL_COMPILER
- acpi_os_printf("File is corrupt or is ASCII text -- "
- "it must be a binary file\n");
-#endif
- return (AE_BAD_HEADER);
- }
-#ifdef ACPI_OBSOLETE_CODE
- /* We only support a limited number of table types */
-
- if (!ACPI_COMPARE_NAME
- ((char *)table_header.signature, ACPI_SIG_DSDT)
- && !ACPI_COMPARE_NAME((char *)table_header.signature,
- ACPI_SIG_PSDT)
- && !ACPI_COMPARE_NAME((char *)table_header.signature,
- ACPI_SIG_SSDT)) {
- acpi_os_printf
- ("Table signature [%4.4s] is invalid or not supported\n",
- (char *)table_header.signature);
- ACPI_DUMP_BUFFER(&table_header,
- sizeof(struct acpi_table_header));
- return (AE_ERROR);
- }
-#endif
-
- *table_length = table_header.length;
- }
-
- /* Allocate a buffer for the table */
-
- *table = acpi_os_allocate((size_t) file_size);
- if (!*table) {
- acpi_os_printf
- ("Could not allocate memory for ACPI table %4.4s (size=0x%X)\n",
- table_header.signature, *table_length);
- return (AE_NO_MEMORY);
- }
-
- /* Get the rest of the table */
-
- fseek(fp, 0, SEEK_SET);
- actual = fread(*table, 1, (size_t) file_size, fp);
- if (actual == file_size) {
- if (standard_header) {
-
- /* Now validate the checksum */
-
- status = acpi_tb_verify_checksum((void *)*table,
- ACPI_CAST_PTR(struct
- acpi_table_header,
- *table)->
- length);
-
- if (status == AE_BAD_CHECKSUM) {
- status =
- acpi_ut_check_text_mode_corruption((u8 *)
- *table,
- file_size,
- (*table)->
- length);
- return (status);
- }
- }
- return (AE_OK);
- }
-
- if (actual > 0) {
- acpi_os_printf("Warning - reading table, asked for %X got %X\n",
- file_size, actual);
- return (AE_OK);
- }
-
- acpi_os_printf("Error - could not read the table file\n");
- acpi_os_free(*table);
- *table = NULL;
- *table_length = 0;
- return (AE_ERROR);
-}
-
-/*******************************************************************************
- *
- * FUNCTION: acpi_ut_read_table_from_file
- *
- * PARAMETERS: filename - File where table is located
- * table - Where a pointer to the table is returned
- *
- * RETURN: Status
- *
- * DESCRIPTION: Get an ACPI table from a file
- *
- ******************************************************************************/
-
-acpi_status
-acpi_ut_read_table_from_file(char *filename, struct acpi_table_header ** table)
-{
- FILE *file;
- u32 file_size;
- u32 table_length;
- acpi_status status = AE_ERROR;
-
- /* Open the file, get current size */
-
- file = fopen(filename, "rb");
- if (!file) {
- perror("Could not open input file");
-
- if (errno == ENOENT) {
- return (AE_NOT_EXIST);
- }
-
- return (status);
- }
-
- file_size = cm_get_file_size(file);
- if (file_size == ACPI_UINT32_MAX) {
- goto exit;
- }
-
- /* Get the entire file */
-
- fprintf(stderr,
- "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);
- if (ACPI_FAILURE(status)) {
- acpi_os_printf("Could not get table from the file\n");
- }
-
-exit:
- fclose(file);
- return (status);
-}
-
-#endif
ACPI_MODULE_NAME("uthex")
/* Hex to ASCII conversion table */
-static char acpi_gbl_hex_to_ascii[] = {
+static const char acpi_gbl_hex_to_ascii[] = {
'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D',
'E', 'F'
};
return_ACPI_STATUS(status);
}
-/*******************************************************************************
- *
- * FUNCTION: acpi_ut_execute_SUB
- *
- * PARAMETERS: device_node - Node for the device
- * return_id - Where the _SUB is returned
- *
- * RETURN: Status
- *
- * DESCRIPTION: Executes the _SUB control method that returns the subsystem
- * ID of the device. The _SUB value is always a string containing
- * either a valid PNP or ACPI ID.
- *
- * NOTE: Internal function, no parameter validation
- *
- ******************************************************************************/
-
-acpi_status
-acpi_ut_execute_SUB(struct acpi_namespace_node *device_node,
- struct acpi_pnp_device_id **return_id)
-{
- union acpi_operand_object *obj_desc;
- struct acpi_pnp_device_id *sub;
- u32 length;
- acpi_status status;
-
- ACPI_FUNCTION_TRACE(ut_execute_SUB);
-
- status = acpi_ut_evaluate_object(device_node, METHOD_NAME__SUB,
- ACPI_BTYPE_STRING, &obj_desc);
- if (ACPI_FAILURE(status)) {
- return_ACPI_STATUS(status);
- }
-
- /* Get the size of the String to be returned, includes null terminator */
-
- length = obj_desc->string.length + 1;
-
- /* Allocate a buffer for the SUB */
-
- sub =
- ACPI_ALLOCATE_ZEROED(sizeof(struct acpi_pnp_device_id) +
- (acpi_size) length);
- if (!sub) {
- status = AE_NO_MEMORY;
- goto cleanup;
- }
-
- /* Area for the string starts after PNP_DEVICE_ID struct */
-
- sub->string =
- ACPI_ADD_PTR(char, sub, sizeof(struct acpi_pnp_device_id));
-
- /* Simply copy existing string */
-
- strcpy(sub->string, obj_desc->string.pointer);
- sub->length = length;
- *return_id = sub;
-
-cleanup:
-
- /* On exit, we must delete the return object */
-
- acpi_ut_remove_reference(obj_desc);
- return_ACPI_STATUS(status);
-}
-
/*******************************************************************************
*
* FUNCTION: acpi_ut_execute_UID
acpi_gbl_next_owner_id_offset = 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 */
*/
ACPI_DIV_64_BY_32(0, dividend_ovl.part.hi, divisor,
quotient.part.hi, remainder32);
+
ACPI_DIV_64_BY_32(remainder32, dividend_ovl.part.lo, divisor,
quotient.part.lo, remainder32);
*/
ACPI_DIV_64_BY_32(0, dividend.part.hi, divisor.part.lo,
quotient.part.hi, partial1);
+
ACPI_DIV_64_BY_32(partial1, dividend.part.lo, divisor.part.lo,
quotient.part.lo, remainder.part.lo);
}
ACPI_DIV_64_BY_32(normalized_dividend.part.hi,
normalized_dividend.part.lo,
- normalized_divisor.part.lo,
- quotient.part.lo, partial1);
+ normalized_divisor.part.lo, quotient.part.lo,
+ partial1);
/*
- * The quotient is always 32 bits, and simply requires adjustment.
- * The 64-bit remainder must be generated.
+ * The quotient is always 32 bits, and simply requires
+ * adjustment. The 64-bit remainder must be generated.
*/
partial1 = quotient.part.lo * divisor.part.hi;
partial2.full = (u64) quotient.part.lo * divisor.part.lo;
*/
if ((!this_source_obj) ||
(ACPI_GET_DESCRIPTOR_TYPE(this_source_obj) !=
- ACPI_DESC_TYPE_OPERAND)
- || (this_source_obj->common.type != ACPI_TYPE_PACKAGE)) {
+ ACPI_DESC_TYPE_OPERAND) ||
+ (this_source_obj->common.type != ACPI_TYPE_PACKAGE)) {
status =
walk_callback(ACPI_COPY_TYPE_SIMPLE,
this_source_obj, state, context);
* The callback above returned a new target package object.
*/
acpi_ut_push_generic_state(&state_list, state);
- state = acpi_ut_create_pkg_state(this_source_obj,
- state->pkg.
- this_target_obj, 0);
+ state =
+ acpi_ut_create_pkg_state(this_source_obj,
+ state->pkg.this_target_obj,
+ 0);
if (!state) {
/* Free any stacked Update State objects */
if (ACPI_FAILURE(status)) {
return_ACPI_STATUS(status);
}
-#ifdef ACPI_DEBUGGER
-
- /* Debugger Support */
-
- status = acpi_os_create_mutex(&acpi_gbl_db_command_ready);
- if (ACPI_FAILURE(status)) {
- return_ACPI_STATUS(status);
- }
-
- status = acpi_os_create_mutex(&acpi_gbl_db_command_complete);
-#endif
return_ACPI_STATUS(status);
}
/* Delete the reader/writer lock */
acpi_ut_delete_rw_lock(&acpi_gbl_namespace_rw_lock);
-
-#ifdef ACPI_DEBUGGER
- acpi_os_delete_mutex(acpi_gbl_db_command_ready);
- acpi_os_delete_mutex(acpi_gbl_db_command_complete);
-#endif
-
return_VOID;
}
(u32)this_thread_id,
acpi_ut_get_mutex_name(mutex_id)));
- status = acpi_os_acquire_mutex(acpi_gbl_mutex_info[mutex_id].mutex,
- ACPI_WAIT_FOREVER);
+ status =
+ acpi_os_acquire_mutex(acpi_gbl_mutex_info[mutex_id].mutex,
+ ACPI_WAIT_FOREVER);
if (ACPI_SUCCESS(status)) {
ACPI_DEBUG_PRINT((ACPI_DB_MUTEX,
"Thread %u acquired Mutex [%s]\n",
/* Divide the digit into the correct position */
- (void)acpi_ut_short_divide((dividend - (u64)this_digit),
- base, "ient, NULL);
+ (void)acpi_ut_short_divide((dividend - (u64)this_digit), base,
+ "ient, NULL);
if (return_value > quotient) {
if (to_integer_op) {
/* These types require a secondary object */
- second_object = acpi_ut_allocate_object_desc_dbg(module_name,
- line_number,
- component_id);
+ second_object =
+ acpi_ut_allocate_object_desc_dbg(module_name, line_number,
+ component_id);
if (!second_object) {
acpi_ut_delete_object_desc(object);
return_PTR(NULL);
buffer = ACPI_ALLOCATE_ZEROED(buffer_size);
if (!buffer) {
ACPI_ERROR((AE_INFO, "Could not allocate size %u",
- (u32) buffer_size));
+ (u32)buffer_size));
+
acpi_ut_remove_reference(buffer_desc);
return_PTR(NULL);
}
string = ACPI_ALLOCATE_ZEROED(string_size + 1);
if (!string) {
ACPI_ERROR((AE_INFO, "Could not allocate size %u",
- (u32) string_size));
+ (u32)string_size));
+
acpi_ut_remove_reference(string_desc);
return_PTR(NULL);
}
info.object_space = 0;
info.num_packages = 1;
- status = acpi_ut_walk_package_tree(internal_object, NULL,
- acpi_ut_get_element_length, &info);
+ status =
+ acpi_ut_walk_package_tree(internal_object, NULL,
+ acpi_ut_get_element_length, &info);
if (ACPI_FAILURE(status)) {
return_ACPI_STATUS(status);
}
* just add the length of the package objects themselves.
* Round up to the next machine word.
*/
- info.length += ACPI_ROUND_UP_TO_NATIVE_WORD(sizeof(union acpi_object)) *
+ info.length +=
+ ACPI_ROUND_UP_TO_NATIVE_WORD(sizeof(union acpi_object)) *
(acpi_size) info.num_packages;
/* Return the total package length */
ACPI_FUNCTION_ENTRY();
if ((ACPI_GET_DESCRIPTOR_TYPE(internal_object) ==
- ACPI_DESC_TYPE_OPERAND)
- && (internal_object->common.type == ACPI_TYPE_PACKAGE)) {
+ ACPI_DESC_TYPE_OPERAND) &&
+ (internal_object->common.type == ACPI_TYPE_PACKAGE)) {
status =
acpi_ut_get_package_object_size(internal_object,
obj_length);
previous_interface = next_interface = acpi_gbl_supported_interfaces;
while (next_interface) {
if (!strcmp(interface_name, next_interface->name)) {
-
- /* Found: name is in either the static list or was added at runtime */
-
+ /*
+ * Found: name is in either the static list
+ * or was added at runtime
+ */
if (next_interface->flags & ACPI_OSI_DYNAMIC) {
/* Interface was added dynamically, remove and free it */
ACPI_FREE(next_interface);
} else {
/*
- * Interface is in static list. If marked invalid, then it
- * does not actually exist. Else, mark it invalid.
+ * Interface is in static list. If marked invalid, then
+ * it does not actually exist. Else, mark it invalid.
*/
if (next_interface->flags & ACPI_OSI_INVALID) {
return (AE_NOT_EXIST);
/* Guard against multiple allocations of ID to the same location */
if (*owner_id) {
- ACPI_ERROR((AE_INFO, "Owner ID [0x%2.2X] already exists",
- *owner_id));
+ ACPI_ERROR((AE_INFO,
+ "Owner ID [0x%2.2X] already exists", *owner_id));
return_ACPI_STATUS(AE_ALREADY_EXISTS);
}
/*
* Find a free owner ID, cycle through all possible IDs on repeated
- * allocations. (ACPI_NUM_OWNERID_MASKS + 1) because first index may have
- * to be scanned twice.
+ * allocations. (ACPI_NUM_OWNERID_MASKS + 1) because first index
+ * may have to be scanned twice.
*/
for (i = 0, j = acpi_gbl_last_owner_id_index;
i < (ACPI_NUM_OWNERID_MASKS + 1); i++, j++) {
* they are released when a table is unloaded or a method completes
* execution.
*
- * If this error happens, there may be very deep nesting of invoked control
- * methods, or there may be a bug where the IDs are not released.
+ * If this error happens, there may be very deep nesting of invoked
+ * control methods, or there may be a bug where the IDs are not released.
*/
status = AE_OWNER_ID_LIMIT;
ACPI_ERROR((AE_INFO,
{
const union acpi_predefined_info *this_name;
- /* Quick check for a predefined name, first character must be underscore */
-
+ /*
+ * Quick check for a predefined name, first character must
+ * be underscore
+ */
if (name[0] != '_') {
return (NULL);
}
if (need_prefix) {
string = acpi_ut_bound_string_output(string, end, '0');
if (base == 16) {
- string = acpi_ut_bound_string_output(string, end,
- upper ? 'X' : 'x');
+ string =
+ acpi_ut_bound_string_output(string, end,
+ upper ? 'X' : 'x');
}
}
if (!(type & ACPI_FORMAT_LEFT)) {
} else {
break;
}
+
} while (1);
/* Process width */
++format;
precision = va_arg(args, int);
}
+
if (precision < 0) {
precision = 0;
}
' ');
}
}
+
for (i = 0; i < length; ++i) {
pos = acpi_ut_bound_string_output(pos, end, *s);
++s;
}
+
while (length < width--) {
pos =
acpi_ut_bound_string_output(pos, end, ' ');
}
p = va_arg(args, void *);
- pos = acpi_ut_format_number(pos, end,
- ACPI_TO_INTEGER(p), 16,
- width, precision, type);
+ pos =
+ acpi_ut_format_number(pos, end, ACPI_TO_INTEGER(p),
+ 16, width, precision, type);
continue;
default:
acpi_ut_validate_resource(walk_state, aml, &resource_index);
if (ACPI_FAILURE(status)) {
/*
- * Exit on failure. Cannot continue because the descriptor length
- * may be bogus also.
+ * Exit on failure. Cannot continue because the descriptor
+ * length may be bogus also.
*/
return_ACPI_STATUS(status);
}
}
/*
- * Check validity of the resource type, via acpi_gbl_resource_types. Zero
- * indicates an invalid resource.
+ * Check validity of the resource type, via acpi_gbl_resource_types.
+ * Zero indicates an invalid resource.
*/
if (!acpi_gbl_resource_types[resource_index]) {
goto invalid_resource;
state->pkg.dest_object = external_object;
state->pkg.index = index;
state->pkg.num_packages = 1;
+
return (state);
}
state->common.descriptor_type = ACPI_DESC_TYPE_STATE_CONTROL;
state->common.state = ACPI_CONTROL_CONDITIONAL_EXECUTING;
+
return (state);
}
if (state) {
(void)acpi_os_release_object(acpi_gbl_state_cache, state);
}
+
return;
}
break;
}
}
+
acpi_os_printf("\"");
if (i == max_length && string[i]) {
ACPI_FUNCTION_NAME(ut_repair_name);
+ /*
+ * Special case for the root node. This can happen if we get an
+ * error during the execution of module-level code.
+ */
+ if (ACPI_COMPARE_NAME(name, "\\___")) {
+ return;
+ }
+
ACPI_MOVE_NAME(&original_name, name);
/* Check each character in the name */
return (NULL);
}
- status = acpi_ut_track_allocation(allocation, size,
- ACPI_MEM_MALLOC, component, module,
- line);
+ status =
+ acpi_ut_track_allocation(allocation, size, ACPI_MEM_MALLOC,
+ component, module, line);
if (ACPI_FAILURE(status)) {
acpi_os_free(allocation);
return (NULL);
acpi_gbl_global_list->total_allocated++;
acpi_gbl_global_list->total_size += (u32)size;
acpi_gbl_global_list->current_total_size += (u32)size;
+
if (acpi_gbl_global_list->current_total_size >
acpi_gbl_global_list->max_occupied) {
acpi_gbl_global_list->max_occupied =
acpi_gbl_global_list->total_allocated++;
acpi_gbl_global_list->total_size += (u32)size;
acpi_gbl_global_list->current_total_size += (u32)size;
+
if (acpi_gbl_global_list->current_total_size >
acpi_gbl_global_list->max_occupied) {
acpi_gbl_global_list->max_occupied =
acpi_gbl_global_list->total_freed++;
acpi_gbl_global_list->current_total_size -= debug_block->size;
- status = acpi_ut_remove_allocation(debug_block,
- component, module, line);
+ status =
+ acpi_ut_remove_allocation(debug_block, component, module, line);
if (ACPI_FAILURE(status)) {
ACPI_EXCEPTION((AE_INFO, status, "Could not free memory"));
}
/*
ACPI_DEBUG_PRINT (TRACE_ALLOCATIONS | TRACE_TABLES,
- ("%30s: %4d (%3d Kb)\n", "Current allocations",
- mem_list->current_count,
- ROUND_UP_TO_1K (mem_list->current_size)));
+ ("%30s: %4d (%3d Kb)\n", "Current allocations",
+ mem_list->current_count,
+ ROUND_UP_TO_1K (mem_list->current_size)));
ACPI_DEBUG_PRINT (TRACE_ALLOCATIONS | TRACE_TABLES,
- ("%30s: %4d (%3d Kb)\n", "Max concurrent allocations",
- mem_list->max_concurrent_count,
- ROUND_UP_TO_1K (mem_list->max_concurrent_size)));
+ ("%30s: %4d (%3d Kb)\n", "Max concurrent allocations",
+ mem_list->max_concurrent_count,
+ ROUND_UP_TO_1K (mem_list->max_concurrent_size)));
ACPI_DEBUG_PRINT (TRACE_ALLOCATIONS | TRACE_TABLES,
- ("%30s: %4d (%3d Kb)\n", "Total (all) internal objects",
- running_object_count,
- ROUND_UP_TO_1K (running_object_size)));
+ ("%30s: %4d (%3d Kb)\n", "Total (all) internal objects",
+ running_object_count,
+ ROUND_UP_TO_1K (running_object_size)));
ACPI_DEBUG_PRINT (TRACE_ALLOCATIONS | TRACE_TABLES,
- ("%30s: %4d (%3d Kb)\n", "Total (all) allocations",
- running_alloc_count,
- ROUND_UP_TO_1K (running_alloc_size)));
+ ("%30s: %4d (%3d Kb)\n", "Total (all) allocations",
+ running_alloc_count,
+ ROUND_UP_TO_1K (running_alloc_size)));
ACPI_DEBUG_PRINT (TRACE_ALLOCATIONS | TRACE_TABLES,
- ("%30s: %4d (%3d Kb)\n", "Current Nodes",
- acpi_gbl_current_node_count,
- ROUND_UP_TO_1K (acpi_gbl_current_node_size)));
+ ("%30s: %4d (%3d Kb)\n", "Current Nodes",
+ acpi_gbl_current_node_count,
+ ROUND_UP_TO_1K (acpi_gbl_current_node_size)));
ACPI_DEBUG_PRINT (TRACE_ALLOCATIONS | TRACE_TABLES,
- ("%30s: %4d (%3d Kb)\n", "Max Nodes",
- acpi_gbl_max_concurrent_node_count,
- ROUND_UP_TO_1K ((acpi_gbl_max_concurrent_node_count *
- sizeof (struct acpi_namespace_node)))));
+ ("%30s: %4d (%3d Kb)\n", "Max Nodes",
+ acpi_gbl_max_concurrent_node_count,
+ ROUND_UP_TO_1K ((acpi_gbl_max_concurrent_node_count *
+ sizeof (struct acpi_namespace_node)))));
*/
return_VOID;
}
* Populate the return buffer
*/
info_ptr = (struct acpi_system_info *)out_buffer->pointer;
-
info_ptr->acpi_ca_version = ACPI_CA_VERSION;
/* System flags (ACPI capabilities) */
/* Other counters */
stats->method_count = acpi_method_count;
-
return_ACPI_STATUS(AE_OK);
}
acpi_os_printf(ACPI_MSG_EXCEPTION "%s, ",
acpi_format_exception(status));
}
+
va_start(arg_list, format);
acpi_os_vprintf(format, arg_list);
ACPI_MSG_SUFFIX;
ACPI_FUNCTION_TRACE(acpi_enable_subsystem);
+ /*
+ * The early initialization phase is complete. The namespace is loaded,
+ * and we can now support address spaces other than Memory, I/O, and
+ * PCI_Config.
+ */
+ acpi_gbl_early_initialization = FALSE;
+
+ /*
+ * Install the default operation region handlers. These are the
+ * handlers that are defined by the ACPI specification to be
+ * "always accessible" -- namely, system_memory, system_IO, and
+ * PCI_Config. This also means that no _REG methods need to be
+ * run for these address spaces. We need to have these handlers
+ * installed before any AML code can be executed, especially any
+ * module-level code (11/2015).
+ */
+ status = acpi_ev_install_region_handlers();
+ if (ACPI_FAILURE(status)) {
+ ACPI_EXCEPTION((AE_INFO, status,
+ "During Region initialization"));
+ return_ACPI_STATUS(status);
+ }
#if (!ACPI_REDUCED_HARDWARE)
/* Enable ACPI mode */
return_ACPI_STATUS(status);
}
}
-#endif /* !ACPI_REDUCED_HARDWARE */
-
- /*
- * Install the default op_region handlers. These are installed unless
- * other handlers have already been installed via the
- * install_address_space_handler interface.
- */
- if (!(flags & ACPI_NO_ADDRESS_SPACE_INIT)) {
- ACPI_DEBUG_PRINT((ACPI_DB_EXEC,
- "[Init] Installing default address space handlers\n"));
- status = acpi_ev_install_region_handlers();
- if (ACPI_FAILURE(status)) {
- return_ACPI_STATUS(status);
- }
- }
-#if (!ACPI_REDUCED_HARDWARE)
/*
* Initialize ACPI Event handling (Fixed and General Purpose)
*
* initialized, even if they contain executable AML (see the call to
* acpi_ns_initialize_objects below).
*/
+ acpi_gbl_reg_methods_enabled = TRUE;
if (!(flags & ACPI_NO_ADDRESS_SPACE_INIT)) {
ACPI_DEBUG_PRINT((ACPI_DB_EXEC,
"[Init] Executing _REG OpRegion methods\n"));
* outside of any control method is wrapped with a temporary control
* method object and placed on a global list. The methods on this list
* are executed below.
+ *
+ * This case executes the module-level code for all tables only after
+ * all of the tables have been loaded. It is a legacy option and is
+ * not compatible with other ACPI implementations. See acpi_ns_load_table.
*/
- acpi_ns_exec_module_code_list();
+ if (acpi_gbl_group_module_level_code) {
+ acpi_ns_exec_module_code_list();
+ }
/*
* Initialize the objects that remain uninitialized. This runs the
mutex_node = handle;
if (pathname != NULL) {
- status = acpi_get_handle(handle, pathname,
- ACPI_CAST_PTR(acpi_handle,
- &mutex_node));
+ status =
+ acpi_get_handle(handle, pathname,
+ ACPI_CAST_PTR(acpi_handle, &mutex_node));
if (ACPI_FAILURE(status)) {
return (status);
}
int i;
if (ACPI_FAILURE(acpi_get_name(handle, ACPI_FULL_PATHNAME, &buffer)))
- printk(KERN_DEBUG "%s\n", error);
+ printk(KERN_DEBUG "%s: %s\n", context->uuid_str, error);
else {
- printk(KERN_DEBUG "%s:%s\n", (char *)buffer.pointer, error);
+ printk(KERN_DEBUG "%s (%s): %s\n",
+ (char *)buffer.pointer, context->uuid_str, error);
kfree(buffer.pointer);
}
- printk(KERN_DEBUG"_OSC request data:");
+ printk(KERN_DEBUG "_OSC request data:");
for (i = 0; i < context->cap.length; i += sizeof(u32))
- printk("%x ", *((u32 *)(context->cap.pointer + i)));
+ printk(" %x", *((u32 *)(context->cap.pointer + i)));
printk("\n");
}
acpi_debugfs_init();
acpi_sleep_proc_init();
acpi_wakeup_device_init();
+ acpi_debugger_init();
return 0;
}
static struct fwnode_handle *acpi_gsi_domain_id;
-static unsigned int acpi_gsi_get_irq_type(int trigger, int polarity)
-{
- switch (polarity) {
- case ACPI_ACTIVE_LOW:
- return trigger == ACPI_EDGE_SENSITIVE ?
- IRQ_TYPE_EDGE_FALLING :
- IRQ_TYPE_LEVEL_LOW;
- case ACPI_ACTIVE_HIGH:
- return trigger == ACPI_EDGE_SENSITIVE ?
- IRQ_TYPE_EDGE_RISING :
- IRQ_TYPE_LEVEL_HIGH;
- case ACPI_ACTIVE_BOTH:
- if (trigger == ACPI_EDGE_SENSITIVE)
- return IRQ_TYPE_EDGE_BOTH;
- default:
- return IRQ_TYPE_NONE;
- }
-}
-
/**
* acpi_gsi_to_irq() - Retrieve the linux irq number for a given GSI
* @gsi: GSI IRQ number to map
fwspec.fwnode = acpi_gsi_domain_id;
fwspec.param[0] = gsi;
- fwspec.param[1] = acpi_gsi_get_irq_type(trigger, polarity);
+ fwspec.param[1] = acpi_dev_get_irq_type(trigger, polarity);
fwspec.param_count = 2;
return irq_create_fwspec_mapping(&fwspec);
#define ACPI_STA_DEFAULT (ACPI_STA_DEVICE_PRESENT | ACPI_STA_DEVICE_ENABLED | \
ACPI_STA_DEVICE_UI | ACPI_STA_DEVICE_FUNCTIONING)
+extern struct list_head acpi_bus_id_list;
+
+struct acpi_device_bus_id {
+ char bus_id[15];
+ unsigned int instance_no;
+ struct list_head node;
+};
+
int acpi_device_add(struct acpi_device *device,
void (*release)(struct device *));
void acpi_init_device_object(struct acpi_device *device, acpi_handle handle,
acpi_os_vprintf(fmt, args);
va_end(args);
}
+EXPORT_SYMBOL(acpi_os_printf);
void acpi_os_vprintf(const char *fmt, va_list args)
{
printk(KERN_CONT "%s", buffer);
}
#else
- printk(KERN_CONT "%s", buffer);
+ if (acpi_debugger_write_log(buffer) < 0)
+ printk(KERN_CONT "%s", buffer);
#endif
}
iounmap(vaddr);
}
+/**
+ * acpi_os_map_iomem - Get a virtual address for a given physical address range.
+ * @phys: Start of the physical address range to map.
+ * @size: Size of the physical address range to map.
+ *
+ * Look up the given physical address range in the list of existing ACPI memory
+ * mappings. If found, get a reference to it and return a pointer to it (its
+ * virtual address). If not found, map it, add it to that list and return a
+ * pointer to it.
+ *
+ * During early init (when acpi_gbl_permanent_mmap has not been set yet) this
+ * routine simply calls __acpi_map_table() to get the job done.
+ */
void __iomem *__init_refok
acpi_os_map_iomem(acpi_physical_address phys, acpi_size size)
{
}
}
+/**
+ * acpi_os_unmap_iomem - Drop a memory mapping reference.
+ * @virt: Start of the address range to drop a reference to.
+ * @size: Size of the address range to drop a reference to.
+ *
+ * Look up the given virtual address range in the list of existing ACPI memory
+ * mappings, drop a reference to it and unmap it if there are no more active
+ * references to it.
+ *
+ * During early init (when acpi_gbl_permanent_mmap has not been set yet) this
+ * routine simply calls __acpi_unmap_table() to get the job done. Since
+ * __acpi_unmap_table() is an __init function, the __ref annotation is needed
+ * here.
+ */
void __ref acpi_os_unmap_iomem(void __iomem *virt, acpi_size size)
{
struct acpi_ioremap *map;
kfree(dpc);
}
+#ifdef CONFIG_ACPI_DEBUGGER
+static struct acpi_debugger acpi_debugger;
+static bool acpi_debugger_initialized;
+
+int acpi_register_debugger(struct module *owner,
+ const struct acpi_debugger_ops *ops)
+{
+ int ret = 0;
+
+ mutex_lock(&acpi_debugger.lock);
+ if (acpi_debugger.ops) {
+ ret = -EBUSY;
+ goto err_lock;
+ }
+
+ acpi_debugger.owner = owner;
+ acpi_debugger.ops = ops;
+
+err_lock:
+ mutex_unlock(&acpi_debugger.lock);
+ return ret;
+}
+EXPORT_SYMBOL(acpi_register_debugger);
+
+void acpi_unregister_debugger(const struct acpi_debugger_ops *ops)
+{
+ mutex_lock(&acpi_debugger.lock);
+ if (ops == acpi_debugger.ops) {
+ acpi_debugger.ops = NULL;
+ acpi_debugger.owner = NULL;
+ }
+ mutex_unlock(&acpi_debugger.lock);
+}
+EXPORT_SYMBOL(acpi_unregister_debugger);
+
+int acpi_debugger_create_thread(acpi_osd_exec_callback function, void *context)
+{
+ int ret;
+ int (*func)(acpi_osd_exec_callback, void *);
+ struct module *owner;
+
+ if (!acpi_debugger_initialized)
+ return -ENODEV;
+ mutex_lock(&acpi_debugger.lock);
+ if (!acpi_debugger.ops) {
+ ret = -ENODEV;
+ goto err_lock;
+ }
+ if (!try_module_get(acpi_debugger.owner)) {
+ ret = -ENODEV;
+ goto err_lock;
+ }
+ func = acpi_debugger.ops->create_thread;
+ owner = acpi_debugger.owner;
+ mutex_unlock(&acpi_debugger.lock);
+
+ ret = func(function, context);
+
+ mutex_lock(&acpi_debugger.lock);
+ module_put(owner);
+err_lock:
+ mutex_unlock(&acpi_debugger.lock);
+ return ret;
+}
+
+ssize_t acpi_debugger_write_log(const char *msg)
+{
+ ssize_t ret;
+ ssize_t (*func)(const char *);
+ struct module *owner;
+
+ if (!acpi_debugger_initialized)
+ return -ENODEV;
+ mutex_lock(&acpi_debugger.lock);
+ if (!acpi_debugger.ops) {
+ ret = -ENODEV;
+ goto err_lock;
+ }
+ if (!try_module_get(acpi_debugger.owner)) {
+ ret = -ENODEV;
+ goto err_lock;
+ }
+ func = acpi_debugger.ops->write_log;
+ owner = acpi_debugger.owner;
+ mutex_unlock(&acpi_debugger.lock);
+
+ ret = func(msg);
+
+ mutex_lock(&acpi_debugger.lock);
+ module_put(owner);
+err_lock:
+ mutex_unlock(&acpi_debugger.lock);
+ return ret;
+}
+
+ssize_t acpi_debugger_read_cmd(char *buffer, size_t buffer_length)
+{
+ ssize_t ret;
+ ssize_t (*func)(char *, size_t);
+ struct module *owner;
+
+ if (!acpi_debugger_initialized)
+ return -ENODEV;
+ mutex_lock(&acpi_debugger.lock);
+ if (!acpi_debugger.ops) {
+ ret = -ENODEV;
+ goto err_lock;
+ }
+ if (!try_module_get(acpi_debugger.owner)) {
+ ret = -ENODEV;
+ goto err_lock;
+ }
+ func = acpi_debugger.ops->read_cmd;
+ owner = acpi_debugger.owner;
+ mutex_unlock(&acpi_debugger.lock);
+
+ ret = func(buffer, buffer_length);
+
+ mutex_lock(&acpi_debugger.lock);
+ module_put(owner);
+err_lock:
+ mutex_unlock(&acpi_debugger.lock);
+ return ret;
+}
+
+int acpi_debugger_wait_command_ready(void)
+{
+ int ret;
+ int (*func)(bool, char *, size_t);
+ struct module *owner;
+
+ if (!acpi_debugger_initialized)
+ return -ENODEV;
+ mutex_lock(&acpi_debugger.lock);
+ if (!acpi_debugger.ops) {
+ ret = -ENODEV;
+ goto err_lock;
+ }
+ if (!try_module_get(acpi_debugger.owner)) {
+ ret = -ENODEV;
+ goto err_lock;
+ }
+ func = acpi_debugger.ops->wait_command_ready;
+ owner = acpi_debugger.owner;
+ mutex_unlock(&acpi_debugger.lock);
+
+ ret = func(acpi_gbl_method_executing,
+ acpi_gbl_db_line_buf, ACPI_DB_LINE_BUFFER_SIZE);
+
+ mutex_lock(&acpi_debugger.lock);
+ module_put(owner);
+err_lock:
+ mutex_unlock(&acpi_debugger.lock);
+ return ret;
+}
+
+int acpi_debugger_notify_command_complete(void)
+{
+ int ret;
+ int (*func)(void);
+ struct module *owner;
+
+ if (!acpi_debugger_initialized)
+ return -ENODEV;
+ mutex_lock(&acpi_debugger.lock);
+ if (!acpi_debugger.ops) {
+ ret = -ENODEV;
+ goto err_lock;
+ }
+ if (!try_module_get(acpi_debugger.owner)) {
+ ret = -ENODEV;
+ goto err_lock;
+ }
+ func = acpi_debugger.ops->notify_command_complete;
+ owner = acpi_debugger.owner;
+ mutex_unlock(&acpi_debugger.lock);
+
+ ret = func();
+
+ mutex_lock(&acpi_debugger.lock);
+ module_put(owner);
+err_lock:
+ mutex_unlock(&acpi_debugger.lock);
+ return ret;
+}
+
+int __init acpi_debugger_init(void)
+{
+ mutex_init(&acpi_debugger.lock);
+ acpi_debugger_initialized = true;
+ return 0;
+}
+#endif
+
/*******************************************************************************
*
* FUNCTION: acpi_os_execute
"Scheduling function [%p(%p)] for deferred execution.\n",
function, context));
+ if (type == OSL_DEBUGGER_MAIN_THREAD) {
+ ret = acpi_debugger_create_thread(function, context);
+ if (ret) {
+ pr_err("Call to kthread_create() failed.\n");
+ status = AE_ERROR;
+ }
+ goto out_thread;
+ }
+
/*
* Allocate/initialize DPC structure. Note that this memory will be
* freed by the callee. The kernel handles the work_struct list in a
if (type == OSL_NOTIFY_HANDLER) {
queue = kacpi_notify_wq;
INIT_WORK(&dpc->work, acpi_os_execute_deferred);
- } else {
+ } else if (type == OSL_GPE_HANDLER) {
queue = kacpid_wq;
INIT_WORK(&dpc->work, acpi_os_execute_deferred);
+ } else {
+ pr_err("Unsupported os_execute type %d.\n", type);
+ status = AE_ERROR;
}
+ if (ACPI_FAILURE(status))
+ goto err_workqueue;
+
/*
* On some machines, a software-initiated SMI causes corruption unless
* the SMI runs on CPU 0. An SMI can be initiated by any AML, but
* queueing on CPU 0.
*/
ret = queue_work_on(0, queue, &dpc->work);
-
if (!ret) {
printk(KERN_ERR PREFIX
"Call to queue_work() failed.\n");
status = AE_ERROR;
- kfree(dpc);
}
+err_workqueue:
+ if (ACPI_FAILURE(status))
+ kfree(dpc);
+out_thread:
return status;
}
EXPORT_SYMBOL(acpi_os_execute);
chars = strlen(buffer) - 1;
buffer[chars] = '\0';
}
+#else
+ int ret;
+
+ ret = acpi_debugger_read_cmd(buffer, buffer_length);
+ if (ret < 0)
+ return AE_ERROR;
+ if (bytes_read)
+ *bytes_read = ret;
#endif
return AE_OK;
}
+EXPORT_SYMBOL(acpi_os_get_line);
+
+acpi_status acpi_os_wait_command_ready(void)
+{
+ int ret;
+
+ ret = acpi_debugger_wait_command_ready();
+ if (ret < 0)
+ return AE_ERROR;
+ return AE_OK;
+}
+
+acpi_status acpi_os_notify_command_complete(void)
+{
+ int ret;
+
+ ret = acpi_debugger_notify_command_complete();
+ if (ret < 0)
+ return AE_ERROR;
+ return AE_OK;
+}
acpi_status acpi_os_signal(u32 function, void *info)
{
quirk = &prt_quirks[i];
/* All current quirks involve link devices, not GSIs */
- if (!prt->source)
- continue;
-
if (dmi_check_system(quirk->system) &&
entry->id.segment == quirk->segment &&
entry->id.bus == quirk->bus &&
* Copyright (C) 2001, 2002 Andy Grover <andrew.grover@intel.com>
* Copyright (C) 2001, 2002 Paul Diefenbaugh <paul.s.diefenbaugh@intel.com>
* Copyright (C) 2002 Dominik Brodowski <devel@brodo.de>
+ * Copyright (c) 2015, The Linux Foundation. All rights reserved.
*
* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
*
* later even the link is disable. Instead, we just repick the active irq
*/
struct acpi_pci_link_irq {
- u8 active; /* Current IRQ */
+ u32 active; /* Current IRQ */
u8 triggering; /* All IRQs */
u8 polarity; /* All IRQs */
u8 resource_type;
u8 possible_count;
- u8 possible[ACPI_PCI_LINK_MAX_POSSIBLE];
+ u32 possible[ACPI_PCI_LINK_MAX_POSSIBLE];
u8 initialized:1;
u8 reserved:7;
};
* enabled system.
*/
-#define ACPI_MAX_IRQS 256
#define ACPI_MAX_ISA_IRQ 16
#define PIRQ_PENALTY_PCI_AVAILABLE (0)
#define PIRQ_PENALTY_ISA_USED (16*16*16*16*16)
#define PIRQ_PENALTY_ISA_ALWAYS (16*16*16*16*16*16)
-static int acpi_irq_penalty[ACPI_MAX_IRQS] = {
+static int acpi_irq_isa_penalty[ACPI_MAX_ISA_IRQ] = {
PIRQ_PENALTY_ISA_ALWAYS, /* IRQ0 timer */
PIRQ_PENALTY_ISA_ALWAYS, /* IRQ1 keyboard */
PIRQ_PENALTY_ISA_ALWAYS, /* IRQ2 cascade */
PIRQ_PENALTY_ISA_USED, /* IRQ13 fpe, sometimes */
PIRQ_PENALTY_ISA_USED, /* IRQ14 ide0 */
PIRQ_PENALTY_ISA_USED, /* IRQ15 ide1 */
- /* >IRQ15 */
};
+struct irq_penalty_info {
+ int irq;
+ int penalty;
+ struct list_head node;
+};
+
+static LIST_HEAD(acpi_irq_penalty_list);
+
+static int acpi_irq_get_penalty(int irq)
+{
+ struct irq_penalty_info *irq_info;
+
+ if (irq < ACPI_MAX_ISA_IRQ)
+ return acpi_irq_isa_penalty[irq];
+
+ list_for_each_entry(irq_info, &acpi_irq_penalty_list, node) {
+ if (irq_info->irq == irq)
+ return irq_info->penalty;
+ }
+
+ return 0;
+}
+
+static int acpi_irq_set_penalty(int irq, int new_penalty)
+{
+ struct irq_penalty_info *irq_info;
+
+ /* see if this is a ISA IRQ */
+ if (irq < ACPI_MAX_ISA_IRQ) {
+ acpi_irq_isa_penalty[irq] = new_penalty;
+ return 0;
+ }
+
+ /* next, try to locate from the dynamic list */
+ list_for_each_entry(irq_info, &acpi_irq_penalty_list, node) {
+ if (irq_info->irq == irq) {
+ irq_info->penalty = new_penalty;
+ return 0;
+ }
+ }
+
+ /* nope, let's allocate a slot for this IRQ */
+ irq_info = kzalloc(sizeof(*irq_info), GFP_KERNEL);
+ if (!irq_info)
+ return -ENOMEM;
+
+ irq_info->irq = irq;
+ irq_info->penalty = new_penalty;
+ list_add_tail(&irq_info->node, &acpi_irq_penalty_list);
+
+ return 0;
+}
+
+static void acpi_irq_add_penalty(int irq, int penalty)
+{
+ int curpen = acpi_irq_get_penalty(irq);
+
+ acpi_irq_set_penalty(irq, curpen + penalty);
+}
+
int __init acpi_irq_penalty_init(void)
{
struct acpi_pci_link *link;
link->irq.possible_count;
for (i = 0; i < link->irq.possible_count; i++) {
- if (link->irq.possible[i] < ACPI_MAX_ISA_IRQ)
- acpi_irq_penalty[link->irq.
- possible[i]] +=
- penalty;
+ if (link->irq.possible[i] < ACPI_MAX_ISA_IRQ) {
+ int irqpos = link->irq.possible[i];
+
+ acpi_irq_add_penalty(irqpos, penalty);
+ }
}
} else if (link->irq.active) {
- acpi_irq_penalty[link->irq.active] +=
- PIRQ_PENALTY_PCI_POSSIBLE;
+ acpi_irq_add_penalty(link->irq.active,
+ PIRQ_PENALTY_PCI_POSSIBLE);
}
}
* the use of IRQs 9, 10, 11, and >15.
*/
for (i = (link->irq.possible_count - 1); i >= 0; i--) {
- if (acpi_irq_penalty[irq] >
- acpi_irq_penalty[link->irq.possible[i]])
+ if (acpi_irq_get_penalty(irq) >
+ acpi_irq_get_penalty(link->irq.possible[i]))
irq = link->irq.possible[i];
}
}
- if (acpi_irq_penalty[irq] >= PIRQ_PENALTY_ISA_ALWAYS) {
+ if (acpi_irq_get_penalty(irq) >= PIRQ_PENALTY_ISA_ALWAYS) {
printk(KERN_ERR PREFIX "No IRQ available for %s [%s]. "
"Try pci=noacpi or acpi=off\n",
acpi_device_name(link->device),
acpi_device_bid(link->device));
return -ENODEV;
} else {
- acpi_irq_penalty[link->irq.active] += PIRQ_PENALTY_PCI_USING;
+ acpi_irq_add_penalty(link->irq.active, PIRQ_PENALTY_PCI_USING);
+
printk(KERN_WARNING PREFIX "%s [%s] enabled at IRQ %d\n",
acpi_device_name(link->device),
acpi_device_bid(link->device), link->irq.active);
}
/*
- * modify acpi_irq_penalty[] from cmdline
+ * modify penalty from cmdline
*/
static int __init acpi_irq_penalty_update(char *str, int used)
{
if (irq < 0)
continue;
- if (irq >= ARRAY_SIZE(acpi_irq_penalty))
- continue;
-
if (used)
- acpi_irq_penalty[irq] += PIRQ_PENALTY_ISA_USED;
+ acpi_irq_add_penalty(irq, PIRQ_PENALTY_ISA_USED);
else
- acpi_irq_penalty[irq] = PIRQ_PENALTY_PCI_AVAILABLE;
+ acpi_irq_set_penalty(irq, PIRQ_PENALTY_PCI_AVAILABLE);
if (retval != 2) /* no next number */
break;
*/
void acpi_penalize_isa_irq(int irq, int active)
{
- if (irq >= 0 && irq < ARRAY_SIZE(acpi_irq_penalty)) {
- if (active)
- acpi_irq_penalty[irq] += PIRQ_PENALTY_ISA_USED;
- else
- acpi_irq_penalty[irq] += PIRQ_PENALTY_PCI_USING;
- }
+ if (irq >= 0)
+ acpi_irq_add_penalty(irq, active ?
+ PIRQ_PENALTY_ISA_USED : PIRQ_PENALTY_PCI_USING);
}
bool acpi_isa_irq_available(int irq)
{
- return irq >= 0 && (irq >= ARRAY_SIZE(acpi_irq_penalty) ||
- acpi_irq_penalty[irq] < PIRQ_PENALTY_ISA_ALWAYS);
+ return irq >= 0 &&
+ (acpi_irq_get_penalty(irq) < PIRQ_PENALTY_ISA_ALWAYS);
}
/*
*/
void acpi_penalize_sci_irq(int irq, int trigger, int polarity)
{
- if (irq >= 0 && irq < ARRAY_SIZE(acpi_irq_penalty)) {
- if (trigger != ACPI_MADT_TRIGGER_LEVEL ||
- polarity != ACPI_MADT_POLARITY_ACTIVE_LOW)
- acpi_irq_penalty[irq] += PIRQ_PENALTY_ISA_ALWAYS;
- else
- acpi_irq_penalty[irq] += PIRQ_PENALTY_PCI_USING;
- }
+ int penalty;
+
+ if (irq < 0)
+ return;
+
+ if (trigger != ACPI_MADT_TRIGGER_LEVEL ||
+ polarity != ACPI_MADT_POLARITY_ACTIVE_LOW)
+ penalty = PIRQ_PENALTY_ISA_ALWAYS;
+ else
+ penalty = PIRQ_PENALTY_PCI_USING;
+
+ acpi_irq_add_penalty(irq, penalty);
}
/*
*
* Return: %0 if property with @name has been found (success),
* %-EINVAL if the arguments are invalid,
- * %-ENODATA if the property doesn't exist,
+ * %-EINVAL if the property doesn't exist,
* %-EPROTO if the property value type doesn't match @type.
*/
static int acpi_data_get_property(struct acpi_device_data *data,
return -EINVAL;
if (!data->pointer || !data->properties)
- return -ENODATA;
+ return -EINVAL;
properties = data->properties;
for (i = 0; i < properties->package.count; i++) {
if (!strcmp(name, propname->string.pointer)) {
if (type != ACPI_TYPE_ANY && propvalue->type != type)
return -EPROTO;
- else if (obj)
+ if (obj)
*obj = propvalue;
return 0;
}
}
- return -ENODATA;
+ return -EINVAL;
}
/**
*
* Return: %0 if array property (package) with @name has been found (success),
* %-EINVAL if the arguments are invalid,
- * %-ENODATA if the property doesn't exist,
+ * %-EINVAL if the property doesn't exist,
* %-EPROTO if the property is not a package or the type of its elements
* doesn't match @type.
*/
#include <linux/export.h>
#include <linux/ioport.h>
#include <linux/slab.h>
+#include <linux/irq.h>
#ifdef CONFIG_X86
#define valid_IRQ(i) (((i) != 0) && ((i) != 2))
}
EXPORT_SYMBOL_GPL(acpi_dev_irq_flags);
+/**
+ * acpi_dev_get_irq_type - Determine irq type.
+ * @triggering: Triggering type as provided by ACPI.
+ * @polarity: Interrupt polarity as provided by ACPI.
+ */
+unsigned int acpi_dev_get_irq_type(int triggering, int polarity)
+{
+ switch (polarity) {
+ case ACPI_ACTIVE_LOW:
+ return triggering == ACPI_EDGE_SENSITIVE ?
+ IRQ_TYPE_EDGE_FALLING :
+ IRQ_TYPE_LEVEL_LOW;
+ case ACPI_ACTIVE_HIGH:
+ return triggering == ACPI_EDGE_SENSITIVE ?
+ IRQ_TYPE_EDGE_RISING :
+ IRQ_TYPE_LEVEL_HIGH;
+ case ACPI_ACTIVE_BOTH:
+ if (triggering == ACPI_EDGE_SENSITIVE)
+ return IRQ_TYPE_EDGE_BOTH;
+ default:
+ return IRQ_TYPE_NONE;
+ }
+}
+EXPORT_SYMBOL_GPL(acpi_dev_get_irq_type);
+
static void acpi_dev_irqresource_disabled(struct resource *res, u32 gsi)
{
res->start = gsi;
if ((value & 0xf000) != sel) {
value &= 0x0fff;
value |= sel;
- ret = acpi_smbus_write(sbs->hc, SMBUS_WRITE_WORD,
+ ret = acpi_smbus_write(sbs->hc, SMBUS_WRITE_WORD,
ACPI_SBS_MANAGER,
0x01, (u8 *)&value, 2);
- if (ret)
- goto end;
+ if (ret)
+ goto end;
}
}
ret = acpi_smbus_write(sbs->hc, SMBUS_WRITE_WORD, ACPI_SBS_BATTERY,
static LIST_HEAD(acpi_dep_list);
static DEFINE_MUTEX(acpi_dep_list_lock);
-static LIST_HEAD(acpi_bus_id_list);
+LIST_HEAD(acpi_bus_id_list);
static DEFINE_MUTEX(acpi_scan_lock);
static LIST_HEAD(acpi_scan_handlers_list);
DEFINE_MUTEX(acpi_device_lock);
acpi_handle slave;
};
-struct acpi_device_bus_id{
- char bus_id[15];
- unsigned int instance_no;
- struct list_head node;
-};
-
void acpi_scan_lock_acquire(void)
{
mutex_lock(&acpi_scan_lock);
static void acpi_device_del(struct acpi_device *device)
{
+ struct acpi_device_bus_id *acpi_device_bus_id;
+
mutex_lock(&acpi_device_lock);
if (device->parent)
list_del(&device->node);
+ list_for_each_entry(acpi_device_bus_id, &acpi_bus_id_list, node)
+ if (!strcmp(acpi_device_bus_id->bus_id,
+ acpi_device_hid(device))) {
+ if (acpi_device_bus_id->instance_no > 0)
+ acpi_device_bus_id->instance_no--;
+ else {
+ list_del(&acpi_device_bus_id->node);
+ kfree(acpi_device_bus_id);
+ }
+ break;
+ }
+
list_del(&device->wakeup_list);
mutex_unlock(&acpi_device_lock);
*type = ACPI_BUS_TYPE_DEVICE;
status = acpi_bus_get_status_handle(handle, sta);
if (ACPI_FAILURE(status))
- return -ENODEV;
+ *sta = 0;
break;
case ACPI_TYPE_PROCESSOR:
*type = ACPI_BUS_TYPE_PROCESSOR;
if (acpi_state == ACPI_STATE_S3) {
if (!acpi_wakeup_address)
return -EFAULT;
- acpi_set_firmware_waking_vector(acpi_wakeup_address);
+ acpi_set_waking_vector(acpi_wakeup_address);
}
ACPI_FLUSH_CPU_CACHE();
acpi_leave_sleep_state(acpi_state);
/* reset firmware waking vector */
- acpi_set_firmware_waking_vector((acpi_physical_address) 0);
+ acpi_set_waking_vector(0);
acpi_target_sleep_state = ACPI_STATE_S0;
extern struct mutex acpi_device_lock;
extern void acpi_resume_power_resources(void);
+
+static inline acpi_status acpi_set_waking_vector(u32 wakeup_address)
+{
+ return acpi_set_firmware_waking_vector(
+ (acpi_physical_address)wakeup_address, 0);
+}
#include <linux/dynamic_debug.h>
#include "internal.h"
+#include "sleep.h"
#define _COMPONENT ACPI_BUS_COMPONENT
ACPI_MODULE_NAME("utils");
}
EXPORT_SYMBOL(acpi_check_dsm);
+/**
+ * acpi_dev_present - Detect presence of a given ACPI device in the system.
+ * @hid: Hardware ID of the device.
+ *
+ * Return %true if the device was present at the moment of invocation.
+ * Note that if the device is pluggable, it may since have disappeared.
+ *
+ * For this function to work, acpi_bus_scan() must have been executed
+ * which happens in the subsys_initcall() subsection. Hence, do not
+ * call from a subsys_initcall() or earlier (use acpi_get_devices()
+ * instead). Calling from module_init() is fine (which is synonymous
+ * with device_initcall()).
+ */
+bool acpi_dev_present(const char *hid)
+{
+ struct acpi_device_bus_id *acpi_device_bus_id;
+ bool found = false;
+
+ mutex_lock(&acpi_device_lock);
+ list_for_each_entry(acpi_device_bus_id, &acpi_bus_id_list, node)
+ if (!strcmp(acpi_device_bus_id->bus_id, hid)) {
+ found = true;
+ break;
+ }
+ mutex_unlock(&acpi_device_lock);
+
+ return found;
+}
+EXPORT_SYMBOL(acpi_dev_present);
+
/*
* acpi_backlight= handling, this is done here rather then in video_detect.c
* because __setup cannot be used in modules.
DMI_MATCH(DMI_PRODUCT_NAME, "XPS L521X"),
},
},
+ {
+ /* https://bugzilla.kernel.org/show_bug.cgi?id=108971 */
+ .callback = video_detect_force_video,
+ .ident = "SAMSUNG 530U4E/540U4E",
+ .matches = {
+ DMI_MATCH(DMI_SYS_VENDOR, "SAMSUNG ELECTRONICS CO., LTD."),
+ DMI_MATCH(DMI_PRODUCT_NAME, "530U4E/540U4E"),
+ },
+ },
/* Non win8 machines which need native backlight nevertheless */
{
DMI_MATCH(DMI_PRODUCT_NAME, "MacBookPro12,1"),
},
},
+ {
+ .callback = video_detect_force_native,
+ .ident = "Dell Vostro V131",
+ .matches = {
+ DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc."),
+ DMI_MATCH(DMI_PRODUCT_NAME, "Vostro V131"),
+ },
+ },
{ },
};
extern char *make_class_name(const char *name, struct kobject *kobj);
extern int devres_release_all(struct device *dev);
+extern void device_block_probing(void);
+extern void device_unblock_probing(void);
/* /sys/devices directory */
extern struct kset *devices_kset;
if (fwnode_is_primary(fn))
fn = fn->secondary;
- fwnode->secondary = fn;
+ if (fn) {
+ WARN_ON(fwnode->secondary);
+ fwnode->secondary = fn;
+ }
dev->fwnode = fwnode;
} else {
dev->fwnode = fwnode_is_primary(dev->fwnode) ?
static struct workqueue_struct *deferred_wq;
static atomic_t deferred_trigger_count = ATOMIC_INIT(0);
+/*
+ * In some cases, like suspend to RAM or hibernation, It might be reasonable
+ * to prohibit probing of devices as it could be unsafe.
+ * Once defer_all_probes is true all drivers probes will be forcibly deferred.
+ */
+static bool defer_all_probes;
+
/*
* deferred_probe_work_func() - Retry probing devices in the active list.
*/
queue_work(deferred_wq, &deferred_probe_work);
}
+/**
+ * device_block_probing() - Block/defere device's probes
+ *
+ * It will disable probing of devices and defer their probes instead.
+ */
+void device_block_probing(void)
+{
+ defer_all_probes = true;
+ /* sync with probes to avoid races. */
+ wait_for_device_probe();
+}
+
+/**
+ * device_unblock_probing() - Unblock/enable device's probes
+ *
+ * It will restore normal behavior and trigger re-probing of deferred
+ * devices.
+ */
+void device_unblock_probing(void)
+{
+ defer_all_probes = false;
+ driver_deferred_probe_trigger();
+}
+
/**
* deferred_probe_initcall() - Enable probing of deferred devices
*
ret = driver_sysfs_add(dev);
if (!ret)
driver_bound(dev);
+ else if (dev->bus)
+ blocking_notifier_call_chain(&dev->bus->p->bus_notifier,
+ BUS_NOTIFY_DRIVER_NOT_BOUND, dev);
return ret;
}
EXPORT_SYMBOL_GPL(device_bind_driver);
static int really_probe(struct device *dev, struct device_driver *drv)
{
- int ret = 0;
+ int ret = -EPROBE_DEFER;
int local_trigger_count = atomic_read(&deferred_trigger_count);
+ if (defer_all_probes) {
+ /*
+ * Value of defer_all_probes can be set only by
+ * device_defer_all_probes_enable() which, in turn, will call
+ * wait_for_device_probe() right after that to avoid any races.
+ */
+ dev_dbg(dev, "Driver %s force probe deferral\n", drv->name);
+ driver_deferred_probe_add(dev);
+ return ret;
+ }
+
atomic_inc(&probe_count);
pr_debug("bus: '%s': %s: probing driver %s with device %s\n",
drv->bus->name, __func__, drv->name, dev_name(dev));
/* If using pinctrl, bind pins now before probing */
ret = pinctrl_bind_pins(dev);
if (ret)
- goto probe_failed;
+ goto pinctrl_bind_failed;
if (driver_sysfs_add(dev)) {
printk(KERN_ERR "%s: driver_sysfs_add(%s) failed\n",
goto done;
probe_failed:
+ if (dev->bus)
+ blocking_notifier_call_chain(&dev->bus->p->bus_notifier,
+ BUS_NOTIFY_DRIVER_NOT_BOUND, dev);
+pinctrl_bind_failed:
devres_release_all(dev);
driver_sysfs_remove(dev);
dev->driver = NULL;
dev_set_drvdata(dev, NULL);
if (dev->pm_domain && dev->pm_domain->dismiss)
dev->pm_domain->dismiss(dev);
+ pm_runtime_reinit(dev);
switch (ret) {
case -EPROBE_DEFER:
*/
void wait_for_device_probe(void)
{
+ /* wait for the deferred probe workqueue to finish */
+ if (driver_deferred_probe_enable)
+ flush_workqueue(deferred_wq);
+
/* wait for the known devices to complete their probing */
wait_event(probe_waitqueue, atomic_read(&probe_count) == 0);
async_synchronize_full();
dev_set_drvdata(dev, NULL);
if (dev->pm_domain && dev->pm_domain->dismiss)
dev->pm_domain->dismiss(dev);
+ pm_runtime_reinit(dev);
klist_remove(&dev->p->knode_driver);
if (dev->bus)
blocking_notifier_call_chain(&dev->bus->p->bus_notifier,
BUS_NOTIFY_UNBOUND_DRIVER,
dev);
-
}
}
#include <linux/acpi.h>
#include <linux/clk/clk-conf.h>
#include <linux/limits.h>
+#include <linux/property.h>
#include "base.h"
#include "power/power.h"
}
EXPORT_SYMBOL_GPL(platform_device_add_data);
+/**
+ * platform_device_add_properties - add built-in properties to a platform device
+ * @pdev: platform device to add properties to
+ * @pset: properties to add
+ *
+ * The function will take deep copy of the properties in @pset and attach
+ * the copy to the platform device. The memory associated with properties
+ * will be freed when the platform device is released.
+ */
+int platform_device_add_properties(struct platform_device *pdev,
+ const struct property_set *pset)
+{
+ return device_add_property_set(&pdev->dev, pset);
+}
+EXPORT_SYMBOL_GPL(platform_device_add_properties);
+
/**
* platform_device_add - add a platform device to device hierarchy
* @pdev: platform device we're adding
if (r->parent)
release_resource(r);
}
+
+ device_remove_property_set(&pdev->dev);
}
}
EXPORT_SYMBOL_GPL(platform_device_del);
if (ret)
goto err;
+ if (pdevinfo->pset) {
+ ret = platform_device_add_properties(pdev, pdevinfo->pset);
+ if (ret)
+ goto err;
+ }
+
ret = platform_device_add(pdev);
if (ret) {
err:
enable_clock(dev, NULL);
}
break;
+ case BUS_NOTIFY_DRIVER_NOT_BOUND:
case BUS_NOTIFY_UNBOUND_DRIVER:
if (clknb->con_ids[0]) {
for (con_id = clknb->con_ids; *con_id; con_id++)
/**
* dev_pm_domain_detach - Detach a device from its PM domain.
- * @dev: Device to attach.
+ * @dev: Device to detach.
* @power_off: Used to indicate whether we should power off the device.
*
* This functions will reverse the actions from dev_pm_domain_attach() and thus
return ret;
}
+EXPORT_SYMBOL_GPL(__pm_genpd_add_device);
/**
* pm_genpd_remove_device - Remove a device from an I/O PM domain.
return ret;
}
+EXPORT_SYMBOL_GPL(pm_genpd_remove_device);
/**
* pm_genpd_add_subdomain - Add a subdomain to an I/O PM domain.
}
list_splice(&list, &dpm_list);
mutex_unlock(&dpm_list_mtx);
+
+ /* Allow device probing and trigger re-probing of deferred devices */
+ device_unblock_probing();
trace_suspend_resume(TPS("dpm_complete"), state.event, false);
}
trace_suspend_resume(TPS("dpm_prepare"), state.event, true);
might_sleep();
+ /*
+ * Give a chance for the known devices to complete their probes, before
+ * disable probing of devices. This sync point is important at least
+ * at boot time + hibernation restore.
+ */
+ wait_for_device_probe();
+ /*
+ * It is unsafe if probing of devices will happen during suspend or
+ * hibernation and system behavior will be unpredictable in this case.
+ * So, let's prohibit device's probing here and defer their probes
+ * instead. The normal behavior will be restored in dpm_complete().
+ */
+ device_block_probing();
+
mutex_lock(&dpm_list_mtx);
while (!list_empty(&dpm_list)) {
struct device *dev = to_device(dpm_list.next);
ccflags-$(CONFIG_DEBUG_DRIVER) := -DDEBUG
obj-y += core.o cpu.o
+obj-$(CONFIG_DEBUG_FS) += debugfs.o
static void _remove_list_dev(struct device_list_opp *list_dev,
struct device_opp *dev_opp)
{
+ opp_debug_unregister(list_dev, dev_opp);
list_del(&list_dev->node);
call_srcu(&dev_opp->srcu_head.srcu, &list_dev->rcu_head,
_kfree_list_dev_rcu);
struct device_opp *dev_opp)
{
struct device_list_opp *list_dev;
+ int ret;
list_dev = kzalloc(sizeof(*list_dev), GFP_KERNEL);
if (!list_dev)
list_dev->dev = dev;
list_add_rcu(&list_dev->node, &dev_opp->dev_list);
+ /* Create debugfs entries for the dev_opp */
+ ret = opp_debug_register(list_dev, dev_opp);
+ if (ret)
+ dev_err(dev, "%s: Failed to register opp debugfs (%d)\n",
+ __func__, ret);
+
return list_dev;
}
if (!list_empty(&dev_opp->opp_list))
return;
+ if (dev_opp->supported_hw)
+ return;
+
+ if (dev_opp->prop_name)
+ return;
+
list_dev = list_first_entry(&dev_opp->dev_list, struct device_list_opp,
node);
*/
if (notify)
srcu_notifier_call_chain(&dev_opp->srcu_head, OPP_EVENT_REMOVE, opp);
+ opp_debug_remove_one(opp);
list_del_rcu(&opp->node);
call_srcu(&dev_opp->srcu_head.srcu, &opp->rcu_head, _kfree_opp_rcu);
{
struct dev_pm_opp *opp;
struct list_head *head = &dev_opp->opp_list;
+ int ret;
/*
* Insert new OPP in order of increasing frequency and discard if
new_opp->dev_opp = dev_opp;
list_add_rcu(&new_opp->node, head);
+ ret = opp_debug_create_one(new_opp, dev_opp);
+ if (ret)
+ dev_err(dev, "%s: Failed to register opp to debugfs (%d)\n",
+ __func__, ret);
+
return 0;
}
}
/* TODO: Support multiple regulators */
-static int opp_parse_supplies(struct dev_pm_opp *opp, struct device *dev)
+static int opp_parse_supplies(struct dev_pm_opp *opp, struct device *dev,
+ struct device_opp *dev_opp)
{
u32 microvolt[3] = {0};
u32 val;
int count, ret;
+ struct property *prop = NULL;
+ char name[NAME_MAX];
+
+ /* Search for "opp-microvolt-<name>" */
+ if (dev_opp->prop_name) {
+ snprintf(name, sizeof(name), "opp-microvolt-%s",
+ dev_opp->prop_name);
+ prop = of_find_property(opp->np, name, NULL);
+ }
- /* Missing property isn't a problem, but an invalid entry is */
- if (!of_find_property(opp->np, "opp-microvolt", NULL))
- return 0;
+ if (!prop) {
+ /* Search for "opp-microvolt" */
+ sprintf(name, "opp-microvolt");
+ prop = of_find_property(opp->np, name, NULL);
- count = of_property_count_u32_elems(opp->np, "opp-microvolt");
+ /* Missing property isn't a problem, but an invalid entry is */
+ if (!prop)
+ return 0;
+ }
+
+ count = of_property_count_u32_elems(opp->np, name);
if (count < 0) {
- dev_err(dev, "%s: Invalid opp-microvolt property (%d)\n",
- __func__, count);
+ dev_err(dev, "%s: Invalid %s property (%d)\n",
+ __func__, name, count);
return count;
}
/* There can be one or three elements here */
if (count != 1 && count != 3) {
- dev_err(dev, "%s: Invalid number of elements in opp-microvolt property (%d)\n",
- __func__, count);
+ dev_err(dev, "%s: Invalid number of elements in %s property (%d)\n",
+ __func__, name, count);
return -EINVAL;
}
- ret = of_property_read_u32_array(opp->np, "opp-microvolt", microvolt,
- count);
+ ret = of_property_read_u32_array(opp->np, name, microvolt, count);
if (ret) {
- dev_err(dev, "%s: error parsing opp-microvolt: %d\n", __func__,
- ret);
+ dev_err(dev, "%s: error parsing %s: %d\n", __func__, name, ret);
return -EINVAL;
}
opp->u_volt_min = microvolt[1];
opp->u_volt_max = microvolt[2];
- if (!of_property_read_u32(opp->np, "opp-microamp", &val))
+ /* Search for "opp-microamp-<name>" */
+ prop = NULL;
+ if (dev_opp->prop_name) {
+ snprintf(name, sizeof(name), "opp-microamp-%s",
+ dev_opp->prop_name);
+ prop = of_find_property(opp->np, name, NULL);
+ }
+
+ if (!prop) {
+ /* Search for "opp-microamp" */
+ sprintf(name, "opp-microamp");
+ prop = of_find_property(opp->np, name, NULL);
+ }
+
+ if (prop && !of_property_read_u32(opp->np, name, &val))
opp->u_amp = val;
return 0;
}
+/**
+ * dev_pm_opp_set_supported_hw() - Set supported platforms
+ * @dev: Device for which supported-hw has to be set.
+ * @versions: Array of hierarchy of versions to match.
+ * @count: Number of elements in the array.
+ *
+ * This is required only for the V2 bindings, and it enables a platform to
+ * specify the hierarchy of versions it supports. OPP layer will then enable
+ * OPPs, which are available for those versions, based on its 'opp-supported-hw'
+ * property.
+ *
+ * Locking: The internal device_opp and opp structures are RCU protected.
+ * Hence this function internally uses RCU updater strategy with mutex locks
+ * to keep the integrity of the internal data structures. Callers should ensure
+ * that this function is *NOT* called under RCU protection or in contexts where
+ * mutex cannot be locked.
+ */
+int dev_pm_opp_set_supported_hw(struct device *dev, const u32 *versions,
+ unsigned int count)
+{
+ struct device_opp *dev_opp;
+ int ret = 0;
+
+ /* Hold our list modification lock here */
+ mutex_lock(&dev_opp_list_lock);
+
+ dev_opp = _add_device_opp(dev);
+ if (!dev_opp) {
+ ret = -ENOMEM;
+ goto unlock;
+ }
+
+ /* Make sure there are no concurrent readers while updating dev_opp */
+ WARN_ON(!list_empty(&dev_opp->opp_list));
+
+ /* Do we already have a version hierarchy associated with dev_opp? */
+ if (dev_opp->supported_hw) {
+ dev_err(dev, "%s: Already have supported hardware list\n",
+ __func__);
+ ret = -EBUSY;
+ goto err;
+ }
+
+ dev_opp->supported_hw = kmemdup(versions, count * sizeof(*versions),
+ GFP_KERNEL);
+ if (!dev_opp->supported_hw) {
+ ret = -ENOMEM;
+ goto err;
+ }
+
+ dev_opp->supported_hw_count = count;
+ mutex_unlock(&dev_opp_list_lock);
+ return 0;
+
+err:
+ _remove_device_opp(dev_opp);
+unlock:
+ mutex_unlock(&dev_opp_list_lock);
+
+ return ret;
+}
+EXPORT_SYMBOL_GPL(dev_pm_opp_set_supported_hw);
+
+/**
+ * dev_pm_opp_put_supported_hw() - Releases resources blocked for supported hw
+ * @dev: Device for which supported-hw has to be set.
+ *
+ * This is required only for the V2 bindings, and is called for a matching
+ * dev_pm_opp_set_supported_hw(). Until this is called, the device_opp structure
+ * will not be freed.
+ *
+ * Locking: The internal device_opp and opp structures are RCU protected.
+ * Hence this function internally uses RCU updater strategy with mutex locks
+ * to keep the integrity of the internal data structures. Callers should ensure
+ * that this function is *NOT* called under RCU protection or in contexts where
+ * mutex cannot be locked.
+ */
+void dev_pm_opp_put_supported_hw(struct device *dev)
+{
+ struct device_opp *dev_opp;
+
+ /* Hold our list modification lock here */
+ mutex_lock(&dev_opp_list_lock);
+
+ /* Check for existing list for 'dev' first */
+ dev_opp = _find_device_opp(dev);
+ if (IS_ERR(dev_opp)) {
+ dev_err(dev, "Failed to find dev_opp: %ld\n", PTR_ERR(dev_opp));
+ goto unlock;
+ }
+
+ /* Make sure there are no concurrent readers while updating dev_opp */
+ WARN_ON(!list_empty(&dev_opp->opp_list));
+
+ if (!dev_opp->supported_hw) {
+ dev_err(dev, "%s: Doesn't have supported hardware list\n",
+ __func__);
+ goto unlock;
+ }
+
+ kfree(dev_opp->supported_hw);
+ dev_opp->supported_hw = NULL;
+ dev_opp->supported_hw_count = 0;
+
+ /* Try freeing device_opp if this was the last blocking resource */
+ _remove_device_opp(dev_opp);
+
+unlock:
+ mutex_unlock(&dev_opp_list_lock);
+}
+EXPORT_SYMBOL_GPL(dev_pm_opp_put_supported_hw);
+
+/**
+ * dev_pm_opp_set_prop_name() - Set prop-extn name
+ * @dev: Device for which the regulator has to be set.
+ * @name: name to postfix to properties.
+ *
+ * This is required only for the V2 bindings, and it enables a platform to
+ * specify the extn to be used for certain property names. The properties to
+ * which the extension will apply are opp-microvolt and opp-microamp. OPP core
+ * should postfix the property name with -<name> while looking for them.
+ *
+ * Locking: The internal device_opp and opp structures are RCU protected.
+ * Hence this function internally uses RCU updater strategy with mutex locks
+ * to keep the integrity of the internal data structures. Callers should ensure
+ * that this function is *NOT* called under RCU protection or in contexts where
+ * mutex cannot be locked.
+ */
+int dev_pm_opp_set_prop_name(struct device *dev, const char *name)
+{
+ struct device_opp *dev_opp;
+ int ret = 0;
+
+ /* Hold our list modification lock here */
+ mutex_lock(&dev_opp_list_lock);
+
+ dev_opp = _add_device_opp(dev);
+ if (!dev_opp) {
+ ret = -ENOMEM;
+ goto unlock;
+ }
+
+ /* Make sure there are no concurrent readers while updating dev_opp */
+ WARN_ON(!list_empty(&dev_opp->opp_list));
+
+ /* Do we already have a prop-name associated with dev_opp? */
+ if (dev_opp->prop_name) {
+ dev_err(dev, "%s: Already have prop-name %s\n", __func__,
+ dev_opp->prop_name);
+ ret = -EBUSY;
+ goto err;
+ }
+
+ dev_opp->prop_name = kstrdup(name, GFP_KERNEL);
+ if (!dev_opp->prop_name) {
+ ret = -ENOMEM;
+ goto err;
+ }
+
+ mutex_unlock(&dev_opp_list_lock);
+ return 0;
+
+err:
+ _remove_device_opp(dev_opp);
+unlock:
+ mutex_unlock(&dev_opp_list_lock);
+
+ return ret;
+}
+EXPORT_SYMBOL_GPL(dev_pm_opp_set_prop_name);
+
+/**
+ * dev_pm_opp_put_prop_name() - Releases resources blocked for prop-name
+ * @dev: Device for which the regulator has to be set.
+ *
+ * This is required only for the V2 bindings, and is called for a matching
+ * dev_pm_opp_set_prop_name(). Until this is called, the device_opp structure
+ * will not be freed.
+ *
+ * Locking: The internal device_opp and opp structures are RCU protected.
+ * Hence this function internally uses RCU updater strategy with mutex locks
+ * to keep the integrity of the internal data structures. Callers should ensure
+ * that this function is *NOT* called under RCU protection or in contexts where
+ * mutex cannot be locked.
+ */
+void dev_pm_opp_put_prop_name(struct device *dev)
+{
+ struct device_opp *dev_opp;
+
+ /* Hold our list modification lock here */
+ mutex_lock(&dev_opp_list_lock);
+
+ /* Check for existing list for 'dev' first */
+ dev_opp = _find_device_opp(dev);
+ if (IS_ERR(dev_opp)) {
+ dev_err(dev, "Failed to find dev_opp: %ld\n", PTR_ERR(dev_opp));
+ goto unlock;
+ }
+
+ /* Make sure there are no concurrent readers while updating dev_opp */
+ WARN_ON(!list_empty(&dev_opp->opp_list));
+
+ if (!dev_opp->prop_name) {
+ dev_err(dev, "%s: Doesn't have a prop-name\n", __func__);
+ goto unlock;
+ }
+
+ kfree(dev_opp->prop_name);
+ dev_opp->prop_name = NULL;
+
+ /* Try freeing device_opp if this was the last blocking resource */
+ _remove_device_opp(dev_opp);
+
+unlock:
+ mutex_unlock(&dev_opp_list_lock);
+}
+EXPORT_SYMBOL_GPL(dev_pm_opp_put_prop_name);
+
+static bool _opp_is_supported(struct device *dev, struct device_opp *dev_opp,
+ struct device_node *np)
+{
+ unsigned int count = dev_opp->supported_hw_count;
+ u32 version;
+ int ret;
+
+ if (!dev_opp->supported_hw)
+ return true;
+
+ while (count--) {
+ ret = of_property_read_u32_index(np, "opp-supported-hw", count,
+ &version);
+ if (ret) {
+ dev_warn(dev, "%s: failed to read opp-supported-hw property at index %d: %d\n",
+ __func__, count, ret);
+ return false;
+ }
+
+ /* Both of these are bitwise masks of the versions */
+ if (!(version & dev_opp->supported_hw[count]))
+ return false;
+ }
+
+ return true;
+}
+
/**
* _opp_add_static_v2() - Allocate static OPPs (As per 'v2' DT bindings)
* @dev: device for which we do this operation
goto free_opp;
}
+ /* Check if the OPP supports hardware's hierarchy of versions or not */
+ if (!_opp_is_supported(dev, dev_opp, np)) {
+ dev_dbg(dev, "OPP not supported by hardware: %llu\n", rate);
+ goto free_opp;
+ }
+
/*
* Rate is defined as an unsigned long in clk API, and so casting
* explicitly to its type. Must be fixed once rate is 64 bit
if (!of_property_read_u32(np, "clock-latency-ns", &val))
new_opp->clock_latency_ns = val;
- ret = opp_parse_supplies(new_opp, dev);
+ ret = opp_parse_supplies(new_opp, dev, dev_opp);
if (ret)
goto free_opp;
/* OPP to select on device suspend */
if (of_property_read_bool(np, "opp-suspend")) {
- if (dev_opp->suspend_opp)
+ if (dev_opp->suspend_opp) {
dev_warn(dev, "%s: Multiple suspend OPPs found (%lu %lu)\n",
__func__, dev_opp->suspend_opp->rate,
new_opp->rate);
- else
+ } else {
+ new_opp->suspend = true;
dev_opp->suspend_opp = new_opp;
+ }
}
if (new_opp->clock_latency_ns > dev_opp->clock_latency_ns_max)
/*
* Works only for OPP v2 bindings.
*
- * cpumask should be already set to mask of cpu_dev->id.
* Returns -ENOENT if operating-points-v2 bindings aren't supported.
*/
int dev_pm_opp_of_get_sharing_cpus(struct device *cpu_dev, cpumask_var_t cpumask)
return -ENOENT;
}
+ cpumask_set_cpu(cpu_dev->id, cpumask);
+
/* OPPs are shared ? */
if (!of_property_read_bool(np, "opp-shared"))
goto put_cpu_node;
--- /dev/null
+/*
+ * Generic OPP debugfs interface
+ *
+ * Copyright (C) 2015-2016 Viresh Kumar <viresh.kumar@linaro.org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
+#include <linux/debugfs.h>
+#include <linux/device.h>
+#include <linux/err.h>
+#include <linux/init.h>
+#include <linux/limits.h>
+
+#include "opp.h"
+
+static struct dentry *rootdir;
+
+static void opp_set_dev_name(const struct device *dev, char *name)
+{
+ if (dev->parent)
+ snprintf(name, NAME_MAX, "%s-%s", dev_name(dev->parent),
+ dev_name(dev));
+ else
+ snprintf(name, NAME_MAX, "%s", dev_name(dev));
+}
+
+void opp_debug_remove_one(struct dev_pm_opp *opp)
+{
+ debugfs_remove_recursive(opp->dentry);
+}
+
+int opp_debug_create_one(struct dev_pm_opp *opp, struct device_opp *dev_opp)
+{
+ struct dentry *pdentry = dev_opp->dentry;
+ struct dentry *d;
+ char name[25]; /* 20 chars for 64 bit value + 5 (opp:\0) */
+
+ /* Rate is unique to each OPP, use it to give opp-name */
+ snprintf(name, sizeof(name), "opp:%lu", opp->rate);
+
+ /* Create per-opp directory */
+ d = debugfs_create_dir(name, pdentry);
+ if (!d)
+ return -ENOMEM;
+
+ if (!debugfs_create_bool("available", S_IRUGO, d, &opp->available))
+ return -ENOMEM;
+
+ if (!debugfs_create_bool("dynamic", S_IRUGO, d, &opp->dynamic))
+ return -ENOMEM;
+
+ if (!debugfs_create_bool("turbo", S_IRUGO, d, &opp->turbo))
+ return -ENOMEM;
+
+ if (!debugfs_create_bool("suspend", S_IRUGO, d, &opp->suspend))
+ return -ENOMEM;
+
+ if (!debugfs_create_ulong("rate_hz", S_IRUGO, d, &opp->rate))
+ return -ENOMEM;
+
+ if (!debugfs_create_ulong("u_volt_target", S_IRUGO, d, &opp->u_volt))
+ return -ENOMEM;
+
+ if (!debugfs_create_ulong("u_volt_min", S_IRUGO, d, &opp->u_volt_min))
+ return -ENOMEM;
+
+ if (!debugfs_create_ulong("u_volt_max", S_IRUGO, d, &opp->u_volt_max))
+ return -ENOMEM;
+
+ if (!debugfs_create_ulong("u_amp", S_IRUGO, d, &opp->u_amp))
+ return -ENOMEM;
+
+ if (!debugfs_create_ulong("clock_latency_ns", S_IRUGO, d,
+ &opp->clock_latency_ns))
+ return -ENOMEM;
+
+ opp->dentry = d;
+ return 0;
+}
+
+static int device_opp_debug_create_dir(struct device_list_opp *list_dev,
+ struct device_opp *dev_opp)
+{
+ const struct device *dev = list_dev->dev;
+ struct dentry *d;
+
+ opp_set_dev_name(dev, dev_opp->dentry_name);
+
+ /* Create device specific directory */
+ d = debugfs_create_dir(dev_opp->dentry_name, rootdir);
+ if (!d) {
+ dev_err(dev, "%s: Failed to create debugfs dir\n", __func__);
+ return -ENOMEM;
+ }
+
+ list_dev->dentry = d;
+ dev_opp->dentry = d;
+
+ return 0;
+}
+
+static int device_opp_debug_create_link(struct device_list_opp *list_dev,
+ struct device_opp *dev_opp)
+{
+ const struct device *dev = list_dev->dev;
+ char name[NAME_MAX];
+ struct dentry *d;
+
+ opp_set_dev_name(list_dev->dev, name);
+
+ /* Create device specific directory link */
+ d = debugfs_create_symlink(name, rootdir, dev_opp->dentry_name);
+ if (!d) {
+ dev_err(dev, "%s: Failed to create link\n", __func__);
+ return -ENOMEM;
+ }
+
+ list_dev->dentry = d;
+
+ return 0;
+}
+
+/**
+ * opp_debug_register - add a device opp node to the debugfs 'opp' directory
+ * @list_dev: list-dev pointer for device
+ * @dev_opp: the device-opp being added
+ *
+ * Dynamically adds device specific directory in debugfs 'opp' directory. If the
+ * device-opp is shared with other devices, then links will be created for all
+ * devices except the first.
+ *
+ * Return: 0 on success, otherwise negative error.
+ */
+int opp_debug_register(struct device_list_opp *list_dev,
+ struct device_opp *dev_opp)
+{
+ if (!rootdir) {
+ pr_debug("%s: Uninitialized rootdir\n", __func__);
+ return -EINVAL;
+ }
+
+ if (dev_opp->dentry)
+ return device_opp_debug_create_link(list_dev, dev_opp);
+
+ return device_opp_debug_create_dir(list_dev, dev_opp);
+}
+
+static void opp_migrate_dentry(struct device_list_opp *list_dev,
+ struct device_opp *dev_opp)
+{
+ struct device_list_opp *new_dev;
+ const struct device *dev;
+ struct dentry *dentry;
+
+ /* Look for next list-dev */
+ list_for_each_entry(new_dev, &dev_opp->dev_list, node)
+ if (new_dev != list_dev)
+ break;
+
+ /* new_dev is guaranteed to be valid here */
+ dev = new_dev->dev;
+ debugfs_remove_recursive(new_dev->dentry);
+
+ opp_set_dev_name(dev, dev_opp->dentry_name);
+
+ dentry = debugfs_rename(rootdir, list_dev->dentry, rootdir,
+ dev_opp->dentry_name);
+ if (!dentry) {
+ dev_err(dev, "%s: Failed to rename link from: %s to %s\n",
+ __func__, dev_name(list_dev->dev), dev_name(dev));
+ return;
+ }
+
+ new_dev->dentry = dentry;
+ dev_opp->dentry = dentry;
+}
+
+/**
+ * opp_debug_unregister - remove a device opp node from debugfs opp directory
+ * @list_dev: list-dev pointer for device
+ * @dev_opp: the device-opp being removed
+ *
+ * Dynamically removes device specific directory from debugfs 'opp' directory.
+ */
+void opp_debug_unregister(struct device_list_opp *list_dev,
+ struct device_opp *dev_opp)
+{
+ if (list_dev->dentry == dev_opp->dentry) {
+ /* Move the real dentry object under another device */
+ if (!list_is_singular(&dev_opp->dev_list)) {
+ opp_migrate_dentry(list_dev, dev_opp);
+ goto out;
+ }
+ dev_opp->dentry = NULL;
+ }
+
+ debugfs_remove_recursive(list_dev->dentry);
+
+out:
+ list_dev->dentry = NULL;
+}
+
+static int __init opp_debug_init(void)
+{
+ /* Create /sys/kernel/debug/opp directory */
+ rootdir = debugfs_create_dir("opp", NULL);
+ if (!rootdir) {
+ pr_err("%s: Failed to create root directory\n", __func__);
+ return -ENOMEM;
+ }
+
+ return 0;
+}
+core_initcall(opp_debug_init);
#include <linux/device.h>
#include <linux/kernel.h>
#include <linux/list.h>
+#include <linux/limits.h>
#include <linux/pm_opp.h>
#include <linux/rculist.h>
#include <linux/rcupdate.h>
* are protected by the dev_opp_list_lock for integrity.
* IMPORTANT: the opp nodes should be maintained in increasing
* order.
- * @dynamic: not-created from static DT entries.
* @available: true/false - marks if this OPP as available or not
+ * @dynamic: not-created from static DT entries.
* @turbo: true if turbo (boost) OPP
+ * @suspend: true if suspend OPP
* @rate: Frequency in hertz
* @u_volt: Target voltage in microvolts corresponding to this OPP
* @u_volt_min: Minimum voltage in microvolts corresponding to this OPP
* @dev_opp: points back to the device_opp struct this opp belongs to
* @rcu_head: RCU callback head used for deferred freeing
* @np: OPP's device node.
+ * @dentry: debugfs dentry pointer (per opp)
*
* This structure stores the OPP information for a given device.
*/
bool available;
bool dynamic;
bool turbo;
+ bool suspend;
unsigned long rate;
unsigned long u_volt;
struct rcu_head rcu_head;
struct device_node *np;
+
+#ifdef CONFIG_DEBUG_FS
+ struct dentry *dentry;
+#endif
};
/**
* @node: list node
* @dev: device to which the struct object belongs
* @rcu_head: RCU callback head used for deferred freeing
+ * @dentry: debugfs dentry pointer (per device)
*
* This is an internal data structure maintaining the list of devices that are
* managed by 'struct device_opp'.
struct list_head node;
const struct device *dev;
struct rcu_head rcu_head;
+
+#ifdef CONFIG_DEBUG_FS
+ struct dentry *dentry;
+#endif
};
/**
* @dev_list: list of devices that share these OPPs
* @opp_list: list of opps
* @np: struct device_node pointer for opp's DT node.
+ * @clock_latency_ns_max: Max clock latency in nanoseconds.
* @shared_opp: OPP is shared between multiple devices.
+ * @suspend_opp: Pointer to OPP to be used during device suspend.
+ * @supported_hw: Array of version number to support.
+ * @supported_hw_count: Number of elements in supported_hw array.
+ * @prop_name: A name to postfix to many DT properties, while parsing them.
+ * @dentry: debugfs dentry pointer of the real device directory (not links).
+ * @dentry_name: Name of the real dentry.
*
* This is an internal data structure maintaining the link to opps attached to
* a device. This structure is not meant to be shared to users as it is
unsigned long clock_latency_ns_max;
bool shared_opp;
struct dev_pm_opp *suspend_opp;
+
+ unsigned int *supported_hw;
+ unsigned int supported_hw_count;
+ const char *prop_name;
+
+#ifdef CONFIG_DEBUG_FS
+ struct dentry *dentry;
+ char dentry_name[NAME_MAX];
+#endif
};
/* Routines internal to opp core */
struct device_opp *dev_opp);
struct device_node *_of_get_opp_desc_node(struct device *dev);
+#ifdef CONFIG_DEBUG_FS
+void opp_debug_remove_one(struct dev_pm_opp *opp);
+int opp_debug_create_one(struct dev_pm_opp *opp, struct device_opp *dev_opp);
+int opp_debug_register(struct device_list_opp *list_dev,
+ struct device_opp *dev_opp);
+void opp_debug_unregister(struct device_list_opp *list_dev,
+ struct device_opp *dev_opp);
+#else
+static inline void opp_debug_remove_one(struct dev_pm_opp *opp) {}
+
+static inline int opp_debug_create_one(struct dev_pm_opp *opp,
+ struct device_opp *dev_opp)
+{ return 0; }
+static inline int opp_debug_register(struct device_list_opp *list_dev,
+ struct device_opp *dev_opp)
+{ return 0; }
+
+static inline void opp_debug_unregister(struct device_list_opp *list_dev,
+ struct device_opp *dev_opp)
+{ }
+#endif /* DEBUG_FS */
+
#endif /* __DRIVER_OPP_H__ */
}
extern void pm_runtime_init(struct device *dev);
+extern void pm_runtime_reinit(struct device *dev);
extern void pm_runtime_remove(struct device *dev);
struct wake_irq {
}
static inline void pm_runtime_init(struct device *dev) {}
+static inline void pm_runtime_reinit(struct device *dev) {}
static inline void pm_runtime_remove(struct device *dev) {}
static inline int dpm_sysfs_add(struct device *dev) { return 0; }
}
EXPORT_SYMBOL_GPL(__pm_runtime_resume);
+/**
+ * pm_runtime_get_if_in_use - Conditionally bump up the device's usage counter.
+ * @dev: Device to handle.
+ *
+ * Return -EINVAL if runtime PM is disabled for the device.
+ *
+ * If that's not the case and if the device's runtime PM status is RPM_ACTIVE
+ * and the runtime PM usage counter is nonzero, increment the counter and
+ * return 1. Otherwise return 0 without changing the counter.
+ */
+int pm_runtime_get_if_in_use(struct device *dev)
+{
+ unsigned long flags;
+ int retval;
+
+ spin_lock_irqsave(&dev->power.lock, flags);
+ retval = dev->power.disable_depth > 0 ? -EINVAL :
+ dev->power.runtime_status == RPM_ACTIVE
+ && atomic_inc_not_zero(&dev->power.usage_count);
+ spin_unlock_irqrestore(&dev->power.lock, flags);
+ return retval;
+}
+EXPORT_SYMBOL_GPL(pm_runtime_get_if_in_use);
+
/**
* __pm_runtime_set_status - Set runtime PM status of a device.
* @dev: Device to handle.
init_waitqueue_head(&dev->power.wait_queue);
}
+/**
+ * pm_runtime_reinit - Re-initialize runtime PM fields in given device object.
+ * @dev: Device object to re-initialize.
+ */
+void pm_runtime_reinit(struct device *dev)
+{
+ if (!pm_runtime_enabled(dev)) {
+ if (dev->power.runtime_status == RPM_ACTIVE)
+ pm_runtime_set_suspended(dev);
+ if (dev->power.irq_safe) {
+ spin_lock_irq(&dev->power.lock);
+ dev->power.irq_safe = 0;
+ spin_unlock_irq(&dev->power.lock);
+ if (dev->parent)
+ pm_runtime_put(dev->parent);
+ }
+ }
+}
+
/**
* pm_runtime_remove - Prepare for removing a device from device hierarchy.
* @dev: Device object being removed from device hierarchy.
void pm_runtime_remove(struct device *dev)
{
__pm_runtime_disable(dev, false);
-
- /* Change the status back to 'suspended' to match the initial status. */
- if (dev->power.runtime_status == RPM_ACTIVE)
- pm_runtime_set_suspended(dev);
- if (dev->power.irq_safe && dev->parent)
- pm_runtime_put(dev->parent);
+ pm_runtime_reinit(dev);
}
/**
#include <linux/etherdevice.h>
#include <linux/phy.h>
-/**
- * device_add_property_set - Add a collection of properties to a device object.
- * @dev: Device to add properties to.
- * @pset: Collection of properties to add.
- *
- * Associate a collection of device properties represented by @pset with @dev
- * as its secondary firmware node.
- */
-void device_add_property_set(struct device *dev, struct property_set *pset)
-{
- if (!pset)
- return;
-
- pset->fwnode.type = FWNODE_PDATA;
- set_secondary_fwnode(dev, &pset->fwnode);
-}
-EXPORT_SYMBOL_GPL(device_add_property_set);
-
-static inline bool is_pset(struct fwnode_handle *fwnode)
+static inline bool is_pset_node(struct fwnode_handle *fwnode)
{
return fwnode && fwnode->type == FWNODE_PDATA;
}
-static inline struct property_set *to_pset(struct fwnode_handle *fwnode)
+static inline struct property_set *to_pset_node(struct fwnode_handle *fwnode)
{
- return is_pset(fwnode) ?
+ return is_pset_node(fwnode) ?
container_of(fwnode, struct property_set, fwnode) : NULL;
}
return NULL;
}
-static int pset_prop_read_array(struct property_set *pset, const char *name,
- enum dev_prop_type type, void *val, size_t nval)
+static void *pset_prop_find(struct property_set *pset, const char *propname,
+ size_t length)
{
struct property_entry *prop;
- unsigned int item_size;
+ void *pointer;
- prop = pset_prop_get(pset, name);
+ prop = pset_prop_get(pset, propname);
if (!prop)
- return -ENODATA;
+ return ERR_PTR(-EINVAL);
+ if (prop->is_array)
+ pointer = prop->pointer.raw_data;
+ else
+ pointer = &prop->value.raw_data;
+ if (!pointer)
+ return ERR_PTR(-ENODATA);
+ if (length > prop->length)
+ return ERR_PTR(-EOVERFLOW);
+ return pointer;
+}
+
+static int pset_prop_read_u8_array(struct property_set *pset,
+ const char *propname,
+ u8 *values, size_t nval)
+{
+ void *pointer;
+ size_t length = nval * sizeof(*values);
+
+ pointer = pset_prop_find(pset, propname, length);
+ if (IS_ERR(pointer))
+ return PTR_ERR(pointer);
+
+ memcpy(values, pointer, length);
+ return 0;
+}
+
+static int pset_prop_read_u16_array(struct property_set *pset,
+ const char *propname,
+ u16 *values, size_t nval)
+{
+ void *pointer;
+ size_t length = nval * sizeof(*values);
+
+ pointer = pset_prop_find(pset, propname, length);
+ if (IS_ERR(pointer))
+ return PTR_ERR(pointer);
+
+ memcpy(values, pointer, length);
+ return 0;
+}
+
+static int pset_prop_read_u32_array(struct property_set *pset,
+ const char *propname,
+ u32 *values, size_t nval)
+{
+ void *pointer;
+ size_t length = nval * sizeof(*values);
+
+ pointer = pset_prop_find(pset, propname, length);
+ if (IS_ERR(pointer))
+ return PTR_ERR(pointer);
+
+ memcpy(values, pointer, length);
+ return 0;
+}
+
+static int pset_prop_read_u64_array(struct property_set *pset,
+ const char *propname,
+ u64 *values, size_t nval)
+{
+ void *pointer;
+ size_t length = nval * sizeof(*values);
+
+ pointer = pset_prop_find(pset, propname, length);
+ if (IS_ERR(pointer))
+ return PTR_ERR(pointer);
+
+ memcpy(values, pointer, length);
+ return 0;
+}
+
+static int pset_prop_count_elems_of_size(struct property_set *pset,
+ const char *propname, size_t length)
+{
+ struct property_entry *prop;
+
+ prop = pset_prop_get(pset, propname);
+ if (!prop)
+ return -EINVAL;
+
+ return prop->length / length;
+}
+
+static int pset_prop_read_string_array(struct property_set *pset,
+ const char *propname,
+ const char **strings, size_t nval)
+{
+ void *pointer;
+ size_t length = nval * sizeof(*strings);
+
+ pointer = pset_prop_find(pset, propname, length);
+ if (IS_ERR(pointer))
+ return PTR_ERR(pointer);
+
+ memcpy(strings, pointer, length);
+ return 0;
+}
+
+static int pset_prop_read_string(struct property_set *pset,
+ const char *propname, const char **strings)
+{
+ struct property_entry *prop;
+ const char **pointer;
- if (prop->type != type)
- return -EPROTO;
-
- if (!val)
- return prop->nval;
-
- if (prop->nval < nval)
- return -EOVERFLOW;
-
- switch (type) {
- case DEV_PROP_U8:
- item_size = sizeof(u8);
- break;
- case DEV_PROP_U16:
- item_size = sizeof(u16);
- break;
- case DEV_PROP_U32:
- item_size = sizeof(u32);
- break;
- case DEV_PROP_U64:
- item_size = sizeof(u64);
- break;
- case DEV_PROP_STRING:
- item_size = sizeof(const char *);
- break;
- default:
+ prop = pset_prop_get(pset, propname);
+ if (!prop)
return -EINVAL;
+ if (!prop->is_string)
+ return -EILSEQ;
+ if (prop->is_array) {
+ pointer = prop->pointer.str;
+ if (!pointer)
+ return -ENODATA;
+ } else {
+ pointer = &prop->value.str;
+ if (*pointer && strnlen(*pointer, prop->length) >= prop->length)
+ return -EILSEQ;
}
- memcpy(val, prop->value.raw_data, nval * item_size);
+
+ *strings = *pointer;
return 0;
}
}
EXPORT_SYMBOL_GPL(device_property_present);
+static bool __fwnode_property_present(struct fwnode_handle *fwnode,
+ const char *propname)
+{
+ if (is_of_node(fwnode))
+ return of_property_read_bool(to_of_node(fwnode), propname);
+ else if (is_acpi_node(fwnode))
+ return !acpi_node_prop_get(fwnode, propname, NULL);
+ else if (is_pset_node(fwnode))
+ return !!pset_prop_get(to_pset_node(fwnode), propname);
+ return false;
+}
+
/**
* fwnode_property_present - check if a property of a firmware node is present
* @fwnode: Firmware node whose property to check
*/
bool fwnode_property_present(struct fwnode_handle *fwnode, const char *propname)
{
- if (is_of_node(fwnode))
- return of_property_read_bool(to_of_node(fwnode), propname);
- else if (is_acpi_node(fwnode))
- return !acpi_node_prop_get(fwnode, propname, NULL);
+ bool ret;
- return !!pset_prop_get(to_pset(fwnode), propname);
+ ret = __fwnode_property_present(fwnode, propname);
+ if (ret == false && fwnode && fwnode->secondary)
+ ret = __fwnode_property_present(fwnode->secondary, propname);
+ return ret;
}
EXPORT_SYMBOL_GPL(fwnode_property_present);
}
EXPORT_SYMBOL_GPL(device_property_match_string);
-#define OF_DEV_PROP_READ_ARRAY(node, propname, type, val, nval) \
- (val) ? of_property_read_##type##_array((node), (propname), (val), (nval)) \
+#define OF_DEV_PROP_READ_ARRAY(node, propname, type, val, nval) \
+ (val) ? of_property_read_##type##_array((node), (propname), (val), (nval)) \
: of_property_count_elems_of_size((node), (propname), sizeof(type))
-#define FWNODE_PROP_READ_ARRAY(_fwnode_, _propname_, _type_, _proptype_, _val_, _nval_) \
-({ \
- int _ret_; \
- if (is_of_node(_fwnode_)) \
- _ret_ = OF_DEV_PROP_READ_ARRAY(to_of_node(_fwnode_), _propname_, \
- _type_, _val_, _nval_); \
- else if (is_acpi_node(_fwnode_)) \
- _ret_ = acpi_node_prop_read(_fwnode_, _propname_, _proptype_, \
- _val_, _nval_); \
- else if (is_pset(_fwnode_)) \
- _ret_ = pset_prop_read_array(to_pset(_fwnode_), _propname_, \
- _proptype_, _val_, _nval_); \
- else \
- _ret_ = -ENXIO; \
- _ret_; \
+#define PSET_PROP_READ_ARRAY(node, propname, type, val, nval) \
+ (val) ? pset_prop_read_##type##_array((node), (propname), (val), (nval)) \
+ : pset_prop_count_elems_of_size((node), (propname), sizeof(type))
+
+#define FWNODE_PROP_READ(_fwnode_, _propname_, _type_, _proptype_, _val_, _nval_) \
+({ \
+ int _ret_; \
+ if (is_of_node(_fwnode_)) \
+ _ret_ = OF_DEV_PROP_READ_ARRAY(to_of_node(_fwnode_), _propname_, \
+ _type_, _val_, _nval_); \
+ else if (is_acpi_node(_fwnode_)) \
+ _ret_ = acpi_node_prop_read(_fwnode_, _propname_, _proptype_, \
+ _val_, _nval_); \
+ else if (is_pset_node(_fwnode_)) \
+ _ret_ = PSET_PROP_READ_ARRAY(to_pset_node(_fwnode_), _propname_, \
+ _type_, _val_, _nval_); \
+ else \
+ _ret_ = -ENXIO; \
+ _ret_; \
+})
+
+#define FWNODE_PROP_READ_ARRAY(_fwnode_, _propname_, _type_, _proptype_, _val_, _nval_) \
+({ \
+ int _ret_; \
+ _ret_ = FWNODE_PROP_READ(_fwnode_, _propname_, _type_, _proptype_, \
+ _val_, _nval_); \
+ if (_ret_ == -EINVAL && _fwnode_ && _fwnode_->secondary) \
+ _ret_ = FWNODE_PROP_READ(_fwnode_->secondary, _propname_, _type_, \
+ _proptype_, _val_, _nval_); \
+ _ret_; \
})
/**
}
EXPORT_SYMBOL_GPL(fwnode_property_read_u64_array);
+static int __fwnode_property_read_string_array(struct fwnode_handle *fwnode,
+ const char *propname,
+ const char **val, size_t nval)
+{
+ if (is_of_node(fwnode))
+ return val ?
+ of_property_read_string_array(to_of_node(fwnode),
+ propname, val, nval) :
+ of_property_count_strings(to_of_node(fwnode), propname);
+ else if (is_acpi_node(fwnode))
+ return acpi_node_prop_read(fwnode, propname, DEV_PROP_STRING,
+ val, nval);
+ else if (is_pset_node(fwnode))
+ return val ?
+ pset_prop_read_string_array(to_pset_node(fwnode),
+ propname, val, nval) :
+ pset_prop_count_elems_of_size(to_pset_node(fwnode),
+ propname,
+ sizeof(const char *));
+ return -ENXIO;
+}
+
+static int __fwnode_property_read_string(struct fwnode_handle *fwnode,
+ const char *propname, const char **val)
+{
+ if (is_of_node(fwnode))
+ return of_property_read_string(to_of_node(fwnode), propname, val);
+ else if (is_acpi_node(fwnode))
+ return acpi_node_prop_read(fwnode, propname, DEV_PROP_STRING,
+ val, 1);
+ else if (is_pset_node(fwnode))
+ return pset_prop_read_string(to_pset_node(fwnode), propname, val);
+ return -ENXIO;
+}
+
/**
* fwnode_property_read_string_array - return string array property of a node
* @fwnode: Firmware node to get the property of
const char *propname, const char **val,
size_t nval)
{
- if (is_of_node(fwnode))
- return val ?
- of_property_read_string_array(to_of_node(fwnode),
- propname, val, nval) :
- of_property_count_strings(to_of_node(fwnode), propname);
- else if (is_acpi_node(fwnode))
- return acpi_node_prop_read(fwnode, propname, DEV_PROP_STRING,
- val, nval);
- else if (is_pset(fwnode))
- return pset_prop_read_array(to_pset(fwnode), propname,
- DEV_PROP_STRING, val, nval);
- return -ENXIO;
+ int ret;
+
+ ret = __fwnode_property_read_string_array(fwnode, propname, val, nval);
+ if (ret == -EINVAL && fwnode && fwnode->secondary)
+ ret = __fwnode_property_read_string_array(fwnode->secondary,
+ propname, val, nval);
+ return ret;
}
EXPORT_SYMBOL_GPL(fwnode_property_read_string_array);
int fwnode_property_read_string(struct fwnode_handle *fwnode,
const char *propname, const char **val)
{
- if (is_of_node(fwnode))
- return of_property_read_string(to_of_node(fwnode), propname, val);
- else if (is_acpi_node(fwnode))
- return acpi_node_prop_read(fwnode, propname, DEV_PROP_STRING,
- val, 1);
+ int ret;
- return pset_prop_read_array(to_pset(fwnode), propname,
- DEV_PROP_STRING, val, 1);
+ ret = __fwnode_property_read_string(fwnode, propname, val);
+ if (ret == -EINVAL && fwnode && fwnode->secondary)
+ ret = __fwnode_property_read_string(fwnode->secondary,
+ propname, val);
+ return ret;
}
EXPORT_SYMBOL_GPL(fwnode_property_read_string);
if (nval < 0)
return nval;
+ if (nval == 0)
+ return -ENODATA;
+
values = kcalloc(nval, sizeof(*values), GFP_KERNEL);
if (!values)
return -ENOMEM;
}
EXPORT_SYMBOL_GPL(fwnode_property_match_string);
+/**
+ * pset_free_set - releases memory allocated for copied property set
+ * @pset: Property set to release
+ *
+ * Function takes previously copied property set and releases all the
+ * memory allocated to it.
+ */
+static void pset_free_set(struct property_set *pset)
+{
+ const struct property_entry *prop;
+ size_t i, nval;
+
+ if (!pset)
+ return;
+
+ for (prop = pset->properties; prop->name; prop++) {
+ if (prop->is_array) {
+ if (prop->is_string && prop->pointer.str) {
+ nval = prop->length / sizeof(const char *);
+ for (i = 0; i < nval; i++)
+ kfree(prop->pointer.str[i]);
+ }
+ kfree(prop->pointer.raw_data);
+ } else if (prop->is_string) {
+ kfree(prop->value.str);
+ }
+ kfree(prop->name);
+ }
+
+ kfree(pset->properties);
+ kfree(pset);
+}
+
+static int pset_copy_entry(struct property_entry *dst,
+ const struct property_entry *src)
+{
+ const char **d, **s;
+ size_t i, nval;
+
+ dst->name = kstrdup(src->name, GFP_KERNEL);
+ if (!dst->name)
+ return -ENOMEM;
+
+ if (src->is_array) {
+ if (!src->length)
+ return -ENODATA;
+
+ if (src->is_string) {
+ nval = src->length / sizeof(const char *);
+ dst->pointer.str = kcalloc(nval, sizeof(const char *),
+ GFP_KERNEL);
+ if (!dst->pointer.str)
+ return -ENOMEM;
+
+ d = dst->pointer.str;
+ s = src->pointer.str;
+ for (i = 0; i < nval; i++) {
+ d[i] = kstrdup(s[i], GFP_KERNEL);
+ if (!d[i] && s[i])
+ return -ENOMEM;
+ }
+ } else {
+ dst->pointer.raw_data = kmemdup(src->pointer.raw_data,
+ src->length, GFP_KERNEL);
+ if (!dst->pointer.raw_data)
+ return -ENOMEM;
+ }
+ } else if (src->is_string) {
+ dst->value.str = kstrdup(src->value.str, GFP_KERNEL);
+ if (!dst->value.str && src->value.str)
+ return -ENOMEM;
+ } else {
+ dst->value.raw_data = src->value.raw_data;
+ }
+
+ dst->length = src->length;
+ dst->is_array = src->is_array;
+ dst->is_string = src->is_string;
+
+ return 0;
+}
+
+/**
+ * pset_copy_set - copies property set
+ * @pset: Property set to copy
+ *
+ * This function takes a deep copy of the given property set and returns
+ * pointer to the copy. Call device_free_property_set() to free resources
+ * allocated in this function.
+ *
+ * Return: Pointer to the new property set or error pointer.
+ */
+static struct property_set *pset_copy_set(const struct property_set *pset)
+{
+ const struct property_entry *entry;
+ struct property_set *p;
+ size_t i, n = 0;
+
+ p = kzalloc(sizeof(*p), GFP_KERNEL);
+ if (!p)
+ return ERR_PTR(-ENOMEM);
+
+ while (pset->properties[n].name)
+ n++;
+
+ p->properties = kcalloc(n + 1, sizeof(*entry), GFP_KERNEL);
+ if (!p->properties) {
+ kfree(p);
+ return ERR_PTR(-ENOMEM);
+ }
+
+ for (i = 0; i < n; i++) {
+ int ret = pset_copy_entry(&p->properties[i],
+ &pset->properties[i]);
+ if (ret) {
+ pset_free_set(p);
+ return ERR_PTR(ret);
+ }
+ }
+
+ return p;
+}
+
+/**
+ * device_remove_property_set - Remove properties from a device object.
+ * @dev: Device whose properties to remove.
+ *
+ * The function removes properties previously associated to the device
+ * secondary firmware node with device_add_property_set(). Memory allocated
+ * to the properties will also be released.
+ */
+void device_remove_property_set(struct device *dev)
+{
+ struct fwnode_handle *fwnode;
+
+ fwnode = dev_fwnode(dev);
+ if (!fwnode)
+ return;
+ /*
+ * Pick either primary or secondary node depending which one holds
+ * the pset. If there is no real firmware node (ACPI/DT) primary
+ * will hold the pset.
+ */
+ if (!is_pset_node(fwnode))
+ fwnode = fwnode->secondary;
+ if (!IS_ERR(fwnode) && is_pset_node(fwnode))
+ pset_free_set(to_pset_node(fwnode));
+ set_secondary_fwnode(dev, NULL);
+}
+EXPORT_SYMBOL_GPL(device_remove_property_set);
+
+/**
+ * device_add_property_set - Add a collection of properties to a device object.
+ * @dev: Device to add properties to.
+ * @pset: Collection of properties to add.
+ *
+ * Associate a collection of device properties represented by @pset with @dev
+ * as its secondary firmware node. The function takes a copy of @pset.
+ */
+int device_add_property_set(struct device *dev, const struct property_set *pset)
+{
+ struct property_set *p;
+
+ if (!pset)
+ return -EINVAL;
+
+ p = pset_copy_set(pset);
+ if (IS_ERR(p))
+ return PTR_ERR(p);
+
+ p->fwnode.type = FWNODE_PDATA;
+ set_secondary_fwnode(dev, &p->fwnode);
+ return 0;
+}
+EXPORT_SYMBOL_GPL(device_add_property_set);
+
/**
* device_get_next_child_node - Return the next child node handle for a device
* @dev: Device to find the next child node for.
config ARM_BIG_LITTLE_CPUFREQ
tristate "Generic ARM big LITTLE CPUfreq driver"
depends on (ARM_CPU_TOPOLOGY || ARM64) && HAVE_CLK
+ # if CPU_THERMAL is on and THERMAL=m, ARM_BIT_LITTLE_CPUFREQ cannot be =y
+ depends on !CPU_THERMAL || THERMAL
select PM_OPP
help
This enables the Generic CPUfreq driver for ARM big.LITTLE platforms.
help
This adds the CPUFreq driver support for SPEAr SOCs.
+config ARM_STI_CPUFREQ
+ tristate "STi CPUFreq support"
+ depends on SOC_STIH407
+ help
+ This driver uses the generic OPP framework to match the running
+ platform with a predefined set of suitable values. If not provided
+ we will fall-back so safe-values contained in Device Tree. Enable
+ this config option if you wish to add CPUFreq support for STi based
+ SoCs.
+
config ARM_TEGRA20_CPUFREQ
bool "Tegra20 CPUFreq support"
depends on ARCH_TEGRA
obj-$(CONFIG_ARM_SA1110_CPUFREQ) += sa1110-cpufreq.o
obj-$(CONFIG_ARM_SCPI_CPUFREQ) += scpi-cpufreq.o
obj-$(CONFIG_ARM_SPEAR_CPUFREQ) += spear-cpufreq.o
+obj-$(CONFIG_ARM_STI_CPUFREQ) += sti-cpufreq.o
obj-$(CONFIG_ARM_TEGRA20_CPUFREQ) += tegra20-cpufreq.o
obj-$(CONFIG_ARM_TEGRA124_CPUFREQ) += tegra124-cpufreq.o
obj-$(CONFIG_ARM_VEXPRESS_SPC_CPUFREQ) += vexpress-spc-cpufreq.o
wrmsr_on_cpus(cpumask, msr_addr, msrs);
}
-static int _store_boost(int val)
+static int set_boost(int val)
{
get_online_cpus();
boost_set_msrs(val, cpu_online_mask);
cpufreq_freq_attr_ro(freqdomain_cpus);
#ifdef CONFIG_X86_ACPI_CPUFREQ_CPB
-static ssize_t store_boost(const char *buf, size_t count)
+static ssize_t store_cpb(struct cpufreq_policy *policy, const char *buf,
+ size_t count)
{
int ret;
- unsigned long val = 0;
+ unsigned int val = 0;
- if (!acpi_cpufreq_driver.boost_supported)
+ if (!acpi_cpufreq_driver.set_boost)
return -EINVAL;
- ret = kstrtoul(buf, 10, &val);
- if (ret || (val > 1))
+ ret = kstrtouint(buf, 10, &val);
+ if (ret || val > 1)
return -EINVAL;
- _store_boost((int) val);
+ set_boost(val);
return count;
}
-static ssize_t store_cpb(struct cpufreq_policy *policy, const char *buf,
- size_t count)
-{
- return store_boost(buf, count);
-}
-
static ssize_t show_cpb(struct cpufreq_policy *policy, char *buf)
{
return sprintf(buf, "%u\n", acpi_cpufreq_driver.boost_enabled);
.resume = acpi_cpufreq_resume,
.name = "acpi-cpufreq",
.attr = acpi_cpufreq_attr,
- .set_boost = _store_boost,
};
static void __init acpi_cpufreq_boost_init(void)
if (!msrs)
return;
- acpi_cpufreq_driver.boost_supported = true;
+ acpi_cpufreq_driver.set_boost = set_boost;
acpi_cpufreq_driver.boost_enabled = boost_state(0);
cpu_notifier_register_begin();
#include <linux/cpu.h>
#include <linux/cpufreq.h>
#include <linux/cpumask.h>
+#include <linux/cpu_cooling.h>
#include <linux/export.h>
#include <linux/module.h>
#include <linux/mutex.h>
#define ACTUAL_FREQ(cluster, freq) ((cluster == A7_CLUSTER) ? freq << 1 : freq)
#define VIRT_FREQ(cluster, freq) ((cluster == A7_CLUSTER) ? freq >> 1 : freq)
+static struct thermal_cooling_device *cdev[MAX_CLUSTERS];
static struct cpufreq_arm_bL_ops *arm_bL_ops;
static struct clk *clk[MAX_CLUSTERS];
static struct cpufreq_frequency_table *freq_table[MAX_CLUSTERS + 1];
static int bL_cpufreq_exit(struct cpufreq_policy *policy)
{
struct device *cpu_dev;
+ int cur_cluster = cpu_to_cluster(policy->cpu);
+
+ if (cur_cluster < MAX_CLUSTERS) {
+ cpufreq_cooling_unregister(cdev[cur_cluster]);
+ cdev[cur_cluster] = NULL;
+ }
cpu_dev = get_cpu_device(policy->cpu);
if (!cpu_dev) {
return 0;
}
+static void bL_cpufreq_ready(struct cpufreq_policy *policy)
+{
+ struct device *cpu_dev = get_cpu_device(policy->cpu);
+ int cur_cluster = cpu_to_cluster(policy->cpu);
+ struct device_node *np;
+
+ /* Do not register a cpu_cooling device if we are in IKS mode */
+ if (cur_cluster >= MAX_CLUSTERS)
+ return;
+
+ np = of_node_get(cpu_dev->of_node);
+ if (WARN_ON(!np))
+ return;
+
+ if (of_find_property(np, "#cooling-cells", NULL)) {
+ u32 power_coefficient = 0;
+
+ of_property_read_u32(np, "dynamic-power-coefficient",
+ &power_coefficient);
+
+ cdev[cur_cluster] = of_cpufreq_power_cooling_register(np,
+ policy->related_cpus, power_coefficient, NULL);
+ if (IS_ERR(cdev[cur_cluster])) {
+ dev_err(cpu_dev,
+ "running cpufreq without cooling device: %ld\n",
+ PTR_ERR(cdev[cur_cluster]));
+ cdev[cur_cluster] = NULL;
+ }
+ }
+ of_node_put(np);
+}
+
static struct cpufreq_driver bL_cpufreq_driver = {
.name = "arm-big-little",
.flags = CPUFREQ_STICKY |
.get = bL_cpufreq_get_rate,
.init = bL_cpufreq_init,
.exit = bL_cpufreq_exit,
+ .ready = bL_cpufreq_ready,
.attr = cpufreq_generic_attr,
};
}
#ifdef CONFIG_BF60x
-unsigned long cpu_set_cclk(int cpu, unsigned long new)
+static int cpu_set_cclk(int cpu, unsigned long new)
{
struct clk *clk;
int ret;
struct private_data *priv = policy->driver_data;
struct device *cpu_dev = priv->cpu_dev;
struct regulator *cpu_reg = priv->cpu_reg;
- unsigned long volt = 0, volt_old = 0, tol = 0;
+ unsigned long volt = 0, tol = 0;
+ int volt_old = 0;
unsigned int old_freq, new_freq;
long freq_Hz, freq_exact;
int ret;
opp_freq / 1000, volt);
}
- dev_dbg(cpu_dev, "%u MHz, %ld mV --> %u MHz, %ld mV\n",
+ dev_dbg(cpu_dev, "%u MHz, %d mV --> %u MHz, %ld mV\n",
old_freq / 1000, (volt_old > 0) ? volt_old / 1000 : -1,
new_freq / 1000, volt ? volt / 1000 : -1);
* thermal DT code takes care of matching them.
*/
if (of_find_property(np, "#cooling-cells", NULL)) {
- priv->cdev = of_cpufreq_cooling_register(np,
- policy->related_cpus);
+ u32 power_coefficient = 0;
+
+ of_property_read_u32(np, "dynamic-power-coefficient",
+ &power_coefficient);
+
+ priv->cdev = of_cpufreq_power_cooling_register(np,
+ policy->related_cpus, power_coefficient, NULL);
if (IS_ERR(priv->cdev)) {
dev_err(priv->cpu_dev,
"running cpufreq without cooling device: %ld\n",
return ret;
}
-int cpufreq_boost_supported(void)
+static bool cpufreq_boost_supported(void)
{
- if (likely(cpufreq_driver))
- return cpufreq_driver->boost_supported;
-
- return 0;
+ return likely(cpufreq_driver) && cpufreq_driver->set_boost;
}
-EXPORT_SYMBOL_GPL(cpufreq_boost_supported);
static int create_boost_sysfs_file(void)
{
int ret;
- if (!cpufreq_boost_supported())
- return 0;
-
- /*
- * Check if driver provides function to enable boost -
- * if not, use cpufreq_boost_set_sw as default
- */
- if (!cpufreq_driver->set_boost)
- cpufreq_driver->set_boost = cpufreq_boost_set_sw;
-
ret = sysfs_create_file(cpufreq_global_kobject, &boost.attr);
if (ret)
pr_err("%s: cannot register global BOOST sysfs file\n",
if (cpufreq_boost_supported())
return 0;
- cpufreq_driver->boost_supported = true;
+ cpufreq_driver->set_boost = cpufreq_boost_set_sw;
/* This will get removed on driver unregister */
return create_boost_sysfs_file();
if (driver_data->setpolicy)
driver_data->flags |= CPUFREQ_CONST_LOOPS;
- ret = create_boost_sysfs_file();
- if (ret)
- goto err_null_driver;
+ if (cpufreq_boost_supported()) {
+ ret = create_boost_sysfs_file();
+ if (ret)
+ goto err_null_driver;
+ }
ret = subsys_interface_register(&cpufreq_interface);
if (ret)
}
}
-static unsigned int cs_dbs_timer(struct cpu_dbs_info *cdbs,
- struct dbs_data *dbs_data, bool modify_all)
+static unsigned int cs_dbs_timer(struct cpufreq_policy *policy, bool modify_all)
{
+ struct dbs_data *dbs_data = policy->governor_data;
struct cs_dbs_tuners *cs_tuners = dbs_data->tuners;
if (modify_all)
- dbs_check_cpu(dbs_data, cdbs->shared->policy->cpu);
+ dbs_check_cpu(dbs_data, policy->cpu);
return delay_for_sampling_rate(cs_tuners->sampling_rate);
}
(cur_wall_time - j_cdbs->prev_cpu_wall);
j_cdbs->prev_cpu_wall = cur_wall_time;
+ if (cur_idle_time < j_cdbs->prev_cpu_idle)
+ cur_idle_time = j_cdbs->prev_cpu_idle;
+
idle_time = (unsigned int)
(cur_idle_time - j_cdbs->prev_cpu_idle);
j_cdbs->prev_cpu_idle = cur_idle_time;
}
EXPORT_SYMBOL_GPL(dbs_check_cpu);
-static inline void __gov_queue_work(int cpu, struct dbs_data *dbs_data,
- unsigned int delay)
+void gov_add_timers(struct cpufreq_policy *policy, unsigned int delay)
{
- struct cpu_dbs_info *cdbs = dbs_data->cdata->get_cpu_cdbs(cpu);
-
- mod_delayed_work_on(cpu, system_wq, &cdbs->dwork, delay);
-}
-
-void gov_queue_work(struct dbs_data *dbs_data, struct cpufreq_policy *policy,
- unsigned int delay, bool all_cpus)
-{
- int i;
+ struct dbs_data *dbs_data = policy->governor_data;
+ struct cpu_dbs_info *cdbs;
+ int cpu;
- if (!all_cpus) {
- /*
- * Use raw_smp_processor_id() to avoid preemptible warnings.
- * We know that this is only called with all_cpus == false from
- * works that have been queued with *_work_on() functions and
- * those works are canceled during CPU_DOWN_PREPARE so they
- * can't possibly run on any other CPU.
- */
- __gov_queue_work(raw_smp_processor_id(), dbs_data, delay);
- } else {
- for_each_cpu(i, policy->cpus)
- __gov_queue_work(i, dbs_data, delay);
+ for_each_cpu(cpu, policy->cpus) {
+ cdbs = dbs_data->cdata->get_cpu_cdbs(cpu);
+ cdbs->timer.expires = jiffies + delay;
+ add_timer_on(&cdbs->timer, cpu);
}
}
-EXPORT_SYMBOL_GPL(gov_queue_work);
+EXPORT_SYMBOL_GPL(gov_add_timers);
-static inline void gov_cancel_work(struct dbs_data *dbs_data,
- struct cpufreq_policy *policy)
+static inline void gov_cancel_timers(struct cpufreq_policy *policy)
{
+ struct dbs_data *dbs_data = policy->governor_data;
struct cpu_dbs_info *cdbs;
int i;
for_each_cpu(i, policy->cpus) {
cdbs = dbs_data->cdata->get_cpu_cdbs(i);
- cancel_delayed_work_sync(&cdbs->dwork);
+ del_timer_sync(&cdbs->timer);
}
}
+void gov_cancel_work(struct cpu_common_dbs_info *shared)
+{
+ /* Tell dbs_timer_handler() to skip queuing up work items. */
+ atomic_inc(&shared->skip_work);
+ /*
+ * If dbs_timer_handler() is already running, it may not notice the
+ * incremented skip_work, so wait for it to complete to prevent its work
+ * item from being queued up after the cancel_work_sync() below.
+ */
+ gov_cancel_timers(shared->policy);
+ /*
+ * In case dbs_timer_handler() managed to run and spawn a work item
+ * before the timers have been canceled, wait for that work item to
+ * complete and then cancel all of the timers set up by it. If
+ * dbs_timer_handler() runs again at that point, it will see the
+ * positive value of skip_work and won't spawn any more work items.
+ */
+ cancel_work_sync(&shared->work);
+ gov_cancel_timers(shared->policy);
+ atomic_set(&shared->skip_work, 0);
+}
+EXPORT_SYMBOL_GPL(gov_cancel_work);
+
/* Will return if we need to evaluate cpu load again or not */
static bool need_load_eval(struct cpu_common_dbs_info *shared,
unsigned int sampling_rate)
return true;
}
-static void dbs_timer(struct work_struct *work)
+static void dbs_work_handler(struct work_struct *work)
{
- struct cpu_dbs_info *cdbs = container_of(work, struct cpu_dbs_info,
- dwork.work);
- struct cpu_common_dbs_info *shared = cdbs->shared;
+ struct cpu_common_dbs_info *shared = container_of(work, struct
+ cpu_common_dbs_info, work);
struct cpufreq_policy *policy;
struct dbs_data *dbs_data;
unsigned int sampling_rate, delay;
- bool modify_all = true;
-
- mutex_lock(&shared->timer_mutex);
+ bool eval_load;
policy = shared->policy;
-
- /*
- * Governor might already be disabled and there is no point continuing
- * with the work-handler.
- */
- if (!policy)
- goto unlock;
-
dbs_data = policy->governor_data;
+ /* Kill all timers */
+ gov_cancel_timers(policy);
+
if (dbs_data->cdata->governor == GOV_CONSERVATIVE) {
struct cs_dbs_tuners *cs_tuners = dbs_data->tuners;
sampling_rate = od_tuners->sampling_rate;
}
- if (!need_load_eval(cdbs->shared, sampling_rate))
- modify_all = false;
-
- delay = dbs_data->cdata->gov_dbs_timer(cdbs, dbs_data, modify_all);
- gov_queue_work(dbs_data, policy, delay, modify_all);
+ eval_load = need_load_eval(shared, sampling_rate);
-unlock:
+ /*
+ * Make sure cpufreq_governor_limits() isn't evaluating load in
+ * parallel.
+ */
+ mutex_lock(&shared->timer_mutex);
+ delay = dbs_data->cdata->gov_dbs_timer(policy, eval_load);
mutex_unlock(&shared->timer_mutex);
+
+ atomic_dec(&shared->skip_work);
+
+ gov_add_timers(policy, delay);
+}
+
+static void dbs_timer_handler(unsigned long data)
+{
+ struct cpu_dbs_info *cdbs = (struct cpu_dbs_info *)data;
+ struct cpu_common_dbs_info *shared = cdbs->shared;
+
+ /*
+ * Timer handler may not be allowed to queue the work at the moment,
+ * because:
+ * - Another timer handler has done that
+ * - We are stopping the governor
+ * - Or we are updating the sampling rate of the ondemand governor
+ */
+ if (atomic_inc_return(&shared->skip_work) > 1)
+ atomic_dec(&shared->skip_work);
+ else
+ queue_work(system_wq, &shared->work);
}
static void set_sampling_rate(struct dbs_data *dbs_data,
for_each_cpu(j, policy->related_cpus)
cdata->get_cpu_cdbs(j)->shared = shared;
+ mutex_init(&shared->timer_mutex);
+ atomic_set(&shared->skip_work, 0);
+ INIT_WORK(&shared->work, dbs_work_handler);
return 0;
}
struct cpu_common_dbs_info *shared = cdbs->shared;
int j;
+ mutex_destroy(&shared->timer_mutex);
+
for_each_cpu(j, policy->cpus)
cdata->get_cpu_cdbs(j)->shared = NULL;
shared->policy = policy;
shared->time_stamp = ktime_get();
- mutex_init(&shared->timer_mutex);
for_each_cpu(j, policy->cpus) {
struct cpu_dbs_info *j_cdbs = cdata->get_cpu_cdbs(j);
if (ignore_nice)
j_cdbs->prev_cpu_nice = kcpustat_cpu(j).cpustat[CPUTIME_NICE];
- INIT_DEFERRABLE_WORK(&j_cdbs->dwork, dbs_timer);
+ __setup_timer(&j_cdbs->timer, dbs_timer_handler,
+ (unsigned long)j_cdbs,
+ TIMER_DEFERRABLE | TIMER_IRQSAFE);
}
if (cdata->governor == GOV_CONSERVATIVE) {
od_ops->powersave_bias_init_cpu(cpu);
}
- gov_queue_work(dbs_data, policy, delay_for_sampling_rate(sampling_rate),
- true);
+ gov_add_timers(policy, delay_for_sampling_rate(sampling_rate));
return 0;
}
if (!shared || !shared->policy)
return -EBUSY;
- /*
- * Work-handler must see this updated, as it should not proceed any
- * further after governor is disabled. And so timer_mutex is taken while
- * updating this value.
- */
- mutex_lock(&shared->timer_mutex);
+ gov_cancel_work(shared);
shared->policy = NULL;
- mutex_unlock(&shared->timer_mutex);
-
- gov_cancel_work(dbs_data, policy);
- mutex_destroy(&shared->timer_mutex);
return 0;
}
#ifndef _CPUFREQ_GOVERNOR_H
#define _CPUFREQ_GOVERNOR_H
+#include <linux/atomic.h>
#include <linux/cpufreq.h>
#include <linux/kernel_stat.h>
#include <linux/module.h>
struct cpu_common_dbs_info {
struct cpufreq_policy *policy;
/*
- * percpu mutex that serializes governor limit change with dbs_timer
- * invocation. We do not want dbs_timer to run when user is changing
- * the governor or limits.
+ * Per policy mutex that serializes load evaluation from limit-change
+ * and work-handler.
*/
struct mutex timer_mutex;
+
ktime_t time_stamp;
+ atomic_t skip_work;
+ struct work_struct work;
};
/* Per cpu structures */
* wake-up from idle.
*/
unsigned int prev_load;
- struct delayed_work dwork;
+ struct timer_list timer;
struct cpu_common_dbs_info *shared;
};
struct cpu_dbs_info *(*get_cpu_cdbs)(int cpu);
void *(*get_cpu_dbs_info_s)(int cpu);
- unsigned int (*gov_dbs_timer)(struct cpu_dbs_info *cdbs,
- struct dbs_data *dbs_data,
+ unsigned int (*gov_dbs_timer)(struct cpufreq_policy *policy,
bool modify_all);
void (*gov_check_cpu)(int cpu, unsigned int load);
int (*init)(struct dbs_data *dbs_data, bool notify);
extern struct mutex cpufreq_governor_lock;
+void gov_add_timers(struct cpufreq_policy *policy, unsigned int delay);
+void gov_cancel_work(struct cpu_common_dbs_info *shared);
void dbs_check_cpu(struct dbs_data *dbs_data, int cpu);
int cpufreq_governor_dbs(struct cpufreq_policy *policy,
struct common_dbs_data *cdata, unsigned int event);
-void gov_queue_work(struct dbs_data *dbs_data, struct cpufreq_policy *policy,
- unsigned int delay, bool all_cpus);
void od_register_powersave_bias_handler(unsigned int (*f)
(struct cpufreq_policy *, unsigned int, unsigned int),
unsigned int powersave_bias);
}
}
-static unsigned int od_dbs_timer(struct cpu_dbs_info *cdbs,
- struct dbs_data *dbs_data, bool modify_all)
+static unsigned int od_dbs_timer(struct cpufreq_policy *policy, bool modify_all)
{
- struct cpufreq_policy *policy = cdbs->shared->policy;
+ struct dbs_data *dbs_data = policy->governor_data;
unsigned int cpu = policy->cpu;
struct od_cpu_dbs_info_s *dbs_info = &per_cpu(od_cpu_dbs_info,
cpu);
unsigned int new_rate)
{
struct od_dbs_tuners *od_tuners = dbs_data->tuners;
+ struct cpumask cpumask;
int cpu;
od_tuners->sampling_rate = new_rate = max(new_rate,
dbs_data->min_sampling_rate);
- for_each_online_cpu(cpu) {
+ /*
+ * Lock governor so that governor start/stop can't execute in parallel.
+ */
+ mutex_lock(&od_dbs_cdata.mutex);
+
+ cpumask_copy(&cpumask, cpu_online_mask);
+
+ for_each_cpu(cpu, &cpumask) {
struct cpufreq_policy *policy;
struct od_cpu_dbs_info_s *dbs_info;
+ struct cpu_dbs_info *cdbs;
+ struct cpu_common_dbs_info *shared;
unsigned long next_sampling, appointed_at;
- policy = cpufreq_cpu_get(cpu);
- if (!policy)
- continue;
- if (policy->governor != &cpufreq_gov_ondemand) {
- cpufreq_cpu_put(policy);
- continue;
- }
dbs_info = &per_cpu(od_cpu_dbs_info, cpu);
- cpufreq_cpu_put(policy);
+ cdbs = &dbs_info->cdbs;
+ shared = cdbs->shared;
- if (!delayed_work_pending(&dbs_info->cdbs.dwork))
+ /*
+ * A valid shared and shared->policy means governor hasn't
+ * stopped or exited yet.
+ */
+ if (!shared || !shared->policy)
+ continue;
+
+ policy = shared->policy;
+
+ /* clear all CPUs of this policy */
+ cpumask_andnot(&cpumask, &cpumask, policy->cpus);
+
+ /*
+ * Update sampling rate for CPUs whose policy is governed by
+ * dbs_data. In case of governor_per_policy, only a single
+ * policy will be governed by dbs_data, otherwise there can be
+ * multiple policies that are governed by the same dbs_data.
+ */
+ if (dbs_data != policy->governor_data)
continue;
+ /*
+ * Checking this for any CPU should be fine, timers for all of
+ * them are scheduled together.
+ */
next_sampling = jiffies + usecs_to_jiffies(new_rate);
- appointed_at = dbs_info->cdbs.dwork.timer.expires;
+ appointed_at = dbs_info->cdbs.timer.expires;
if (time_before(next_sampling, appointed_at)) {
- cancel_delayed_work_sync(&dbs_info->cdbs.dwork);
-
- gov_queue_work(dbs_data, policy,
- usecs_to_jiffies(new_rate), true);
+ gov_cancel_work(shared);
+ gov_add_timers(policy, usecs_to_jiffies(new_rate));
}
}
+
+ mutex_unlock(&od_dbs_cdata.mutex);
}
static ssize_t store_sampling_rate(struct dbs_data *dbs_data, const char *buf,
struct sample {
int32_t core_pct_busy;
+ int32_t busy_scaled;
u64 aperf;
u64 mperf;
u64 tsc;
u64 prev_aperf;
u64 prev_mperf;
u64 prev_tsc;
+ u64 prev_cummulative_iowait;
struct sample sample;
};
int (*get_scaling)(void);
void (*set)(struct cpudata*, int pstate);
void (*get_vid)(struct cpudata *);
+ int32_t (*get_target_pstate)(struct cpudata *);
};
struct cpu_defaults {
struct pstate_funcs funcs;
};
+static inline int32_t get_target_pstate_use_performance(struct cpudata *cpu);
+static inline int32_t get_target_pstate_use_cpu_load(struct cpudata *cpu);
+
static struct pstate_adjust_policy pid_params;
static struct pstate_funcs pstate_funcs;
static int hwp_active;
.get_turbo = core_get_turbo_pstate,
.get_scaling = core_get_scaling,
.set = core_set_pstate,
+ .get_target_pstate = get_target_pstate_use_performance,
},
};
.set = atom_set_pstate,
.get_scaling = silvermont_get_scaling,
.get_vid = atom_get_vid,
+ .get_target_pstate = get_target_pstate_use_cpu_load,
},
};
.set = atom_set_pstate,
.get_scaling = airmont_get_scaling,
.get_vid = atom_get_vid,
+ .get_target_pstate = get_target_pstate_use_cpu_load,
},
};
.get_turbo = knl_get_turbo_pstate,
.get_scaling = core_get_scaling,
.set = core_set_pstate,
+ .get_target_pstate = get_target_pstate_use_performance,
},
};
local_irq_save(flags);
rdmsrl(MSR_IA32_APERF, aperf);
rdmsrl(MSR_IA32_MPERF, mperf);
- if (cpu->prev_mperf == mperf) {
+ tsc = rdtsc();
+ if ((cpu->prev_mperf == mperf) || (cpu->prev_tsc == tsc)) {
local_irq_restore(flags);
return;
}
-
- tsc = rdtsc();
local_irq_restore(flags);
cpu->last_sample_time = cpu->sample.time;
mod_timer_pinned(&cpu->timer, jiffies + delay);
}
-static inline int32_t intel_pstate_get_scaled_busy(struct cpudata *cpu)
+static inline int32_t get_target_pstate_use_cpu_load(struct cpudata *cpu)
+{
+ struct sample *sample = &cpu->sample;
+ u64 cummulative_iowait, delta_iowait_us;
+ u64 delta_iowait_mperf;
+ u64 mperf, now;
+ int32_t cpu_load;
+
+ cummulative_iowait = get_cpu_iowait_time_us(cpu->cpu, &now);
+
+ /*
+ * Convert iowait time into number of IO cycles spent at max_freq.
+ * IO is considered as busy only for the cpu_load algorithm. For
+ * performance this is not needed since we always try to reach the
+ * maximum P-State, so we are already boosting the IOs.
+ */
+ delta_iowait_us = cummulative_iowait - cpu->prev_cummulative_iowait;
+ delta_iowait_mperf = div64_u64(delta_iowait_us * cpu->pstate.scaling *
+ cpu->pstate.max_pstate, MSEC_PER_SEC);
+
+ mperf = cpu->sample.mperf + delta_iowait_mperf;
+ cpu->prev_cummulative_iowait = cummulative_iowait;
+
+
+ /*
+ * The load can be estimated as the ratio of the mperf counter
+ * running at a constant frequency during active periods
+ * (C0) and the time stamp counter running at the same frequency
+ * also during C-states.
+ */
+ cpu_load = div64_u64(int_tofp(100) * mperf, sample->tsc);
+ cpu->sample.busy_scaled = cpu_load;
+
+ return cpu->pstate.current_pstate - pid_calc(&cpu->pid, cpu_load);
+}
+
+static inline int32_t get_target_pstate_use_performance(struct cpudata *cpu)
{
int32_t core_busy, max_pstate, current_pstate, sample_ratio;
s64 duration_us;
core_busy = mul_fp(core_busy, sample_ratio);
}
- return core_busy;
+ cpu->sample.busy_scaled = core_busy;
+ return cpu->pstate.current_pstate - pid_calc(&cpu->pid, core_busy);
}
static inline void intel_pstate_adjust_busy_pstate(struct cpudata *cpu)
{
- int32_t busy_scaled;
- struct _pid *pid;
- signed int ctl;
- int from;
+ int from, target_pstate;
struct sample *sample;
from = cpu->pstate.current_pstate;
- pid = &cpu->pid;
- busy_scaled = intel_pstate_get_scaled_busy(cpu);
+ target_pstate = pstate_funcs.get_target_pstate(cpu);
- ctl = pid_calc(pid, busy_scaled);
-
- /* Negative values of ctl increase the pstate and vice versa */
- intel_pstate_set_pstate(cpu, cpu->pstate.current_pstate - ctl, true);
+ intel_pstate_set_pstate(cpu, target_pstate, true);
sample = &cpu->sample;
trace_pstate_sample(fp_toint(sample->core_pct_busy),
- fp_toint(busy_scaled),
+ fp_toint(sample->busy_scaled),
from,
cpu->pstate.current_pstate,
sample->mperf,
pstate_funcs.get_scaling = funcs->get_scaling;
pstate_funcs.set = funcs->set;
pstate_funcs.get_vid = funcs->get_vid;
+ pstate_funcs.get_target_pstate = funcs->get_target_pstate;
+
}
#if IS_ENABLED(CONFIG_ACPI)
* the original PLL becomes stable at target frequency.
*/
struct mtk_cpu_dvfs_info {
+ struct cpumask cpus;
struct device *cpu_dev;
struct regulator *proc_reg;
struct regulator *sram_reg;
struct clk *cpu_clk;
struct clk *inter_clk;
struct thermal_cooling_device *cdev;
+ struct list_head list_head;
int intermediate_voltage;
bool need_voltage_tracking;
};
+static LIST_HEAD(dvfs_info_list);
+
+static struct mtk_cpu_dvfs_info *mtk_cpu_dvfs_info_lookup(int cpu)
+{
+ struct mtk_cpu_dvfs_info *info;
+ struct list_head *list;
+
+ list_for_each(list, &dvfs_info_list) {
+ info = list_entry(list, struct mtk_cpu_dvfs_info, list_head);
+
+ if (cpumask_test_cpu(cpu, &info->cpus))
+ return info;
+ }
+
+ return NULL;
+}
+
static int mtk_cpufreq_voltage_tracking(struct mtk_cpu_dvfs_info *info,
int new_vproc)
{
int old_vproc, old_vsram, new_vsram, vsram, vproc, ret;
old_vproc = regulator_get_voltage(proc_reg);
- old_vsram = regulator_get_voltage(sram_reg);
+ if (old_vproc < 0) {
+ pr_err("%s: invalid Vproc value: %d\n", __func__, old_vproc);
+ return old_vproc;
+ }
/* Vsram should not exceed the maximum allowed voltage of SoC. */
new_vsram = min(new_vproc + MIN_VOLT_SHIFT, MAX_VOLT_LIMIT);
*/
do {
old_vsram = regulator_get_voltage(sram_reg);
+ if (old_vsram < 0) {
+ pr_err("%s: invalid Vsram value: %d\n",
+ __func__, old_vsram);
+ return old_vsram;
+ }
old_vproc = regulator_get_voltage(proc_reg);
+ if (old_vproc < 0) {
+ pr_err("%s: invalid Vproc value: %d\n",
+ __func__, old_vproc);
+ return old_vproc;
+ }
vsram = min(new_vsram, old_vproc + MAX_VOLT_SHIFT);
*/
do {
old_vproc = regulator_get_voltage(proc_reg);
+ if (old_vproc < 0) {
+ pr_err("%s: invalid Vproc value: %d\n",
+ __func__, old_vproc);
+ return old_vproc;
+ }
old_vsram = regulator_get_voltage(sram_reg);
+ if (old_vsram < 0) {
+ pr_err("%s: invalid Vsram value: %d\n",
+ __func__, old_vsram);
+ return old_vsram;
+ }
vproc = max(new_vproc, old_vsram - MAX_VOLT_SHIFT);
ret = regulator_set_voltage(proc_reg, vproc,
old_freq_hz = clk_get_rate(cpu_clk);
old_vproc = regulator_get_voltage(info->proc_reg);
+ if (old_vproc < 0) {
+ pr_err("%s: invalid Vproc value: %d\n", __func__, old_vproc);
+ return old_vproc;
+ }
freq_hz = freq_table[index].frequency * 1000;
/* Both presence and absence of sram regulator are valid cases. */
sram_reg = regulator_get_exclusive(cpu_dev, "sram");
- ret = dev_pm_opp_of_add_table(cpu_dev);
+ /* Get OPP-sharing information from "operating-points-v2" bindings */
+ ret = dev_pm_opp_of_get_sharing_cpus(cpu_dev, &info->cpus);
+ if (ret) {
+ pr_err("failed to get OPP-sharing information for cpu%d\n",
+ cpu);
+ goto out_free_resources;
+ }
+
+ ret = dev_pm_opp_of_cpumask_add_table(&info->cpus);
if (ret) {
pr_warn("no OPP table for cpu%d\n", cpu);
goto out_free_resources;
return 0;
out_free_opp_table:
- dev_pm_opp_of_remove_table(cpu_dev);
+ dev_pm_opp_of_cpumask_remove_table(&info->cpus);
out_free_resources:
if (!IS_ERR(proc_reg))
if (!IS_ERR(info->inter_clk))
clk_put(info->inter_clk);
- dev_pm_opp_of_remove_table(info->cpu_dev);
+ dev_pm_opp_of_cpumask_remove_table(&info->cpus);
}
static int mtk_cpufreq_init(struct cpufreq_policy *policy)
struct cpufreq_frequency_table *freq_table;
int ret;
- info = kzalloc(sizeof(*info), GFP_KERNEL);
- if (!info)
- return -ENOMEM;
-
- ret = mtk_cpu_dvfs_info_init(info, policy->cpu);
- if (ret) {
- pr_err("%s failed to initialize dvfs info for cpu%d\n",
- __func__, policy->cpu);
- goto out_free_dvfs_info;
+ info = mtk_cpu_dvfs_info_lookup(policy->cpu);
+ if (!info) {
+ pr_err("dvfs info for cpu%d is not initialized.\n",
+ policy->cpu);
+ return -EINVAL;
}
ret = dev_pm_opp_init_cpufreq_table(info->cpu_dev, &freq_table);
if (ret) {
pr_err("failed to init cpufreq table for cpu%d: %d\n",
policy->cpu, ret);
- goto out_release_dvfs_info;
+ return ret;
}
ret = cpufreq_table_validate_and_show(policy, freq_table);
goto out_free_cpufreq_table;
}
- /* CPUs in the same cluster share a clock and power domain. */
- cpumask_copy(policy->cpus, &cpu_topology[policy->cpu].core_sibling);
+ cpumask_copy(policy->cpus, &info->cpus);
policy->driver_data = info;
policy->clk = info->cpu_clk;
out_free_cpufreq_table:
dev_pm_opp_free_cpufreq_table(info->cpu_dev, &freq_table);
-
-out_release_dvfs_info:
- mtk_cpu_dvfs_info_release(info);
-
-out_free_dvfs_info:
- kfree(info);
-
return ret;
}
cpufreq_cooling_unregister(info->cdev);
dev_pm_opp_free_cpufreq_table(info->cpu_dev, &policy->freq_table);
- mtk_cpu_dvfs_info_release(info);
- kfree(info);
return 0;
}
static struct cpufreq_driver mt8173_cpufreq_driver = {
- .flags = CPUFREQ_STICKY | CPUFREQ_NEED_INITIAL_FREQ_CHECK,
+ .flags = CPUFREQ_STICKY | CPUFREQ_NEED_INITIAL_FREQ_CHECK |
+ CPUFREQ_HAVE_GOVERNOR_PER_POLICY,
.verify = cpufreq_generic_frequency_table_verify,
.target_index = mtk_cpufreq_set_target,
.get = cpufreq_generic_get,
static int mt8173_cpufreq_probe(struct platform_device *pdev)
{
- int ret;
+ struct mtk_cpu_dvfs_info *info;
+ struct list_head *list, *tmp;
+ int cpu, ret;
+
+ for_each_possible_cpu(cpu) {
+ info = mtk_cpu_dvfs_info_lookup(cpu);
+ if (info)
+ continue;
+
+ info = devm_kzalloc(&pdev->dev, sizeof(*info), GFP_KERNEL);
+ if (!info) {
+ ret = -ENOMEM;
+ goto release_dvfs_info_list;
+ }
+
+ ret = mtk_cpu_dvfs_info_init(info, cpu);
+ if (ret) {
+ dev_err(&pdev->dev,
+ "failed to initialize dvfs info for cpu%d\n",
+ cpu);
+ goto release_dvfs_info_list;
+ }
+
+ list_add(&info->list_head, &dvfs_info_list);
+ }
ret = cpufreq_register_driver(&mt8173_cpufreq_driver);
- if (ret)
- pr_err("failed to register mtk cpufreq driver\n");
+ if (ret) {
+ dev_err(&pdev->dev, "failed to register mtk cpufreq driver\n");
+ goto release_dvfs_info_list;
+ }
+
+ return 0;
+
+release_dvfs_info_list:
+ list_for_each_safe(list, tmp, &dvfs_info_list) {
+ info = list_entry(list, struct mtk_cpu_dvfs_info, list_head);
+
+ mtk_cpu_dvfs_info_release(info);
+ list_del(list);
+ }
return ret;
}
policy->min = policy->cpuinfo.min_freq =
ioread32(&pcch_hdr->minimum_frequency) * 1000;
+ policy->cpuinfo.transition_latency = CPUFREQ_ETERNAL;
+
pr_debug("init: policy->max is %d, policy->min is %d\n",
policy->max, policy->min);
out:
#include <linux/clk.h>
#include <linux/cpufreq.h>
+#include <linux/cpu_cooling.h>
#include <linux/errno.h>
#include <linux/init.h>
#include <linux/kernel.h>
struct cpu_data {
struct clk **pclk;
struct cpufreq_frequency_table *table;
+ struct thermal_cooling_device *cdev;
};
/**
return clk_set_parent(policy->clk, parent);
}
+
+static void qoriq_cpufreq_ready(struct cpufreq_policy *policy)
+{
+ struct cpu_data *cpud = policy->driver_data;
+ struct device_node *np = of_get_cpu_node(policy->cpu, NULL);
+
+ if (of_find_property(np, "#cooling-cells", NULL)) {
+ cpud->cdev = of_cpufreq_cooling_register(np,
+ policy->related_cpus);
+
+ if (IS_ERR(cpud->cdev)) {
+ pr_err("Failed to register cooling device cpu%d: %ld\n",
+ policy->cpu, PTR_ERR(cpud->cdev));
+
+ cpud->cdev = NULL;
+ }
+ }
+
+ of_node_put(np);
+}
+
static struct cpufreq_driver qoriq_cpufreq_driver = {
.name = "qoriq_cpufreq",
.flags = CPUFREQ_CONST_LOOPS,
.verify = cpufreq_generic_frequency_table_verify,
.target_index = qoriq_cpufreq_target,
.get = cpufreq_generic_get,
+ .ready = qoriq_cpufreq_ready,
.attr = cpufreq_generic_attr,
};
--- /dev/null
+/*
+ * Match running platform with pre-defined OPP values for CPUFreq
+ *
+ * Author: Ajit Pal Singh <ajitpal.singh@st.com>
+ * Lee Jones <lee.jones@linaro.org>
+ *
+ * Copyright (C) 2015 STMicroelectronics (R&D) Limited
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the version 2 of the GNU General Public License as
+ * published by the Free Software Foundation
+ */
+
+#include <linux/cpu.h>
+#include <linux/io.h>
+#include <linux/mfd/syscon.h>
+#include <linux/module.h>
+#include <linux/of.h>
+#include <linux/of_platform.h>
+#include <linux/pm_opp.h>
+#include <linux/regmap.h>
+
+#define VERSION_ELEMENTS 3
+#define MAX_PCODE_NAME_LEN 7
+
+#define VERSION_SHIFT 28
+#define HW_INFO_INDEX 1
+#define MAJOR_ID_INDEX 1
+#define MINOR_ID_INDEX 2
+
+/*
+ * Only match on "suitable for ALL versions" entries
+ *
+ * This will be used with the BIT() macro. It sets the
+ * top bit of a 32bit value and is equal to 0x80000000.
+ */
+#define DEFAULT_VERSION 31
+
+enum {
+ PCODE = 0,
+ SUBSTRATE,
+ DVFS_MAX_REGFIELDS,
+};
+
+/**
+ * ST CPUFreq Driver Data
+ *
+ * @cpu_node CPU's OF node
+ * @syscfg_eng Engineering Syscon register map
+ * @regmap Syscon register map
+ */
+static struct sti_cpufreq_ddata {
+ struct device *cpu;
+ struct regmap *syscfg_eng;
+ struct regmap *syscfg;
+} ddata;
+
+static int sti_cpufreq_fetch_major(void) {
+ struct device_node *np = ddata.cpu->of_node;
+ struct device *dev = ddata.cpu;
+ unsigned int major_offset;
+ unsigned int socid;
+ int ret;
+
+ ret = of_property_read_u32_index(np, "st,syscfg",
+ MAJOR_ID_INDEX, &major_offset);
+ if (ret) {
+ dev_err(dev, "No major number offset provided in %s [%d]\n",
+ np->full_name, ret);
+ return ret;
+ }
+
+ ret = regmap_read(ddata.syscfg, major_offset, &socid);
+ if (ret) {
+ dev_err(dev, "Failed to read major number from syscon [%d]\n",
+ ret);
+ return ret;
+ }
+
+ return ((socid >> VERSION_SHIFT) & 0xf) + 1;
+}
+
+static int sti_cpufreq_fetch_minor(void)
+{
+ struct device *dev = ddata.cpu;
+ struct device_node *np = dev->of_node;
+ unsigned int minor_offset;
+ unsigned int minid;
+ int ret;
+
+ ret = of_property_read_u32_index(np, "st,syscfg-eng",
+ MINOR_ID_INDEX, &minor_offset);
+ if (ret) {
+ dev_err(dev,
+ "No minor number offset provided %s [%d]\n",
+ np->full_name, ret);
+ return ret;
+ }
+
+ ret = regmap_read(ddata.syscfg_eng, minor_offset, &minid);
+ if (ret) {
+ dev_err(dev,
+ "Failed to read the minor number from syscon [%d]\n",
+ ret);
+ return ret;
+ }
+
+ return minid & 0xf;
+}
+
+static int sti_cpufreq_fetch_regmap_field(const struct reg_field *reg_fields,
+ int hw_info_offset, int field)
+{
+ struct regmap_field *regmap_field;
+ struct reg_field reg_field = reg_fields[field];
+ struct device *dev = ddata.cpu;
+ unsigned int value;
+ int ret;
+
+ reg_field.reg = hw_info_offset;
+ regmap_field = devm_regmap_field_alloc(dev,
+ ddata.syscfg_eng,
+ reg_field);
+ if (IS_ERR(regmap_field)) {
+ dev_err(dev, "Failed to allocate reg field\n");
+ return PTR_ERR(regmap_field);
+ }
+
+ ret = regmap_field_read(regmap_field, &value);
+ if (ret) {
+ dev_err(dev, "Failed to read %s code\n",
+ field ? "SUBSTRATE" : "PCODE");
+ return ret;
+ }
+
+ return value;
+}
+
+static const struct reg_field sti_stih407_dvfs_regfields[DVFS_MAX_REGFIELDS] = {
+ [PCODE] = REG_FIELD(0, 16, 19),
+ [SUBSTRATE] = REG_FIELD(0, 0, 2),
+};
+
+static const struct reg_field *sti_cpufreq_match(void)
+{
+ if (of_machine_is_compatible("st,stih407") ||
+ of_machine_is_compatible("st,stih410"))
+ return sti_stih407_dvfs_regfields;
+
+ return NULL;
+}
+
+static int sti_cpufreq_set_opp_info(void)
+{
+ struct device *dev = ddata.cpu;
+ struct device_node *np = dev->of_node;
+ const struct reg_field *reg_fields;
+ unsigned int hw_info_offset;
+ unsigned int version[VERSION_ELEMENTS];
+ int pcode, substrate, major, minor;
+ int ret;
+ char name[MAX_PCODE_NAME_LEN];
+
+ reg_fields = sti_cpufreq_match();
+ if (!reg_fields) {
+ dev_err(dev, "This SoC doesn't support voltage scaling");
+ return -ENODEV;
+ }
+
+ ret = of_property_read_u32_index(np, "st,syscfg-eng",
+ HW_INFO_INDEX, &hw_info_offset);
+ if (ret) {
+ dev_warn(dev, "Failed to read HW info offset from DT\n");
+ substrate = DEFAULT_VERSION;
+ pcode = 0;
+ goto use_defaults;
+ }
+
+ pcode = sti_cpufreq_fetch_regmap_field(reg_fields,
+ hw_info_offset,
+ PCODE);
+ if (pcode < 0) {
+ dev_warn(dev, "Failed to obtain process code\n");
+ /* Use default pcode */
+ pcode = 0;
+ }
+
+ substrate = sti_cpufreq_fetch_regmap_field(reg_fields,
+ hw_info_offset,
+ SUBSTRATE);
+ if (substrate) {
+ dev_warn(dev, "Failed to obtain substrate code\n");
+ /* Use default substrate */
+ substrate = DEFAULT_VERSION;
+ }
+
+use_defaults:
+ major = sti_cpufreq_fetch_major();
+ if (major < 0) {
+ dev_err(dev, "Failed to obtain major version\n");
+ /* Use default major number */
+ major = DEFAULT_VERSION;
+ }
+
+ minor = sti_cpufreq_fetch_minor();
+ if (minor < 0) {
+ dev_err(dev, "Failed to obtain minor version\n");
+ /* Use default minor number */
+ minor = DEFAULT_VERSION;
+ }
+
+ snprintf(name, MAX_PCODE_NAME_LEN, "pcode%d", pcode);
+
+ ret = dev_pm_opp_set_prop_name(dev, name);
+ if (ret) {
+ dev_err(dev, "Failed to set prop name\n");
+ return ret;
+ }
+
+ version[0] = BIT(major);
+ version[1] = BIT(minor);
+ version[2] = BIT(substrate);
+
+ ret = dev_pm_opp_set_supported_hw(dev, version, VERSION_ELEMENTS);
+ if (ret) {
+ dev_err(dev, "Failed to set supported hardware\n");
+ return ret;
+ }
+
+ dev_dbg(dev, "pcode: %d major: %d minor: %d substrate: %d\n",
+ pcode, major, minor, substrate);
+ dev_dbg(dev, "version[0]: %x version[1]: %x version[2]: %x\n",
+ version[0], version[1], version[2]);
+
+ return 0;
+}
+
+static int sti_cpufreq_fetch_syscon_regsiters(void)
+{
+ struct device *dev = ddata.cpu;
+ struct device_node *np = dev->of_node;
+
+ ddata.syscfg = syscon_regmap_lookup_by_phandle(np, "st,syscfg");
+ if (IS_ERR(ddata.syscfg)) {
+ dev_err(dev, "\"st,syscfg\" not supplied\n");
+ return PTR_ERR(ddata.syscfg);
+ }
+
+ ddata.syscfg_eng = syscon_regmap_lookup_by_phandle(np, "st,syscfg-eng");
+ if (IS_ERR(ddata.syscfg_eng)) {
+ dev_err(dev, "\"st,syscfg-eng\" not supplied\n");
+ return PTR_ERR(ddata.syscfg_eng);
+ }
+
+ return 0;
+}
+
+static int sti_cpufreq_init(void)
+{
+ int ret;
+
+ ddata.cpu = get_cpu_device(0);
+ if (!ddata.cpu) {
+ dev_err(ddata.cpu, "Failed to get device for CPU0\n");
+ goto skip_voltage_scaling;
+ }
+
+ if (!of_get_property(ddata.cpu->of_node, "operating-points-v2", NULL)) {
+ dev_err(ddata.cpu, "OPP-v2 not supported\n");
+ goto skip_voltage_scaling;
+ }
+
+ ret = sti_cpufreq_fetch_syscon_regsiters();
+ if (ret)
+ goto skip_voltage_scaling;
+
+ ret = sti_cpufreq_set_opp_info();
+ if (!ret)
+ goto register_cpufreq_dt;
+
+skip_voltage_scaling:
+ dev_err(ddata.cpu, "Not doing voltage scaling\n");
+
+register_cpufreq_dt:
+ platform_device_register_simple("cpufreq-dt", -1, NULL, 0);
+
+ return 0;
+}
+module_init(sti_cpufreq_init);
+
+MODULE_DESCRIPTION("STMicroelectronics CPUFreq/OPP driver");
+MODULE_AUTHOR("Ajitpal Singh <ajitpal.singh@st.com>");
+MODULE_AUTHOR("Lee Jones <lee.jones@linaro.org>");
+MODULE_LICENSE("GPL v2");
#include <linux/cpuidle.h>
#include <linux/err.h>
#include <linux/io.h>
-#include <linux/module.h>
+#include <linux/init.h>
#include <linux/platform_device.h>
#define CLPS711X_CPUIDLE_NAME "clps711x-cpuidle"
.name = CLPS711X_CPUIDLE_NAME,
},
};
-module_platform_driver_probe(clps711x_cpuidle_driver, clps711x_cpuidle_probe);
-
-MODULE_AUTHOR("Alexander Shiyan <shc_work@mail.ru>");
-MODULE_DESCRIPTION("CLPS711X CPU idle driver");
-MODULE_LICENSE("GPL");
+builtin_platform_driver_probe(clps711x_cpuidle_driver, clps711x_cpuidle_probe);
#include <linux/cpuidle.h>
#include <linux/cpu_pm.h>
#include <linux/export.h>
-#include <linux/module.h>
+#include <linux/init.h>
#include <linux/platform_device.h>
#include <linux/of.h>
#include <linux/platform_data/cpuidle-exynos.h>
.name = "exynos_cpuidle",
},
};
-
-module_platform_driver(exynos_cpuidle_driver);
+builtin_platform_driver(exynos_cpuidle_driver);
* published by the Free Software Foundation.
*/
-#include <linux/module.h>
+#include <linux/init.h>
#include <linux/cpuidle.h>
#include <linux/spinlock.h>
#include <linux/atomic.h>
},
.probe = dbx500_cpuidle_probe,
};
-
-module_platform_driver(dbx500_cpuidle_plat_driver);
+builtin_platform_driver(dbx500_cpuidle_plat_driver);
* We want to default to C1 (hlt), not to busy polling
* unless the timer is happening really really soon.
*/
- if (data->next_timer_us > 5 &&
+ if (interactivity_req > 20 &&
!drv->states[CPUIDLE_DRIVER_STATE_START].disabled &&
dev->states_usage[CPUIDLE_DRIVER_STATE_START].disable == 0)
data->last_state_idx = CPUIDLE_DRIVER_STATE_START;
measured_us = cpuidle_get_last_residency(dev);
/* Deduct exit latency */
- if (measured_us > target->exit_latency)
+ if (measured_us > 2 * target->exit_latency)
measured_us -= target->exit_latency;
+ else
+ measured_us /= 2;
/* Make sure our coefficients do not exceed unity */
if (measured_us > data->next_timer_us)
static irqreturn_t dw_dma_interrupt(int irq, void *dev_id)
{
struct dw_dma *dw = dev_id;
- u32 status = dma_readl(dw, STATUS_INT);
+ u32 status;
+ /* Check if we have any interrupt from the DMAC which is not in use */
+ if (!dw->in_use)
+ return IRQ_NONE;
+
+ status = dma_readl(dw, STATUS_INT);
dev_vdbg(dw->dma.dev, "%s: status=0x%x\n", __func__, status);
/* Check if we have any interrupt from the DMAC */
- if (!status || !dw->in_use)
+ if (!status)
return IRQ_NONE;
/*
struct dw_dma_chip *chip;
struct device *dev = &pdev->dev;
struct resource *mem;
- const struct acpi_device_id *id;
struct dw_dma_platform_data *pdata;
int err;
pdata = dev_get_platdata(dev);
if (!pdata)
pdata = dw_dma_parse_dt(pdev);
- if (!pdata && has_acpi_companion(dev)) {
- id = acpi_match_device(dev->driver->acpi_match_table, dev);
- if (id)
- pdata = (struct dw_dma_platform_data *)id->driver_data;
- }
chip->dev = dev;
{
struct dw_dma_chip *chip = platform_get_drvdata(pdev);
+ /*
+ * We have to call dw_dma_disable() to stop any ongoing transfer. On
+ * some platforms we can't do that since DMA device is powered off.
+ * Moreover we have no possibility to check if the platform is affected
+ * or not. That's why we call pm_runtime_get_sync() / pm_runtime_put()
+ * unconditionally. On the other hand we can't use
+ * pm_runtime_suspended() because runtime PM framework is not fully
+ * used by the driver.
+ */
+ pm_runtime_get_sync(chip->dev);
dw_dma_disable(chip);
+ pm_runtime_put_sync_suspend(chip->dev);
+
clk_disable_unprepare(chip->clk);
}
#endif
#ifdef CONFIG_ACPI
-static struct dw_dma_platform_data dw_dma_acpi_pdata = {
- .nr_channels = 8,
- .is_private = true,
- .chan_allocation_order = CHAN_ALLOCATION_ASCENDING,
- .chan_priority = CHAN_PRIORITY_ASCENDING,
- .block_size = 4095,
- .nr_masters = 2,
-};
-
static const struct acpi_device_id dw_dma_acpi_id_table[] = {
- { "INTL9C60", (kernel_ulong_t)&dw_dma_acpi_pdata },
+ { "INTL9C60", 0 },
{ }
};
MODULE_DEVICE_TABLE(acpi, dw_dma_acpi_id_table);
* ActiveLow is only specified for GpioInt resource. If
* GpioIo is used then the only way to set the flag is
* to use _DSD "gpios" property.
+ * Note: we expect here:
+ * - ACPI_ACTIVE_LOW == GPIO_ACTIVE_LOW
+ * - ACPI_ACTIVE_HIGH == GPIO_ACTIVE_HIGH
*/
- if (lookup->info.gpioint)
- lookup->info.active_low =
- agpio->polarity == ACPI_ACTIVE_LOW;
+ if (lookup->info.gpioint) {
+ lookup->info.polarity = agpio->polarity;
+ lookup->info.triggering = agpio->triggering;
+ }
+
}
return 1;
if (info) {
*info = lookup->info;
if (lookup->active_low)
- info->active_low = lookup->active_low;
+ info->polarity = lookup->active_low;
}
return 0;
}
int acpi_dev_gpio_irq_get(struct acpi_device *adev, int index)
{
int idx, i;
+ unsigned int irq_flags;
for (i = 0, idx = 0; idx <= index; i++) {
struct acpi_gpio_info info;
desc = acpi_get_gpiod_by_index(adev, NULL, i, &info);
if (IS_ERR(desc))
break;
- if (info.gpioint && idx++ == index)
- return gpiod_to_irq(desc);
+ if (info.gpioint && idx++ == index) {
+ int irq = gpiod_to_irq(desc);
+
+ if (irq < 0)
+ return irq;
+
+ irq_flags = acpi_dev_get_irq_type(info.triggering,
+ info.polarity);
+
+ /* Set type if specified and different than the current one */
+ if (irq_flags != IRQ_TYPE_NONE &&
+ irq_flags != irq_get_trigger_type(irq))
+ irq_set_irq_type(irq, irq_flags);
+
+ return irq;
+ }
+
}
return -ENOENT;
}
return desc;
}
- if (info.active_low)
+ if (info.polarity == GPIO_ACTIVE_LOW)
*flags |= GPIO_ACTIVE_LOW;
return desc;
desc = acpi_node_get_gpiod(fwnode, propname, 0, &info);
if (!IS_ERR(desc))
- active_low = info.active_low;
+ active_low = info.polarity == GPIO_ACTIVE_LOW;
}
if (IS_ERR(desc))
*/
struct acpi_gpio_info {
bool gpioint;
- bool active_low;
+ int polarity;
+ int triggering;
};
/* gpio suffixes used for ACPI and device tree lookup */
u32 data;
int ret;
- ret = iosf_mbi_read(BT_MBI_UNIT_PMC, BT_MBI_BUNIT_READ, PUNIT_SEMAPHORE,
- &data);
+ ret = iosf_mbi_read(BT_MBI_UNIT_PMC, MBI_REG_READ, PUNIT_SEMAPHORE, &data);
if (ret) {
dev_err(dev, "iosf failed to read punit semaphore\n");
return ret;
{
u32 data;
- if (iosf_mbi_read(BT_MBI_UNIT_PMC, BT_MBI_BUNIT_READ,
- PUNIT_SEMAPHORE, &data)) {
+ if (iosf_mbi_read(BT_MBI_UNIT_PMC, MBI_REG_READ, PUNIT_SEMAPHORE, &data)) {
dev_err(dev, "iosf failed to reset punit semaphore during read\n");
return;
}
data &= ~PUNIT_SEMAPHORE_BIT;
- if (iosf_mbi_write(BT_MBI_UNIT_PMC, BT_MBI_BUNIT_WRITE,
- PUNIT_SEMAPHORE, data))
+ if (iosf_mbi_write(BT_MBI_UNIT_PMC, MBI_REG_WRITE, PUNIT_SEMAPHORE, data))
dev_err(dev, "iosf failed to reset punit semaphore during write\n");
}
static int baytrail_i2c_acquire(struct dw_i2c_dev *dev)
{
- u32 sem;
+ u32 sem = PUNIT_SEMAPHORE_ACQUIRE;
int ret;
unsigned long start, end;
return 0;
/* host driver writes to side band semaphore register */
- ret = iosf_mbi_write(BT_MBI_UNIT_PMC, BT_MBI_BUNIT_WRITE,
- PUNIT_SEMAPHORE, PUNIT_SEMAPHORE_ACQUIRE);
+ ret = iosf_mbi_write(BT_MBI_UNIT_PMC, MBI_REG_WRITE, PUNIT_SEMAPHORE, sem);
if (ret) {
dev_err(dev->dev, "iosf punit semaphore request failed\n");
return ret;
dev_err(dev->dev, "punit semaphore timed out, resetting\n");
reset_semaphore(dev->dev);
- ret = iosf_mbi_read(BT_MBI_UNIT_PMC, BT_MBI_BUNIT_READ,
- PUNIT_SEMAPHORE, &sem);
+ ret = iosf_mbi_read(BT_MBI_UNIT_PMC, MBI_REG_READ, PUNIT_SEMAPHORE, &sem);
if (ret)
dev_err(dev->dev, "iosf failed to read punit semaphore\n");
else
#include <linux/platform_device.h>
#include <linux/pm.h>
#include <linux/pm_runtime.h>
+#include <linux/property.h>
#include <linux/io.h>
#include <linux/slab.h>
#include <linux/acpi.h>
{ "80860F41", 0 },
{ "808622C1", 0 },
{ "AMD0010", ACCESS_INTR_MASK },
+ { "APMC0D0F", 0 },
{ }
};
MODULE_DEVICE_TABLE(acpi, dw_i2c_acpi_match);
static int dw_i2c_plat_probe(struct platform_device *pdev)
{
+ struct dw_i2c_platform_data *pdata = dev_get_platdata(&pdev->dev);
struct dw_i2c_dev *dev;
struct i2c_adapter *adap;
struct resource *mem;
- struct dw_i2c_platform_data *pdata;
int irq, r;
u32 clk_freq, ht = 0;
/* fast mode by default because of legacy reasons */
clk_freq = 400000;
- if (has_acpi_companion(&pdev->dev)) {
- dw_i2c_acpi_configure(pdev);
- } else if (pdev->dev.of_node) {
- of_property_read_u32(pdev->dev.of_node,
- "i2c-sda-hold-time-ns", &ht);
-
- of_property_read_u32(pdev->dev.of_node,
- "i2c-sda-falling-time-ns",
- &dev->sda_falling_time);
- of_property_read_u32(pdev->dev.of_node,
- "i2c-scl-falling-time-ns",
- &dev->scl_falling_time);
-
- of_property_read_u32(pdev->dev.of_node, "clock-frequency",
- &clk_freq);
-
- /* Only standard mode at 100kHz and fast mode at 400kHz
- * are supported.
- */
- if (clk_freq != 100000 && clk_freq != 400000) {
- dev_err(&pdev->dev, "Only 100kHz and 400kHz supported");
- return -EINVAL;
- }
+ if (pdata) {
+ clk_freq = pdata->i2c_scl_freq;
} else {
- pdata = dev_get_platdata(&pdev->dev);
- if (pdata)
- clk_freq = pdata->i2c_scl_freq;
+ device_property_read_u32(&pdev->dev, "i2c-sda-hold-time-ns",
+ &ht);
+ device_property_read_u32(&pdev->dev, "i2c-sda-falling-time-ns",
+ &dev->sda_falling_time);
+ device_property_read_u32(&pdev->dev, "i2c-scl-falling-time-ns",
+ &dev->scl_falling_time);
+ device_property_read_u32(&pdev->dev, "clock-frequency",
+ &clk_freq);
+ }
+
+ if (has_acpi_companion(&pdev->dev))
+ dw_i2c_acpi_configure(pdev);
+
+ /*
+ * Only standard mode at 100kHz and fast mode at 400kHz are supported.
+ */
+ if (clk_freq != 100000 && clk_freq != 400000) {
+ dev_err(&pdev->dev, "Only 100kHz and 400kHz supported");
+ return -EINVAL;
}
r = i2c_dw_eval_lock_support(dev);
#include <linux/pm.h>
#include <linux/pm_runtime.h>
#include <linux/platform_device.h>
+#include <linux/property.h>
#include "intel-lpss.h"
.clk_rate = 120000000,
};
+static struct property_entry spt_i2c_properties[] = {
+ PROPERTY_ENTRY_U32("i2c-sda-hold-time-ns", 230),
+ { },
+};
+
+static struct property_set spt_i2c_pset = {
+ .properties = spt_i2c_properties,
+};
+
+static const struct intel_lpss_platform_info spt_i2c_info = {
+ .clk_rate = 120000000,
+ .pset = &spt_i2c_pset,
+};
+
static const struct intel_lpss_platform_info bxt_info = {
.clk_rate = 100000000,
};
static const struct acpi_device_id intel_lpss_acpi_ids[] = {
/* SPT */
- { "INT3446", (kernel_ulong_t)&spt_info },
- { "INT3447", (kernel_ulong_t)&spt_info },
+ { "INT3446", (kernel_ulong_t)&spt_i2c_info },
+ { "INT3447", (kernel_ulong_t)&spt_i2c_info },
/* BXT */
{ "80860AAC", (kernel_ulong_t)&bxt_i2c_info },
{ "80860ABC", (kernel_ulong_t)&bxt_info },
#include <linux/pci.h>
#include <linux/pm.h>
#include <linux/pm_runtime.h>
+#include <linux/property.h>
#include "intel-lpss.h"
.clk_rate = 120000000,
};
+static struct property_entry spt_i2c_properties[] = {
+ PROPERTY_ENTRY_U32("i2c-sda-hold-time-ns", 230),
+ { },
+};
+
+static struct property_set spt_i2c_pset = {
+ .properties = spt_i2c_properties,
+};
+
+static const struct intel_lpss_platform_info spt_i2c_info = {
+ .clk_rate = 120000000,
+ .pset = &spt_i2c_pset,
+};
+
+static struct property_entry uart_properties[] = {
+ PROPERTY_ENTRY_U32("reg-io-width", 4),
+ PROPERTY_ENTRY_U32("reg-shift", 2),
+ PROPERTY_ENTRY_BOOL("snps,uart-16550-compatible"),
+ { },
+};
+
+static struct property_set uart_pset = {
+ .properties = uart_properties,
+};
+
static const struct intel_lpss_platform_info spt_uart_info = {
.clk_rate = 120000000,
.clk_con_id = "baudclk",
+ .pset = &uart_pset,
};
static const struct intel_lpss_platform_info bxt_info = {
static const struct intel_lpss_platform_info bxt_uart_info = {
.clk_rate = 100000000,
.clk_con_id = "baudclk",
+ .pset = &uart_pset,
};
static const struct intel_lpss_platform_info bxt_i2c_info = {
{ PCI_VDEVICE(INTEL, 0x9d28), (kernel_ulong_t)&spt_uart_info },
{ PCI_VDEVICE(INTEL, 0x9d29), (kernel_ulong_t)&spt_info },
{ PCI_VDEVICE(INTEL, 0x9d2a), (kernel_ulong_t)&spt_info },
- { PCI_VDEVICE(INTEL, 0x9d60), (kernel_ulong_t)&spt_info },
- { PCI_VDEVICE(INTEL, 0x9d61), (kernel_ulong_t)&spt_info },
- { PCI_VDEVICE(INTEL, 0x9d62), (kernel_ulong_t)&spt_info },
- { PCI_VDEVICE(INTEL, 0x9d63), (kernel_ulong_t)&spt_info },
- { PCI_VDEVICE(INTEL, 0x9d64), (kernel_ulong_t)&spt_info },
- { PCI_VDEVICE(INTEL, 0x9d65), (kernel_ulong_t)&spt_info },
+ { PCI_VDEVICE(INTEL, 0x9d60), (kernel_ulong_t)&spt_i2c_info },
+ { PCI_VDEVICE(INTEL, 0x9d61), (kernel_ulong_t)&spt_i2c_info },
+ { PCI_VDEVICE(INTEL, 0x9d62), (kernel_ulong_t)&spt_i2c_info },
+ { PCI_VDEVICE(INTEL, 0x9d63), (kernel_ulong_t)&spt_i2c_info },
+ { PCI_VDEVICE(INTEL, 0x9d64), (kernel_ulong_t)&spt_i2c_info },
+ { PCI_VDEVICE(INTEL, 0x9d65), (kernel_ulong_t)&spt_i2c_info },
{ PCI_VDEVICE(INTEL, 0x9d66), (kernel_ulong_t)&spt_uart_info },
/* SPT-H */
{ PCI_VDEVICE(INTEL, 0xa127), (kernel_ulong_t)&spt_uart_info },
{ PCI_VDEVICE(INTEL, 0xa128), (kernel_ulong_t)&spt_uart_info },
{ PCI_VDEVICE(INTEL, 0xa129), (kernel_ulong_t)&spt_info },
{ PCI_VDEVICE(INTEL, 0xa12a), (kernel_ulong_t)&spt_info },
- { PCI_VDEVICE(INTEL, 0xa160), (kernel_ulong_t)&spt_info },
- { PCI_VDEVICE(INTEL, 0xa161), (kernel_ulong_t)&spt_info },
+ { PCI_VDEVICE(INTEL, 0xa160), (kernel_ulong_t)&spt_i2c_info },
+ { PCI_VDEVICE(INTEL, 0xa161), (kernel_ulong_t)&spt_i2c_info },
{ PCI_VDEVICE(INTEL, 0xa166), (kernel_ulong_t)&spt_uart_info },
{ }
};
#include <linux/mfd/core.h>
#include <linux/pm_qos.h>
#include <linux/pm_runtime.h>
+#include <linux/property.h>
#include <linux/seq_file.h>
#include <linux/io-64-nonatomic-lo-hi.h>
enum intel_lpss_dev_type type;
struct clk *clk;
struct clk_lookup *clock;
- const struct mfd_cell *cell;
+ struct mfd_cell *cell;
struct device *dev;
void __iomem *priv;
int devid;
static int intel_lpss_assign_devs(struct intel_lpss *lpss)
{
+ const struct mfd_cell *cell;
unsigned int type;
type = lpss->caps & LPSS_PRIV_CAPS_TYPE_MASK;
switch (type) {
case LPSS_DEV_I2C:
- lpss->cell = &intel_lpss_i2c_cell;
+ cell = &intel_lpss_i2c_cell;
break;
case LPSS_DEV_UART:
- lpss->cell = &intel_lpss_uart_cell;
+ cell = &intel_lpss_uart_cell;
break;
case LPSS_DEV_SPI:
- lpss->cell = &intel_lpss_spi_cell;
+ cell = &intel_lpss_spi_cell;
break;
default:
return -ENODEV;
}
+ lpss->cell = devm_kmemdup(lpss->dev, cell, sizeof(*cell), GFP_KERNEL);
+ if (!lpss->cell)
+ return -ENOMEM;
+
lpss->type = type;
return 0;
if (ret)
return ret;
+ lpss->cell->pset = info->pset;
+
intel_lpss_init_dev(lpss);
lpss->devid = ida_simple_get(&intel_lpss_devid_ida, 0, 0, GFP_KERNEL);
struct device;
struct resource;
+struct property_set;
struct intel_lpss_platform_info {
struct resource *mem;
int irq;
unsigned long clk_rate;
const char *clk_con_id;
+ struct property_set *pset;
};
int intel_lpss_probe(struct device *dev,
#include <linux/kernel.h>
#include <linux/platform_device.h>
#include <linux/acpi.h>
+#include <linux/property.h>
#include <linux/mfd/core.h>
#include <linux/pm_runtime.h>
#include <linux/slab.h>
goto fail_alias;
}
+ if (cell->pset) {
+ ret = platform_device_add_properties(pdev, cell->pset);
+ if (ret)
+ goto fail_alias;
+ }
+
ret = mfd_platform_add_cell(pdev, cell, usage_count);
if (ret)
goto fail_alias;
return !!adev->power.flags.dsw_present;
}
-static struct pci_platform_pm_ops acpi_pci_platform_pm = {
+static const struct pci_platform_pm_ops acpi_pci_platform_pm = {
.is_manageable = acpi_pci_power_manageable,
.set_state = acpi_pci_set_power_state,
.choose_state = acpi_pci_choose_state,
pci_update_resource(dev, i);
}
-static struct pci_platform_pm_ops *pci_platform_pm;
+static const struct pci_platform_pm_ops *pci_platform_pm;
-int pci_set_platform_pm(struct pci_platform_pm_ops *ops)
+int pci_set_platform_pm(const struct pci_platform_pm_ops *ops)
{
if (!ops->is_manageable || !ops->set_state || !ops->choose_state
|| !ops->sleep_wake)
bool (*need_resume)(struct pci_dev *dev);
};
-int pci_set_platform_pm(struct pci_platform_pm_ops *ops);
+int pci_set_platform_pm(const struct pci_platform_pm_ops *ops);
void pci_update_current_state(struct pci_dev *dev, pci_power_t state);
void pci_power_up(struct pci_dev *dev);
void pci_disable_enabled_device(struct pci_dev *dev);
#define DELL_EVENT_GUID "9DBB5994-A997-11DA-B012-B622A1EF5492"
-static int acpi_video;
-
MODULE_ALIAS("wmi:"DELL_EVENT_GUID);
/*
/* Don't report brightness notifications that will also come via ACPI */
if ((key->keycode == KEY_BRIGHTNESSUP ||
- key->keycode == KEY_BRIGHTNESSDOWN) && acpi_video)
+ key->keycode == KEY_BRIGHTNESSDOWN) &&
+ acpi_video_handles_brightness_key_presses())
return;
sparse_keymap_report_entry(dell_wmi_input_dev, key, 1, true);
}
dmi_walk(find_hk_type, NULL);
- acpi_video = acpi_video_get_backlight_type() != acpi_backlight_vendor;
err = dell_wmi_input_setup();
if (err)
/* Do not issue duplicate brightness change events to
* userspace. tpacpi_detect_brightness_capabilities() must have
* been called before this point */
- if (acpi_video_get_backlight_type() != acpi_backlight_vendor) {
+ if (acpi_video_handles_brightness_key_presses()) {
pr_info("This ThinkPad has standard ACPI backlight "
"brightness control, supported by the ACPI "
"video driver\n");
if (pnp_dev->status == PNP_ATTACHED)
pnp_dev->status = PNP_READY;
mutex_unlock(&pnp_lock);
- pnp_disable_dev(pnp_dev);
}
static int pnp_device_probe(struct device *dev)
drv->remove(pnp_dev);
pnp_dev->driver = NULL;
}
+
+ if (pnp_dev->active &&
+ (!drv || !(drv->flags & PNP_DRIVER_RES_DO_NOT_CHANGE)))
+ pnp_disable_dev(pnp_dev);
+
pnp_device_detach(pnp_dev);
return 0;
}
static const unsigned int mch_quirk_devices[] = {
0x0154, /* Ivy Bridge */
0x0c00, /* Haswell */
+ 0x1604, /* Broadwell */
};
static struct pci_dev *get_intel_host(void)
}
/* per RAPL domain ops, in the order of rapl_domain_type */
-static struct powercap_zone_ops zone_ops[] = {
+static const struct powercap_zone_ops zone_ops[] = {
/* RAPL_DOMAIN_PACKAGE */
{
.get_energy_uj = get_energy_counter,
return ret;
}
-static struct powercap_zone_constraint_ops constraint_ops = {
+static const struct powercap_zone_constraint_ops constraint_ops = {
.set_power_limit_uw = set_power_limit,
.get_power_limit_uw = get_current_power_limit,
.set_time_window_us = set_time_window,
}
if (!power_ctrl_orig_val)
- iosf_mbi_read(BT_MBI_UNIT_PMC, BT_MBI_PMC_READ,
- rapl_defaults->floor_freq_reg_addr,
- &power_ctrl_orig_val);
+ iosf_mbi_read(BT_MBI_UNIT_PMC, MBI_CR_READ,
+ rapl_defaults->floor_freq_reg_addr,
+ &power_ctrl_orig_val);
mdata = power_ctrl_orig_val;
if (enable) {
mdata &= ~(0x7f << 8);
mdata |= 1 << 8;
}
- iosf_mbi_write(BT_MBI_UNIT_PMC, BT_MBI_PMC_WRITE,
- rapl_defaults->floor_freq_reg_addr, mdata);
+ iosf_mbi_write(BT_MBI_UNIT_PMC, MBI_CR_WRITE,
+ rapl_defaults->floor_freq_reg_addr, mdata);
}
static u64 rapl_compute_time_window_core(struct rapl_package *rp, u64 value,
}
static int create_constraints(struct powercap_zone *power_zone,
- int nr_constraints,
- struct powercap_zone_constraint_ops *const_ops)
+ int nr_constraints,
+ const struct powercap_zone_constraint_ops *const_ops)
{
int i;
int ret = 0;
};
struct powercap_zone *powercap_register_zone(
- struct powercap_zone *power_zone,
- struct powercap_control_type *control_type,
- const char *name,
- struct powercap_zone *parent,
- const struct powercap_zone_ops *ops,
- int nr_constraints,
- struct powercap_zone_constraint_ops *const_ops)
+ struct powercap_zone *power_zone,
+ struct powercap_control_type *control_type,
+ const char *name,
+ struct powercap_zone *parent,
+ const struct powercap_zone_ops *ops,
+ int nr_constraints,
+ const struct powercap_zone_constraint_ops *const_ops)
{
int result;
int nr_attrs;
return AE_OK;
}
+ if (spi->irq < 0)
+ spi->irq = acpi_dev_gpio_irq_get(adev, 0);
+
adev->power.flags.ignore_parent = true;
strlcpy(spi->modalias, acpi_device_hid(adev), sizeof(spi->modalias));
if (spi_add_device(spi)) {
struct soc_sensor_entry *aux_entry = tzd->devdata;
int ret;
- ret = iosf_mbi_read(QRK_MBI_UNIT_RMU, QRK_MBI_RMU_READ,
- QRK_DTS_REG_OFFSET_ENABLE, &out);
+ ret = iosf_mbi_read(QRK_MBI_UNIT_RMU, MBI_REG_READ,
+ QRK_DTS_REG_OFFSET_ENABLE, &out);
if (ret)
return ret;
if (!aux_entry->locked) {
out |= QRK_DTS_ENABLE_BIT;
- ret = iosf_mbi_write(QRK_MBI_UNIT_RMU, QRK_MBI_RMU_WRITE,
- QRK_DTS_REG_OFFSET_ENABLE, out);
+ ret = iosf_mbi_write(QRK_MBI_UNIT_RMU, MBI_REG_WRITE,
+ QRK_DTS_REG_OFFSET_ENABLE, out);
if (ret)
return ret;
struct soc_sensor_entry *aux_entry = tzd->devdata;
int ret;
- ret = iosf_mbi_read(QRK_MBI_UNIT_RMU, QRK_MBI_RMU_READ,
- QRK_DTS_REG_OFFSET_ENABLE, &out);
+ ret = iosf_mbi_read(QRK_MBI_UNIT_RMU, MBI_REG_READ,
+ QRK_DTS_REG_OFFSET_ENABLE, &out);
if (ret)
return ret;
if (!aux_entry->locked) {
out &= ~QRK_DTS_ENABLE_BIT;
- ret = iosf_mbi_write(QRK_MBI_UNIT_RMU, QRK_MBI_RMU_WRITE,
- QRK_DTS_REG_OFFSET_ENABLE, out);
+ ret = iosf_mbi_write(QRK_MBI_UNIT_RMU, MBI_REG_WRITE,
+ QRK_DTS_REG_OFFSET_ENABLE, out);
if (ret)
return ret;
u32 out;
mutex_lock(&dts_update_mutex);
- status = iosf_mbi_read(QRK_MBI_UNIT_RMU, QRK_MBI_RMU_READ,
- QRK_DTS_REG_OFFSET_PTPS, &out);
+ status = iosf_mbi_read(QRK_MBI_UNIT_RMU, MBI_REG_READ,
+ QRK_DTS_REG_OFFSET_PTPS, &out);
mutex_unlock(&dts_update_mutex);
if (status)
goto failed;
}
- ret = iosf_mbi_read(QRK_MBI_UNIT_RMU, QRK_MBI_RMU_READ,
- QRK_DTS_REG_OFFSET_PTPS, &store_ptps);
+ ret = iosf_mbi_read(QRK_MBI_UNIT_RMU, MBI_REG_READ,
+ QRK_DTS_REG_OFFSET_PTPS, &store_ptps);
if (ret)
goto failed;
out |= (temp_out & QRK_DTS_MASK_TP_THRES) <<
(trip * QRK_DTS_SHIFT_TP);
- ret = iosf_mbi_write(QRK_MBI_UNIT_RMU, QRK_MBI_RMU_WRITE,
- QRK_DTS_REG_OFFSET_PTPS, out);
+ ret = iosf_mbi_write(QRK_MBI_UNIT_RMU, MBI_REG_WRITE,
+ QRK_DTS_REG_OFFSET_PTPS, out);
failed:
mutex_unlock(&dts_update_mutex);
int ret;
mutex_lock(&dts_update_mutex);
- ret = iosf_mbi_read(QRK_MBI_UNIT_RMU, QRK_MBI_RMU_READ,
- QRK_DTS_REG_OFFSET_TEMP, &out);
+ ret = iosf_mbi_read(QRK_MBI_UNIT_RMU, MBI_REG_READ,
+ QRK_DTS_REG_OFFSET_TEMP, &out);
mutex_unlock(&dts_update_mutex);
if (ret)
if (aux_entry) {
if (!aux_entry->locked) {
mutex_lock(&dts_update_mutex);
- iosf_mbi_write(QRK_MBI_UNIT_RMU, QRK_MBI_RMU_WRITE,
- QRK_DTS_REG_OFFSET_ENABLE,
- aux_entry->store_dts_enable);
+ iosf_mbi_write(QRK_MBI_UNIT_RMU, MBI_REG_WRITE,
+ QRK_DTS_REG_OFFSET_ENABLE,
+ aux_entry->store_dts_enable);
- iosf_mbi_write(QRK_MBI_UNIT_RMU, QRK_MBI_RMU_WRITE,
- QRK_DTS_REG_OFFSET_PTPS,
- aux_entry->store_ptps);
+ iosf_mbi_write(QRK_MBI_UNIT_RMU, MBI_REG_WRITE,
+ QRK_DTS_REG_OFFSET_PTPS,
+ aux_entry->store_ptps);
mutex_unlock(&dts_update_mutex);
}
thermal_zone_device_unregister(aux_entry->tzone);
}
/* Check if DTS register is locked */
- err = iosf_mbi_read(QRK_MBI_UNIT_RMU, QRK_MBI_RMU_READ,
- QRK_DTS_REG_OFFSET_LOCK,
- &out);
+ err = iosf_mbi_read(QRK_MBI_UNIT_RMU, MBI_REG_READ,
+ QRK_DTS_REG_OFFSET_LOCK, &out);
if (err)
goto err_ret;
/* Store DTS default state if DTS registers are not locked */
if (!aux_entry->locked) {
/* Store DTS default enable for restore on exit */
- err = iosf_mbi_read(QRK_MBI_UNIT_RMU, QRK_MBI_RMU_READ,
- QRK_DTS_REG_OFFSET_ENABLE,
- &aux_entry->store_dts_enable);
+ err = iosf_mbi_read(QRK_MBI_UNIT_RMU, MBI_REG_READ,
+ QRK_DTS_REG_OFFSET_ENABLE,
+ &aux_entry->store_dts_enable);
if (err)
goto err_ret;
/* Store DTS default PTPS register for restore on exit */
- err = iosf_mbi_read(QRK_MBI_UNIT_RMU, QRK_MBI_RMU_READ,
- QRK_DTS_REG_OFFSET_PTPS,
- &aux_entry->store_ptps);
+ err = iosf_mbi_read(QRK_MBI_UNIT_RMU, MBI_REG_READ,
+ QRK_DTS_REG_OFFSET_PTPS,
+ &aux_entry->store_ptps);
if (err)
goto err_ret;
}
dts = tzd->devdata;
sensors = dts->sensors;
mutex_lock(&sensors->dts_update_lock);
- status = iosf_mbi_read(BT_MBI_UNIT_PMC, BT_MBI_BUNIT_READ,
+ status = iosf_mbi_read(BT_MBI_UNIT_PMC, MBI_REG_READ,
SOC_DTS_OFFSET_PTPS, &out);
mutex_unlock(&sensors->dts_update_lock);
if (status)
temp_out = (sensors->tj_max - temp) / 1000;
- status = iosf_mbi_read(BT_MBI_UNIT_PMC, BT_MBI_BUNIT_READ,
+ status = iosf_mbi_read(BT_MBI_UNIT_PMC, MBI_REG_READ,
SOC_DTS_OFFSET_PTPS, &store_ptps);
if (status)
return status;
out = (store_ptps & ~(0xFF << (thres_index * 8)));
out |= (temp_out & 0xFF) << (thres_index * 8);
- status = iosf_mbi_write(BT_MBI_UNIT_PMC, BT_MBI_BUNIT_WRITE,
+ status = iosf_mbi_write(BT_MBI_UNIT_PMC, MBI_REG_WRITE,
SOC_DTS_OFFSET_PTPS, out);
if (status)
return status;
pr_debug("update_trip_temp PTPS = %x\n", out);
- status = iosf_mbi_read(BT_MBI_UNIT_PMC, BT_MBI_BUNIT_READ,
+ status = iosf_mbi_read(BT_MBI_UNIT_PMC, MBI_REG_READ,
SOC_DTS_OFFSET_PTMC, &out);
if (status)
goto err_restore_ptps;
store_ptmc = out;
- status = iosf_mbi_read(BT_MBI_UNIT_PMC, BT_MBI_BUNIT_READ,
+ status = iosf_mbi_read(BT_MBI_UNIT_PMC, MBI_REG_READ,
SOC_DTS_TE_AUX0 + thres_index,
&te_out);
if (status)
out &= ~SOC_DTS_AUX0_ENABLE_BIT;
te_out &= ~int_enable_bit;
}
- status = iosf_mbi_write(BT_MBI_UNIT_PMC, BT_MBI_BUNIT_WRITE,
+ status = iosf_mbi_write(BT_MBI_UNIT_PMC, MBI_REG_WRITE,
SOC_DTS_OFFSET_PTMC, out);
if (status)
goto err_restore_te_out;
- status = iosf_mbi_write(BT_MBI_UNIT_PMC, BT_MBI_BUNIT_WRITE,
+ status = iosf_mbi_write(BT_MBI_UNIT_PMC, MBI_REG_WRITE,
SOC_DTS_TE_AUX0 + thres_index,
te_out);
if (status)
return 0;
err_restore_te_out:
- iosf_mbi_write(BT_MBI_UNIT_PMC, BT_MBI_BUNIT_WRITE,
+ iosf_mbi_write(BT_MBI_UNIT_PMC, MBI_REG_WRITE,
SOC_DTS_OFFSET_PTMC, store_te_out);
err_restore_ptmc:
- iosf_mbi_write(BT_MBI_UNIT_PMC, BT_MBI_BUNIT_WRITE,
+ iosf_mbi_write(BT_MBI_UNIT_PMC, MBI_REG_WRITE,
SOC_DTS_OFFSET_PTMC, store_ptmc);
err_restore_ptps:
- iosf_mbi_write(BT_MBI_UNIT_PMC, BT_MBI_BUNIT_WRITE,
+ iosf_mbi_write(BT_MBI_UNIT_PMC, MBI_REG_WRITE,
SOC_DTS_OFFSET_PTPS, store_ptps);
/* Nothing we can do if restore fails */
dts = tzd->devdata;
sensors = dts->sensors;
- status = iosf_mbi_read(BT_MBI_UNIT_PMC, BT_MBI_BUNIT_READ,
+ status = iosf_mbi_read(BT_MBI_UNIT_PMC, MBI_REG_READ,
SOC_DTS_OFFSET_TEMP, &out);
if (status)
return status;
u32 out;
int ret;
- ret = iosf_mbi_read(BT_MBI_UNIT_PMC, BT_MBI_BUNIT_READ,
+ ret = iosf_mbi_read(BT_MBI_UNIT_PMC, MBI_REG_READ,
SOC_DTS_OFFSET_ENABLE, &out);
if (ret)
return ret;
if (!(out & BIT(id))) {
out |= BIT(id);
- ret = iosf_mbi_write(BT_MBI_UNIT_PMC, BT_MBI_BUNIT_WRITE,
+ ret = iosf_mbi_write(BT_MBI_UNIT_PMC, MBI_REG_WRITE,
SOC_DTS_OFFSET_ENABLE, out);
if (ret)
return ret;
static void remove_dts_thermal_zone(struct intel_soc_dts_sensor_entry *dts)
{
if (dts) {
- iosf_mbi_write(BT_MBI_UNIT_PMC, BT_MBI_BUNIT_WRITE,
+ iosf_mbi_write(BT_MBI_UNIT_PMC, MBI_REG_WRITE,
SOC_DTS_OFFSET_ENABLE, dts->store_status);
thermal_zone_device_unregister(dts->tzone);
}
int i;
/* Store status to restor on exit */
- ret = iosf_mbi_read(BT_MBI_UNIT_PMC, BT_MBI_BUNIT_READ,
- SOC_DTS_OFFSET_ENABLE,
- &dts->store_status);
+ ret = iosf_mbi_read(BT_MBI_UNIT_PMC, MBI_REG_READ,
+ SOC_DTS_OFFSET_ENABLE, &dts->store_status);
if (ret)
goto err_ret;
}
/* Check if the writable trip we provide is not used by BIOS */
- ret = iosf_mbi_read(BT_MBI_UNIT_PMC, BT_MBI_BUNIT_READ,
+ ret = iosf_mbi_read(BT_MBI_UNIT_PMC, MBI_REG_READ,
SOC_DTS_OFFSET_PTPS, &store_ptps);
if (ret)
trip_mask = 0;
spin_lock_irqsave(&sensors->intr_notify_lock, flags);
- status = iosf_mbi_read(BT_MBI_UNIT_PMC, BT_MBI_BUNIT_READ,
+ status = iosf_mbi_read(BT_MBI_UNIT_PMC, MBI_REG_READ,
SOC_DTS_OFFSET_PTMC, &ptmc_out);
ptmc_out |= SOC_DTS_PTMC_APIC_DEASSERT_BIT;
- status = iosf_mbi_write(BT_MBI_UNIT_PMC, BT_MBI_BUNIT_WRITE,
+ status = iosf_mbi_write(BT_MBI_UNIT_PMC, MBI_REG_WRITE,
SOC_DTS_OFFSET_PTMC, ptmc_out);
- status = iosf_mbi_read(BT_MBI_UNIT_PMC, BT_MBI_BUNIT_READ,
+ status = iosf_mbi_read(BT_MBI_UNIT_PMC, MBI_REG_READ,
SOC_DTS_OFFSET_PTTSS, &sticky_out);
pr_debug("status %d PTTSS %x\n", status, sticky_out);
if (sticky_out & SOC_DTS_TRIP_MASK) {
int i;
/* reset sticky bit */
- status = iosf_mbi_write(BT_MBI_UNIT_PMC, BT_MBI_BUNIT_WRITE,
+ status = iosf_mbi_write(BT_MBI_UNIT_PMC, MBI_REG_WRITE,
SOC_DTS_OFFSET_PTTSS, sticky_out);
spin_unlock_irqrestore(&sensors->intr_notify_lock, flags);
#define AE_OWNER_ID_LIMIT EXCEP_ENV (0x001B)
#define AE_NOT_CONFIGURED EXCEP_ENV (0x001C)
#define AE_ACCESS EXCEP_ENV (0x001D)
+#define AE_IO_ERROR EXCEP_ENV (0x001E)
-#define AE_CODE_ENV_MAX 0x001D
+#define AE_CODE_ENV_MAX 0x001E
/*
* Programmer exceptions
"There are no more Owner IDs available for ACPI tables or control methods"),
EXCEP_TXT("AE_NOT_CONFIGURED",
"The interface is not part of the current subsystem configuration"),
- EXCEP_TXT("AE_ACCESS", "Permission denied for the requested operation")
+ EXCEP_TXT("AE_ACCESS", "Permission denied for the requested operation"),
+ EXCEP_TXT("AE_IO_ERROR", "An I/O error occurred")
};
static const struct acpi_exception_info acpi_gbl_exception_names_pgm[] = {
.package.elements = (eles) \
}
+bool acpi_dev_present(const char *hid);
+
#ifdef CONFIG_ACPI
#include <linux/proc_fs.h>
static inline bool acpi_device_can_poweroff(struct acpi_device *adev)
{
- return adev->power.states[ACPI_STATE_D3_COLD].flags.valid;
+ return adev->power.states[ACPI_STATE_D3_COLD].flags.valid ||
+ ((acpi_gbl_FADT.header.revision < 6) &&
+ adev->power.states[ACPI_STATE_D3_HOT].flags.explicit_set);
}
#else /* CONFIG_ACPI */
#endif
/*
- * Debug input
+ * Debug IO
*/
#ifndef ACPI_USE_ALTERNATE_PROTOTYPE_acpi_os_get_line
acpi_status acpi_os_get_line(char *buffer, u32 buffer_length, u32 *bytes_read);
#endif
+#ifndef ACPI_USE_ALTERNATE_PROTOTYPE_acpi_os_initialize_command_signals
+acpi_status acpi_os_initialize_command_signals(void);
+#endif
+
+#ifndef ACPI_USE_ALTERNATE_PROTOTYPE_acpi_os_terminate_command_signals
+void acpi_os_terminate_command_signals(void);
+#endif
+
+#ifndef ACPI_USE_ALTERNATE_PROTOTYPE_acpi_os_wait_command_ready
+acpi_status acpi_os_wait_command_ready(void);
+#endif
+
+#ifndef ACPI_USE_ALTERNATE_PROTOTYPE_acpi_os_notify_command_complete
+acpi_status acpi_os_notify_command_complete(void);
+#endif
+
/*
* Obtain ACPI table(s)
*/
/* Current ACPICA subsystem version in YYYYMMDD format */
-#define ACPI_CA_VERSION 0x20150930
+#define ACPI_CA_VERSION 0x20151218
#include <acpi/acconfig.h>
#include <acpi/actypes.h>
*/
ACPI_INIT_GLOBAL(u8, acpi_gbl_do_not_use_xsdt, FALSE);
+/*
+ * Optionally support group module level code.
+ */
+ACPI_INIT_GLOBAL(u8, acpi_gbl_group_module_level_code, TRUE);
+
/*
* Optionally use 32-bit FADT addresses if and when there is a conflict
* (address mismatch) between the 32-bit and 64-bit versions of the
ACPI_INIT_GLOBAL(u32, acpi_dbg_level, ACPI_DEBUG_DEFAULT);
ACPI_INIT_GLOBAL(u32, acpi_dbg_layer, 0);
+/* Optionally enable timer output with Debug Object output */
+
+ACPI_INIT_GLOBAL(u8, acpi_gbl_display_debug_timer, FALSE);
+
+/*
+ * Debugger command handshake globals. Host OSes need to access these
+ * variables to implement their own command handshake mechanism.
+ */
+#ifdef ACPI_DEBUGGER
+ACPI_INIT_GLOBAL(u8, acpi_gbl_method_executing, FALSE);
+ACPI_GLOBAL(char, acpi_gbl_db_line_buf[ACPI_DB_LINE_BUFFER_SIZE]);
+#endif
+
/*
* Other miscellaneous globals
*/
#endif /* ACPI_APPLICATION */
+/*
+ * Debugger prototypes
+ *
+ * All interfaces used by debugger will be configured
+ * out of the ACPICA build unless the ACPI_DEBUGGER
+ * flag is defined.
+ */
+#ifdef ACPI_DEBUGGER
+#define ACPI_DBR_DEPENDENT_RETURN_OK(prototype) \
+ ACPI_EXTERNAL_RETURN_OK(prototype)
+
+#define ACPI_DBR_DEPENDENT_RETURN_VOID(prototype) \
+ ACPI_EXTERNAL_RETURN_VOID(prototype)
+
+#else
+#define ACPI_DBR_DEPENDENT_RETURN_OK(prototype) \
+ static ACPI_INLINE prototype {return(AE_OK);}
+
+#define ACPI_DBR_DEPENDENT_RETURN_VOID(prototype) \
+ static ACPI_INLINE prototype {return;}
+
+#endif /* ACPI_DEBUGGER */
+
/*****************************************************************************
*
* ACPICA public interface prototypes
ACPI_EXTERNAL_RETURN_STATUS(acpi_status acpi_leave_sleep_state(u8 sleep_state))
ACPI_HW_DEPENDENT_RETURN_STATUS(acpi_status
- acpi_set_firmware_waking_vectors
+ acpi_set_firmware_waking_vector
(acpi_physical_address physical_address,
acpi_physical_address physical_address64))
-ACPI_HW_DEPENDENT_RETURN_STATUS(acpi_status
- acpi_set_firmware_waking_vector(u32
- physical_address))
-#if ACPI_MACHINE_WIDTH == 64
-ACPI_HW_DEPENDENT_RETURN_STATUS(acpi_status
- acpi_set_firmware_waking_vector64(u64
- physical_address))
-#endif
/*
* ACPI Timer interfaces
*/
void **data,
void (*callback)(void *)))
+void acpi_run_debugger(char *batch_buffer);
+
void acpi_set_debugger_thread_id(acpi_thread_id thread_id);
#endif /* __ACXFACE_H__ */
#define ACPI_PCICLS_STRING_SIZE 7 /* Includes null terminator */
-/* Structures used for device/processor HID, UID, CID, and SUB */
+/* Structures used for device/processor HID, UID, CID */
struct acpi_pnp_device_id {
u32 length; /* Length of string + null */
u64 address; /* _ADR value */
struct acpi_pnp_device_id hardware_id; /* _HID value */
struct acpi_pnp_device_id unique_id; /* _UID value */
- struct acpi_pnp_device_id subsystem_id; /* _SUB value */
struct acpi_pnp_device_id class_code; /* _CLS value */
struct acpi_pnp_device_id_list compatible_id_list; /* _CID list <must be last> */
};
#define ACPI_VALID_ADR 0x0002
#define ACPI_VALID_HID 0x0004
#define ACPI_VALID_UID 0x0008
-#define ACPI_VALID_SUB 0x0010
#define ACPI_VALID_CID 0x0020
#define ACPI_VALID_CLS 0x0040
#define ACPI_VALID_SXDS 0x0100
#define ACPI_VALID_SXWS 0x0200
-/* Flags for _STA return value (current_status above) */
+/* Flags for _STA method */
#define ACPI_STA_DEVICE_PRESENT 0x01
#define ACPI_STA_DEVICE_ENABLED 0x02
*/
#define ACPI_USE_ALTERNATE_PROTOTYPE_acpi_os_readable
#define ACPI_USE_ALTERNATE_PROTOTYPE_acpi_os_writable
+#define ACPI_USE_ALTERNATE_PROTOTYPE_acpi_os_initialize_command_signals
+#define ACPI_USE_ALTERNATE_PROTOTYPE_acpi_os_terminate_command_signals
/*
* OSL interfaces used by utilities
return TRUE;
}
+static inline acpi_status acpi_os_initialize_command_signals(void)
+{
+ return AE_OK;
+}
+
+static inline void acpi_os_terminate_command_signals(void)
+{
+ return;
+}
+
/*
* OSL interfaces added by Linux
*/
#define __ACPI_VIDEO_H
#include <linux/errno.h> /* for ENODEV */
+#include <linux/types.h> /* for bool */
struct acpi_device;
int device_id, void **edid);
extern enum acpi_backlight_type acpi_video_get_backlight_type(void);
extern void acpi_video_set_dmi_backlight_type(enum acpi_backlight_type type);
+extern bool acpi_video_handles_brightness_key_presses(void);
#else
static inline int acpi_video_register(void) { return 0; }
static inline void acpi_video_unregister(void) { return; }
static inline void acpi_video_set_dmi_backlight_type(enum acpi_backlight_type type)
{
}
+static inline bool acpi_video_handles_brightness_key_presses(void)
+{
+ return false;
+}
#endif
#endif
#include <linux/list.h>
#include <linux/mod_devicetable.h>
#include <linux/dynamic_debug.h>
+#include <linux/module.h>
+#include <linux/mutex.h>
#include <acpi/acpi_bus.h>
#include <acpi/acpi_drivers.h>
typedef int (*acpi_tbl_entry_handler)(struct acpi_subtable_header *header,
const unsigned long end);
+/* Debugger support */
+
+struct acpi_debugger_ops {
+ int (*create_thread)(acpi_osd_exec_callback function, void *context);
+ ssize_t (*write_log)(const char *msg);
+ ssize_t (*read_cmd)(char *buffer, size_t length);
+ int (*wait_command_ready)(bool single_step, char *buffer, size_t length);
+ int (*notify_command_complete)(void);
+};
+
+struct acpi_debugger {
+ const struct acpi_debugger_ops *ops;
+ struct module *owner;
+ struct mutex lock;
+};
+
+#ifdef CONFIG_ACPI_DEBUGGER
+int __init acpi_debugger_init(void);
+int acpi_register_debugger(struct module *owner,
+ const struct acpi_debugger_ops *ops);
+void acpi_unregister_debugger(const struct acpi_debugger_ops *ops);
+int acpi_debugger_create_thread(acpi_osd_exec_callback function, void *context);
+ssize_t acpi_debugger_write_log(const char *msg);
+ssize_t acpi_debugger_read_cmd(char *buffer, size_t buffer_length);
+int acpi_debugger_wait_command_ready(void);
+int acpi_debugger_notify_command_complete(void);
+#else
+static inline int acpi_debugger_init(void)
+{
+ return -ENODEV;
+}
+
+static inline int acpi_register_debugger(struct module *owner,
+ const struct acpi_debugger_ops *ops)
+{
+ return -ENODEV;
+}
+
+static inline void acpi_unregister_debugger(const struct acpi_debugger_ops *ops)
+{
+}
+
+static inline int acpi_debugger_create_thread(acpi_osd_exec_callback function,
+ void *context)
+{
+ return -ENODEV;
+}
+
+static inline int acpi_debugger_write_log(const char *msg)
+{
+ return -ENODEV;
+}
+
+static inline int acpi_debugger_read_cmd(char *buffer, u32 buffer_length)
+{
+ return -ENODEV;
+}
+
+static inline int acpi_debugger_wait_command_ready(void)
+{
+ return -ENODEV;
+}
+
+static inline int acpi_debugger_notify_command_complete(void)
+{
+ return -ENODEV;
+}
+#endif
+
#ifdef CONFIG_ACPI_INITRD_TABLE_OVERRIDE
void acpi_initrd_override(void *data, size_t size);
#else
bool acpi_dev_resource_ext_address_space(struct acpi_resource *ares,
struct resource_win *win);
unsigned long acpi_dev_irq_flags(u8 triggering, u8 polarity, u8 shareable);
+unsigned int acpi_dev_get_irq_type(int triggering, int polarity);
bool acpi_dev_resource_interrupt(struct acpi_resource *ares, int index,
struct resource *res);
struct freq_attr **attr;
/* platform specific boost support code */
- bool boost_supported;
bool boost_enabled;
int (*set_boost)(int state);
};
#ifdef CONFIG_CPU_FREQ
int cpufreq_boost_trigger_state(int state);
-int cpufreq_boost_supported(void);
int cpufreq_boost_enabled(void);
int cpufreq_enable_boost_support(void);
bool policy_has_boost_freq(struct cpufreq_policy *policy);
{
return 0;
}
-static inline int cpufreq_boost_supported(void)
-{
- return 0;
-}
static inline int cpufreq_boost_enabled(void)
{
return 0;
unbound */
#define BUS_NOTIFY_UNBOUND_DRIVER 0x00000007 /* driver is unbound
from the device */
+#define BUS_NOTIFY_DRIVER_NOT_BOUND 0x00000008 /* driver fails to be bound */
extern struct kset *bus_get_kset(struct bus_type *bus);
extern struct klist *bus_get_device_klist(struct bus_type *bus);
#include <linux/platform_device.h>
struct irq_domain;
+struct property_set;
/* Matches ACPI PNP id, either _HID or _CID, or ACPI _ADR */
struct mfd_cell_acpi_match {
/* platform data passed to the sub devices drivers */
void *platform_data;
size_t pdata_size;
+
+ /* device properties passed to the sub devices drivers */
+ const struct property_set *pset;
+
/*
* Device Tree compatible string
* See: Documentation/devicetree/usage-model.txt Chapter 2.2 for details
#define PLATFORM_DEVID_AUTO (-2)
struct mfd_cell;
+struct property_set;
struct platform_device {
const char *name;
const void *data;
size_t size_data;
u64 dma_mask;
+
+ const struct property_set *pset;
};
extern struct platform_device *platform_device_register_full(
const struct platform_device_info *pdevinfo);
unsigned int num);
extern int platform_device_add_data(struct platform_device *pdev,
const void *data, size_t size);
+extern int platform_device_add_properties(struct platform_device *pdev,
+ const struct property_set *pset);
extern int platform_device_add(struct platform_device *pdev);
extern void platform_device_del(struct platform_device *pdev);
extern void platform_device_put(struct platform_device *pdev);
int dev_pm_opp_disable(struct device *dev, unsigned long freq);
struct srcu_notifier_head *dev_pm_opp_get_notifier(struct device *dev);
+int dev_pm_opp_set_supported_hw(struct device *dev, const u32 *versions,
+ unsigned int count);
+void dev_pm_opp_put_supported_hw(struct device *dev);
+int dev_pm_opp_set_prop_name(struct device *dev, const char *name);
+void dev_pm_opp_put_prop_name(struct device *dev);
#else
static inline unsigned long dev_pm_opp_get_voltage(struct dev_pm_opp *opp)
{
{
return ERR_PTR(-EINVAL);
}
+
+static inline int dev_pm_opp_set_supported_hw(struct device *dev,
+ const u32 *versions,
+ unsigned int count)
+{
+ return -EINVAL;
+}
+
+static inline void dev_pm_opp_put_supported_hw(struct device *dev) {}
+
+static inline int dev_pm_opp_set_prop_name(struct device *dev, const char *name)
+{
+ return -EINVAL;
+}
+
+static inline void dev_pm_opp_put_prop_name(struct device *dev) {}
+
#endif /* CONFIG_PM_OPP */
#if defined(CONFIG_PM_OPP) && defined(CONFIG_OF)
extern int __pm_runtime_idle(struct device *dev, int rpmflags);
extern int __pm_runtime_suspend(struct device *dev, int rpmflags);
extern int __pm_runtime_resume(struct device *dev, int rpmflags);
+extern int pm_runtime_get_if_in_use(struct device *dev);
extern int pm_schedule_suspend(struct device *dev, unsigned int delay);
extern int __pm_runtime_set_status(struct device *dev, unsigned int status);
extern int pm_runtime_barrier(struct device *dev);
{
return -ENOSYS;
}
+static inline int pm_runtime_get_if_in_use(struct device *dev)
+{
+ return -EINVAL;
+}
static inline int __pm_runtime_set_status(struct device *dev,
unsigned int status) { return 0; }
static inline int pm_runtime_barrier(struct device *dev) { return 0; }
struct powercap_zone_constraint {
int id;
struct powercap_zone *power_zone;
- struct powercap_zone_constraint_ops *ops;
+ const struct powercap_zone_constraint_ops *ops;
};
struct powercap_zone *parent,
const struct powercap_zone_ops *ops,
int nr_constraints,
- struct powercap_zone_constraint_ops *const_ops);
+ const struct powercap_zone_constraint_ops *const_ops);
/**
* powercap_unregister_zone() - Unregister a zone device
struct fwnode_handle *device_get_next_child_node(struct device *dev,
struct fwnode_handle *child);
-#define device_for_each_child_node(dev, child) \
- for (child = device_get_next_child_node(dev, NULL); child; \
+#define device_for_each_child_node(dev, child) \
+ for (child = device_get_next_child_node(dev, NULL); child; \
child = device_get_next_child_node(dev, child))
void fwnode_handle_put(struct fwnode_handle *fwnode);
/**
* struct property_entry - "Built-in" device property representation.
* @name: Name of the property.
- * @type: Type of the property.
- * @nval: Number of items of type @type making up the value.
- * @value: Value of the property (an array of @nval items of type @type).
+ * @length: Length of data making up the value.
+ * @is_array: True when the property is an array.
+ * @is_string: True when property is a string.
+ * @pointer: Pointer to the property (an array of items of the given type).
+ * @value: Value of the property (when it is a single item of the given type).
*/
struct property_entry {
const char *name;
- enum dev_prop_type type;
- size_t nval;
+ size_t length;
+ bool is_array;
+ bool is_string;
union {
- void *raw_data;
- u8 *u8_data;
- u16 *u16_data;
- u32 *u32_data;
- u64 *u64_data;
- const char **str;
- } value;
+ union {
+ void *raw_data;
+ u8 *u8_data;
+ u16 *u16_data;
+ u32 *u32_data;
+ u64 *u64_data;
+ const char **str;
+ } pointer;
+ union {
+ unsigned long long raw_data;
+ u8 u8_data;
+ u16 u16_data;
+ u32 u32_data;
+ u64 u64_data;
+ const char *str;
+ } value;
+ };
};
+/*
+ * Note: the below four initializers for the anonymous union are carefully
+ * crafted to avoid gcc-4.4.4's problems with initialization of anon unions
+ * and structs.
+ */
+
+#define PROPERTY_ENTRY_INTEGER_ARRAY(_name_, _type_, _val_) \
+{ \
+ .name = _name_, \
+ .length = ARRAY_SIZE(_val_) * sizeof(_type_), \
+ .is_array = true, \
+ .is_string = false, \
+ { .pointer = { _type_##_data = _val_ } }, \
+}
+
+#define PROPERTY_ENTRY_U8_ARRAY(_name_, _val_) \
+ PROPERTY_ENTRY_INTEGER_ARRAY(_name_, u8, _val_)
+#define PROPERTY_ENTRY_U16_ARRAY(_name_, _val_) \
+ PROPERTY_ENTRY_INTEGER_ARRAY(_name_, u16, _val_)
+#define PROPERTY_ENTRY_U32_ARRAY(_name_, _val_) \
+ PROPERTY_ENTRY_INTEGER_ARRAY(_name_, u32, _val_)
+#define PROPERTY_ENTRY_U64_ARRAY(_name_, _val_) \
+ PROPERTY_ENTRY_INTEGER_ARRAY(_name_, u64, _val_)
+
+#define PROPERTY_ENTRY_STRING_ARRAY(_name_, _val_) \
+{ \
+ .name = _name_, \
+ .length = ARRAY_SIZE(_val_) * sizeof(const char *), \
+ .is_array = true, \
+ .is_string = true, \
+ { .pointer = { .str = _val_ } }, \
+}
+
+#define PROPERTY_ENTRY_INTEGER(_name_, _type_, _val_) \
+{ \
+ .name = _name_, \
+ .length = sizeof(_type_), \
+ .is_string = false, \
+ { .value = { ._type_##_data = _val_ } }, \
+}
+
+#define PROPERTY_ENTRY_U8(_name_, _val_) \
+ PROPERTY_ENTRY_INTEGER(_name_, u8, _val_)
+#define PROPERTY_ENTRY_U16(_name_, _val_) \
+ PROPERTY_ENTRY_INTEGER(_name_, u16, _val_)
+#define PROPERTY_ENTRY_U32(_name_, _val_) \
+ PROPERTY_ENTRY_INTEGER(_name_, u32, _val_)
+#define PROPERTY_ENTRY_U64(_name_, _val_) \
+ PROPERTY_ENTRY_INTEGER(_name_, u64, _val_)
+
+#define PROPERTY_ENTRY_STRING(_name_, _val_) \
+{ \
+ .name = _name_, \
+ .length = sizeof(_val_), \
+ .is_string = true, \
+ { .value = { .str = _val_ } }, \
+}
+
+#define PROPERTY_ENTRY_BOOL(_name_) \
+{ \
+ .name = _name_, \
+}
+
/**
* struct property_set - Collection of "built-in" device properties.
* @fwnode: Handle to be pointed to by the fwnode field of struct device.
struct property_entry *properties;
};
-void device_add_property_set(struct device *dev, struct property_set *pset);
+int device_add_property_set(struct device *dev, const struct property_set *pset);
+void device_remove_property_set(struct device *dev);
bool device_dma_supported(struct device *dev);
return pm_wakeup_irq ? sprintf(buf, "%u\n", pm_wakeup_irq) : -ENODATA;
}
-static ssize_t pm_wakeup_irq_store(struct kobject *kobj,
- struct kobj_attribute *attr,
- const char *buf, size_t n)
-{
- return -EINVAL;
-}
-power_attr(pm_wakeup_irq);
+power_attr_ro(pm_wakeup_irq);
#else /* !CONFIG_PM_SLEEP_DEBUG */
static inline void pm_print_times_init(void) {}
return show_trace_dev_match(buf, PAGE_SIZE);
}
-static ssize_t
-pm_trace_dev_match_store(struct kobject *kobj, struct kobj_attribute *attr,
- const char *buf, size_t n)
-{
- return -EINVAL;
-}
-
-power_attr(pm_trace_dev_match);
+power_attr_ro(pm_trace_dev_match);
#endif /* CONFIG_PM_TRACE */
.store = _name##_store, \
}
+#define power_attr_ro(_name) \
+static struct kobj_attribute _name##_attr = { \
+ .attr = { \
+ .name = __stringify(_name), \
+ .mode = S_IRUGO, \
+ }, \
+ .show = _name##_show, \
+}
+
/* Preferred image size in bytes (default 500 MB) */
extern unsigned long image_size;
/* Size of memory reserved for drivers (default SPARE_PAGES x PAGE_SIZE) */
include ../../scripts/Makefile.include
-all: acpidump ec
-clean: acpidump_clean ec_clean
-install: acpidump_install ec_install
-uninstall: acpidump_uninstall ec_uninstall
+all: acpidbg acpidump ec
+clean: acpidbg_clean acpidump_clean ec_clean
+install: acpidbg_install acpidump_install ec_install
+uninstall: acpidbg_uninstall acpidump_uninstall ec_uninstall
-acpidump ec: FORCE
+acpidbg acpidump ec: FORCE
$(call descend,tools/$@,all)
-acpidump_clean ec_clean:
+acpidbg_clean acpidump_clean ec_clean:
$(call descend,tools/$(@:_clean=),clean)
-acpidump_install ec_install:
+acpidbg_install acpidump_install ec_install:
$(call descend,tools/$(@:_install=),install)
-acpidump_uninstall ec_uninstall:
+acpidbg_uninstall acpidump_uninstall ec_uninstall:
$(call descend,tools/$(@:_uninstall=),uninstall)
.PHONY: FORCE
* Option strings:
* "f" - Option has no arguments
* "f:" - Option requires an argument
+ * "f+" - Option has an optional argument
* "f^" - Option has optional single-char sub-options
* "f|" - Option has required single-char sub-options
*/
int acpi_getopt_argument(int argc, char **argv)
{
+
acpi_gbl_optind--;
current_char_ptr++;
if (modes & ACPI_FILE_WRITING) {
modes_str[i++] = 'w';
}
+
if (modes & ACPI_FILE_BINARY) {
modes_str[i++] = 'b';
}
void acpi_os_close_file(ACPI_FILE file)
{
+
fclose(file);
}
if (from == ACPI_FILE_BEGIN) {
ret = fseek(file, offset, SEEK_SET);
}
+
if (from == ACPI_FILE_END) {
ret = fseek(file, offset, SEEK_END);
}
--- /dev/null
+# tools/power/acpi/tools/acpidbg/Makefile - ACPI tool Makefile
+#
+# Copyright (c) 2015, Intel Corporation
+# Author: Lv Zheng <lv.zheng@intel.com>
+#
+# This program is free software; you can redistribute it and/or
+# modify it under the terms of the GNU General Public License
+# as published by the Free Software Foundation; version 2
+# of the License.
+
+include ../../Makefile.config
+
+TOOL = acpidbg
+vpath %.c \
+ ../../../../../drivers/acpi/acpica\
+ ../../common\
+ ../../os_specific/service_layers\
+ .
+CFLAGS += -DACPI_APPLICATION -DACPI_SINGLE_THREAD -DACPI_DEBUGGER\
+ -I.\
+ -I../../../../../drivers/acpi/acpica\
+ -I../../../../../include
+LDFLAGS += -lpthread
+TOOL_OBJS = \
+ acpidbg.o
+
+include ../../Makefile.rules
--- /dev/null
+/*
+ * ACPI AML interfacing userspace utility
+ *
+ * Copyright (C) 2015, Intel Corporation
+ * Authors: Lv Zheng <lv.zheng@intel.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#include <acpi/acpi.h>
+
+/* Headers not included by include/acpi/platform/aclinux.h */
+#include <stdbool.h>
+#include <fcntl.h>
+#include <assert.h>
+#include <linux/circ_buf.h>
+
+#define ACPI_AML_FILE "/sys/kernel/debug/acpi/acpidbg"
+#define ACPI_AML_SEC_TICK 1
+#define ACPI_AML_USEC_PEEK 200
+#define ACPI_AML_BUF_SIZE 4096
+
+#define ACPI_AML_BATCH_WRITE_CMD 0x00 /* Write command to kernel */
+#define ACPI_AML_BATCH_READ_LOG 0x01 /* Read log from kernel */
+#define ACPI_AML_BATCH_WRITE_LOG 0x02 /* Write log to console */
+
+#define ACPI_AML_LOG_START 0x00
+#define ACPI_AML_PROMPT_START 0x01
+#define ACPI_AML_PROMPT_STOP 0x02
+#define ACPI_AML_LOG_STOP 0x03
+#define ACPI_AML_PROMPT_ROLL 0x04
+
+#define ACPI_AML_INTERACTIVE 0x00
+#define ACPI_AML_BATCH 0x01
+
+#define circ_count(circ) \
+ (CIRC_CNT((circ)->head, (circ)->tail, ACPI_AML_BUF_SIZE))
+#define circ_count_to_end(circ) \
+ (CIRC_CNT_TO_END((circ)->head, (circ)->tail, ACPI_AML_BUF_SIZE))
+#define circ_space(circ) \
+ (CIRC_SPACE((circ)->head, (circ)->tail, ACPI_AML_BUF_SIZE))
+#define circ_space_to_end(circ) \
+ (CIRC_SPACE_TO_END((circ)->head, (circ)->tail, ACPI_AML_BUF_SIZE))
+
+#define acpi_aml_cmd_count() circ_count(&acpi_aml_cmd_crc)
+#define acpi_aml_log_count() circ_count(&acpi_aml_log_crc)
+#define acpi_aml_cmd_space() circ_space(&acpi_aml_cmd_crc)
+#define acpi_aml_log_space() circ_space(&acpi_aml_log_crc)
+
+#define ACPI_AML_DO(_fd, _op, _buf, _ret) \
+ do { \
+ _ret = acpi_aml_##_op(_fd, &acpi_aml_##_buf##_crc); \
+ if (_ret == 0) { \
+ fprintf(stderr, \
+ "%s %s pipe closed.\n", #_buf, #_op); \
+ return; \
+ } \
+ } while (0)
+#define ACPI_AML_BATCH_DO(_fd, _op, _buf, _ret) \
+ do { \
+ _ret = acpi_aml_##_op##_batch_##_buf(_fd, \
+ &acpi_aml_##_buf##_crc); \
+ if (_ret == 0) \
+ return; \
+ } while (0)
+
+
+static char acpi_aml_cmd_buf[ACPI_AML_BUF_SIZE];
+static char acpi_aml_log_buf[ACPI_AML_BUF_SIZE];
+static struct circ_buf acpi_aml_cmd_crc = {
+ .buf = acpi_aml_cmd_buf,
+ .head = 0,
+ .tail = 0,
+};
+static struct circ_buf acpi_aml_log_crc = {
+ .buf = acpi_aml_log_buf,
+ .head = 0,
+ .tail = 0,
+};
+static const char *acpi_aml_file_path = ACPI_AML_FILE;
+static unsigned long acpi_aml_mode = ACPI_AML_INTERACTIVE;
+static bool acpi_aml_exit;
+
+static bool acpi_aml_batch_drain;
+static unsigned long acpi_aml_batch_state;
+static char acpi_aml_batch_prompt;
+static char acpi_aml_batch_roll;
+static unsigned long acpi_aml_log_state;
+static char *acpi_aml_batch_cmd = NULL;
+static char *acpi_aml_batch_pos = NULL;
+
+static int acpi_aml_set_fl(int fd, int flags)
+{
+ int ret;
+
+ ret = fcntl(fd, F_GETFL, 0);
+ if (ret < 0) {
+ perror("fcntl(F_GETFL)");
+ return ret;
+ }
+ flags |= ret;
+ ret = fcntl(fd, F_SETFL, flags);
+ if (ret < 0) {
+ perror("fcntl(F_SETFL)");
+ return ret;
+ }
+ return ret;
+}
+
+static int acpi_aml_set_fd(int fd, int maxfd, fd_set *set)
+{
+ if (fd > maxfd)
+ maxfd = fd;
+ FD_SET(fd, set);
+ return maxfd;
+}
+
+static int acpi_aml_read(int fd, struct circ_buf *crc)
+{
+ char *p;
+ int len;
+
+ p = &crc->buf[crc->head];
+ len = circ_space_to_end(crc);
+ len = read(fd, p, len);
+ if (len < 0)
+ perror("read");
+ else if (len > 0)
+ crc->head = (crc->head + len) & (ACPI_AML_BUF_SIZE - 1);
+ return len;
+}
+
+static int acpi_aml_read_batch_cmd(int unused, struct circ_buf *crc)
+{
+ char *p;
+ int len;
+ int remained = strlen(acpi_aml_batch_pos);
+
+ p = &crc->buf[crc->head];
+ len = circ_space_to_end(crc);
+ if (len > remained) {
+ memcpy(p, acpi_aml_batch_pos, remained);
+ acpi_aml_batch_pos += remained;
+ len = remained;
+ } else {
+ memcpy(p, acpi_aml_batch_pos, len);
+ acpi_aml_batch_pos += len;
+ }
+ if (len > 0)
+ crc->head = (crc->head + len) & (ACPI_AML_BUF_SIZE - 1);
+ return len;
+}
+
+static int acpi_aml_read_batch_log(int fd, struct circ_buf *crc)
+{
+ char *p;
+ int len;
+ int ret = 0;
+
+ p = &crc->buf[crc->head];
+ len = circ_space_to_end(crc);
+ while (ret < len && acpi_aml_log_state != ACPI_AML_LOG_STOP) {
+ if (acpi_aml_log_state == ACPI_AML_PROMPT_ROLL) {
+ *p = acpi_aml_batch_roll;
+ len = 1;
+ crc->head = (crc->head + 1) & (ACPI_AML_BUF_SIZE - 1);
+ ret += 1;
+ acpi_aml_log_state = ACPI_AML_LOG_START;
+ } else {
+ len = read(fd, p, 1);
+ if (len <= 0) {
+ if (len < 0)
+ perror("read");
+ ret = len;
+ break;
+ }
+ }
+ switch (acpi_aml_log_state) {
+ case ACPI_AML_LOG_START:
+ if (*p == '\n')
+ acpi_aml_log_state = ACPI_AML_PROMPT_START;
+ crc->head = (crc->head + 1) & (ACPI_AML_BUF_SIZE - 1);
+ ret += 1;
+ break;
+ case ACPI_AML_PROMPT_START:
+ if (*p == ACPI_DEBUGGER_COMMAND_PROMPT ||
+ *p == ACPI_DEBUGGER_EXECUTE_PROMPT) {
+ acpi_aml_batch_prompt = *p;
+ acpi_aml_log_state = ACPI_AML_PROMPT_STOP;
+ } else {
+ if (*p != '\n')
+ acpi_aml_log_state = ACPI_AML_LOG_START;
+ crc->head = (crc->head + 1) & (ACPI_AML_BUF_SIZE - 1);
+ ret += 1;
+ }
+ break;
+ case ACPI_AML_PROMPT_STOP:
+ if (*p == ' ') {
+ acpi_aml_log_state = ACPI_AML_LOG_STOP;
+ acpi_aml_exit = true;
+ } else {
+ /* Roll back */
+ acpi_aml_log_state = ACPI_AML_PROMPT_ROLL;
+ acpi_aml_batch_roll = *p;
+ *p = acpi_aml_batch_prompt;
+ crc->head = (crc->head + 1) & (ACPI_AML_BUF_SIZE - 1);
+ ret += 1;
+ }
+ break;
+ default:
+ assert(0);
+ break;
+ }
+ }
+ return ret;
+}
+
+static int acpi_aml_write(int fd, struct circ_buf *crc)
+{
+ char *p;
+ int len;
+
+ p = &crc->buf[crc->tail];
+ len = circ_count_to_end(crc);
+ len = write(fd, p, len);
+ if (len < 0)
+ perror("write");
+ else if (len > 0)
+ crc->tail = (crc->tail + len) & (ACPI_AML_BUF_SIZE - 1);
+ return len;
+}
+
+static int acpi_aml_write_batch_log(int fd, struct circ_buf *crc)
+{
+ char *p;
+ int len;
+
+ p = &crc->buf[crc->tail];
+ len = circ_count_to_end(crc);
+ if (!acpi_aml_batch_drain) {
+ len = write(fd, p, len);
+ if (len < 0)
+ perror("write");
+ }
+ if (len > 0)
+ crc->tail = (crc->tail + len) & (ACPI_AML_BUF_SIZE - 1);
+ return len;
+}
+
+static int acpi_aml_write_batch_cmd(int fd, struct circ_buf *crc)
+{
+ int len;
+
+ len = acpi_aml_write(fd, crc);
+ if (circ_count_to_end(crc) == 0)
+ acpi_aml_batch_state = ACPI_AML_BATCH_READ_LOG;
+ return len;
+}
+
+static void acpi_aml_loop(int fd)
+{
+ fd_set rfds;
+ fd_set wfds;
+ struct timeval tv;
+ int ret;
+ int maxfd = 0;
+
+ if (acpi_aml_mode == ACPI_AML_BATCH) {
+ acpi_aml_log_state = ACPI_AML_LOG_START;
+ acpi_aml_batch_pos = acpi_aml_batch_cmd;
+ if (acpi_aml_batch_drain)
+ acpi_aml_batch_state = ACPI_AML_BATCH_READ_LOG;
+ else
+ acpi_aml_batch_state = ACPI_AML_BATCH_WRITE_CMD;
+ }
+ acpi_aml_exit = false;
+ while (!acpi_aml_exit) {
+ tv.tv_sec = ACPI_AML_SEC_TICK;
+ tv.tv_usec = 0;
+ FD_ZERO(&rfds);
+ FD_ZERO(&wfds);
+
+ if (acpi_aml_cmd_space()) {
+ if (acpi_aml_mode == ACPI_AML_INTERACTIVE)
+ maxfd = acpi_aml_set_fd(STDIN_FILENO, maxfd, &rfds);
+ else if (strlen(acpi_aml_batch_pos) &&
+ acpi_aml_batch_state == ACPI_AML_BATCH_WRITE_CMD)
+ ACPI_AML_BATCH_DO(STDIN_FILENO, read, cmd, ret);
+ }
+ if (acpi_aml_cmd_count() &&
+ (acpi_aml_mode == ACPI_AML_INTERACTIVE ||
+ acpi_aml_batch_state == ACPI_AML_BATCH_WRITE_CMD))
+ maxfd = acpi_aml_set_fd(fd, maxfd, &wfds);
+ if (acpi_aml_log_space() &&
+ (acpi_aml_mode == ACPI_AML_INTERACTIVE ||
+ acpi_aml_batch_state == ACPI_AML_BATCH_READ_LOG))
+ maxfd = acpi_aml_set_fd(fd, maxfd, &rfds);
+ if (acpi_aml_log_count())
+ maxfd = acpi_aml_set_fd(STDOUT_FILENO, maxfd, &wfds);
+
+ ret = select(maxfd+1, &rfds, &wfds, NULL, &tv);
+ if (ret < 0) {
+ perror("select");
+ break;
+ }
+ if (ret > 0) {
+ if (FD_ISSET(STDIN_FILENO, &rfds))
+ ACPI_AML_DO(STDIN_FILENO, read, cmd, ret);
+ if (FD_ISSET(fd, &wfds)) {
+ if (acpi_aml_mode == ACPI_AML_BATCH)
+ ACPI_AML_BATCH_DO(fd, write, cmd, ret);
+ else
+ ACPI_AML_DO(fd, write, cmd, ret);
+ }
+ if (FD_ISSET(fd, &rfds)) {
+ if (acpi_aml_mode == ACPI_AML_BATCH)
+ ACPI_AML_BATCH_DO(fd, read, log, ret);
+ else
+ ACPI_AML_DO(fd, read, log, ret);
+ }
+ if (FD_ISSET(STDOUT_FILENO, &wfds)) {
+ if (acpi_aml_mode == ACPI_AML_BATCH)
+ ACPI_AML_BATCH_DO(STDOUT_FILENO, write, log, ret);
+ else
+ ACPI_AML_DO(STDOUT_FILENO, write, log, ret);
+ }
+ }
+ }
+}
+
+static bool acpi_aml_readable(int fd)
+{
+ fd_set rfds;
+ struct timeval tv;
+ int ret;
+ int maxfd = 0;
+
+ tv.tv_sec = 0;
+ tv.tv_usec = ACPI_AML_USEC_PEEK;
+ FD_ZERO(&rfds);
+ maxfd = acpi_aml_set_fd(fd, maxfd, &rfds);
+ ret = select(maxfd+1, &rfds, NULL, NULL, &tv);
+ if (ret < 0)
+ perror("select");
+ if (ret > 0 && FD_ISSET(fd, &rfds))
+ return true;
+ return false;
+}
+
+/*
+ * This is a userspace IO flush implementation, replying on the prompt
+ * characters and can be turned into a flush() call after kernel implements
+ * .flush() filesystem operation.
+ */
+static void acpi_aml_flush(int fd)
+{
+ while (acpi_aml_readable(fd)) {
+ acpi_aml_batch_drain = true;
+ acpi_aml_loop(fd);
+ acpi_aml_batch_drain = false;
+ }
+}
+
+void usage(FILE *file, char *progname)
+{
+ fprintf(file, "usage: %s [-b cmd] [-f file] [-h]\n", progname);
+ fprintf(file, "\nOptions:\n");
+ fprintf(file, " -b Specify command to be executed in batch mode\n");
+ fprintf(file, " -f Specify interface file other than");
+ fprintf(file, " /sys/kernel/debug/acpi/acpidbg\n");
+ fprintf(file, " -h Print this help message\n");
+}
+
+int main(int argc, char **argv)
+{
+ int fd = 0;
+ int ch;
+ int len;
+ int ret = EXIT_SUCCESS;
+
+ while ((ch = getopt(argc, argv, "b:f:h")) != -1) {
+ switch (ch) {
+ case 'b':
+ if (acpi_aml_batch_cmd) {
+ fprintf(stderr, "Already specify %s\n",
+ acpi_aml_batch_cmd);
+ ret = EXIT_FAILURE;
+ goto exit;
+ }
+ len = strlen(optarg);
+ acpi_aml_batch_cmd = calloc(len + 2, 1);
+ if (!acpi_aml_batch_cmd) {
+ perror("calloc");
+ ret = EXIT_FAILURE;
+ goto exit;
+ }
+ memcpy(acpi_aml_batch_cmd, optarg, len);
+ acpi_aml_batch_cmd[len] = '\n';
+ acpi_aml_mode = ACPI_AML_BATCH;
+ break;
+ case 'f':
+ acpi_aml_file_path = optarg;
+ break;
+ case 'h':
+ usage(stdout, argv[0]);
+ goto exit;
+ break;
+ case '?':
+ default:
+ usage(stderr, argv[0]);
+ ret = EXIT_FAILURE;
+ goto exit;
+ break;
+ }
+ }
+
+ fd = open(acpi_aml_file_path, O_RDWR | O_NONBLOCK);
+ if (fd < 0) {
+ perror("open");
+ ret = EXIT_FAILURE;
+ goto exit;
+ }
+ acpi_aml_set_fl(STDIN_FILENO, O_NONBLOCK);
+ acpi_aml_set_fl(STDOUT_FILENO, O_NONBLOCK);
+
+ if (acpi_aml_mode == ACPI_AML_BATCH)
+ acpi_aml_flush(fd);
+ acpi_aml_loop(fd);
+
+exit:
+ if (fd < 0)
+ close(fd);
+ if (acpi_aml_batch_cmd)
+ free(acpi_aml_batch_cmd);
+ return ret;
+}
static int ap_is_existing_file(char *pathname);
+/******************************************************************************
+ *
+ * FUNCTION: ap_is_existing_file
+ *
+ * PARAMETERS: pathname - Output filename
+ *
+ * RETURN: 0 on success
+ *
+ * DESCRIPTION: Query for file overwrite if it already exists.
+ *
+ ******************************************************************************/
+
static int ap_is_existing_file(char *pathname)
{
#ifndef _GNU_EFI
} else {
ACPI_MOVE_NAME(filename, table->signature);
}
+
filename[0] = (char)tolower((int)filename[0]);
filename[1] = (char)tolower((int)filename[1]);
filename[2] = (char)tolower((int)filename[2]);
# cpufreq-bench benchmarking tool
CPUFREQ_BENCH ?= true
+# Do not build libraries, but build the code in statically
+# Libraries are still built, otherwise the Makefile code would
+# be rather ugly.
+export STATIC ?= false
+
# Prefix to the directories we're installing to
DESTDIR ?=
COMPILE_BENCH += compile-bench
endif
+ifeq ($(strip $(STATIC)),true)
+ UTIL_OBJS += $(LIB_OBJS)
+ UTIL_HEADERS += $(LIB_HEADERS)
+ UTIL_SRC += $(LIB_SRC)
+endif
+
CFLAGS += $(WARNINGS)
ifeq ($(strip $(V)),false)
$(OUTPUT)cpupower: $(UTIL_OBJS) $(OUTPUT)libcpupower.so.$(LIB_MAJ)
$(ECHO) " CC " $@
+ifeq ($(strip $(STATIC)),true)
+ $(QUIET) $(CC) $(CFLAGS) $(LDFLAGS) $(UTIL_OBJS) -lrt -lpci -L$(OUTPUT) -o $@
+else
$(QUIET) $(CC) $(CFLAGS) $(LDFLAGS) $(UTIL_OBJS) -lcpupower -lrt -lpci -L$(OUTPUT) -o $@
+endif
$(QUIET) $(STRIPCMD) $@
$(OUTPUT)po/$(PACKAGE).pot: $(UTIL_SRC)
@#DESTDIR must be set from outside to survive
@sbindir=$(sbindir) bindir=$(bindir) docdir=$(docdir) confdir=$(confdir) $(MAKE) -C bench O=$(OUTPUT) install
+ifeq ($(strip $(STATIC)),true)
+install: all install-tools install-man $(INSTALL_NLS) $(INSTALL_BENCH)
+else
install: all install-lib install-tools install-man $(INSTALL_NLS) $(INSTALL_BENCH)
+endif
uninstall:
- rm -f $(DESTDIR)${libdir}/libcpupower.*
endif
endif
+ifeq ($(strip $(STATIC)),true)
+LIBS = -L../ -L$(OUTPUT) -lm
+OBJS = $(OUTPUT)main.o $(OUTPUT)parse.o $(OUTPUT)system.o $(OUTPUT)benchmark.o \
+ $(OUTPUT)../lib/cpufreq.o $(OUTPUT)../lib/sysfs.o
+else
LIBS = -L../ -L$(OUTPUT) -lm -lcpupower
-
OBJS = $(OUTPUT)main.o $(OUTPUT)parse.o $(OUTPUT)system.o $(OUTPUT)benchmark.o
+endif
+
CFLAGS += -D_GNU_SOURCE -I../lib -DDEFAULT_CONFIG_FILE=\"$(confdir)/cpufreq-bench.conf\"
$(OUTPUT)%.o : %.c
#include <getopt.h>
#include "cpufreq.h"
+#include "helpers/sysfs.h"
#include "helpers/helpers.h"
#include "helpers/bitmask.h"
return 0;
}
-static void debug_output_one(unsigned int cpu)
-{
- char *driver;
- struct cpufreq_affected_cpus *cpus;
- struct cpufreq_available_frequencies *freqs;
- unsigned long min, max, freq_kernel, freq_hardware;
- unsigned long total_trans, latency;
- unsigned long long total_time;
- struct cpufreq_policy *policy;
- struct cpufreq_available_governors *governors;
- struct cpufreq_stats *stats;
-
- if (cpufreq_cpu_exists(cpu))
- return;
-
- freq_kernel = cpufreq_get_freq_kernel(cpu);
- freq_hardware = cpufreq_get_freq_hardware(cpu);
-
- driver = cpufreq_get_driver(cpu);
- if (!driver) {
- printf(_(" no or unknown cpufreq driver is active on this CPU\n"));
- } else {
- printf(_(" driver: %s\n"), driver);
- cpufreq_put_driver(driver);
- }
-
- cpus = cpufreq_get_related_cpus(cpu);
- if (cpus) {
- printf(_(" CPUs which run at the same hardware frequency: "));
- while (cpus->next) {
- printf("%d ", cpus->cpu);
- cpus = cpus->next;
- }
- printf("%d\n", cpus->cpu);
- cpufreq_put_related_cpus(cpus);
- }
-
- cpus = cpufreq_get_affected_cpus(cpu);
- if (cpus) {
- printf(_(" CPUs which need to have their frequency coordinated by software: "));
- while (cpus->next) {
- printf("%d ", cpus->cpu);
- cpus = cpus->next;
- }
- printf("%d\n", cpus->cpu);
- cpufreq_put_affected_cpus(cpus);
- }
-
- latency = cpufreq_get_transition_latency(cpu);
- if (latency) {
- printf(_(" maximum transition latency: "));
- print_duration(latency);
- printf(".\n");
- }
-
- if (!(cpufreq_get_hardware_limits(cpu, &min, &max))) {
- printf(_(" hardware limits: "));
- print_speed(min);
- printf(" - ");
- print_speed(max);
- printf("\n");
- }
-
- freqs = cpufreq_get_available_frequencies(cpu);
- if (freqs) {
- printf(_(" available frequency steps: "));
- while (freqs->next) {
- print_speed(freqs->frequency);
- printf(", ");
- freqs = freqs->next;
- }
- print_speed(freqs->frequency);
- printf("\n");
- cpufreq_put_available_frequencies(freqs);
- }
-
- governors = cpufreq_get_available_governors(cpu);
- if (governors) {
- printf(_(" available cpufreq governors: "));
- while (governors->next) {
- printf("%s, ", governors->governor);
- governors = governors->next;
- }
- printf("%s\n", governors->governor);
- cpufreq_put_available_governors(governors);
- }
-
- policy = cpufreq_get_policy(cpu);
- if (policy) {
- printf(_(" current policy: frequency should be within "));
- print_speed(policy->min);
- printf(_(" and "));
- print_speed(policy->max);
-
- printf(".\n ");
- printf(_("The governor \"%s\" may"
- " decide which speed to use\n within this range.\n"),
- policy->governor);
- cpufreq_put_policy(policy);
- }
-
- if (freq_kernel || freq_hardware) {
- printf(_(" current CPU frequency is "));
- if (freq_hardware) {
- print_speed(freq_hardware);
- printf(_(" (asserted by call to hardware)"));
- } else
- print_speed(freq_kernel);
- printf(".\n");
- }
- stats = cpufreq_get_stats(cpu, &total_time);
- if (stats) {
- printf(_(" cpufreq stats: "));
- while (stats) {
- print_speed(stats->frequency);
- printf(":%.2f%%", (100.0 * stats->time_in_state) / total_time);
- stats = stats->next;
- if (stats)
- printf(", ");
- }
- cpufreq_put_stats(stats);
- total_trans = cpufreq_get_transitions(cpu);
- if (total_trans)
- printf(" (%lu)\n", total_trans);
- else
- printf("\n");
- }
- get_boost_mode(cpu);
-
-}
-
/* --freq / -f */
static int get_freq_kernel(unsigned int cpu, unsigned int human)
{
unsigned long freq = cpufreq_get_freq_kernel(cpu);
- if (!freq)
+ printf(_(" current CPU frequency: "));
+ if (!freq) {
+ printf(_(" Unable to call to kernel\n"));
return -EINVAL;
+ }
if (human) {
print_speed(freq);
- printf("\n");
} else
- printf("%lu\n", freq);
+ printf("%lu", freq);
+ printf(_(" (asserted by call to kernel)\n"));
return 0;
}
static int get_freq_hardware(unsigned int cpu, unsigned int human)
{
unsigned long freq = cpufreq_get_freq_hardware(cpu);
- if (!freq)
+ printf(_(" current CPU frequency: "));
+ if (!freq) {
+ printf("Unable to call hardware\n");
return -EINVAL;
+ }
if (human) {
print_speed(freq);
- printf("\n");
} else
- printf("%lu\n", freq);
+ printf("%lu", freq);
+ printf(_(" (asserted by call to hardware)\n"));
return 0;
}
static int get_hardware_limits(unsigned int cpu)
{
unsigned long min, max;
- if (cpufreq_get_hardware_limits(cpu, &min, &max))
+
+ printf(_(" hardware limits: "));
+ if (cpufreq_get_hardware_limits(cpu, &min, &max)) {
+ printf(_("Not Available\n"));
return -EINVAL;
- printf("%lu %lu\n", min, max);
+ }
+
+ print_speed(min);
+ printf(" - ");
+ print_speed(max);
+ printf("\n");
return 0;
}
static int get_driver(unsigned int cpu)
{
char *driver = cpufreq_get_driver(cpu);
- if (!driver)
+ if (!driver) {
+ printf(_(" no or unknown cpufreq driver is active on this CPU\n"));
return -EINVAL;
- printf("%s\n", driver);
+ }
+ printf(" driver: %s\n", driver);
cpufreq_put_driver(driver);
return 0;
}
static int get_policy(unsigned int cpu)
{
struct cpufreq_policy *policy = cpufreq_get_policy(cpu);
- if (!policy)
+ if (!policy) {
+ printf(_(" Unable to determine current policy\n"));
return -EINVAL;
- printf("%lu %lu %s\n", policy->min, policy->max, policy->governor);
+ }
+ printf(_(" current policy: frequency should be within "));
+ print_speed(policy->min);
+ printf(_(" and "));
+ print_speed(policy->max);
+
+ printf(".\n ");
+ printf(_("The governor \"%s\" may decide which speed to use\n"
+ " within this range.\n"),
+ policy->governor);
cpufreq_put_policy(policy);
return 0;
}
{
struct cpufreq_available_governors *governors =
cpufreq_get_available_governors(cpu);
- if (!governors)
+
+ printf(_(" available cpufreq governors: "));
+ if (!governors) {
+ printf(_("Not Available\n"));
return -EINVAL;
+ }
while (governors->next) {
printf("%s ", governors->governor);
static int get_affected_cpus(unsigned int cpu)
{
struct cpufreq_affected_cpus *cpus = cpufreq_get_affected_cpus(cpu);
- if (!cpus)
+
+ printf(_(" CPUs which need to have their frequency coordinated by software: "));
+ if (!cpus) {
+ printf(_("Not Available\n"));
return -EINVAL;
+ }
while (cpus->next) {
printf("%d ", cpus->cpu);
static int get_related_cpus(unsigned int cpu)
{
struct cpufreq_affected_cpus *cpus = cpufreq_get_related_cpus(cpu);
- if (!cpus)
+
+ printf(_(" CPUs which run at the same hardware frequency: "));
+ if (!cpus) {
+ printf(_("Not Available\n"));
return -EINVAL;
+ }
while (cpus->next) {
printf("%d ", cpus->cpu);
static int get_latency(unsigned int cpu, unsigned int human)
{
unsigned long latency = cpufreq_get_transition_latency(cpu);
- if (!latency)
+
+ printf(_(" maximum transition latency: "));
+ if (!latency || latency == UINT_MAX) {
+ printf(_(" Cannot determine or is not supported.\n"));
return -EINVAL;
+ }
if (human) {
print_duration(latency);
return 0;
}
+static void debug_output_one(unsigned int cpu)
+{
+ struct cpufreq_available_frequencies *freqs;
+
+ get_driver(cpu);
+ get_related_cpus(cpu);
+ get_affected_cpus(cpu);
+ get_latency(cpu, 1);
+ get_hardware_limits(cpu);
+
+ freqs = cpufreq_get_available_frequencies(cpu);
+ if (freqs) {
+ printf(_(" available frequency steps: "));
+ while (freqs->next) {
+ print_speed(freqs->frequency);
+ printf(", ");
+ freqs = freqs->next;
+ }
+ print_speed(freqs->frequency);
+ printf("\n");
+ cpufreq_put_available_frequencies(freqs);
+ }
+
+ get_available_governors(cpu);
+ get_policy(cpu);
+ if (get_freq_hardware(cpu, 1) < 0)
+ get_freq_kernel(cpu, 1);
+ get_boost_mode(cpu);
+}
+
static struct option info_opts[] = {
{"debug", no_argument, NULL, 'e'},
{"boost", no_argument, NULL, 'b'},
if (!bitmask_isbitset(cpus_chosen, cpu))
continue;
- if (cpufreq_cpu_exists(cpu)) {
- printf(_("couldn't analyze CPU %d as it doesn't seem to be present\n"), cpu);
+
+ printf(_("analyzing CPU %d:\n"), cpu);
+
+ if (sysfs_is_cpu_online(cpu) != 1) {
+ printf(_(" *is offline\n"));
+ printf("\n");
continue;
}
- printf(_("analyzing CPU %d:\n"), cpu);
switch (output_param) {
case 'b':
}
if (ret)
return ret;
+ printf("\n");
}
return ret;
}
#include <stdlib.h>
#include <string.h>
#include <getopt.h>
-#include <cpufreq.h>
#include "helpers/helpers.h"
#include "helpers/sysfs.h"
unsigned int idlestates, idlestate;
char *tmp;
- printf(_ ("Analyzing CPU %d:\n"), cpu);
-
idlestates = sysfs_get_idlestate_count(cpu);
if (idlestates == 0) {
printf(_("CPU %u: No idle states\n"), cpu);
printf(_("Duration: %llu\n"),
sysfs_get_idlestate_time(cpu, idlestate));
}
- printf("\n");
}
static void cpuidle_general_output(void)
for (cpu = bitmask_first(cpus_chosen);
cpu <= bitmask_last(cpus_chosen); cpu++) {
- if (!bitmask_isbitset(cpus_chosen, cpu) ||
- cpufreq_cpu_exists(cpu))
+ if (!bitmask_isbitset(cpus_chosen, cpu))
continue;
+ printf(_("analyzing CPU %d:\n"), cpu);
+
+ if (sysfs_is_cpu_online(cpu) != 1) {
+ printf(_(" *is offline\n"));
+ printf("\n");
+ continue;
+ }
+
switch (output_param) {
case 'o':
cpuidle_cpu_output(cpu, verbose);
break;
}
+ printf("\n");
}
return EXIT_SUCCESS;
}
#include <string.h>
#include <getopt.h>
-#include <cpufreq.h>
#include "helpers/helpers.h"
#include "helpers/sysfs.h"
for (cpu = bitmask_first(cpus_chosen);
cpu <= bitmask_last(cpus_chosen); cpu++) {
- if (!bitmask_isbitset(cpus_chosen, cpu) ||
- cpufreq_cpu_exists(cpu))
+ if (!bitmask_isbitset(cpus_chosen, cpu))
continue;
printf(_("analyzing CPU %d:\n"), cpu);
+ if (sysfs_is_cpu_online(cpu) != 1){
+ printf(_(" *is offline\n"));
+ continue;
+ }
+
if (params.perf_bias) {
ret = msr_intel_get_perf_bias(cpu);
if (ret < 0) {
#include <string.h>
#include <getopt.h>
-#include <cpufreq.h>
#include "helpers/helpers.h"
#include "helpers/sysfs.h"
#include "helpers/bitmask.h"
for (cpu = bitmask_first(cpus_chosen);
cpu <= bitmask_last(cpus_chosen); cpu++) {
- if (!bitmask_isbitset(cpus_chosen, cpu) ||
- cpufreq_cpu_exists(cpu))
+ if (!bitmask_isbitset(cpus_chosen, cpu))
continue;
+ if (sysfs_is_cpu_online(cpu) != 1){
+ fprintf(stderr, _("Cannot set values on CPU %d:"), cpu);
+ fprintf(stderr, _(" *is offline\n"));
+ continue;
+ }
+
if (params.perf_bias) {
ret = msr_intel_set_perf_bias(cpu, perf_bias);
if (ret) {
cpu_top->pkgs++;
}
}
- if (!cpu_top->core_info[0].pkg == -1)
+ if (!(cpu_top->core_info[0].pkg == -1))
cpu_top->pkgs++;
/* Intel's cores count is not consecutively numbered, there may