diff options
260 files changed, 7312 insertions, 3389 deletions
diff --git a/Documentation/cpu-freq/intel-pstate.txt b/Documentation/cpu-freq/intel-pstate.txt index be8d400..f7b12c0 100644 --- a/Documentation/cpu-freq/intel-pstate.txt +++ b/Documentation/cpu-freq/intel-pstate.txt @@ -1,61 +1,131 @@ -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 @@ -63,3 +133,90 @@ the internal governor algorythm. These files are located at 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 diff --git a/Documentation/cpu-freq/pcc-cpufreq.txt b/Documentation/cpu-freq/pcc-cpufreq.txt index 9e3c3b3..0a94224 100644 --- a/Documentation/cpu-freq/pcc-cpufreq.txt +++ b/Documentation/cpu-freq/pcc-cpufreq.txt @@ -159,8 +159,8 @@ to be strictly associated with a P-state. 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: --------------------- diff --git a/Documentation/devicetree/bindings/arm/cpus.txt b/Documentation/devicetree/bindings/arm/cpus.txt index 3a07a87..6aca64f 100644 --- a/Documentation/devicetree/bindings/arm/cpus.txt +++ b/Documentation/devicetree/bindings/arm/cpus.txt @@ -242,6 +242,23 @@ nodes to be present and contain the properties described below. 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 { diff --git a/Documentation/devicetree/bindings/cpufreq/cpufreq-st.txt b/Documentation/devicetree/bindings/cpufreq/cpufreq-st.txt new file mode 100644 index 0000000..d91a02a --- /dev/null +++ b/Documentation/devicetree/bindings/cpufreq/cpufreq-st.txt @@ -0,0 +1,91 @@ +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>; + }; +}; diff --git a/Documentation/devicetree/bindings/opp/opp.txt b/Documentation/devicetree/bindings/opp/opp.txt index 0cb44dc..601256f 100644 --- a/Documentation/devicetree/bindings/opp/opp.txt +++ b/Documentation/devicetree/bindings/opp/opp.txt @@ -45,21 +45,10 @@ Devices supporting OPPs must set their "operating-points-v2" property with 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 @@ -100,6 +89,14 @@ Optional properties: 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 @@ -112,6 +109,9 @@ Optional properties: 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. @@ -123,6 +123,26 @@ Optional properties: - 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. @@ -157,20 +177,20 @@ 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>; @@ -236,20 +256,20 @@ independently. * 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; @@ -312,20 +332,20 @@ DVFS state 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>; opp-microamp = <90000>; @@ -338,20 +358,20 @@ DVFS state together. 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>; @@ -378,7 +398,7 @@ Example 4: Handling multiple regulators compatible = "operating-points-v2"; opp-shared; - opp00 { + opp@1000000000 { opp-hz = /bits/ 64 <1000000000>; opp-microvolt = <970000>, /* Supply 0 */ <960000>, /* Supply 1 */ @@ -391,7 +411,7 @@ Example 4: Handling multiple regulators /* OR */ - opp00 { + opp@1000000000 { opp-hz = /bits/ 64 <1000000000>; opp-microvolt = <970000 975000 985000>, /* Supply 0 */ <960000 965000 975000>, /* Supply 1 */ @@ -404,7 +424,7 @@ Example 4: Handling multiple regulators /* OR */ - opp00 { + opp@1000000000 { opp-hz = /bits/ 64 <1000000000>; opp-microvolt = <970000 975000 985000>, /* Supply 0 */ <960000 965000 975000>, /* Supply 1 */ @@ -417,7 +437,8 @@ Example 4: Handling multiple regulators }; }; -Example 5: Multiple OPP tables +Example 5: opp-supported-hw +(example: three level hierarchy of versions: cuts, substrate and process) / { cpus { @@ -426,40 +447,73 @@ Example 5: Multiple OPP tables ... 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 */ }; }; }; diff --git a/Documentation/power/pci.txt b/Documentation/power/pci.txt index b0e911e..4455888 100644 --- a/Documentation/power/pci.txt +++ b/Documentation/power/pci.txt @@ -999,7 +999,7 @@ from its probe routine to make runtime PM work for the device. 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. diff --git a/Documentation/power/runtime_pm.txt b/Documentation/power/runtime_pm.txt index 0784bc3..7328cf8 100644 --- a/Documentation/power/runtime_pm.txt +++ b/Documentation/power/runtime_pm.txt @@ -371,6 +371,12 @@ drivers/base/power/runtime.c and include/linux/pm_runtime.h: - 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 diff --git a/MAINTAINERS b/MAINTAINERS index 14ef6ec..ded9640 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -8466,6 +8466,17 @@ F: fs/timerfd.c 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> diff --git a/arch/arm/boot/dts/exynos4412.dtsi b/arch/arm/boot/dts/exynos4412.dtsi index 294cfe4..40beede 100644 --- a/arch/arm/boot/dts/exynos4412.dtsi +++ b/arch/arm/boot/dts/exynos4412.dtsi @@ -64,73 +64,73 @@ 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>; diff --git a/arch/x86/Kconfig b/arch/x86/Kconfig index 258965d..ccfeded 100644 --- a/arch/x86/Kconfig +++ b/arch/x86/Kconfig @@ -534,9 +534,10 @@ config X86_INTEL_QUARK 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 diff --git a/arch/x86/include/asm/iosf_mbi.h b/arch/x86/include/asm/iosf_mbi.h index b72ad0f..b41ee16 100644 --- a/arch/x86/include/asm/iosf_mbi.h +++ b/arch/x86/include/asm/iosf_mbi.h @@ -1,5 +1,5 @@ /* - * iosf_mbi.h: Intel OnChip System Fabric MailBox access support + * Intel OnChip System Fabric MailBox access support */ #ifndef IOSF_MBI_SYMS_H @@ -16,6 +16,18 @@ #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 @@ -28,50 +40,13 @@ #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); diff --git a/arch/x86/platform/atom/punit_atom_debug.c b/arch/x86/platform/atom/punit_atom_debug.c index 5ca8ead..81c769e 100644 --- a/arch/x86/platform/atom/punit_atom_debug.c +++ b/arch/x86/platform/atom/punit_atom_debug.c @@ -25,8 +25,6 @@ #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 */ @@ -85,9 +83,8 @@ static int punit_dev_state_show(struct seq_file *seq_file, void *unused) 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); diff --git a/arch/x86/platform/intel-quark/imr.c b/arch/x86/platform/intel-quark/imr.c index 0ee619f..c1bdafa 100644 --- a/arch/x86/platform/intel-quark/imr.c +++ b/arch/x86/platform/intel-quark/imr.c @@ -111,23 +111,19 @@ static int imr_read(struct imr_device *idev, u32 imr_id, struct imr_regs *imr) 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); } /** @@ -151,31 +147,27 @@ static int imr_write(struct imr_device *idev, u32 imr_id, 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; } diff --git a/drivers/acpi/Kconfig b/drivers/acpi/Kconfig index 5eef4cb..82b96ee 100644 --- a/drivers/acpi/Kconfig +++ b/drivers/acpi/Kconfig @@ -58,14 +58,25 @@ config ACPI_CCA_REQUIRED 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 diff --git a/drivers/acpi/Makefile b/drivers/acpi/Makefile index 675eaf3..cb648a4 100644 --- a/drivers/acpi/Makefile +++ b/drivers/acpi/Makefile @@ -8,13 +8,13 @@ ccflags-$(CONFIG_ACPI_DEBUG) += -DACPI_DEBUG_OUTPUT # # 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. @@ -66,10 +66,10 @@ obj-$(CONFIG_ACPI_FAN) += fan.o 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 @@ -79,6 +79,7 @@ obj-$(CONFIG_ACPI_EC_DEBUGFS) += ec_sys.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 diff --git a/drivers/acpi/acpi_apd.c b/drivers/acpi/acpi_apd.c index a450e7a..d507cf6 100644 --- a/drivers/acpi/acpi_apd.c +++ b/drivers/acpi/acpi_apd.c @@ -51,7 +51,7 @@ struct apd_private_data { 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) @@ -71,6 +71,7 @@ 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, @@ -80,6 +81,14 @@ static struct apd_device_desc cz_uart_desc = { .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 @@ -132,9 +141,14 @@ static int acpi_apd_create_device(struct acpi_device *adev, 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 { } }; diff --git a/drivers/acpi/acpi_dbg.c b/drivers/acpi/acpi_dbg.c new file mode 100644 index 0000000..15e4604 --- /dev/null +++ b/drivers/acpi/acpi_dbg.c @@ -0,0 +1,804 @@ +/* + * 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"); diff --git a/drivers/acpi/acpi_lpss.c b/drivers/acpi/acpi_lpss.c index f9e0d09..047281a6 100644 --- a/drivers/acpi/acpi_lpss.c +++ b/drivers/acpi/acpi_lpss.c @@ -15,6 +15,7 @@ #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> @@ -26,6 +27,10 @@ ACPI_MODULE_NAME("acpi_lpss"); #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 @@ -71,7 +76,7 @@ struct lpss_device_desc { 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, }; @@ -84,6 +89,23 @@ struct lpss_private_data { 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) @@ -196,13 +218,21 @@ static const struct lpss_device_desc bsw_i2c_dev_desc = { .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) @@ -574,6 +604,17 @@ static void acpi_lpss_restore_ctx(struct device *dev, { 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 @@ -586,14 +627,34 @@ static void acpi_lpss_restore_ctx(struct device *dev, 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 @@ -621,6 +682,8 @@ static int acpi_lpss_resume_early(struct device *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); @@ -628,6 +691,89 @@ static int acpi_lpss_resume_early(struct device *dev) } #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)); @@ -640,7 +786,17 @@ static int acpi_lpss_runtime_suspend(struct device *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) @@ -648,10 +804,19 @@ 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); @@ -660,6 +825,10 @@ static int acpi_lpss_runtime_resume(struct device *dev) #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 @@ -705,8 +874,14 @@ static int acpi_lpss_platform_notify(struct notifier_block *nb, } 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); @@ -714,7 +889,6 @@ static int acpi_lpss_platform_notify(struct notifier_block *nb, 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; @@ -754,10 +928,19 @@ static struct acpi_scan_handler lpss_handler = { 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 diff --git a/drivers/acpi/acpi_pnp.c b/drivers/acpi/acpi_pnp.c index 48fc3ad..67d97c0 100644 --- a/drivers/acpi/acpi_pnp.c +++ b/drivers/acpi/acpi_pnp.c @@ -367,7 +367,7 @@ static struct acpi_scan_handler acpi_pnp_handler = { */ 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" }, diff --git a/drivers/acpi/acpi_video.c b/drivers/acpi/acpi_video.c index 3405f7a..06a006f 100644 --- a/drivers/acpi/acpi_video.c +++ b/drivers/acpi/acpi_video.c @@ -77,14 +77,21 @@ module_param(allow_duplicates, bool, 0644); 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); @@ -412,6 +419,13 @@ static int video_enable_only_lcd(const struct dmi_system_id *d) 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 @@ -500,6 +514,24 @@ static struct dmi_system_id video_dmi_table[] = { 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"), + }, + }, {} }; @@ -1480,7 +1512,7 @@ static void acpi_video_bus_notify(struct acpi_device *device, u32 event) /* 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); @@ -1544,7 +1576,7 @@ static void acpi_video_device_notify(acpi_handle handle, u32 event, void *data) 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); @@ -2017,8 +2049,8 @@ int acpi_video_register(void) { 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. @@ -2039,22 +2071,22 @@ int acpi_video_register(void) * 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); @@ -2062,15 +2094,29 @@ void acpi_video_unregister_backlight(void) { 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 diff --git a/drivers/acpi/acpica/Makefile b/drivers/acpi/acpica/Makefile index 885936f..f682374 100644 --- a/drivers/acpi/acpica/Makefile +++ b/drivers/acpi/acpica/Makefile @@ -50,6 +50,7 @@ acpi-y += \ exdump.o \ exfield.o \ exfldio.o \ + exmisc.o \ exmutex.o \ exnames.o \ exoparg1.o \ @@ -57,7 +58,6 @@ acpi-y += \ exoparg3.o \ exoparg6.o \ exprep.o \ - exmisc.o \ exregion.o \ exresnte.o \ exresolv.o \ @@ -66,6 +66,7 @@ acpi-y += \ exstoren.o \ exstorob.o \ exsystem.o \ + extrace.o \ exutils.o acpi-y += \ @@ -196,7 +197,6 @@ acpi-$(ACPI_FUTURE_USAGE) += \ dbfileio.o \ dbtest.o \ utcache.o \ - utfileio.o \ utprint.o \ uttrack.o \ utuuid.o diff --git a/drivers/acpi/acpica/acapps.h b/drivers/acpi/acpica/acapps.h index e4cc48f..8b4ff40 100644 --- a/drivers/acpi/acpica/acapps.h +++ b/drivers/acpi/acpica/acapps.h @@ -44,6 +44,8 @@ #ifndef _ACAPPS #define _ACAPPS +#include <stdio.h> + /* Common info for tool signons */ #define ACPICA_NAME "Intel ACPI Component Architecture" @@ -85,11 +87,40 @@ 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 */ @@ -107,30 +138,6 @@ extern char *acpi_gbl_optarg; */ 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 */ @@ -168,6 +175,5 @@ char *ad_generate_filename(char *prefix, char *table_id); void ad_write_table(struct acpi_table_header *table, u32 length, char *table_name, char *oem_table_id); -#endif #endif /* _ACAPPS */ diff --git a/drivers/acpi/acpica/acdebug.h b/drivers/acpi/acpica/acdebug.h index c928ba4..ecb05f1 100644 --- a/drivers/acpi/acpica/acdebug.h +++ b/drivers/acpi/acpica/acdebug.h @@ -80,9 +80,15 @@ struct acpi_db_execute_walk { /* * 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 @@ -182,11 +188,15 @@ void acpi_db_display_method_info(union acpi_parse_object *op); 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); @@ -198,9 +208,13 @@ void acpi_db_display_calling_tree(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 @@ -231,10 +245,7 @@ void acpi_db_open_debug_file(char *name); 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 @@ -257,7 +268,7 @@ acpi_db_command_dispatch(char *input_buffer, 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); diff --git a/drivers/acpi/acpica/acevents.h b/drivers/acpi/acpica/acevents.h index 228704b7..d18f184 100644 --- a/drivers/acpi/acpica/acevents.h +++ b/drivers/acpi/acpica/acevents.h @@ -161,6 +161,11 @@ acpi_ev_delete_gpe_handlers(struct acpi_gpe_xrupt_info *gpe_xrupt_info, /* * 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); @@ -193,9 +198,11 @@ void 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); diff --git a/drivers/acpi/acpica/acglobal.h b/drivers/acpi/acpica/acglobal.h index faa9760..73462ca 100644 --- a/drivers/acpi/acpica/acglobal.h +++ b/drivers/acpi/acpica/acglobal.h @@ -145,6 +145,7 @@ ACPI_GLOBAL(acpi_cache_t *, acpi_gbl_operand_cache); 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 */ @@ -164,7 +165,7 @@ ACPI_GLOBAL(u8, acpi_gbl_next_owner_id_offset); /* Initialization sequencing */ -ACPI_GLOBAL(u8, acpi_gbl_reg_methods_executed); +ACPI_INIT_GLOBAL(u8, acpi_gbl_reg_methods_enabled, FALSE); /* Misc */ @@ -326,7 +327,6 @@ ACPI_GLOBAL(struct acpi_external_file *, acpi_gbl_external_file_list); #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); @@ -345,7 +345,6 @@ ACPI_GLOBAL(acpi_object_type, acpi_gbl_db_arg_types[ACPI_DEBUGGER_MAX_ARGS]); /* 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]); @@ -360,9 +359,6 @@ ACPI_GLOBAL(u16, acpi_gbl_node_type_count_misc); 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 */ /***************************************************************************** diff --git a/drivers/acpi/acpica/aclocal.h b/drivers/acpi/acpica/aclocal.h index e1dd784..24928ec 100644 --- a/drivers/acpi/acpica/aclocal.h +++ b/drivers/acpi/acpica/aclocal.h @@ -219,6 +219,13 @@ struct acpi_table_list { #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) @@ -388,7 +395,8 @@ union acpi_predefined_info { /* 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); @@ -420,6 +428,7 @@ struct acpi_simple_repair_info { struct acpi_reg_walk_info { acpi_adr_space_type space_id; + u32 function; u32 reg_run_count; }; @@ -861,6 +870,7 @@ struct acpi_parse_state { #define ACPI_PARSEOP_CLOSING_PAREN 0x10 #define ACPI_PARSEOP_COMPOUND 0x20 #define ACPI_PARSEOP_ASSIGNMENT 0x40 +#define ACPI_PARSEOP_ELSEIF 0x80 /***************************************************************************** * diff --git a/drivers/acpi/acpica/acmacros.h b/drivers/acpi/acpica/acmacros.h index e85366c..bad5bca 100644 --- a/drivers/acpi/acpica/acmacros.h +++ b/drivers/acpi/acpica/acmacros.h @@ -401,17 +401,6 @@ #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 */ diff --git a/drivers/acpi/acpica/acnamesp.h b/drivers/acpi/acpica/acnamesp.h index 5d261c9..d082e62 100644 --- a/drivers/acpi/acpica/acnamesp.h +++ b/drivers/acpi/acpica/acnamesp.h @@ -77,6 +77,7 @@ /* 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 */ @@ -183,13 +184,20 @@ acpi_ns_convert_to_buffer(union acpi_operand_object *original_object, 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 */ diff --git a/drivers/acpi/acpica/acobject.h b/drivers/acpi/acpica/acobject.h index 0bd02c4..2b154cf 100644 --- a/drivers/acpi/acpica/acobject.h +++ b/drivers/acpi/acpica/acobject.h @@ -93,9 +93,10 @@ #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 */ /****************************************************************************** * diff --git a/drivers/acpi/acpica/acopcode.h b/drivers/acpi/acpica/acopcode.h index f9acf92..324512d 100644 --- a/drivers/acpi/acpica/acopcode.h +++ b/drivers/acpi/acpica/acopcode.h @@ -92,7 +92,7 @@ #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) @@ -152,13 +152,14 @@ #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) @@ -185,7 +186,6 @@ #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) @@ -223,7 +223,7 @@ #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 @@ -285,6 +285,7 @@ #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) @@ -318,7 +319,6 @@ #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) diff --git a/drivers/acpi/acpica/acparser.h b/drivers/acpi/acpica/acparser.h index 8fc8c7c..96d510a 100644 --- a/drivers/acpi/acpica/acparser.h +++ b/drivers/acpi/acpica/acparser.h @@ -92,7 +92,13 @@ acpi_ps_get_next_simple_arg(struct acpi_parse_state *parser_state, 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, diff --git a/drivers/acpi/acpica/acutils.h b/drivers/acpi/acpica/acutils.h index 8b8fef6..9e84c05 100644 --- a/drivers/acpi/acpica/acutils.h +++ b/drivers/acpi/acpica/acutils.h @@ -184,24 +184,24 @@ acpi_status acpi_ut_init_globals(void); #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); @@ -353,14 +353,6 @@ acpi_ut_execute_power_methods(struct acpi_namespace_node *device_node, 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_status @@ -372,10 +364,6 @@ 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); diff --git a/drivers/acpi/acpica/amlcode.h b/drivers/acpi/acpica/amlcode.h index 883f20c..ab9f3f1 100644 --- a/drivers/acpi/acpica/amlcode.h +++ b/drivers/acpi/acpica/amlcode.h @@ -120,7 +120,7 @@ #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 @@ -238,7 +238,8 @@ #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 diff --git a/drivers/acpi/acpica/dbcmds.c b/drivers/acpi/acpica/dbcmds.c index 30414b3..328c35b 100644 --- a/drivers/acpi/acpica/dbcmds.c +++ b/drivers/acpi/acpica/dbcmds.c @@ -798,7 +798,7 @@ acpi_db_device_resources(acpi_handle obj_handle, 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); } @@ -1131,13 +1131,8 @@ void acpi_db_trace(char *enable_arg, char *method_arg, char *once_arg) 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) { diff --git a/drivers/acpi/acpica/dbdisply.c b/drivers/acpi/acpica/dbdisply.c index 672977e..1965b48 100644 --- a/drivers/acpi/acpica/dbdisply.c +++ b/drivers/acpi/acpica/dbdisply.c @@ -48,6 +48,7 @@ #include "acnamesp.h" #include "acparser.h" #include "acinterp.h" +#include "acevents.h" #include "acdebug.h" #define _COMPONENT ACPI_CA_DEBUGGER @@ -588,7 +589,7 @@ void acpi_db_display_calling_tree(void) * * 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 * @@ -596,44 +597,34 @@ void acpi_db_display_calling_tree(void) * ******************************************************************************/ -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); @@ -643,10 +634,6 @@ void acpi_db_display_object_type(char *name) 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, @@ -679,6 +666,12 @@ acpi_db_display_result_object(union acpi_operand_object *obj_desc, 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) { @@ -708,6 +701,12 @@ acpi_db_display_argument_object(union acpi_operand_object *obj_desc, 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; } @@ -951,28 +950,25 @@ void acpi_db_display_handlers(void) 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 */ @@ -984,7 +980,7 @@ found_handler: ; /* 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) { @@ -1079,14 +1075,14 @@ acpi_db_display_non_root_handlers(acpi_handle obj_handle, 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-> diff --git a/drivers/acpi/acpica/dbfileio.c b/drivers/acpi/acpica/dbfileio.c index d0e6b20..31f54d7 100644 --- a/drivers/acpi/acpica/dbfileio.c +++ b/drivers/acpi/acpica/dbfileio.c @@ -46,6 +46,10 @@ #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") @@ -110,122 +114,31 @@ void acpi_db_open_debug_file(char *name) } #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 @@ -239,18 +152,12 @@ acpi_db_get_table_from_file(char *filename, 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); } diff --git a/drivers/acpi/acpica/dbinput.c b/drivers/acpi/acpica/dbinput.c index 0480254..6203001 100644 --- a/drivers/acpi/acpica/dbinput.c +++ b/drivers/acpi/acpica/dbinput.c @@ -45,6 +45,10 @@ #include "accommon.h" #include "acdebug.h" +#ifdef ACPI_APPLICATION +#include "acapps.h" +#endif + #define _COMPONENT ACPI_CA_DEBUGGER ACPI_MODULE_NAME("dbinput") @@ -53,8 +57,6 @@ static u32 acpi_db_get_line(char *input_buffer); 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); @@ -623,9 +625,7 @@ static u32 acpi_db_get_line(char *input_buffer) /* 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) { @@ -1050,11 +1050,17 @@ acpi_db_command_dispatch(char *input_buffer, 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: @@ -1149,55 +1155,16 @@ acpi_db_command_dispatch(char *input_buffer, 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 * @@ -1206,7 +1173,7 @@ static void acpi_db_single_thread(void) * ******************************************************************************/ -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; @@ -1216,52 +1183,31 @@ acpi_status acpi_db_user_commands(char prompt, union acpi_parse_object *op) 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); } diff --git a/drivers/acpi/acpica/dbnames.c b/drivers/acpi/acpica/dbnames.c index 04ff1eb..4f68dfc 100644 --- a/drivers/acpi/acpica/dbnames.c +++ b/drivers/acpi/acpica/dbnames.c @@ -438,7 +438,7 @@ acpi_db_walk_for_predefined_names(acpi_handle obj_handle, return (AE_OK); } - pathname = acpi_ns_get_external_pathname(node); + pathname = acpi_ns_get_normalized_pathname(node, TRUE); if (!pathname) { return (AE_OK); } diff --git a/drivers/acpi/acpica/dbstats.c b/drivers/acpi/acpica/dbstats.c index 4ba0a20..de255d9 100644 --- a/drivers/acpi/acpica/dbstats.c +++ b/drivers/acpi/acpica/dbstats.c @@ -382,6 +382,7 @@ acpi_status acpi_db_display_statistics(char *type_arg) 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); diff --git a/drivers/acpi/acpica/dbtest.c b/drivers/acpi/acpica/dbtest.c index 10ea8bf..68b4e8d 100644 --- a/drivers/acpi/acpica/dbtest.c +++ b/drivers/acpi/acpica/dbtest.c @@ -953,7 +953,7 @@ acpi_db_evaluate_one_predefined_name(acpi_handle obj_handle, return (AE_OK); } - pathname = acpi_ns_get_external_pathname(node); + pathname = acpi_ns_get_normalized_pathname(node, TRUE); if (!pathname) { return (AE_OK); } diff --git a/drivers/acpi/acpica/dbutils.c b/drivers/acpi/acpica/dbutils.c index 86790e0..8c85d85 100644 --- a/drivers/acpi/acpica/dbutils.c +++ b/drivers/acpi/acpica/dbutils.c @@ -173,6 +173,7 @@ void acpi_db_dump_external_object(union acpi_object *obj_desc, u32 level) if (obj_desc->buffer.length > 16) { acpi_os_printf("\n"); } + acpi_ut_debug_dump_buffer(ACPI_CAST_PTR (u8, obj_desc->buffer.pointer), diff --git a/drivers/acpi/acpica/dbxface.c b/drivers/acpi/acpica/dbxface.c index 342298a..d7ff58e 100644 --- a/drivers/acpi/acpica/dbxface.c +++ b/drivers/acpi/acpica/dbxface.c @@ -85,46 +85,21 @@ acpi_db_start_command(struct acpi_walk_state *walk_state, 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 = @@ -134,11 +109,46 @@ acpi_db_start_command(struct acpi_walk_state *walk_state, /* 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 * * PARAMETERS: walk_state - Current walk @@ -420,15 +430,7 @@ acpi_status acpi_initialize_debugger(void) /* 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); @@ -473,13 +475,14 @@ void acpi_terminate_debugger(void) 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) { diff --git a/drivers/acpi/acpica/dsargs.c b/drivers/acpi/acpica/dsargs.c index e2ab59e..76cfced 100644 --- a/drivers/acpi/acpica/dsargs.c +++ b/drivers/acpi/acpica/dsargs.c @@ -194,8 +194,8 @@ acpi_ds_get_buffer_field_arguments(union acpi_operand_object *obj_desc) 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))); @@ -385,7 +385,8 @@ acpi_status acpi_ds_get_region_arguments(union acpi_operand_object *obj_desc) 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)); diff --git a/drivers/acpi/acpica/dscontrol.c b/drivers/acpi/acpica/dscontrol.c index 435fc16..06a6f7f 100644 --- a/drivers/acpi/acpica/dscontrol.c +++ b/drivers/acpi/acpica/dscontrol.c @@ -47,6 +47,7 @@ #include "amlcode.h" #include "acdispat.h" #include "acinterp.h" +#include "acdebug.h" #define _COMPONENT ACPI_DISPATCHER ACPI_MODULE_NAME("dscontrol") @@ -348,14 +349,7 @@ acpi_ds_exec_end_control_op(struct acpi_walk_state * walk_state, 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 */ diff --git a/drivers/acpi/acpica/dsdebug.c b/drivers/acpi/acpica/dsdebug.c index 309556e..1eb82bd 100644 --- a/drivers/acpi/acpica/dsdebug.c +++ b/drivers/acpi/acpica/dsdebug.c @@ -161,6 +161,7 @@ acpi_ds_dump_method_stack(acpi_status status, 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 */ @@ -203,8 +204,8 @@ acpi_ds_dump_method_stack(acpi_status status, } 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 ")); diff --git a/drivers/acpi/acpica/dsfield.c b/drivers/acpi/acpica/dsfield.c index 20de148..6bca0ec 100644 --- a/drivers/acpi/acpica/dsfield.c +++ b/drivers/acpi/acpica/dsfield.c @@ -106,6 +106,7 @@ acpi_ds_create_external_region(acpi_status lookup_status, * 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); @@ -202,11 +203,10 @@ acpi_ds_create_buffer_field(union acpi_parse_object *op, /* 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); @@ -244,8 +244,8 @@ acpi_ds_create_buffer_field(union acpi_parse_object *op, } /* - * Remember location in AML stream of the field unit opcode and operands -- - * since the buffer and index operands must be evaluated. + * Remember location in AML stream of the field unit opcode and operands + * -- since the buffer and index operands must be evaluated. */ second_desc = obj_desc->common.next_object; second_desc->extra.aml_start = op->named.data; @@ -310,8 +310,8 @@ acpi_ds_get_field_names(struct acpi_create_field_info *info, 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, @@ -344,13 +344,13 @@ acpi_ds_get_field_names(struct acpi_create_field_info *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: @@ -425,8 +425,8 @@ acpi_ds_get_field_names(struct acpi_create_field_info *info, /* 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, @@ -716,11 +716,12 @@ acpi_ds_create_bank_field(union acpi_parse_object *op, /* * 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; diff --git a/drivers/acpi/acpica/dsinit.c b/drivers/acpi/acpica/dsinit.c index 920f1b1..c1d8af8 100644 --- a/drivers/acpi/acpica/dsinit.c +++ b/drivers/acpi/acpica/dsinit.c @@ -247,7 +247,7 @@ acpi_ds_initialize_objects(u32 table_index, /* 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, diff --git a/drivers/acpi/acpica/dsmethod.c b/drivers/acpi/acpica/dsmethod.c index bc32f31..6585e8e 100644 --- a/drivers/acpi/acpica/dsmethod.c +++ b/drivers/acpi/acpica/dsmethod.c @@ -118,10 +118,9 @@ acpi_ds_auto_serialize_method(struct acpi_namespace_node *node, 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); @@ -375,7 +374,8 @@ acpi_ds_begin_method_execution(struct acpi_namespace_node *method_node, && (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)); @@ -411,8 +411,19 @@ acpi_ds_begin_method_execution(struct acpi_namespace_node *method_node, 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 = @@ -501,16 +512,18 @@ acpi_ds_call_control_method(struct acpi_thread_state *thread, /* 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; @@ -797,7 +810,8 @@ acpi_ds_terminate_control_method(union acpi_operand_object *method_desc, 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)); } @@ -815,6 +829,7 @@ acpi_ds_terminate_control_method(union acpi_operand_object *method_desc, */ method_desc->method.info_flags &= ~ACPI_METHOD_SERIALIZED_PENDING; + method_desc->method.info_flags |= (ACPI_METHOD_SERIALIZED | ACPI_METHOD_IGNORE_SYNC_LEVEL); diff --git a/drivers/acpi/acpica/dsmthdat.c b/drivers/acpi/acpica/dsmthdat.c index 2e4c42b..03c44f2 100644 --- a/drivers/acpi/acpica/dsmthdat.c +++ b/drivers/acpi/acpica/dsmthdat.c @@ -99,6 +99,7 @@ void acpi_ds_method_data_init(struct acpi_walk_state *walk_state) 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; @@ -201,7 +202,7 @@ acpi_ds_method_data_init_args(union acpi_operand_object **params, 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); } @@ -214,9 +215,9 @@ acpi_ds_method_data_init_args(union acpi_operand_object **params, * 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); } @@ -610,11 +611,11 @@ acpi_ds_store_object_to_local(u8 type, * 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, @@ -638,6 +639,7 @@ acpi_ds_store_object_to_local(u8 type, if (new_obj_desc != obj_desc) { acpi_ut_remove_reference(new_obj_desc); } + return_ACPI_STATUS(status); } } diff --git a/drivers/acpi/acpica/dsobject.c b/drivers/acpi/acpica/dsobject.c index 2beb7fd..302c91f 100644 --- a/drivers/acpi/acpica/dsobject.c +++ b/drivers/acpi/acpica/dsobject.c @@ -463,10 +463,10 @@ acpi_ds_build_internal_package_obj(struct acpi_walk_state *walk_state, 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) { @@ -525,7 +525,8 @@ acpi_ds_build_internal_package_obj(struct acpi_walk_state *walk_state, } 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) { /* @@ -533,7 +534,8 @@ acpi_ds_build_internal_package_obj(struct acpi_walk_state *walk_state, * 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)); } @@ -584,8 +586,9 @@ acpi_ds_create_node(struct acpi_walk_state *walk_state, /* 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); } diff --git a/drivers/acpi/acpica/dsopcode.c b/drivers/acpi/acpica/dsopcode.c index 81d7b986..1edd66f 100644 --- a/drivers/acpi/acpica/dsopcode.c +++ b/drivers/acpi/acpica/dsopcode.c @@ -243,8 +243,9 @@ acpi_ds_init_buffer_field(u16 aml_opcode, * 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; } @@ -330,8 +331,9 @@ acpi_ds_eval_buffer_field_operands(struct acpi_walk_state *walk_state, /* 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), @@ -414,8 +416,9 @@ acpi_ds_eval_region_operands(struct acpi_walk_state *walk_state, /* 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); } @@ -452,7 +455,6 @@ acpi_ds_eval_region_operands(struct acpi_walk_state *walk_state, /* Now the address and length are valid for this opregion */ obj_desc->region.flags |= AOPOBJ_DATA_VALID; - return_ACPI_STATUS(status); } @@ -510,8 +512,9 @@ acpi_ds_eval_table_region_operands(struct acpi_walk_state *walk_state, * 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; } diff --git a/drivers/acpi/acpica/dsutils.c b/drivers/acpi/acpica/dsutils.c index ebc577b..fa8e292 100644 --- a/drivers/acpi/acpica/dsutils.c +++ b/drivers/acpi/acpica/dsutils.c @@ -245,9 +245,9 @@ acpi_ds_is_result_used(union acpi_parse_object * op, * 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; @@ -481,10 +481,9 @@ acpi_ds_create_operand(struct acpi_walk_state *walk_state, /* 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); @@ -503,9 +502,8 @@ acpi_ds_create_operand(struct acpi_walk_state *walk_state, */ 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); @@ -522,9 +520,10 @@ acpi_ds_create_operand(struct acpi_walk_state *walk_state, 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)) { @@ -605,8 +604,8 @@ acpi_ds_create_operand(struct acpi_walk_state *walk_state, 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 */ @@ -633,15 +632,16 @@ acpi_ds_create_operand(struct acpi_walk_state *walk_state, 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 @@ -685,8 +685,7 @@ acpi_ds_create_operand(struct acpi_walk_state *walk_state, 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); diff --git a/drivers/acpi/acpica/dswexec.c b/drivers/acpi/acpica/dswexec.c index df54d46..ed2f1d3 100644 --- a/drivers/acpi/acpica/dswexec.c +++ b/drivers/acpi/acpica/dswexec.c @@ -172,14 +172,14 @@ acpi_ds_get_predicate_value(struct acpi_walk_state *walk_state, 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 @@ -264,8 +264,8 @@ acpi_ds_exec_begin_op(struct acpi_walk_state *walk_state, (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; @@ -386,11 +386,10 @@ acpi_status acpi_ds_exec_end_op(struct acpi_walk_state *walk_state) /* 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 */ @@ -502,9 +501,8 @@ acpi_status acpi_ds_exec_end_op(struct acpi_walk_state *walk_state) "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); @@ -586,8 +584,8 @@ acpi_status acpi_ds_exec_end_op(struct acpi_walk_state *walk_state) * 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, @@ -692,7 +690,8 @@ acpi_status acpi_ds_exec_end_op(struct acpi_walk_state *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)); @@ -728,8 +727,8 @@ cleanup: /* 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: diff --git a/drivers/acpi/acpica/dswload.c b/drivers/acpi/acpica/dswload.c index 097188a..b325474 100644 --- a/drivers/acpi/acpica/dswload.c +++ b/drivers/acpi/acpica/dswload.c @@ -476,13 +476,9 @@ acpi_status acpi_ds_load1_end_op(struct acpi_walk_state *walk_state) status = acpi_ex_create_region(op->named.data, op->named.length, - (acpi_adr_space_type) ((op-> - common. - value. - arg)-> - common. - value. - integer), + (acpi_adr_space_type) + ((op->common.value.arg)-> + common.value.integer), walk_state); if (ACPI_FAILURE(status)) { return_ACPI_STATUS(status); diff --git a/drivers/acpi/acpica/dswload2.c b/drivers/acpi/acpica/dswload2.c index e2c08cd..8a32153 100644 --- a/drivers/acpi/acpica/dswload2.c +++ b/drivers/acpi/acpica/dswload2.c @@ -598,11 +598,10 @@ acpi_status acpi_ds_load2_end_op(struct acpi_walk_state *walk_state) * 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); } @@ -664,6 +663,7 @@ acpi_status acpi_ds_load2_end_op(struct acpi_walk_state *walk_state) length, walk_state); } + walk_state->operands[0] = NULL; walk_state->num_operands = 0; diff --git a/drivers/acpi/acpica/dswscope.c b/drivers/acpi/acpica/dswscope.c index 43b3ea4..2d7a044 100644 --- a/drivers/acpi/acpica/dswscope.c +++ b/drivers/acpi/acpica/dswscope.c @@ -77,6 +77,7 @@ void acpi_ds_scope_stack_clear(struct acpi_walk_state *walk_state) "Popped object type (%s)\n", acpi_ut_get_type_name(scope_info->common. value))); + acpi_ut_delete_generic_state(scope_info); } } diff --git a/drivers/acpi/acpica/evgpe.c b/drivers/acpi/acpica/evgpe.c index ccf7932..112e821 100644 --- a/drivers/acpi/acpica/evgpe.c +++ b/drivers/acpi/acpica/evgpe.c @@ -92,8 +92,8 @@ acpi_ev_update_gpe_enable_mask(struct acpi_gpe_event_info *gpe_event_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); } diff --git a/drivers/acpi/acpica/evgpeblk.c b/drivers/acpi/acpica/evgpeblk.c index e0f24c5..c00a9f2 100644 --- a/drivers/acpi/acpica/evgpeblk.c +++ b/drivers/acpi/acpica/evgpeblk.c @@ -167,6 +167,7 @@ acpi_status acpi_ev_delete_gpe_block(struct acpi_gpe_block_info *gpe_block) if (gpe_block->next) { gpe_block->next->previous = gpe_block->previous; } + acpi_os_release_lock(acpi_gbl_gpe_lock, flags); } diff --git a/drivers/acpi/acpica/evgpeutil.c b/drivers/acpi/acpica/evgpeutil.c index 3a958f3..fd5ab90 100644 --- a/drivers/acpi/acpica/evgpeutil.c +++ b/drivers/acpi/acpica/evgpeutil.c @@ -346,6 +346,7 @@ acpi_ev_delete_gpe_handlers(struct acpi_gpe_xrupt_info *gpe_xrupt_info, ACPI_FREE(notify); notify = next; } + gpe_event_info->dispatch.notify_list = NULL; gpe_event_info->flags &= ~ACPI_GPE_DISPATCH_MASK; diff --git a/drivers/acpi/acpica/evhandler.c b/drivers/acpi/acpica/evhandler.c index 74e8595f..709419c7 100644 --- a/drivers/acpi/acpica/evhandler.c +++ b/drivers/acpi/acpica/evhandler.c @@ -159,7 +159,7 @@ acpi_ev_has_default_handler(struct acpi_namespace_node *node, 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 */ @@ -247,35 +247,31 @@ acpi_ev_install_handler(acpi_handle obj_handle, /* 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); } /* @@ -309,6 +305,44 @@ acpi_ev_install_handler(acpi_handle obj_handle, /******************************************************************************* * + * 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 * * PARAMETERS: node - Namespace node for the device @@ -332,15 +366,15 @@ acpi_ev_install_space_handler(struct acpi_namespace_node * node, { 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) && @@ -407,38 +441,30 @@ acpi_ev_install_space_handler(struct acpi_namespace_node * node, 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, @@ -477,7 +503,8 @@ acpi_ev_install_space_handler(struct acpi_namespace_node * node, } 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)); @@ -506,28 +533,26 @@ acpi_ev_install_space_handler(struct acpi_namespace_node * node, /* 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); diff --git a/drivers/acpi/acpica/evmisc.c b/drivers/acpi/acpica/evmisc.c index f7c9dfe..8866f50 100644 --- a/drivers/acpi/acpica/evmisc.c +++ b/drivers/acpi/acpica/evmisc.c @@ -68,6 +68,7 @@ static void ACPI_SYSTEM_XFACE acpi_ev_notify_dispatch(void *context); u8 acpi_ev_is_notify_object(struct acpi_namespace_node *node) { + switch (node->type) { case ACPI_TYPE_DEVICE: case ACPI_TYPE_PROCESSOR: @@ -170,8 +171,8 @@ acpi_ev_queue_notify_request(struct acpi_namespace_node * node, 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); } diff --git a/drivers/acpi/acpica/evregion.c b/drivers/acpi/acpica/evregion.c index 5ee79a1..a43178f 100644 --- a/drivers/acpi/acpica/evregion.c +++ b/drivers/acpi/acpica/evregion.c @@ -97,15 +97,12 @@ acpi_status acpi_ev_initialize_op_regions(void) 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); } @@ -127,6 +124,12 @@ acpi_status acpi_ev_initialize_op_regions(void) * 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 @@ -498,6 +501,12 @@ acpi_ev_attach_region(union acpi_operand_object *handler_obj, 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), @@ -509,17 +518,56 @@ acpi_ev_attach_region(union acpi_operand_object *handler_obj, 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; } /******************************************************************************* @@ -550,7 +598,18 @@ acpi_ev_execute_reg_method(union acpi_operand_object *region_obj, u32 function) 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); } @@ -599,6 +658,16 @@ acpi_ev_execute_reg_method(union acpi_operand_object *region_obj, u32 function) 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]); @@ -613,24 +682,25 @@ cleanup1: * * 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, @@ -643,9 +713,9 @@ acpi_ev_execute_reg_methods(struct acpi_namespace_node *node, * 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 */ @@ -658,7 +728,7 @@ acpi_ev_execute_reg_methods(struct acpi_namespace_node *node, info.reg_run_count, acpi_ut_get_region_name(info.space_id))); - return_ACPI_STATUS(status); + return_VOID; } /******************************************************************************* @@ -717,7 +787,7 @@ acpi_ev_reg_run(acpi_handle obj_handle, } 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); } diff --git a/drivers/acpi/acpica/evrgnini.c b/drivers/acpi/acpica/evrgnini.c index da32339..bb2e529 100644 --- a/drivers/acpi/acpica/evrgnini.c +++ b/drivers/acpi/acpica/evrgnini.c @@ -507,9 +507,6 @@ acpi_ev_initialize_region(union acpi_operand_object *region_obj, 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); @@ -521,38 +518,15 @@ acpi_ev_initialize_region(union acpi_operand_object *region_obj, 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) { @@ -566,18 +540,10 @@ acpi_ev_initialize_region(union acpi_operand_object *region_obj, 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: @@ -602,60 +568,49 @@ acpi_ev_initialize_region(union acpi_operand_object *region_obj, 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); } } diff --git a/drivers/acpi/acpica/evxface.c b/drivers/acpi/acpica/evxface.c index 07d22bf..012b9de 100644 --- a/drivers/acpi/acpica/evxface.c +++ b/drivers/acpi/acpica/evxface.c @@ -879,9 +879,8 @@ acpi_install_gpe_handler(acpi_handle gpe_device, 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); } @@ -914,8 +913,8 @@ acpi_install_gpe_raw_handler(acpi_handle gpe_device, 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); } diff --git a/drivers/acpi/acpica/evxfregn.c b/drivers/acpi/acpica/evxfregn.c index f21afba..35f9e60 100644 --- a/drivers/acpi/acpica/evxfregn.c +++ b/drivers/acpi/acpica/evxfregn.c @@ -112,41 +112,9 @@ acpi_install_address_space_handler(acpi_handle device, 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); @@ -215,8 +183,8 @@ acpi_remove_address_space_handler(acpi_handle device, /* 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 */ diff --git a/drivers/acpi/acpica/exconfig.c b/drivers/acpi/acpica/exconfig.c index b540913..adcb9c7 100644 --- a/drivers/acpi/acpica/exconfig.c +++ b/drivers/acpi/acpica/exconfig.c @@ -358,8 +358,8 @@ acpi_ex_load_op(union acpi_operand_object *obj_desc, } /* - * 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); @@ -454,8 +454,8 @@ acpi_ex_load_op(union acpi_operand_object *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) { diff --git a/drivers/acpi/acpica/exconvrt.c b/drivers/acpi/acpica/exconvrt.c index 1e4c5b6..73c2e82 100644 --- a/drivers/acpi/acpica/exconvrt.c +++ b/drivers/acpi/acpica/exconvrt.c @@ -227,8 +227,8 @@ acpi_ex_convert_to_buffer(union acpi_operand_object *obj_desc, /* 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: @@ -354,9 +354,8 @@ acpi_ex_convert_to_ascii(u64 integer, u16 base, u8 *string, u8 data_width) /* 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; diff --git a/drivers/acpi/acpica/excreate.c b/drivers/acpi/acpica/excreate.c index ccb7219..46be5a2 100644 --- a/drivers/acpi/acpica/excreate.c +++ b/drivers/acpi/acpica/excreate.c @@ -189,9 +189,9 @@ acpi_status acpi_ex_create_event(struct acpi_walk_state *walk_state) /* 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: /* @@ -326,9 +326,10 @@ acpi_ex_create_region(u8 * aml_start, * 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; @@ -342,6 +343,10 @@ acpi_ex_create_region(u8 * aml_start, 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 */ @@ -492,10 +497,9 @@ acpi_ex_create_method(u8 * aml_start, * 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 diff --git a/drivers/acpi/acpica/exdebug.c b/drivers/acpi/acpica/exdebug.c index de92458..b223090 100644 --- a/drivers/acpi/acpica/exdebug.c +++ b/drivers/acpi/acpica/exdebug.c @@ -43,21 +43,11 @@ #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 /******************************************************************************* * @@ -80,7 +70,6 @@ static const char *acpi_ex_get_trace_event_name(acpi_trace_event_type type); * enabled if necessary. * ******************************************************************************/ - void acpi_ex_do_debug_object(union acpi_operand_object *source_desc, u32 level, u32 index) @@ -99,20 +88,40 @@ acpi_ex_do_debug_object(union acpi_operand_object *source_desc, 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 */ @@ -127,8 +136,15 @@ acpi_ex_do_debug_object(union acpi_operand_object *source_desc, } 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", @@ -137,7 +153,7 @@ acpi_ex_do_debug_object(union acpi_operand_object *source_desc, } } 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), @@ -175,14 +191,12 @@ acpi_ex_do_debug_object(union acpi_operand_object *source_desc, 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 */ @@ -261,11 +275,14 @@ acpi_ex_do_debug_object(union acpi_operand_object *source_desc, 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; @@ -293,9 +310,14 @@ acpi_ex_do_debug_object(union acpi_operand_object *source_desc, 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: @@ -311,7 +333,7 @@ acpi_ex_do_debug_object(union acpi_operand_object *source_desc, default: - acpi_os_printf("%p\n", source_desc); + acpi_os_printf("(Descriptor %p)\n", source_desc); break; } @@ -319,316 +341,3 @@ acpi_ex_do_debug_object(union acpi_operand_object *source_desc, return_VOID; } #endif - -/******************************************************************************* - * - * FUNCTION: acpi_ex_interpreter_trace_enabled - * - * PARAMETERS: name - Whether method name should be matched, - * this should be checked before starting - * the tracer - * - * RETURN: TRUE if interpreter trace is enabled. - * - * DESCRIPTION: Check whether interpreter trace is enabled - * - ******************************************************************************/ - -static u8 acpi_ex_interpreter_trace_enabled(char *name) -{ - - /* Check if tracing is enabled */ - - if (!(acpi_gbl_trace_flags & ACPI_TRACE_ENABLED)) { - return (FALSE); - } - - /* - * Check if tracing is filtered: - * - * 1. If the tracer is started, acpi_gbl_trace_method_object should have - * been filled by the trace starter - * 2. If the tracer is not started, acpi_gbl_trace_method_name should be - * matched if it is specified - * 3. If the tracer is oneshot style, acpi_gbl_trace_method_name should - * not be cleared by the trace stopper during the first match - */ - if (acpi_gbl_trace_method_object) { - return (TRUE); - } - if (name && - (acpi_gbl_trace_method_name && - strcmp(acpi_gbl_trace_method_name, name))) { - return (FALSE); - } - if ((acpi_gbl_trace_flags & ACPI_TRACE_ONESHOT) && - !acpi_gbl_trace_method_name) { - return (FALSE); - } - - return (TRUE); -} - -/******************************************************************************* - * - * FUNCTION: acpi_ex_get_trace_event_name - * - * PARAMETERS: type - Trace event type - * - * RETURN: Trace event name. - * - * DESCRIPTION: Used to obtain the full trace event name. - * - ******************************************************************************/ - -#ifdef ACPI_DEBUG_OUTPUT - -static const char *acpi_ex_get_trace_event_name(acpi_trace_event_type type) -{ - switch (type) { - case ACPI_TRACE_AML_METHOD: - - return "Method"; - - case ACPI_TRACE_AML_OPCODE: - - return "Opcode"; - - case ACPI_TRACE_AML_REGION: - - return "Region"; - - default: - - return ""; - } -} - -#endif - -/******************************************************************************* - * - * FUNCTION: acpi_ex_trace_point - * - * PARAMETERS: type - Trace event type - * begin - TRUE if before execution - * aml - Executed AML address - * pathname - Object path - * - * RETURN: None - * - * DESCRIPTION: Internal interpreter execution trace. - * - ******************************************************************************/ - -void -acpi_ex_trace_point(acpi_trace_event_type type, - u8 begin, u8 *aml, char *pathname) -{ - - ACPI_FUNCTION_NAME(ex_trace_point); - - if (pathname) { - ACPI_DEBUG_PRINT((ACPI_DB_TRACE_POINT, - "%s %s [0x%p:%s] execution.\n", - acpi_ex_get_trace_event_name(type), - begin ? "Begin" : "End", aml, pathname)); - } else { - ACPI_DEBUG_PRINT((ACPI_DB_TRACE_POINT, - "%s %s [0x%p] execution.\n", - acpi_ex_get_trace_event_name(type), - begin ? "Begin" : "End", aml)); - } -} - -/******************************************************************************* - * - * FUNCTION: acpi_ex_start_trace_method - * - * PARAMETERS: method_node - Node of the method - * obj_desc - The method object - * walk_state - current state, NULL if not yet executing - * a method. - * - * RETURN: None - * - * DESCRIPTION: Start control method execution trace - * - ******************************************************************************/ - -void -acpi_ex_start_trace_method(struct acpi_namespace_node *method_node, - union acpi_operand_object *obj_desc, - struct acpi_walk_state *walk_state) -{ - acpi_status status; - char *pathname = NULL; - u8 enabled = FALSE; - - ACPI_FUNCTION_NAME(ex_start_trace_method); - - if (method_node) { - pathname = acpi_ns_get_normalized_pathname(method_node, TRUE); - } - - status = acpi_ut_acquire_mutex(ACPI_MTX_NAMESPACE); - if (ACPI_FAILURE(status)) { - goto exit; - } - - enabled = acpi_ex_interpreter_trace_enabled(pathname); - if (enabled && !acpi_gbl_trace_method_object) { - acpi_gbl_trace_method_object = obj_desc; - acpi_gbl_original_dbg_level = acpi_dbg_level; - acpi_gbl_original_dbg_layer = acpi_dbg_layer; - acpi_dbg_level = ACPI_TRACE_LEVEL_ALL; - acpi_dbg_layer = ACPI_TRACE_LAYER_ALL; - - if (acpi_gbl_trace_dbg_level) { - acpi_dbg_level = acpi_gbl_trace_dbg_level; - } - if (acpi_gbl_trace_dbg_layer) { - acpi_dbg_layer = acpi_gbl_trace_dbg_layer; - } - } - (void)acpi_ut_release_mutex(ACPI_MTX_NAMESPACE); - -exit: - if (enabled) { - ACPI_TRACE_POINT(ACPI_TRACE_AML_METHOD, TRUE, - obj_desc ? obj_desc->method.aml_start : NULL, - pathname); - } - if (pathname) { - ACPI_FREE(pathname); - } -} - -/******************************************************************************* - * - * FUNCTION: acpi_ex_stop_trace_method - * - * PARAMETERS: method_node - Node of the method - * obj_desc - The method object - * walk_state - current state, NULL if not yet executing - * a method. - * - * RETURN: None - * - * DESCRIPTION: Stop control method execution trace - * - ******************************************************************************/ - -void -acpi_ex_stop_trace_method(struct acpi_namespace_node *method_node, - union acpi_operand_object *obj_desc, - struct acpi_walk_state *walk_state) -{ - acpi_status status; - char *pathname = NULL; - u8 enabled; - - ACPI_FUNCTION_NAME(ex_stop_trace_method); - - if (method_node) { - pathname = acpi_ns_get_normalized_pathname(method_node, TRUE); - } - - status = acpi_ut_acquire_mutex(ACPI_MTX_NAMESPACE); - if (ACPI_FAILURE(status)) { - goto exit_path; - } - - enabled = acpi_ex_interpreter_trace_enabled(NULL); - - (void)acpi_ut_release_mutex(ACPI_MTX_NAMESPACE); - - if (enabled) { - ACPI_TRACE_POINT(ACPI_TRACE_AML_METHOD, FALSE, - obj_desc ? obj_desc->method.aml_start : NULL, - pathname); - } - - status = acpi_ut_acquire_mutex(ACPI_MTX_NAMESPACE); - if (ACPI_FAILURE(status)) { - goto exit_path; - } - - /* Check whether the tracer should be stopped */ - - if (acpi_gbl_trace_method_object == obj_desc) { - - /* Disable further tracing if type is one-shot */ - - if (acpi_gbl_trace_flags & ACPI_TRACE_ONESHOT) { - acpi_gbl_trace_method_name = NULL; - } - - acpi_dbg_level = acpi_gbl_original_dbg_level; - acpi_dbg_layer = acpi_gbl_original_dbg_layer; - acpi_gbl_trace_method_object = NULL; - } - - (void)acpi_ut_release_mutex(ACPI_MTX_NAMESPACE); - -exit_path: - if (pathname) { - ACPI_FREE(pathname); - } -} - -/******************************************************************************* - * - * FUNCTION: acpi_ex_start_trace_opcode - * - * PARAMETERS: op - The parser opcode object - * walk_state - current state, NULL if not yet executing - * a method. - * - * RETURN: None - * - * DESCRIPTION: Start opcode execution trace - * - ******************************************************************************/ - -void -acpi_ex_start_trace_opcode(union acpi_parse_object *op, - struct acpi_walk_state *walk_state) -{ - - ACPI_FUNCTION_NAME(ex_start_trace_opcode); - - if (acpi_ex_interpreter_trace_enabled(NULL) && - (acpi_gbl_trace_flags & ACPI_TRACE_OPCODE)) { - ACPI_TRACE_POINT(ACPI_TRACE_AML_OPCODE, TRUE, - op->common.aml, op->common.aml_op_name); - } -} - -/******************************************************************************* - * - * FUNCTION: acpi_ex_stop_trace_opcode - * - * PARAMETERS: op - The parser opcode object - * walk_state - current state, NULL if not yet executing - * a method. - * - * RETURN: None - * - * DESCRIPTION: Stop opcode execution trace - * - ******************************************************************************/ - -void -acpi_ex_stop_trace_opcode(union acpi_parse_object *op, - struct acpi_walk_state *walk_state) -{ - - ACPI_FUNCTION_NAME(ex_stop_trace_opcode); - - if (acpi_ex_interpreter_trace_enabled(NULL) && - (acpi_gbl_trace_flags & ACPI_TRACE_OPCODE)) { - ACPI_TRACE_POINT(ACPI_TRACE_AML_OPCODE, FALSE, - op->common.aml, op->common.aml_op_name); - } -} diff --git a/drivers/acpi/acpica/exdump.c b/drivers/acpi/acpica/exdump.c index d836f88..ff976c4 100644 --- a/drivers/acpi/acpica/exdump.c +++ b/drivers/acpi/acpica/exdump.c @@ -508,7 +508,8 @@ acpi_ex_dump_object(union acpi_operand_object *obj_desc, 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 == @@ -520,7 +521,8 @@ acpi_ex_dump_object(union acpi_operand_object *obj_desc, 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 diff --git a/drivers/acpi/acpica/exfield.c b/drivers/acpi/acpica/exfield.c index 61fd9c7..ad7080b 100644 --- a/drivers/acpi/acpica/exfield.c +++ b/drivers/acpi/acpica/exfield.c @@ -167,10 +167,11 @@ acpi_ex_read_data_from_field(struct acpi_walk_state * walk_state, || 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) { @@ -180,17 +181,17 @@ acpi_ex_read_data_from_field(struct acpi_walk_state * walk_state, } 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); @@ -216,6 +217,7 @@ acpi_ex_read_data_from_field(struct acpi_walk_state * walk_state, buffer_desc-> buffer.pointer), function); + acpi_ex_release_global_lock(obj_desc->common_field.field_flags); goto exit; } @@ -232,6 +234,7 @@ acpi_ex_read_data_from_field(struct acpi_walk_state * walk_state, */ 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 */ @@ -273,8 +276,10 @@ acpi_ex_read_data_from_field(struct acpi_walk_state * walk_state, /* 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); @@ -366,19 +371,22 @@ acpi_ex_write_data_to_field(union acpi_operand_object *source_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); @@ -392,17 +400,17 @@ acpi_ex_write_data_to_field(union acpi_operand_object *source_desc, } 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); @@ -414,7 +422,8 @@ acpi_ex_write_data_to_field(union acpi_operand_object *source_desc, 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); @@ -438,8 +447,8 @@ acpi_ex_write_data_to_field(union acpi_operand_object *source_desc, * 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; @@ -460,7 +469,7 @@ acpi_ex_write_data_to_field(union acpi_operand_object *source_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, @@ -476,8 +485,9 @@ acpi_ex_write_data_to_field(union acpi_operand_object *source_desc, /* 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); } diff --git a/drivers/acpi/acpica/exfldio.c b/drivers/acpi/acpica/exfldio.c index 70b7bbb..0337191 100644 --- a/drivers/acpi/acpica/exfldio.c +++ b/drivers/acpi/acpica/exfldio.c @@ -180,7 +180,8 @@ acpi_ex_setup_region(union acpi_operand_object *obj_desc, * 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, @@ -194,7 +195,8 @@ acpi_ex_setup_region(union acpi_operand_object *obj_desc, * 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, @@ -638,15 +640,15 @@ acpi_ex_write_with_update_rule(union acpi_operand_object *obj_desc, 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, @@ -655,8 +657,9 @@ acpi_ex_write_with_update_rule(union acpi_operand_object *obj_desc, /* 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); } @@ -764,8 +767,9 @@ acpi_ex_extract_from_field(union acpi_operand_object *obj_desc, /* 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); } @@ -858,6 +862,7 @@ acpi_ex_insert_into_field(union acpi_operand_object *obj_desc, 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 @@ -932,9 +937,9 @@ acpi_ex_insert_into_field(union acpi_operand_object *obj_desc, /* 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; } @@ -990,9 +995,9 @@ acpi_ex_insert_into_field(union acpi_operand_object *obj_desc, /* 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 */ diff --git a/drivers/acpi/acpica/exmisc.c b/drivers/acpi/acpica/exmisc.c index d02afec..f598b39 100644 --- a/drivers/acpi/acpica/exmisc.c +++ b/drivers/acpi/acpica/exmisc.c @@ -98,9 +98,9 @@ acpi_ex_get_object_reference(union acpi_operand_object *obj_desc, 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; @@ -247,6 +247,7 @@ acpi_ex_do_concatenate(union acpi_operand_object *operand0, 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); @@ -266,9 +267,41 @@ acpi_ex_do_concatenate(union acpi_operand_object *operand0, 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: @@ -347,8 +380,7 @@ acpi_ex_do_concatenate(union acpi_operand_object *operand0, /* 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: @@ -591,8 +623,9 @@ acpi_ex_do_logical_op(u16 opcode, 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: diff --git a/drivers/acpi/acpica/exmutex.c b/drivers/acpi/acpica/exmutex.c index 472030f..843c60a 100644 --- a/drivers/acpi/acpica/exmutex.c +++ b/drivers/acpi/acpica/exmutex.c @@ -185,8 +185,9 @@ acpi_ex_acquire_mutex_object(u16 timeout, 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)) { @@ -243,20 +244,30 @@ acpi_ex_acquire_mutex(union acpi_operand_object *time_desc, } /* - * 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 */ @@ -272,6 +283,12 @@ acpi_ex_acquire_mutex(union acpi_operand_object *time_desc, 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); } @@ -356,9 +373,9 @@ acpi_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); @@ -409,7 +426,8 @@ acpi_ex_release_mutex(union acpi_operand_object *obj_desc, */ 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)); @@ -424,6 +442,15 @@ acpi_ex_release_mutex(union acpi_operand_object *obj_desc, 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); @@ -436,6 +463,14 @@ acpi_ex_release_mutex(union acpi_operand_object *obj_desc, 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); } @@ -462,21 +497,17 @@ void acpi_ex_release_all_mutexes(struct acpi_thread_state *thread) 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 */ @@ -489,14 +520,21 @@ void acpi_ex_release_all_mutexes(struct acpi_thread_state *thread) 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; } diff --git a/drivers/acpi/acpica/exnames.c b/drivers/acpi/acpica/exnames.c index 20e8781..b2e911a 100644 --- a/drivers/acpi/acpica/exnames.c +++ b/drivers/acpi/acpica/exnames.c @@ -164,8 +164,8 @@ static acpi_status acpi_ex_name_segment(u8 ** in_aml_address, char *name_string) 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; diff --git a/drivers/acpi/acpica/exoparg1.c b/drivers/acpi/acpica/exoparg1.c index 7793068..efe7ac3 100644 --- a/drivers/acpi/acpica/exoparg1.c +++ b/drivers/acpi/acpica/exoparg1.c @@ -484,22 +484,26 @@ acpi_status acpi_ex_opcode_1A_1T_1R(struct acpi_walk_state *walk_state) 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; @@ -510,17 +514,20 @@ acpi_status acpi_ex_opcode_1A_1T_1R(struct acpi_walk_state *walk_state) 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; @@ -679,7 +686,7 @@ acpi_status acpi_ex_opcode_1A_0T_1R(struct acpi_walk_state *walk_state) 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 @@ -713,9 +720,9 @@ acpi_status acpi_ex_opcode_1A_0T_1R(struct acpi_walk_state *walk_state) /* 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; } @@ -759,8 +766,10 @@ acpi_status acpi_ex_opcode_1A_0T_1R(struct acpi_walk_state *walk_state) 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; } @@ -981,6 +990,7 @@ acpi_status acpi_ex_opcode_1A_0T_1R(struct acpi_walk_state *walk_state) "Unknown Index TargetType 0x%X in reference object %p", operand[0]->reference. target_type, operand[0])); + status = AE_AML_OPERAND_TYPE; goto cleanup; } @@ -1050,6 +1060,7 @@ acpi_status acpi_ex_opcode_1A_0T_1R(struct acpi_walk_state *walk_state) ACPI_ERROR((AE_INFO, "Unknown AML opcode 0x%X", walk_state->opcode)); + status = AE_AML_BAD_OPCODE; goto cleanup; } diff --git a/drivers/acpi/acpica/exoparg2.c b/drivers/acpi/acpica/exoparg2.c index b8944eb..6dad2ca 100644 --- a/drivers/acpi/acpica/exoparg2.c +++ b/drivers/acpi/acpica/exoparg2.c @@ -199,6 +199,7 @@ acpi_status acpi_ex_opcode_2A_2T_1R(struct acpi_walk_state *walk_state) ACPI_ERROR((AE_INFO, "Unknown AML opcode 0x%X", walk_state->opcode)); + status = AE_AML_BAD_OPCODE; goto cleanup; } @@ -299,8 +300,9 @@ acpi_status acpi_ex_opcode_2A_1T_1R(struct acpi_walk_state *walk_state) 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) */ @@ -345,8 +347,9 @@ acpi_status acpi_ex_opcode_2A_1T_1R(struct acpi_walk_state *walk_state) /* 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) */ @@ -553,6 +556,7 @@ acpi_status acpi_ex_opcode_2A_0T_1R(struct acpi_walk_state *walk_state) ACPI_ERROR((AE_INFO, "Unknown AML opcode 0x%X", walk_state->opcode)); + status = AE_AML_BAD_OPCODE; goto cleanup; } diff --git a/drivers/acpi/acpica/exoparg3.c b/drivers/acpi/acpica/exoparg3.c index fa100b3..27fb017 100644 --- a/drivers/acpi/acpica/exoparg3.c +++ b/drivers/acpi/acpica/exoparg3.c @@ -95,10 +95,11 @@ acpi_status acpi_ex_opcode_3A_0T_0R(struct acpi_walk_state *walk_state) 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) { @@ -131,6 +132,7 @@ acpi_status acpi_ex_opcode_3A_0T_0R(struct acpi_walk_state *walk_state) ACPI_ERROR((AE_INFO, "Unknown AML opcode 0x%X", walk_state->opcode)); + status = AE_AML_BAD_OPCODE; goto cleanup; } @@ -193,7 +195,8 @@ acpi_status acpi_ex_opcode_3A_1T_1R(struct acpi_walk_state *walk_state) /* 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; } @@ -237,8 +240,8 @@ acpi_status acpi_ex_opcode_3A_1T_1R(struct acpi_walk_state *walk_state) /* 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 */ @@ -255,6 +258,7 @@ acpi_status acpi_ex_opcode_3A_1T_1R(struct acpi_walk_state *walk_state) ACPI_ERROR((AE_INFO, "Unknown AML opcode 0x%X", walk_state->opcode)); + status = AE_AML_BAD_OPCODE; goto cleanup; } @@ -270,12 +274,11 @@ 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); } diff --git a/drivers/acpi/acpica/exoparg6.c b/drivers/acpi/acpica/exoparg6.c index c930edd..7efc9f4 100644 --- a/drivers/acpi/acpica/exoparg6.c +++ b/drivers/acpi/acpica/exoparg6.c @@ -310,6 +310,7 @@ acpi_status acpi_ex_opcode_6A_0T_1R(struct acpi_walk_state * walk_state) ACPI_ERROR((AE_INFO, "Unknown AML opcode 0x%X", walk_state->opcode)); + status = AE_AML_BAD_OPCODE; goto cleanup; } diff --git a/drivers/acpi/acpica/exprep.c b/drivers/acpi/acpica/exprep.c index 4c2836d..1f111cc 100644 --- a/drivers/acpi/acpica/exprep.c +++ b/drivers/acpi/acpica/exprep.c @@ -1,6 +1,6 @@ /****************************************************************************** * - * Module Name: exprep - ACPI AML (p-code) execution - field prep utilities + * Module Name: exprep - ACPI AML field prep utilities * *****************************************************************************/ @@ -103,8 +103,10 @@ acpi_ex_generate_access(u32 field_bit_offset, /* 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, @@ -159,7 +161,8 @@ acpi_ex_generate_access(u32 field_bit_offset, 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); } @@ -202,6 +205,7 @@ acpi_ex_generate_access(u32 field_bit_offset, */ ACPI_DEBUG_PRINT((ACPI_DB_BFIELD, "Cannot access field in one operation, using width 8\n")); + return_VALUE(8); } #endif /* ACPI_UNDER_DEVELOPMENT */ @@ -281,6 +285,7 @@ acpi_ex_decode_field_access(union acpi_operand_object *obj_desc, /* Invalid field access type */ ACPI_ERROR((AE_INFO, "Unknown field access type 0x%X", access)); + return_UINT32(0); } @@ -354,8 +359,8 @@ acpi_ex_prep_common_field_object(union acpi_operand_object *obj_desc, * 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); } @@ -595,7 +600,8 @@ acpi_status acpi_ex_prep_field_value(struct acpi_create_field_info *info) 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, @@ -615,8 +621,9 @@ acpi_status acpi_ex_prep_field_value(struct acpi_create_field_info *info) * 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", diff --git a/drivers/acpi/acpica/exregion.c b/drivers/acpi/acpica/exregion.c index b4a5e44..1851a30 100644 --- a/drivers/acpi/acpica/exregion.c +++ b/drivers/acpi/acpica/exregion.c @@ -392,7 +392,8 @@ acpi_ex_pci_config_space_handler(u32 function, 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)); @@ -400,14 +401,16 @@ acpi_ex_pci_config_space_handler(u32 function, 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: diff --git a/drivers/acpi/acpica/exresnte.c b/drivers/acpi/acpica/exresnte.c index 1b372ef..6793dcc 100644 --- a/drivers/acpi/acpica/exresnte.c +++ b/drivers/acpi/acpica/exresnte.c @@ -112,7 +112,7 @@ acpi_ex_resolve_node_to_value(struct acpi_namespace_node **object_ptr, /* * Several object types require no further processing: - * 1) Device/Thermal objects don't have a "real" subobject, return the Node + * 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. */ diff --git a/drivers/acpi/acpica/exresolv.c b/drivers/acpi/acpica/exresolv.c index a1afe1a..7f9260b 100644 --- a/drivers/acpi/acpica/exresolv.c +++ b/drivers/acpi/acpica/exresolv.c @@ -217,7 +217,8 @@ acpi_ex_resolve_object_to_value(union acpi_operand_object **stack_ptr, * 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; } @@ -361,10 +362,9 @@ acpi_ex_resolve_multiple(struct acpi_walk_state *walk_state, 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) { diff --git a/drivers/acpi/acpica/exresop.c b/drivers/acpi/acpica/exresop.c index 424442d..861453e 100644 --- a/drivers/acpi/acpica/exresop.c +++ b/drivers/acpi/acpica/exresop.c @@ -90,8 +90,8 @@ acpi_ex_check_object_type(acpi_object_type type_needed, * 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); } } @@ -196,10 +196,10 @@ acpi_ex_resolve_operands(u16 opcode, * 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)-> @@ -285,8 +285,8 @@ acpi_ex_resolve_operands(u16 opcode, 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 @@ -465,8 +465,9 @@ acpi_ex_resolve_operands(u16 opcode, * 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, @@ -597,8 +598,10 @@ acpi_ex_resolve_operands(u16 opcode, 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: @@ -640,9 +643,9 @@ acpi_ex_resolve_operands(u16 opcode, 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; } @@ -655,7 +658,8 @@ acpi_ex_resolve_operands(u16 opcode, } 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)); @@ -678,9 +682,10 @@ acpi_ex_resolve_operands(u16 opcode, * 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); } diff --git a/drivers/acpi/acpica/exstore.c b/drivers/acpi/acpica/exstore.c index c076e91..d3afbcb 100644 --- a/drivers/acpi/acpica/exstore.c +++ b/drivers/acpi/acpica/exstore.c @@ -467,7 +467,8 @@ acpi_ex_store_object_to_node(union acpi_operand_object *source_desc, 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)); @@ -504,8 +505,9 @@ acpi_ex_store_object_to_node(union acpi_operand_object *source_desc, * 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; } @@ -528,8 +530,9 @@ acpi_ex_store_object_to_node(union acpi_operand_object *source_desc, * 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", @@ -563,8 +566,8 @@ acpi_ex_store_object_to_node(union acpi_operand_object *source_desc, * 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; } diff --git a/drivers/acpi/acpica/exstorob.c b/drivers/acpi/acpica/exstorob.c index e1d4f4d..ad3bc92 100644 --- a/drivers/acpi/acpica/exstorob.c +++ b/drivers/acpi/acpica/exstorob.c @@ -1,6 +1,6 @@ /****************************************************************************** * - * Module Name: exstorob - AML Interpreter object store support, store to object + * Module Name: exstorob - AML object store support, store to object * *****************************************************************************/ @@ -203,8 +203,9 @@ acpi_ex_store_string_to_string(union acpi_operand_object *source_desc, 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); } diff --git a/drivers/acpi/acpica/exsystem.c b/drivers/acpi/acpica/exsystem.c index 0545065..7c91c1f 100644 --- a/drivers/acpi/acpica/exsystem.c +++ b/drivers/acpi/acpica/exsystem.c @@ -78,7 +78,6 @@ acpi_status acpi_ex_system_wait_semaphore(acpi_semaphore semaphore, u16 timeout) /* 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, @@ -124,7 +123,6 @@ acpi_status acpi_ex_system_wait_mutex(acpi_mutex mutex, u16 timeout) /* We must wait, so unlock the interpreter */ acpi_ex_exit_interpreter(); - status = acpi_os_acquire_mutex(mutex, timeout); ACPI_DEBUG_PRINT((ACPI_DB_EXEC, @@ -169,8 +167,8 @@ acpi_status acpi_ex_system_do_stall(u32 how_long) * (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); diff --git a/drivers/acpi/acpica/extrace.c b/drivers/acpi/acpica/extrace.c new file mode 100644 index 0000000..e4a185e --- /dev/null +++ b/drivers/acpi/acpica/extrace.c @@ -0,0 +1,377 @@ +/****************************************************************************** + * + * 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); + } +} diff --git a/drivers/acpi/acpica/exutils.c b/drivers/acpi/acpica/exutils.c index 30c3f46..8ae7634 100644 --- a/drivers/acpi/acpica/exutils.c +++ b/drivers/acpi/acpica/exutils.c @@ -167,8 +167,8 @@ u8 acpi_ex_truncate_for32bit_table(union acpi_operand_object *obj_desc) 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); @@ -323,7 +323,8 @@ void acpi_ex_eisa_id_to_string(char *out_string, u64 compressed_id) 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))); } diff --git a/drivers/acpi/acpica/hwesleep.c b/drivers/acpi/acpica/hwesleep.c index e5599f6..d0319a2 100644 --- a/drivers/acpi/acpica/hwesleep.c +++ b/drivers/acpi/acpica/hwesleep.c @@ -117,8 +117,8 @@ acpi_status acpi_hw_extended_sleep(u8 sleep_state) /* 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); } diff --git a/drivers/acpi/acpica/hwgpe.c b/drivers/acpi/acpica/hwgpe.c index 73cfa59..8272f96 100644 --- a/drivers/acpi/acpica/hwgpe.c +++ b/drivers/acpi/acpica/hwgpe.c @@ -187,9 +187,8 @@ acpi_status acpi_hw_clear_gpe(struct acpi_gpe_event_info * gpe_event_info) */ 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); } @@ -297,6 +296,7 @@ acpi_hw_gpe_enable_write(u8 enable_mask, acpi_status status; gpe_register_info->enable_mask = enable_mask; + status = acpi_hw_write(enable_mask, &gpe_register_info->enable_address); return (status); } diff --git a/drivers/acpi/acpica/hwsleep.c b/drivers/acpi/acpica/hwsleep.c index 7d21cae..ac5b7f7 100644 --- a/drivers/acpi/acpica/hwsleep.c +++ b/drivers/acpi/acpica/hwsleep.c @@ -80,8 +80,8 @@ acpi_status acpi_hw_legacy_sleep(u8 sleep_state) /* 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); } diff --git a/drivers/acpi/acpica/hwxface.c b/drivers/acpi/acpica/hwxface.c index 5f97468..b2e50d8 100644 --- a/drivers/acpi/acpica/hwxface.c +++ b/drivers/acpi/acpica/hwxface.c @@ -504,11 +504,20 @@ acpi_get_sleep_type_data(u8 sleep_state, u8 *sleep_type_a, u8 *sleep_type_b) * 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 */ @@ -517,7 +526,7 @@ acpi_get_sleep_type_data(u8 sleep_state, u8 *sleep_type_a, u8 *sleep_type_b) 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 */ @@ -526,7 +535,7 @@ acpi_get_sleep_type_data(u8 sleep_state, u8 *sleep_type_a, u8 *sleep_type_b) ACPI_ERROR((AE_INFO, "Sleep State return object is not a Package")); status = AE_AML_OPERAND_TYPE; - goto cleanup1; + goto return_value_cleanup; } /* @@ -570,16 +579,17 @@ acpi_get_sleep_type_data(u8 sleep_state, u8 *sleep_type_a, u8 *sleep_type_b) 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); } diff --git a/drivers/acpi/acpica/hwxfsleep.c b/drivers/acpi/acpica/hwxfsleep.c index d62a616..1ce4efa 100644 --- a/drivers/acpi/acpica/hwxfsleep.c +++ b/drivers/acpi/acpica/hwxfsleep.c @@ -52,9 +52,9 @@ ACPI_MODULE_NAME("hwxfsleep") /* 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); @@ -79,22 +79,20 @@ static struct acpi_sleep_functions acpi_sleep_dispatch[] = { /* * 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 * @@ -103,11 +101,11 @@ static struct acpi_sleep_functions acpi_sleep_dispatch[] = { ******************************************************************************/ 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); /* @@ -140,12 +138,12 @@ acpi_hw_set_firmware_waking_vectors(struct acpi_table_facs *facs, /******************************************************************************* * - * 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 * @@ -154,79 +152,23 @@ acpi_hw_set_firmware_waking_vectors(struct acpi_table_facs *facs, ******************************************************************************/ 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 @@ -286,6 +228,7 @@ acpi_status acpi_enter_sleep_state_s4bios(void) if (ACPI_FAILURE(status)) { return_ACPI_STATUS(status); } + } while (!in_value); return_ACPI_STATUS(AE_OK); diff --git a/drivers/acpi/acpica/nsconvert.c b/drivers/acpi/acpica/nsconvert.c index da55a1c..f21568b 100644 --- a/drivers/acpi/acpica/nsconvert.c +++ b/drivers/acpi/acpica/nsconvert.c @@ -96,9 +96,9 @@ acpi_ns_convert_to_integer(union acpi_operand_object *original_object, /* 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; @@ -153,10 +153,9 @@ acpi_ns_convert_to_string(union acpi_operand_object *original_object, 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); } @@ -244,9 +243,8 @@ acpi_ns_convert_to_buffer(union acpi_operand_object *original_object, /* 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); } @@ -308,7 +306,8 @@ acpi_ns_convert_to_buffer(union acpi_operand_object *original_object, * * 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. @@ -318,7 +317,8 @@ acpi_ns_convert_to_buffer(union acpi_operand_object *original_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) { union acpi_operand_object *new_object; @@ -372,7 +372,8 @@ acpi_ns_convert_to_unicode(union acpi_operand_object *original_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 @@ -383,7 +384,8 @@ acpi_ns_convert_to_unicode(union acpi_operand_object *original_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) { union acpi_operand_object *new_object; @@ -444,3 +446,78 @@ acpi_ns_convert_to_resource(union acpi_operand_object *original_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); +} diff --git a/drivers/acpi/acpica/nsdump.c b/drivers/acpi/acpica/nsdump.c index 37aa5c4..bc5ff35 100644 --- a/drivers/acpi/acpica/nsdump.c +++ b/drivers/acpi/acpica/nsdump.c @@ -539,11 +539,13 @@ acpi_ns_dump_one_object(acpi_handle obj_handle, 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); } @@ -573,6 +575,7 @@ acpi_ns_dump_one_object(acpi_handle obj_handle, */ 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); @@ -717,7 +720,7 @@ acpi_ns_dump_one_object_path(acpi_handle obj_handle, 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) { diff --git a/drivers/acpi/acpica/nseval.c b/drivers/acpi/acpica/nseval.c index 7eba578..15e0b2e 100644 --- a/drivers/acpi/acpica/nseval.c +++ b/drivers/acpi/acpica/nseval.c @@ -135,7 +135,7 @@ acpi_status acpi_ns_evaluate(struct acpi_evaluate_info *info) /* 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); } diff --git a/drivers/acpi/acpica/nsinit.c b/drivers/acpi/acpica/nsinit.c index b744a53..ac59929 100644 --- a/drivers/acpi/acpica/nsinit.c +++ b/drivers/acpi/acpica/nsinit.c @@ -582,7 +582,8 @@ acpi_ns_init_one_device(acpi_handle obj_handle, /* 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)); diff --git a/drivers/acpi/acpica/nsload.c b/drivers/acpi/acpica/nsload.c index 14ab836..14c953e 100644 --- a/drivers/acpi/acpica/nsload.c +++ b/drivers/acpi/acpica/nsload.c @@ -149,6 +149,23 @@ unlock: 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); } @@ -321,7 +338,6 @@ acpi_status acpi_ns_unload_namespace(acpi_handle handle) /* This function does the real work */ status = acpi_ns_delete_subtree(handle); - return_ACPI_STATUS(status); } #endif diff --git a/drivers/acpi/acpica/nsnames.c b/drivers/acpi/acpica/nsnames.c index 8934b4e..521031f 100644 --- a/drivers/acpi/acpica/nsnames.c +++ b/drivers/acpi/acpica/nsnames.c @@ -70,7 +70,6 @@ char *acpi_ns_get_external_pathname(struct acpi_namespace_node *node) ACPI_FUNCTION_TRACE_PTR(ns_get_external_pathname, node); name_buffer = acpi_ns_get_normalized_pathname(node, FALSE); - return_PTR(name_buffer); } @@ -93,7 +92,6 @@ acpi_size acpi_ns_get_pathname_length(struct acpi_namespace_node *node) ACPI_FUNCTION_ENTRY(); size = acpi_ns_build_normalized_path(node, NULL, 0, FALSE); - return (size); } @@ -217,6 +215,7 @@ acpi_ns_build_normalized_path(struct acpi_namespace_node *node, ACPI_PATH_PUT8(full_path, path_size, AML_DUAL_NAME_PREFIX, length); } + ACPI_MOVE_32_TO_32(name, &next_node->name); do_no_trailing = no_trailing; for (i = 0; i < 4; i++) { @@ -228,8 +227,10 @@ acpi_ns_build_normalized_path(struct acpi_namespace_node *node, 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 */ @@ -237,6 +238,7 @@ acpi_ns_build_normalized_path(struct acpi_namespace_node *node, if (length <= path_size) { left = full_path; right = full_path + length - 1; + while (left < right) { c = *left; *left++ = *right; diff --git a/drivers/acpi/acpica/nsparse.c b/drivers/acpi/acpica/nsparse.c index 3736d43b..43b45a8 100644 --- a/drivers/acpi/acpica/nsparse.c +++ b/drivers/acpi/acpica/nsparse.c @@ -141,8 +141,8 @@ acpi_ns_one_complete_parse(u32 pass_number, /* 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: @@ -181,6 +181,7 @@ acpi_ns_parse_table(u32 table_index, struct acpi_namespace_node *start_node) * 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)) { diff --git a/drivers/acpi/acpica/nsprepkg.c b/drivers/acpi/acpica/nsprepkg.c index 9bb2519..c05a83b 100644 --- a/drivers/acpi/acpica/nsprepkg.c +++ b/drivers/acpi/acpica/nsprepkg.c @@ -233,8 +233,9 @@ acpi_ns_check_package(struct acpi_evaluate_info *info, /* 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); } @@ -252,8 +253,9 @@ acpi_ns_check_package(struct acpi_evaluate_info *info, /* 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); } diff --git a/drivers/acpi/acpica/nsrepair.c b/drivers/acpi/acpica/nsrepair.c index 77d8103..6418863 100644 --- a/drivers/acpi/acpica/nsrepair.c +++ b/drivers/acpi/acpica/nsrepair.c @@ -116,6 +116,11 @@ static const struct acpi_simple_repair_info acpi_object_repair_info[] = { 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, @@ -172,8 +177,8 @@ acpi_ns_simple_repair(struct acpi_evaluate_info *info, "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 */ @@ -360,12 +365,15 @@ static const struct acpi_simple_repair_info *acpi_ns_match_simple_repair(struct /* 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++; } @@ -521,6 +529,7 @@ acpi_ns_remove_null_elements(struct acpi_evaluate_info *info, *dest = *source; dest++; } + source++; } @@ -572,8 +581,8 @@ acpi_ns_wrap_with_package(struct acpi_evaluate_info *info, 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) { diff --git a/drivers/acpi/acpica/nsrepair2.c b/drivers/acpi/acpica/nsrepair2.c index 0515a70..f6dd2a8 100644 --- a/drivers/acpi/acpica/nsrepair2.c +++ b/drivers/acpi/acpica/nsrepair2.c @@ -225,6 +225,7 @@ static const struct acpi_repair_info *acpi_ns_match_complex_repair(struct if (ACPI_COMPARE_NAME(node->name.ascii, this_name->name)) { return (this_name); } + this_name++; } @@ -301,7 +302,8 @@ acpi_ns_repair_FDE(struct acpi_evaluate_info *info, /* 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, @@ -321,8 +323,8 @@ acpi_ns_repair_FDE(struct acpi_evaluate_info *info, /* 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; @@ -461,7 +463,8 @@ acpi_ns_repair_CST(struct acpi_evaluate_info *info, 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)); @@ -471,7 +474,8 @@ acpi_ns_repair_CST(struct acpi_evaluate_info *info, 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)); @@ -538,8 +542,8 @@ acpi_ns_repair_HID(struct acpi_evaluate_info *info, } 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 */ @@ -710,8 +714,9 @@ acpi_ns_repair_PSS(struct acpi_evaluate_info *info, 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)); @@ -969,6 +974,7 @@ acpi_ns_remove_element(union acpi_operand_object *obj_desc, u32 index) *dest = *source; dest++; } + source++; } diff --git a/drivers/acpi/acpica/nssearch.c b/drivers/acpi/acpica/nssearch.c index d739040..9cc3564d 100644 --- a/drivers/acpi/acpica/nssearch.c +++ b/drivers/acpi/acpica/nssearch.c @@ -105,7 +105,7 @@ acpi_ns_search_one_scope(u32 target_name, 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", diff --git a/drivers/acpi/acpica/nsutils.c b/drivers/acpi/acpica/nsutils.c index de325ae..32f1d95 100644 --- a/drivers/acpi/acpica/nsutils.c +++ b/drivers/acpi/acpica/nsutils.c @@ -173,9 +173,10 @@ void acpi_ns_get_internal_name_length(struct acpi_namestring_info *info) 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 */ @@ -699,6 +700,7 @@ acpi_ns_get_node(struct acpi_namespace_node *prefix_node, if (!prefix_node) { *return_node = acpi_gbl_root_node; } + return_ACPI_STATUS(AE_OK); } diff --git a/drivers/acpi/acpica/nsxfeval.c b/drivers/acpi/acpica/nsxfeval.c index 6ee1e52..429f0d2 100644 --- a/drivers/acpi/acpica/nsxfeval.c +++ b/drivers/acpi/acpica/nsxfeval.c @@ -750,8 +750,8 @@ acpi_ns_get_device_callback(acpi_handle obj_handle, /* 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); } diff --git a/drivers/acpi/acpica/nsxfname.c b/drivers/acpi/acpica/nsxfname.c index 4b4d2f4..669e0f1 100644 --- a/drivers/acpi/acpica/nsxfname.c +++ b/drivers/acpi/acpica/nsxfname.c @@ -159,7 +159,7 @@ acpi_get_name(acpi_handle handle, u32 name_type, struct acpi_buffer * buffer) { acpi_status status; struct acpi_namespace_node *node; - char *node_name; + const char *node_name; /* Parameter validation */ @@ -238,7 +238,6 @@ static char *acpi_ns_copy_device_id(struct acpi_pnp_device_id *dest, struct acpi_pnp_device_id *source, char *string_area) { - /* Create the destination PNP_DEVICE_ID */ dest->string = string_area; @@ -263,11 +262,18 @@ static char *acpi_ns_copy_device_id(struct acpi_pnp_device_id *dest, * 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 @@ -279,7 +285,6 @@ acpi_get_object_info(acpi_handle handle, 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; @@ -325,7 +330,7 @@ acpi_get_object_info(acpi_handle handle, 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 @@ -348,14 +353,6 @@ acpi_get_object_info(acpi_handle handle, 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); @@ -456,9 +453,8 @@ acpi_get_object_info(acpi_handle handle, } /* - * 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. */ @@ -476,11 +472,6 @@ acpi_get_object_info(acpi_handle handle, 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; @@ -522,9 +513,6 @@ cleanup: if (uid) { ACPI_FREE(uid); } - if (sub) { - ACPI_FREE(sub); - } if (cid_list) { ACPI_FREE(cid_list); } @@ -591,6 +579,7 @@ acpi_status acpi_install_method(u8 *buffer) 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); diff --git a/drivers/acpi/acpica/nsxfobj.c b/drivers/acpi/acpica/nsxfobj.c index 7933835..6e1389b 100644 --- a/drivers/acpi/acpica/nsxfobj.c +++ b/drivers/acpi/acpica/nsxfobj.c @@ -74,10 +74,8 @@ acpi_status acpi_get_type(acpi_handle handle, acpi_object_type * ret_type) 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); diff --git a/drivers/acpi/acpica/psargs.c b/drivers/acpi/acpica/psargs.c index 29d8b7b..f3bcfa2 100644 --- a/drivers/acpi/acpica/psargs.c +++ b/drivers/acpi/acpica/psargs.c @@ -269,7 +269,8 @@ acpi_ps_get_next_namepath(struct acpi_walk_state *walk_state, */ if (ACPI_SUCCESS(status) && possible_method_call && (node->type == ACPI_TYPE_METHOD)) { - if (walk_state->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. @@ -696,7 +697,7 @@ static union acpi_parse_object *acpi_ps_get_next_field(struct acpi_parse_state * * 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. @@ -733,6 +734,7 @@ acpi_ps_get_next_arg(struct acpi_walk_state *walk_state, if (!arg) { return_ACPI_STATUS(AE_NO_MEMORY); } + acpi_ps_get_next_simple_arg(parser_state, arg_type, arg); break; @@ -798,6 +800,7 @@ acpi_ps_get_next_arg(struct acpi_walk_state *walk_state, case ARGP_TARGET: case ARGP_SUPERNAME: case ARGP_SIMPLENAME: + case ARGP_NAME_OR_REF: subop = acpi_ps_peek_opcode(parser_state); if (subop == 0 || @@ -814,17 +817,17 @@ acpi_ps_get_next_arg(struct acpi_walk_state *walk_state, 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) { @@ -835,7 +838,7 @@ acpi_ps_get_next_arg(struct acpi_walk_state *walk_state, status = acpi_ps_get_next_namepath(walk_state, parser_state, arg, - 0); + ACPI_NOT_METHOD_CALL); } } else { /* Single complex argument, nothing returned */ diff --git a/drivers/acpi/acpica/psloop.c b/drivers/acpi/acpica/psloop.c index 03ac8c9..a57f473 100644 --- a/drivers/acpi/acpica/psloop.c +++ b/drivers/acpi/acpica/psloop.c @@ -109,10 +109,10 @@ acpi_ps_get_arguments(struct acpi_walk_state *walk_state, 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); } @@ -124,8 +124,8 @@ acpi_ps_get_arguments(struct acpi_walk_state *walk_state, /* * 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 = diff --git a/drivers/acpi/acpica/psopcode.c b/drivers/acpi/acpica/psopcode.c index ed90fdd..40909dd 100644 --- a/drivers/acpi/acpica/psopcode.c +++ b/drivers/acpi/acpica/psopcode.c @@ -185,458 +185,458 @@ const struct acpi_opcode_info acpi_gbl_aml_op_info[AML_NUM_OPCODES] = { /* 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 */ diff --git a/drivers/acpi/acpica/psparse.c b/drivers/acpi/acpica/psparse.c index 98001d7..b729d9b 100644 --- a/drivers/acpi/acpica/psparse.c +++ b/drivers/acpi/acpica/psparse.c @@ -526,8 +526,8 @@ acpi_status acpi_ps_parse_aml(struct acpi_walk_state *walk_state) } /* - * 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; @@ -544,8 +544,8 @@ acpi_status acpi_ps_parse_aml(struct acpi_walk_state *walk_state) /* 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 diff --git a/drivers/acpi/acpica/psutils.c b/drivers/acpi/acpica/psutils.c index 71d2877..6cb02a2 100644 --- a/drivers/acpi/acpica/psutils.c +++ b/drivers/acpi/acpica/psutils.c @@ -175,8 +175,8 @@ void acpi_ps_free_op(union acpi_parse_object *op) 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) { diff --git a/drivers/acpi/acpica/pswalk.c b/drivers/acpi/acpica/pswalk.c index ba5f691..f620d43 100644 --- a/drivers/acpi/acpica/pswalk.c +++ b/drivers/acpi/acpica/pswalk.c @@ -99,6 +99,7 @@ void acpi_ps_delete_parse_tree(union acpi_parse_object *subtree_root) if (op == subtree_root) { return_VOID; } + if (next) { op = next; } else { diff --git a/drivers/acpi/acpica/rsaddr.c b/drivers/acpi/acpica/rsaddr.c index 66d406e..bdb7e73 100644 --- a/drivers/acpi/acpica/rsaddr.c +++ b/drivers/acpi/acpica/rsaddr.c @@ -312,8 +312,8 @@ acpi_rs_get_address_common(struct acpi_resource *resource, /* 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); } diff --git a/drivers/acpi/acpica/rscalc.c b/drivers/acpi/acpica/rscalc.c index cb739a6..88fce58 100644 --- a/drivers/acpi/acpica/rscalc.c +++ b/drivers/acpi/acpica/rscalc.c @@ -143,16 +143,17 @@ acpi_rs_stream_option_length(u32 resource_length, 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) { @@ -277,11 +278,11 @@ acpi_rs_get_aml_length(struct acpi_resource *resource, * 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: @@ -289,11 +290,11 @@ acpi_rs_get_aml_length(struct acpi_resource *resource, * 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: @@ -301,11 +302,11 @@ acpi_rs_get_aml_length(struct acpi_resource *resource, * 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: @@ -314,26 +315,28 @@ acpi_rs_get_aml_length(struct acpi_resource *resource, * 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; @@ -566,8 +569,8 @@ acpi_rs_get_list_length(u8 * aml_buffer, 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, diff --git a/drivers/acpi/acpica/rscreate.c b/drivers/acpi/acpica/rscreate.c index a534442..603e544 100644 --- a/drivers/acpi/acpica/rscreate.c +++ b/drivers/acpi/acpica/rscreate.c @@ -81,8 +81,9 @@ acpi_buffer_to_resource(u8 *aml_buffer, /* 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; } @@ -232,8 +233,9 @@ acpi_rs_create_pci_routing_table(union acpi_operand_object *package_object, /* 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); } @@ -270,9 +272,9 @@ acpi_rs_create_pci_routing_table(union acpi_operand_object *package_object, 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); @@ -345,11 +347,7 @@ acpi_rs_create_pci_routing_table(union acpi_operand_object *package_object, (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 */ @@ -371,8 +369,8 @@ acpi_rs_create_pci_routing_table(union acpi_operand_object *package_object, 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 */ @@ -451,9 +449,9 @@ acpi_rs_create_aml_resources(struct acpi_buffer *resource_list, /* 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))); diff --git a/drivers/acpi/acpica/rsdump.c b/drivers/acpi/acpica/rsdump.c index 2a09288..05cc560 100644 --- a/drivers/acpi/acpica/rsdump.c +++ b/drivers/acpi/acpica/rsdump.c @@ -483,6 +483,7 @@ static void acpi_rs_dump_address_common(union acpi_resource_data *resource) static void acpi_rs_out_string(char *title, char *value) { + acpi_os_printf("%27s : %s", title, value); if (!*value) { acpi_os_printf("[NULL NAMESTRING]"); @@ -497,21 +498,25 @@ static void acpi_rs_out_integer8(char *title, u8 value) 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); } @@ -544,6 +549,7 @@ static void acpi_rs_dump_short_byte_list(u8 length, u8 * data) for (i = 0; i < length; i++) { acpi_os_printf("%X ", data[i]); } + acpi_os_printf("\n"); } diff --git a/drivers/acpi/acpica/rslist.c b/drivers/acpi/acpica/rslist.c index 50d5be2..286ccb461 100644 --- a/drivers/acpi/acpica/rslist.c +++ b/drivers/acpi/acpica/rslist.c @@ -89,6 +89,7 @@ acpi_rs_convert_aml_to_resources(u8 * aml, /* 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) { @@ -225,10 +226,10 @@ acpi_rs_convert_resources_to_aml(struct acpi_resource *resource, /* 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); } diff --git a/drivers/acpi/acpica/rsmisc.c b/drivers/acpi/acpica/rsmisc.c index ac37852..b112c7b 100644 --- a/drivers/acpi/acpica/rsmisc.c +++ b/drivers/acpi/acpica/rsmisc.c @@ -189,8 +189,8 @@ acpi_rs_convert_aml_to_resource(struct acpi_resource *resource, 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: @@ -445,8 +445,8 @@ exit: /* 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); } @@ -550,9 +550,8 @@ acpi_rs_convert_resource_to_aml(struct acpi_resource *resource, 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: @@ -723,11 +722,10 @@ acpi_rs_convert_resource_to_aml(struct acpi_resource *resource, /* * 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; diff --git a/drivers/acpi/acpica/rsutils.c b/drivers/acpi/acpica/rsutils.c index 9486992..33e558c 100644 --- a/drivers/acpi/acpica/rsutils.c +++ b/drivers/acpi/acpica/rsutils.c @@ -221,14 +221,13 @@ acpi_rs_set_resource_length(acpi_rsdesc_size total_length, 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); } } @@ -333,8 +332,8 @@ acpi_rs_get_resource_source(acpi_rs_length 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. @@ -366,6 +365,7 @@ acpi_rs_get_resource_source(acpi_rs_length resource_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); @@ -438,8 +438,8 @@ acpi_rs_set_resource_source(union aml_resource * aml, * 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 */ @@ -478,8 +478,9 @@ acpi_rs_get_prt_method_data(struct acpi_namespace_node * node, /* 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); } @@ -527,8 +528,9 @@ acpi_rs_get_crs_method_data(struct acpi_namespace_node *node, /* 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); } @@ -577,8 +579,9 @@ acpi_rs_get_prs_method_data(struct acpi_namespace_node *node, /* 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); } @@ -627,8 +630,9 @@ acpi_rs_get_aei_method_data(struct acpi_namespace_node *node, /* 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); } diff --git a/drivers/acpi/acpica/rsxface.c b/drivers/acpi/acpica/rsxface.c index 1e8cd57..308bfd6 100644 --- a/drivers/acpi/acpica/rsxface.c +++ b/drivers/acpi/acpica/rsxface.c @@ -53,7 +53,7 @@ ACPI_MODULE_NAME("rsxface") /* 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); \ diff --git a/drivers/acpi/acpica/tbdata.c b/drivers/acpi/acpica/tbdata.c index 5c9d5ab..4a81527 100644 --- a/drivers/acpi/acpica/tbdata.c +++ b/drivers/acpi/acpica/tbdata.c @@ -407,6 +407,7 @@ acpi_tb_verify_temp_table(struct acpi_table_desc * table_desc, char *signature) table_desc->signature.ascii : "????", ACPI_FORMAT_UINT64(table_desc-> address))); + goto invalidate_and_exit; } } diff --git a/drivers/acpi/acpica/tbinstal.c b/drivers/acpi/acpica/tbinstal.c index 6319b42..bd87801 100644 --- a/drivers/acpi/acpica/tbinstal.c +++ b/drivers/acpi/acpica/tbinstal.c @@ -337,8 +337,8 @@ acpi_tb_install_standard_table(acpi_physical_address address, * 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 */ diff --git a/drivers/acpi/acpica/tbprint.c b/drivers/acpi/acpica/tbprint.c index 709d511..d0d1259 100644 --- a/drivers/acpi/acpica/tbprint.c +++ b/drivers/acpi/acpica/tbprint.c @@ -76,6 +76,7 @@ static void acpi_tb_fix_string(char *string, acpi_size length) if (!isprint((int)*string)) { *string = '?'; } + string++; length--; } diff --git a/drivers/acpi/acpica/tbutils.c b/drivers/acpi/acpica/tbutils.c index d8ddef3..7c1b5f8 100644 --- a/drivers/acpi/acpica/tbutils.c +++ b/drivers/acpi/acpica/tbutils.c @@ -121,6 +121,7 @@ void acpi_tb_check_dsdt_header(void) 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); @@ -379,7 +380,6 @@ next_table: } acpi_os_unmap_memory(table, length); - return_ACPI_STATUS(AE_OK); } @@ -389,7 +389,7 @@ next_table: * * 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. * @@ -399,12 +399,6 @@ u8 acpi_is_valid_signature(char *signature) { u32 i; - /* Validate the signature length */ - - if (strlen(signature) != ACPI_NAME_SIZE) { - return (FALSE); - } - /* Validate each character in the signature */ for (i = 0; i < ACPI_NAME_SIZE; i++) { diff --git a/drivers/acpi/acpica/tbxfload.c b/drivers/acpi/acpica/tbxfload.c index 55ee14c..ca2f136 100644 --- a/drivers/acpi/acpica/tbxfload.c +++ b/drivers/acpi/acpica/tbxfload.c @@ -191,6 +191,7 @@ acpi_status acpi_tb_load_namespace(void) "(%4.4s:%8.8s) while loading table", table->signature.ascii, table->pointer->oem_table_id)); + tables_failed++; ACPI_DEBUG_PRINT_RAW((ACPI_DB_INIT, @@ -206,7 +207,7 @@ acpi_status acpi_tb_load_namespace(void) 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, diff --git a/drivers/acpi/acpica/utaddress.c b/drivers/acpi/acpica/utaddress.c index 911ea8e..38a29e2 100644 --- a/drivers/acpi/acpica/utaddress.c +++ b/drivers/acpi/acpica/utaddress.c @@ -239,8 +239,9 @@ acpi_ut_check_address_range(acpi_adr_space_type space_id, 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)", diff --git a/drivers/acpi/acpica/utcopy.c b/drivers/acpi/acpica/utcopy.c index 257221d..ade8acf 100644 --- a/drivers/acpi/acpica/utcopy.c +++ b/drivers/acpi/acpica/utcopy.c @@ -257,9 +257,9 @@ acpi_ut_copy_ielement_to_eelement(u8 object_type, 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: @@ -348,15 +348,15 @@ acpi_ut_copy_ipackage_to_epackage(union acpi_operand_object *internal_object, * 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 @@ -593,8 +593,8 @@ acpi_ut_copy_epackage_to_ipackage(union acpi_object *external_object, 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 = @@ -649,9 +649,8 @@ acpi_ut_copy_eobject_to_iobject(union acpi_object *external_object, /* * 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); diff --git a/drivers/acpi/acpica/utdecode.c b/drivers/acpi/acpica/utdecode.c index ecaaaff..3533135 100644 --- a/drivers/acpi/acpica/utdecode.c +++ b/drivers/acpi/acpica/utdecode.c @@ -114,7 +114,7 @@ const char *acpi_gbl_region_types[ACPI_NUM_PREDEFINED_REGIONS] = { "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) { @@ -127,7 +127,7 @@ char *acpi_ut_get_region_name(u8 space_id) return ("InvalidSpaceId"); } - return (ACPI_CAST_PTR(char, acpi_gbl_region_types[space_id])); + return (acpi_gbl_region_types[space_id]); } /******************************************************************************* @@ -152,14 +152,14 @@ static const char *acpi_gbl_event_types[ACPI_NUM_FIXED_EVENTS] = { "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]); } /******************************************************************************* @@ -180,7 +180,8 @@ char *acpi_ut_get_event_name(u32 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"; @@ -220,17 +221,17 @@ static const char *acpi_gbl_ns_type_names[] = { /* 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); @@ -267,7 +268,7 @@ char *acpi_ut_get_object_type_name(union acpi_operand_object *obj_desc) * ******************************************************************************/ -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; @@ -333,7 +334,7 @@ static const char *acpi_gbl_desc_type_names[] = { /* 15 */ "Node" }; -char *acpi_ut_get_descriptor_name(void *object) +const char *acpi_ut_get_descriptor_name(void *object) { if (!object) { @@ -344,10 +345,7 @@ char *acpi_ut_get_descriptor_name(void *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)]); } /******************************************************************************* @@ -415,7 +413,7 @@ const char *acpi_ut_get_reference_name(union acpi_operand_object *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", @@ -424,7 +422,7 @@ static char *acpi_gbl_mutex_names[ACPI_NUM_MUTEX] = { "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) { diff --git a/drivers/acpi/acpica/utdelete.c b/drivers/acpi/acpica/utdelete.c index 1638312..1afd742 100644 --- a/drivers/acpi/acpica/utdelete.c +++ b/drivers/acpi/acpica/utdelete.c @@ -209,6 +209,7 @@ static void acpi_ut_delete_internal_obj(union acpi_operand_object *object) acpi_ut_delete_object_desc(object->method.mutex); object->method.mutex = NULL; } + if (object->method.node) { object->method.node = NULL; } @@ -515,8 +516,8 @@ acpi_ut_update_object_reference(union acpi_operand_object *object, u16 action) } /* - * 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: diff --git a/drivers/acpi/acpica/uterror.c b/drivers/acpi/acpica/uterror.c index 9ef80f2..f93bb90 100644 --- a/drivers/acpi/acpica/uterror.c +++ b/drivers/acpi/acpica/uterror.c @@ -217,8 +217,9 @@ acpi_ut_namespace_error(const char *module_name, } 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 */ @@ -271,9 +272,8 @@ acpi_ut_method_error(const char *module_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]"); } diff --git a/drivers/acpi/acpica/utfileio.c b/drivers/acpi/acpica/utfileio.c deleted file mode 100644 index d435b7b..0000000 --- a/drivers/acpi/acpica/utfileio.c +++ /dev/null @@ -1,334 +0,0 @@ -/******************************************************************************* - * - * 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 diff --git a/drivers/acpi/acpica/uthex.c b/drivers/acpi/acpica/uthex.c index fda8b3d..8ad086e 100644 --- a/drivers/acpi/acpica/uthex.c +++ b/drivers/acpi/acpica/uthex.c @@ -48,7 +48,7 @@ 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' }; diff --git a/drivers/acpi/acpica/utids.c b/drivers/acpi/acpica/utids.c index 7956df1e..05ee76e 100644 --- a/drivers/acpi/acpica/utids.c +++ b/drivers/acpi/acpica/utids.c @@ -127,73 +127,6 @@ cleanup: /******************************************************************************* * - * 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 * * PARAMETERS: device_node - Node for the device diff --git a/drivers/acpi/acpica/utinit.c b/drivers/acpi/acpica/utinit.c index ccd0745..fd82a12 100644 --- a/drivers/acpi/acpica/utinit.c +++ b/drivers/acpi/acpica/utinit.c @@ -206,7 +206,6 @@ acpi_status acpi_ut_init_globals(void) 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 */ diff --git a/drivers/acpi/acpica/utmath.c b/drivers/acpi/acpica/utmath.c index f9ff100..58b5d42 100644 --- a/drivers/acpi/acpica/utmath.c +++ b/drivers/acpi/acpica/utmath.c @@ -111,6 +111,7 @@ acpi_ut_short_divide(u64 dividend, */ 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); @@ -179,6 +180,7 @@ acpi_ut_divide(u64 in_dividend, */ 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); } @@ -206,12 +208,12 @@ acpi_ut_divide(u64 in_dividend, 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; diff --git a/drivers/acpi/acpica/utmisc.c b/drivers/acpi/acpica/utmisc.c index bd4443b..eab1cfe 100644 --- a/drivers/acpi/acpica/utmisc.c +++ b/drivers/acpi/acpica/utmisc.c @@ -264,8 +264,8 @@ acpi_ut_walk_package_tree(union acpi_operand_object *source_object, */ 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); @@ -318,9 +318,10 @@ acpi_ut_walk_package_tree(union acpi_operand_object *source_object, * 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 */ diff --git a/drivers/acpi/acpica/utmutex.c b/drivers/acpi/acpica/utmutex.c index ce406e3..038ff84 100644 --- a/drivers/acpi/acpica/utmutex.c +++ b/drivers/acpi/acpica/utmutex.c @@ -111,17 +111,6 @@ acpi_status acpi_ut_mutex_initialize(void) 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); } @@ -162,12 +151,6 @@ void acpi_ut_mutex_terminate(void) /* 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; } @@ -290,8 +273,9 @@ acpi_status acpi_ut_acquire_mutex(acpi_mutex_handle mutex_id) (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", diff --git a/drivers/acpi/acpica/utnonansi.c b/drivers/acpi/acpica/utnonansi.c index 1d5f6b1..9c3cadc 100644 --- a/drivers/acpi/acpica/utnonansi.c +++ b/drivers/acpi/acpica/utnonansi.c @@ -282,8 +282,8 @@ acpi_status acpi_ut_strtoul64(char *string, u32 base, u64 *ret_integer) /* 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) { diff --git a/drivers/acpi/acpica/utobject.c b/drivers/acpi/acpica/utobject.c index 7d83efe..787eccf 100644 --- a/drivers/acpi/acpica/utobject.c +++ b/drivers/acpi/acpica/utobject.c @@ -112,9 +112,9 @@ union acpi_operand_object *acpi_ut_create_internal_object_dbg(const char /* 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); @@ -253,7 +253,8 @@ union acpi_operand_object *acpi_ut_create_buffer_object(acpi_size buffer_size) 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); } @@ -305,7 +306,8 @@ union acpi_operand_object *acpi_ut_create_string_object(acpi_size string_size) 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); } @@ -649,8 +651,9 @@ acpi_ut_get_package_object_size(union acpi_operand_object *internal_object, 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); } @@ -660,7 +663,8 @@ acpi_ut_get_package_object_size(union acpi_operand_object *internal_object, * 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 */ @@ -692,8 +696,8 @@ acpi_ut_get_object_size(union acpi_operand_object *internal_object, 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); diff --git a/drivers/acpi/acpica/utosi.c b/drivers/acpi/acpica/utosi.c index 8f3d203a..0809d73 100644 --- a/drivers/acpi/acpica/utosi.c +++ b/drivers/acpi/acpica/utosi.c @@ -269,9 +269,10 @@ acpi_status acpi_ut_remove_interface(acpi_string interface_name) 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 */ @@ -288,8 +289,8 @@ acpi_status acpi_ut_remove_interface(acpi_string interface_name) 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); diff --git a/drivers/acpi/acpica/utownerid.c b/drivers/acpi/acpica/utownerid.c index 2959217..ebb811c 100644 --- a/drivers/acpi/acpica/utownerid.c +++ b/drivers/acpi/acpica/utownerid.c @@ -73,8 +73,8 @@ acpi_status acpi_ut_allocate_owner_id(acpi_owner_id * owner_id) /* 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); } @@ -87,8 +87,8 @@ acpi_status acpi_ut_allocate_owner_id(acpi_owner_id * owner_id) /* * 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++) { @@ -141,8 +141,8 @@ acpi_status acpi_ut_allocate_owner_id(acpi_owner_id * owner_id) * 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, diff --git a/drivers/acpi/acpica/utpredef.c b/drivers/acpi/acpica/utpredef.c index 97898ed..9f8e415 100644 --- a/drivers/acpi/acpica/utpredef.c +++ b/drivers/acpi/acpica/utpredef.c @@ -225,8 +225,10 @@ const union acpi_predefined_info *acpi_ut_match_resource_name(char *name) { 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); } diff --git a/drivers/acpi/acpica/utprint.c b/drivers/acpi/acpica/utprint.c index b26297c..01f04da 100644 --- a/drivers/acpi/acpica/utprint.c +++ b/drivers/acpi/acpica/utprint.c @@ -314,8 +314,9 @@ static char *acpi_ut_format_number(char *string, 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)) { @@ -400,6 +401,7 @@ acpi_ut_vsnprintf(char *string, } else { break; } + } while (1); /* Process width */ @@ -429,6 +431,7 @@ acpi_ut_vsnprintf(char *string, ++format; precision = va_arg(args, int); } + if (precision < 0) { precision = 0; } @@ -488,10 +491,12 @@ acpi_ut_vsnprintf(char *string, ' '); } } + 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, ' '); @@ -529,9 +534,9 @@ acpi_ut_vsnprintf(char *string, } 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: diff --git a/drivers/acpi/acpica/utresrc.c b/drivers/acpi/acpica/utresrc.c index b3505db..d50b41c 100644 --- a/drivers/acpi/acpica/utresrc.c +++ b/drivers/acpi/acpica/utresrc.c @@ -441,8 +441,8 @@ acpi_ut_walk_aml_resources(struct acpi_walk_state *walk_state, 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); } @@ -568,8 +568,8 @@ acpi_ut_validate_resource(struct acpi_walk_state *walk_state, } /* - * 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; diff --git a/drivers/acpi/acpica/utstate.c b/drivers/acpi/acpica/utstate.c index f201171..0050e00 100644 --- a/drivers/acpi/acpica/utstate.c +++ b/drivers/acpi/acpica/utstate.c @@ -246,6 +246,7 @@ union acpi_generic_state *acpi_ut_create_pkg_state(void *internal_object, state->pkg.dest_object = external_object; state->pkg.index = index; state->pkg.num_packages = 1; + return (state); } @@ -279,6 +280,7 @@ union acpi_generic_state *acpi_ut_create_control_state(void) state->common.descriptor_type = ACPI_DESC_TYPE_STATE_CONTROL; state->common.state = ACPI_CONTROL_CONDITIONAL_EXECUTING; + return (state); } @@ -304,5 +306,6 @@ void acpi_ut_delete_generic_state(union acpi_generic_state *state) if (state) { (void)acpi_os_release_object(acpi_gbl_state_cache, state); } + return; } diff --git a/drivers/acpi/acpica/utstring.c b/drivers/acpi/acpica/utstring.c index 4ddd105..958b2f7 100644 --- a/drivers/acpi/acpica/utstring.c +++ b/drivers/acpi/acpica/utstring.c @@ -135,6 +135,7 @@ void acpi_ut_print_string(char *string, u16 max_length) break; } } + acpi_os_printf("\""); if (i == max_length && string[i]) { @@ -239,6 +240,14 @@ void acpi_ut_repair_name(char *name) 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 */ diff --git a/drivers/acpi/acpica/uttrack.c b/drivers/acpi/acpica/uttrack.c index 9a7dc81..ea698e9 100644 --- a/drivers/acpi/acpica/uttrack.c +++ b/drivers/acpi/acpica/uttrack.c @@ -150,9 +150,9 @@ void *acpi_ut_allocate_and_track(acpi_size size, 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); @@ -161,6 +161,7 @@ void *acpi_ut_allocate_and_track(acpi_size size, 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 = @@ -223,6 +224,7 @@ void *acpi_ut_allocate_zeroed_and_track(acpi_size size, 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 = @@ -269,8 +271,8 @@ acpi_ut_free_and_track(void *allocation, 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")); } @@ -525,35 +527,35 @@ void acpi_ut_dump_allocation_info(void) /* 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; } diff --git a/drivers/acpi/acpica/utxface.c b/drivers/acpi/acpica/utxface.c index f9c8f9c..9f3f0a1 100644 --- a/drivers/acpi/acpica/utxface.c +++ b/drivers/acpi/acpica/utxface.c @@ -154,7 +154,6 @@ acpi_status acpi_get_system_info(struct acpi_buffer * out_buffer) * 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) */ @@ -216,7 +215,6 @@ acpi_status acpi_get_statistics(struct acpi_statistics *stats) /* Other counters */ stats->method_count = acpi_method_count; - return_ACPI_STATUS(AE_OK); } diff --git a/drivers/acpi/acpica/utxferror.c b/drivers/acpi/acpica/utxferror.c index 98d5787..f6cbaf4 100644 --- a/drivers/acpi/acpica/utxferror.c +++ b/drivers/acpi/acpica/utxferror.c @@ -117,6 +117,7 @@ acpi_exception(const char *module_name, 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; diff --git a/drivers/acpi/acpica/utxfinit.c b/drivers/acpi/acpica/utxfinit.c index a7137ec..e38facd 100644 --- a/drivers/acpi/acpica/utxfinit.c +++ b/drivers/acpi/acpica/utxfinit.c @@ -147,6 +147,28 @@ acpi_status __init acpi_enable_subsystem(u32 flags) 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 */ @@ -175,23 +197,7 @@ acpi_status __init acpi_enable_subsystem(u32 flags) 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) * @@ -261,6 +267,7 @@ acpi_status __init acpi_initialize_objects(u32 flags) * 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")); @@ -285,8 +292,14 @@ acpi_status __init acpi_initialize_objects(u32 flags) * 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 diff --git a/drivers/acpi/acpica/utxfmutex.c b/drivers/acpi/acpica/utxfmutex.c index f2606af..95d6123 100644 --- a/drivers/acpi/acpica/utxfmutex.c +++ b/drivers/acpi/acpica/utxfmutex.c @@ -89,9 +89,9 @@ acpi_ut_get_mutex_object(acpi_handle handle, 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); } diff --git a/drivers/acpi/bus.c b/drivers/acpi/bus.c index a212cef..891c42d 100644 --- a/drivers/acpi/bus.c +++ b/drivers/acpi/bus.c @@ -180,14 +180,15 @@ static void acpi_print_osc_error(acpi_handle handle, 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"); } @@ -1094,6 +1095,7 @@ static int __init acpi_init(void) acpi_debugfs_init(); acpi_sleep_proc_init(); acpi_wakeup_device_init(); + acpi_debugger_init(); return 0; } diff --git a/drivers/acpi/gsi.c b/drivers/acpi/gsi.c index fa4585a..ee9e0f2 100644 --- a/drivers/acpi/gsi.c +++ b/drivers/acpi/gsi.c @@ -17,25 +17,6 @@ enum acpi_irq_model_id acpi_irq_model; 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 @@ -82,7 +63,7 @@ int acpi_register_gsi(struct device *dev, u32 gsi, int trigger, 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); diff --git a/drivers/acpi/internal.h b/drivers/acpi/internal.h index 11d87bf..1e6833a 100644 --- a/drivers/acpi/internal.h +++ b/drivers/acpi/internal.h @@ -86,6 +86,14 @@ bool acpi_scan_is_offline(struct acpi_device *adev, bool uevent); #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, diff --git a/drivers/acpi/osl.c b/drivers/acpi/osl.c index 32d684a..67da6fb 100644 --- a/drivers/acpi/osl.c +++ b/drivers/acpi/osl.c @@ -220,6 +220,7 @@ void acpi_os_printf(const char *fmt, ...) acpi_os_vprintf(fmt, args); va_end(args); } +EXPORT_SYMBOL(acpi_os_printf); void acpi_os_vprintf(const char *fmt, va_list args) { @@ -234,7 +235,8 @@ 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 } @@ -364,6 +366,19 @@ static void acpi_unmap(acpi_physical_address pg_off, void __iomem *vaddr) 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) { @@ -439,6 +454,20 @@ static void acpi_os_map_cleanup(struct acpi_ioremap *map) } } +/** + * 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; @@ -1101,6 +1130,200 @@ static void acpi_os_execute_deferred(struct work_struct *work) 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 @@ -1127,6 +1350,15 @@ acpi_status acpi_os_execute(acpi_execute_type type, "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 @@ -1151,11 +1383,17 @@ acpi_status acpi_os_execute(acpi_execute_type type, 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 @@ -1164,13 +1402,15 @@ acpi_status acpi_os_execute(acpi_execute_type type, * 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); @@ -1358,10 +1598,39 @@ acpi_status acpi_os_get_line(char *buffer, u32 buffer_length, u32 *bytes_read) 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) { diff --git a/drivers/acpi/pci_irq.c b/drivers/acpi/pci_irq.c index c933675..d30184c 100644 --- a/drivers/acpi/pci_irq.c +++ b/drivers/acpi/pci_irq.c @@ -131,9 +131,6 @@ static void do_prt_fixups(struct acpi_prt_entry *entry, 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 && diff --git a/drivers/acpi/pci_link.c b/drivers/acpi/pci_link.c index 7c8408b..fa28635 100644 --- a/drivers/acpi/pci_link.c +++ b/drivers/acpi/pci_link.c @@ -4,6 +4,7 @@ * 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. * * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ * @@ -67,12 +68,12 @@ static struct acpi_scan_handler pci_link_handler = { * 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; }; @@ -437,7 +438,6 @@ static int acpi_pci_link_set(struct acpi_pci_link *link, int irq) * enabled system. */ -#define ACPI_MAX_IRQS 256 #define ACPI_MAX_ISA_IRQ 16 #define PIRQ_PENALTY_PCI_AVAILABLE (0) @@ -447,7 +447,7 @@ static int acpi_pci_link_set(struct acpi_pci_link *link, int irq) #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 */ @@ -464,9 +464,68 @@ static int acpi_irq_penalty[ACPI_MAX_IRQS] = { 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; @@ -487,15 +546,16 @@ int __init acpi_irq_penalty_init(void) 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); } } @@ -547,12 +607,12 @@ static int acpi_pci_link_allocate(struct acpi_pci_link *link) * 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), @@ -568,7 +628,8 @@ static int acpi_pci_link_allocate(struct acpi_pci_link *link) 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); @@ -778,7 +839,7 @@ static void acpi_pci_link_remove(struct acpi_device *device) } /* - * modify acpi_irq_penalty[] from cmdline + * modify penalty from cmdline */ static int __init acpi_irq_penalty_update(char *str, int used) { @@ -796,13 +857,10 @@ 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; @@ -819,18 +877,15 @@ static int __init acpi_irq_penalty_update(char *str, int used) */ 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); } /* @@ -840,13 +895,18 @@ bool acpi_isa_irq_available(int irq) */ 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); } /* diff --git a/drivers/acpi/property.c b/drivers/acpi/property.c index 88f4306..2aee416 100644 --- a/drivers/acpi/property.c +++ b/drivers/acpi/property.c @@ -346,7 +346,7 @@ void acpi_free_properties(struct acpi_device *adev) * * 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, @@ -360,7 +360,7 @@ 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++) { @@ -375,13 +375,13 @@ static int acpi_data_get_property(struct acpi_device_data *data, 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; } /** @@ -439,7 +439,7 @@ int acpi_node_prop_get(struct fwnode_handle *fwnode, const char *propname, * * 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. */ diff --git a/drivers/acpi/resource.c b/drivers/acpi/resource.c index cdc5c25..d02fd53 100644 --- a/drivers/acpi/resource.c +++ b/drivers/acpi/resource.c @@ -23,6 +23,7 @@ #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)) @@ -336,6 +337,31 @@ unsigned long acpi_dev_irq_flags(u8 triggering, u8 polarity, u8 shareable) } 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; diff --git a/drivers/acpi/sbs.c b/drivers/acpi/sbs.c index cb3dedb..ad0b13a 100644 --- a/drivers/acpi/sbs.c +++ b/drivers/acpi/sbs.c @@ -417,11 +417,11 @@ static int acpi_battery_set_alarm(struct acpi_battery *battery) 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, diff --git a/drivers/acpi/scan.c b/drivers/acpi/scan.c index 78d5f02..407a376 100644 --- a/drivers/acpi/scan.c +++ b/drivers/acpi/scan.c @@ -39,7 +39,7 @@ static const char *dummy_hid = "device"; 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); @@ -52,12 +52,6 @@ struct acpi_dep_data { 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); @@ -471,10 +465,24 @@ static void acpi_device_release(struct device *dev) 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); @@ -1461,7 +1469,7 @@ static int acpi_bus_type_and_status(acpi_handle handle, int *type, *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; diff --git a/drivers/acpi/sleep.c b/drivers/acpi/sleep.c index 0d94621..9cb9752 100644 --- a/drivers/acpi/sleep.c +++ b/drivers/acpi/sleep.c @@ -61,7 +61,7 @@ static int acpi_sleep_prepare(u32 acpi_state) 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(); @@ -410,7 +410,7 @@ static void acpi_pm_finish(void) 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; diff --git a/drivers/acpi/sleep.h b/drivers/acpi/sleep.h index c797ffa..a9cc34e 100644 --- a/drivers/acpi/sleep.h +++ b/drivers/acpi/sleep.h @@ -6,3 +6,9 @@ extern struct list_head acpi_wakeup_device_list; 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); +} diff --git a/drivers/acpi/utils.c b/drivers/acpi/utils.c index 475c907..f2f9873 100644 --- a/drivers/acpi/utils.c +++ b/drivers/acpi/utils.c @@ -29,6 +29,7 @@ #include <linux/dynamic_debug.h> #include "internal.h" +#include "sleep.h" #define _COMPONENT ACPI_BUS_COMPONENT ACPI_MODULE_NAME("utils"); @@ -709,6 +710,36 @@ bool acpi_check_dsm(acpi_handle handle, const u8 *uuid, int rev, u64 funcs) } 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. diff --git a/drivers/acpi/video_detect.c b/drivers/acpi/video_detect.c index daaf1c4..90e2d54 100644 --- a/drivers/acpi/video_detect.c +++ b/drivers/acpi/video_detect.c @@ -250,6 +250,15 @@ static const struct dmi_system_id video_detect_dmi_table[] = { 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 */ { @@ -279,6 +288,14 @@ static const struct dmi_system_id video_detect_dmi_table[] = { 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"), + }, + }, { }, }; diff --git a/drivers/base/base.h b/drivers/base/base.h index 1782f3a..e05db38 100644 --- a/drivers/base/base.h +++ b/drivers/base/base.h @@ -131,6 +131,8 @@ extern void device_remove_groups(struct device *dev, 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; diff --git a/drivers/base/core.c b/drivers/base/core.c index b7d56c5..0a8bdad 100644 --- a/drivers/base/core.c +++ b/drivers/base/core.c @@ -2261,7 +2261,10 @@ void set_primary_fwnode(struct device *dev, struct fwnode_handle *fwnode) 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) ? diff --git a/drivers/base/dd.c b/drivers/base/dd.c index a641cf3..7399be7 100644 --- a/drivers/base/dd.c +++ b/drivers/base/dd.c @@ -55,6 +55,13 @@ 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. */ static void deferred_probe_work_func(struct work_struct *work) @@ -172,6 +179,30 @@ static void driver_deferred_probe_trigger(void) } /** + * 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 * * We don't want to get in the way when the bulk of drivers are getting probed. @@ -268,6 +299,9 @@ int device_bind_driver(struct device *dev) 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); @@ -277,9 +311,20 @@ static DECLARE_WAIT_QUEUE_HEAD(probe_waitqueue); 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)); @@ -290,7 +335,7 @@ static int really_probe(struct device *dev, struct device_driver *drv) /* 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", @@ -334,12 +379,17 @@ static int really_probe(struct device *dev, struct device_driver *drv) 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: @@ -393,6 +443,10 @@ int driver_probe_done(void) */ 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(); @@ -695,13 +749,13 @@ static void __device_release_driver(struct device *dev) 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); - } } diff --git a/drivers/base/platform.c b/drivers/base/platform.c index 73e3994..8dcbb26 100644 --- a/drivers/base/platform.c +++ b/drivers/base/platform.c @@ -26,6 +26,7 @@ #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" @@ -319,6 +320,22 @@ int platform_device_add_data(struct platform_device *pdev, const void *data, 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 * @@ -429,6 +446,8 @@ void platform_device_del(struct platform_device *pdev) if (r->parent) release_resource(r); } + + device_remove_property_set(&pdev->dev); } } EXPORT_SYMBOL_GPL(platform_device_del); @@ -507,6 +526,12 @@ struct platform_device *platform_device_register_full( 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: diff --git a/drivers/base/power/clock_ops.c b/drivers/base/power/clock_ops.c index 60ee559..c39b861 100644 --- a/drivers/base/power/clock_ops.c +++ b/drivers/base/power/clock_ops.c @@ -473,6 +473,7 @@ static int pm_clk_notify(struct notifier_block *nb, 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++) diff --git a/drivers/base/power/common.c b/drivers/base/power/common.c index f32b802..f48e333 100644 --- a/drivers/base/power/common.c +++ b/drivers/base/power/common.c @@ -112,7 +112,7 @@ EXPORT_SYMBOL_GPL(dev_pm_domain_attach); /** * 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 diff --git a/drivers/base/power/domain.c b/drivers/base/power/domain.c index 65f50ec..b803790 100644 --- a/drivers/base/power/domain.c +++ b/drivers/base/power/domain.c @@ -1263,6 +1263,7 @@ int __pm_genpd_add_device(struct generic_pm_domain *genpd, struct device *dev, return ret; } +EXPORT_SYMBOL_GPL(__pm_genpd_add_device); /** * pm_genpd_remove_device - Remove a device from an I/O PM domain. @@ -1313,6 +1314,7 @@ int pm_genpd_remove_device(struct generic_pm_domain *genpd, return ret; } +EXPORT_SYMBOL_GPL(pm_genpd_remove_device); /** * pm_genpd_add_subdomain - Add a subdomain to an I/O PM domain. diff --git a/drivers/base/power/main.c b/drivers/base/power/main.c index 1710c26..9d626ac 100644 --- a/drivers/base/power/main.c +++ b/drivers/base/power/main.c @@ -963,6 +963,9 @@ void dpm_complete(pm_message_t state) } 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); } @@ -1624,6 +1627,20 @@ int dpm_prepare(pm_message_t state) 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); diff --git a/drivers/base/power/opp/Makefile b/drivers/base/power/opp/Makefile index 33c1e18..19837ef 100644 --- a/drivers/base/power/opp/Makefile +++ b/drivers/base/power/opp/Makefile @@ -1,2 +1,3 @@ ccflags-$(CONFIG_DEBUG_DRIVER) := -DDEBUG obj-y += core.o cpu.o +obj-$(CONFIG_DEBUG_FS) += debugfs.o diff --git a/drivers/base/power/opp/core.c b/drivers/base/power/opp/core.c index b8e76f7..cf351d3 100644 --- a/drivers/base/power/opp/core.c +++ b/drivers/base/power/opp/core.c @@ -463,6 +463,7 @@ static void _kfree_list_dev_rcu(struct rcu_head *head) 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); @@ -472,6 +473,7 @@ struct device_list_opp *_add_list_dev(const struct device *dev, struct device_opp *dev_opp) { struct device_list_opp *list_dev; + int ret; list_dev = kzalloc(sizeof(*list_dev), GFP_KERNEL); if (!list_dev) @@ -481,6 +483,12 @@ struct device_list_opp *_add_list_dev(const struct device *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; } @@ -551,6 +559,12 @@ static void _remove_device_opp(struct device_opp *dev_opp) 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); @@ -596,6 +610,7 @@ static void _opp_remove(struct device_opp *dev_opp, */ 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); @@ -673,6 +688,7 @@ static int _opp_add(struct device *dev, struct dev_pm_opp *new_opp, { 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 @@ -703,6 +719,11 @@ static int _opp_add(struct device *dev, struct dev_pm_opp *new_opp, 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; } @@ -776,35 +797,49 @@ unlock: } /* 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; } @@ -812,13 +847,272 @@ static int opp_parse_supplies(struct dev_pm_opp *opp, struct device *dev) 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 * @np: device node @@ -864,6 +1158,12 @@ static int _opp_add_static_v2(struct device *dev, struct device_node *np) 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 @@ -879,7 +1179,7 @@ static int _opp_add_static_v2(struct device *dev, struct device_node *np) 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; @@ -889,12 +1189,14 @@ static int _opp_add_static_v2(struct device *dev, struct device_node *np) /* 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) diff --git a/drivers/base/power/opp/cpu.c b/drivers/base/power/opp/cpu.c index 7b445e8..9f0c155 100644 --- a/drivers/base/power/opp/cpu.c +++ b/drivers/base/power/opp/cpu.c @@ -214,7 +214,6 @@ EXPORT_SYMBOL_GPL(dev_pm_opp_of_cpumask_add_table); /* * 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) @@ -230,6 +229,8 @@ 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; diff --git a/drivers/base/power/opp/debugfs.c b/drivers/base/power/opp/debugfs.c new file mode 100644 index 0000000..ddfe477 --- /dev/null +++ b/drivers/base/power/opp/debugfs.c @@ -0,0 +1,219 @@ +/* + * 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); diff --git a/drivers/base/power/opp/opp.h b/drivers/base/power/opp/opp.h index 7366b2a..690638e 100644 --- a/drivers/base/power/opp/opp.h +++ b/drivers/base/power/opp/opp.h @@ -17,6 +17,7 @@ #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> @@ -50,9 +51,10 @@ extern struct mutex dev_opp_list_lock; * 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 @@ -63,6 +65,7 @@ extern struct mutex dev_opp_list_lock; * @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. */ @@ -72,6 +75,7 @@ struct dev_pm_opp { bool available; bool dynamic; bool turbo; + bool suspend; unsigned long rate; unsigned long u_volt; @@ -84,6 +88,10 @@ struct dev_pm_opp { struct rcu_head rcu_head; struct device_node *np; + +#ifdef CONFIG_DEBUG_FS + struct dentry *dentry; +#endif }; /** @@ -91,6 +99,7 @@ struct dev_pm_opp { * @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'. @@ -99,6 +108,10 @@ struct device_list_opp { struct list_head node; const struct device *dev; struct rcu_head rcu_head; + +#ifdef CONFIG_DEBUG_FS + struct dentry *dentry; +#endif }; /** @@ -113,7 +126,14 @@ struct device_list_opp { * @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 @@ -135,6 +155,15 @@ struct device_opp { 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 */ @@ -143,4 +172,26 @@ struct device_list_opp *_add_list_dev(const struct device *dev, 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__ */ diff --git a/drivers/base/power/power.h b/drivers/base/power/power.h index 998fa6b..8b06193 100644 --- a/drivers/base/power/power.h +++ b/drivers/base/power/power.h @@ -18,6 +18,7 @@ static inline void pm_runtime_early_init(struct device *dev) } 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 { @@ -84,6 +85,7 @@ static inline void pm_runtime_early_init(struct device *dev) } 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; } diff --git a/drivers/base/power/runtime.c b/drivers/base/power/runtime.c index e1a10a0..4c70550 100644 --- a/drivers/base/power/runtime.c +++ b/drivers/base/power/runtime.c @@ -966,6 +966,30 @@ int __pm_runtime_resume(struct device *dev, int rpmflags) 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. * @status: New runtime PM status of the device. @@ -1390,18 +1414,32 @@ void pm_runtime_init(struct device *dev) } /** + * 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); } /** diff --git a/drivers/base/property.c b/drivers/base/property.c index 1325ff2..c359351 100644 --- a/drivers/base/property.c +++ b/drivers/base/property.c @@ -19,32 +19,14 @@ #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; } @@ -63,45 +45,135 @@ static struct property_entry *pset_prop_get(struct property_set *pset, 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; } @@ -124,6 +196,18 @@ bool device_property_present(struct device *dev, const char *propname) } 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 @@ -131,12 +215,12 @@ EXPORT_SYMBOL_GPL(device_property_present); */ 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); @@ -309,25 +393,40 @@ int device_property_match_string(struct device *dev, const char *propname, } 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_; \ }) /** @@ -434,6 +533,41 @@ int fwnode_property_read_u64_array(struct fwnode_handle *fwnode, } 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 @@ -456,18 +590,13 @@ 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(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); @@ -489,14 +618,13 @@ 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); @@ -525,6 +653,9 @@ int fwnode_property_match_string(struct fwnode_handle *fwnode, if (nval < 0) return nval; + if (nval == 0) + return -ENODATA; + values = kcalloc(nval, sizeof(*values), GFP_KERNEL); if (!values) return -ENOMEM; @@ -547,6 +678,182 @@ out: 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. * @child: Handle to one of the device's child nodes or a null handle. diff --git a/drivers/cpufreq/Kconfig.arm b/drivers/cpufreq/Kconfig.arm index b1f8a73..0031069 100644 --- a/drivers/cpufreq/Kconfig.arm +++ b/drivers/cpufreq/Kconfig.arm @@ -6,6 +6,8 @@ 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. @@ -217,6 +219,16 @@ config ARM_SPEAR_CPUFREQ 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 diff --git a/drivers/cpufreq/Makefile b/drivers/cpufreq/Makefile index c0af1a1..9e63fb1 100644 --- a/drivers/cpufreq/Makefile +++ b/drivers/cpufreq/Makefile @@ -73,6 +73,7 @@ obj-$(CONFIG_ARM_SA1100_CPUFREQ) += sa1100-cpufreq.o 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 diff --git a/drivers/cpufreq/acpi-cpufreq.c b/drivers/cpufreq/acpi-cpufreq.c index cec1ee2..51eef87 100644 --- a/drivers/cpufreq/acpi-cpufreq.c +++ b/drivers/cpufreq/acpi-cpufreq.c @@ -135,7 +135,7 @@ static void boost_set_msrs(bool enable, const struct cpumask *cpumask) 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); @@ -158,29 +158,24 @@ static ssize_t show_freqdomain_cpus(struct cpufreq_policy *policy, char *buf) 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); @@ -905,7 +900,6 @@ static struct cpufreq_driver acpi_cpufreq_driver = { .resume = acpi_cpufreq_resume, .name = "acpi-cpufreq", .attr = acpi_cpufreq_attr, - .set_boost = _store_boost, }; static void __init acpi_cpufreq_boost_init(void) @@ -916,7 +910,7 @@ 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(); diff --git a/drivers/cpufreq/arm_big_little.c b/drivers/cpufreq/arm_big_little.c index c5d256c..c251247 100644 --- a/drivers/cpufreq/arm_big_little.c +++ b/drivers/cpufreq/arm_big_little.c @@ -23,6 +23,7 @@ #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> @@ -55,6 +56,7 @@ static bool bL_switching_enabled; #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]; @@ -493,6 +495,12 @@ static int bL_cpufreq_init(struct cpufreq_policy *policy) 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) { @@ -507,6 +515,38 @@ static int bL_cpufreq_exit(struct cpufreq_policy *policy) 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 | @@ -517,6 +557,7 @@ static struct cpufreq_driver bL_cpufreq_driver = { .get = bL_cpufreq_get_rate, .init = bL_cpufreq_init, .exit = bL_cpufreq_exit, + .ready = bL_cpufreq_ready, .attr = cpufreq_generic_attr, }; diff --git a/drivers/cpufreq/blackfin-cpufreq.c b/drivers/cpufreq/blackfin-cpufreq.c index a9f8e5b..12e97d8 100644 --- a/drivers/cpufreq/blackfin-cpufreq.c +++ b/drivers/cpufreq/blackfin-cpufreq.c @@ -112,7 +112,7 @@ static unsigned int bfin_getfreq_khz(unsigned int cpu) } #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; diff --git a/drivers/cpufreq/cpufreq-dt.c b/drivers/cpufreq/cpufreq-dt.c index 90d6408..9bc37c4 100644 --- a/drivers/cpufreq/cpufreq-dt.c +++ b/drivers/cpufreq/cpufreq-dt.c @@ -50,7 +50,8 @@ static int set_target(struct cpufreq_policy *policy, unsigned int index) 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; @@ -83,7 +84,7 @@ static int set_target(struct cpufreq_policy *policy, unsigned int index) 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); @@ -407,8 +408,13 @@ static void cpufreq_ready(struct cpufreq_policy *policy) * 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", diff --git a/drivers/cpufreq/cpufreq.c b/drivers/cpufreq/cpufreq.c index 8412ce5..c35e7da 100644 --- a/drivers/cpufreq/cpufreq.c +++ b/drivers/cpufreq/cpufreq.c @@ -2330,29 +2330,15 @@ int cpufreq_boost_trigger_state(int state) 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", @@ -2375,7 +2361,7 @@ int cpufreq_enable_boost_support(void) 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(); @@ -2435,9 +2421,11 @@ int cpufreq_register_driver(struct cpufreq_driver *driver_data) 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) diff --git a/drivers/cpufreq/cpufreq_conservative.c b/drivers/cpufreq/cpufreq_conservative.c index 1fa1deb..606ad74ab 100644 --- a/drivers/cpufreq/cpufreq_conservative.c +++ b/drivers/cpufreq/cpufreq_conservative.c @@ -115,13 +115,13 @@ static void cs_check_cpu(int cpu, unsigned int load) } } -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); } diff --git a/drivers/cpufreq/cpufreq_governor.c b/drivers/cpufreq/cpufreq_governor.c index b260576..bab3a51 100644 --- a/drivers/cpufreq/cpufreq_governor.c +++ b/drivers/cpufreq/cpufreq_governor.c @@ -84,6 +84,9 @@ void dbs_check_cpu(struct dbs_data *dbs_data, int cpu) (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; @@ -158,47 +161,55 @@ void dbs_check_cpu(struct dbs_data *dbs_data, int cpu) } 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) @@ -217,29 +228,21 @@ static bool need_load_eval(struct cpu_common_dbs_info *shared, 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; @@ -250,14 +253,37 @@ static void dbs_timer(struct work_struct *work) 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, @@ -287,6 +313,9 @@ static int alloc_common_dbs_info(struct cpufreq_policy *policy, 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; } @@ -297,6 +326,8 @@ static void free_common_dbs_info(struct cpufreq_policy *policy, 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; @@ -433,7 +464,6 @@ static int cpufreq_governor_start(struct cpufreq_policy *policy, 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); @@ -450,7 +480,9 @@ static int cpufreq_governor_start(struct cpufreq_policy *policy, 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) { @@ -468,8 +500,7 @@ static int cpufreq_governor_start(struct cpufreq_policy *policy, 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; } @@ -483,18 +514,9 @@ static int cpufreq_governor_stop(struct cpufreq_policy *policy, 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; } diff --git a/drivers/cpufreq/cpufreq_governor.h b/drivers/cpufreq/cpufreq_governor.h index 5621bb0..91e767a 100644 --- a/drivers/cpufreq/cpufreq_governor.h +++ b/drivers/cpufreq/cpufreq_governor.h @@ -17,6 +17,7 @@ #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> @@ -132,12 +133,14 @@ static void *get_cpu_dbs_info_s(int cpu) \ 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 */ @@ -152,7 +155,7 @@ struct cpu_dbs_info { * wake-up from idle. */ unsigned int prev_load; - struct delayed_work dwork; + struct timer_list timer; struct cpu_common_dbs_info *shared; }; @@ -209,8 +212,7 @@ struct common_dbs_data { 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); @@ -269,11 +271,11 @@ static ssize_t show_sampling_rate_min_gov_pol \ 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); diff --git a/drivers/cpufreq/cpufreq_ondemand.c b/drivers/cpufreq/cpufreq_ondemand.c index 03ac6ce..eae5107 100644 --- a/drivers/cpufreq/cpufreq_ondemand.c +++ b/drivers/cpufreq/cpufreq_ondemand.c @@ -191,10 +191,9 @@ static void od_check_cpu(int cpu, unsigned int load) } } -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); @@ -247,40 +246,66 @@ static void update_sampling_rate(struct dbs_data *dbs_data, 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, diff --git a/drivers/cpufreq/intel_pstate.c b/drivers/cpufreq/intel_pstate.c index 98fb882..cd83d47 100644 --- a/drivers/cpufreq/intel_pstate.c +++ b/drivers/cpufreq/intel_pstate.c @@ -66,6 +66,7 @@ static inline int ceiling_fp(int32_t x) struct sample { int32_t core_pct_busy; + int32_t busy_scaled; u64 aperf; u64 mperf; u64 tsc; @@ -112,6 +113,7 @@ struct cpudata { u64 prev_aperf; u64 prev_mperf; u64 prev_tsc; + u64 prev_cummulative_iowait; struct sample sample; }; @@ -133,6 +135,7 @@ struct pstate_funcs { 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 { @@ -140,6 +143,9 @@ 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; @@ -738,6 +744,7 @@ static struct cpu_defaults core_params = { .get_turbo = core_get_turbo_pstate, .get_scaling = core_get_scaling, .set = core_set_pstate, + .get_target_pstate = get_target_pstate_use_performance, }, }; @@ -758,6 +765,7 @@ static struct cpu_defaults silvermont_params = { .set = atom_set_pstate, .get_scaling = silvermont_get_scaling, .get_vid = atom_get_vid, + .get_target_pstate = get_target_pstate_use_cpu_load, }, }; @@ -778,6 +786,7 @@ static struct cpu_defaults airmont_params = { .set = atom_set_pstate, .get_scaling = airmont_get_scaling, .get_vid = atom_get_vid, + .get_target_pstate = get_target_pstate_use_cpu_load, }, }; @@ -797,6 +806,7 @@ static struct cpu_defaults knl_params = { .get_turbo = knl_get_turbo_pstate, .get_scaling = core_get_scaling, .set = core_set_pstate, + .get_target_pstate = get_target_pstate_use_performance, }, }; @@ -882,12 +892,11 @@ static inline void intel_pstate_sample(struct cpudata *cpu) 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; @@ -922,7 +931,43 @@ static inline void intel_pstate_set_sample_time(struct cpudata *cpu) 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; @@ -960,30 +1005,24 @@ static inline int32_t intel_pstate_get_scaled_busy(struct cpudata *cpu) 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, @@ -1237,6 +1276,8 @@ static void copy_cpu_funcs(struct pstate_funcs *funcs) 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) diff --git a/drivers/cpufreq/mt8173-cpufreq.c b/drivers/cpufreq/mt8173-cpufreq.c index 83001dc..1efba34 100644 --- a/drivers/cpufreq/mt8173-cpufreq.c +++ b/drivers/cpufreq/mt8173-cpufreq.c @@ -41,16 +41,35 @@ * 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) { @@ -59,7 +78,10 @@ static int mtk_cpufreq_voltage_tracking(struct mtk_cpu_dvfs_info *info, 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); @@ -72,7 +94,17 @@ static int mtk_cpufreq_voltage_tracking(struct mtk_cpu_dvfs_info *info, */ 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); @@ -117,7 +149,17 @@ static int mtk_cpufreq_voltage_tracking(struct mtk_cpu_dvfs_info *info, */ 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, @@ -185,6 +227,10 @@ static int mtk_cpufreq_set_target(struct cpufreq_policy *policy, 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; @@ -344,7 +390,15 @@ static int mtk_cpu_dvfs_info_init(struct mtk_cpu_dvfs_info *info, int cpu) /* 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; @@ -378,7 +432,7 @@ static int mtk_cpu_dvfs_info_init(struct mtk_cpu_dvfs_info *info, int cpu) 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)) @@ -404,7 +458,7 @@ static void mtk_cpu_dvfs_info_release(struct mtk_cpu_dvfs_info *info) 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) @@ -413,22 +467,18 @@ 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); @@ -437,8 +487,7 @@ static int mtk_cpufreq_init(struct cpufreq_policy *policy) 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; @@ -446,13 +495,6 @@ static int mtk_cpufreq_init(struct cpufreq_policy *policy) 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; } @@ -462,14 +504,13 @@ static int mtk_cpufreq_exit(struct cpufreq_policy *policy) 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, @@ -482,11 +523,47 @@ static struct cpufreq_driver mt8173_cpufreq_driver = { 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; } diff --git a/drivers/cpufreq/pcc-cpufreq.c b/drivers/cpufreq/pcc-cpufreq.c index 2a0d589..808a320 100644 --- a/drivers/cpufreq/pcc-cpufreq.c +++ b/drivers/cpufreq/pcc-cpufreq.c @@ -555,6 +555,8 @@ static int pcc_cpufreq_cpu_init(struct cpufreq_policy *policy) 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: diff --git a/drivers/cpufreq/qoriq-cpufreq.c b/drivers/cpufreq/qoriq-cpufreq.c index 358f075..b23e525 100644 --- a/drivers/cpufreq/qoriq-cpufreq.c +++ b/drivers/cpufreq/qoriq-cpufreq.c @@ -12,6 +12,7 @@ #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> @@ -33,6 +34,7 @@ struct cpu_data { struct clk **pclk; struct cpufreq_frequency_table *table; + struct thermal_cooling_device *cdev; }; /** @@ -321,6 +323,27 @@ static int qoriq_cpufreq_target(struct cpufreq_policy *policy, 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, @@ -329,6 +352,7 @@ static struct cpufreq_driver qoriq_cpufreq_driver = { .verify = cpufreq_generic_frequency_table_verify, .target_index = qoriq_cpufreq_target, .get = cpufreq_generic_get, + .ready = qoriq_cpufreq_ready, .attr = cpufreq_generic_attr, }; diff --git a/drivers/cpufreq/sti-cpufreq.c b/drivers/cpufreq/sti-cpufreq.c new file mode 100644 index 0000000..a9c659f --- /dev/null +++ b/drivers/cpufreq/sti-cpufreq.c @@ -0,0 +1,294 @@ +/* + * 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"); diff --git a/drivers/cpuidle/cpuidle-clps711x.c b/drivers/cpuidle/cpuidle-clps711x.c index 18a7f73..66a9f23 100644 --- a/drivers/cpuidle/cpuidle-clps711x.c +++ b/drivers/cpuidle/cpuidle-clps711x.c @@ -12,7 +12,7 @@ #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" @@ -56,8 +56,4 @@ static struct platform_driver clps711x_cpuidle_driver = { .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); diff --git a/drivers/cpuidle/cpuidle-exynos.c b/drivers/cpuidle/cpuidle-exynos.c index b5f0a9c..00cd129 100644 --- a/drivers/cpuidle/cpuidle-exynos.c +++ b/drivers/cpuidle/cpuidle-exynos.c @@ -14,7 +14,7 @@ #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> @@ -142,5 +142,4 @@ static struct platform_driver exynos_cpuidle_driver = { .name = "exynos_cpuidle", }, }; - -module_platform_driver(exynos_cpuidle_driver); +builtin_platform_driver(exynos_cpuidle_driver); diff --git a/drivers/cpuidle/cpuidle-ux500.c b/drivers/cpuidle/cpuidle-ux500.c index 8bf895c..7941a09 100644 --- a/drivers/cpuidle/cpuidle-ux500.c +++ b/drivers/cpuidle/cpuidle-ux500.c @@ -9,7 +9,7 @@ * 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> @@ -124,5 +124,4 @@ static struct platform_driver dbx500_cpuidle_plat_driver = { }, .probe = dbx500_cpuidle_probe, }; - -module_platform_driver(dbx500_cpuidle_plat_driver); +builtin_platform_driver(dbx500_cpuidle_plat_driver); diff --git a/drivers/cpuidle/governors/menu.c b/drivers/cpuidle/governors/menu.c index 22e4463..7b0971d 100644 --- a/drivers/cpuidle/governors/menu.c +++ b/drivers/cpuidle/governors/menu.c @@ -330,7 +330,7 @@ static int menu_select(struct cpuidle_driver *drv, struct cpuidle_device *dev) * 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; @@ -404,8 +404,10 @@ static void menu_update(struct cpuidle_driver *drv, struct cpuidle_device *dev) 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) diff --git a/drivers/dma/dw/core.c b/drivers/dma/dw/core.c index 7067b6d..8b20930 100644 --- a/drivers/dma/dw/core.c +++ b/drivers/dma/dw/core.c @@ -622,12 +622,17 @@ static void dw_dma_tasklet(unsigned long data) 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; /* diff --git a/drivers/dma/dw/platform.c b/drivers/dma/dw/platform.c index 68a4815..127093a 100644 --- a/drivers/dma/dw/platform.c +++ b/drivers/dma/dw/platform.c @@ -155,7 +155,6 @@ static int dw_probe(struct platform_device *pdev) 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; @@ -179,11 +178,6 @@ static int dw_probe(struct platform_device *pdev) 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; @@ -239,7 +233,19 @@ static void dw_shutdown(struct platform_device *pdev) { 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); } @@ -252,17 +258,8 @@ MODULE_DEVICE_TABLE(of, dw_dma_of_id_table); #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); diff --git a/drivers/gpio/gpiolib-acpi.c b/drivers/gpio/gpiolib-acpi.c index 16a7b68..cbbb67a 100644 --- a/drivers/gpio/gpiolib-acpi.c +++ b/drivers/gpio/gpiolib-acpi.c @@ -417,10 +417,15 @@ static int acpi_find_gpio(struct acpi_resource *ares, void *data) * 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; @@ -447,7 +452,7 @@ static int acpi_gpio_resource_lookup(struct acpi_gpio_lookup *lookup, if (info) { *info = lookup->info; if (lookup->active_low) - info->active_low = lookup->active_low; + info->polarity = lookup->active_low; } return 0; } @@ -595,6 +600,7 @@ struct gpio_desc *acpi_node_get_gpiod(struct fwnode_handle *fwnode, 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; @@ -603,8 +609,23 @@ int acpi_dev_gpio_irq_get(struct acpi_device *adev, int index) 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; } diff --git a/drivers/gpio/gpiolib.c b/drivers/gpio/gpiolib.c index 4e4c308..5d8d7ab 100644 --- a/drivers/gpio/gpiolib.c +++ b/drivers/gpio/gpiolib.c @@ -1879,7 +1879,7 @@ static struct gpio_desc *acpi_find_gpio(struct device *dev, const char *con_id, return desc; } - if (info.active_low) + if (info.polarity == GPIO_ACTIVE_LOW) *flags |= GPIO_ACTIVE_LOW; return desc; @@ -2217,7 +2217,7 @@ struct gpio_desc *fwnode_get_named_gpiod(struct fwnode_handle *fwnode, 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)) diff --git a/drivers/gpio/gpiolib.h b/drivers/gpio/gpiolib.h index 98ab08c..5ac3b88 100644 --- a/drivers/gpio/gpiolib.h +++ b/drivers/gpio/gpiolib.h @@ -26,7 +26,8 @@ struct acpi_device; */ struct acpi_gpio_info { bool gpioint; - bool active_low; + int polarity; + int triggering; }; /* gpio suffixes used for ACPI and device tree lookup */ diff --git a/drivers/i2c/busses/i2c-designware-baytrail.c b/drivers/i2c/busses/i2c-designware-baytrail.c index 7d7ae97..e38c2bb 100644 --- a/drivers/i2c/busses/i2c-designware-baytrail.c +++ b/drivers/i2c/busses/i2c-designware-baytrail.c @@ -34,8 +34,7 @@ static int get_sem(struct device *dev, u32 *sem) 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; @@ -50,21 +49,19 @@ static void reset_semaphore(struct device *dev) { 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; @@ -77,8 +74,7 @@ static int baytrail_i2c_acquire(struct dw_i2c_dev *dev) 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; @@ -102,8 +98,7 @@ static int baytrail_i2c_acquire(struct dw_i2c_dev *dev) 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 diff --git a/drivers/i2c/busses/i2c-designware-platdrv.c b/drivers/i2c/busses/i2c-designware-platdrv.c index 6b00061c..bf72ae7 100644 --- a/drivers/i2c/busses/i2c-designware-platdrv.c +++ b/drivers/i2c/busses/i2c-designware-platdrv.c @@ -36,6 +36,7 @@ #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> @@ -122,6 +123,7 @@ static const struct acpi_device_id dw_i2c_acpi_match[] = { { "80860F41", 0 }, { "808622C1", 0 }, { "AMD0010", ACCESS_INTR_MASK }, + { "APMC0D0F", 0 }, { } }; MODULE_DEVICE_TABLE(acpi, dw_i2c_acpi_match); @@ -134,10 +136,10 @@ static inline int dw_i2c_acpi_configure(struct platform_device *pdev) 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; @@ -161,33 +163,28 @@ static int dw_i2c_plat_probe(struct platform_device *pdev) /* 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); diff --git a/drivers/mfd/intel-lpss-acpi.c b/drivers/mfd/intel-lpss-acpi.c index b6fd904..06f00d6 100644 --- a/drivers/mfd/intel-lpss-acpi.c +++ b/drivers/mfd/intel-lpss-acpi.c @@ -18,6 +18,7 @@ #include <linux/pm.h> #include <linux/pm_runtime.h> #include <linux/platform_device.h> +#include <linux/property.h> #include "intel-lpss.h" @@ -25,6 +26,20 @@ static const struct intel_lpss_platform_info spt_info = { .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, }; @@ -35,8 +50,8 @@ static const struct intel_lpss_platform_info bxt_i2c_info = { 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 }, diff --git a/drivers/mfd/intel-lpss-pci.c b/drivers/mfd/intel-lpss-pci.c index 5bfdfcc..a7136c7 100644 --- a/drivers/mfd/intel-lpss-pci.c +++ b/drivers/mfd/intel-lpss-pci.c @@ -17,6 +17,7 @@ #include <linux/pci.h> #include <linux/pm.h> #include <linux/pm_runtime.h> +#include <linux/property.h> #include "intel-lpss.h" @@ -65,9 +66,35 @@ static const struct intel_lpss_platform_info spt_info = { .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 = { @@ -77,6 +104,7 @@ 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 = { @@ -121,20 +149,20 @@ static const struct pci_device_id intel_lpss_pci_ids[] = { { 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 }, { } }; diff --git a/drivers/mfd/intel-lpss.c b/drivers/mfd/intel-lpss.c index 6255513..1743788 100644 --- a/drivers/mfd/intel-lpss.c +++ b/drivers/mfd/intel-lpss.c @@ -24,6 +24,7 @@ #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> @@ -72,7 +73,7 @@ struct intel_lpss { 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; @@ -217,6 +218,7 @@ static void intel_lpss_ltr_hide(struct intel_lpss *lpss) 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; @@ -224,18 +226,22 @@ static int intel_lpss_assign_devs(struct intel_lpss *lpss) 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; @@ -401,6 +407,8 @@ int intel_lpss_probe(struct device *dev, 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); diff --git a/drivers/mfd/intel-lpss.h b/drivers/mfd/intel-lpss.h index 2c7f8d7..0dcea9e 100644 --- a/drivers/mfd/intel-lpss.h +++ b/drivers/mfd/intel-lpss.h @@ -16,12 +16,14 @@ 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, diff --git a/drivers/mfd/mfd-core.c b/drivers/mfd/mfd-core.c index 60b60dc..88bd1b1 100644 --- a/drivers/mfd/mfd-core.c +++ b/drivers/mfd/mfd-core.c @@ -14,6 +14,7 @@ #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> @@ -192,6 +193,12 @@ static int mfd_add_device(struct device *parent, int id, 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; diff --git a/drivers/pci/pci-acpi.c b/drivers/pci/pci-acpi.c index d3f32d6..9a033e8 100644 --- a/drivers/pci/pci-acpi.c +++ b/drivers/pci/pci-acpi.c @@ -531,7 +531,7 @@ static bool acpi_pci_need_resume(struct pci_dev *dev) 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, diff --git a/drivers/pci/pci.c b/drivers/pci/pci.c index 314db8c..d1a7105 100644 --- a/drivers/pci/pci.c +++ b/drivers/pci/pci.c @@ -527,9 +527,9 @@ static void pci_restore_bars(struct pci_dev *dev) 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) diff --git a/drivers/pci/pci.h b/drivers/pci/pci.h index d390fc1..f6f151a 100644 --- a/drivers/pci/pci.h +++ b/drivers/pci/pci.h @@ -68,7 +68,7 @@ struct pci_platform_pm_ops { 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); diff --git a/drivers/platform/x86/dell-wmi.c b/drivers/platform/x86/dell-wmi.c index f2d77fe..cb8a9c2 100644 --- a/drivers/platform/x86/dell-wmi.c +++ b/drivers/platform/x86/dell-wmi.c @@ -43,8 +43,6 @@ MODULE_LICENSE("GPL"); #define DELL_EVENT_GUID "9DBB5994-A997-11DA-B012-B622A1EF5492" -static int acpi_video; - MODULE_ALIAS("wmi:"DELL_EVENT_GUID); /* @@ -159,7 +157,8 @@ static void dell_wmi_process_key(int reported_key) /* 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); @@ -398,7 +397,6 @@ static int __init dell_wmi_init(void) } dmi_walk(find_hk_type, NULL); - acpi_video = acpi_video_get_backlight_type() != acpi_backlight_vendor; err = dell_wmi_input_setup(); if (err) diff --git a/drivers/platform/x86/thinkpad_acpi.c b/drivers/platform/x86/thinkpad_acpi.c index 0bed473..f453d5d 100644 --- a/drivers/platform/x86/thinkpad_acpi.c +++ b/drivers/platform/x86/thinkpad_acpi.c @@ -3488,7 +3488,7 @@ static int __init hotkey_init(struct ibm_init_struct *iibm) /* 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"); diff --git a/drivers/pnp/driver.c b/drivers/pnp/driver.c index 153a493..63452f2 100644 --- a/drivers/pnp/driver.c +++ b/drivers/pnp/driver.c @@ -74,7 +74,6 @@ void pnp_device_detach(struct pnp_dev *pnp_dev) 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) @@ -131,6 +130,11 @@ static int pnp_device_remove(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; } diff --git a/drivers/pnp/quirks.c b/drivers/pnp/quirks.c index 943c1cb..f700723 100644 --- a/drivers/pnp/quirks.c +++ b/drivers/pnp/quirks.c @@ -343,6 +343,7 @@ static void quirk_amd_mmconfig_area(struct pnp_dev *dev) static const unsigned int mch_quirk_devices[] = { 0x0154, /* Ivy Bridge */ 0x0c00, /* Haswell */ + 0x1604, /* Broadwell */ }; static struct pci_dev *get_intel_host(void) diff --git a/drivers/powercap/intel_rapl.c b/drivers/powercap/intel_rapl.c index 48747c2..6c592dc 100644 --- a/drivers/powercap/intel_rapl.c +++ b/drivers/powercap/intel_rapl.c @@ -388,7 +388,7 @@ static int get_domain_enable(struct powercap_zone *power_zone, bool *mode) } /* 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, @@ -584,7 +584,7 @@ static int get_max_power(struct powercap_zone *power_zone, int id, 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, @@ -988,16 +988,16 @@ static void set_floor_freq_atom(struct rapl_domain *rd, bool enable) } 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, diff --git a/drivers/powercap/powercap_sys.c b/drivers/powercap/powercap_sys.c index 84419af..14bde0d 100644 --- a/drivers/powercap/powercap_sys.c +++ b/drivers/powercap/powercap_sys.c @@ -293,8 +293,8 @@ err_alloc: } 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; @@ -492,13 +492,13 @@ static struct class powercap_class = { }; 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; diff --git a/drivers/spi/spi.c b/drivers/spi/spi.c index dee1cb8..151b01c 100644 --- a/drivers/spi/spi.c +++ b/drivers/spi/spi.c @@ -1623,6 +1623,9 @@ static acpi_status acpi_spi_add_device(acpi_handle handle, u32 level, 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)) { diff --git a/drivers/thermal/intel_quark_dts_thermal.c b/drivers/thermal/intel_quark_dts_thermal.c index 5ed90e6..5d33b35 100644 --- a/drivers/thermal/intel_quark_dts_thermal.c +++ b/drivers/thermal/intel_quark_dts_thermal.c @@ -125,8 +125,8 @@ static int soc_dts_enable(struct thermal_zone_device *tzd) 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; @@ -137,8 +137,8 @@ static int soc_dts_enable(struct thermal_zone_device *tzd) 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; @@ -158,8 +158,8 @@ static int soc_dts_disable(struct thermal_zone_device *tzd) 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; @@ -170,8 +170,8 @@ static int soc_dts_disable(struct thermal_zone_device *tzd) 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; @@ -192,8 +192,8 @@ static int _get_trip_temp(int trip, int *temp) 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) @@ -236,8 +236,8 @@ static int update_trip_temp(struct soc_sensor_entry *aux_entry, 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; @@ -262,8 +262,8 @@ static int update_trip_temp(struct soc_sensor_entry *aux_entry, 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); @@ -294,8 +294,8 @@ static int sys_get_curr_temp(struct thermal_zone_device *tzd, 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) @@ -350,13 +350,13 @@ static void free_soc_dts(struct soc_sensor_entry *aux_entry) 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); @@ -378,9 +378,8 @@ static struct soc_sensor_entry *alloc_soc_dts(void) } /* 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; @@ -395,16 +394,16 @@ static struct soc_sensor_entry *alloc_soc_dts(void) /* 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; } diff --git a/drivers/thermal/intel_soc_dts_iosf.c b/drivers/thermal/intel_soc_dts_iosf.c index 5841d1d..f72e1db 100644 --- a/drivers/thermal/intel_soc_dts_iosf.c +++ b/drivers/thermal/intel_soc_dts_iosf.c @@ -90,7 +90,7 @@ static int sys_get_trip_temp(struct thermal_zone_device *tzd, int trip, 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) @@ -124,27 +124,27 @@ static int update_trip_temp(struct intel_soc_dts_sensor_entry *dts, 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) @@ -167,12 +167,12 @@ static int update_trip_temp(struct intel_soc_dts_sensor_entry *dts, 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) @@ -182,13 +182,13 @@ static int update_trip_temp(struct intel_soc_dts_sensor_entry *dts, 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 */ @@ -235,7 +235,7 @@ static int sys_get_curr_temp(struct thermal_zone_device *tzd, 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; @@ -259,14 +259,14 @@ static int soc_dts_enable(int id) 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; @@ -278,7 +278,7 @@ static int soc_dts_enable(int id) 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); } @@ -296,9 +296,8 @@ static int add_dts_thermal_zone(int id, struct intel_soc_dts_sensor_entry *dts, 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; @@ -311,7 +310,7 @@ static int add_dts_thermal_zone(int id, struct intel_soc_dts_sensor_entry *dts, } /* 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; @@ -374,19 +373,19 @@ void intel_soc_dts_iosf_interrupt_handler(struct intel_soc_dts_sensors *sensors) 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); diff --git a/include/acpi/acexcep.h b/include/acpi/acexcep.h index 204f581..cd84b12 100644 --- a/include/acpi/acexcep.h +++ b/include/acpi/acexcep.h @@ -126,8 +126,9 @@ struct acpi_exception_info { #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 @@ -263,7 +264,8 @@ static const struct acpi_exception_info acpi_gbl_exception_names_env[] = { "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[] = { diff --git a/include/acpi/acpi_bus.h b/include/acpi/acpi_bus.h index ad0a5ff..14362a8 100644 --- a/include/acpi/acpi_bus.h +++ b/include/acpi/acpi_bus.h @@ -87,6 +87,8 @@ acpi_evaluate_dsm_typed(acpi_handle handle, const u8 *uuid, int rev, int func, .package.elements = (eles) \ } +bool acpi_dev_present(const char *hid); + #ifdef CONFIG_ACPI #include <linux/proc_fs.h> @@ -631,7 +633,9 @@ static inline bool acpi_device_can_wakeup(struct acpi_device *adev) 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 */ diff --git a/include/acpi/acpiosxf.h b/include/acpi/acpiosxf.h index fbc2baf..0d824a2 100644 --- a/include/acpi/acpiosxf.h +++ b/include/acpi/acpiosxf.h @@ -349,12 +349,28 @@ void acpi_os_redirect_output(void *destination); #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) */ diff --git a/include/acpi/acpixf.h b/include/acpi/acpixf.h index 3aaaa86..012b2ee 100644 --- a/include/acpi/acpixf.h +++ b/include/acpi/acpixf.h @@ -46,7 +46,7 @@ /* 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> @@ -190,6 +190,11 @@ ACPI_INIT_GLOBAL(u8, acpi_gbl_copy_dsdt_locally, FALSE); 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 * address. Although ACPICA adheres to the ACPI specification which @@ -263,6 +268,19 @@ ACPI_INIT_GLOBAL(u32, acpi_gbl_trace_dbg_layer, ACPI_TRACE_LAYER_DEFAULT); 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 */ @@ -366,6 +384,29 @@ ACPI_GLOBAL(u8, acpi_gbl_system_awake_and_running); #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 @@ -822,17 +863,9 @@ ACPI_EXTERNAL_RETURN_STATUS(acpi_status 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 */ @@ -929,6 +962,8 @@ ACPI_EXTERNAL_RETURN_STATUS(acpi_status 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__ */ diff --git a/include/acpi/actypes.h b/include/acpi/actypes.h index f914958..9633f60 100644 --- a/include/acpi/actypes.h +++ b/include/acpi/actypes.h @@ -1148,7 +1148,7 @@ u32 (*acpi_interface_handler) (acpi_string interface_name, u32 supported); #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 */ @@ -1178,7 +1178,6 @@ struct acpi_device_info { 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> */ }; @@ -1193,13 +1192,12 @@ struct acpi_device_info { #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 diff --git a/include/acpi/platform/aclinux.h b/include/acpi/platform/aclinux.h index 323e5da..e21857d 100644 --- a/include/acpi/platform/aclinux.h +++ b/include/acpi/platform/aclinux.h @@ -150,6 +150,8 @@ */ #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 diff --git a/include/acpi/platform/aclinuxex.h b/include/acpi/platform/aclinuxex.h index fd6d70f..f903fe6 100644 --- a/include/acpi/platform/aclinuxex.h +++ b/include/acpi/platform/aclinuxex.h @@ -129,6 +129,16 @@ static inline u8 acpi_os_readable(void *pointer, acpi_size length) 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 */ diff --git a/include/acpi/video.h b/include/acpi/video.h index c62392d..f11d342 100644 --- a/include/acpi/video.h +++ b/include/acpi/video.h @@ -2,6 +2,7 @@ #define __ACPI_VIDEO_H #include <linux/errno.h> /* for ENODEV */ +#include <linux/types.h> /* for bool */ struct acpi_device; @@ -31,6 +32,7 @@ extern int acpi_video_get_edid(struct acpi_device *device, int type, 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; } @@ -46,6 +48,10 @@ static inline enum acpi_backlight_type acpi_video_get_backlight_type(void) 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 diff --git a/include/linux/acpi.h b/include/linux/acpi.h index 1991aea..06ed7e5 100644 --- a/include/linux/acpi.h +++ b/include/linux/acpi.h @@ -37,6 +37,8 @@ #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> @@ -119,6 +121,75 @@ typedef int (*acpi_tbl_table_handler)(struct acpi_table_header *table); 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 @@ -318,6 +389,7 @@ bool acpi_dev_resource_address_space(struct acpi_resource *ares, 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); diff --git a/include/linux/cpufreq.h b/include/linux/cpufreq.h index 177c768..88a4215 100644 --- a/include/linux/cpufreq.h +++ b/include/linux/cpufreq.h @@ -278,7 +278,6 @@ struct cpufreq_driver { struct freq_attr **attr; /* platform specific boost support code */ - bool boost_supported; bool boost_enabled; int (*set_boost)(int state); }; @@ -574,7 +573,6 @@ ssize_t cpufreq_show_cpus(const struct cpumask *mask, char *buf); #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); @@ -583,10 +581,6 @@ static inline int cpufreq_boost_trigger_state(int state) { return 0; } -static inline int cpufreq_boost_supported(void) -{ - return 0; -} static inline int cpufreq_boost_enabled(void) { return 0; diff --git a/include/linux/device.h b/include/linux/device.h index b8f411b..f627ba2 100644 --- a/include/linux/device.h +++ b/include/linux/device.h @@ -191,6 +191,7 @@ extern int bus_unregister_notifier(struct bus_type *bus, 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); diff --git a/include/linux/mfd/core.h b/include/linux/mfd/core.h index 27dac3f..bc6f7e0 100644 --- a/include/linux/mfd/core.h +++ b/include/linux/mfd/core.h @@ -17,6 +17,7 @@ #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 { @@ -44,6 +45,10 @@ struct mfd_cell { /* 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 diff --git a/include/linux/platform_device.h b/include/linux/platform_device.h index 6abd019..03b7555 100644 --- a/include/linux/platform_device.h +++ b/include/linux/platform_device.h @@ -18,6 +18,7 @@ #define PLATFORM_DEVID_AUTO (-2) struct mfd_cell; +struct property_set; struct platform_device { const char *name; @@ -71,6 +72,8 @@ struct platform_device_info { 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); @@ -168,6 +171,8 @@ extern int platform_device_add_resources(struct platform_device *pdev, 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); diff --git a/include/linux/pm_opp.h b/include/linux/pm_opp.h index 9a2e503..95403d2 100644 --- a/include/linux/pm_opp.h +++ b/include/linux/pm_opp.h @@ -55,6 +55,11 @@ int dev_pm_opp_enable(struct device *dev, unsigned long freq); 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) { @@ -129,6 +134,23 @@ static inline struct srcu_notifier_head *dev_pm_opp_get_notifier( { 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) diff --git a/include/linux/pm_runtime.h b/include/linux/pm_runtime.h index 3bdbb41..7af093d 100644 --- a/include/linux/pm_runtime.h +++ b/include/linux/pm_runtime.h @@ -39,6 +39,7 @@ extern int pm_runtime_force_resume(struct device *dev); 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); @@ -143,6 +144,10 @@ static inline int pm_schedule_suspend(struct device *dev, unsigned int delay) { 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; } diff --git a/include/linux/powercap.h b/include/linux/powercap.h index 4e25041..f0a4e62 100644 --- a/include/linux/powercap.h +++ b/include/linux/powercap.h @@ -208,7 +208,7 @@ struct powercap_zone_constraint_ops { struct powercap_zone_constraint { int id; struct powercap_zone *power_zone; - struct powercap_zone_constraint_ops *ops; + const struct powercap_zone_constraint_ops *ops; }; @@ -309,7 +309,7 @@ struct powercap_zone *powercap_register_zone( 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 diff --git a/include/linux/property.h b/include/linux/property.h index 0a3705a..b51fcd3 100644 --- a/include/linux/property.h +++ b/include/linux/property.h @@ -73,8 +73,8 @@ int fwnode_property_match_string(struct fwnode_handle *fwnode, 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); @@ -144,24 +144,100 @@ static inline int fwnode_property_read_u64(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. @@ -172,7 +248,8 @@ struct property_set { 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); diff --git a/kernel/power/main.c b/kernel/power/main.c index b2dd4d9..2794697 100644 --- a/kernel/power/main.c +++ b/kernel/power/main.c @@ -280,13 +280,7 @@ static ssize_t pm_wakeup_irq_show(struct kobject *kobj, 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) {} @@ -564,14 +558,7 @@ static ssize_t pm_trace_dev_match_show(struct kobject *kobj, 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 */ diff --git a/kernel/power/power.h b/kernel/power/power.h index caadb56..efe1b3b 100644 --- a/kernel/power/power.h +++ b/kernel/power/power.h @@ -77,6 +77,15 @@ static struct kobj_attribute _name##_attr = { \ .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) */ diff --git a/tools/power/acpi/Makefile b/tools/power/acpi/Makefile index e882c83..a8bf908 100644 --- a/tools/power/acpi/Makefile +++ b/tools/power/acpi/Makefile @@ -10,18 +10,18 @@ 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 diff --git a/tools/power/acpi/common/getopt.c b/tools/power/acpi/common/getopt.c index 326e826..efefe30 100644 --- a/tools/power/acpi/common/getopt.c +++ b/tools/power/acpi/common/getopt.c @@ -47,6 +47,7 @@ * 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 */ @@ -85,6 +86,7 @@ static int current_char_ptr = 1; int acpi_getopt_argument(int argc, char **argv) { + acpi_gbl_optind--; current_char_ptr++; diff --git a/tools/power/acpi/os_specific/service_layers/oslibcfs.c b/tools/power/acpi/os_specific/service_layers/oslibcfs.c index b51e40a..6df7583 100644 --- a/tools/power/acpi/os_specific/service_layers/oslibcfs.c +++ b/tools/power/acpi/os_specific/service_layers/oslibcfs.c @@ -73,6 +73,7 @@ ACPI_FILE acpi_os_open_file(const char *path, u8 modes) if (modes & ACPI_FILE_WRITING) { modes_str[i++] = 'w'; } + if (modes & ACPI_FILE_BINARY) { modes_str[i++] = 'b'; } @@ -101,6 +102,7 @@ ACPI_FILE acpi_os_open_file(const char *path, u8 modes) void acpi_os_close_file(ACPI_FILE file) { + fclose(file); } @@ -202,6 +204,7 @@ acpi_status acpi_os_set_file_offset(ACPI_FILE file, long offset, u8 from) if (from == ACPI_FILE_BEGIN) { ret = fseek(file, offset, SEEK_SET); } + if (from == ACPI_FILE_END) { ret = fseek(file, offset, SEEK_END); } diff --git a/tools/power/acpi/tools/acpidbg/Makefile b/tools/power/acpi/tools/acpidbg/Makefile new file mode 100644 index 0000000..352df4b --- /dev/null +++ b/tools/power/acpi/tools/acpidbg/Makefile @@ -0,0 +1,27 @@ +# 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 diff --git a/tools/power/acpi/tools/acpidbg/acpidbg.c b/tools/power/acpi/tools/acpidbg/acpidbg.c new file mode 100644 index 0000000..d070fcc --- /dev/null +++ b/tools/power/acpi/tools/acpidbg/acpidbg.c @@ -0,0 +1,438 @@ +/* + * 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; +} diff --git a/tools/power/acpi/tools/acpidump/apfiles.c b/tools/power/acpi/tools/acpidump/apfiles.c index a1c62de..bbdf9e8 100644 --- a/tools/power/acpi/tools/acpidump/apfiles.c +++ b/tools/power/acpi/tools/acpidump/apfiles.c @@ -48,6 +48,18 @@ 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 @@ -136,6 +148,7 @@ int ap_write_to_binary_file(struct acpi_table_header *table, u32 instance) } 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]); diff --git a/tools/power/cpupower/Makefile b/tools/power/cpupower/Makefile index 2e2ba2e..0adaf0c 100644 --- a/tools/power/cpupower/Makefile +++ b/tools/power/cpupower/Makefile @@ -47,6 +47,11 @@ NLS ?= true # 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 ?= @@ -161,6 +166,12 @@ ifeq ($(strip $(CPUFREQ_BENCH)),true) 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) @@ -209,7 +220,11 @@ $(OUTPUT)%.o: %.c $(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) @@ -291,7 +306,11 @@ install-bench: @#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.* diff --git a/tools/power/cpupower/bench/Makefile b/tools/power/cpupower/bench/Makefile index 7ec7021..d0f879b 100644 --- a/tools/power/cpupower/bench/Makefile +++ b/tools/power/cpupower/bench/Makefile @@ -5,9 +5,15 @@ ifneq ($(O),) 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 diff --git a/tools/power/cpupower/utils/cpufreq-info.c b/tools/power/cpupower/utils/cpufreq-info.c index 0e67643..8f3f5bb 100644 --- a/tools/power/cpupower/utils/cpufreq-info.c +++ b/tools/power/cpupower/utils/cpufreq-info.c @@ -14,6 +14,7 @@ #include <getopt.h> #include "cpufreq.h" +#include "helpers/sysfs.h" #include "helpers/helpers.h" #include "helpers/bitmask.h" @@ -244,149 +245,21 @@ static int get_boost_mode(unsigned int cpu) 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; } @@ -396,13 +269,16 @@ static int get_freq_kernel(unsigned int cpu, unsigned int human) 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; } @@ -411,9 +287,17 @@ static int get_freq_hardware(unsigned int cpu, unsigned int human) 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; } @@ -422,9 +306,11 @@ static int get_hardware_limits(unsigned int cpu) 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; } @@ -434,9 +320,19 @@ static int get_driver(unsigned int cpu) 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; } @@ -447,8 +343,12 @@ static int get_available_governors(unsigned int cpu) { 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); @@ -465,8 +365,12 @@ static int get_available_governors(unsigned int cpu) 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); @@ -482,8 +386,12 @@ static int get_affected_cpus(unsigned int 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); @@ -524,8 +432,12 @@ static int get_freq_stats(unsigned int cpu, unsigned int human) 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); @@ -535,6 +447,36 @@ static int get_latency(unsigned int cpu, unsigned int human) 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'}, @@ -647,11 +589,14 @@ int cmd_freq_info(int argc, char **argv) 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': @@ -693,6 +638,7 @@ int cmd_freq_info(int argc, char **argv) } if (ret) return ret; + printf("\n"); } return ret; } diff --git a/tools/power/cpupower/utils/cpuidle-info.c b/tools/power/cpupower/utils/cpuidle-info.c index 750c1d8..8bf8ab5 100644 --- a/tools/power/cpupower/utils/cpuidle-info.c +++ b/tools/power/cpupower/utils/cpuidle-info.c @@ -12,7 +12,6 @@ #include <stdlib.h> #include <string.h> #include <getopt.h> -#include <cpufreq.h> #include "helpers/helpers.h" #include "helpers/sysfs.h" @@ -25,8 +24,6 @@ static void cpuidle_cpu_output(unsigned int cpu, int verbose) 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); @@ -71,7 +68,6 @@ static void cpuidle_cpu_output(unsigned int cpu, int verbose) printf(_("Duration: %llu\n"), sysfs_get_idlestate_time(cpu, idlestate)); } - printf("\n"); } static void cpuidle_general_output(void) @@ -189,10 +185,17 @@ int cmd_idle_info(int argc, char **argv) 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': @@ -203,6 +206,7 @@ int cmd_idle_info(int argc, char **argv) cpuidle_cpu_output(cpu, verbose); break; } + printf("\n"); } return EXIT_SUCCESS; } diff --git a/tools/power/cpupower/utils/cpupower-info.c b/tools/power/cpupower/utils/cpupower-info.c index 10299f2..c7caa8e 100644 --- a/tools/power/cpupower/utils/cpupower-info.c +++ b/tools/power/cpupower/utils/cpupower-info.c @@ -12,7 +12,6 @@ #include <string.h> #include <getopt.h> -#include <cpufreq.h> #include "helpers/helpers.h" #include "helpers/sysfs.h" @@ -83,12 +82,16 @@ int cmd_info(int argc, char **argv) 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) { diff --git a/tools/power/cpupower/utils/cpupower-set.c b/tools/power/cpupower/utils/cpupower-set.c index 3e6f374..532f46b 100644 --- a/tools/power/cpupower/utils/cpupower-set.c +++ b/tools/power/cpupower/utils/cpupower-set.c @@ -12,7 +12,6 @@ #include <string.h> #include <getopt.h> -#include <cpufreq.h> #include "helpers/helpers.h" #include "helpers/sysfs.h" #include "helpers/bitmask.h" @@ -78,10 +77,15 @@ int cmd_set(int argc, char **argv) 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) { diff --git a/tools/power/cpupower/utils/helpers/topology.c b/tools/power/cpupower/utils/helpers/topology.c index 9cbb7fd..5f9c908 100644 --- a/tools/power/cpupower/utils/helpers/topology.c +++ b/tools/power/cpupower/utils/helpers/topology.c @@ -106,7 +106,7 @@ int get_cpu_topology(struct cpupower_topology *cpu_top) 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 |