Merge "Merge remote-tracking branch 'msm-4.4/tmp-2bf7955' into msm-4.4"
This commit is contained in:
commit
af0987f562
370 changed files with 4997 additions and 2289 deletions
|
@ -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>;
|
||||
...
|
||||
};
|
||||
};
|
||||
|
||||
cpu0_opp_table_fast: opp_table_fast {
|
||||
compatible = "operating-points-v2";
|
||||
status = "okay";
|
||||
opp-shared;
|
||||
|
||||
opp10 {
|
||||
opp-hz = /bits/ 64 <1000000000>;
|
||||
...
|
||||
};
|
||||
|
||||
opp11 {
|
||||
opp-hz = /bits/ 64 <1100000000>;
|
||||
opp-microvolt = <900000 915000 925000>;
|
||||
...
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
Example 6: opp-microvolt-<name>, opp-microamp-<name>:
|
||||
(example: device with two possible microvolt ranges: slow and fast)
|
||||
|
||||
/ {
|
||||
cpus {
|
||||
cpu@0 {
|
||||
compatible = "arm,cortex-a7";
|
||||
...
|
||||
|
||||
operating-points-v2 = <&cpu0_opp_table>;
|
||||
};
|
||||
};
|
||||
|
||||
cpu0_opp_table: opp_table0 {
|
||||
compatible = "operating-points-v2";
|
||||
opp-shared;
|
||||
|
||||
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>;
|
||||
};
|
||||
|
||||
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 */
|
||||
};
|
||||
};
|
||||
};
|
||||
|
|
|
@ -134,12 +134,12 @@ mfio80 ddr_debug, mips_trace_data, mips_debug
|
|||
mfio81 dreq0, mips_trace_data, eth_debug
|
||||
mfio82 dreq1, mips_trace_data, eth_debug
|
||||
mfio83 mips_pll_lock, mips_trace_data, usb_debug
|
||||
mfio84 sys_pll_lock, mips_trace_data, usb_debug
|
||||
mfio85 wifi_pll_lock, mips_trace_data, sdhost_debug
|
||||
mfio86 bt_pll_lock, mips_trace_data, sdhost_debug
|
||||
mfio87 rpu_v_pll_lock, dreq2, socif_debug
|
||||
mfio88 rpu_l_pll_lock, dreq3, socif_debug
|
||||
mfio89 audio_pll_lock, dreq4, dreq5
|
||||
mfio84 audio_pll_lock, mips_trace_data, usb_debug
|
||||
mfio85 rpu_v_pll_lock, mips_trace_data, sdhost_debug
|
||||
mfio86 rpu_l_pll_lock, mips_trace_data, sdhost_debug
|
||||
mfio87 sys_pll_lock, dreq2, socif_debug
|
||||
mfio88 wifi_pll_lock, dreq3, socif_debug
|
||||
mfio89 bt_pll_lock, dreq4, dreq5
|
||||
tck
|
||||
trstn
|
||||
tdi
|
||||
|
|
|
@ -3936,6 +3936,8 @@ bytes respectively. Such letter suffixes can also be entirely omitted.
|
|||
sector if the number is odd);
|
||||
i = IGNORE_DEVICE (don't bind to this
|
||||
device);
|
||||
j = NO_REPORT_LUNS (don't use report luns
|
||||
command, uas only);
|
||||
l = NOT_LOCKABLE (don't try to lock and
|
||||
unlock ejectable media);
|
||||
m = MAX_SECTORS_64 (don't transfer more
|
||||
|
|
96
MAINTAINERS
96
MAINTAINERS
|
@ -230,13 +230,13 @@ F: kernel/sys_ni.c
|
|||
|
||||
ABIT UGURU 1,2 HARDWARE MONITOR DRIVER
|
||||
M: Hans de Goede <hdegoede@redhat.com>
|
||||
L: lm-sensors@lm-sensors.org
|
||||
L: linux-hwmon@vger.kernel.org
|
||||
S: Maintained
|
||||
F: drivers/hwmon/abituguru.c
|
||||
|
||||
ABIT UGURU 3 HARDWARE MONITOR DRIVER
|
||||
M: Alistair John Strachan <alistair@devzero.co.uk>
|
||||
L: lm-sensors@lm-sensors.org
|
||||
L: linux-hwmon@vger.kernel.org
|
||||
S: Maintained
|
||||
F: drivers/hwmon/abituguru3.c
|
||||
|
||||
|
@ -373,14 +373,14 @@ S: Maintained
|
|||
|
||||
ADM1025 HARDWARE MONITOR DRIVER
|
||||
M: Jean Delvare <jdelvare@suse.com>
|
||||
L: lm-sensors@lm-sensors.org
|
||||
L: linux-hwmon@vger.kernel.org
|
||||
S: Maintained
|
||||
F: Documentation/hwmon/adm1025
|
||||
F: drivers/hwmon/adm1025.c
|
||||
|
||||
ADM1029 HARDWARE MONITOR DRIVER
|
||||
M: Corentin Labbe <clabbe.montjoie@gmail.com>
|
||||
L: lm-sensors@lm-sensors.org
|
||||
L: linux-hwmon@vger.kernel.org
|
||||
S: Maintained
|
||||
F: drivers/hwmon/adm1029.c
|
||||
|
||||
|
@ -425,7 +425,7 @@ F: drivers/video/backlight/adp8860_bl.c
|
|||
|
||||
ADS1015 HARDWARE MONITOR DRIVER
|
||||
M: Dirk Eibach <eibach@gdsys.de>
|
||||
L: lm-sensors@lm-sensors.org
|
||||
L: linux-hwmon@vger.kernel.org
|
||||
S: Maintained
|
||||
F: Documentation/hwmon/ads1015
|
||||
F: drivers/hwmon/ads1015.c
|
||||
|
@ -438,7 +438,7 @@ F: drivers/macintosh/therm_adt746x.c
|
|||
|
||||
ADT7475 HARDWARE MONITOR DRIVER
|
||||
M: Jean Delvare <jdelvare@suse.com>
|
||||
L: lm-sensors@lm-sensors.org
|
||||
L: linux-hwmon@vger.kernel.org
|
||||
S: Maintained
|
||||
F: Documentation/hwmon/adt7475
|
||||
F: drivers/hwmon/adt7475.c
|
||||
|
@ -615,7 +615,7 @@ F: include/linux/ccp.h
|
|||
|
||||
AMD FAM15H PROCESSOR POWER MONITORING DRIVER
|
||||
M: Andreas Herrmann <herrmann.der.user@googlemail.com>
|
||||
L: lm-sensors@lm-sensors.org
|
||||
L: linux-hwmon@vger.kernel.org
|
||||
S: Maintained
|
||||
F: Documentation/hwmon/fam15h_power
|
||||
F: drivers/hwmon/fam15h_power.c
|
||||
|
@ -779,7 +779,7 @@ F: drivers/input/mouse/bcm5974.c
|
|||
|
||||
APPLE SMC DRIVER
|
||||
M: Henrik Rydberg <rydberg@bitmath.org>
|
||||
L: lm-sensors@lm-sensors.org
|
||||
L: linux-hwmon@vger.kernel.org
|
||||
S: Odd fixes
|
||||
F: drivers/hwmon/applesmc.c
|
||||
|
||||
|
@ -1777,7 +1777,7 @@ F: include/media/as3645a.h
|
|||
|
||||
ASC7621 HARDWARE MONITOR DRIVER
|
||||
M: George Joseph <george.joseph@fairview5.com>
|
||||
L: lm-sensors@lm-sensors.org
|
||||
L: linux-hwmon@vger.kernel.org
|
||||
S: Maintained
|
||||
F: Documentation/hwmon/asc7621
|
||||
F: drivers/hwmon/asc7621.c
|
||||
|
@ -1864,7 +1864,7 @@ F: drivers/net/wireless/ath/carl9170/
|
|||
|
||||
ATK0110 HWMON DRIVER
|
||||
M: Luca Tettamanti <kronos.it@gmail.com>
|
||||
L: lm-sensors@lm-sensors.org
|
||||
L: linux-hwmon@vger.kernel.org
|
||||
S: Maintained
|
||||
F: drivers/hwmon/asus_atk0110.c
|
||||
|
||||
|
@ -2984,7 +2984,7 @@ F: mm/swap_cgroup.c
|
|||
|
||||
CORETEMP HARDWARE MONITORING DRIVER
|
||||
M: Fenghua Yu <fenghua.yu@intel.com>
|
||||
L: lm-sensors@lm-sensors.org
|
||||
L: linux-hwmon@vger.kernel.org
|
||||
S: Maintained
|
||||
F: Documentation/hwmon/coretemp
|
||||
F: drivers/hwmon/coretemp.c
|
||||
|
@ -3549,7 +3549,7 @@ T: git git://git.infradead.org/users/vkoul/slave-dma.git
|
|||
|
||||
DME1737 HARDWARE MONITOR DRIVER
|
||||
M: Juerg Haefliger <juergh@gmail.com>
|
||||
L: lm-sensors@lm-sensors.org
|
||||
L: linux-hwmon@vger.kernel.org
|
||||
S: Maintained
|
||||
F: Documentation/hwmon/dme1737
|
||||
F: drivers/hwmon/dme1737.c
|
||||
|
@ -4262,7 +4262,7 @@ F: include/video/exynos_mipi*
|
|||
|
||||
F71805F HARDWARE MONITORING DRIVER
|
||||
M: Jean Delvare <jdelvare@suse.com>
|
||||
L: lm-sensors@lm-sensors.org
|
||||
L: linux-hwmon@vger.kernel.org
|
||||
S: Maintained
|
||||
F: Documentation/hwmon/f71805f
|
||||
F: drivers/hwmon/f71805f.c
|
||||
|
@ -4341,7 +4341,7 @@ F: fs/*
|
|||
|
||||
FINTEK F75375S HARDWARE MONITOR AND FAN CONTROLLER DRIVER
|
||||
M: Riku Voipio <riku.voipio@iki.fi>
|
||||
L: lm-sensors@lm-sensors.org
|
||||
L: linux-hwmon@vger.kernel.org
|
||||
S: Maintained
|
||||
F: drivers/hwmon/f75375s.c
|
||||
F: include/linux/f75375s.h
|
||||
|
@ -4883,8 +4883,8 @@ F: drivers/media/usb/hackrf/
|
|||
HARDWARE MONITORING
|
||||
M: Jean Delvare <jdelvare@suse.com>
|
||||
M: Guenter Roeck <linux@roeck-us.net>
|
||||
L: lm-sensors@lm-sensors.org
|
||||
W: http://www.lm-sensors.org/
|
||||
L: linux-hwmon@vger.kernel.org
|
||||
W: http://hwmon.wiki.kernel.org/
|
||||
T: quilt http://jdelvare.nerim.net/devel/linux/jdelvare-hwmon/
|
||||
T: git git://git.kernel.org/pub/scm/linux/kernel/git/groeck/linux-staging.git
|
||||
S: Maintained
|
||||
|
@ -5393,7 +5393,7 @@ F: drivers/usb/atm/ueagle-atm.c
|
|||
|
||||
INA209 HARDWARE MONITOR DRIVER
|
||||
M: Guenter Roeck <linux@roeck-us.net>
|
||||
L: lm-sensors@lm-sensors.org
|
||||
L: linux-hwmon@vger.kernel.org
|
||||
S: Maintained
|
||||
F: Documentation/hwmon/ina209
|
||||
F: Documentation/devicetree/bindings/i2c/ina209.txt
|
||||
|
@ -5401,7 +5401,7 @@ F: drivers/hwmon/ina209.c
|
|||
|
||||
INA2XX HARDWARE MONITOR DRIVER
|
||||
M: Guenter Roeck <linux@roeck-us.net>
|
||||
L: lm-sensors@lm-sensors.org
|
||||
L: linux-hwmon@vger.kernel.org
|
||||
S: Maintained
|
||||
F: Documentation/hwmon/ina2xx
|
||||
F: drivers/hwmon/ina2xx.c
|
||||
|
@ -5884,7 +5884,7 @@ F: drivers/isdn/hardware/eicon/
|
|||
|
||||
IT87 HARDWARE MONITORING DRIVER
|
||||
M: Jean Delvare <jdelvare@suse.com>
|
||||
L: lm-sensors@lm-sensors.org
|
||||
L: linux-hwmon@vger.kernel.org
|
||||
S: Maintained
|
||||
F: Documentation/hwmon/it87
|
||||
F: drivers/hwmon/it87.c
|
||||
|
@ -5920,7 +5920,7 @@ F: drivers/media/dvb-frontends/ix2505v*
|
|||
|
||||
JC42.4 TEMPERATURE SENSOR DRIVER
|
||||
M: Guenter Roeck <linux@roeck-us.net>
|
||||
L: lm-sensors@lm-sensors.org
|
||||
L: linux-hwmon@vger.kernel.org
|
||||
S: Maintained
|
||||
F: drivers/hwmon/jc42.c
|
||||
F: Documentation/hwmon/jc42
|
||||
|
@ -5970,14 +5970,14 @@ F: drivers/tty/serial/jsm/
|
|||
|
||||
K10TEMP HARDWARE MONITORING DRIVER
|
||||
M: Clemens Ladisch <clemens@ladisch.de>
|
||||
L: lm-sensors@lm-sensors.org
|
||||
L: linux-hwmon@vger.kernel.org
|
||||
S: Maintained
|
||||
F: Documentation/hwmon/k10temp
|
||||
F: drivers/hwmon/k10temp.c
|
||||
|
||||
K8TEMP HARDWARE MONITORING DRIVER
|
||||
M: Rudolf Marek <r.marek@assembler.cz>
|
||||
L: lm-sensors@lm-sensors.org
|
||||
L: linux-hwmon@vger.kernel.org
|
||||
S: Maintained
|
||||
F: Documentation/hwmon/k8temp
|
||||
F: drivers/hwmon/k8temp.c
|
||||
|
@ -6485,27 +6485,27 @@ F: net/llc/
|
|||
|
||||
LM73 HARDWARE MONITOR DRIVER
|
||||
M: Guillaume Ligneul <guillaume.ligneul@gmail.com>
|
||||
L: lm-sensors@lm-sensors.org
|
||||
L: linux-hwmon@vger.kernel.org
|
||||
S: Maintained
|
||||
F: drivers/hwmon/lm73.c
|
||||
|
||||
LM78 HARDWARE MONITOR DRIVER
|
||||
M: Jean Delvare <jdelvare@suse.com>
|
||||
L: lm-sensors@lm-sensors.org
|
||||
L: linux-hwmon@vger.kernel.org
|
||||
S: Maintained
|
||||
F: Documentation/hwmon/lm78
|
||||
F: drivers/hwmon/lm78.c
|
||||
|
||||
LM83 HARDWARE MONITOR DRIVER
|
||||
M: Jean Delvare <jdelvare@suse.com>
|
||||
L: lm-sensors@lm-sensors.org
|
||||
L: linux-hwmon@vger.kernel.org
|
||||
S: Maintained
|
||||
F: Documentation/hwmon/lm83
|
||||
F: drivers/hwmon/lm83.c
|
||||
|
||||
LM90 HARDWARE MONITOR DRIVER
|
||||
M: Jean Delvare <jdelvare@suse.com>
|
||||
L: lm-sensors@lm-sensors.org
|
||||
L: linux-hwmon@vger.kernel.org
|
||||
S: Maintained
|
||||
F: Documentation/hwmon/lm90
|
||||
F: Documentation/devicetree/bindings/hwmon/lm90.txt
|
||||
|
@ -6513,7 +6513,7 @@ F: drivers/hwmon/lm90.c
|
|||
|
||||
LM95234 HARDWARE MONITOR DRIVER
|
||||
M: Guenter Roeck <linux@roeck-us.net>
|
||||
L: lm-sensors@lm-sensors.org
|
||||
L: linux-hwmon@vger.kernel.org
|
||||
S: Maintained
|
||||
F: Documentation/hwmon/lm95234
|
||||
F: drivers/hwmon/lm95234.c
|
||||
|
@ -6580,7 +6580,7 @@ F: drivers/scsi/sym53c8xx_2/
|
|||
|
||||
LTC4261 HARDWARE MONITOR DRIVER
|
||||
M: Guenter Roeck <linux@roeck-us.net>
|
||||
L: lm-sensors@lm-sensors.org
|
||||
L: linux-hwmon@vger.kernel.org
|
||||
S: Maintained
|
||||
F: Documentation/hwmon/ltc4261
|
||||
F: drivers/hwmon/ltc4261.c
|
||||
|
@ -6749,28 +6749,28 @@ F: include/uapi/linux/matroxfb.h
|
|||
|
||||
MAX16065 HARDWARE MONITOR DRIVER
|
||||
M: Guenter Roeck <linux@roeck-us.net>
|
||||
L: lm-sensors@lm-sensors.org
|
||||
L: linux-hwmon@vger.kernel.org
|
||||
S: Maintained
|
||||
F: Documentation/hwmon/max16065
|
||||
F: drivers/hwmon/max16065.c
|
||||
|
||||
MAX20751 HARDWARE MONITOR DRIVER
|
||||
M: Guenter Roeck <linux@roeck-us.net>
|
||||
L: lm-sensors@lm-sensors.org
|
||||
L: linux-hwmon@vger.kernel.org
|
||||
S: Maintained
|
||||
F: Documentation/hwmon/max20751
|
||||
F: drivers/hwmon/max20751.c
|
||||
|
||||
MAX6650 HARDWARE MONITOR AND FAN CONTROLLER DRIVER
|
||||
M: "Hans J. Koch" <hjk@hansjkoch.de>
|
||||
L: lm-sensors@lm-sensors.org
|
||||
L: linux-hwmon@vger.kernel.org
|
||||
S: Maintained
|
||||
F: Documentation/hwmon/max6650
|
||||
F: drivers/hwmon/max6650.c
|
||||
|
||||
MAX6697 HARDWARE MONITOR DRIVER
|
||||
M: Guenter Roeck <linux@roeck-us.net>
|
||||
L: lm-sensors@lm-sensors.org
|
||||
L: linux-hwmon@vger.kernel.org
|
||||
S: Maintained
|
||||
F: Documentation/hwmon/max6697
|
||||
F: Documentation/devicetree/bindings/i2c/max6697.txt
|
||||
|
@ -7303,7 +7303,7 @@ F: drivers/scsi/NCR_D700.*
|
|||
|
||||
NCT6775 HARDWARE MONITOR DRIVER
|
||||
M: Guenter Roeck <linux@roeck-us.net>
|
||||
L: lm-sensors@lm-sensors.org
|
||||
L: linux-hwmon@vger.kernel.org
|
||||
S: Maintained
|
||||
F: Documentation/hwmon/nct6775
|
||||
F: drivers/hwmon/nct6775.c
|
||||
|
@ -8064,7 +8064,7 @@ F: drivers/video/logo/logo_parisc*
|
|||
|
||||
PC87360 HARDWARE MONITORING DRIVER
|
||||
M: Jim Cromie <jim.cromie@gmail.com>
|
||||
L: lm-sensors@lm-sensors.org
|
||||
L: linux-hwmon@vger.kernel.org
|
||||
S: Maintained
|
||||
F: Documentation/hwmon/pc87360
|
||||
F: drivers/hwmon/pc87360.c
|
||||
|
@ -8076,7 +8076,7 @@ F: drivers/char/pc8736x_gpio.c
|
|||
|
||||
PC87427 HARDWARE MONITORING DRIVER
|
||||
M: Jean Delvare <jdelvare@suse.com>
|
||||
L: lm-sensors@lm-sensors.org
|
||||
L: linux-hwmon@vger.kernel.org
|
||||
S: Maintained
|
||||
F: Documentation/hwmon/pc87427
|
||||
F: drivers/hwmon/pc87427.c
|
||||
|
@ -8415,8 +8415,8 @@ F: drivers/rtc/rtc-puv3.c
|
|||
|
||||
PMBUS HARDWARE MONITORING DRIVERS
|
||||
M: Guenter Roeck <linux@roeck-us.net>
|
||||
L: lm-sensors@lm-sensors.org
|
||||
W: http://www.lm-sensors.org/
|
||||
L: linux-hwmon@vger.kernel.org
|
||||
W: http://hwmon.wiki.kernel.org/
|
||||
W: http://www.roeck-us.net/linux/drivers/
|
||||
T: git git://git.kernel.org/pub/scm/linux/kernel/git/groeck/linux-staging.git
|
||||
S: Maintained
|
||||
|
@ -8610,7 +8610,7 @@ F: drivers/media/usb/pwc/*
|
|||
|
||||
PWM FAN DRIVER
|
||||
M: Kamil Debski <k.debski@samsung.com>
|
||||
L: lm-sensors@lm-sensors.org
|
||||
L: linux-hwmon@vger.kernel.org
|
||||
S: Supported
|
||||
F: Documentation/devicetree/bindings/hwmon/pwm-fan.txt
|
||||
F: Documentation/hwmon/pwm-fan
|
||||
|
@ -9882,28 +9882,28 @@ F: Documentation/devicetree/bindings/media/i2c/nokia,smia.txt
|
|||
|
||||
SMM665 HARDWARE MONITOR DRIVER
|
||||
M: Guenter Roeck <linux@roeck-us.net>
|
||||
L: lm-sensors@lm-sensors.org
|
||||
L: linux-hwmon@vger.kernel.org
|
||||
S: Maintained
|
||||
F: Documentation/hwmon/smm665
|
||||
F: drivers/hwmon/smm665.c
|
||||
|
||||
SMSC EMC2103 HARDWARE MONITOR DRIVER
|
||||
M: Steve Glendinning <steve.glendinning@shawell.net>
|
||||
L: lm-sensors@lm-sensors.org
|
||||
L: linux-hwmon@vger.kernel.org
|
||||
S: Maintained
|
||||
F: Documentation/hwmon/emc2103
|
||||
F: drivers/hwmon/emc2103.c
|
||||
|
||||
SMSC SCH5627 HARDWARE MONITOR DRIVER
|
||||
M: Hans de Goede <hdegoede@redhat.com>
|
||||
L: lm-sensors@lm-sensors.org
|
||||
L: linux-hwmon@vger.kernel.org
|
||||
S: Supported
|
||||
F: Documentation/hwmon/sch5627
|
||||
F: drivers/hwmon/sch5627.c
|
||||
|
||||
SMSC47B397 HARDWARE MONITOR DRIVER
|
||||
M: Jean Delvare <jdelvare@suse.com>
|
||||
L: lm-sensors@lm-sensors.org
|
||||
L: linux-hwmon@vger.kernel.org
|
||||
S: Maintained
|
||||
F: Documentation/hwmon/smsc47b397
|
||||
F: drivers/hwmon/smsc47b397.c
|
||||
|
@ -10830,7 +10830,7 @@ F: include/linux/mmc/sh_mobile_sdhi.h
|
|||
|
||||
TMP401 HARDWARE MONITOR DRIVER
|
||||
M: Guenter Roeck <linux@roeck-us.net>
|
||||
L: lm-sensors@lm-sensors.org
|
||||
L: linux-hwmon@vger.kernel.org
|
||||
S: Maintained
|
||||
F: Documentation/hwmon/tmp401
|
||||
F: drivers/hwmon/tmp401.c
|
||||
|
@ -11564,14 +11564,14 @@ F: Documentation/networking/vrf.txt
|
|||
|
||||
VT1211 HARDWARE MONITOR DRIVER
|
||||
M: Juerg Haefliger <juergh@gmail.com>
|
||||
L: lm-sensors@lm-sensors.org
|
||||
L: linux-hwmon@vger.kernel.org
|
||||
S: Maintained
|
||||
F: Documentation/hwmon/vt1211
|
||||
F: drivers/hwmon/vt1211.c
|
||||
|
||||
VT8231 HARDWARE MONITOR DRIVER
|
||||
M: Roger Lucas <vt8231@hiddenengine.co.uk>
|
||||
L: lm-sensors@lm-sensors.org
|
||||
L: linux-hwmon@vger.kernel.org
|
||||
S: Maintained
|
||||
F: drivers/hwmon/vt8231.c
|
||||
|
||||
|
@ -11590,21 +11590,21 @@ F: drivers/w1/
|
|||
|
||||
W83791D HARDWARE MONITORING DRIVER
|
||||
M: Marc Hulsman <m.hulsman@tudelft.nl>
|
||||
L: lm-sensors@lm-sensors.org
|
||||
L: linux-hwmon@vger.kernel.org
|
||||
S: Maintained
|
||||
F: Documentation/hwmon/w83791d
|
||||
F: drivers/hwmon/w83791d.c
|
||||
|
||||
W83793 HARDWARE MONITORING DRIVER
|
||||
M: Rudolf Marek <r.marek@assembler.cz>
|
||||
L: lm-sensors@lm-sensors.org
|
||||
L: linux-hwmon@vger.kernel.org
|
||||
S: Maintained
|
||||
F: Documentation/hwmon/w83793
|
||||
F: drivers/hwmon/w83793.c
|
||||
|
||||
W83795 HARDWARE MONITORING DRIVER
|
||||
M: Jean Delvare <jdelvare@suse.com>
|
||||
L: lm-sensors@lm-sensors.org
|
||||
L: linux-hwmon@vger.kernel.org
|
||||
S: Maintained
|
||||
F: drivers/hwmon/w83795.c
|
||||
|
||||
|
|
2
Makefile
2
Makefile
|
@ -1,6 +1,6 @@
|
|||
VERSION = 4
|
||||
PATCHLEVEL = 4
|
||||
SUBLEVEL = 6
|
||||
SUBLEVEL = 8
|
||||
EXTRAVERSION =
|
||||
NAME = Blurry Fish Butt
|
||||
|
||||
|
|
|
@ -35,21 +35,6 @@ static inline void op##_bit(unsigned long nr, volatile unsigned long *m)\
|
|||
\
|
||||
m += nr >> 5; \
|
||||
\
|
||||
/* \
|
||||
* ARC ISA micro-optimization: \
|
||||
* \
|
||||
* Instructions dealing with bitpos only consider lower 5 bits \
|
||||
* e.g (x << 33) is handled like (x << 1) by ASL instruction \
|
||||
* (mem pointer still needs adjustment to point to next word) \
|
||||
* \
|
||||
* Hence the masking to clamp @nr arg can be elided in general. \
|
||||
* \
|
||||
* However if @nr is a constant (above assumed in a register), \
|
||||
* and greater than 31, gcc can optimize away (x << 33) to 0, \
|
||||
* as overflow, given the 32-bit ISA. Thus masking needs to be \
|
||||
* done for const @nr, but no code is generated due to gcc \
|
||||
* const prop. \
|
||||
*/ \
|
||||
nr &= 0x1f; \
|
||||
\
|
||||
__asm__ __volatile__( \
|
||||
|
|
|
@ -129,15 +129,23 @@ static inline void __raw_writel(u32 w, volatile void __iomem *addr)
|
|||
#define writel(v,c) ({ __iowmb(); writel_relaxed(v,c); })
|
||||
|
||||
/*
|
||||
* Relaxed API for drivers which can handle any ordering themselves
|
||||
* Relaxed API for drivers which can handle barrier ordering themselves
|
||||
*
|
||||
* Also these are defined to perform little endian accesses.
|
||||
* To provide the typical device register semantics of fixed endian,
|
||||
* swap the byte order for Big Endian
|
||||
*
|
||||
* http://lkml.kernel.org/r/201603100845.30602.arnd@arndb.de
|
||||
*/
|
||||
#define readb_relaxed(c) __raw_readb(c)
|
||||
#define readw_relaxed(c) __raw_readw(c)
|
||||
#define readl_relaxed(c) __raw_readl(c)
|
||||
#define readw_relaxed(c) ({ u16 __r = le16_to_cpu((__force __le16) \
|
||||
__raw_readw(c)); __r; })
|
||||
#define readl_relaxed(c) ({ u32 __r = le32_to_cpu((__force __le32) \
|
||||
__raw_readl(c)); __r; })
|
||||
|
||||
#define writeb_relaxed(v,c) __raw_writeb(v,c)
|
||||
#define writew_relaxed(v,c) __raw_writew(v,c)
|
||||
#define writel_relaxed(v,c) __raw_writel(v,c)
|
||||
#define writew_relaxed(v,c) __raw_writew((__force u16) cpu_to_le16(v),c)
|
||||
#define writel_relaxed(v,c) __raw_writel((__force u32) cpu_to_le32(v),c)
|
||||
|
||||
#include <asm-generic/io.h>
|
||||
|
||||
|
|
|
@ -303,6 +303,7 @@
|
|||
regulator-name = "mmc0-card-supply";
|
||||
regulator-min-microvolt = <3300000>;
|
||||
regulator-max-microvolt = <3300000>;
|
||||
regulator-always-on;
|
||||
};
|
||||
|
||||
gpio_keys {
|
||||
|
|
|
@ -268,5 +268,6 @@
|
|||
regulator-min-microvolt = <3300000>;
|
||||
regulator-max-microvolt = <3300000>;
|
||||
vin-supply = <&vcc_3v3_reg>;
|
||||
regulator-always-on;
|
||||
};
|
||||
};
|
||||
|
|
|
@ -54,12 +54,12 @@ static int s3c64xx_i2s_cfg_gpio(struct platform_device *pdev)
|
|||
|
||||
static struct resource s3c64xx_iis0_resource[] = {
|
||||
[0] = DEFINE_RES_MEM(S3C64XX_PA_IIS0, SZ_256),
|
||||
[1] = DEFINE_RES_DMA(DMACH_I2S0_OUT),
|
||||
[2] = DEFINE_RES_DMA(DMACH_I2S0_IN),
|
||||
};
|
||||
|
||||
static struct s3c_audio_pdata i2sv3_pdata = {
|
||||
static struct s3c_audio_pdata i2s0_pdata = {
|
||||
.cfg_gpio = s3c64xx_i2s_cfg_gpio,
|
||||
.dma_playback = DMACH_I2S0_OUT,
|
||||
.dma_capture = DMACH_I2S0_IN,
|
||||
};
|
||||
|
||||
struct platform_device s3c64xx_device_iis0 = {
|
||||
|
@ -68,15 +68,19 @@ struct platform_device s3c64xx_device_iis0 = {
|
|||
.num_resources = ARRAY_SIZE(s3c64xx_iis0_resource),
|
||||
.resource = s3c64xx_iis0_resource,
|
||||
.dev = {
|
||||
.platform_data = &i2sv3_pdata,
|
||||
.platform_data = &i2s0_pdata,
|
||||
},
|
||||
};
|
||||
EXPORT_SYMBOL(s3c64xx_device_iis0);
|
||||
|
||||
static struct resource s3c64xx_iis1_resource[] = {
|
||||
[0] = DEFINE_RES_MEM(S3C64XX_PA_IIS1, SZ_256),
|
||||
[1] = DEFINE_RES_DMA(DMACH_I2S1_OUT),
|
||||
[2] = DEFINE_RES_DMA(DMACH_I2S1_IN),
|
||||
};
|
||||
|
||||
static struct s3c_audio_pdata i2s1_pdata = {
|
||||
.cfg_gpio = s3c64xx_i2s_cfg_gpio,
|
||||
.dma_playback = DMACH_I2S1_OUT,
|
||||
.dma_capture = DMACH_I2S1_IN,
|
||||
};
|
||||
|
||||
struct platform_device s3c64xx_device_iis1 = {
|
||||
|
@ -85,19 +89,19 @@ struct platform_device s3c64xx_device_iis1 = {
|
|||
.num_resources = ARRAY_SIZE(s3c64xx_iis1_resource),
|
||||
.resource = s3c64xx_iis1_resource,
|
||||
.dev = {
|
||||
.platform_data = &i2sv3_pdata,
|
||||
.platform_data = &i2s1_pdata,
|
||||
},
|
||||
};
|
||||
EXPORT_SYMBOL(s3c64xx_device_iis1);
|
||||
|
||||
static struct resource s3c64xx_iisv4_resource[] = {
|
||||
[0] = DEFINE_RES_MEM(S3C64XX_PA_IISV4, SZ_256),
|
||||
[1] = DEFINE_RES_DMA(DMACH_HSI_I2SV40_TX),
|
||||
[2] = DEFINE_RES_DMA(DMACH_HSI_I2SV40_RX),
|
||||
};
|
||||
|
||||
static struct s3c_audio_pdata i2sv4_pdata = {
|
||||
.cfg_gpio = s3c64xx_i2s_cfg_gpio,
|
||||
.dma_playback = DMACH_HSI_I2SV40_TX,
|
||||
.dma_capture = DMACH_HSI_I2SV40_RX,
|
||||
.type = {
|
||||
.i2s = {
|
||||
.quirks = QUIRK_PRI_6CHAN,
|
||||
|
@ -142,12 +146,12 @@ static int s3c64xx_pcm_cfg_gpio(struct platform_device *pdev)
|
|||
|
||||
static struct resource s3c64xx_pcm0_resource[] = {
|
||||
[0] = DEFINE_RES_MEM(S3C64XX_PA_PCM0, SZ_256),
|
||||
[1] = DEFINE_RES_DMA(DMACH_PCM0_TX),
|
||||
[2] = DEFINE_RES_DMA(DMACH_PCM0_RX),
|
||||
};
|
||||
|
||||
static struct s3c_audio_pdata s3c_pcm0_pdata = {
|
||||
.cfg_gpio = s3c64xx_pcm_cfg_gpio,
|
||||
.dma_capture = DMACH_PCM0_RX,
|
||||
.dma_playback = DMACH_PCM0_TX,
|
||||
};
|
||||
|
||||
struct platform_device s3c64xx_device_pcm0 = {
|
||||
|
@ -163,12 +167,12 @@ EXPORT_SYMBOL(s3c64xx_device_pcm0);
|
|||
|
||||
static struct resource s3c64xx_pcm1_resource[] = {
|
||||
[0] = DEFINE_RES_MEM(S3C64XX_PA_PCM1, SZ_256),
|
||||
[1] = DEFINE_RES_DMA(DMACH_PCM1_TX),
|
||||
[2] = DEFINE_RES_DMA(DMACH_PCM1_RX),
|
||||
};
|
||||
|
||||
static struct s3c_audio_pdata s3c_pcm1_pdata = {
|
||||
.cfg_gpio = s3c64xx_pcm_cfg_gpio,
|
||||
.dma_playback = DMACH_PCM1_TX,
|
||||
.dma_capture = DMACH_PCM1_RX,
|
||||
};
|
||||
|
||||
struct platform_device s3c64xx_device_pcm1 = {
|
||||
|
@ -196,13 +200,14 @@ static int s3c64xx_ac97_cfg_gpe(struct platform_device *pdev)
|
|||
|
||||
static struct resource s3c64xx_ac97_resource[] = {
|
||||
[0] = DEFINE_RES_MEM(S3C64XX_PA_AC97, SZ_256),
|
||||
[1] = DEFINE_RES_DMA(DMACH_AC97_PCMOUT),
|
||||
[2] = DEFINE_RES_DMA(DMACH_AC97_PCMIN),
|
||||
[3] = DEFINE_RES_DMA(DMACH_AC97_MICIN),
|
||||
[4] = DEFINE_RES_IRQ(IRQ_AC97),
|
||||
[1] = DEFINE_RES_IRQ(IRQ_AC97),
|
||||
};
|
||||
|
||||
static struct s3c_audio_pdata s3c_ac97_pdata;
|
||||
static struct s3c_audio_pdata s3c_ac97_pdata = {
|
||||
.dma_playback = DMACH_AC97_PCMOUT,
|
||||
.dma_capture = DMACH_AC97_PCMIN,
|
||||
.dma_capture_mic = DMACH_AC97_MICIN,
|
||||
};
|
||||
|
||||
static u64 s3c64xx_ac97_dmamask = DMA_BIT_MASK(32);
|
||||
|
||||
|
|
|
@ -14,38 +14,38 @@
|
|||
#define S3C64XX_DMA_CHAN(name) ((unsigned long)(name))
|
||||
|
||||
/* DMA0/SDMA0 */
|
||||
#define DMACH_UART0 S3C64XX_DMA_CHAN("uart0_tx")
|
||||
#define DMACH_UART0_SRC2 S3C64XX_DMA_CHAN("uart0_rx")
|
||||
#define DMACH_UART1 S3C64XX_DMA_CHAN("uart1_tx")
|
||||
#define DMACH_UART1_SRC2 S3C64XX_DMA_CHAN("uart1_rx")
|
||||
#define DMACH_UART2 S3C64XX_DMA_CHAN("uart2_tx")
|
||||
#define DMACH_UART2_SRC2 S3C64XX_DMA_CHAN("uart2_rx")
|
||||
#define DMACH_UART3 S3C64XX_DMA_CHAN("uart3_tx")
|
||||
#define DMACH_UART3_SRC2 S3C64XX_DMA_CHAN("uart3_rx")
|
||||
#define DMACH_PCM0_TX S3C64XX_DMA_CHAN("pcm0_tx")
|
||||
#define DMACH_PCM0_RX S3C64XX_DMA_CHAN("pcm0_rx")
|
||||
#define DMACH_I2S0_OUT S3C64XX_DMA_CHAN("i2s0_tx")
|
||||
#define DMACH_I2S0_IN S3C64XX_DMA_CHAN("i2s0_rx")
|
||||
#define DMACH_UART0 "uart0_tx"
|
||||
#define DMACH_UART0_SRC2 "uart0_rx"
|
||||
#define DMACH_UART1 "uart1_tx"
|
||||
#define DMACH_UART1_SRC2 "uart1_rx"
|
||||
#define DMACH_UART2 "uart2_tx"
|
||||
#define DMACH_UART2_SRC2 "uart2_rx"
|
||||
#define DMACH_UART3 "uart3_tx"
|
||||
#define DMACH_UART3_SRC2 "uart3_rx"
|
||||
#define DMACH_PCM0_TX "pcm0_tx"
|
||||
#define DMACH_PCM0_RX "pcm0_rx"
|
||||
#define DMACH_I2S0_OUT "i2s0_tx"
|
||||
#define DMACH_I2S0_IN "i2s0_rx"
|
||||
#define DMACH_SPI0_TX S3C64XX_DMA_CHAN("spi0_tx")
|
||||
#define DMACH_SPI0_RX S3C64XX_DMA_CHAN("spi0_rx")
|
||||
#define DMACH_HSI_I2SV40_TX S3C64XX_DMA_CHAN("i2s2_tx")
|
||||
#define DMACH_HSI_I2SV40_RX S3C64XX_DMA_CHAN("i2s2_rx")
|
||||
#define DMACH_HSI_I2SV40_TX "i2s2_tx"
|
||||
#define DMACH_HSI_I2SV40_RX "i2s2_rx"
|
||||
|
||||
/* DMA1/SDMA1 */
|
||||
#define DMACH_PCM1_TX S3C64XX_DMA_CHAN("pcm1_tx")
|
||||
#define DMACH_PCM1_RX S3C64XX_DMA_CHAN("pcm1_rx")
|
||||
#define DMACH_I2S1_OUT S3C64XX_DMA_CHAN("i2s1_tx")
|
||||
#define DMACH_I2S1_IN S3C64XX_DMA_CHAN("i2s1_rx")
|
||||
#define DMACH_PCM1_TX "pcm1_tx"
|
||||
#define DMACH_PCM1_RX "pcm1_rx"
|
||||
#define DMACH_I2S1_OUT "i2s1_tx"
|
||||
#define DMACH_I2S1_IN "i2s1_rx"
|
||||
#define DMACH_SPI1_TX S3C64XX_DMA_CHAN("spi1_tx")
|
||||
#define DMACH_SPI1_RX S3C64XX_DMA_CHAN("spi1_rx")
|
||||
#define DMACH_AC97_PCMOUT S3C64XX_DMA_CHAN("ac97_out")
|
||||
#define DMACH_AC97_PCMIN S3C64XX_DMA_CHAN("ac97_in")
|
||||
#define DMACH_AC97_MICIN S3C64XX_DMA_CHAN("ac97_mic")
|
||||
#define DMACH_PWM S3C64XX_DMA_CHAN("pwm")
|
||||
#define DMACH_IRDA S3C64XX_DMA_CHAN("irda")
|
||||
#define DMACH_EXTERNAL S3C64XX_DMA_CHAN("external")
|
||||
#define DMACH_SECURITY_RX S3C64XX_DMA_CHAN("sec_rx")
|
||||
#define DMACH_SECURITY_TX S3C64XX_DMA_CHAN("sec_tx")
|
||||
#define DMACH_AC97_PCMOUT "ac97_out"
|
||||
#define DMACH_AC97_PCMIN "ac97_in"
|
||||
#define DMACH_AC97_MICIN "ac97_mic"
|
||||
#define DMACH_PWM "pwm"
|
||||
#define DMACH_IRDA "irda"
|
||||
#define DMACH_EXTERNAL "external"
|
||||
#define DMACH_SECURITY_RX "sec_rx"
|
||||
#define DMACH_SECURITY_TX "sec_tx"
|
||||
|
||||
enum dma_ch {
|
||||
DMACH_MAX = 32
|
||||
|
|
|
@ -65,6 +65,7 @@
|
|||
#include <linux/platform_data/usb-ohci-s3c2410.h>
|
||||
#include <plat/usb-phy.h>
|
||||
#include <plat/regs-spi.h>
|
||||
#include <linux/platform_data/asoc-s3c.h>
|
||||
#include <linux/platform_data/spi-s3c64xx.h>
|
||||
|
||||
static u64 samsung_device_dma_mask = DMA_BIT_MASK(32);
|
||||
|
@ -74,9 +75,12 @@ static u64 samsung_device_dma_mask = DMA_BIT_MASK(32);
|
|||
static struct resource s3c_ac97_resource[] = {
|
||||
[0] = DEFINE_RES_MEM(S3C2440_PA_AC97, S3C2440_SZ_AC97),
|
||||
[1] = DEFINE_RES_IRQ(IRQ_S3C244X_AC97),
|
||||
[2] = DEFINE_RES_DMA_NAMED(DMACH_PCM_OUT, "PCM out"),
|
||||
[3] = DEFINE_RES_DMA_NAMED(DMACH_PCM_IN, "PCM in"),
|
||||
[4] = DEFINE_RES_DMA_NAMED(DMACH_MIC_IN, "Mic in"),
|
||||
};
|
||||
|
||||
static struct s3c_audio_pdata s3c_ac97_pdata = {
|
||||
.dma_playback = (void *)DMACH_PCM_OUT,
|
||||
.dma_capture = (void *)DMACH_PCM_IN,
|
||||
.dma_capture_mic = (void *)DMACH_MIC_IN,
|
||||
};
|
||||
|
||||
struct platform_device s3c_device_ac97 = {
|
||||
|
@ -87,6 +91,7 @@ struct platform_device s3c_device_ac97 = {
|
|||
.dev = {
|
||||
.dma_mask = &samsung_device_dma_mask,
|
||||
.coherent_dma_mask = DMA_BIT_MASK(32),
|
||||
.platform_data = &s3c_ac97_pdata,
|
||||
}
|
||||
};
|
||||
#endif /* CONFIG_CPU_S3C2440 */
|
||||
|
|
|
@ -1 +1,5 @@
|
|||
#ifdef CONFIG_CPU_BIG_ENDIAN
|
||||
#define CONFIG_CPU_ENDIAN_BE8 CONFIG_CPU_BIG_ENDIAN
|
||||
#endif
|
||||
|
||||
#include <../../arm/include/asm/opcodes.h>
|
||||
|
|
|
@ -186,20 +186,21 @@ static void clear_regs_spsr_ss(struct pt_regs *regs)
|
|||
|
||||
/* EL1 Single Step Handler hooks */
|
||||
static LIST_HEAD(step_hook);
|
||||
static DEFINE_RWLOCK(step_hook_lock);
|
||||
static DEFINE_SPINLOCK(step_hook_lock);
|
||||
|
||||
void register_step_hook(struct step_hook *hook)
|
||||
{
|
||||
write_lock(&step_hook_lock);
|
||||
list_add(&hook->node, &step_hook);
|
||||
write_unlock(&step_hook_lock);
|
||||
spin_lock(&step_hook_lock);
|
||||
list_add_rcu(&hook->node, &step_hook);
|
||||
spin_unlock(&step_hook_lock);
|
||||
}
|
||||
|
||||
void unregister_step_hook(struct step_hook *hook)
|
||||
{
|
||||
write_lock(&step_hook_lock);
|
||||
list_del(&hook->node);
|
||||
write_unlock(&step_hook_lock);
|
||||
spin_lock(&step_hook_lock);
|
||||
list_del_rcu(&hook->node);
|
||||
spin_unlock(&step_hook_lock);
|
||||
synchronize_rcu();
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -213,15 +214,15 @@ static int call_step_hook(struct pt_regs *regs, unsigned int esr)
|
|||
struct step_hook *hook;
|
||||
int retval = DBG_HOOK_ERROR;
|
||||
|
||||
read_lock(&step_hook_lock);
|
||||
rcu_read_lock();
|
||||
|
||||
list_for_each_entry(hook, &step_hook, node) {
|
||||
list_for_each_entry_rcu(hook, &step_hook, node) {
|
||||
retval = hook->fn(regs, esr);
|
||||
if (retval == DBG_HOOK_HANDLED)
|
||||
break;
|
||||
}
|
||||
|
||||
read_unlock(&step_hook_lock);
|
||||
rcu_read_unlock();
|
||||
|
||||
return retval;
|
||||
}
|
||||
|
|
|
@ -21,9 +21,8 @@
|
|||
#include <linux/const.h>
|
||||
#include <asm/page.h>
|
||||
|
||||
__PAGE_ALIGNED_DATA
|
||||
|
||||
.globl vdso_start, vdso_end
|
||||
.section .rodata
|
||||
.balign PAGE_SIZE
|
||||
vdso_start:
|
||||
.incbin "arch/arm64/kernel/vdso/vdso.so"
|
||||
|
|
|
@ -436,6 +436,7 @@ static inline void __iomem * ioremap_cache (unsigned long phys_addr, unsigned lo
|
|||
return ioremap(phys_addr, size);
|
||||
}
|
||||
#define ioremap_cache ioremap_cache
|
||||
#define ioremap_uc ioremap_nocache
|
||||
|
||||
|
||||
/*
|
||||
|
|
|
@ -503,15 +503,15 @@ int __init db1000_dev_setup(void)
|
|||
if (board == BCSR_WHOAMI_DB1500) {
|
||||
c0 = AU1500_GPIO2_INT;
|
||||
c1 = AU1500_GPIO5_INT;
|
||||
d0 = AU1500_GPIO0_INT;
|
||||
d1 = AU1500_GPIO3_INT;
|
||||
d0 = 0; /* GPIO number, NOT irq! */
|
||||
d1 = 3; /* GPIO number, NOT irq! */
|
||||
s0 = AU1500_GPIO1_INT;
|
||||
s1 = AU1500_GPIO4_INT;
|
||||
} else if (board == BCSR_WHOAMI_DB1100) {
|
||||
c0 = AU1100_GPIO2_INT;
|
||||
c1 = AU1100_GPIO5_INT;
|
||||
d0 = AU1100_GPIO0_INT;
|
||||
d1 = AU1100_GPIO3_INT;
|
||||
d0 = 0; /* GPIO number, NOT irq! */
|
||||
d1 = 3; /* GPIO number, NOT irq! */
|
||||
s0 = AU1100_GPIO1_INT;
|
||||
s1 = AU1100_GPIO4_INT;
|
||||
|
||||
|
@ -545,15 +545,15 @@ int __init db1000_dev_setup(void)
|
|||
} else if (board == BCSR_WHOAMI_DB1000) {
|
||||
c0 = AU1000_GPIO2_INT;
|
||||
c1 = AU1000_GPIO5_INT;
|
||||
d0 = AU1000_GPIO0_INT;
|
||||
d1 = AU1000_GPIO3_INT;
|
||||
d0 = 0; /* GPIO number, NOT irq! */
|
||||
d1 = 3; /* GPIO number, NOT irq! */
|
||||
s0 = AU1000_GPIO1_INT;
|
||||
s1 = AU1000_GPIO4_INT;
|
||||
platform_add_devices(db1000_devs, ARRAY_SIZE(db1000_devs));
|
||||
} else if ((board == BCSR_WHOAMI_PB1500) ||
|
||||
(board == BCSR_WHOAMI_PB1500R2)) {
|
||||
c0 = AU1500_GPIO203_INT;
|
||||
d0 = AU1500_GPIO201_INT;
|
||||
d0 = 1; /* GPIO number, NOT irq! */
|
||||
s0 = AU1500_GPIO202_INT;
|
||||
twosocks = 0;
|
||||
flashsize = 64;
|
||||
|
@ -566,7 +566,7 @@ int __init db1000_dev_setup(void)
|
|||
*/
|
||||
} else if (board == BCSR_WHOAMI_PB1100) {
|
||||
c0 = AU1100_GPIO11_INT;
|
||||
d0 = AU1100_GPIO9_INT;
|
||||
d0 = 9; /* GPIO number, NOT irq! */
|
||||
s0 = AU1100_GPIO10_INT;
|
||||
twosocks = 0;
|
||||
flashsize = 64;
|
||||
|
@ -583,7 +583,6 @@ int __init db1000_dev_setup(void)
|
|||
} else
|
||||
return 0; /* unknown board, no further dev setup to do */
|
||||
|
||||
irq_set_irq_type(d0, IRQ_TYPE_EDGE_BOTH);
|
||||
irq_set_irq_type(c0, IRQ_TYPE_LEVEL_LOW);
|
||||
irq_set_irq_type(s0, IRQ_TYPE_LEVEL_LOW);
|
||||
|
||||
|
@ -597,7 +596,6 @@ int __init db1000_dev_setup(void)
|
|||
c0, d0, /*s0*/0, 0, 0);
|
||||
|
||||
if (twosocks) {
|
||||
irq_set_irq_type(d1, IRQ_TYPE_EDGE_BOTH);
|
||||
irq_set_irq_type(c1, IRQ_TYPE_LEVEL_LOW);
|
||||
irq_set_irq_type(s1, IRQ_TYPE_LEVEL_LOW);
|
||||
|
||||
|
|
|
@ -514,7 +514,7 @@ static void __init db1550_devices(void)
|
|||
AU1000_PCMCIA_MEM_PHYS_ADDR + 0x000400000 - 1,
|
||||
AU1000_PCMCIA_IO_PHYS_ADDR,
|
||||
AU1000_PCMCIA_IO_PHYS_ADDR + 0x000010000 - 1,
|
||||
AU1550_GPIO3_INT, AU1550_GPIO0_INT,
|
||||
AU1550_GPIO3_INT, 0,
|
||||
/*AU1550_GPIO21_INT*/0, 0, 0);
|
||||
|
||||
db1x_register_pcmcia_socket(
|
||||
|
@ -524,7 +524,7 @@ static void __init db1550_devices(void)
|
|||
AU1000_PCMCIA_MEM_PHYS_ADDR + 0x004400000 - 1,
|
||||
AU1000_PCMCIA_IO_PHYS_ADDR + 0x004000000,
|
||||
AU1000_PCMCIA_IO_PHYS_ADDR + 0x004010000 - 1,
|
||||
AU1550_GPIO5_INT, AU1550_GPIO1_INT,
|
||||
AU1550_GPIO5_INT, 1,
|
||||
/*AU1550_GPIO22_INT*/0, 0, 1);
|
||||
|
||||
platform_device_register(&db1550_nand_dev);
|
||||
|
|
|
@ -885,7 +885,7 @@ static void emulate_load_store_insn(struct pt_regs *regs,
|
|||
{
|
||||
union mips_instruction insn;
|
||||
unsigned long value;
|
||||
unsigned int res;
|
||||
unsigned int res, preempted;
|
||||
unsigned long origpc;
|
||||
unsigned long orig31;
|
||||
void __user *fault_addr = NULL;
|
||||
|
@ -1226,27 +1226,36 @@ static void emulate_load_store_insn(struct pt_regs *regs,
|
|||
if (!access_ok(VERIFY_READ, addr, sizeof(*fpr)))
|
||||
goto sigbus;
|
||||
|
||||
/*
|
||||
* Disable preemption to avoid a race between copying
|
||||
* state from userland, migrating to another CPU and
|
||||
* updating the hardware vector register below.
|
||||
*/
|
||||
preempt_disable();
|
||||
do {
|
||||
/*
|
||||
* If we have live MSA context keep track of
|
||||
* whether we get preempted in order to avoid
|
||||
* the register context we load being clobbered
|
||||
* by the live context as it's saved during
|
||||
* preemption. If we don't have live context
|
||||
* then it can't be saved to clobber the value
|
||||
* we load.
|
||||
*/
|
||||
preempted = test_thread_flag(TIF_USEDMSA);
|
||||
|
||||
res = __copy_from_user_inatomic(fpr, addr,
|
||||
sizeof(*fpr));
|
||||
if (res)
|
||||
goto fault;
|
||||
res = __copy_from_user_inatomic(fpr, addr,
|
||||
sizeof(*fpr));
|
||||
if (res)
|
||||
goto fault;
|
||||
|
||||
/*
|
||||
* Update the hardware register if it is in use by the
|
||||
* task in this quantum, in order to avoid having to
|
||||
* save & restore the whole vector context.
|
||||
*/
|
||||
if (test_thread_flag(TIF_USEDMSA))
|
||||
write_msa_wr(wd, fpr, df);
|
||||
|
||||
preempt_enable();
|
||||
/*
|
||||
* Update the hardware register if it is in use
|
||||
* by the task in this quantum, in order to
|
||||
* avoid having to save & restore the whole
|
||||
* vector context.
|
||||
*/
|
||||
preempt_disable();
|
||||
if (test_thread_flag(TIF_USEDMSA)) {
|
||||
write_msa_wr(wd, fpr, df);
|
||||
preempted = 0;
|
||||
}
|
||||
preempt_enable();
|
||||
} while (preempted);
|
||||
break;
|
||||
|
||||
case msa_st_op:
|
||||
|
|
|
@ -76,6 +76,7 @@ struct exception_table_entry {
|
|||
*/
|
||||
struct exception_data {
|
||||
unsigned long fault_ip;
|
||||
unsigned long fault_gp;
|
||||
unsigned long fault_space;
|
||||
unsigned long fault_addr;
|
||||
};
|
||||
|
|
|
@ -299,6 +299,7 @@ int main(void)
|
|||
#endif
|
||||
BLANK();
|
||||
DEFINE(EXCDATA_IP, offsetof(struct exception_data, fault_ip));
|
||||
DEFINE(EXCDATA_GP, offsetof(struct exception_data, fault_gp));
|
||||
DEFINE(EXCDATA_SPACE, offsetof(struct exception_data, fault_space));
|
||||
DEFINE(EXCDATA_ADDR, offsetof(struct exception_data, fault_addr));
|
||||
BLANK();
|
||||
|
|
|
@ -47,11 +47,11 @@ EXPORT_SYMBOL(__cmpxchg_u64);
|
|||
EXPORT_SYMBOL(lclear_user);
|
||||
EXPORT_SYMBOL(lstrnlen_user);
|
||||
|
||||
/* Global fixups */
|
||||
extern void fixup_get_user_skip_1(void);
|
||||
extern void fixup_get_user_skip_2(void);
|
||||
extern void fixup_put_user_skip_1(void);
|
||||
extern void fixup_put_user_skip_2(void);
|
||||
/* Global fixups - defined as int to avoid creation of function pointers */
|
||||
extern int fixup_get_user_skip_1;
|
||||
extern int fixup_get_user_skip_2;
|
||||
extern int fixup_put_user_skip_1;
|
||||
extern int fixup_put_user_skip_2;
|
||||
EXPORT_SYMBOL(fixup_get_user_skip_1);
|
||||
EXPORT_SYMBOL(fixup_get_user_skip_2);
|
||||
EXPORT_SYMBOL(fixup_put_user_skip_1);
|
||||
|
|
|
@ -798,6 +798,9 @@ void notrace handle_interruption(int code, struct pt_regs *regs)
|
|||
|
||||
if (fault_space == 0 && !faulthandler_disabled())
|
||||
{
|
||||
/* Clean up and return if in exception table. */
|
||||
if (fixup_exception(regs))
|
||||
return;
|
||||
pdc_chassis_send_status(PDC_CHASSIS_DIRECT_PANIC);
|
||||
parisc_terminate("Kernel Fault", regs, code, fault_address);
|
||||
}
|
||||
|
|
|
@ -26,6 +26,7 @@
|
|||
|
||||
#ifdef CONFIG_SMP
|
||||
.macro get_fault_ip t1 t2
|
||||
loadgp
|
||||
addil LT%__per_cpu_offset,%r27
|
||||
LDREG RT%__per_cpu_offset(%r1),\t1
|
||||
/* t2 = smp_processor_id() */
|
||||
|
@ -40,14 +41,19 @@
|
|||
LDREG RT%exception_data(%r1),\t1
|
||||
/* t1 = this_cpu_ptr(&exception_data) */
|
||||
add,l \t1,\t2,\t1
|
||||
/* %r27 = t1->fault_gp - restore gp */
|
||||
LDREG EXCDATA_GP(\t1), %r27
|
||||
/* t1 = t1->fault_ip */
|
||||
LDREG EXCDATA_IP(\t1), \t1
|
||||
.endm
|
||||
#else
|
||||
.macro get_fault_ip t1 t2
|
||||
loadgp
|
||||
/* t1 = this_cpu_ptr(&exception_data) */
|
||||
addil LT%exception_data,%r27
|
||||
LDREG RT%exception_data(%r1),\t2
|
||||
/* %r27 = t2->fault_gp - restore gp */
|
||||
LDREG EXCDATA_GP(\t2), %r27
|
||||
/* t1 = t2->fault_ip */
|
||||
LDREG EXCDATA_IP(\t2), \t1
|
||||
.endm
|
||||
|
|
|
@ -151,6 +151,7 @@ int fixup_exception(struct pt_regs *regs)
|
|||
struct exception_data *d;
|
||||
d = this_cpu_ptr(&exception_data);
|
||||
d->fault_ip = regs->iaoq[0];
|
||||
d->fault_gp = regs->gr[27];
|
||||
d->fault_space = regs->isr;
|
||||
d->fault_addr = regs->ior;
|
||||
|
||||
|
|
|
@ -486,13 +486,13 @@ static void hugepd_free(struct mmu_gather *tlb, void *hugepte)
|
|||
{
|
||||
struct hugepd_freelist **batchp;
|
||||
|
||||
batchp = this_cpu_ptr(&hugepd_freelist_cur);
|
||||
batchp = &get_cpu_var(hugepd_freelist_cur);
|
||||
|
||||
if (atomic_read(&tlb->mm->mm_users) < 2 ||
|
||||
cpumask_equal(mm_cpumask(tlb->mm),
|
||||
cpumask_of(smp_processor_id()))) {
|
||||
kmem_cache_free(hugepte_cache, hugepte);
|
||||
put_cpu_var(hugepd_freelist_cur);
|
||||
put_cpu_var(hugepd_freelist_cur);
|
||||
return;
|
||||
}
|
||||
|
||||
|
|
|
@ -45,7 +45,7 @@ struct zpci_fmb {
|
|||
u64 rpcit_ops;
|
||||
u64 dma_rbytes;
|
||||
u64 dma_wbytes;
|
||||
} __packed __aligned(16);
|
||||
} __packed __aligned(64);
|
||||
|
||||
enum zpci_state {
|
||||
ZPCI_FN_STATE_RESERVED,
|
||||
|
|
|
@ -1197,114 +1197,12 @@ cleanup_critical:
|
|||
.quad .Lpsw_idle_lpsw
|
||||
|
||||
.Lcleanup_save_fpu_regs:
|
||||
TSTMSK __LC_CPU_FLAGS,_CIF_FPU
|
||||
bor %r14
|
||||
clg %r9,BASED(.Lcleanup_save_fpu_regs_done)
|
||||
jhe 5f
|
||||
clg %r9,BASED(.Lcleanup_save_fpu_regs_fp)
|
||||
jhe 4f
|
||||
clg %r9,BASED(.Lcleanup_save_fpu_regs_vx_high)
|
||||
jhe 3f
|
||||
clg %r9,BASED(.Lcleanup_save_fpu_regs_vx_low)
|
||||
jhe 2f
|
||||
clg %r9,BASED(.Lcleanup_save_fpu_fpc_end)
|
||||
jhe 1f
|
||||
lg %r2,__LC_CURRENT
|
||||
aghi %r2,__TASK_thread
|
||||
0: # Store floating-point controls
|
||||
stfpc __THREAD_FPU_fpc(%r2)
|
||||
1: # Load register save area and check if VX is active
|
||||
lg %r3,__THREAD_FPU_regs(%r2)
|
||||
TSTMSK __LC_MACHINE_FLAGS,MACHINE_FLAG_VX
|
||||
jz 4f # no VX -> store FP regs
|
||||
2: # Store vector registers (V0-V15)
|
||||
VSTM %v0,%v15,0,%r3 # vstm 0,15,0(3)
|
||||
3: # Store vector registers (V16-V31)
|
||||
VSTM %v16,%v31,256,%r3 # vstm 16,31,256(3)
|
||||
j 5f # -> done, set CIF_FPU flag
|
||||
4: # Store floating-point registers
|
||||
std 0,0(%r3)
|
||||
std 1,8(%r3)
|
||||
std 2,16(%r3)
|
||||
std 3,24(%r3)
|
||||
std 4,32(%r3)
|
||||
std 5,40(%r3)
|
||||
std 6,48(%r3)
|
||||
std 7,56(%r3)
|
||||
std 8,64(%r3)
|
||||
std 9,72(%r3)
|
||||
std 10,80(%r3)
|
||||
std 11,88(%r3)
|
||||
std 12,96(%r3)
|
||||
std 13,104(%r3)
|
||||
std 14,112(%r3)
|
||||
std 15,120(%r3)
|
||||
5: # Set CIF_FPU flag
|
||||
oi __LC_CPU_FLAGS+7,_CIF_FPU
|
||||
lg %r9,48(%r11) # return from save_fpu_regs
|
||||
larl %r9,save_fpu_regs
|
||||
br %r14
|
||||
.Lcleanup_save_fpu_fpc_end:
|
||||
.quad .Lsave_fpu_regs_fpc_end
|
||||
.Lcleanup_save_fpu_regs_vx_low:
|
||||
.quad .Lsave_fpu_regs_vx_low
|
||||
.Lcleanup_save_fpu_regs_vx_high:
|
||||
.quad .Lsave_fpu_regs_vx_high
|
||||
.Lcleanup_save_fpu_regs_fp:
|
||||
.quad .Lsave_fpu_regs_fp
|
||||
.Lcleanup_save_fpu_regs_done:
|
||||
.quad .Lsave_fpu_regs_done
|
||||
|
||||
.Lcleanup_load_fpu_regs:
|
||||
TSTMSK __LC_CPU_FLAGS,_CIF_FPU
|
||||
bnor %r14
|
||||
clg %r9,BASED(.Lcleanup_load_fpu_regs_done)
|
||||
jhe 1f
|
||||
clg %r9,BASED(.Lcleanup_load_fpu_regs_fp)
|
||||
jhe 2f
|
||||
clg %r9,BASED(.Lcleanup_load_fpu_regs_vx_high)
|
||||
jhe 3f
|
||||
clg %r9,BASED(.Lcleanup_load_fpu_regs_vx)
|
||||
jhe 4f
|
||||
lg %r4,__LC_CURRENT
|
||||
aghi %r4,__TASK_thread
|
||||
lfpc __THREAD_FPU_fpc(%r4)
|
||||
TSTMSK __LC_MACHINE_FLAGS,MACHINE_FLAG_VX
|
||||
lg %r4,__THREAD_FPU_regs(%r4) # %r4 <- reg save area
|
||||
jz 2f # -> no VX, load FP regs
|
||||
4: # Load V0 ..V15 registers
|
||||
VLM %v0,%v15,0,%r4
|
||||
3: # Load V16..V31 registers
|
||||
VLM %v16,%v31,256,%r4
|
||||
j 1f
|
||||
2: # Load floating-point registers
|
||||
ld 0,0(%r4)
|
||||
ld 1,8(%r4)
|
||||
ld 2,16(%r4)
|
||||
ld 3,24(%r4)
|
||||
ld 4,32(%r4)
|
||||
ld 5,40(%r4)
|
||||
ld 6,48(%r4)
|
||||
ld 7,56(%r4)
|
||||
ld 8,64(%r4)
|
||||
ld 9,72(%r4)
|
||||
ld 10,80(%r4)
|
||||
ld 11,88(%r4)
|
||||
ld 12,96(%r4)
|
||||
ld 13,104(%r4)
|
||||
ld 14,112(%r4)
|
||||
ld 15,120(%r4)
|
||||
1: # Clear CIF_FPU bit
|
||||
ni __LC_CPU_FLAGS+7,255-_CIF_FPU
|
||||
lg %r9,48(%r11) # return from load_fpu_regs
|
||||
larl %r9,load_fpu_regs
|
||||
br %r14
|
||||
.Lcleanup_load_fpu_regs_vx:
|
||||
.quad .Lload_fpu_regs_vx
|
||||
.Lcleanup_load_fpu_regs_vx_high:
|
||||
.quad .Lload_fpu_regs_vx_high
|
||||
.Lcleanup_load_fpu_regs_fp:
|
||||
.quad .Lload_fpu_regs_fp
|
||||
.Lcleanup_load_fpu_regs_done:
|
||||
.quad .Lload_fpu_regs_done
|
||||
|
||||
/*
|
||||
* Integer constants
|
||||
|
|
|
@ -16,7 +16,7 @@
|
|||
|
||||
__HEAD
|
||||
ENTRY(startup_continue)
|
||||
tm __LC_STFL_FAC_LIST+6,0x80 # LPP available ?
|
||||
tm __LC_STFL_FAC_LIST+5,0x80 # LPP available ?
|
||||
jz 0f
|
||||
xc __LC_LPP+1(7,0),__LC_LPP+1 # clear lpp and current_pid
|
||||
mvi __LC_LPP,0x80 # and set LPP_MAGIC
|
||||
|
|
|
@ -329,6 +329,7 @@ static void __init setup_lowcore(void)
|
|||
+ PAGE_SIZE - STACK_FRAME_OVERHEAD - sizeof(struct pt_regs);
|
||||
lc->current_task = (unsigned long) init_thread_union.thread_info.task;
|
||||
lc->thread_info = (unsigned long) &init_thread_union;
|
||||
lc->lpp = LPP_MAGIC;
|
||||
lc->machine_flags = S390_lowcore.machine_flags;
|
||||
lc->stfl_fac_list = S390_lowcore.stfl_fac_list;
|
||||
memcpy(lc->stfle_fac_list, S390_lowcore.stfle_fac_list,
|
||||
|
|
|
@ -871,8 +871,11 @@ static inline int barsize(u8 size)
|
|||
|
||||
static int zpci_mem_init(void)
|
||||
{
|
||||
BUILD_BUG_ON(!is_power_of_2(__alignof__(struct zpci_fmb)) ||
|
||||
__alignof__(struct zpci_fmb) < sizeof(struct zpci_fmb));
|
||||
|
||||
zdev_fmb_cache = kmem_cache_create("PCI_FMB_cache", sizeof(struct zpci_fmb),
|
||||
16, 0, NULL);
|
||||
__alignof__(struct zpci_fmb), 0, NULL);
|
||||
if (!zdev_fmb_cache)
|
||||
goto error_zdev;
|
||||
|
||||
|
|
|
@ -36,6 +36,7 @@ void *kmap_coherent(struct page *page, unsigned long addr)
|
|||
|
||||
BUG_ON(!test_bit(PG_dcache_clean, &page->flags));
|
||||
|
||||
preempt_disable();
|
||||
pagefault_disable();
|
||||
|
||||
idx = FIX_CMAP_END -
|
||||
|
@ -64,4 +65,5 @@ void kunmap_coherent(void *kvaddr)
|
|||
}
|
||||
|
||||
pagefault_enable();
|
||||
preempt_enable();
|
||||
}
|
||||
|
|
|
@ -133,7 +133,7 @@ void mconsole_proc(struct mc_request *req)
|
|||
ptr += strlen("proc");
|
||||
ptr = skip_spaces(ptr);
|
||||
|
||||
file = file_open_root(mnt->mnt_root, mnt, ptr, O_RDONLY);
|
||||
file = file_open_root(mnt->mnt_root, mnt, ptr, O_RDONLY, 0);
|
||||
if (IS_ERR(file)) {
|
||||
mconsole_reply(req, "Failed to open file", 1, 0);
|
||||
printk(KERN_ERR "open /proc/%s: %ld\n", ptr, PTR_ERR(file));
|
||||
|
|
|
@ -1146,22 +1146,23 @@ config MICROCODE
|
|||
bool "CPU microcode loading support"
|
||||
default y
|
||||
depends on CPU_SUP_AMD || CPU_SUP_INTEL
|
||||
depends on BLK_DEV_INITRD
|
||||
select FW_LOADER
|
||||
---help---
|
||||
|
||||
If you say Y here, you will be able to update the microcode on
|
||||
certain Intel and AMD processors. The Intel support is for the
|
||||
IA32 family, e.g. Pentium Pro, Pentium II, Pentium III, Pentium 4,
|
||||
Xeon etc. The AMD support is for families 0x10 and later. You will
|
||||
obviously need the actual microcode binary data itself which is not
|
||||
shipped with the Linux kernel.
|
||||
Intel and AMD processors. The Intel support is for the IA32 family,
|
||||
e.g. Pentium Pro, Pentium II, Pentium III, Pentium 4, Xeon etc. The
|
||||
AMD support is for families 0x10 and later. You will obviously need
|
||||
the actual microcode binary data itself which is not shipped with
|
||||
the Linux kernel.
|
||||
|
||||
This option selects the general module only, you need to select
|
||||
at least one vendor specific module as well.
|
||||
The preferred method to load microcode from a detached initrd is described
|
||||
in Documentation/x86/early-microcode.txt. For that you need to enable
|
||||
CONFIG_BLK_DEV_INITRD in order for the loader to be able to scan the
|
||||
initrd for microcode blobs.
|
||||
|
||||
To compile this driver as a module, choose M here: the module
|
||||
will be called microcode.
|
||||
In addition, you can build-in the microcode into the kernel. For that you
|
||||
need to enable FIRMWARE_IN_KERNEL and add the vendor-supplied microcode
|
||||
to the CONFIG_EXTRA_FIRMWARE config option.
|
||||
|
||||
config MICROCODE_INTEL
|
||||
bool "Intel microcode loading support"
|
||||
|
|
|
@ -268,6 +268,7 @@ static void exit_to_usermode_loop(struct pt_regs *regs, u32 cached_flags)
|
|||
/* Called with IRQs disabled. */
|
||||
__visible inline void prepare_exit_to_usermode(struct pt_regs *regs)
|
||||
{
|
||||
struct thread_info *ti = pt_regs_to_thread_info(regs);
|
||||
u32 cached_flags;
|
||||
|
||||
if (IS_ENABLED(CONFIG_PROVE_LOCKING) && WARN_ON(!irqs_disabled()))
|
||||
|
@ -275,12 +276,22 @@ __visible inline void prepare_exit_to_usermode(struct pt_regs *regs)
|
|||
|
||||
lockdep_sys_exit();
|
||||
|
||||
cached_flags =
|
||||
READ_ONCE(pt_regs_to_thread_info(regs)->flags);
|
||||
cached_flags = READ_ONCE(ti->flags);
|
||||
|
||||
if (unlikely(cached_flags & EXIT_TO_USERMODE_LOOP_FLAGS))
|
||||
exit_to_usermode_loop(regs, cached_flags);
|
||||
|
||||
#ifdef CONFIG_COMPAT
|
||||
/*
|
||||
* Compat syscalls set TS_COMPAT. Make sure we clear it before
|
||||
* returning to user mode. We need to clear it *after* signal
|
||||
* handling, because syscall restart has a fixup for compat
|
||||
* syscalls. The fixup is exercised by the ptrace_syscall_32
|
||||
* selftest.
|
||||
*/
|
||||
ti->status &= ~TS_COMPAT;
|
||||
#endif
|
||||
|
||||
user_enter();
|
||||
}
|
||||
|
||||
|
@ -332,14 +343,6 @@ __visible inline void syscall_return_slowpath(struct pt_regs *regs)
|
|||
if (unlikely(cached_flags & SYSCALL_EXIT_WORK_FLAGS))
|
||||
syscall_slow_exit_work(regs, cached_flags);
|
||||
|
||||
#ifdef CONFIG_COMPAT
|
||||
/*
|
||||
* Compat syscalls set TS_COMPAT. Make sure we clear it before
|
||||
* returning to user mode.
|
||||
*/
|
||||
ti->status &= ~TS_COMPAT;
|
||||
#endif
|
||||
|
||||
local_irq_disable();
|
||||
prepare_exit_to_usermode(regs);
|
||||
}
|
||||
|
|
|
@ -638,8 +638,8 @@ static inline void entering_irq(void)
|
|||
|
||||
static inline void entering_ack_irq(void)
|
||||
{
|
||||
ack_APIC_irq();
|
||||
entering_irq();
|
||||
ack_APIC_irq();
|
||||
}
|
||||
|
||||
static inline void ipi_entering_ack_irq(void)
|
||||
|
|
|
@ -136,6 +136,7 @@ struct irq_alloc_info {
|
|||
struct irq_cfg {
|
||||
unsigned int dest_apicid;
|
||||
u8 vector;
|
||||
u8 old_vector;
|
||||
};
|
||||
|
||||
extern struct irq_cfg *irq_cfg(unsigned int irq);
|
||||
|
|
|
@ -41,7 +41,7 @@
|
|||
|
||||
#define KVM_PIO_PAGE_OFFSET 1
|
||||
#define KVM_COALESCED_MMIO_PAGE_OFFSET 2
|
||||
#define KVM_HALT_POLL_NS_DEFAULT 500000
|
||||
#define KVM_HALT_POLL_NS_DEFAULT 400000
|
||||
|
||||
#define KVM_IRQCHIP_NUM_PINS KVM_IOAPIC_NUM_PINS
|
||||
|
||||
|
|
|
@ -2,6 +2,7 @@
|
|||
#define _ASM_X86_MICROCODE_H
|
||||
|
||||
#include <linux/earlycpio.h>
|
||||
#include <linux/initrd.h>
|
||||
|
||||
#define native_rdmsr(msr, val1, val2) \
|
||||
do { \
|
||||
|
@ -168,4 +169,29 @@ static inline void reload_early_microcode(void) { }
|
|||
static inline bool
|
||||
get_builtin_firmware(struct cpio_data *cd, const char *name) { return false; }
|
||||
#endif
|
||||
|
||||
static inline unsigned long get_initrd_start(void)
|
||||
{
|
||||
#ifdef CONFIG_BLK_DEV_INITRD
|
||||
return initrd_start;
|
||||
#else
|
||||
return 0;
|
||||
#endif
|
||||
}
|
||||
|
||||
static inline unsigned long get_initrd_start_addr(void)
|
||||
{
|
||||
#ifdef CONFIG_BLK_DEV_INITRD
|
||||
#ifdef CONFIG_X86_32
|
||||
unsigned long *initrd_start_p = (unsigned long *)__pa_nodebug(&initrd_start);
|
||||
|
||||
return (unsigned long)__pa_nodebug(*initrd_start_p);
|
||||
#else
|
||||
return get_initrd_start();
|
||||
#endif
|
||||
#else /* CONFIG_BLK_DEV_INITRD */
|
||||
return 0;
|
||||
#endif
|
||||
}
|
||||
|
||||
#endif /* _ASM_X86_MICROCODE_H */
|
||||
|
|
|
@ -93,6 +93,8 @@ extern raw_spinlock_t pci_config_lock;
|
|||
extern int (*pcibios_enable_irq)(struct pci_dev *dev);
|
||||
extern void (*pcibios_disable_irq)(struct pci_dev *dev);
|
||||
|
||||
extern bool mp_should_keep_irq(struct device *dev);
|
||||
|
||||
struct pci_raw_ops {
|
||||
int (*read)(unsigned int domain, unsigned int bus, unsigned int devfn,
|
||||
int reg, int len, u32 *val);
|
||||
|
|
|
@ -165,6 +165,7 @@ struct x86_pmu_capability {
|
|||
#define GLOBAL_STATUS_ASIF BIT_ULL(60)
|
||||
#define GLOBAL_STATUS_COUNTERS_FROZEN BIT_ULL(59)
|
||||
#define GLOBAL_STATUS_LBRS_FROZEN BIT_ULL(58)
|
||||
#define GLOBAL_STATUS_TRACE_TOPAPMI BIT_ULL(55)
|
||||
|
||||
/*
|
||||
* IBS cpuid feature detection
|
||||
|
|
|
@ -62,4 +62,6 @@ void xen_arch_register_cpu(int num);
|
|||
void xen_arch_unregister_cpu(int num);
|
||||
#endif
|
||||
|
||||
extern void xen_set_iopl_mask(unsigned mask);
|
||||
|
||||
#endif /* _ASM_X86_XEN_HYPERVISOR_H */
|
||||
|
|
|
@ -211,6 +211,7 @@ update:
|
|||
*/
|
||||
cpumask_and(d->old_domain, d->old_domain, cpu_online_mask);
|
||||
d->move_in_progress = !cpumask_empty(d->old_domain);
|
||||
d->cfg.old_vector = d->move_in_progress ? d->cfg.vector : 0;
|
||||
d->cfg.vector = vector;
|
||||
cpumask_copy(d->domain, vector_cpumask);
|
||||
success:
|
||||
|
@ -653,46 +654,97 @@ void irq_complete_move(struct irq_cfg *cfg)
|
|||
}
|
||||
|
||||
/*
|
||||
* Called with @desc->lock held and interrupts disabled.
|
||||
* Called from fixup_irqs() with @desc->lock held and interrupts disabled.
|
||||
*/
|
||||
void irq_force_complete_move(struct irq_desc *desc)
|
||||
{
|
||||
struct irq_data *irqdata = irq_desc_get_irq_data(desc);
|
||||
struct apic_chip_data *data = apic_chip_data(irqdata);
|
||||
struct irq_cfg *cfg = data ? &data->cfg : NULL;
|
||||
unsigned int cpu;
|
||||
|
||||
if (!cfg)
|
||||
return;
|
||||
|
||||
__irq_complete_move(cfg, cfg->vector);
|
||||
|
||||
/*
|
||||
* This is tricky. If the cleanup of @data->old_domain has not been
|
||||
* done yet, then the following setaffinity call will fail with
|
||||
* -EBUSY. This can leave the interrupt in a stale state.
|
||||
*
|
||||
* The cleanup cannot make progress because we hold @desc->lock. So in
|
||||
* case @data->old_domain is not yet cleaned up, we need to drop the
|
||||
* lock and acquire it again. @desc cannot go away, because the
|
||||
* hotplug code holds the sparse irq lock.
|
||||
* All CPUs are stuck in stop machine with interrupts disabled so
|
||||
* calling __irq_complete_move() would be completely pointless.
|
||||
*/
|
||||
raw_spin_lock(&vector_lock);
|
||||
/* Clean out all offline cpus (including ourself) first. */
|
||||
/*
|
||||
* Clean out all offline cpus (including the outgoing one) from the
|
||||
* old_domain mask.
|
||||
*/
|
||||
cpumask_and(data->old_domain, data->old_domain, cpu_online_mask);
|
||||
while (!cpumask_empty(data->old_domain)) {
|
||||
|
||||
/*
|
||||
* If move_in_progress is cleared and the old_domain mask is empty,
|
||||
* then there is nothing to cleanup. fixup_irqs() will take care of
|
||||
* the stale vectors on the outgoing cpu.
|
||||
*/
|
||||
if (!data->move_in_progress && cpumask_empty(data->old_domain)) {
|
||||
raw_spin_unlock(&vector_lock);
|
||||
raw_spin_unlock(&desc->lock);
|
||||
cpu_relax();
|
||||
raw_spin_lock(&desc->lock);
|
||||
/*
|
||||
* Reevaluate apic_chip_data. It might have been cleared after
|
||||
* we dropped @desc->lock.
|
||||
*/
|
||||
data = apic_chip_data(irqdata);
|
||||
if (!data)
|
||||
return;
|
||||
raw_spin_lock(&vector_lock);
|
||||
return;
|
||||
}
|
||||
|
||||
/*
|
||||
* 1) The interrupt is in move_in_progress state. That means that we
|
||||
* have not seen an interrupt since the io_apic was reprogrammed to
|
||||
* the new vector.
|
||||
*
|
||||
* 2) The interrupt has fired on the new vector, but the cleanup IPIs
|
||||
* have not been processed yet.
|
||||
*/
|
||||
if (data->move_in_progress) {
|
||||
/*
|
||||
* In theory there is a race:
|
||||
*
|
||||
* set_ioapic(new_vector) <-- Interrupt is raised before update
|
||||
* is effective, i.e. it's raised on
|
||||
* the old vector.
|
||||
*
|
||||
* So if the target cpu cannot handle that interrupt before
|
||||
* the old vector is cleaned up, we get a spurious interrupt
|
||||
* and in the worst case the ioapic irq line becomes stale.
|
||||
*
|
||||
* But in case of cpu hotplug this should be a non issue
|
||||
* because if the affinity update happens right before all
|
||||
* cpus rendevouz in stop machine, there is no way that the
|
||||
* interrupt can be blocked on the target cpu because all cpus
|
||||
* loops first with interrupts enabled in stop machine, so the
|
||||
* old vector is not yet cleaned up when the interrupt fires.
|
||||
*
|
||||
* So the only way to run into this issue is if the delivery
|
||||
* of the interrupt on the apic/system bus would be delayed
|
||||
* beyond the point where the target cpu disables interrupts
|
||||
* in stop machine. I doubt that it can happen, but at least
|
||||
* there is a theroretical chance. Virtualization might be
|
||||
* able to expose this, but AFAICT the IOAPIC emulation is not
|
||||
* as stupid as the real hardware.
|
||||
*
|
||||
* Anyway, there is nothing we can do about that at this point
|
||||
* w/o refactoring the whole fixup_irq() business completely.
|
||||
* We print at least the irq number and the old vector number,
|
||||
* so we have the necessary information when a problem in that
|
||||
* area arises.
|
||||
*/
|
||||
pr_warn("IRQ fixup: irq %d move in progress, old vector %d\n",
|
||||
irqdata->irq, cfg->old_vector);
|
||||
}
|
||||
/*
|
||||
* If old_domain is not empty, then other cpus still have the irq
|
||||
* descriptor set in their vector array. Clean it up.
|
||||
*/
|
||||
for_each_cpu(cpu, data->old_domain)
|
||||
per_cpu(vector_irq, cpu)[cfg->old_vector] = VECTOR_UNUSED;
|
||||
|
||||
/* Cleanup the left overs of the (half finished) move */
|
||||
cpumask_clear(data->old_domain);
|
||||
data->move_in_progress = 0;
|
||||
raw_spin_unlock(&vector_lock);
|
||||
}
|
||||
#endif
|
||||
|
|
|
@ -555,10 +555,14 @@ scan_microcode(struct mc_saved_data *mc_saved_data, unsigned long *initrd,
|
|||
cd.data = NULL;
|
||||
cd.size = 0;
|
||||
|
||||
cd = find_cpio_data(p, (void *)start, size, &offset);
|
||||
if (!cd.data) {
|
||||
/* try built-in microcode if no initrd */
|
||||
if (!size) {
|
||||
if (!load_builtin_intel_microcode(&cd))
|
||||
return UCODE_ERROR;
|
||||
} else {
|
||||
cd = find_cpio_data(p, (void *)start, size, &offset);
|
||||
if (!cd.data)
|
||||
return UCODE_ERROR;
|
||||
}
|
||||
|
||||
return get_matching_model_microcode(0, start, cd.data, cd.size,
|
||||
|
@ -694,7 +698,7 @@ int __init save_microcode_in_initrd_intel(void)
|
|||
if (count == 0)
|
||||
return ret;
|
||||
|
||||
copy_initrd_ptrs(mc_saved, mc_saved_in_initrd, initrd_start, count);
|
||||
copy_initrd_ptrs(mc_saved, mc_saved_in_initrd, get_initrd_start(), count);
|
||||
ret = save_microcode(&mc_saved_data, mc_saved, count);
|
||||
if (ret)
|
||||
pr_err("Cannot save microcode patches from initrd.\n");
|
||||
|
@ -732,16 +736,20 @@ void __init load_ucode_intel_bsp(void)
|
|||
struct boot_params *p;
|
||||
|
||||
p = (struct boot_params *)__pa_nodebug(&boot_params);
|
||||
start = p->hdr.ramdisk_image;
|
||||
size = p->hdr.ramdisk_size;
|
||||
|
||||
_load_ucode_intel_bsp(
|
||||
(struct mc_saved_data *)__pa_nodebug(&mc_saved_data),
|
||||
(unsigned long *)__pa_nodebug(&mc_saved_in_initrd),
|
||||
start, size);
|
||||
/*
|
||||
* Set start only if we have an initrd image. We cannot use initrd_start
|
||||
* because it is not set that early yet.
|
||||
*/
|
||||
start = (size ? p->hdr.ramdisk_image : 0);
|
||||
|
||||
_load_ucode_intel_bsp((struct mc_saved_data *)__pa_nodebug(&mc_saved_data),
|
||||
(unsigned long *)__pa_nodebug(&mc_saved_in_initrd),
|
||||
start, size);
|
||||
#else
|
||||
start = boot_params.hdr.ramdisk_image + PAGE_OFFSET;
|
||||
size = boot_params.hdr.ramdisk_size;
|
||||
start = (size ? boot_params.hdr.ramdisk_image + PAGE_OFFSET : 0);
|
||||
|
||||
_load_ucode_intel_bsp(&mc_saved_data, mc_saved_in_initrd, start, size);
|
||||
#endif
|
||||
|
@ -752,20 +760,14 @@ void load_ucode_intel_ap(void)
|
|||
struct mc_saved_data *mc_saved_data_p;
|
||||
struct ucode_cpu_info uci;
|
||||
unsigned long *mc_saved_in_initrd_p;
|
||||
unsigned long initrd_start_addr;
|
||||
enum ucode_state ret;
|
||||
#ifdef CONFIG_X86_32
|
||||
unsigned long *initrd_start_p;
|
||||
|
||||
mc_saved_in_initrd_p =
|
||||
(unsigned long *)__pa_nodebug(mc_saved_in_initrd);
|
||||
mc_saved_in_initrd_p = (unsigned long *)__pa_nodebug(mc_saved_in_initrd);
|
||||
mc_saved_data_p = (struct mc_saved_data *)__pa_nodebug(&mc_saved_data);
|
||||
initrd_start_p = (unsigned long *)__pa_nodebug(&initrd_start);
|
||||
initrd_start_addr = (unsigned long)__pa_nodebug(*initrd_start_p);
|
||||
#else
|
||||
mc_saved_data_p = &mc_saved_data;
|
||||
mc_saved_in_initrd_p = mc_saved_in_initrd;
|
||||
initrd_start_addr = initrd_start;
|
||||
mc_saved_data_p = &mc_saved_data;
|
||||
#endif
|
||||
|
||||
/*
|
||||
|
@ -777,7 +779,7 @@ void load_ucode_intel_ap(void)
|
|||
|
||||
collect_cpu_info_early(&uci);
|
||||
ret = load_microcode(mc_saved_data_p, mc_saved_in_initrd_p,
|
||||
initrd_start_addr, &uci);
|
||||
get_initrd_start_addr(), &uci);
|
||||
|
||||
if (ret != UCODE_OK)
|
||||
return;
|
||||
|
|
|
@ -593,6 +593,19 @@ void x86_pmu_disable_all(void)
|
|||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* There may be PMI landing after enabled=0. The PMI hitting could be before or
|
||||
* after disable_all.
|
||||
*
|
||||
* If PMI hits before disable_all, the PMU will be disabled in the NMI handler.
|
||||
* It will not be re-enabled in the NMI handler again, because enabled=0. After
|
||||
* handling the NMI, disable_all will be called, which will not change the
|
||||
* state either. If PMI hits after disable_all, the PMU is already disabled
|
||||
* before entering NMI handler. The NMI handler will not change the state
|
||||
* either.
|
||||
*
|
||||
* So either situation is harmless.
|
||||
*/
|
||||
static void x86_pmu_disable(struct pmu *pmu)
|
||||
{
|
||||
struct cpu_hw_events *cpuc = this_cpu_ptr(&cpu_hw_events);
|
||||
|
|
|
@ -591,6 +591,7 @@ struct x86_pmu {
|
|||
pebs_active :1,
|
||||
pebs_broken :1;
|
||||
int pebs_record_size;
|
||||
int pebs_buffer_size;
|
||||
void (*drain_pebs)(struct pt_regs *regs);
|
||||
struct event_constraint *pebs_constraints;
|
||||
void (*pebs_aliases)(struct perf_event *event);
|
||||
|
@ -907,6 +908,8 @@ void intel_pmu_lbr_init_hsw(void);
|
|||
|
||||
void intel_pmu_lbr_init_skl(void);
|
||||
|
||||
void intel_pmu_pebs_data_source_nhm(void);
|
||||
|
||||
int intel_pmu_setup_lbr_filter(struct perf_event *event);
|
||||
|
||||
void intel_pt_interrupt(void);
|
||||
|
|
|
@ -1458,7 +1458,15 @@ static __initconst const u64 slm_hw_cache_event_ids
|
|||
};
|
||||
|
||||
/*
|
||||
* Use from PMIs where the LBRs are already disabled.
|
||||
* Used from PMIs where the LBRs are already disabled.
|
||||
*
|
||||
* This function could be called consecutively. It is required to remain in
|
||||
* disabled state if called consecutively.
|
||||
*
|
||||
* During consecutive calls, the same disable value will be written to related
|
||||
* registers, so the PMU state remains unchanged. hw.state in
|
||||
* intel_bts_disable_local will remain PERF_HES_STOPPED too in consecutive
|
||||
* calls.
|
||||
*/
|
||||
static void __intel_pmu_disable_all(void)
|
||||
{
|
||||
|
@ -1840,6 +1848,16 @@ again:
|
|||
if (__test_and_clear_bit(62, (unsigned long *)&status)) {
|
||||
handled++;
|
||||
x86_pmu.drain_pebs(regs);
|
||||
/*
|
||||
* There are cases where, even though, the PEBS ovfl bit is set
|
||||
* in GLOBAL_OVF_STATUS, the PEBS events may also have their
|
||||
* overflow bits set for their counters. We must clear them
|
||||
* here because they have been processed as exact samples in
|
||||
* the drain_pebs() routine. They must not be processed again
|
||||
* in the for_each_bit_set() loop for regular samples below.
|
||||
*/
|
||||
status &= ~cpuc->pebs_enabled;
|
||||
status &= x86_pmu.intel_ctrl | GLOBAL_STATUS_TRACE_TOPAPMI;
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -1885,7 +1903,10 @@ again:
|
|||
goto again;
|
||||
|
||||
done:
|
||||
__intel_pmu_enable_all(0, true);
|
||||
/* Only restore PMU state when it's active. See x86_pmu_disable(). */
|
||||
if (cpuc->enabled)
|
||||
__intel_pmu_enable_all(0, true);
|
||||
|
||||
/*
|
||||
* Only unmask the NMI after the overflow counters
|
||||
* have been reset. This avoids spurious NMIs on
|
||||
|
@ -3315,6 +3336,7 @@ __init int intel_pmu_init(void)
|
|||
intel_perfmon_event_map[PERF_COUNT_HW_STALLED_CYCLES_BACKEND] =
|
||||
X86_CONFIG(.event=0xb1, .umask=0x3f, .inv=1, .cmask=1);
|
||||
|
||||
intel_pmu_pebs_data_source_nhm();
|
||||
x86_add_quirk(intel_nehalem_quirk);
|
||||
|
||||
pr_cont("Nehalem events, ");
|
||||
|
@ -3377,6 +3399,7 @@ __init int intel_pmu_init(void)
|
|||
intel_perfmon_event_map[PERF_COUNT_HW_STALLED_CYCLES_BACKEND] =
|
||||
X86_CONFIG(.event=0xb1, .umask=0x3f, .inv=1, .cmask=1);
|
||||
|
||||
intel_pmu_pebs_data_source_nhm();
|
||||
pr_cont("Westmere events, ");
|
||||
break;
|
||||
|
||||
|
|
|
@ -51,7 +51,8 @@ union intel_x86_pebs_dse {
|
|||
#define OP_LH (P(OP, LOAD) | P(LVL, HIT))
|
||||
#define SNOOP_NONE_MISS (P(SNOOP, NONE) | P(SNOOP, MISS))
|
||||
|
||||
static const u64 pebs_data_source[] = {
|
||||
/* Version for Sandy Bridge and later */
|
||||
static u64 pebs_data_source[] = {
|
||||
P(OP, LOAD) | P(LVL, MISS) | P(LVL, L3) | P(SNOOP, NA),/* 0x00:ukn L3 */
|
||||
OP_LH | P(LVL, L1) | P(SNOOP, NONE), /* 0x01: L1 local */
|
||||
OP_LH | P(LVL, LFB) | P(SNOOP, NONE), /* 0x02: LFB hit */
|
||||
|
@ -70,6 +71,14 @@ static const u64 pebs_data_source[] = {
|
|||
OP_LH | P(LVL, UNC) | P(SNOOP, NONE), /* 0x0f: uncached */
|
||||
};
|
||||
|
||||
/* Patch up minor differences in the bits */
|
||||
void __init intel_pmu_pebs_data_source_nhm(void)
|
||||
{
|
||||
pebs_data_source[0x05] = OP_LH | P(LVL, L3) | P(SNOOP, HIT);
|
||||
pebs_data_source[0x06] = OP_LH | P(LVL, L3) | P(SNOOP, HITM);
|
||||
pebs_data_source[0x07] = OP_LH | P(LVL, L3) | P(SNOOP, HITM);
|
||||
}
|
||||
|
||||
static u64 precise_store_data(u64 status)
|
||||
{
|
||||
union intel_x86_pebs_dse dse;
|
||||
|
@ -269,7 +278,7 @@ static int alloc_pebs_buffer(int cpu)
|
|||
if (!x86_pmu.pebs)
|
||||
return 0;
|
||||
|
||||
buffer = kzalloc_node(PEBS_BUFFER_SIZE, GFP_KERNEL, node);
|
||||
buffer = kzalloc_node(x86_pmu.pebs_buffer_size, GFP_KERNEL, node);
|
||||
if (unlikely(!buffer))
|
||||
return -ENOMEM;
|
||||
|
||||
|
@ -286,7 +295,7 @@ static int alloc_pebs_buffer(int cpu)
|
|||
per_cpu(insn_buffer, cpu) = ibuffer;
|
||||
}
|
||||
|
||||
max = PEBS_BUFFER_SIZE / x86_pmu.pebs_record_size;
|
||||
max = x86_pmu.pebs_buffer_size / x86_pmu.pebs_record_size;
|
||||
|
||||
ds->pebs_buffer_base = (u64)(unsigned long)buffer;
|
||||
ds->pebs_index = ds->pebs_buffer_base;
|
||||
|
@ -1296,6 +1305,7 @@ void __init intel_ds_init(void)
|
|||
|
||||
x86_pmu.bts = boot_cpu_has(X86_FEATURE_BTS);
|
||||
x86_pmu.pebs = boot_cpu_has(X86_FEATURE_PEBS);
|
||||
x86_pmu.pebs_buffer_size = PEBS_BUFFER_SIZE;
|
||||
if (x86_pmu.pebs) {
|
||||
char pebs_type = x86_pmu.intel_cap.pebs_trap ? '+' : '-';
|
||||
int format = x86_pmu.intel_cap.pebs_format;
|
||||
|
@ -1304,6 +1314,14 @@ void __init intel_ds_init(void)
|
|||
case 0:
|
||||
printk(KERN_CONT "PEBS fmt0%c, ", pebs_type);
|
||||
x86_pmu.pebs_record_size = sizeof(struct pebs_record_core);
|
||||
/*
|
||||
* Using >PAGE_SIZE buffers makes the WRMSR to
|
||||
* PERF_GLOBAL_CTRL in intel_pmu_enable_all()
|
||||
* mysteriously hang on Core2.
|
||||
*
|
||||
* As a workaround, we don't do this.
|
||||
*/
|
||||
x86_pmu.pebs_buffer_size = PAGE_SIZE;
|
||||
x86_pmu.drain_pebs = intel_pmu_drain_pebs_core;
|
||||
break;
|
||||
|
||||
|
|
|
@ -263,7 +263,9 @@ again:
|
|||
goto again;
|
||||
|
||||
done:
|
||||
knc_pmu_enable_all(0);
|
||||
/* Only restore PMU state when it's active. See x86_pmu_disable(). */
|
||||
if (cpuc->enabled)
|
||||
knc_pmu_enable_all(0);
|
||||
|
||||
return handled;
|
||||
}
|
||||
|
|
|
@ -96,9 +96,14 @@ asmlinkage long sys_ioperm(unsigned long from, unsigned long num, int turn_on)
|
|||
SYSCALL_DEFINE1(iopl, unsigned int, level)
|
||||
{
|
||||
struct pt_regs *regs = current_pt_regs();
|
||||
unsigned int old = (regs->flags >> 12) & 3;
|
||||
struct thread_struct *t = ¤t->thread;
|
||||
|
||||
/*
|
||||
* Careful: the IOPL bits in regs->flags are undefined under Xen PV
|
||||
* and changing them has no effect.
|
||||
*/
|
||||
unsigned int old = t->iopl >> X86_EFLAGS_IOPL_BIT;
|
||||
|
||||
if (level > 3)
|
||||
return -EINVAL;
|
||||
/* Trying to gain more privileges? */
|
||||
|
@ -106,8 +111,9 @@ SYSCALL_DEFINE1(iopl, unsigned int, level)
|
|||
if (!capable(CAP_SYS_RAWIO))
|
||||
return -EPERM;
|
||||
}
|
||||
regs->flags = (regs->flags & ~X86_EFLAGS_IOPL) | (level << 12);
|
||||
t->iopl = level << 12;
|
||||
regs->flags = (regs->flags & ~X86_EFLAGS_IOPL) |
|
||||
(level << X86_EFLAGS_IOPL_BIT);
|
||||
t->iopl = level << X86_EFLAGS_IOPL_BIT;
|
||||
set_iopl_mask(t->iopl);
|
||||
|
||||
return 0;
|
||||
|
|
|
@ -48,6 +48,7 @@
|
|||
#include <asm/syscalls.h>
|
||||
#include <asm/debugreg.h>
|
||||
#include <asm/switch_to.h>
|
||||
#include <asm/xen/hypervisor.h>
|
||||
|
||||
asmlinkage extern void ret_from_fork(void);
|
||||
|
||||
|
@ -411,6 +412,17 @@ __switch_to(struct task_struct *prev_p, struct task_struct *next_p)
|
|||
task_thread_info(prev_p)->flags & _TIF_WORK_CTXSW_PREV))
|
||||
__switch_to_xtra(prev_p, next_p, tss);
|
||||
|
||||
#ifdef CONFIG_XEN
|
||||
/*
|
||||
* On Xen PV, IOPL bits in pt_regs->flags have no effect, and
|
||||
* current_pt_regs()->flags may not match the current task's
|
||||
* intended IOPL. We need to switch it manually.
|
||||
*/
|
||||
if (unlikely(static_cpu_has(X86_FEATURE_XENPV) &&
|
||||
prev->iopl != next->iopl))
|
||||
xen_set_iopl_mask(next->iopl);
|
||||
#endif
|
||||
|
||||
if (static_cpu_has_bug(X86_BUG_SYSRET_SS_ATTRS)) {
|
||||
/*
|
||||
* AMD CPUs have a misfeature: SYSRET sets the SS selector but
|
||||
|
|
|
@ -245,7 +245,7 @@ static void kvm_pit_ack_irq(struct kvm_irq_ack_notifier *kian)
|
|||
* PIC is being reset. Handle it gracefully here
|
||||
*/
|
||||
atomic_inc(&ps->pending);
|
||||
else if (value > 0)
|
||||
else if (value > 0 && ps->reinject)
|
||||
/* in this case, we had multiple outstanding pit interrupts
|
||||
* that we needed to inject. Reinject
|
||||
*/
|
||||
|
@ -288,7 +288,9 @@ static void pit_do_work(struct kthread_work *work)
|
|||
* last one has been acked.
|
||||
*/
|
||||
spin_lock(&ps->inject_lock);
|
||||
if (ps->irq_ack) {
|
||||
if (!ps->reinject)
|
||||
inject = 1;
|
||||
else if (ps->irq_ack) {
|
||||
ps->irq_ack = 0;
|
||||
inject = 1;
|
||||
}
|
||||
|
@ -317,10 +319,10 @@ static enum hrtimer_restart pit_timer_fn(struct hrtimer *data)
|
|||
struct kvm_kpit_state *ps = container_of(data, struct kvm_kpit_state, timer);
|
||||
struct kvm_pit *pt = ps->kvm->arch.vpit;
|
||||
|
||||
if (ps->reinject || !atomic_read(&ps->pending)) {
|
||||
if (ps->reinject)
|
||||
atomic_inc(&ps->pending);
|
||||
queue_kthread_work(&pt->worker, &pt->expired);
|
||||
}
|
||||
|
||||
queue_kthread_work(&pt->worker, &pt->expired);
|
||||
|
||||
if (ps->is_periodic) {
|
||||
hrtimer_add_expires_ns(&ps->timer, ps->period);
|
||||
|
|
|
@ -2637,8 +2637,15 @@ static void nested_vmx_setup_ctls_msrs(struct vcpu_vmx *vmx)
|
|||
} else
|
||||
vmx->nested.nested_vmx_ept_caps = 0;
|
||||
|
||||
/*
|
||||
* Old versions of KVM use the single-context version without
|
||||
* checking for support, so declare that it is supported even
|
||||
* though it is treated as global context. The alternative is
|
||||
* not failing the single-context invvpid, and it is worse.
|
||||
*/
|
||||
if (enable_vpid)
|
||||
vmx->nested.nested_vmx_vpid_caps = VMX_VPID_INVVPID_BIT |
|
||||
VMX_VPID_EXTENT_SINGLE_CONTEXT_BIT |
|
||||
VMX_VPID_EXTENT_GLOBAL_CONTEXT_BIT;
|
||||
else
|
||||
vmx->nested.nested_vmx_vpid_caps = 0;
|
||||
|
@ -7340,6 +7347,7 @@ static int handle_invept(struct kvm_vcpu *vcpu)
|
|||
if (!(types & (1UL << type))) {
|
||||
nested_vmx_failValid(vcpu,
|
||||
VMXERR_INVALID_OPERAND_TO_INVEPT_INVVPID);
|
||||
skip_emulated_instruction(vcpu);
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
@ -7398,6 +7406,7 @@ static int handle_invvpid(struct kvm_vcpu *vcpu)
|
|||
if (!(types & (1UL << type))) {
|
||||
nested_vmx_failValid(vcpu,
|
||||
VMXERR_INVALID_OPERAND_TO_INVEPT_INVVPID);
|
||||
skip_emulated_instruction(vcpu);
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
@ -7414,12 +7423,17 @@ static int handle_invvpid(struct kvm_vcpu *vcpu)
|
|||
}
|
||||
|
||||
switch (type) {
|
||||
case VMX_VPID_EXTENT_SINGLE_CONTEXT:
|
||||
/*
|
||||
* Old versions of KVM use the single-context version so we
|
||||
* have to support it; just treat it the same as all-context.
|
||||
*/
|
||||
case VMX_VPID_EXTENT_ALL_CONTEXT:
|
||||
__vmx_flush_tlb(vcpu, to_vmx(vcpu)->nested.vpid02);
|
||||
nested_vmx_succeed(vcpu);
|
||||
break;
|
||||
default:
|
||||
/* Trap single context invalidation invvpid calls */
|
||||
/* Trap individual address invalidation invvpid calls */
|
||||
BUG_ON(1);
|
||||
break;
|
||||
}
|
||||
|
|
|
@ -2736,6 +2736,7 @@ void kvm_arch_vcpu_load(struct kvm_vcpu *vcpu, int cpu)
|
|||
}
|
||||
|
||||
kvm_make_request(KVM_REQ_STEAL_UPDATE, vcpu);
|
||||
vcpu->arch.switch_db_regs |= KVM_DEBUGREG_RELOAD;
|
||||
}
|
||||
|
||||
void kvm_arch_vcpu_put(struct kvm_vcpu *vcpu)
|
||||
|
@ -6023,12 +6024,10 @@ static int inject_pending_event(struct kvm_vcpu *vcpu, bool req_int_win)
|
|||
}
|
||||
|
||||
/* try to inject new event if pending */
|
||||
if (vcpu->arch.nmi_pending) {
|
||||
if (kvm_x86_ops->nmi_allowed(vcpu)) {
|
||||
--vcpu->arch.nmi_pending;
|
||||
vcpu->arch.nmi_injected = true;
|
||||
kvm_x86_ops->set_nmi(vcpu);
|
||||
}
|
||||
if (vcpu->arch.nmi_pending && kvm_x86_ops->nmi_allowed(vcpu)) {
|
||||
--vcpu->arch.nmi_pending;
|
||||
vcpu->arch.nmi_injected = true;
|
||||
kvm_x86_ops->set_nmi(vcpu);
|
||||
} else if (kvm_cpu_has_injectable_intr(vcpu)) {
|
||||
/*
|
||||
* Because interrupts can be injected asynchronously, we are
|
||||
|
@ -6473,10 +6472,12 @@ static int vcpu_enter_guest(struct kvm_vcpu *vcpu)
|
|||
if (inject_pending_event(vcpu, req_int_win) != 0)
|
||||
req_immediate_exit = true;
|
||||
/* enable NMI/IRQ window open exits if needed */
|
||||
else if (vcpu->arch.nmi_pending)
|
||||
kvm_x86_ops->enable_nmi_window(vcpu);
|
||||
else if (kvm_cpu_has_injectable_intr(vcpu) || req_int_win)
|
||||
kvm_x86_ops->enable_irq_window(vcpu);
|
||||
else {
|
||||
if (vcpu->arch.nmi_pending)
|
||||
kvm_x86_ops->enable_nmi_window(vcpu);
|
||||
if (kvm_cpu_has_injectable_intr(vcpu) || req_int_win)
|
||||
kvm_x86_ops->enable_irq_window(vcpu);
|
||||
}
|
||||
|
||||
if (kvm_lapic_enabled(vcpu)) {
|
||||
update_cr8_intercept(vcpu);
|
||||
|
|
|
@ -106,8 +106,6 @@ static void flush_tlb_func(void *info)
|
|||
|
||||
if (f->flush_mm != this_cpu_read(cpu_tlbstate.active_mm))
|
||||
return;
|
||||
if (!f->flush_end)
|
||||
f->flush_end = f->flush_start + PAGE_SIZE;
|
||||
|
||||
count_vm_tlb_event(NR_TLB_REMOTE_FLUSH_RECEIVED);
|
||||
if (this_cpu_read(cpu_tlbstate.state) == TLBSTATE_OK) {
|
||||
|
@ -135,12 +133,20 @@ void native_flush_tlb_others(const struct cpumask *cpumask,
|
|||
unsigned long end)
|
||||
{
|
||||
struct flush_tlb_info info;
|
||||
|
||||
if (end == 0)
|
||||
end = start + PAGE_SIZE;
|
||||
info.flush_mm = mm;
|
||||
info.flush_start = start;
|
||||
info.flush_end = end;
|
||||
|
||||
count_vm_tlb_event(NR_TLB_REMOTE_FLUSH);
|
||||
trace_tlb_flush(TLB_REMOTE_SEND_IPI, end - start);
|
||||
if (end == TLB_FLUSH_ALL)
|
||||
trace_tlb_flush(TLB_REMOTE_SEND_IPI, TLB_FLUSH_ALL);
|
||||
else
|
||||
trace_tlb_flush(TLB_REMOTE_SEND_IPI,
|
||||
(end - start) >> PAGE_SHIFT);
|
||||
|
||||
if (is_uv_system()) {
|
||||
unsigned int cpu;
|
||||
|
||||
|
|
|
@ -673,28 +673,22 @@ int pcibios_add_device(struct pci_dev *dev)
|
|||
return 0;
|
||||
}
|
||||
|
||||
int pcibios_alloc_irq(struct pci_dev *dev)
|
||||
{
|
||||
/*
|
||||
* If the PCI device was already claimed by core code and has
|
||||
* MSI enabled, probing of the pcibios IRQ will overwrite
|
||||
* dev->irq. So bail out if MSI is already enabled.
|
||||
*/
|
||||
if (pci_dev_msi_enabled(dev))
|
||||
return -EBUSY;
|
||||
|
||||
return pcibios_enable_irq(dev);
|
||||
}
|
||||
|
||||
void pcibios_free_irq(struct pci_dev *dev)
|
||||
{
|
||||
if (pcibios_disable_irq)
|
||||
pcibios_disable_irq(dev);
|
||||
}
|
||||
|
||||
int pcibios_enable_device(struct pci_dev *dev, int mask)
|
||||
{
|
||||
return pci_enable_resources(dev, mask);
|
||||
int err;
|
||||
|
||||
if ((err = pci_enable_resources(dev, mask)) < 0)
|
||||
return err;
|
||||
|
||||
if (!pci_dev_msi_enabled(dev))
|
||||
return pcibios_enable_irq(dev);
|
||||
return 0;
|
||||
}
|
||||
|
||||
void pcibios_disable_device (struct pci_dev *dev)
|
||||
{
|
||||
if (!pci_dev_msi_enabled(dev) && pcibios_disable_irq)
|
||||
pcibios_disable_irq(dev);
|
||||
}
|
||||
|
||||
int pci_ext_cfg_avail(void)
|
||||
|
|
|
@ -540,3 +540,10 @@ static void twinhead_reserve_killing_zone(struct pci_dev *dev)
|
|||
}
|
||||
}
|
||||
DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, 0x27B9, twinhead_reserve_killing_zone);
|
||||
|
||||
static void pci_bdwep_bar(struct pci_dev *dev)
|
||||
{
|
||||
dev->non_compliant_bars = 1;
|
||||
}
|
||||
DECLARE_PCI_FIXUP_EARLY(PCI_VENDOR_ID_INTEL, 0x6fa0, pci_bdwep_bar);
|
||||
DECLARE_PCI_FIXUP_EARLY(PCI_VENDOR_ID_INTEL, 0x6fc0, pci_bdwep_bar);
|
||||
|
|
|
@ -215,7 +215,7 @@ static int intel_mid_pci_irq_enable(struct pci_dev *dev)
|
|||
int polarity;
|
||||
int ret;
|
||||
|
||||
if (pci_has_managed_irq(dev))
|
||||
if (dev->irq_managed && dev->irq > 0)
|
||||
return 0;
|
||||
|
||||
switch (intel_mid_identify_cpu()) {
|
||||
|
@ -256,13 +256,10 @@ static int intel_mid_pci_irq_enable(struct pci_dev *dev)
|
|||
|
||||
static void intel_mid_pci_irq_disable(struct pci_dev *dev)
|
||||
{
|
||||
if (pci_has_managed_irq(dev)) {
|
||||
if (!mp_should_keep_irq(&dev->dev) && dev->irq_managed &&
|
||||
dev->irq > 0) {
|
||||
mp_unmap_irq(dev->irq);
|
||||
dev->irq_managed = 0;
|
||||
/*
|
||||
* Don't reset dev->irq here, otherwise
|
||||
* intel_mid_pci_irq_enable() will fail on next call.
|
||||
*/
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -1202,7 +1202,7 @@ static int pirq_enable_irq(struct pci_dev *dev)
|
|||
struct pci_dev *temp_dev;
|
||||
int irq;
|
||||
|
||||
if (pci_has_managed_irq(dev))
|
||||
if (dev->irq_managed && dev->irq > 0)
|
||||
return 0;
|
||||
|
||||
irq = IO_APIC_get_PCI_irq_vector(dev->bus->number,
|
||||
|
@ -1230,7 +1230,8 @@ static int pirq_enable_irq(struct pci_dev *dev)
|
|||
}
|
||||
dev = temp_dev;
|
||||
if (irq >= 0) {
|
||||
pci_set_managed_irq(dev, irq);
|
||||
dev->irq_managed = 1;
|
||||
dev->irq = irq;
|
||||
dev_info(&dev->dev, "PCI->APIC IRQ transform: "
|
||||
"INT %c -> IRQ %d\n", 'A' + pin - 1, irq);
|
||||
return 0;
|
||||
|
@ -1256,10 +1257,24 @@ static int pirq_enable_irq(struct pci_dev *dev)
|
|||
return 0;
|
||||
}
|
||||
|
||||
bool mp_should_keep_irq(struct device *dev)
|
||||
{
|
||||
if (dev->power.is_prepared)
|
||||
return true;
|
||||
#ifdef CONFIG_PM
|
||||
if (dev->power.runtime_status == RPM_SUSPENDING)
|
||||
return true;
|
||||
#endif
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
static void pirq_disable_irq(struct pci_dev *dev)
|
||||
{
|
||||
if (io_apic_assign_pci_irqs && pci_has_managed_irq(dev)) {
|
||||
if (io_apic_assign_pci_irqs && !mp_should_keep_irq(&dev->dev) &&
|
||||
dev->irq_managed && dev->irq) {
|
||||
mp_unmap_irq(dev->irq);
|
||||
pci_reset_managed_irq(dev);
|
||||
dev->irq = 0;
|
||||
dev->irq_managed = 0;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -961,7 +961,7 @@ static void xen_load_sp0(struct tss_struct *tss,
|
|||
tss->x86_tss.sp0 = thread->sp0;
|
||||
}
|
||||
|
||||
static void xen_set_iopl_mask(unsigned mask)
|
||||
void xen_set_iopl_mask(unsigned mask)
|
||||
{
|
||||
struct physdev_set_iopl set_iopl;
|
||||
|
||||
|
|
|
@ -128,7 +128,7 @@ ENTRY(_startup)
|
|||
wsr a0, icountlevel
|
||||
|
||||
.set _index, 0
|
||||
.rept XCHAL_NUM_DBREAK - 1
|
||||
.rept XCHAL_NUM_DBREAK
|
||||
wsr a0, SREG_DBREAKC + _index
|
||||
.set _index, _index + 1
|
||||
.endr
|
||||
|
|
|
@ -97,11 +97,11 @@ void clear_user_highpage(struct page *page, unsigned long vaddr)
|
|||
unsigned long paddr;
|
||||
void *kvaddr = coherent_kvaddr(page, TLBTEMP_BASE_1, vaddr, &paddr);
|
||||
|
||||
pagefault_disable();
|
||||
preempt_disable();
|
||||
kmap_invalidate_coherent(page, vaddr);
|
||||
set_bit(PG_arch_1, &page->flags);
|
||||
clear_page_alias(kvaddr, paddr);
|
||||
pagefault_enable();
|
||||
preempt_enable();
|
||||
}
|
||||
|
||||
void copy_user_highpage(struct page *dst, struct page *src,
|
||||
|
@ -113,11 +113,11 @@ void copy_user_highpage(struct page *dst, struct page *src,
|
|||
void *src_vaddr = coherent_kvaddr(src, TLBTEMP_BASE_2, vaddr,
|
||||
&src_paddr);
|
||||
|
||||
pagefault_disable();
|
||||
preempt_disable();
|
||||
kmap_invalidate_coherent(dst, vaddr);
|
||||
set_bit(PG_arch_1, &dst->flags);
|
||||
copy_page_alias(dst_vaddr, src_vaddr, dst_paddr, src_paddr);
|
||||
pagefault_enable();
|
||||
preempt_enable();
|
||||
}
|
||||
|
||||
#endif /* DCACHE_WAY_SIZE > PAGE_SIZE */
|
||||
|
|
|
@ -100,21 +100,23 @@ static void rs_poll(unsigned long priv)
|
|||
{
|
||||
struct tty_port *port = (struct tty_port *)priv;
|
||||
int i = 0;
|
||||
int rd = 1;
|
||||
unsigned char c;
|
||||
|
||||
spin_lock(&timer_lock);
|
||||
|
||||
while (simc_poll(0)) {
|
||||
simc_read(0, &c, 1);
|
||||
rd = simc_read(0, &c, 1);
|
||||
if (rd <= 0)
|
||||
break;
|
||||
tty_insert_flip_char(port, c, TTY_NORMAL);
|
||||
i++;
|
||||
}
|
||||
|
||||
if (i)
|
||||
tty_flip_buffer_push(port);
|
||||
|
||||
|
||||
mod_timer(&serial_timer, jiffies + SERIAL_TIMER_VALUE);
|
||||
if (rd)
|
||||
mod_timer(&serial_timer, jiffies + SERIAL_TIMER_VALUE);
|
||||
spin_unlock(&timer_lock);
|
||||
}
|
||||
|
||||
|
|
|
@ -2218,7 +2218,7 @@ int blk_insert_cloned_request(struct request_queue *q, struct request *rq)
|
|||
if (q->mq_ops) {
|
||||
if (blk_queue_io_stat(q))
|
||||
blk_account_io_start(rq, true);
|
||||
blk_mq_insert_request(rq, false, true, true);
|
||||
blk_mq_insert_request(rq, false, true, false);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
|
@ -178,6 +178,8 @@ int pkcs7_validate_trust(struct pkcs7_message *pkcs7,
|
|||
int cached_ret = -ENOKEY;
|
||||
int ret;
|
||||
|
||||
*_trusted = false;
|
||||
|
||||
for (p = pkcs7->certs; p; p = p->next)
|
||||
p->seen = false;
|
||||
|
||||
|
|
|
@ -494,7 +494,7 @@ int x509_decode_time(time64_t *_t, size_t hdrlen,
|
|||
unsigned char tag,
|
||||
const unsigned char *value, size_t vlen)
|
||||
{
|
||||
static const unsigned char month_lengths[] = { 31, 29, 31, 30, 31, 30,
|
||||
static const unsigned char month_lengths[] = { 31, 28, 31, 30, 31, 30,
|
||||
31, 31, 30, 31, 30, 31 };
|
||||
const unsigned char *p = value;
|
||||
unsigned year, mon, day, hour, min, sec, mon_len;
|
||||
|
@ -540,9 +540,9 @@ int x509_decode_time(time64_t *_t, size_t hdrlen,
|
|||
if (year % 4 == 0) {
|
||||
mon_len = 29;
|
||||
if (year % 100 == 0) {
|
||||
year /= 100;
|
||||
if (year % 4 != 0)
|
||||
mon_len = 28;
|
||||
mon_len = 28;
|
||||
if (year % 400 == 0)
|
||||
mon_len = 29;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -212,7 +212,7 @@ static int crypto_kw_decrypt(struct blkcipher_desc *desc,
|
|||
SEMIBSIZE))
|
||||
ret = -EBADMSG;
|
||||
|
||||
memzero_explicit(&block, sizeof(struct crypto_kw_block));
|
||||
memzero_explicit(block, sizeof(struct crypto_kw_block));
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
@ -297,7 +297,7 @@ static int crypto_kw_encrypt(struct blkcipher_desc *desc,
|
|||
/* establish the IV for the caller to pick up */
|
||||
memcpy(desc->info, block->A, SEMIBSIZE);
|
||||
|
||||
memzero_explicit(&block, sizeof(struct crypto_kw_block));
|
||||
memzero_explicit(block, sizeof(struct crypto_kw_block));
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
|
|
@ -409,7 +409,7 @@ int acpi_pci_irq_enable(struct pci_dev *dev)
|
|||
return 0;
|
||||
}
|
||||
|
||||
if (pci_has_managed_irq(dev))
|
||||
if (dev->irq_managed && dev->irq > 0)
|
||||
return 0;
|
||||
|
||||
entry = acpi_pci_irq_lookup(dev, pin);
|
||||
|
@ -454,7 +454,8 @@ int acpi_pci_irq_enable(struct pci_dev *dev)
|
|||
kfree(entry);
|
||||
return rc;
|
||||
}
|
||||
pci_set_managed_irq(dev, rc);
|
||||
dev->irq = rc;
|
||||
dev->irq_managed = 1;
|
||||
|
||||
if (link)
|
||||
snprintf(link_desc, sizeof(link_desc), " -> Link[%s]", link);
|
||||
|
@ -477,9 +478,17 @@ void acpi_pci_irq_disable(struct pci_dev *dev)
|
|||
u8 pin;
|
||||
|
||||
pin = dev->pin;
|
||||
if (!pin || !pci_has_managed_irq(dev))
|
||||
if (!pin || !dev->irq_managed || dev->irq <= 0)
|
||||
return;
|
||||
|
||||
/* Keep IOAPIC pin configuration when suspending */
|
||||
if (dev->dev.power.is_prepared)
|
||||
return;
|
||||
#ifdef CONFIG_PM
|
||||
if (dev->dev.power.runtime_status == RPM_SUSPENDING)
|
||||
return;
|
||||
#endif
|
||||
|
||||
entry = acpi_pci_irq_lookup(dev, pin);
|
||||
if (!entry)
|
||||
return;
|
||||
|
@ -499,6 +508,6 @@ void acpi_pci_irq_disable(struct pci_dev *dev)
|
|||
dev_dbg(&dev->dev, "PCI INT %c disabled\n", pin_name(pin));
|
||||
if (gsi >= 0) {
|
||||
acpi_unregister_gsi(gsi);
|
||||
pci_reset_managed_irq(dev);
|
||||
dev->irq_managed = 0;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -26,8 +26,20 @@
|
|||
|
||||
#ifdef CONFIG_X86
|
||||
#define valid_IRQ(i) (((i) != 0) && ((i) != 2))
|
||||
static inline bool acpi_iospace_resource_valid(struct resource *res)
|
||||
{
|
||||
/* On X86 IO space is limited to the [0 - 64K] IO port range */
|
||||
return res->end < 0x10003;
|
||||
}
|
||||
#else
|
||||
#define valid_IRQ(i) (true)
|
||||
/*
|
||||
* ACPI IO descriptors on arches other than X86 contain MMIO CPU physical
|
||||
* addresses mapping IO space in CPU physical address space, IO space
|
||||
* resources can be placed anywhere in the 64-bit physical address space.
|
||||
*/
|
||||
static inline bool
|
||||
acpi_iospace_resource_valid(struct resource *res) { return true; }
|
||||
#endif
|
||||
|
||||
static bool acpi_dev_resource_len_valid(u64 start, u64 end, u64 len, bool io)
|
||||
|
@ -126,7 +138,7 @@ static void acpi_dev_ioresource_flags(struct resource *res, u64 len,
|
|||
if (!acpi_dev_resource_len_valid(res->start, res->end, len, true))
|
||||
res->flags |= IORESOURCE_DISABLED | IORESOURCE_UNSET;
|
||||
|
||||
if (res->end >= 0x10003)
|
||||
if (!acpi_iospace_resource_valid(res))
|
||||
res->flags |= IORESOURCE_DISABLED | IORESOURCE_UNSET;
|
||||
|
||||
if (io_decode == ACPI_DECODE_16)
|
||||
|
|
|
@ -714,6 +714,7 @@ static int acpi_hibernation_enter(void)
|
|||
|
||||
static void acpi_hibernation_leave(void)
|
||||
{
|
||||
pm_set_resume_via_firmware();
|
||||
/*
|
||||
* If ACPI is not enabled by the BIOS and the boot kernel, we need to
|
||||
* enable it here.
|
||||
|
|
|
@ -1,2 +1,3 @@
|
|||
ccflags-$(CONFIG_DEBUG_DRIVER) := -DDEBUG
|
||||
obj-y += core.o cpu.o
|
||||
obj-$(CONFIG_DEBUG_FS) += debugfs.o
|
||||
|
|
File diff suppressed because it is too large
Load diff
|
@ -31,7 +31,7 @@
|
|||
* @table: Cpufreq table returned back to caller
|
||||
*
|
||||
* Generate a cpufreq table for a provided device- this assumes that the
|
||||
* opp list is already initialized and ready for usage.
|
||||
* opp table is already initialized and ready for usage.
|
||||
*
|
||||
* This function allocates required memory for the cpufreq table. It is
|
||||
* expected that the caller does the required maintenance such as freeing
|
||||
|
@ -44,7 +44,7 @@
|
|||
* WARNING: It is important for the callers to ensure refreshing their copy of
|
||||
* the table if any of the mentioned functions have been invoked in the interim.
|
||||
*
|
||||
* Locking: The internal device_opp and opp structures are RCU protected.
|
||||
* Locking: The internal opp_table and opp structures are RCU protected.
|
||||
* Since we just use the regular accessor functions to access the internal data
|
||||
* structures, we use RCU read lock inside this function. As a result, users of
|
||||
* this function DONOT need to use explicit locks for invoking.
|
||||
|
@ -122,15 +122,15 @@ EXPORT_SYMBOL_GPL(dev_pm_opp_free_cpufreq_table);
|
|||
/* Required only for V1 bindings, as v2 can manage it from DT itself */
|
||||
int dev_pm_opp_set_sharing_cpus(struct device *cpu_dev, cpumask_var_t cpumask)
|
||||
{
|
||||
struct device_list_opp *list_dev;
|
||||
struct device_opp *dev_opp;
|
||||
struct opp_device *opp_dev;
|
||||
struct opp_table *opp_table;
|
||||
struct device *dev;
|
||||
int cpu, ret = 0;
|
||||
|
||||
mutex_lock(&dev_opp_list_lock);
|
||||
mutex_lock(&opp_table_lock);
|
||||
|
||||
dev_opp = _find_device_opp(cpu_dev);
|
||||
if (IS_ERR(dev_opp)) {
|
||||
opp_table = _find_opp_table(cpu_dev);
|
||||
if (IS_ERR(opp_table)) {
|
||||
ret = -EINVAL;
|
||||
goto unlock;
|
||||
}
|
||||
|
@ -146,15 +146,15 @@ int dev_pm_opp_set_sharing_cpus(struct device *cpu_dev, cpumask_var_t cpumask)
|
|||
continue;
|
||||
}
|
||||
|
||||
list_dev = _add_list_dev(dev, dev_opp);
|
||||
if (!list_dev) {
|
||||
dev_err(dev, "%s: failed to add list-dev for cpu%d device\n",
|
||||
opp_dev = _add_opp_dev(dev, opp_table);
|
||||
if (!opp_dev) {
|
||||
dev_err(dev, "%s: failed to add opp-dev for cpu%d device\n",
|
||||
__func__, cpu);
|
||||
continue;
|
||||
}
|
||||
}
|
||||
unlock:
|
||||
mutex_unlock(&dev_opp_list_lock);
|
||||
mutex_unlock(&opp_table_lock);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
@ -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;
|
||||
|
|
218
drivers/base/power/opp/debugfs.c
Normal file
218
drivers/base/power/opp/debugfs.c
Normal file
|
@ -0,0 +1,218 @@
|
|||
/*
|
||||
* 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 opp_table *opp_table)
|
||||
{
|
||||
struct dentry *pdentry = opp_table->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 opp_list_debug_create_dir(struct opp_device *opp_dev,
|
||||
struct opp_table *opp_table)
|
||||
{
|
||||
const struct device *dev = opp_dev->dev;
|
||||
struct dentry *d;
|
||||
|
||||
opp_set_dev_name(dev, opp_table->dentry_name);
|
||||
|
||||
/* Create device specific directory */
|
||||
d = debugfs_create_dir(opp_table->dentry_name, rootdir);
|
||||
if (!d) {
|
||||
dev_err(dev, "%s: Failed to create debugfs dir\n", __func__);
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
opp_dev->dentry = d;
|
||||
opp_table->dentry = d;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int opp_list_debug_create_link(struct opp_device *opp_dev,
|
||||
struct opp_table *opp_table)
|
||||
{
|
||||
const struct device *dev = opp_dev->dev;
|
||||
char name[NAME_MAX];
|
||||
struct dentry *d;
|
||||
|
||||
opp_set_dev_name(opp_dev->dev, name);
|
||||
|
||||
/* Create device specific directory link */
|
||||
d = debugfs_create_symlink(name, rootdir, opp_table->dentry_name);
|
||||
if (!d) {
|
||||
dev_err(dev, "%s: Failed to create link\n", __func__);
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
opp_dev->dentry = d;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* opp_debug_register - add a device opp node to the debugfs 'opp' directory
|
||||
* @opp_dev: opp-dev pointer for device
|
||||
* @opp_table: 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 opp_device *opp_dev, struct opp_table *opp_table)
|
||||
{
|
||||
if (!rootdir) {
|
||||
pr_debug("%s: Uninitialized rootdir\n", __func__);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
if (opp_table->dentry)
|
||||
return opp_list_debug_create_link(opp_dev, opp_table);
|
||||
|
||||
return opp_list_debug_create_dir(opp_dev, opp_table);
|
||||
}
|
||||
|
||||
static void opp_migrate_dentry(struct opp_device *opp_dev,
|
||||
struct opp_table *opp_table)
|
||||
{
|
||||
struct opp_device *new_dev;
|
||||
const struct device *dev;
|
||||
struct dentry *dentry;
|
||||
|
||||
/* Look for next opp-dev */
|
||||
list_for_each_entry(new_dev, &opp_table->dev_list, node)
|
||||
if (new_dev != opp_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, opp_table->dentry_name);
|
||||
|
||||
dentry = debugfs_rename(rootdir, opp_dev->dentry, rootdir,
|
||||
opp_table->dentry_name);
|
||||
if (!dentry) {
|
||||
dev_err(dev, "%s: Failed to rename link from: %s to %s\n",
|
||||
__func__, dev_name(opp_dev->dev), dev_name(dev));
|
||||
return;
|
||||
}
|
||||
|
||||
new_dev->dentry = dentry;
|
||||
opp_table->dentry = dentry;
|
||||
}
|
||||
|
||||
/**
|
||||
* opp_debug_unregister - remove a device opp node from debugfs opp directory
|
||||
* @opp_dev: opp-dev pointer for device
|
||||
* @opp_table: the device-opp being removed
|
||||
*
|
||||
* Dynamically removes device specific directory from debugfs 'opp' directory.
|
||||
*/
|
||||
void opp_debug_unregister(struct opp_device *opp_dev,
|
||||
struct opp_table *opp_table)
|
||||
{
|
||||
if (opp_dev->dentry == opp_table->dentry) {
|
||||
/* Move the real dentry object under another device */
|
||||
if (!list_is_singular(&opp_table->dev_list)) {
|
||||
opp_migrate_dentry(opp_dev, opp_table);
|
||||
goto out;
|
||||
}
|
||||
opp_table->dentry = NULL;
|
||||
}
|
||||
|
||||
debugfs_remove_recursive(opp_dev->dentry);
|
||||
|
||||
out:
|
||||
opp_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);
|
|
@ -17,17 +17,21 @@
|
|||
#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>
|
||||
|
||||
struct clk;
|
||||
struct regulator;
|
||||
|
||||
/* Lock to allow exclusive modification to the device and opp lists */
|
||||
extern struct mutex dev_opp_list_lock;
|
||||
extern struct mutex opp_table_lock;
|
||||
|
||||
/*
|
||||
* Internal data structure organization with the OPP layer library is as
|
||||
* follows:
|
||||
* dev_opp_list (root)
|
||||
* opp_tables (root)
|
||||
* |- device 1 (represents voltage domain 1)
|
||||
* | |- opp 1 (availability, freq, voltage)
|
||||
* | |- opp 2 ..
|
||||
|
@ -36,23 +40,24 @@ extern struct mutex dev_opp_list_lock;
|
|||
* |- device 2 (represents the next voltage domain)
|
||||
* ...
|
||||
* `- device m (represents mth voltage domain)
|
||||
* device 1, 2.. are represented by dev_opp structure while each opp
|
||||
* device 1, 2.. are represented by opp_table structure while each opp
|
||||
* is represented by the opp structure.
|
||||
*/
|
||||
|
||||
/**
|
||||
* struct dev_pm_opp - Generic OPP description structure
|
||||
* @node: opp list node. The nodes are maintained throughout the lifetime
|
||||
* @node: opp table node. The nodes are maintained throughout the lifetime
|
||||
* of boot. It is expected only an optimal set of OPPs are
|
||||
* added to the library by the SoC framework.
|
||||
* RCU usage: opp list is traversed with RCU locks. node
|
||||
* RCU usage: opp table is traversed with RCU locks. node
|
||||
* modification is possible realtime, hence the modifications
|
||||
* are protected by the dev_opp_list_lock for integrity.
|
||||
* are protected by the opp_table_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
|
||||
|
@ -60,9 +65,10 @@ extern struct mutex dev_opp_list_lock;
|
|||
* @u_amp: Maximum current drawn by the device in microamperes
|
||||
* @clock_latency_ns: Latency (in nanoseconds) of switching to this OPP's
|
||||
* frequency from any other OPP's frequency.
|
||||
* @dev_opp: points back to the device_opp struct this opp belongs to
|
||||
* @opp_table: points back to the opp_table 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 +78,7 @@ struct dev_pm_opp {
|
|||
bool available;
|
||||
bool dynamic;
|
||||
bool turbo;
|
||||
bool suspend;
|
||||
unsigned long rate;
|
||||
|
||||
unsigned long u_volt;
|
||||
|
@ -80,40 +87,60 @@ struct dev_pm_opp {
|
|||
unsigned long u_amp;
|
||||
unsigned long clock_latency_ns;
|
||||
|
||||
struct device_opp *dev_opp;
|
||||
struct opp_table *opp_table;
|
||||
struct rcu_head rcu_head;
|
||||
|
||||
struct device_node *np;
|
||||
|
||||
#ifdef CONFIG_DEBUG_FS
|
||||
struct dentry *dentry;
|
||||
#endif
|
||||
};
|
||||
|
||||
/**
|
||||
* struct device_list_opp - devices managed by 'struct device_opp'
|
||||
* struct opp_device - devices managed by 'struct opp_table'
|
||||
* @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'.
|
||||
* This is an internal data structure maintaining the devices that are managed
|
||||
* by 'struct opp_table'.
|
||||
*/
|
||||
struct device_list_opp {
|
||||
struct opp_device {
|
||||
struct list_head node;
|
||||
const struct device *dev;
|
||||
struct rcu_head rcu_head;
|
||||
|
||||
#ifdef CONFIG_DEBUG_FS
|
||||
struct dentry *dentry;
|
||||
#endif
|
||||
};
|
||||
|
||||
/**
|
||||
* struct device_opp - Device opp structure
|
||||
* @node: list node - contains the devices with OPPs that
|
||||
* struct opp_table - Device opp structure
|
||||
* @node: table node - contains the devices with OPPs that
|
||||
* have been registered. Nodes once added are not modified in this
|
||||
* list.
|
||||
* RCU usage: nodes are not modified in the list of device_opp,
|
||||
* however addition is possible and is secured by dev_opp_list_lock
|
||||
* table.
|
||||
* RCU usage: nodes are not modified in the table of opp_table,
|
||||
* however addition is possible and is secured by opp_table_lock
|
||||
* @srcu_head: notifier head to notify the OPP availability changes.
|
||||
* @rcu_head: RCU callback head used for deferred freeing
|
||||
* @dev_list: list of devices that share these OPPs
|
||||
* @opp_list: list of opps
|
||||
* @opp_list: table 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.
|
||||
* @clk: Device's clock handle
|
||||
* @regulator: Supply regulator
|
||||
* @dentry: debugfs dentry pointer of the real device directory (not links).
|
||||
* @dentry_name: Name of the real dentry.
|
||||
*
|
||||
* @voltage_tolerance_v1: In percentage, for v1 bindings only.
|
||||
*
|
||||
* 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
|
||||
|
@ -123,7 +150,7 @@ struct device_list_opp {
|
|||
* need to wait for the grace period of both of them before freeing any
|
||||
* resources. And so we have used kfree_rcu() from within call_srcu() handlers.
|
||||
*/
|
||||
struct device_opp {
|
||||
struct opp_table {
|
||||
struct list_head node;
|
||||
|
||||
struct srcu_notifier_head srcu_head;
|
||||
|
@ -133,14 +160,48 @@ struct device_opp {
|
|||
|
||||
struct device_node *np;
|
||||
unsigned long clock_latency_ns_max;
|
||||
|
||||
/* For backward compatibility with v1 bindings */
|
||||
unsigned int voltage_tolerance_v1;
|
||||
|
||||
bool shared_opp;
|
||||
struct dev_pm_opp *suspend_opp;
|
||||
|
||||
unsigned int *supported_hw;
|
||||
unsigned int supported_hw_count;
|
||||
const char *prop_name;
|
||||
struct clk *clk;
|
||||
struct regulator *regulator;
|
||||
|
||||
#ifdef CONFIG_DEBUG_FS
|
||||
struct dentry *dentry;
|
||||
char dentry_name[NAME_MAX];
|
||||
#endif
|
||||
};
|
||||
|
||||
/* Routines internal to opp core */
|
||||
struct device_opp *_find_device_opp(struct device *dev);
|
||||
struct device_list_opp *_add_list_dev(const struct device *dev,
|
||||
struct device_opp *dev_opp);
|
||||
struct opp_table *_find_opp_table(struct device *dev);
|
||||
struct opp_device *_add_opp_dev(const struct device *dev, struct opp_table *opp_table);
|
||||
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 opp_table *opp_table);
|
||||
int opp_debug_register(struct opp_device *opp_dev, struct opp_table *opp_table);
|
||||
void opp_debug_unregister(struct opp_device *opp_dev, struct opp_table *opp_table);
|
||||
#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 opp_table *opp_table)
|
||||
{ return 0; }
|
||||
static inline int opp_debug_register(struct opp_device *opp_dev,
|
||||
struct opp_table *opp_table)
|
||||
{ return 0; }
|
||||
|
||||
static inline void opp_debug_unregister(struct opp_device *opp_dev,
|
||||
struct opp_table *opp_table)
|
||||
{ }
|
||||
#endif /* DEBUG_FS */
|
||||
|
||||
#endif /* __DRIVER_OPP_H__ */
|
||||
|
|
|
@ -338,7 +338,7 @@ static blk_qc_t brd_make_request(struct request_queue *q, struct bio *bio)
|
|||
|
||||
if (unlikely(bio->bi_rw & REQ_DISCARD)) {
|
||||
if (sector & ((PAGE_SIZE >> SECTOR_SHIFT) - 1) ||
|
||||
bio->bi_iter.bi_size & PAGE_MASK)
|
||||
bio->bi_iter.bi_size & ~PAGE_MASK)
|
||||
goto io_error;
|
||||
discard_from_brd(brd, sector, bio->bi_iter.bi_size);
|
||||
goto out;
|
||||
|
|
|
@ -173,7 +173,13 @@ static struct mtip_cmd *mtip_get_int_command(struct driver_data *dd)
|
|||
{
|
||||
struct request *rq;
|
||||
|
||||
if (mtip_check_surprise_removal(dd->pdev))
|
||||
return NULL;
|
||||
|
||||
rq = blk_mq_alloc_request(dd->queue, 0, __GFP_RECLAIM, true);
|
||||
if (IS_ERR(rq))
|
||||
return NULL;
|
||||
|
||||
return blk_mq_rq_to_pdu(rq);
|
||||
}
|
||||
|
||||
|
@ -233,15 +239,9 @@ static void mtip_async_complete(struct mtip_port *port,
|
|||
"Command tag %d failed due to TFE\n", tag);
|
||||
}
|
||||
|
||||
/* Unmap the DMA scatter list entries */
|
||||
dma_unmap_sg(&dd->pdev->dev, cmd->sg, cmd->scatter_ents, cmd->direction);
|
||||
|
||||
rq = mtip_rq_from_tag(dd, tag);
|
||||
|
||||
if (unlikely(cmd->unaligned))
|
||||
up(&port->cmd_slot_unal);
|
||||
|
||||
blk_mq_end_request(rq, status ? -EIO : 0);
|
||||
blk_mq_complete_request(rq, status);
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -581,6 +581,8 @@ static void mtip_completion(struct mtip_port *port,
|
|||
dev_warn(&port->dd->pdev->dev,
|
||||
"Internal command %d completed with TFE\n", tag);
|
||||
|
||||
command->comp_func = NULL;
|
||||
command->comp_data = NULL;
|
||||
complete(waiting);
|
||||
}
|
||||
|
||||
|
@ -618,8 +620,6 @@ static void mtip_handle_tfe(struct driver_data *dd)
|
|||
|
||||
port = dd->port;
|
||||
|
||||
set_bit(MTIP_PF_EH_ACTIVE_BIT, &port->flags);
|
||||
|
||||
if (test_bit(MTIP_PF_IC_ACTIVE_BIT, &port->flags)) {
|
||||
cmd = mtip_cmd_from_tag(dd, MTIP_TAG_INTERNAL);
|
||||
dbg_printk(MTIP_DRV_NAME " TFE for the internal command\n");
|
||||
|
@ -628,7 +628,7 @@ static void mtip_handle_tfe(struct driver_data *dd)
|
|||
cmd->comp_func(port, MTIP_TAG_INTERNAL,
|
||||
cmd, PORT_IRQ_TF_ERR);
|
||||
}
|
||||
goto handle_tfe_exit;
|
||||
return;
|
||||
}
|
||||
|
||||
/* clear the tag accumulator */
|
||||
|
@ -701,7 +701,7 @@ static void mtip_handle_tfe(struct driver_data *dd)
|
|||
fail_reason = "thermal shutdown";
|
||||
}
|
||||
if (buf[288] == 0xBF) {
|
||||
set_bit(MTIP_DDF_SEC_LOCK_BIT, &dd->dd_flag);
|
||||
set_bit(MTIP_DDF_REBUILD_FAILED_BIT, &dd->dd_flag);
|
||||
dev_info(&dd->pdev->dev,
|
||||
"Drive indicates rebuild has failed. Secure erase required.\n");
|
||||
fail_all_ncq_cmds = 1;
|
||||
|
@ -771,11 +771,6 @@ static void mtip_handle_tfe(struct driver_data *dd)
|
|||
}
|
||||
}
|
||||
print_tags(dd, "reissued (TFE)", tagaccum, cmd_cnt);
|
||||
|
||||
handle_tfe_exit:
|
||||
/* clear eh_active */
|
||||
clear_bit(MTIP_PF_EH_ACTIVE_BIT, &port->flags);
|
||||
wake_up_interruptible(&port->svc_wait);
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -1007,6 +1002,7 @@ static bool mtip_pause_ncq(struct mtip_port *port,
|
|||
(fis->features == 0x27 || fis->features == 0x72 ||
|
||||
fis->features == 0x62 || fis->features == 0x26))) {
|
||||
clear_bit(MTIP_DDF_SEC_LOCK_BIT, &port->dd->dd_flag);
|
||||
clear_bit(MTIP_DDF_REBUILD_FAILED_BIT, &port->dd->dd_flag);
|
||||
/* Com reset after secure erase or lowlevel format */
|
||||
mtip_restart_port(port);
|
||||
clear_bit(MTIP_PF_SE_ACTIVE_BIT, &port->flags);
|
||||
|
@ -1021,12 +1017,14 @@ static bool mtip_pause_ncq(struct mtip_port *port,
|
|||
*
|
||||
* @port Pointer to port data structure
|
||||
* @timeout Max duration to wait (ms)
|
||||
* @atomic gfp_t flag to indicate blockable context or not
|
||||
*
|
||||
* return value
|
||||
* 0 Success
|
||||
* -EBUSY Commands still active
|
||||
*/
|
||||
static int mtip_quiesce_io(struct mtip_port *port, unsigned long timeout)
|
||||
static int mtip_quiesce_io(struct mtip_port *port, unsigned long timeout,
|
||||
gfp_t atomic)
|
||||
{
|
||||
unsigned long to;
|
||||
unsigned int n;
|
||||
|
@ -1037,16 +1035,21 @@ static int mtip_quiesce_io(struct mtip_port *port, unsigned long timeout)
|
|||
to = jiffies + msecs_to_jiffies(timeout);
|
||||
do {
|
||||
if (test_bit(MTIP_PF_SVC_THD_ACTIVE_BIT, &port->flags) &&
|
||||
test_bit(MTIP_PF_ISSUE_CMDS_BIT, &port->flags)) {
|
||||
test_bit(MTIP_PF_ISSUE_CMDS_BIT, &port->flags) &&
|
||||
atomic == GFP_KERNEL) {
|
||||
msleep(20);
|
||||
continue; /* svc thd is actively issuing commands */
|
||||
}
|
||||
|
||||
msleep(100);
|
||||
if (atomic == GFP_KERNEL)
|
||||
msleep(100);
|
||||
else {
|
||||
cpu_relax();
|
||||
udelay(100);
|
||||
}
|
||||
|
||||
if (mtip_check_surprise_removal(port->dd->pdev))
|
||||
goto err_fault;
|
||||
if (test_bit(MTIP_DDF_REMOVE_PENDING_BIT, &port->dd->dd_flag))
|
||||
goto err_fault;
|
||||
|
||||
/*
|
||||
* Ignore s_active bit 0 of array element 0.
|
||||
|
@ -1099,6 +1102,7 @@ static int mtip_exec_internal_command(struct mtip_port *port,
|
|||
struct mtip_cmd *int_cmd;
|
||||
struct driver_data *dd = port->dd;
|
||||
int rv = 0;
|
||||
unsigned long start;
|
||||
|
||||
/* Make sure the buffer is 8 byte aligned. This is asic specific. */
|
||||
if (buffer & 0x00000007) {
|
||||
|
@ -1107,6 +1111,10 @@ static int mtip_exec_internal_command(struct mtip_port *port,
|
|||
}
|
||||
|
||||
int_cmd = mtip_get_int_command(dd);
|
||||
if (!int_cmd) {
|
||||
dbg_printk(MTIP_DRV_NAME "Unable to allocate tag for PIO cmd\n");
|
||||
return -EFAULT;
|
||||
}
|
||||
|
||||
set_bit(MTIP_PF_IC_ACTIVE_BIT, &port->flags);
|
||||
|
||||
|
@ -1119,7 +1127,7 @@ static int mtip_exec_internal_command(struct mtip_port *port,
|
|||
if (fis->command != ATA_CMD_STANDBYNOW1) {
|
||||
/* wait for io to complete if non atomic */
|
||||
if (mtip_quiesce_io(port,
|
||||
MTIP_QUIESCE_IO_TIMEOUT_MS) < 0) {
|
||||
MTIP_QUIESCE_IO_TIMEOUT_MS, atomic) < 0) {
|
||||
dev_warn(&dd->pdev->dev,
|
||||
"Failed to quiesce IO\n");
|
||||
mtip_put_int_command(dd, int_cmd);
|
||||
|
@ -1162,6 +1170,8 @@ static int mtip_exec_internal_command(struct mtip_port *port,
|
|||
/* Populate the command header */
|
||||
int_cmd->command_header->byte_count = 0;
|
||||
|
||||
start = jiffies;
|
||||
|
||||
/* Issue the command to the hardware */
|
||||
mtip_issue_non_ncq_command(port, MTIP_TAG_INTERNAL);
|
||||
|
||||
|
@ -1170,10 +1180,12 @@ static int mtip_exec_internal_command(struct mtip_port *port,
|
|||
if ((rv = wait_for_completion_interruptible_timeout(
|
||||
&wait,
|
||||
msecs_to_jiffies(timeout))) <= 0) {
|
||||
|
||||
if (rv == -ERESTARTSYS) { /* interrupted */
|
||||
dev_err(&dd->pdev->dev,
|
||||
"Internal command [%02X] was interrupted after %lu ms\n",
|
||||
fis->command, timeout);
|
||||
"Internal command [%02X] was interrupted after %u ms\n",
|
||||
fis->command,
|
||||
jiffies_to_msecs(jiffies - start));
|
||||
rv = -EINTR;
|
||||
goto exec_ic_exit;
|
||||
} else if (rv == 0) /* timeout */
|
||||
|
@ -2897,6 +2909,42 @@ static int mtip_ftl_rebuild_poll(struct driver_data *dd)
|
|||
return -EFAULT;
|
||||
}
|
||||
|
||||
static void mtip_softirq_done_fn(struct request *rq)
|
||||
{
|
||||
struct mtip_cmd *cmd = blk_mq_rq_to_pdu(rq);
|
||||
struct driver_data *dd = rq->q->queuedata;
|
||||
|
||||
/* Unmap the DMA scatter list entries */
|
||||
dma_unmap_sg(&dd->pdev->dev, cmd->sg, cmd->scatter_ents,
|
||||
cmd->direction);
|
||||
|
||||
if (unlikely(cmd->unaligned))
|
||||
up(&dd->port->cmd_slot_unal);
|
||||
|
||||
blk_mq_end_request(rq, rq->errors);
|
||||
}
|
||||
|
||||
static void mtip_abort_cmd(struct request *req, void *data,
|
||||
bool reserved)
|
||||
{
|
||||
struct driver_data *dd = data;
|
||||
|
||||
dbg_printk(MTIP_DRV_NAME " Aborting request, tag = %d\n", req->tag);
|
||||
|
||||
clear_bit(req->tag, dd->port->cmds_to_issue);
|
||||
req->errors = -EIO;
|
||||
mtip_softirq_done_fn(req);
|
||||
}
|
||||
|
||||
static void mtip_queue_cmd(struct request *req, void *data,
|
||||
bool reserved)
|
||||
{
|
||||
struct driver_data *dd = data;
|
||||
|
||||
set_bit(req->tag, dd->port->cmds_to_issue);
|
||||
blk_abort_request(req);
|
||||
}
|
||||
|
||||
/*
|
||||
* service thread to issue queued commands
|
||||
*
|
||||
|
@ -2909,7 +2957,7 @@ static int mtip_ftl_rebuild_poll(struct driver_data *dd)
|
|||
static int mtip_service_thread(void *data)
|
||||
{
|
||||
struct driver_data *dd = (struct driver_data *)data;
|
||||
unsigned long slot, slot_start, slot_wrap;
|
||||
unsigned long slot, slot_start, slot_wrap, to;
|
||||
unsigned int num_cmd_slots = dd->slot_groups * 32;
|
||||
struct mtip_port *port = dd->port;
|
||||
|
||||
|
@ -2924,9 +2972,7 @@ static int mtip_service_thread(void *data)
|
|||
* is in progress nor error handling is active
|
||||
*/
|
||||
wait_event_interruptible(port->svc_wait, (port->flags) &&
|
||||
!(port->flags & MTIP_PF_PAUSE_IO));
|
||||
|
||||
set_bit(MTIP_PF_SVC_THD_ACTIVE_BIT, &port->flags);
|
||||
(port->flags & MTIP_PF_SVC_THD_WORK));
|
||||
|
||||
if (kthread_should_stop() ||
|
||||
test_bit(MTIP_PF_SVC_THD_STOP_BIT, &port->flags))
|
||||
|
@ -2936,6 +2982,8 @@ static int mtip_service_thread(void *data)
|
|||
&dd->dd_flag)))
|
||||
goto st_out;
|
||||
|
||||
set_bit(MTIP_PF_SVC_THD_ACTIVE_BIT, &port->flags);
|
||||
|
||||
restart_eh:
|
||||
/* Demux bits: start with error handling */
|
||||
if (test_bit(MTIP_PF_EH_ACTIVE_BIT, &port->flags)) {
|
||||
|
@ -2946,6 +2994,32 @@ restart_eh:
|
|||
if (test_bit(MTIP_PF_EH_ACTIVE_BIT, &port->flags))
|
||||
goto restart_eh;
|
||||
|
||||
if (test_bit(MTIP_PF_TO_ACTIVE_BIT, &port->flags)) {
|
||||
to = jiffies + msecs_to_jiffies(5000);
|
||||
|
||||
do {
|
||||
mdelay(100);
|
||||
} while (atomic_read(&dd->irq_workers_active) != 0 &&
|
||||
time_before(jiffies, to));
|
||||
|
||||
if (atomic_read(&dd->irq_workers_active) != 0)
|
||||
dev_warn(&dd->pdev->dev,
|
||||
"Completion workers still active!");
|
||||
|
||||
spin_lock(dd->queue->queue_lock);
|
||||
blk_mq_all_tag_busy_iter(*dd->tags.tags,
|
||||
mtip_queue_cmd, dd);
|
||||
spin_unlock(dd->queue->queue_lock);
|
||||
|
||||
set_bit(MTIP_PF_ISSUE_CMDS_BIT, &dd->port->flags);
|
||||
|
||||
if (mtip_device_reset(dd))
|
||||
blk_mq_all_tag_busy_iter(*dd->tags.tags,
|
||||
mtip_abort_cmd, dd);
|
||||
|
||||
clear_bit(MTIP_PF_TO_ACTIVE_BIT, &dd->port->flags);
|
||||
}
|
||||
|
||||
if (test_bit(MTIP_PF_ISSUE_CMDS_BIT, &port->flags)) {
|
||||
slot = 1;
|
||||
/* used to restrict the loop to one iteration */
|
||||
|
@ -2978,10 +3052,8 @@ restart_eh:
|
|||
}
|
||||
|
||||
if (test_bit(MTIP_PF_REBUILD_BIT, &port->flags)) {
|
||||
if (mtip_ftl_rebuild_poll(dd) < 0)
|
||||
set_bit(MTIP_DDF_REBUILD_FAILED_BIT,
|
||||
&dd->dd_flag);
|
||||
clear_bit(MTIP_PF_REBUILD_BIT, &port->flags);
|
||||
if (mtip_ftl_rebuild_poll(dd) == 0)
|
||||
clear_bit(MTIP_PF_REBUILD_BIT, &port->flags);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -3096,7 +3168,7 @@ static int mtip_hw_get_identify(struct driver_data *dd)
|
|||
if (buf[288] == 0xBF) {
|
||||
dev_info(&dd->pdev->dev,
|
||||
"Drive indicates rebuild has failed.\n");
|
||||
/* TODO */
|
||||
set_bit(MTIP_DDF_REBUILD_FAILED_BIT, &dd->dd_flag);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -3270,20 +3342,25 @@ out1:
|
|||
return rv;
|
||||
}
|
||||
|
||||
static void mtip_standby_drive(struct driver_data *dd)
|
||||
static int mtip_standby_drive(struct driver_data *dd)
|
||||
{
|
||||
if (dd->sr)
|
||||
return;
|
||||
int rv = 0;
|
||||
|
||||
if (dd->sr || !dd->port)
|
||||
return -ENODEV;
|
||||
/*
|
||||
* Send standby immediate (E0h) to the drive so that it
|
||||
* saves its state.
|
||||
*/
|
||||
if (!test_bit(MTIP_PF_REBUILD_BIT, &dd->port->flags) &&
|
||||
!test_bit(MTIP_DDF_SEC_LOCK_BIT, &dd->dd_flag))
|
||||
if (mtip_standby_immediate(dd->port))
|
||||
!test_bit(MTIP_DDF_REBUILD_FAILED_BIT, &dd->dd_flag) &&
|
||||
!test_bit(MTIP_DDF_SEC_LOCK_BIT, &dd->dd_flag)) {
|
||||
rv = mtip_standby_immediate(dd->port);
|
||||
if (rv)
|
||||
dev_warn(&dd->pdev->dev,
|
||||
"STANDBY IMMEDIATE failed\n");
|
||||
}
|
||||
return rv;
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -3296,10 +3373,6 @@ static void mtip_standby_drive(struct driver_data *dd)
|
|||
*/
|
||||
static int mtip_hw_exit(struct driver_data *dd)
|
||||
{
|
||||
/*
|
||||
* Send standby immediate (E0h) to the drive so that it
|
||||
* saves its state.
|
||||
*/
|
||||
if (!dd->sr) {
|
||||
/* de-initialize the port. */
|
||||
mtip_deinit_port(dd->port);
|
||||
|
@ -3341,8 +3414,7 @@ static int mtip_hw_shutdown(struct driver_data *dd)
|
|||
* Send standby immediate (E0h) to the drive so that it
|
||||
* saves its state.
|
||||
*/
|
||||
if (!dd->sr && dd->port)
|
||||
mtip_standby_immediate(dd->port);
|
||||
mtip_standby_drive(dd);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
@ -3365,7 +3437,7 @@ static int mtip_hw_suspend(struct driver_data *dd)
|
|||
* Send standby immediate (E0h) to the drive
|
||||
* so that it saves its state.
|
||||
*/
|
||||
if (mtip_standby_immediate(dd->port) != 0) {
|
||||
if (mtip_standby_drive(dd) != 0) {
|
||||
dev_err(&dd->pdev->dev,
|
||||
"Failed standby-immediate command\n");
|
||||
return -EFAULT;
|
||||
|
@ -3603,6 +3675,28 @@ static int mtip_block_getgeo(struct block_device *dev,
|
|||
return 0;
|
||||
}
|
||||
|
||||
static int mtip_block_open(struct block_device *dev, fmode_t mode)
|
||||
{
|
||||
struct driver_data *dd;
|
||||
|
||||
if (dev && dev->bd_disk) {
|
||||
dd = (struct driver_data *) dev->bd_disk->private_data;
|
||||
|
||||
if (dd) {
|
||||
if (test_bit(MTIP_DDF_REMOVAL_BIT,
|
||||
&dd->dd_flag)) {
|
||||
return -ENODEV;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
void mtip_block_release(struct gendisk *disk, fmode_t mode)
|
||||
{
|
||||
}
|
||||
|
||||
/*
|
||||
* Block device operation function.
|
||||
*
|
||||
|
@ -3610,6 +3704,8 @@ static int mtip_block_getgeo(struct block_device *dev,
|
|||
* layer.
|
||||
*/
|
||||
static const struct block_device_operations mtip_block_ops = {
|
||||
.open = mtip_block_open,
|
||||
.release = mtip_block_release,
|
||||
.ioctl = mtip_block_ioctl,
|
||||
#ifdef CONFIG_COMPAT
|
||||
.compat_ioctl = mtip_block_compat_ioctl,
|
||||
|
@ -3671,10 +3767,9 @@ static int mtip_submit_request(struct blk_mq_hw_ctx *hctx, struct request *rq)
|
|||
rq_data_dir(rq))) {
|
||||
return -ENODATA;
|
||||
}
|
||||
if (unlikely(test_bit(MTIP_DDF_SEC_LOCK_BIT, &dd->dd_flag)))
|
||||
if (unlikely(test_bit(MTIP_DDF_SEC_LOCK_BIT, &dd->dd_flag) ||
|
||||
test_bit(MTIP_DDF_REBUILD_FAILED_BIT, &dd->dd_flag)))
|
||||
return -ENODATA;
|
||||
if (test_bit(MTIP_DDF_REBUILD_FAILED_BIT, &dd->dd_flag))
|
||||
return -ENXIO;
|
||||
}
|
||||
|
||||
if (rq->cmd_flags & REQ_DISCARD) {
|
||||
|
@ -3786,11 +3881,33 @@ static int mtip_init_cmd(void *data, struct request *rq, unsigned int hctx_idx,
|
|||
return 0;
|
||||
}
|
||||
|
||||
static enum blk_eh_timer_return mtip_cmd_timeout(struct request *req,
|
||||
bool reserved)
|
||||
{
|
||||
struct driver_data *dd = req->q->queuedata;
|
||||
int ret = BLK_EH_RESET_TIMER;
|
||||
|
||||
if (reserved)
|
||||
goto exit_handler;
|
||||
|
||||
if (test_bit(req->tag, dd->port->cmds_to_issue))
|
||||
goto exit_handler;
|
||||
|
||||
if (test_and_set_bit(MTIP_PF_TO_ACTIVE_BIT, &dd->port->flags))
|
||||
goto exit_handler;
|
||||
|
||||
wake_up_interruptible(&dd->port->svc_wait);
|
||||
exit_handler:
|
||||
return ret;
|
||||
}
|
||||
|
||||
static struct blk_mq_ops mtip_mq_ops = {
|
||||
.queue_rq = mtip_queue_rq,
|
||||
.map_queue = blk_mq_map_queue,
|
||||
.init_request = mtip_init_cmd,
|
||||
.exit_request = mtip_free_cmd,
|
||||
.complete = mtip_softirq_done_fn,
|
||||
.timeout = mtip_cmd_timeout,
|
||||
};
|
||||
|
||||
/*
|
||||
|
@ -3857,7 +3974,6 @@ static int mtip_block_initialize(struct driver_data *dd)
|
|||
|
||||
mtip_hw_debugfs_init(dd);
|
||||
|
||||
skip_create_disk:
|
||||
memset(&dd->tags, 0, sizeof(dd->tags));
|
||||
dd->tags.ops = &mtip_mq_ops;
|
||||
dd->tags.nr_hw_queues = 1;
|
||||
|
@ -3867,12 +3983,13 @@ skip_create_disk:
|
|||
dd->tags.numa_node = dd->numa_node;
|
||||
dd->tags.flags = BLK_MQ_F_SHOULD_MERGE;
|
||||
dd->tags.driver_data = dd;
|
||||
dd->tags.timeout = MTIP_NCQ_CMD_TIMEOUT_MS;
|
||||
|
||||
rv = blk_mq_alloc_tag_set(&dd->tags);
|
||||
if (rv) {
|
||||
dev_err(&dd->pdev->dev,
|
||||
"Unable to allocate request queue\n");
|
||||
goto block_queue_alloc_init_error;
|
||||
goto block_queue_alloc_tag_error;
|
||||
}
|
||||
|
||||
/* Allocate the request queue. */
|
||||
|
@ -3887,6 +4004,7 @@ skip_create_disk:
|
|||
dd->disk->queue = dd->queue;
|
||||
dd->queue->queuedata = dd;
|
||||
|
||||
skip_create_disk:
|
||||
/* Initialize the protocol layer. */
|
||||
wait_for_rebuild = mtip_hw_get_identify(dd);
|
||||
if (wait_for_rebuild < 0) {
|
||||
|
@ -3983,8 +4101,9 @@ kthread_run_error:
|
|||
read_capacity_error:
|
||||
init_hw_cmds_error:
|
||||
blk_cleanup_queue(dd->queue);
|
||||
blk_mq_free_tag_set(&dd->tags);
|
||||
block_queue_alloc_init_error:
|
||||
blk_mq_free_tag_set(&dd->tags);
|
||||
block_queue_alloc_tag_error:
|
||||
mtip_hw_debugfs_exit(dd);
|
||||
disk_index_error:
|
||||
spin_lock(&rssd_index_lock);
|
||||
|
@ -4001,6 +4120,22 @@ protocol_init_error:
|
|||
return rv;
|
||||
}
|
||||
|
||||
static void mtip_no_dev_cleanup(struct request *rq, void *data, bool reserv)
|
||||
{
|
||||
struct driver_data *dd = (struct driver_data *)data;
|
||||
struct mtip_cmd *cmd;
|
||||
|
||||
if (likely(!reserv))
|
||||
blk_mq_complete_request(rq, -ENODEV);
|
||||
else if (test_bit(MTIP_PF_IC_ACTIVE_BIT, &dd->port->flags)) {
|
||||
|
||||
cmd = mtip_cmd_from_tag(dd, MTIP_TAG_INTERNAL);
|
||||
if (cmd->comp_func)
|
||||
cmd->comp_func(dd->port, MTIP_TAG_INTERNAL,
|
||||
cmd, -ENODEV);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Block layer deinitialization function.
|
||||
*
|
||||
|
@ -4032,12 +4167,23 @@ static int mtip_block_remove(struct driver_data *dd)
|
|||
}
|
||||
}
|
||||
|
||||
if (!dd->sr)
|
||||
mtip_standby_drive(dd);
|
||||
if (!dd->sr) {
|
||||
/*
|
||||
* Explicitly wait here for IOs to quiesce,
|
||||
* as mtip_standby_drive usually won't wait for IOs.
|
||||
*/
|
||||
if (!mtip_quiesce_io(dd->port, MTIP_QUIESCE_IO_TIMEOUT_MS,
|
||||
GFP_KERNEL))
|
||||
mtip_standby_drive(dd);
|
||||
}
|
||||
else
|
||||
dev_info(&dd->pdev->dev, "device %s surprise removal\n",
|
||||
dd->disk->disk_name);
|
||||
|
||||
blk_mq_freeze_queue_start(dd->queue);
|
||||
blk_mq_stop_hw_queues(dd->queue);
|
||||
blk_mq_all_tag_busy_iter(dd->tags.tags[0], mtip_no_dev_cleanup, dd);
|
||||
|
||||
/*
|
||||
* Delete our gendisk structure. This also removes the device
|
||||
* from /dev
|
||||
|
@ -4047,7 +4193,8 @@ static int mtip_block_remove(struct driver_data *dd)
|
|||
dd->bdev = NULL;
|
||||
}
|
||||
if (dd->disk) {
|
||||
del_gendisk(dd->disk);
|
||||
if (test_bit(MTIP_DDF_INIT_DONE_BIT, &dd->dd_flag))
|
||||
del_gendisk(dd->disk);
|
||||
if (dd->disk->queue) {
|
||||
blk_cleanup_queue(dd->queue);
|
||||
blk_mq_free_tag_set(&dd->tags);
|
||||
|
@ -4088,7 +4235,8 @@ static int mtip_block_shutdown(struct driver_data *dd)
|
|||
dev_info(&dd->pdev->dev,
|
||||
"Shutting down %s ...\n", dd->disk->disk_name);
|
||||
|
||||
del_gendisk(dd->disk);
|
||||
if (test_bit(MTIP_DDF_INIT_DONE_BIT, &dd->dd_flag))
|
||||
del_gendisk(dd->disk);
|
||||
if (dd->disk->queue) {
|
||||
blk_cleanup_queue(dd->queue);
|
||||
blk_mq_free_tag_set(&dd->tags);
|
||||
|
@ -4433,7 +4581,7 @@ static void mtip_pci_remove(struct pci_dev *pdev)
|
|||
struct driver_data *dd = pci_get_drvdata(pdev);
|
||||
unsigned long flags, to;
|
||||
|
||||
set_bit(MTIP_DDF_REMOVE_PENDING_BIT, &dd->dd_flag);
|
||||
set_bit(MTIP_DDF_REMOVAL_BIT, &dd->dd_flag);
|
||||
|
||||
spin_lock_irqsave(&dev_lock, flags);
|
||||
list_del_init(&dd->online_list);
|
||||
|
@ -4450,12 +4598,17 @@ static void mtip_pci_remove(struct pci_dev *pdev)
|
|||
} while (atomic_read(&dd->irq_workers_active) != 0 &&
|
||||
time_before(jiffies, to));
|
||||
|
||||
if (!dd->sr)
|
||||
fsync_bdev(dd->bdev);
|
||||
|
||||
if (atomic_read(&dd->irq_workers_active) != 0) {
|
||||
dev_warn(&dd->pdev->dev,
|
||||
"Completion workers still active!\n");
|
||||
}
|
||||
|
||||
blk_mq_stop_hw_queues(dd->queue);
|
||||
blk_set_queue_dying(dd->queue);
|
||||
set_bit(MTIP_DDF_REMOVE_PENDING_BIT, &dd->dd_flag);
|
||||
|
||||
/* Clean up the block layer. */
|
||||
mtip_block_remove(dd);
|
||||
|
||||
|
|
|
@ -134,16 +134,24 @@ enum {
|
|||
MTIP_PF_EH_ACTIVE_BIT = 1, /* error handling */
|
||||
MTIP_PF_SE_ACTIVE_BIT = 2, /* secure erase */
|
||||
MTIP_PF_DM_ACTIVE_BIT = 3, /* download microcde */
|
||||
MTIP_PF_TO_ACTIVE_BIT = 9, /* timeout handling */
|
||||
MTIP_PF_PAUSE_IO = ((1 << MTIP_PF_IC_ACTIVE_BIT) |
|
||||
(1 << MTIP_PF_EH_ACTIVE_BIT) |
|
||||
(1 << MTIP_PF_SE_ACTIVE_BIT) |
|
||||
(1 << MTIP_PF_DM_ACTIVE_BIT)),
|
||||
(1 << MTIP_PF_DM_ACTIVE_BIT) |
|
||||
(1 << MTIP_PF_TO_ACTIVE_BIT)),
|
||||
|
||||
MTIP_PF_SVC_THD_ACTIVE_BIT = 4,
|
||||
MTIP_PF_ISSUE_CMDS_BIT = 5,
|
||||
MTIP_PF_REBUILD_BIT = 6,
|
||||
MTIP_PF_SVC_THD_STOP_BIT = 8,
|
||||
|
||||
MTIP_PF_SVC_THD_WORK = ((1 << MTIP_PF_EH_ACTIVE_BIT) |
|
||||
(1 << MTIP_PF_ISSUE_CMDS_BIT) |
|
||||
(1 << MTIP_PF_REBUILD_BIT) |
|
||||
(1 << MTIP_PF_SVC_THD_STOP_BIT) |
|
||||
(1 << MTIP_PF_TO_ACTIVE_BIT)),
|
||||
|
||||
/* below are bit numbers in 'dd_flag' defined in driver_data */
|
||||
MTIP_DDF_SEC_LOCK_BIT = 0,
|
||||
MTIP_DDF_REMOVE_PENDING_BIT = 1,
|
||||
|
@ -153,6 +161,7 @@ enum {
|
|||
MTIP_DDF_RESUME_BIT = 6,
|
||||
MTIP_DDF_INIT_DONE_BIT = 7,
|
||||
MTIP_DDF_REBUILD_FAILED_BIT = 8,
|
||||
MTIP_DDF_REMOVAL_BIT = 9,
|
||||
|
||||
MTIP_DDF_STOP_IO = ((1 << MTIP_DDF_REMOVE_PENDING_BIT) |
|
||||
(1 << MTIP_DDF_SEC_LOCK_BIT) |
|
||||
|
|
|
@ -1955,7 +1955,7 @@ static struct ceph_osd_request *rbd_osd_req_create(
|
|||
|
||||
osdc = &rbd_dev->rbd_client->client->osdc;
|
||||
osd_req = ceph_osdc_alloc_request(osdc, snapc, num_ops, false,
|
||||
GFP_ATOMIC);
|
||||
GFP_NOIO);
|
||||
if (!osd_req)
|
||||
return NULL; /* ENOMEM */
|
||||
|
||||
|
@ -2004,7 +2004,7 @@ rbd_osd_req_create_copyup(struct rbd_obj_request *obj_request)
|
|||
rbd_dev = img_request->rbd_dev;
|
||||
osdc = &rbd_dev->rbd_client->client->osdc;
|
||||
osd_req = ceph_osdc_alloc_request(osdc, snapc, num_osd_ops,
|
||||
false, GFP_ATOMIC);
|
||||
false, GFP_NOIO);
|
||||
if (!osd_req)
|
||||
return NULL; /* ENOMEM */
|
||||
|
||||
|
@ -2506,7 +2506,7 @@ static int rbd_img_request_fill(struct rbd_img_request *img_request,
|
|||
bio_chain_clone_range(&bio_list,
|
||||
&bio_offset,
|
||||
clone_size,
|
||||
GFP_ATOMIC);
|
||||
GFP_NOIO);
|
||||
if (!obj_request->bio_list)
|
||||
goto out_unwind;
|
||||
} else if (type == OBJ_REQUEST_PAGES) {
|
||||
|
|
|
@ -82,6 +82,7 @@ static const struct usb_device_id ath3k_table[] = {
|
|||
{ USB_DEVICE(0x0489, 0xe05f) },
|
||||
{ USB_DEVICE(0x0489, 0xe076) },
|
||||
{ USB_DEVICE(0x0489, 0xe078) },
|
||||
{ USB_DEVICE(0x0489, 0xe095) },
|
||||
{ USB_DEVICE(0x04c5, 0x1330) },
|
||||
{ USB_DEVICE(0x04CA, 0x3004) },
|
||||
{ USB_DEVICE(0x04CA, 0x3005) },
|
||||
|
@ -92,6 +93,7 @@ static const struct usb_device_id ath3k_table[] = {
|
|||
{ USB_DEVICE(0x04CA, 0x300d) },
|
||||
{ USB_DEVICE(0x04CA, 0x300f) },
|
||||
{ USB_DEVICE(0x04CA, 0x3010) },
|
||||
{ USB_DEVICE(0x04CA, 0x3014) },
|
||||
{ USB_DEVICE(0x0930, 0x0219) },
|
||||
{ USB_DEVICE(0x0930, 0x021c) },
|
||||
{ USB_DEVICE(0x0930, 0x0220) },
|
||||
|
@ -113,10 +115,12 @@ static const struct usb_device_id ath3k_table[] = {
|
|||
{ USB_DEVICE(0x13d3, 0x3362) },
|
||||
{ USB_DEVICE(0x13d3, 0x3375) },
|
||||
{ USB_DEVICE(0x13d3, 0x3393) },
|
||||
{ USB_DEVICE(0x13d3, 0x3395) },
|
||||
{ USB_DEVICE(0x13d3, 0x3402) },
|
||||
{ USB_DEVICE(0x13d3, 0x3408) },
|
||||
{ USB_DEVICE(0x13d3, 0x3423) },
|
||||
{ USB_DEVICE(0x13d3, 0x3432) },
|
||||
{ USB_DEVICE(0x13d3, 0x3472) },
|
||||
{ USB_DEVICE(0x13d3, 0x3474) },
|
||||
|
||||
/* Atheros AR5BBU12 with sflash firmware */
|
||||
|
@ -144,6 +148,7 @@ static const struct usb_device_id ath3k_blist_tbl[] = {
|
|||
{ USB_DEVICE(0x0489, 0xe05f), .driver_info = BTUSB_ATH3012 },
|
||||
{ USB_DEVICE(0x0489, 0xe076), .driver_info = BTUSB_ATH3012 },
|
||||
{ USB_DEVICE(0x0489, 0xe078), .driver_info = BTUSB_ATH3012 },
|
||||
{ USB_DEVICE(0x0489, 0xe095), .driver_info = BTUSB_ATH3012 },
|
||||
{ USB_DEVICE(0x04c5, 0x1330), .driver_info = BTUSB_ATH3012 },
|
||||
{ USB_DEVICE(0x04ca, 0x3004), .driver_info = BTUSB_ATH3012 },
|
||||
{ USB_DEVICE(0x04ca, 0x3005), .driver_info = BTUSB_ATH3012 },
|
||||
|
@ -154,6 +159,7 @@ static const struct usb_device_id ath3k_blist_tbl[] = {
|
|||
{ USB_DEVICE(0x04ca, 0x300d), .driver_info = BTUSB_ATH3012 },
|
||||
{ USB_DEVICE(0x04ca, 0x300f), .driver_info = BTUSB_ATH3012 },
|
||||
{ USB_DEVICE(0x04ca, 0x3010), .driver_info = BTUSB_ATH3012 },
|
||||
{ USB_DEVICE(0x04ca, 0x3014), .driver_info = BTUSB_ATH3012 },
|
||||
{ USB_DEVICE(0x0930, 0x0219), .driver_info = BTUSB_ATH3012 },
|
||||
{ USB_DEVICE(0x0930, 0x021c), .driver_info = BTUSB_ATH3012 },
|
||||
{ USB_DEVICE(0x0930, 0x0220), .driver_info = BTUSB_ATH3012 },
|
||||
|
@ -175,10 +181,12 @@ static const struct usb_device_id ath3k_blist_tbl[] = {
|
|||
{ USB_DEVICE(0x13d3, 0x3362), .driver_info = BTUSB_ATH3012 },
|
||||
{ USB_DEVICE(0x13d3, 0x3375), .driver_info = BTUSB_ATH3012 },
|
||||
{ USB_DEVICE(0x13d3, 0x3393), .driver_info = BTUSB_ATH3012 },
|
||||
{ USB_DEVICE(0x13d3, 0x3395), .driver_info = BTUSB_ATH3012 },
|
||||
{ USB_DEVICE(0x13d3, 0x3402), .driver_info = BTUSB_ATH3012 },
|
||||
{ USB_DEVICE(0x13d3, 0x3408), .driver_info = BTUSB_ATH3012 },
|
||||
{ USB_DEVICE(0x13d3, 0x3423), .driver_info = BTUSB_ATH3012 },
|
||||
{ USB_DEVICE(0x13d3, 0x3432), .driver_info = BTUSB_ATH3012 },
|
||||
{ USB_DEVICE(0x13d3, 0x3472), .driver_info = BTUSB_ATH3012 },
|
||||
{ USB_DEVICE(0x13d3, 0x3474), .driver_info = BTUSB_ATH3012 },
|
||||
|
||||
/* Atheros AR5BBU22 with sflash firmware */
|
||||
|
|
|
@ -196,6 +196,7 @@ static const struct usb_device_id blacklist_table[] = {
|
|||
{ USB_DEVICE(0x0489, 0xe05f), .driver_info = BTUSB_ATH3012 },
|
||||
{ USB_DEVICE(0x0489, 0xe076), .driver_info = BTUSB_ATH3012 },
|
||||
{ USB_DEVICE(0x0489, 0xe078), .driver_info = BTUSB_ATH3012 },
|
||||
{ USB_DEVICE(0x0489, 0xe095), .driver_info = BTUSB_ATH3012 },
|
||||
{ USB_DEVICE(0x04c5, 0x1330), .driver_info = BTUSB_ATH3012 },
|
||||
{ USB_DEVICE(0x04ca, 0x3004), .driver_info = BTUSB_ATH3012 },
|
||||
{ USB_DEVICE(0x04ca, 0x3005), .driver_info = BTUSB_ATH3012 },
|
||||
|
@ -206,6 +207,7 @@ static const struct usb_device_id blacklist_table[] = {
|
|||
{ USB_DEVICE(0x04ca, 0x300d), .driver_info = BTUSB_ATH3012 },
|
||||
{ USB_DEVICE(0x04ca, 0x300f), .driver_info = BTUSB_ATH3012 },
|
||||
{ USB_DEVICE(0x04ca, 0x3010), .driver_info = BTUSB_ATH3012 },
|
||||
{ USB_DEVICE(0x04ca, 0x3014), .driver_info = BTUSB_ATH3012 },
|
||||
{ USB_DEVICE(0x0930, 0x0219), .driver_info = BTUSB_ATH3012 },
|
||||
{ USB_DEVICE(0x0930, 0x021c), .driver_info = BTUSB_ATH3012 },
|
||||
{ USB_DEVICE(0x0930, 0x0220), .driver_info = BTUSB_ATH3012 },
|
||||
|
@ -227,10 +229,12 @@ static const struct usb_device_id blacklist_table[] = {
|
|||
{ USB_DEVICE(0x13d3, 0x3362), .driver_info = BTUSB_ATH3012 },
|
||||
{ USB_DEVICE(0x13d3, 0x3375), .driver_info = BTUSB_ATH3012 },
|
||||
{ USB_DEVICE(0x13d3, 0x3393), .driver_info = BTUSB_ATH3012 },
|
||||
{ USB_DEVICE(0x13d3, 0x3395), .driver_info = BTUSB_ATH3012 },
|
||||
{ USB_DEVICE(0x13d3, 0x3402), .driver_info = BTUSB_ATH3012 },
|
||||
{ USB_DEVICE(0x13d3, 0x3408), .driver_info = BTUSB_ATH3012 },
|
||||
{ USB_DEVICE(0x13d3, 0x3423), .driver_info = BTUSB_ATH3012 },
|
||||
{ USB_DEVICE(0x13d3, 0x3432), .driver_info = BTUSB_ATH3012 },
|
||||
{ USB_DEVICE(0x13d3, 0x3472), .driver_info = BTUSB_ATH3012 },
|
||||
{ USB_DEVICE(0x13d3, 0x3474), .driver_info = BTUSB_ATH3012 },
|
||||
|
||||
/* Atheros AR5BBU12 with sflash firmware */
|
||||
|
|
|
@ -136,11 +136,13 @@ struct tpm_chip *tpmm_chip_alloc(struct device *dev,
|
|||
chip->cdev.owner = chip->pdev->driver->owner;
|
||||
chip->cdev.kobj.parent = &chip->dev.kobj;
|
||||
|
||||
devm_add_action(dev, (void (*)(void *)) put_device, &chip->dev);
|
||||
|
||||
return chip;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(tpmm_chip_alloc);
|
||||
|
||||
static int tpm_dev_add_device(struct tpm_chip *chip)
|
||||
static int tpm_add_char_device(struct tpm_chip *chip)
|
||||
{
|
||||
int rc;
|
||||
|
||||
|
@ -151,7 +153,6 @@ static int tpm_dev_add_device(struct tpm_chip *chip)
|
|||
chip->devname, MAJOR(chip->dev.devt),
|
||||
MINOR(chip->dev.devt), rc);
|
||||
|
||||
device_unregister(&chip->dev);
|
||||
return rc;
|
||||
}
|
||||
|
||||
|
@ -162,16 +163,17 @@ static int tpm_dev_add_device(struct tpm_chip *chip)
|
|||
chip->devname, MAJOR(chip->dev.devt),
|
||||
MINOR(chip->dev.devt), rc);
|
||||
|
||||
cdev_del(&chip->cdev);
|
||||
return rc;
|
||||
}
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
static void tpm_dev_del_device(struct tpm_chip *chip)
|
||||
static void tpm_del_char_device(struct tpm_chip *chip)
|
||||
{
|
||||
cdev_del(&chip->cdev);
|
||||
device_unregister(&chip->dev);
|
||||
device_del(&chip->dev);
|
||||
}
|
||||
|
||||
static int tpm1_chip_register(struct tpm_chip *chip)
|
||||
|
@ -222,7 +224,7 @@ int tpm_chip_register(struct tpm_chip *chip)
|
|||
|
||||
tpm_add_ppi(chip);
|
||||
|
||||
rc = tpm_dev_add_device(chip);
|
||||
rc = tpm_add_char_device(chip);
|
||||
if (rc)
|
||||
goto out_err;
|
||||
|
||||
|
@ -274,6 +276,6 @@ void tpm_chip_unregister(struct tpm_chip *chip)
|
|||
sysfs_remove_link(&chip->pdev->kobj, "ppi");
|
||||
|
||||
tpm1_chip_unregister(chip);
|
||||
tpm_dev_del_device(chip);
|
||||
tpm_del_char_device(chip);
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(tpm_chip_unregister);
|
||||
|
|
|
@ -310,11 +310,11 @@ static int crb_acpi_remove(struct acpi_device *device)
|
|||
struct device *dev = &device->dev;
|
||||
struct tpm_chip *chip = dev_get_drvdata(dev);
|
||||
|
||||
tpm_chip_unregister(chip);
|
||||
|
||||
if (chip->flags & TPM_CHIP_FLAG_TPM2)
|
||||
tpm2_shutdown(chip, TPM2_SU_CLEAR);
|
||||
|
||||
tpm_chip_unregister(chip);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
|
@ -232,7 +232,7 @@ static int tpm_binary_bios_measurements_show(struct seq_file *m, void *v)
|
|||
{
|
||||
struct tcpa_event *event = v;
|
||||
struct tcpa_event temp_event;
|
||||
char *tempPtr;
|
||||
char *temp_ptr;
|
||||
int i;
|
||||
|
||||
memcpy(&temp_event, event, sizeof(struct tcpa_event));
|
||||
|
@ -242,10 +242,16 @@ static int tpm_binary_bios_measurements_show(struct seq_file *m, void *v)
|
|||
temp_event.event_type = do_endian_conversion(event->event_type);
|
||||
temp_event.event_size = do_endian_conversion(event->event_size);
|
||||
|
||||
tempPtr = (char *)&temp_event;
|
||||
temp_ptr = (char *) &temp_event;
|
||||
|
||||
for (i = 0; i < sizeof(struct tcpa_event) + temp_event.event_size; i++)
|
||||
seq_putc(m, tempPtr[i]);
|
||||
for (i = 0; i < (sizeof(struct tcpa_event) - 1) ; i++)
|
||||
seq_putc(m, temp_ptr[i]);
|
||||
|
||||
temp_ptr = (char *) v;
|
||||
|
||||
for (i = (sizeof(struct tcpa_event) - 1);
|
||||
i < (sizeof(struct tcpa_event) + temp_event.event_size); i++)
|
||||
seq_putc(m, temp_ptr[i]);
|
||||
|
||||
return 0;
|
||||
|
||||
|
|
|
@ -1097,13 +1097,15 @@ static int bcm2835_pll_divider_set_rate(struct clk_hw *hw,
|
|||
struct bcm2835_pll_divider *divider = bcm2835_pll_divider_from_hw(hw);
|
||||
struct bcm2835_cprman *cprman = divider->cprman;
|
||||
const struct bcm2835_pll_divider_data *data = divider->data;
|
||||
u32 cm;
|
||||
int ret;
|
||||
u32 cm, div, max_div = 1 << A2W_PLL_DIV_BITS;
|
||||
|
||||
ret = clk_divider_ops.set_rate(hw, rate, parent_rate);
|
||||
if (ret)
|
||||
return ret;
|
||||
div = DIV_ROUND_UP_ULL(parent_rate, rate);
|
||||
|
||||
div = min(div, max_div);
|
||||
if (div == max_div)
|
||||
div = 0;
|
||||
|
||||
cprman_write(cprman, data->a2w_reg, div);
|
||||
cm = cprman_read(cprman, data->cm_reg);
|
||||
cprman_write(cprman, data->cm_reg, cm | data->load_mask);
|
||||
cprman_write(cprman, data->cm_reg, cm & ~data->load_mask);
|
||||
|
|
|
@ -718,6 +718,7 @@ static const char *const rk3188_critical_clocks[] __initconst = {
|
|||
"hclk_peri",
|
||||
"pclk_cpu",
|
||||
"pclk_peri",
|
||||
"hclk_cpubus"
|
||||
};
|
||||
|
||||
static void __init rk3188_common_clk_init(struct device_node *np)
|
||||
|
|
|
@ -165,7 +165,7 @@ static const struct rockchip_cpuclk_reg_data rk3368_cpuclkb_data = {
|
|||
.core_reg = RK3368_CLKSEL_CON(0),
|
||||
.div_core_shift = 0,
|
||||
.div_core_mask = 0x1f,
|
||||
.mux_core_shift = 15,
|
||||
.mux_core_shift = 7,
|
||||
};
|
||||
|
||||
static const struct rockchip_cpuclk_reg_data rk3368_cpuclkl_data = {
|
||||
|
@ -218,29 +218,29 @@ static const struct rockchip_cpuclk_reg_data rk3368_cpuclkl_data = {
|
|||
}
|
||||
|
||||
static struct rockchip_cpuclk_rate_table rk3368_cpuclkb_rates[] __initdata = {
|
||||
RK3368_CPUCLKB_RATE(1512000000, 2, 6, 6),
|
||||
RK3368_CPUCLKB_RATE(1488000000, 2, 5, 5),
|
||||
RK3368_CPUCLKB_RATE(1416000000, 2, 5, 5),
|
||||
RK3368_CPUCLKB_RATE(1200000000, 2, 4, 4),
|
||||
RK3368_CPUCLKB_RATE(1008000000, 2, 4, 4),
|
||||
RK3368_CPUCLKB_RATE( 816000000, 2, 3, 3),
|
||||
RK3368_CPUCLKB_RATE( 696000000, 2, 3, 3),
|
||||
RK3368_CPUCLKB_RATE( 600000000, 2, 2, 2),
|
||||
RK3368_CPUCLKB_RATE( 408000000, 2, 2, 2),
|
||||
RK3368_CPUCLKB_RATE( 312000000, 2, 2, 2),
|
||||
RK3368_CPUCLKB_RATE(1512000000, 1, 5, 5),
|
||||
RK3368_CPUCLKB_RATE(1488000000, 1, 4, 4),
|
||||
RK3368_CPUCLKB_RATE(1416000000, 1, 4, 4),
|
||||
RK3368_CPUCLKB_RATE(1200000000, 1, 3, 3),
|
||||
RK3368_CPUCLKB_RATE(1008000000, 1, 3, 3),
|
||||
RK3368_CPUCLKB_RATE( 816000000, 1, 2, 2),
|
||||
RK3368_CPUCLKB_RATE( 696000000, 1, 2, 2),
|
||||
RK3368_CPUCLKB_RATE( 600000000, 1, 1, 1),
|
||||
RK3368_CPUCLKB_RATE( 408000000, 1, 1, 1),
|
||||
RK3368_CPUCLKB_RATE( 312000000, 1, 1, 1),
|
||||
};
|
||||
|
||||
static struct rockchip_cpuclk_rate_table rk3368_cpuclkl_rates[] __initdata = {
|
||||
RK3368_CPUCLKL_RATE(1512000000, 2, 7, 7),
|
||||
RK3368_CPUCLKL_RATE(1488000000, 2, 6, 6),
|
||||
RK3368_CPUCLKL_RATE(1416000000, 2, 6, 6),
|
||||
RK3368_CPUCLKL_RATE(1200000000, 2, 5, 5),
|
||||
RK3368_CPUCLKL_RATE(1008000000, 2, 5, 5),
|
||||
RK3368_CPUCLKL_RATE( 816000000, 2, 4, 4),
|
||||
RK3368_CPUCLKL_RATE( 696000000, 2, 3, 3),
|
||||
RK3368_CPUCLKL_RATE( 600000000, 2, 3, 3),
|
||||
RK3368_CPUCLKL_RATE( 408000000, 2, 2, 2),
|
||||
RK3368_CPUCLKL_RATE( 312000000, 2, 2, 2),
|
||||
RK3368_CPUCLKL_RATE(1512000000, 1, 6, 6),
|
||||
RK3368_CPUCLKL_RATE(1488000000, 1, 5, 5),
|
||||
RK3368_CPUCLKL_RATE(1416000000, 1, 5, 5),
|
||||
RK3368_CPUCLKL_RATE(1200000000, 1, 4, 4),
|
||||
RK3368_CPUCLKL_RATE(1008000000, 1, 4, 4),
|
||||
RK3368_CPUCLKL_RATE( 816000000, 1, 3, 3),
|
||||
RK3368_CPUCLKL_RATE( 696000000, 1, 2, 2),
|
||||
RK3368_CPUCLKL_RATE( 600000000, 1, 2, 2),
|
||||
RK3368_CPUCLKL_RATE( 408000000, 1, 1, 1),
|
||||
RK3368_CPUCLKL_RATE( 312000000, 1, 1, 1),
|
||||
};
|
||||
|
||||
static struct rockchip_clk_branch rk3368_clk_branches[] __initdata = {
|
||||
|
@ -384,10 +384,10 @@ static struct rockchip_clk_branch rk3368_clk_branches[] __initdata = {
|
|||
* Clock-Architecture Diagram 3
|
||||
*/
|
||||
|
||||
COMPOSITE(0, "aclk_vepu", mux_pll_src_cpll_gpll_usb_p, 0,
|
||||
COMPOSITE(0, "aclk_vepu", mux_pll_src_cpll_gpll_npll_usb_p, 0,
|
||||
RK3368_CLKSEL_CON(15), 6, 2, MFLAGS, 0, 5, DFLAGS,
|
||||
RK3368_CLKGATE_CON(4), 6, GFLAGS),
|
||||
COMPOSITE(0, "aclk_vdpu", mux_pll_src_cpll_gpll_usb_p, 0,
|
||||
COMPOSITE(0, "aclk_vdpu", mux_pll_src_cpll_gpll_npll_usb_p, 0,
|
||||
RK3368_CLKSEL_CON(15), 14, 2, MFLAGS, 8, 5, DFLAGS,
|
||||
RK3368_CLKGATE_CON(4), 7, GFLAGS),
|
||||
|
||||
|
@ -442,7 +442,7 @@ static struct rockchip_clk_branch rk3368_clk_branches[] __initdata = {
|
|||
GATE(SCLK_HDMI_HDCP, "sclk_hdmi_hdcp", "xin24m", 0,
|
||||
RK3368_CLKGATE_CON(4), 13, GFLAGS),
|
||||
GATE(SCLK_HDMI_CEC, "sclk_hdmi_cec", "xin32k", 0,
|
||||
RK3368_CLKGATE_CON(5), 12, GFLAGS),
|
||||
RK3368_CLKGATE_CON(4), 12, GFLAGS),
|
||||
|
||||
COMPOSITE_NODIV(0, "vip_src", mux_pll_src_cpll_gpll_p, 0,
|
||||
RK3368_CLKSEL_CON(21), 15, 1, MFLAGS,
|
||||
|
|
|
@ -31,9 +31,8 @@
|
|||
|
||||
struct private_data {
|
||||
struct device *cpu_dev;
|
||||
struct regulator *cpu_reg;
|
||||
struct thermal_cooling_device *cdev;
|
||||
unsigned int voltage_tolerance; /* in percentage */
|
||||
const char *reg_name;
|
||||
};
|
||||
|
||||
static struct freq_attr *cpufreq_dt_attr[] = {
|
||||
|
@ -44,175 +43,128 @@ static struct freq_attr *cpufreq_dt_attr[] = {
|
|||
|
||||
static int set_target(struct cpufreq_policy *policy, unsigned int index)
|
||||
{
|
||||
struct dev_pm_opp *opp;
|
||||
struct cpufreq_frequency_table *freq_table = policy->freq_table;
|
||||
struct clk *cpu_clk = policy->clk;
|
||||
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 int old_freq, new_freq;
|
||||
long freq_Hz, freq_exact;
|
||||
int ret;
|
||||
|
||||
freq_Hz = clk_round_rate(cpu_clk, freq_table[index].frequency * 1000);
|
||||
if (freq_Hz <= 0)
|
||||
freq_Hz = freq_table[index].frequency * 1000;
|
||||
|
||||
freq_exact = freq_Hz;
|
||||
new_freq = freq_Hz / 1000;
|
||||
old_freq = clk_get_rate(cpu_clk) / 1000;
|
||||
|
||||
if (!IS_ERR(cpu_reg)) {
|
||||
unsigned long opp_freq;
|
||||
|
||||
rcu_read_lock();
|
||||
opp = dev_pm_opp_find_freq_ceil(cpu_dev, &freq_Hz);
|
||||
if (IS_ERR(opp)) {
|
||||
rcu_read_unlock();
|
||||
dev_err(cpu_dev, "failed to find OPP for %ld\n",
|
||||
freq_Hz);
|
||||
return PTR_ERR(opp);
|
||||
}
|
||||
volt = dev_pm_opp_get_voltage(opp);
|
||||
opp_freq = dev_pm_opp_get_freq(opp);
|
||||
rcu_read_unlock();
|
||||
tol = volt * priv->voltage_tolerance / 100;
|
||||
volt_old = regulator_get_voltage(cpu_reg);
|
||||
dev_dbg(cpu_dev, "Found OPP: %ld kHz, %ld uV\n",
|
||||
opp_freq / 1000, volt);
|
||||
}
|
||||
|
||||
dev_dbg(cpu_dev, "%u MHz, %ld mV --> %u MHz, %ld mV\n",
|
||||
old_freq / 1000, (volt_old > 0) ? volt_old / 1000 : -1,
|
||||
new_freq / 1000, volt ? volt / 1000 : -1);
|
||||
|
||||
/* scaling up? scale voltage before frequency */
|
||||
if (!IS_ERR(cpu_reg) && new_freq > old_freq) {
|
||||
ret = regulator_set_voltage_tol(cpu_reg, volt, tol);
|
||||
if (ret) {
|
||||
dev_err(cpu_dev, "failed to scale voltage up: %d\n",
|
||||
ret);
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
|
||||
ret = clk_set_rate(cpu_clk, freq_exact);
|
||||
if (ret) {
|
||||
dev_err(cpu_dev, "failed to set clock rate: %d\n", ret);
|
||||
if (!IS_ERR(cpu_reg) && volt_old > 0)
|
||||
regulator_set_voltage_tol(cpu_reg, volt_old, tol);
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* scaling down? scale voltage after frequency */
|
||||
if (!IS_ERR(cpu_reg) && new_freq < old_freq) {
|
||||
ret = regulator_set_voltage_tol(cpu_reg, volt, tol);
|
||||
if (ret) {
|
||||
dev_err(cpu_dev, "failed to scale voltage down: %d\n",
|
||||
ret);
|
||||
clk_set_rate(cpu_clk, old_freq * 1000);
|
||||
}
|
||||
}
|
||||
|
||||
return ret;
|
||||
return dev_pm_opp_set_rate(priv->cpu_dev,
|
||||
policy->freq_table[index].frequency * 1000);
|
||||
}
|
||||
|
||||
static int allocate_resources(int cpu, struct device **cdev,
|
||||
struct regulator **creg, struct clk **cclk)
|
||||
/*
|
||||
* An earlier version of opp-v1 bindings used to name the regulator
|
||||
* "cpu0-supply", we still need to handle that for backwards compatibility.
|
||||
*/
|
||||
static const char *find_supply_name(struct device *dev)
|
||||
{
|
||||
struct device_node *np;
|
||||
struct property *pp;
|
||||
int cpu = dev->id;
|
||||
const char *name = NULL;
|
||||
|
||||
np = of_node_get(dev->of_node);
|
||||
|
||||
/* This must be valid for sure */
|
||||
if (WARN_ON(!np))
|
||||
return NULL;
|
||||
|
||||
/* Try "cpu0" for older DTs */
|
||||
if (!cpu) {
|
||||
pp = of_find_property(np, "cpu0-supply", NULL);
|
||||
if (pp) {
|
||||
name = "cpu0";
|
||||
goto node_put;
|
||||
}
|
||||
}
|
||||
|
||||
pp = of_find_property(np, "cpu-supply", NULL);
|
||||
if (pp) {
|
||||
name = "cpu";
|
||||
goto node_put;
|
||||
}
|
||||
|
||||
dev_dbg(dev, "no regulator for cpu%d\n", cpu);
|
||||
node_put:
|
||||
of_node_put(np);
|
||||
return name;
|
||||
}
|
||||
|
||||
static int resources_available(void)
|
||||
{
|
||||
struct device *cpu_dev;
|
||||
struct regulator *cpu_reg;
|
||||
struct clk *cpu_clk;
|
||||
int ret = 0;
|
||||
char *reg_cpu0 = "cpu0", *reg_cpu = "cpu", *reg;
|
||||
const char *name;
|
||||
|
||||
cpu_dev = get_cpu_device(cpu);
|
||||
cpu_dev = get_cpu_device(0);
|
||||
if (!cpu_dev) {
|
||||
pr_err("failed to get cpu%d device\n", cpu);
|
||||
pr_err("failed to get cpu0 device\n");
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
/* Try "cpu0" for older DTs */
|
||||
if (!cpu)
|
||||
reg = reg_cpu0;
|
||||
else
|
||||
reg = reg_cpu;
|
||||
|
||||
try_again:
|
||||
cpu_reg = regulator_get_optional(cpu_dev, reg);
|
||||
if (IS_ERR(cpu_reg)) {
|
||||
/*
|
||||
* If cpu's regulator supply node is present, but regulator is
|
||||
* not yet registered, we should try defering probe.
|
||||
*/
|
||||
if (PTR_ERR(cpu_reg) == -EPROBE_DEFER) {
|
||||
dev_dbg(cpu_dev, "cpu%d regulator not ready, retry\n",
|
||||
cpu);
|
||||
return -EPROBE_DEFER;
|
||||
}
|
||||
|
||||
/* Try with "cpu-supply" */
|
||||
if (reg == reg_cpu0) {
|
||||
reg = reg_cpu;
|
||||
goto try_again;
|
||||
}
|
||||
|
||||
dev_dbg(cpu_dev, "no regulator for cpu%d: %ld\n",
|
||||
cpu, PTR_ERR(cpu_reg));
|
||||
}
|
||||
|
||||
cpu_clk = clk_get(cpu_dev, NULL);
|
||||
if (IS_ERR(cpu_clk)) {
|
||||
/* put regulator */
|
||||
if (!IS_ERR(cpu_reg))
|
||||
regulator_put(cpu_reg);
|
||||
|
||||
ret = PTR_ERR(cpu_clk);
|
||||
|
||||
ret = PTR_ERR_OR_ZERO(cpu_clk);
|
||||
if (ret) {
|
||||
/*
|
||||
* If cpu's clk node is present, but clock is not yet
|
||||
* registered, we should try defering probe.
|
||||
*/
|
||||
if (ret == -EPROBE_DEFER)
|
||||
dev_dbg(cpu_dev, "cpu%d clock not ready, retry\n", cpu);
|
||||
dev_dbg(cpu_dev, "clock not ready, retry\n");
|
||||
else
|
||||
dev_err(cpu_dev, "failed to get cpu%d clock: %d\n", cpu,
|
||||
ret);
|
||||
} else {
|
||||
*cdev = cpu_dev;
|
||||
*creg = cpu_reg;
|
||||
*cclk = cpu_clk;
|
||||
dev_err(cpu_dev, "failed to get clock: %d\n", ret);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
return ret;
|
||||
clk_put(cpu_clk);
|
||||
|
||||
name = find_supply_name(cpu_dev);
|
||||
/* Platform doesn't require regulator */
|
||||
if (!name)
|
||||
return 0;
|
||||
|
||||
cpu_reg = regulator_get_optional(cpu_dev, name);
|
||||
ret = PTR_ERR_OR_ZERO(cpu_reg);
|
||||
if (ret) {
|
||||
/*
|
||||
* If cpu's regulator supply node is present, but regulator is
|
||||
* not yet registered, we should try defering probe.
|
||||
*/
|
||||
if (ret == -EPROBE_DEFER)
|
||||
dev_dbg(cpu_dev, "cpu0 regulator not ready, retry\n");
|
||||
else
|
||||
dev_dbg(cpu_dev, "no regulator for cpu0: %d\n", ret);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
regulator_put(cpu_reg);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int cpufreq_init(struct cpufreq_policy *policy)
|
||||
{
|
||||
struct cpufreq_frequency_table *freq_table;
|
||||
struct device_node *np;
|
||||
struct private_data *priv;
|
||||
struct device *cpu_dev;
|
||||
struct regulator *cpu_reg;
|
||||
struct clk *cpu_clk;
|
||||
struct dev_pm_opp *suspend_opp;
|
||||
unsigned long min_uV = ~0, max_uV = 0;
|
||||
unsigned int transition_latency;
|
||||
bool need_update = false;
|
||||
bool opp_v1 = false;
|
||||
const char *name;
|
||||
int ret;
|
||||
|
||||
ret = allocate_resources(policy->cpu, &cpu_dev, &cpu_reg, &cpu_clk);
|
||||
if (ret) {
|
||||
pr_err("%s: Failed to allocate resources: %d\n", __func__, ret);
|
||||
return ret;
|
||||
cpu_dev = get_cpu_device(policy->cpu);
|
||||
if (!cpu_dev) {
|
||||
pr_err("failed to get cpu%d device\n", policy->cpu);
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
np = of_node_get(cpu_dev->of_node);
|
||||
if (!np) {
|
||||
dev_err(cpu_dev, "failed to find cpu%d node\n", policy->cpu);
|
||||
ret = -ENOENT;
|
||||
goto out_put_reg_clk;
|
||||
cpu_clk = clk_get(cpu_dev, NULL);
|
||||
if (IS_ERR(cpu_clk)) {
|
||||
ret = PTR_ERR(cpu_clk);
|
||||
dev_err(cpu_dev, "%s: failed to get clk: %d\n", __func__, ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* Get OPP-sharing information from "operating-points-v2" bindings */
|
||||
|
@ -223,9 +175,23 @@ static int cpufreq_init(struct cpufreq_policy *policy)
|
|||
* finding shared-OPPs for backward compatibility.
|
||||
*/
|
||||
if (ret == -ENOENT)
|
||||
need_update = true;
|
||||
opp_v1 = true;
|
||||
else
|
||||
goto out_node_put;
|
||||
goto out_put_clk;
|
||||
}
|
||||
|
||||
/*
|
||||
* OPP layer will be taking care of regulators now, but it needs to know
|
||||
* the name of the regulator first.
|
||||
*/
|
||||
name = find_supply_name(cpu_dev);
|
||||
if (name) {
|
||||
ret = dev_pm_opp_set_regulator(cpu_dev, name);
|
||||
if (ret) {
|
||||
dev_err(cpu_dev, "Failed to set regulator for cpu%d: %d\n",
|
||||
policy->cpu, ret);
|
||||
goto out_put_clk;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -246,12 +212,12 @@ static int cpufreq_init(struct cpufreq_policy *policy)
|
|||
*/
|
||||
ret = dev_pm_opp_get_opp_count(cpu_dev);
|
||||
if (ret <= 0) {
|
||||
pr_debug("OPP table is not ready, deferring probe\n");
|
||||
dev_dbg(cpu_dev, "OPP table is not ready, deferring probe\n");
|
||||
ret = -EPROBE_DEFER;
|
||||
goto out_free_opp;
|
||||
}
|
||||
|
||||
if (need_update) {
|
||||
if (opp_v1) {
|
||||
struct cpufreq_dt_platform_data *pd = cpufreq_get_driver_data();
|
||||
|
||||
if (!pd || !pd->independent_clocks)
|
||||
|
@ -265,10 +231,6 @@ static int cpufreq_init(struct cpufreq_policy *policy)
|
|||
if (ret)
|
||||
dev_err(cpu_dev, "%s: failed to mark OPPs as shared: %d\n",
|
||||
__func__, ret);
|
||||
|
||||
of_property_read_u32(np, "clock-latency", &transition_latency);
|
||||
} else {
|
||||
transition_latency = dev_pm_opp_get_max_clock_latency(cpu_dev);
|
||||
}
|
||||
|
||||
priv = kzalloc(sizeof(*priv), GFP_KERNEL);
|
||||
|
@ -277,62 +239,16 @@ static int cpufreq_init(struct cpufreq_policy *policy)
|
|||
goto out_free_opp;
|
||||
}
|
||||
|
||||
of_property_read_u32(np, "voltage-tolerance", &priv->voltage_tolerance);
|
||||
|
||||
if (!transition_latency)
|
||||
transition_latency = CPUFREQ_ETERNAL;
|
||||
|
||||
if (!IS_ERR(cpu_reg)) {
|
||||
unsigned long opp_freq = 0;
|
||||
|
||||
/*
|
||||
* Disable any OPPs where the connected regulator isn't able to
|
||||
* provide the specified voltage and record minimum and maximum
|
||||
* voltage levels.
|
||||
*/
|
||||
while (1) {
|
||||
struct dev_pm_opp *opp;
|
||||
unsigned long opp_uV, tol_uV;
|
||||
|
||||
rcu_read_lock();
|
||||
opp = dev_pm_opp_find_freq_ceil(cpu_dev, &opp_freq);
|
||||
if (IS_ERR(opp)) {
|
||||
rcu_read_unlock();
|
||||
break;
|
||||
}
|
||||
opp_uV = dev_pm_opp_get_voltage(opp);
|
||||
rcu_read_unlock();
|
||||
|
||||
tol_uV = opp_uV * priv->voltage_tolerance / 100;
|
||||
if (regulator_is_supported_voltage(cpu_reg,
|
||||
opp_uV - tol_uV,
|
||||
opp_uV + tol_uV)) {
|
||||
if (opp_uV < min_uV)
|
||||
min_uV = opp_uV;
|
||||
if (opp_uV > max_uV)
|
||||
max_uV = opp_uV;
|
||||
} else {
|
||||
dev_pm_opp_disable(cpu_dev, opp_freq);
|
||||
}
|
||||
|
||||
opp_freq++;
|
||||
}
|
||||
|
||||
ret = regulator_set_voltage_time(cpu_reg, min_uV, max_uV);
|
||||
if (ret > 0)
|
||||
transition_latency += ret * 1000;
|
||||
}
|
||||
priv->reg_name = name;
|
||||
|
||||
ret = dev_pm_opp_init_cpufreq_table(cpu_dev, &freq_table);
|
||||
if (ret) {
|
||||
pr_err("failed to init cpufreq table: %d\n", ret);
|
||||
dev_err(cpu_dev, "failed to init cpufreq table: %d\n", ret);
|
||||
goto out_free_priv;
|
||||
}
|
||||
|
||||
priv->cpu_dev = cpu_dev;
|
||||
priv->cpu_reg = cpu_reg;
|
||||
policy->driver_data = priv;
|
||||
|
||||
policy->clk = cpu_clk;
|
||||
|
||||
rcu_read_lock();
|
||||
|
@ -357,9 +273,11 @@ static int cpufreq_init(struct cpufreq_policy *policy)
|
|||
cpufreq_dt_attr[1] = &cpufreq_freq_attr_scaling_boost_freqs;
|
||||
}
|
||||
|
||||
policy->cpuinfo.transition_latency = transition_latency;
|
||||
transition_latency = dev_pm_opp_get_max_transition_latency(cpu_dev);
|
||||
if (!transition_latency)
|
||||
transition_latency = CPUFREQ_ETERNAL;
|
||||
|
||||
of_node_put(np);
|
||||
policy->cpuinfo.transition_latency = transition_latency;
|
||||
|
||||
return 0;
|
||||
|
||||
|
@ -369,12 +287,10 @@ out_free_priv:
|
|||
kfree(priv);
|
||||
out_free_opp:
|
||||
dev_pm_opp_of_cpumask_remove_table(policy->cpus);
|
||||
out_node_put:
|
||||
of_node_put(np);
|
||||
out_put_reg_clk:
|
||||
if (name)
|
||||
dev_pm_opp_put_regulator(cpu_dev);
|
||||
out_put_clk:
|
||||
clk_put(cpu_clk);
|
||||
if (!IS_ERR(cpu_reg))
|
||||
regulator_put(cpu_reg);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
@ -386,9 +302,10 @@ static int cpufreq_exit(struct cpufreq_policy *policy)
|
|||
cpufreq_cooling_unregister(priv->cdev);
|
||||
dev_pm_opp_free_cpufreq_table(priv->cpu_dev, &policy->freq_table);
|
||||
dev_pm_opp_of_cpumask_remove_table(policy->related_cpus);
|
||||
if (priv->reg_name)
|
||||
dev_pm_opp_put_regulator(priv->cpu_dev);
|
||||
|
||||
clk_put(policy->clk);
|
||||
if (!IS_ERR(priv->cpu_reg))
|
||||
regulator_put(priv->cpu_reg);
|
||||
kfree(priv);
|
||||
|
||||
return 0;
|
||||
|
@ -407,8 +324,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",
|
||||
|
@ -436,9 +358,6 @@ static struct cpufreq_driver dt_cpufreq_driver = {
|
|||
|
||||
static int dt_cpufreq_probe(struct platform_device *pdev)
|
||||
{
|
||||
struct device *cpu_dev;
|
||||
struct regulator *cpu_reg;
|
||||
struct clk *cpu_clk;
|
||||
int ret;
|
||||
|
||||
/*
|
||||
|
@ -448,19 +367,15 @@ static int dt_cpufreq_probe(struct platform_device *pdev)
|
|||
*
|
||||
* FIXME: Is checking this only for CPU0 sufficient ?
|
||||
*/
|
||||
ret = allocate_resources(0, &cpu_dev, &cpu_reg, &cpu_clk);
|
||||
ret = resources_available();
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
clk_put(cpu_clk);
|
||||
if (!IS_ERR(cpu_reg))
|
||||
regulator_put(cpu_reg);
|
||||
|
||||
dt_cpufreq_driver.driver_data = dev_get_platdata(&pdev->dev);
|
||||
|
||||
ret = cpufreq_register_driver(&dt_cpufreq_driver);
|
||||
if (ret)
|
||||
dev_err(cpu_dev, "failed register driver: %d\n", ret);
|
||||
dev_err(&pdev->dev, "failed register driver: %d\n", ret);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
|
|
@ -1396,9 +1396,9 @@ static int atmel_aes_probe(struct platform_device *pdev)
|
|||
}
|
||||
|
||||
aes_dd->io_base = devm_ioremap_resource(&pdev->dev, aes_res);
|
||||
if (!aes_dd->io_base) {
|
||||
if (IS_ERR(aes_dd->io_base)) {
|
||||
dev_err(dev, "can't ioremap\n");
|
||||
err = -ENOMEM;
|
||||
err = PTR_ERR(aes_dd->io_base);
|
||||
goto res_err;
|
||||
}
|
||||
|
||||
|
|
|
@ -1405,9 +1405,9 @@ static int atmel_sha_probe(struct platform_device *pdev)
|
|||
}
|
||||
|
||||
sha_dd->io_base = devm_ioremap_resource(&pdev->dev, sha_res);
|
||||
if (!sha_dd->io_base) {
|
||||
if (IS_ERR(sha_dd->io_base)) {
|
||||
dev_err(dev, "can't ioremap\n");
|
||||
err = -ENOMEM;
|
||||
err = PTR_ERR(sha_dd->io_base);
|
||||
goto res_err;
|
||||
}
|
||||
|
||||
|
|
|
@ -1417,9 +1417,9 @@ static int atmel_tdes_probe(struct platform_device *pdev)
|
|||
}
|
||||
|
||||
tdes_dd->io_base = devm_ioremap_resource(&pdev->dev, tdes_res);
|
||||
if (!tdes_dd->io_base) {
|
||||
if (IS_ERR(tdes_dd->io_base)) {
|
||||
dev_err(dev, "can't ioremap\n");
|
||||
err = -ENOMEM;
|
||||
err = PTR_ERR(tdes_dd->io_base);
|
||||
goto res_err;
|
||||
}
|
||||
|
||||
|
|
|
@ -220,6 +220,39 @@ static int ccp_aes_cmac_digest(struct ahash_request *req)
|
|||
return ccp_aes_cmac_finup(req);
|
||||
}
|
||||
|
||||
static int ccp_aes_cmac_export(struct ahash_request *req, void *out)
|
||||
{
|
||||
struct ccp_aes_cmac_req_ctx *rctx = ahash_request_ctx(req);
|
||||
struct ccp_aes_cmac_exp_ctx state;
|
||||
|
||||
state.null_msg = rctx->null_msg;
|
||||
memcpy(state.iv, rctx->iv, sizeof(state.iv));
|
||||
state.buf_count = rctx->buf_count;
|
||||
memcpy(state.buf, rctx->buf, sizeof(state.buf));
|
||||
|
||||
/* 'out' may not be aligned so memcpy from local variable */
|
||||
memcpy(out, &state, sizeof(state));
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int ccp_aes_cmac_import(struct ahash_request *req, const void *in)
|
||||
{
|
||||
struct ccp_aes_cmac_req_ctx *rctx = ahash_request_ctx(req);
|
||||
struct ccp_aes_cmac_exp_ctx state;
|
||||
|
||||
/* 'in' may not be aligned so memcpy to local variable */
|
||||
memcpy(&state, in, sizeof(state));
|
||||
|
||||
memset(rctx, 0, sizeof(*rctx));
|
||||
rctx->null_msg = state.null_msg;
|
||||
memcpy(rctx->iv, state.iv, sizeof(rctx->iv));
|
||||
rctx->buf_count = state.buf_count;
|
||||
memcpy(rctx->buf, state.buf, sizeof(rctx->buf));
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int ccp_aes_cmac_setkey(struct crypto_ahash *tfm, const u8 *key,
|
||||
unsigned int key_len)
|
||||
{
|
||||
|
@ -352,10 +385,13 @@ int ccp_register_aes_cmac_algs(struct list_head *head)
|
|||
alg->final = ccp_aes_cmac_final;
|
||||
alg->finup = ccp_aes_cmac_finup;
|
||||
alg->digest = ccp_aes_cmac_digest;
|
||||
alg->export = ccp_aes_cmac_export;
|
||||
alg->import = ccp_aes_cmac_import;
|
||||
alg->setkey = ccp_aes_cmac_setkey;
|
||||
|
||||
halg = &alg->halg;
|
||||
halg->digestsize = AES_BLOCK_SIZE;
|
||||
halg->statesize = sizeof(struct ccp_aes_cmac_exp_ctx);
|
||||
|
||||
base = &halg->base;
|
||||
snprintf(base->cra_name, CRYPTO_MAX_ALG_NAME, "cmac(aes)");
|
||||
|
|
|
@ -207,6 +207,43 @@ static int ccp_sha_digest(struct ahash_request *req)
|
|||
return ccp_sha_finup(req);
|
||||
}
|
||||
|
||||
static int ccp_sha_export(struct ahash_request *req, void *out)
|
||||
{
|
||||
struct ccp_sha_req_ctx *rctx = ahash_request_ctx(req);
|
||||
struct ccp_sha_exp_ctx state;
|
||||
|
||||
state.type = rctx->type;
|
||||
state.msg_bits = rctx->msg_bits;
|
||||
state.first = rctx->first;
|
||||
memcpy(state.ctx, rctx->ctx, sizeof(state.ctx));
|
||||
state.buf_count = rctx->buf_count;
|
||||
memcpy(state.buf, rctx->buf, sizeof(state.buf));
|
||||
|
||||
/* 'out' may not be aligned so memcpy from local variable */
|
||||
memcpy(out, &state, sizeof(state));
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int ccp_sha_import(struct ahash_request *req, const void *in)
|
||||
{
|
||||
struct ccp_sha_req_ctx *rctx = ahash_request_ctx(req);
|
||||
struct ccp_sha_exp_ctx state;
|
||||
|
||||
/* 'in' may not be aligned so memcpy to local variable */
|
||||
memcpy(&state, in, sizeof(state));
|
||||
|
||||
memset(rctx, 0, sizeof(*rctx));
|
||||
rctx->type = state.type;
|
||||
rctx->msg_bits = state.msg_bits;
|
||||
rctx->first = state.first;
|
||||
memcpy(rctx->ctx, state.ctx, sizeof(rctx->ctx));
|
||||
rctx->buf_count = state.buf_count;
|
||||
memcpy(rctx->buf, state.buf, sizeof(rctx->buf));
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int ccp_sha_setkey(struct crypto_ahash *tfm, const u8 *key,
|
||||
unsigned int key_len)
|
||||
{
|
||||
|
@ -403,9 +440,12 @@ static int ccp_register_sha_alg(struct list_head *head,
|
|||
alg->final = ccp_sha_final;
|
||||
alg->finup = ccp_sha_finup;
|
||||
alg->digest = ccp_sha_digest;
|
||||
alg->export = ccp_sha_export;
|
||||
alg->import = ccp_sha_import;
|
||||
|
||||
halg = &alg->halg;
|
||||
halg->digestsize = def->digest_size;
|
||||
halg->statesize = sizeof(struct ccp_sha_exp_ctx);
|
||||
|
||||
base = &halg->base;
|
||||
snprintf(base->cra_name, CRYPTO_MAX_ALG_NAME, "%s", def->name);
|
||||
|
|
|
@ -129,6 +129,15 @@ struct ccp_aes_cmac_req_ctx {
|
|||
struct ccp_cmd cmd;
|
||||
};
|
||||
|
||||
struct ccp_aes_cmac_exp_ctx {
|
||||
unsigned int null_msg;
|
||||
|
||||
u8 iv[AES_BLOCK_SIZE];
|
||||
|
||||
unsigned int buf_count;
|
||||
u8 buf[AES_BLOCK_SIZE];
|
||||
};
|
||||
|
||||
/***** SHA related defines *****/
|
||||
#define MAX_SHA_CONTEXT_SIZE SHA256_DIGEST_SIZE
|
||||
#define MAX_SHA_BLOCK_SIZE SHA256_BLOCK_SIZE
|
||||
|
@ -171,6 +180,19 @@ struct ccp_sha_req_ctx {
|
|||
struct ccp_cmd cmd;
|
||||
};
|
||||
|
||||
struct ccp_sha_exp_ctx {
|
||||
enum ccp_sha_type type;
|
||||
|
||||
u64 msg_bits;
|
||||
|
||||
unsigned int first;
|
||||
|
||||
u8 ctx[MAX_SHA_CONTEXT_SIZE];
|
||||
|
||||
unsigned int buf_count;
|
||||
u8 buf[MAX_SHA_BLOCK_SIZE];
|
||||
};
|
||||
|
||||
/***** Common Context Structure *****/
|
||||
struct ccp_ctx {
|
||||
int (*complete)(struct crypto_async_request *req, int ret);
|
||||
|
|
|
@ -420,7 +420,7 @@ static int mv_cesa_probe(struct platform_device *pdev)
|
|||
res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "regs");
|
||||
cesa->regs = devm_ioremap_resource(dev, res);
|
||||
if (IS_ERR(cesa->regs))
|
||||
return -ENOMEM;
|
||||
return PTR_ERR(cesa->regs);
|
||||
|
||||
ret = mv_cesa_dev_dma_init(cesa);
|
||||
if (ret)
|
||||
|
|
|
@ -1440,9 +1440,9 @@ static int ux500_cryp_probe(struct platform_device *pdev)
|
|||
|
||||
device_data->phybase = res->start;
|
||||
device_data->base = devm_ioremap_resource(dev, res);
|
||||
if (!device_data->base) {
|
||||
if (IS_ERR(device_data->base)) {
|
||||
dev_err(dev, "[%s]: ioremap failed!", __func__);
|
||||
ret = -ENOMEM;
|
||||
ret = PTR_ERR(device_data->base);
|
||||
goto out;
|
||||
}
|
||||
|
||||
|
|
|
@ -1675,9 +1675,9 @@ static int ux500_hash_probe(struct platform_device *pdev)
|
|||
|
||||
device_data->phybase = res->start;
|
||||
device_data->base = devm_ioremap_resource(dev, res);
|
||||
if (!device_data->base) {
|
||||
if (IS_ERR(device_data->base)) {
|
||||
dev_err(dev, "%s: ioremap() failed!\n", __func__);
|
||||
ret = -ENOMEM;
|
||||
ret = PTR_ERR(device_data->base);
|
||||
goto out;
|
||||
}
|
||||
spin_lock_init(&device_data->ctx_lock);
|
||||
|
|
|
@ -1452,7 +1452,7 @@ static u64 f1x_get_norm_dct_addr(struct amd64_pvt *pvt, u8 range,
|
|||
u64 chan_off;
|
||||
u64 dram_base = get_dram_base(pvt, range);
|
||||
u64 hole_off = f10_dhar_offset(pvt);
|
||||
u64 dct_sel_base_off = (pvt->dct_sel_hi & 0xFFFFFC00) << 16;
|
||||
u64 dct_sel_base_off = (u64)(pvt->dct_sel_hi & 0xFFFFFC00) << 16;
|
||||
|
||||
if (hi_rng) {
|
||||
/*
|
||||
|
|
|
@ -1117,8 +1117,8 @@ static void get_memory_layout(const struct mem_ctl_info *mci)
|
|||
edac_dbg(0, "TAD#%d: up to %u.%03u GB (0x%016Lx), socket interleave %d, memory interleave %d, TGT: %d, %d, %d, %d, reg=0x%08x\n",
|
||||
n_tads, gb, (mb*1000)/1024,
|
||||
((u64)tmp_mb) << 20L,
|
||||
(u32)TAD_SOCK(reg),
|
||||
(u32)TAD_CH(reg),
|
||||
(u32)(1 << TAD_SOCK(reg)),
|
||||
(u32)TAD_CH(reg) + 1,
|
||||
(u32)TAD_TGT0(reg),
|
||||
(u32)TAD_TGT1(reg),
|
||||
(u32)TAD_TGT2(reg),
|
||||
|
@ -1396,7 +1396,7 @@ static int get_memory_error_data(struct mem_ctl_info *mci,
|
|||
}
|
||||
|
||||
ch_way = TAD_CH(reg) + 1;
|
||||
sck_way = TAD_SOCK(reg) + 1;
|
||||
sck_way = 1 << TAD_SOCK(reg);
|
||||
|
||||
if (ch_way == 3)
|
||||
idx = addr >> 6;
|
||||
|
@ -1453,7 +1453,7 @@ static int get_memory_error_data(struct mem_ctl_info *mci,
|
|||
n_tads,
|
||||
addr,
|
||||
limit,
|
||||
(u32)TAD_SOCK(reg),
|
||||
sck_way,
|
||||
ch_way,
|
||||
offset,
|
||||
idx,
|
||||
|
@ -1468,18 +1468,12 @@ static int get_memory_error_data(struct mem_ctl_info *mci,
|
|||
offset, addr);
|
||||
return -EINVAL;
|
||||
}
|
||||
addr -= offset;
|
||||
/* Store the low bits [0:6] of the addr */
|
||||
ch_addr = addr & 0x7f;
|
||||
/* Remove socket wayness and remove 6 bits */
|
||||
addr >>= 6;
|
||||
addr = div_u64(addr, sck_xch);
|
||||
#if 0
|
||||
/* Divide by channel way */
|
||||
addr = addr / ch_way;
|
||||
#endif
|
||||
/* Recover the last 6 bits */
|
||||
ch_addr |= addr << 6;
|
||||
|
||||
ch_addr = addr - offset;
|
||||
ch_addr >>= (6 + shiftup);
|
||||
ch_addr /= ch_way * sck_way;
|
||||
ch_addr <<= (6 + shiftup);
|
||||
ch_addr |= addr & ((1 << (6 + shiftup)) - 1);
|
||||
|
||||
/*
|
||||
* Step 3) Decode rank
|
||||
|
|
|
@ -63,6 +63,10 @@ bool amdgpu_has_atpx(void) {
|
|||
return amdgpu_atpx_priv.atpx_detected;
|
||||
}
|
||||
|
||||
bool amdgpu_has_atpx_dgpu_power_cntl(void) {
|
||||
return amdgpu_atpx_priv.atpx.functions.power_cntl;
|
||||
}
|
||||
|
||||
/**
|
||||
* amdgpu_atpx_call - call an ATPX method
|
||||
*
|
||||
|
@ -142,10 +146,6 @@ static void amdgpu_atpx_parse_functions(struct amdgpu_atpx_functions *f, u32 mas
|
|||
*/
|
||||
static int amdgpu_atpx_validate(struct amdgpu_atpx *atpx)
|
||||
{
|
||||
/* make sure required functions are enabled */
|
||||
/* dGPU power control is required */
|
||||
atpx->functions.power_cntl = true;
|
||||
|
||||
if (atpx->functions.px_params) {
|
||||
union acpi_object *info;
|
||||
struct atpx_px_params output;
|
||||
|
|
Some files were not shown because too many files have changed in this diff Show more
Loading…
Add table
Reference in a new issue