Merge "spi-geni-qcom: Support to disable runtime PM autosuspend" into msm-4.9
diff --git a/Documentation/ABI/testing/sysfs-devices-system-cpu b/Documentation/ABI/testing/sysfs-devices-system-cpu
index dfd56ec..6d75a9c 100644
--- a/Documentation/ABI/testing/sysfs-devices-system-cpu
+++ b/Documentation/ABI/testing/sysfs-devices-system-cpu
@@ -355,6 +355,7 @@
/sys/devices/system/cpu/vulnerabilities/meltdown
/sys/devices/system/cpu/vulnerabilities/spectre_v1
/sys/devices/system/cpu/vulnerabilities/spectre_v2
+ /sys/devices/system/cpu/vulnerabilities/spec_store_bypass
Date: January 2018
Contact: Linux kernel mailing list <linux-kernel@vger.kernel.org>
Description: Information about CPU vulnerabilities
diff --git a/Documentation/devicetree/bindings/arm/coresight.txt b/Documentation/devicetree/bindings/arm/coresight.txt
index 3a96610..ee9b465 100644
--- a/Documentation/devicetree/bindings/arm/coresight.txt
+++ b/Documentation/devicetree/bindings/arm/coresight.txt
@@ -110,6 +110,9 @@
* cpu: the cpu phandle this ETM/PTM is affined to. When omitted the
source is considered to belong to CPU0.
+ * qcom,tupwr-disable: For ETM, don't keep trace unit powered across power
+ collapse.
+
* Optional property for TMC:
* arm,buffer-size: size of contiguous buffer space for TMC ETR
diff --git a/Documentation/devicetree/bindings/arm/msm/msm.txt b/Documentation/devicetree/bindings/arm/msm/msm.txt
index 9df16fb..b2640da 100644
--- a/Documentation/devicetree/bindings/arm/msm/msm.txt
+++ b/Documentation/devicetree/bindings/arm/msm/msm.txt
@@ -95,6 +95,9 @@
- QCS605
compatible = "qcom,qcs605"
+- SXR1120
+ compatible = "qcom,sxr1120"
+
- SDA670
compatible = "qcom,sda670"
@@ -324,6 +327,8 @@
compatible = "qcom,sdm670-qrd"
compatible = "qcom,qcs605-cdp"
compatible = "qcom,qcs605-mtp"
+compatible = "qcom,sxr1120-mtp"
+compatible = "qcom,sxr1120-cdp"
compatible = "qcom,sda670-cdp"
compatible = "qcom,sda670-mtp"
compatible = "qcom,sda670-hdk"
@@ -383,4 +388,5 @@
compatible = "qcom,sdxpoorwills-atp"
compatible = "qcom,sdxpoorwills-mtp"
compatible = "qcom,sdxpoorwills-cdp"
+compatible = "qcom,sdxpoorwills-ttp"
compatible = "qcom,mdm9607-ttp"
diff --git a/Documentation/devicetree/bindings/display/msm/sde.txt b/Documentation/devicetree/bindings/display/msm/sde.txt
index 0589165..15f1e93 100644
--- a/Documentation/devicetree/bindings/display/msm/sde.txt
+++ b/Documentation/devicetree/bindings/display/msm/sde.txt
@@ -103,6 +103,8 @@
- qcom,sde-dsc-size: A u32 value indicates the address range for each dsc.
- qcom,sde-cdm-size: A u32 value indicates the address range for each cdm.
- qcom,sde-pp-size: A u32 value indicates the address range for each pingpong.
+- qcom,sde-te-source: Array of GPIO sources indicating which pingpong TE is
+ sourced to which panel TE gpio.
- qcom,sde-wb-size: A u32 value indicates the address range for each writeback.
- qcom,sde-len: A u32 entry for SDE address range.
- qcom,sde-intf-max-prefetch-lines: Array of u32 values for max prefetch lines on
@@ -502,6 +504,7 @@
qcom,sde-pp-off = <0x00071000 0x00071800
0x00072000 0x00072800>;
qcom,sde-pp-slave = <0x0 0x0 0x0 0x0>;
+ qcom,sde-te-source = <0x0 0x1 0x0 0x0>;
qcom,sde-cdm-off = <0x0007a200>;
qcom,sde-dsc-off = <0x00081000 0x00081400>;
qcom,sde-intf-max-prefetch-lines = <0x15 0x15 0x15 0x15>;
diff --git a/Documentation/devicetree/bindings/fb/mdss-dsi-panel.txt b/Documentation/devicetree/bindings/fb/mdss-dsi-panel.txt
index 73a6dbc..7454863 100644
--- a/Documentation/devicetree/bindings/fb/mdss-dsi-panel.txt
+++ b/Documentation/devicetree/bindings/fb/mdss-dsi-panel.txt
@@ -285,6 +285,35 @@
60 = 60 frames per second (default)
- qcom,mdss-dsi-panel-clockrate: A 64 bit value specifies the panel clock speed in Hz.
0 = default value.
+- qcom,mdss-mdp-kickoff-threshold: This property can be used to define a region
+ (in terms of scanlines) where the
+hardware is allowed
+ to trigger a data transfer from MDP to DSI.
+ If this property is used, the region must be defined setting
+ two values, the low and the high thresholds:
+ <low_threshold high_threshold>
+ Where following condition must be met:
+ low_threshold < high_threshold
+ These values will be used by the driver in such way that if
+ the Driver receives a request to kickoff a transfer (MDP to DSI),
+ the transfer will be triggered only if the following condition
+ is satisfied:
+ low_threshold < scanline < high_threshold
+ If the condition is not met, then the driver will delay the
+ transfer by the time defined in the following property:
+ "qcom,mdss-mdp-kickoff-delay".
+ So in order to use this property, the delay property must
+ be defined as well and greater than 0.
+- qcom,mdss-mdp-kickoff-delay: This property defines the delay in microseconds that
+ the driver will delay before triggering an MDP transfer if the
+ thresholds defined by the following property are not met:
+ "qcom,mdss-mdp-kickoff-threshold".
+ So in order to use this property, the threshold property must
+ be defined as well. Note that this delay cannot be zero
+ and also should not be greater than
+the fps window.
+ i.e. For 60fps value should not exceed
+16666 uS.
- qcom,mdss-mdp-transfer-time-us: Specifies the dsi transfer time for command mode
panels in microseconds. Driver uses this number to adjust
the clock rate according to the expected transfer time.
@@ -634,6 +663,8 @@
qcom,mdss-dsi-dma-trigger = <0>;
qcom,mdss-dsi-panel-framerate = <60>;
qcom,mdss-dsi-panel-clockrate = <424000000>;
+ qcom,mdss-mdp-kickoff-threshold = <11 2430>;
+ qcom,mdss-mdp-kickoff-delay = <1000>;
qcom,mdss-mdp-transfer-time-us = <12500>;
qcom,mdss-dsi-panel-timings = [7d 25 1d 00 37 33
22 27 1e 03 04 00];
diff --git a/Documentation/devicetree/bindings/fb/mdss-dsi.txt b/Documentation/devicetree/bindings/fb/mdss-dsi.txt
index 1934bc5..2d689d2 100644
--- a/Documentation/devicetree/bindings/fb/mdss-dsi.txt
+++ b/Documentation/devicetree/bindings/fb/mdss-dsi.txt
@@ -113,6 +113,7 @@
- qcom,platform-bklight-en-gpio-invert: Invert the gpio used to enable display back-light
- qcom,panel-mode-gpio: Specifies the GPIO to select video/command/single-port/dual-port
mode of panel through gpio when it supports these modes.
+- qcom,ext-vdd-gpio: Specifies the GPIO to enable external VDD supply.
- pinctrl-names: List of names to assign mdss pin states defined in pinctrl device node
Refer to pinctrl-bindings.txt
- pinctrl-<0..n>: Lists phandles each pointing to the pin configuration node within a pin
diff --git a/Documentation/devicetree/bindings/fb/mdss-spi-client.txt b/Documentation/devicetree/bindings/fb/mdss-spi-client.txt
new file mode 100644
index 0000000..0d5fde8
--- /dev/null
+++ b/Documentation/devicetree/bindings/fb/mdss-spi-client.txt
@@ -0,0 +1,27 @@
+Qualcomm Technologies, Inc. mdss-spi-client
+
+mdss-spi-client is for SPI display to send the FB data to SPI master.
+
+Required properties:
+- compatible : should be "qcom,mdss-spi-client"
+- spi-max-frequency : Maximum SPI clocking speed of device in Hz
+
+Optional properties:
+- label: A string used to describe the controller used.
+- spi-cpol : Boolean property indicating device requires inverse
+ clock polarity (CPOL) mode
+- spi-cpha : Empty property indicating device requires shifted
+ clock phase (CPHA) mode
+- spi-cs-high : Empty property indicating device requires
+ chip select active high
+
+Example:
+spi@78b9000 { /* BLSP1 QUP5 */
+ qcom,mdss_spi_client {
+ reg = <0>;
+ compatible = "qcom,mdss-spi-client";
+ label = "MDSS SPI QUP5 CLIENT";
+ spi-max-frequency = <50000000>;
+ };
+};
+
diff --git a/Documentation/devicetree/bindings/fb/mdss-spi-panel.txt b/Documentation/devicetree/bindings/fb/mdss-spi-panel.txt
new file mode 100644
index 0000000..d46068f
--- /dev/null
+++ b/Documentation/devicetree/bindings/fb/mdss-spi-panel.txt
@@ -0,0 +1,203 @@
+Qualcomm Technologies, Inc. mdss-spi-panel
+
+mdss-spi-panel is a SPI panel device which supports panels that
+are compatible with display serial interface specification.
+
+Required properties:
+- qcom,mdss-spi-panel-controller: Specifies the phandle for the SPI controller that
+ this panel will be mapped to.
+- qcom,mdss-spi-panel-width: Specifies panel width in pixels.
+- qcom,mdss-spi-panel-height: Specifies panel height in pixels.
+- qcom,mdss-spi-bpp: Specifies the panel bits per pixels.
+ 3 = for rgb111
+ 8 = for rgb332
+ 12 = for rgb444
+ 16 = for rgb565
+ 18 = for rgb666
+ 24 = for rgb888
+- qcom,mdss-spi-panel-destination: A string that specifies the destination display for the panel.
+ "display_1" = DISPLAY_1
+ "display_2" = DISPLAY_2
+- qcom,mdss-spi-on-command: A byte stream formed by multiple packets
+ byte 0: wait number of specified ms after command
+ transmitted
+ byte 1: 8 bits length in network byte order
+ byte 3 and beyond: number byte of payload
+- qcom,mdss-spi-off-command: A byte stream formed by multiple packets
+ byte 0: wait number of specified ms after command
+ transmitted
+ byte 1: 8 bits length in network byte order
+ byte 3 and beyond: number byte of payload
+Optional properties:
+- qcom,mdss-spi-panel-name: A string used as a descriptive name of the panel
+- qcom,cont-splash-enabled: Boolean used to enable continuous splash mode.
+ If this property is specified, it is required to
+ to specify the memory reserved for the splash
+ screen using the qcom,memblock-reserve binding
+ for the framebuffer device attached to the panel.
+- qcom,mdss-spi-h-back-porch: Horizontal back porch value in pixels.
+ 6 = default value.
+- qcom,mdss-spi-h-front-porch: Horizontal front porch value in pixels.
+ 6 = default value.
+- qcom,mdss-spi-h-pulse-width: Horizontal pulse width.
+ 2 = default value.
+- qcom,mdss-spi-h-sync-skew: Horizontal sync skew value.
+ 0 = default value.
+- qcom,mdss-spi-v-back-porch: Vertical back porch value in pixels.
+ 6 = default value.
+- qcom,mdss-spi-v-front-porch: Vertical front porch value in pixels.
+ 6 = default value.
+- qcom,mdss-spi-v-pulse-width: Vertical pulse width.
+ 2 = default value.
+- qcom,mdss-spi-bl-pmic-control-type: A string that specifies the implementation of backlight
+ control for this panel.
+ "bl_ctrl_pwm" = Backlight controlled by PWM gpio.
+ "bl_ctrl_wled" = Backlight controlled by WLED.
+ other: Unknown backlight control. (default)
+- qcom,mdss-spi-bl-min-level: Specifies the min backlight level supported by the panel.
+ 0 = default value.
+- qcom,mdss-spi-bl-max-level: Specifies the max backlight level supported by the panel.
+ 255 = default value.
+- qcom,mdss-spi-panel-framerate: Specifies the frame rate for the panel.
+- qcom,esd-check-enabled: Boolean used to enable ESD recovery feature.
+- qcom,mdss-spi-panel-status-check-mode:Specifies the panel status check method for ESD recovery.
+ "send_init_command" = send init code to recover panel status.
+ "reg_read" = Read register value to check the panel status.
+- qcom,mdss-spi-panel-status-reg:Unsigned 8bits integer value to specifies the value
+ of panel status register address.
+- qcom,mdss-spi-panel-status-read-length:Unsigned 8bits integer value that specifies
+ the expected read-back length of the panel register.
+- qcom,mdss-spi-panel-status-value:An unsigned 8bits integer araray that specifies the
+ values of the panel status register which is used to
+ check the panel status.
+ The size of this array is specified by
+ qcom,mdss-dsi-panel-status-read-length.
+
+Example:
+&mdss_mdp {
+ spi_gc9305_qvga_cmd: qcom,mdss_spi_gc9305_qvga_cmd {
+ qcom,mdss-spi-panel-name = "gc9305 qvga command mode spi panel";
+ qcom,mdss-spi-panel-destination = "display_1";
+ qcom,mdss-spi-panel-controller = <&mdss_spi>;
+ qcom,mdss-spi-panel-framerate = <30>;
+ qcom,mdss-spi-panel-width = <240>;
+ qcom,mdss-spi-panel-height = <320>;
+ qcom,mdss-spi-h-front-porch = <79>;
+ qcom,mdss-spi-h-back-porch = <59>;
+ qcom,mdss-spi-h-pulse-width = <60>;
+ qcom,mdss-spi-v-back-porch = <10>;
+ qcom,mdss-spi-v-front-porch = <7>;
+ qcom,mdss-spi-v-pulse-width = <2>;
+ qcom,mdss-spi-h-left-border = <0>;
+ qcom,mdss-spi-h-right-border = <0>;
+ qcom,mdss-spi-v-top-border = <0>;
+ qcom,mdss-spi-v-bottom-border = <0>;
+ qcom,mdss-spi-bpp = <16>;
+ qcom,mdss-spi-on-command = [00 01 FE
+ 00 01 EF
+ 00 02 36 48
+ 00 02 3A 05
+ 00 02 35 00
+ 00 03 A4 44 44
+ 00 03 A5 42 42
+ 00 03 AA 88 88
+ 00 03 E8 12 40
+ 00 03 E3 01 10
+ 00 02 FF 61
+ 00 02 AC 00
+ 00 03 A6 2A 2A
+ 00 03 A7 2B 2B
+ 00 03 A8 18 18
+ 00 03 A9 2A 2A
+ 00 02 AD 33
+ 00 02 AF 55
+ 00 02 AE 2B
+ 00 05 2A 00 00 00 EF
+ 00 05 2B 00 00 01 3F
+ 00 01 2C
+ 00 07 F0 02 02 00 08 0C 10
+ 00 07 F1 01 00 00 14 1D 0E
+ 00 07 F2 10 09 37 04 04 48
+ 00 07 F3 10 0B 3F 05 05 4E
+ 00 07 F4 0D 19 17 1D 1E 0F
+ 00 07 F5 06 12 13 1A 1B 0F
+ 78 01 11
+ 00 01 29
+ 00 01 2C];
+ qcom,mdss-spi-off-command = [20 01 28
+ 20 01 10];
+ qcom,mdss-spi-bl-min-level = <1>;
+ qcom,mdss-spi-bl-max-level = <4095>;
+ qcom,esd-check-enabled;
+ qcom,mdss-spi-panel-status-check-mode = "reg_read";
+ qcom,mdss-spi-panel-status-reg = /bits/ 8 <0x09>;
+ qcom,mdss-spi-panel-status-read-length = <4>;
+ qcom,mdss-spi-panel-status-value = /bits/ 8 <0x52 0x29 0x83 0x00>;
+ };
+};
+
+mdss-spi-display is a spi interface display which support send frame
+data and command to panel, compatible with SPI interface specification.
+
+Required properties:
+- compatible: This property applies to SPI panels only.
+ compatible = "qcom,mdss-spi-display".
+- vdd-supply: Phandle for vdd regulator device node.
+- vddio-supply: Phandle for vdd-io regulator device node.
+- qcom,mdss-fb-map: pHandle that specifies the framebuffer to which the interface is mapped.
+- qcom,mdss-mdp: pHandle that specifies the mdss-mdp device.
+- qcom,panel-supply-entries: A node that lists the elements of the supply used to
+ power the DSI panel. There can be more than one instance
+ of this binding, in which case the entry would be appended
+ with the supply entry index. For a detailed description
+ fields in the supply entry, refer to the qcom,ctrl-supply-entries
+ binding above.
+- qcom,platform-spi-dc-gpio: Pull down this gpio indicate current package is command,
+ Pull up this gpio indicate current package is parameter or pixels.
+
+Optional properties:
+- label:A string used to describe the controller used.
+ -- qcom,supply-name: name of the supply (vdd/vdda/vddio)
+ -- qcom,supply-min-voltage: minimum voltage level (uV)
+ -- qcom,supply-max-voltage: maximum voltage level (uV)
+ -- qcom,supply-enable-load: load drawn (uA) from enabled supply
+ -- qcom,supply-disable-load: load drawn (uA) from disabled supply
+ -- qcom,supply-pre-on-sleep: time to sleep (ms) before turning on
+ -- qcom,supply-post-on-sleep: time to sleep (ms) after turning on
+ -- qcom,supply-pre-off-sleep: time to sleep (ms) before turning off
+ -- qcom,supply-post-off-sleep: time to sleep (ms) after turning off
+
+Example:
+ mdss_spi: qcom,mdss_spi {
+ compatible = "qcom,mdss-spi-display";
+ label = "mdss spi panel";
+
+ qcom,mdss-fb-map = <&mdss_fb0>;
+ qcom,mdss-mdp = <&mdss_mdp>;
+ vdd-supply = <&pm8909_l17>;
+ vddio-supply = <&pm8909_l6>;
+ qcom,platform-spi-dc-gpio = <&msm_gpio 110 0>;
+
+ qcom,panel-supply-entries {
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ qcom,panel-supply-entry@0 {
+ reg = <0>;
+ qcom,supply-name = "vdd";
+ qcom,supply-min-voltage = <2850000>;
+ qcom,supply-max-voltage = <2850000>;
+ qcom,supply-enable-load = <100000>;
+ qcom,supply-disable-load = <100>;
+ };
+
+ qcom,panel-supply-entry@1 {
+ reg = <1>;
+ qcom,supply-name = "vddio";
+ qcom,supply-min-voltage = <1800000>;
+ qcom,supply-max-voltage = <1800000>;
+ qcom,supply-enable-load = <100000>;
+ qcom,supply-disable-load = <100>;
+ };
+ };
+ };
diff --git a/Documentation/devicetree/bindings/platform/msm/ipa.txt b/Documentation/devicetree/bindings/platform/msm/ipa.txt
index 917c2d0..7652aa4 100644
--- a/Documentation/devicetree/bindings/platform/msm/ipa.txt
+++ b/Documentation/devicetree/bindings/platform/msm/ipa.txt
@@ -87,6 +87,8 @@
need to be unlocked by TZ.
- qcom,ipa-uc-monitor-holb: Boolean context flag to indicate whether
monitoring of holb via IPA uc is required.
+- qcom,wlan-ce-db-over-pcie: Boolean context flag to represent WLAN CE DB
+ over pcie bus or not.
IPA pipe sub nodes (A2 static pipes configurations):
diff --git a/Documentation/devicetree/bindings/power/supply/qcom/qpnp-qg.txt b/Documentation/devicetree/bindings/power/supply/qcom/qpnp-qg.txt
index 43e7380..0da71a3 100644
--- a/Documentation/devicetree/bindings/power/supply/qcom/qpnp-qg.txt
+++ b/Documentation/devicetree/bindings/power/supply/qcom/qpnp-qg.txt
@@ -295,6 +295,12 @@
attempted by QG. If not defined the value defaults
to 10%.
+- qcom,qg-ext-sns
+ Usage: optional
+ Value type: <bool>
+ Definition: Boolean property to support external-rsense based
+ configuration.
+
==========================================================
Second Level Nodes - Peripherals managed by QGAUGE driver
==========================================================
diff --git a/Documentation/devicetree/bindings/power/supply/qcom/qpnp-smb5.txt b/Documentation/devicetree/bindings/power/supply/qcom/qpnp-smb5.txt
index 8ee2749..65dcf59 100644
--- a/Documentation/devicetree/bindings/power/supply/qcom/qpnp-smb5.txt
+++ b/Documentation/devicetree/bindings/power/supply/qcom/qpnp-smb5.txt
@@ -201,6 +201,25 @@
Definition: Phandle for the VADC node, it is used to obtain USBIN_V
and USBIN_I readings on PMIC632 based platform.
+- qcom,hw-die-temp-mitigation
+ Usage: optional
+ Value type: bool
+ Definition: Boolean flag which when present enables h/w based thermal
+ mitigation.
+
+- qcom,hw-connector-mitigation
+ Usage: optional
+ Value type: bool
+ Definition: Boolean flag which when present enables h/w based
+ connector temperature mitigation.
+
+- qcom,connector-internal-pull-kohm
+ Usage: optional
+ Value type: <u32>
+ Definition: Specifies internal pull-up configuration to be applied to
+ connector THERM, only valid values are (0/30/100/400).
+ If not specified 100K is used as default pull-up.
+
=============================================
Second Level Nodes - SMB5 Charger Peripherals
=============================================
diff --git a/Documentation/devicetree/bindings/power/supply/qcom/smb1355-charger.txt b/Documentation/devicetree/bindings/power/supply/qcom/smb1355-charger.txt
index 4f12ec0..528c285 100644
--- a/Documentation/devicetree/bindings/power/supply/qcom/smb1355-charger.txt
+++ b/Documentation/devicetree/bindings/power/supply/qcom/smb1355-charger.txt
@@ -51,6 +51,18 @@
stacked one after the other and thus all the charge current
(FCC) flows through main. In a non-stacked configuration each
charger controls the charge current (FCC) separately.
+
+- qcom,die-temp-threshold-degc
+ Usage: optional
+ Value type: <u32>
+ Definition: Specifies DIE temp threshold beyond which h/w starts mitigation.
+ If not sepcified, 90 degrees centigrade is used.
+
+- qcom,hw-die-temp-mitigation
+ Usage: optional
+ Value type: bool
+ Definition: Boolean property to enable h/w controlled die temp mitigation.
+
================================================
Second Level Nodes - SMB1355 Charger Peripherals
================================================
diff --git a/Documentation/devicetree/bindings/sound/qcom-audio-dev.txt b/Documentation/devicetree/bindings/sound/qcom-audio-dev.txt
index 1e4d2c1..20cb25b 100644
--- a/Documentation/devicetree/bindings/sound/qcom-audio-dev.txt
+++ b/Documentation/devicetree/bindings/sound/qcom-audio-dev.txt
@@ -300,6 +300,11 @@
- compatible : "qcom,msm-audio-apr"
This device is added to represent APR module.
+ - qcom,subsys-name: This value provides the subsystem name where codec
+ is present. It can be "apr_modem" or "apr_adsp". This
+ property enable apr driver to receive subsystem up/down
+ notification from modem/adsp.
+
Optional properties:
- compatible : "qcom,msm-audio-apr-dummy"
@@ -664,6 +669,8 @@
msm_audio_apr_dummy {
compatible = "qcom,msm-audio-apr-dummy";
};
+
+ qcom,subsys-name = "apr_adsp";
};
qcom,msm-ocmem-audio {
diff --git a/Documentation/devicetree/bindings/thermal/tsens.txt b/Documentation/devicetree/bindings/thermal/tsens.txt
index 6ff6e9b..f25691a 100644
--- a/Documentation/devicetree/bindings/thermal/tsens.txt
+++ b/Documentation/devicetree/bindings/thermal/tsens.txt
@@ -20,6 +20,7 @@
should be "qcom,sdm845-tsens" for SDM845 TSENS driver.
should be "qcom,tsens24xx" for 2.4 TSENS controller.
should be "qcom,msm8937-tsens" for 8937 TSENS driver.
+ should be "qcom,msm8909-tsens" for 8909 TSENS driver.
The compatible property is used to identify the respective controller to use
for the corresponding SoC.
- reg : offset and length of the TSENS registers with associated property in reg-names
diff --git a/Documentation/devicetree/bindings/usb/msm-phy.txt b/Documentation/devicetree/bindings/usb/msm-phy.txt
index b880890..c28b05b 100644
--- a/Documentation/devicetree/bindings/usb/msm-phy.txt
+++ b/Documentation/devicetree/bindings/usb/msm-phy.txt
@@ -191,6 +191,8 @@
- qcom,tune2-efuse-correction: The value to be adjusted from fused value for
improved rise/fall times.
- qcom,host-chirp-erratum: Indicates host chirp fix is required.
+ - qcom,override-bias-ctrl2: Indicates override is done from driver for
+ BIAS_CTRL2 register.
- nvmem-cells: specifies the handle to represent the SoC revision.
usually it is defined by qfprom device node.
- nvmem-cell-names: specifies the given nvmem cell name as defined in
diff --git a/Documentation/kernel-parameters.txt b/Documentation/kernel-parameters.txt
index d771f95..435a509 100644
--- a/Documentation/kernel-parameters.txt
+++ b/Documentation/kernel-parameters.txt
@@ -2721,6 +2721,9 @@
allow data leaks with this option, which is equivalent
to spectre_v2=off.
+ nospec_store_bypass_disable
+ [HW] Disable all mitigations for the Speculative Store Bypass vulnerability
+
noxsave [BUGS=X86] Disables x86 extended register state save
and restore using xsave. The kernel will fallback to
enabling legacy floating-point and sse state.
@@ -3995,6 +3998,48 @@
Not specifying this option is equivalent to
spectre_v2=auto.
+ spec_store_bypass_disable=
+ [HW] Control Speculative Store Bypass (SSB) Disable mitigation
+ (Speculative Store Bypass vulnerability)
+
+ Certain CPUs are vulnerable to an exploit against a
+ a common industry wide performance optimization known
+ as "Speculative Store Bypass" in which recent stores
+ to the same memory location may not be observed by
+ later loads during speculative execution. The idea
+ is that such stores are unlikely and that they can
+ be detected prior to instruction retirement at the
+ end of a particular speculation execution window.
+
+ In vulnerable processors, the speculatively forwarded
+ store can be used in a cache side channel attack, for
+ example to read memory to which the attacker does not
+ directly have access (e.g. inside sandboxed code).
+
+ This parameter controls whether the Speculative Store
+ Bypass optimization is used.
+
+ on - Unconditionally disable Speculative Store Bypass
+ off - Unconditionally enable Speculative Store Bypass
+ auto - Kernel detects whether the CPU model contains an
+ implementation of Speculative Store Bypass and
+ picks the most appropriate mitigation. If the
+ CPU is not vulnerable, "off" is selected. If the
+ CPU is vulnerable the default mitigation is
+ architecture and Kconfig dependent. See below.
+ prctl - Control Speculative Store Bypass per thread
+ via prctl. Speculative Store Bypass is enabled
+ for a process by default. The state of the control
+ is inherited on fork.
+ seccomp - Same as "prctl" above, but all seccomp threads
+ will disable SSB unless they explicitly opt out.
+
+ Not specifying this option is equivalent to
+ spec_store_bypass_disable=auto.
+
+ Default mitigations:
+ X86: If CONFIG_SECCOMP=y "seccomp", otherwise "prctl"
+
spia_io_base= [HW,MTD]
spia_fio_base=
spia_pedr=
diff --git a/Documentation/spec_ctrl.txt b/Documentation/spec_ctrl.txt
new file mode 100644
index 0000000..32f3d55
--- /dev/null
+++ b/Documentation/spec_ctrl.txt
@@ -0,0 +1,94 @@
+===================
+Speculation Control
+===================
+
+Quite some CPUs have speculation-related misfeatures which are in
+fact vulnerabilities causing data leaks in various forms even across
+privilege domains.
+
+The kernel provides mitigation for such vulnerabilities in various
+forms. Some of these mitigations are compile-time configurable and some
+can be supplied on the kernel command line.
+
+There is also a class of mitigations which are very expensive, but they can
+be restricted to a certain set of processes or tasks in controlled
+environments. The mechanism to control these mitigations is via
+:manpage:`prctl(2)`.
+
+There are two prctl options which are related to this:
+
+ * PR_GET_SPECULATION_CTRL
+
+ * PR_SET_SPECULATION_CTRL
+
+PR_GET_SPECULATION_CTRL
+-----------------------
+
+PR_GET_SPECULATION_CTRL returns the state of the speculation misfeature
+which is selected with arg2 of prctl(2). The return value uses bits 0-3 with
+the following meaning:
+
+==== ===================== ===================================================
+Bit Define Description
+==== ===================== ===================================================
+0 PR_SPEC_PRCTL Mitigation can be controlled per task by
+ PR_SET_SPECULATION_CTRL.
+1 PR_SPEC_ENABLE The speculation feature is enabled, mitigation is
+ disabled.
+2 PR_SPEC_DISABLE The speculation feature is disabled, mitigation is
+ enabled.
+3 PR_SPEC_FORCE_DISABLE Same as PR_SPEC_DISABLE, but cannot be undone. A
+ subsequent prctl(..., PR_SPEC_ENABLE) will fail.
+==== ===================== ===================================================
+
+If all bits are 0 the CPU is not affected by the speculation misfeature.
+
+If PR_SPEC_PRCTL is set, then the per-task control of the mitigation is
+available. If not set, prctl(PR_SET_SPECULATION_CTRL) for the speculation
+misfeature will fail.
+
+PR_SET_SPECULATION_CTRL
+-----------------------
+
+PR_SET_SPECULATION_CTRL allows to control the speculation misfeature, which
+is selected by arg2 of :manpage:`prctl(2)` per task. arg3 is used to hand
+in the control value, i.e. either PR_SPEC_ENABLE or PR_SPEC_DISABLE or
+PR_SPEC_FORCE_DISABLE.
+
+Common error codes
+------------------
+======= =================================================================
+Value Meaning
+======= =================================================================
+EINVAL The prctl is not implemented by the architecture or unused
+ prctl(2) arguments are not 0.
+
+ENODEV arg2 is selecting a not supported speculation misfeature.
+======= =================================================================
+
+PR_SET_SPECULATION_CTRL error codes
+-----------------------------------
+======= =================================================================
+Value Meaning
+======= =================================================================
+0 Success
+
+ERANGE arg3 is incorrect, i.e. it's neither PR_SPEC_ENABLE nor
+ PR_SPEC_DISABLE nor PR_SPEC_FORCE_DISABLE.
+
+ENXIO Control of the selected speculation misfeature is not possible.
+ See PR_GET_SPECULATION_CTRL.
+
+EPERM Speculation was disabled with PR_SPEC_FORCE_DISABLE and caller
+ tried to enable it again.
+======= =================================================================
+
+Speculation misfeature controls
+-------------------------------
+- PR_SPEC_STORE_BYPASS: Speculative Store Bypass
+
+ Invocations:
+ * prctl(PR_GET_SPECULATION_CTRL, PR_SPEC_STORE_BYPASS, 0, 0, 0);
+ * prctl(PR_SET_SPECULATION_CTRL, PR_SPEC_STORE_BYPASS, PR_SPEC_ENABLE, 0, 0);
+ * prctl(PR_SET_SPECULATION_CTRL, PR_SPEC_STORE_BYPASS, PR_SPEC_DISABLE, 0, 0);
+ * prctl(PR_SET_SPECULATION_CTRL, PR_SPEC_STORE_BYPASS, PR_SPEC_FORCE_DISABLE, 0, 0);
diff --git a/Makefile b/Makefile
index 2f08005..43a123a 100644
--- a/Makefile
+++ b/Makefile
@@ -1,6 +1,6 @@
VERSION = 4
PATCHLEVEL = 9
-SUBLEVEL = 101
+SUBLEVEL = 103
EXTRAVERSION =
NAME = Roaring Lionus
diff --git a/arch/arm/boot/dts/qcom/Makefile b/arch/arm/boot/dts/qcom/Makefile
index e6af69d..824eefa 100644
--- a/arch/arm/boot/dts/qcom/Makefile
+++ b/arch/arm/boot/dts/qcom/Makefile
@@ -3,6 +3,7 @@
sdxpoorwills-cdp.dtb \
sdxpoorwills-mtp.dtb \
sdxpoorwills-atp.dtb \
+ sdxpoorwills-ttp.dtb \
sdxpoorwills-cdp-256.dtb \
sdxpoorwills-mtp-256.dtb \
sdxpoorwills-dualwifi-cdp.dtb \
diff --git a/arch/arm/boot/dts/qcom/sdx-audio-lpass.dtsi b/arch/arm/boot/dts/qcom/sdx-audio-lpass.dtsi
index 6a3210c..d891a4b 100644
--- a/arch/arm/boot/dts/qcom/sdx-audio-lpass.dtsi
+++ b/arch/arm/boot/dts/qcom/sdx-audio-lpass.dtsi
@@ -71,6 +71,7 @@
audio_apr: qcom,msm-audio-apr {
compatible = "qcom,msm-audio-apr";
+ qcom,subsys-name = "apr_modem";
};
host_pcm: qcom,msm-voice-host-pcm {
diff --git a/arch/arm/boot/dts/qcom/sdxpoorwills-dualwifi-mtp.dts b/arch/arm/boot/dts/qcom/sdxpoorwills-dualwifi-mtp.dts
index 5fd7042..243fdaf 100644
--- a/arch/arm/boot/dts/qcom/sdxpoorwills-dualwifi-mtp.dts
+++ b/arch/arm/boot/dts/qcom/sdxpoorwills-dualwifi-mtp.dts
@@ -28,3 +28,7 @@
&cnss_sdio {
status = "okay";
};
+
+&blsp1_uart2b_hs {
+ status = "okay";
+};
diff --git a/arch/arm/boot/dts/qcom/sdxpoorwills-dualwifi-mtp.dtsi b/arch/arm/boot/dts/qcom/sdxpoorwills-dualwifi-mtp.dtsi
index b60225a..252fb04 100644
--- a/arch/arm/boot/dts/qcom/sdxpoorwills-dualwifi-mtp.dtsi
+++ b/arch/arm/boot/dts/qcom/sdxpoorwills-dualwifi-mtp.dtsi
@@ -36,3 +36,11 @@
/delete-property/ qcom,devfreq,freq-table;
/delete-property/ cd-gpios;
};
+
+&soc {
+ bluetooth: bt_qca6174 {
+ compatible = "qca,qca6174";
+ qca,bt-reset-gpio = <&pmxpoorwills_gpios 4 0>; /* BT_EN */
+ qca,bt-vdd-pa-supply = <&vreg_wlan>;
+ };
+};
diff --git a/arch/arm/boot/dts/qcom/sdxpoorwills-ttp.dts b/arch/arm/boot/dts/qcom/sdxpoorwills-ttp.dts
new file mode 100644
index 0000000..775be96
--- /dev/null
+++ b/arch/arm/boot/dts/qcom/sdxpoorwills-ttp.dts
@@ -0,0 +1,22 @@
+/* Copyright (c) 2017-2018, The Linux Foundation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ */
+
+/dts-v1/;
+
+#include "sdxpoorwills-ttp.dtsi"
+
+/ {
+ model = "Qualcomm Technologies, Inc. SDXPOORWILLS TTP";
+ compatible = "qcom,sdxpoorwills-ttp",
+ "qcom,sdxpoorwills", "qcom,ttp";
+ qcom,board-id = <30 0x100>;
+};
diff --git a/arch/arm/boot/dts/qcom/sdxpoorwills-ttp.dtsi b/arch/arm/boot/dts/qcom/sdxpoorwills-ttp.dtsi
new file mode 100644
index 0000000..7f49b6d
--- /dev/null
+++ b/arch/arm/boot/dts/qcom/sdxpoorwills-ttp.dtsi
@@ -0,0 +1,14 @@
+/* Copyright (c) 2018, The Linux Foundation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ */
+
+#include "sdxpoorwills-mtp.dtsi"
+
diff --git a/arch/arm/boot/dts/qcom/sdxpoorwills-usb.dtsi b/arch/arm/boot/dts/qcom/sdxpoorwills-usb.dtsi
index 3bccd8a..9f74227 100644
--- a/arch/arm/boot/dts/qcom/sdxpoorwills-usb.dtsi
+++ b/arch/arm/boot/dts/qcom/sdxpoorwills-usb.dtsi
@@ -76,6 +76,7 @@
snps,disable-clk-gating;
snps,has-lpm-erratum;
snps,hird-threshold = /bits/ 8 <0x10>;
+ snps,xhci-imod-value = <4000>;
};
qcom,usbbam@a704000 {
diff --git a/arch/arm/boot/dts/qcom/sdxpoorwills.dtsi b/arch/arm/boot/dts/qcom/sdxpoorwills.dtsi
index d1b2050..eefea0f 100644
--- a/arch/arm/boot/dts/qcom/sdxpoorwills.dtsi
+++ b/arch/arm/boot/dts/qcom/sdxpoorwills.dtsi
@@ -920,6 +920,7 @@
qcom,mhi-event-ring-id-limits = <9 10>; /* start and end */
qcom,modem-cfg-emb-pipe-flt;
qcom,use-ipa-pm;
+ qcom,wlan-ce-db-over-pcie;
qcom,arm-smmu;
qcom,smmu-fast-map;
qcom,bandwidth-vote-for-ipa;
diff --git a/arch/arm/configs/msm8909-perf_defconfig b/arch/arm/configs/msm8909-perf_defconfig
index f42b90a..e21e912 100644
--- a/arch/arm/configs/msm8909-perf_defconfig
+++ b/arch/arm/configs/msm8909-perf_defconfig
@@ -56,6 +56,7 @@
CONFIG_PREEMPT=y
CONFIG_AEABI=y
CONFIG_HIGHMEM=y
+CONFIG_ARM_MODULE_PLTS=y
CONFIG_CMA=y
CONFIG_ZSMALLOC=y
CONFIG_BALANCE_ANON_FILE_RECLAIM=y
@@ -304,11 +305,17 @@
CONFIG_QPNP_LINEAR_CHARGER=y
CONFIG_SENSORS_QPNP_ADC_VOLTAGE=y
CONFIG_THERMAL=y
+CONFIG_THERMAL_WRITABLE_TRIPS=y
+CONFIG_THERMAL_GOV_USER_SPACE=y
+CONFIG_THERMAL_GOV_LOW_LIMITS=y
+CONFIG_CPU_THERMAL=y
+CONFIG_DEVFREQ_THERMAL=y
CONFIG_THERMAL_QPNP=y
CONFIG_THERMAL_QPNP_ADC_TM=y
CONFIG_THERMAL_TSENS=y
CONFIG_MSM_BCL_PERIPHERAL_CTL=y
-CONFIG_QTI_THERMAL_LIMITS_DCVS=y
+CONFIG_QTI_QMI_COOLING_DEVICE=y
+CONFIG_REGULATOR_COOLING_DEVICE=y
CONFIG_MFD_QCOM_RPM=y
CONFIG_MFD_SPMI_PMIC=y
CONFIG_REGULATOR=y
@@ -475,6 +482,7 @@
CONFIG_TMPFS=y
CONFIG_ECRYPT_FS=y
CONFIG_ECRYPT_FS_MESSAGING=y
+CONFIG_SDCARD_FS=y
CONFIG_NLS_CODEPAGE_437=y
CONFIG_NLS_ISO8859_1=y
CONFIG_PRINTK_TIME=y
diff --git a/arch/arm/configs/msm8909_defconfig b/arch/arm/configs/msm8909_defconfig
index 9eb0afd..8c3b56b 100644
--- a/arch/arm/configs/msm8909_defconfig
+++ b/arch/arm/configs/msm8909_defconfig
@@ -50,6 +50,7 @@
CONFIG_PREEMPT=y
CONFIG_AEABI=y
CONFIG_HIGHMEM=y
+CONFIG_ARM_MODULE_PLTS=y
CONFIG_CMA=y
CONFIG_CMA_DEBUGFS=y
CONFIG_ZSMALLOC=y
@@ -269,6 +270,7 @@
CONFIG_INPUT_TOUCHSCREEN=y
CONFIG_INPUT_MISC=y
CONFIG_INPUT_QPNP_POWER_ON=y
+CONFIG_STMVL53L0X=y
CONFIG_INPUT_UINPUT=y
CONFIG_INPUT_GPIO=y
# CONFIG_LEGACY_PTYS is not set
@@ -312,6 +314,7 @@
CONFIG_QTI_THERMAL_LIMITS_DCVS=y
CONFIG_MFD_QCOM_RPM=y
CONFIG_MFD_SPMI_PMIC=y
+CONFIG_MFD_SYSCON=y
CONFIG_REGULATOR=y
CONFIG_REGULATOR_FIXED_VOLTAGE=y
CONFIG_REGULATOR_PROXY_CONSUMER=y
@@ -462,6 +465,8 @@
CONFIG_MSM_BAM_DMUX=y
CONFIG_CNSS_CRYPTO=y
CONFIG_QCOM_DEVFREQ_DEVBW=y
+CONFIG_IIO=y
+CONFIG_INV_ICM20602_IIO=y
CONFIG_PWM=y
CONFIG_PWM_QPNP=y
CONFIG_QTI_MPM=y
diff --git a/arch/arm/configs/msm8909w-perf_defconfig b/arch/arm/configs/msm8909w-perf_defconfig
index 887ab5c..b2e4be0 100644
--- a/arch/arm/configs/msm8909w-perf_defconfig
+++ b/arch/arm/configs/msm8909w-perf_defconfig
@@ -1,6 +1,5 @@
# CONFIG_FHANDLE is not set
CONFIG_AUDIT=y
-# CONFIG_AUDITSYSCALL is not set
CONFIG_NO_HZ=y
CONFIG_HIGH_RES_TIMERS=y
CONFIG_IRQ_TIME_ACCOUNTING=y
@@ -28,12 +27,17 @@
CONFIG_DEFAULT_USE_ENERGY_AWARE=y
CONFIG_RELAY=y
CONFIG_BLK_DEV_INITRD=y
+# CONFIG_RD_BZIP2 is not set
+# CONFIG_RD_LZMA is not set
+# CONFIG_RD_XZ is not set
+# CONFIG_RD_LZO is not set
+# CONFIG_RD_LZ4 is not set
CONFIG_CC_OPTIMIZE_FOR_SIZE=y
CONFIG_KALLSYMS_ALL=y
CONFIG_BPF_SYSCALL=y
CONFIG_EMBEDDED=y
CONFIG_PROFILING=y
-CONFIG_OPROFILE=y
+CONFIG_OPROFILE=m
CONFIG_CC_STACKPROTECTOR_REGULAR=y
CONFIG_MODULES=y
CONFIG_MODULE_UNLOAD=y
@@ -182,11 +186,8 @@
CONFIG_NET_SCHED=y
CONFIG_NET_SCH_HTB=y
CONFIG_NET_SCH_PRIO=y
-CONFIG_NET_SCH_MULTIQ=y
-CONFIG_NET_SCH_INGRESS=y
CONFIG_NET_CLS_FW=y
CONFIG_NET_CLS_U32=y
-CONFIG_CLS_U32_MARK=y
CONFIG_NET_CLS_FLOW=y
CONFIG_NET_EMATCH=y
CONFIG_NET_EMATCH_CMP=y
@@ -225,19 +226,15 @@
CONFIG_BLK_DEV_SD=y
CONFIG_CHR_DEV_SG=y
CONFIG_CHR_DEV_SCH=y
-CONFIG_SCSI_CONSTANTS=y
-CONFIG_SCSI_LOGGING=y
CONFIG_SCSI_SCAN_ASYNC=y
CONFIG_SCSI_UFSHCD=y
CONFIG_SCSI_UFSHCD_PLATFORM=y
CONFIG_SCSI_UFS_QCOM=y
-CONFIG_SCSI_UFSHCD_CMD_LOGGING=y
CONFIG_MD=y
CONFIG_BLK_DEV_DM=y
CONFIG_DM_CRYPT=y
CONFIG_DM_UEVENT=y
CONFIG_DM_VERITY=y
-CONFIG_DM_VERITY_FEC=y
CONFIG_NETDEVICES=y
CONFIG_DUMMY=y
CONFIG_TUN=y
@@ -295,11 +292,17 @@
CONFIG_QPNP_SMB2=y
CONFIG_SENSORS_QPNP_ADC_VOLTAGE=y
CONFIG_THERMAL=y
+CONFIG_THERMAL_WRITABLE_TRIPS=y
+CONFIG_THERMAL_GOV_USER_SPACE=y
+CONFIG_THERMAL_GOV_LOW_LIMITS=y
+CONFIG_CPU_THERMAL=y
+CONFIG_DEVFREQ_THERMAL=y
CONFIG_THERMAL_QPNP=y
CONFIG_THERMAL_QPNP_ADC_TM=y
CONFIG_THERMAL_TSENS=y
CONFIG_MSM_BCL_PERIPHERAL_CTL=y
-CONFIG_QTI_THERMAL_LIMITS_DCVS=y
+CONFIG_QTI_QMI_COOLING_DEVICE=y
+CONFIG_REGULATOR_COOLING_DEVICE=y
CONFIG_MFD_QCOM_RPM=y
CONFIG_MFD_SPMI_PMIC=y
CONFIG_REGULATOR=y
@@ -326,30 +329,15 @@
CONFIG_FB_MSM=y
CONFIG_FB_MSM_MDSS=y
CONFIG_FB_MSM_MDSS_WRITEBACK=y
+CONFIG_FB_MSM_MDSS_SPI_PANEL=y
CONFIG_FB_MSM_MDSS_MDP3=y
CONFIG_BACKLIGHT_LCD_SUPPORT=y
CONFIG_BACKLIGHT_CLASS_DEVICE=y
-CONFIG_LOGO=y
CONFIG_SOUND=y
CONFIG_SND=y
CONFIG_SND_DYNAMIC_MINORS=y
CONFIG_SND_SOC=y
CONFIG_UHID=y
-CONFIG_HID_A4TECH=y
-CONFIG_HID_APPLE=y
-CONFIG_HID_BELKIN=y
-CONFIG_HID_CHERRY=y
-CONFIG_HID_CHICONY=y
-CONFIG_HID_CYPRESS=y
-CONFIG_HID_ELECOM=y
-CONFIG_HID_EZKEY=y
-CONFIG_HID_KENSINGTON=y
-CONFIG_HID_LOGITECH=y
-CONFIG_HID_MAGICMOUSE=y
-CONFIG_HID_MICROSOFT=y
-CONFIG_HID_MONTEREY=y
-CONFIG_HID_MULTITOUCH=y
-CONFIG_DUAL_ROLE_USB_INTF=y
CONFIG_USB_GADGET=y
CONFIG_USB_GADGET_DEBUG_FILES=y
CONFIG_USB_GADGET_DEBUG_FS=y
@@ -357,9 +345,6 @@
CONFIG_USB_CI13XXX_MSM=y
CONFIG_USB_CONFIGFS=y
CONFIG_USB_CONFIGFS_SERIAL=y
-CONFIG_USB_CONFIGFS_ACM=y
-CONFIG_USB_CONFIGFS_NCM=y
-CONFIG_USB_CONFIGFS_ECM=y
CONFIG_USB_CONFIGFS_RMNET_BAM=y
CONFIG_USB_CONFIGFS_EEM=y
CONFIG_USB_CONFIGFS_MASS_STORAGE=y
@@ -475,28 +460,21 @@
CONFIG_TMPFS=y
CONFIG_ECRYPT_FS=y
CONFIG_ECRYPT_FS_MESSAGING=y
+CONFIG_SDCARD_FS=y
CONFIG_NLS_CODEPAGE_437=y
CONFIG_NLS_ISO8859_1=y
CONFIG_PRINTK_TIME=y
CONFIG_DEBUG_INFO=y
CONFIG_FRAME_WARN=2048
-CONFIG_PAGE_OWNER=y
-CONFIG_PAGE_OWNER_ENABLE_DEFAULT=y
-CONFIG_MAGIC_SYSRQ=y
-CONFIG_LOCKUP_DETECTOR=y
-# CONFIG_DETECT_HUNG_TASK is not set
+CONFIG_PAGE_EXTENSION=y
+CONFIG_PANIC_ON_RECURSIVE_FAULT=y
CONFIG_WQ_WATCHDOG=y
CONFIG_PANIC_TIMEOUT=5
CONFIG_PANIC_ON_SCHED_BUG=y
CONFIG_PANIC_ON_RT_THROTTLING=y
-CONFIG_SCHEDSTATS=y
-CONFIG_SCHED_STACK_END_CHECK=y
# CONFIG_DEBUG_PREEMPT is not set
CONFIG_IPC_LOGGING=y
-CONFIG_LKDTM=y
-CONFIG_PANIC_ON_DATA_CORRUPTION=y
-# CONFIG_ARM_UNWIND is not set
-CONFIG_PID_IN_CONTEXTIDR=y
+CONFIG_DEBUG_USER=y
CONFIG_DEBUG_SET_MODULE_RONX=y
CONFIG_SECURITY_PERF_EVENTS_RESTRICT=y
CONFIG_SECURITY=y
diff --git a/arch/arm/configs/msm8909w_defconfig b/arch/arm/configs/msm8909w_defconfig
index 8c5f143..8108661 100644
--- a/arch/arm/configs/msm8909w_defconfig
+++ b/arch/arm/configs/msm8909w_defconfig
@@ -36,7 +36,6 @@
CONFIG_KALLSYMS_ALL=y
CONFIG_BPF_SYSCALL=y
CONFIG_EMBEDDED=y
-# CONFIG_SLUB_DEBUG is not set
CONFIG_PROFILING=y
CONFIG_OPROFILE=m
CONFIG_CC_STACKPROTECTOR_REGULAR=y
@@ -283,11 +282,17 @@
CONFIG_QPNP_SMB2=y
CONFIG_SENSORS_QPNP_ADC_VOLTAGE=y
CONFIG_THERMAL=y
+CONFIG_THERMAL_WRITABLE_TRIPS=y
+CONFIG_THERMAL_GOV_USER_SPACE=y
+CONFIG_THERMAL_GOV_LOW_LIMITS=y
+CONFIG_CPU_THERMAL=y
+CONFIG_DEVFREQ_THERMAL=y
CONFIG_THERMAL_QPNP=y
CONFIG_THERMAL_QPNP_ADC_TM=y
CONFIG_THERMAL_TSENS=y
CONFIG_MSM_BCL_PERIPHERAL_CTL=y
-CONFIG_QTI_THERMAL_LIMITS_DCVS=y
+CONFIG_QTI_QMI_COOLING_DEVICE=y
+CONFIG_REGULATOR_COOLING_DEVICE=y
CONFIG_MFD_QCOM_RPM=y
CONFIG_MFD_SPMI_PMIC=y
CONFIG_REGULATOR=y
@@ -314,9 +319,12 @@
CONFIG_FB_MSM=y
CONFIG_FB_MSM_MDSS=y
CONFIG_FB_MSM_MDSS_WRITEBACK=y
+CONFIG_FB_MSM_MDSS_SPI_PANEL=y
CONFIG_FB_MSM_MDSS_MDP3=y
CONFIG_BACKLIGHT_LCD_SUPPORT=y
+# CONFIG_LCD_CLASS_DEVICE is not set
CONFIG_BACKLIGHT_CLASS_DEVICE=y
+# CONFIG_BACKLIGHT_GENERIC is not set
CONFIG_LOGO=y
CONFIG_SOUND=y
CONFIG_SND=y
@@ -444,17 +452,20 @@
CONFIG_TMPFS=y
CONFIG_ECRYPT_FS=y
CONFIG_ECRYPT_FS_MESSAGING=y
+CONFIG_SDCARD_FS=y
CONFIG_NLS_CODEPAGE_437=y
CONFIG_NLS_ISO8859_1=y
CONFIG_PRINTK_TIME=y
+CONFIG_MESSAGE_LOGLEVEL_DEFAULT=6
CONFIG_DYNAMIC_DEBUG=y
CONFIG_DEBUG_INFO=y
CONFIG_FRAME_WARN=2048
CONFIG_PAGE_OWNER=y
CONFIG_PAGE_OWNER_ENABLE_DEFAULT=y
-CONFIG_MAGIC_SYSRQ=y
CONFIG_DEBUG_PAGEALLOC=y
+CONFIG_SLUB_DEBUG_PANIC_ON=y
CONFIG_DEBUG_PAGEALLOC_ENABLE_DEFAULT=y
+CONFIG_SLUB_DEBUG_ON=y
CONFIG_DEBUG_KMEMLEAK=y
CONFIG_DEBUG_KMEMLEAK_EARLY_LOG_SIZE=4000
CONFIG_DEBUG_KMEMLEAK_DEFAULT_OFF=y
@@ -463,7 +474,8 @@
CONFIG_LOCKUP_DETECTOR=y
# CONFIG_DETECT_HUNG_TASK is not set
CONFIG_WQ_WATCHDOG=y
-CONFIG_PANIC_TIMEOUT=5
+CONFIG_PANIC_ON_OOPS=y
+CONFIG_PANIC_TIMEOUT=-1
CONFIG_PANIC_ON_SCHED_BUG=y
CONFIG_PANIC_ON_RT_THROTTLING=y
CONFIG_SCHEDSTATS=y
diff --git a/arch/arm/configs/msm8937-perf_defconfig b/arch/arm/configs/msm8937-perf_defconfig
index dae45e1..3163111 100644
--- a/arch/arm/configs/msm8937-perf_defconfig
+++ b/arch/arm/configs/msm8937-perf_defconfig
@@ -67,6 +67,7 @@
CONFIG_PREEMPT=y
CONFIG_AEABI=y
CONFIG_HIGHMEM=y
+CONFIG_ARM_MODULE_PLTS=y
CONFIG_CMA=y
CONFIG_CMA_DEBUGFS=y
CONFIG_ZSMALLOC=y
@@ -147,6 +148,7 @@
CONFIG_NETFILTER_XT_TARGET_TRACE=y
CONFIG_NETFILTER_XT_TARGET_SECMARK=y
CONFIG_NETFILTER_XT_TARGET_TCPMSS=y
+CONFIG_NETFILTER_XT_MATCH_BPF=y
CONFIG_NETFILTER_XT_MATCH_COMMENT=y
CONFIG_NETFILTER_XT_MATCH_CONNLIMIT=y
CONFIG_NETFILTER_XT_MATCH_CONNMARK=y
@@ -348,10 +350,10 @@
CONFIG_POWER_RESET=y
CONFIG_POWER_RESET_QCOM=y
CONFIG_QCOM_DLOAD_MODE=y
-CONFIG_POWER_RESET_SYSCON=y
CONFIG_POWER_SUPPLY=y
CONFIG_QPNP_FG=y
CONFIG_SMB135X_CHARGER=y
+CONFIG_SMB1355_SLAVE_CHARGER=y
CONFIG_SMB1351_USB_CHARGER=y
CONFIG_QPNP_SMB5=y
CONFIG_QPNP_SMBCHARGER=y
@@ -373,7 +375,9 @@
CONFIG_REGULATOR_COOLING_DEVICE=y
CONFIG_QTI_BCL_PMIC5=y
CONFIG_QTI_BCL_SOC_DRIVER=y
+CONFIG_MFD_I2C_PMIC=y
CONFIG_MFD_SPMI_PMIC=y
+CONFIG_MFD_SYSCON=y
CONFIG_REGULATOR=y
CONFIG_REGULATOR_FIXED_VOLTAGE=y
CONFIG_REGULATOR_PROXY_CONSUMER=y
@@ -396,9 +400,7 @@
CONFIG_USB_VIDEO_CLASS=y
CONFIG_V4L_PLATFORM_DRIVERS=y
CONFIG_MSM_CAMERA=y
-CONFIG_MSM_CAMERA_DEBUG=y
CONFIG_MSMB_CAMERA=y
-CONFIG_MSMB_CAMERA_DEBUG=y
CONFIG_MSM_CAMERA_SENSOR=y
CONFIG_MSM_CPP=y
CONFIG_MSM_CCI=y
@@ -564,7 +566,6 @@
CONFIG_MSM_PIL=y
CONFIG_MSM_PIL_SSR_GENERIC=y
CONFIG_MSM_PIL_MSS_QDSP6V5=y
-CONFIG_ICNSS=y
CONFIG_MSM_PERFORMANCE=y
CONFIG_MSM_EVENT_TIMER=y
CONFIG_MSM_AVTIMER=y
@@ -577,12 +578,14 @@
CONFIG_WCNSS_CORE=y
CONFIG_WCNSS_CORE_PRONTO=y
CONFIG_WCNSS_REGISTER_DUMP_ON_BITE=y
+CONFIG_BIG_CLUSTER_MIN_FREQ_ADJUST=y
CONFIG_QCOM_BIMC_BWMON=y
CONFIG_DEVFREQ_GOV_QCOM_BW_HWMON=y
CONFIG_DEVFREQ_SIMPLE_DEV=y
CONFIG_QCOM_DEVFREQ_DEVBW=y
CONFIG_SPDM_SCM=y
CONFIG_DEVFREQ_SPDM=y
+CONFIG_IIO=y
CONFIG_PWM=y
CONFIG_PWM_QPNP=y
CONFIG_PWM_QTI_LPG=y
@@ -595,6 +598,7 @@
CONFIG_EXT4_FS_SECURITY=y
CONFIG_F2FS_FS=y
CONFIG_F2FS_FS_SECURITY=y
+CONFIG_F2FS_FS_ENCRYPTION=y
CONFIG_QUOTA=y
CONFIG_QUOTA_NETLINK_INTERFACE=y
CONFIG_QFMT_V2=y
@@ -628,13 +632,13 @@
CONFIG_CORESIGHT_CTI=y
CONFIG_CORESIGHT_EVENT=y
CONFIG_CORESIGHT_HWEVENT=y
+CONFIG_PFK=y
CONFIG_SECURITY_PERF_EVENTS_RESTRICT=y
CONFIG_SECURITY=y
CONFIG_LSM_MMAP_MIN_ADDR=4096
CONFIG_HARDENED_USERCOPY=y
CONFIG_SECURITY_SELINUX=y
CONFIG_SECURITY_SMACK=y
-CONFIG_CRYPTO_CTR=y
CONFIG_CRYPTO_XCBC=y
CONFIG_CRYPTO_MD4=y
CONFIG_CRYPTO_TWOFISH=y
diff --git a/arch/arm/configs/msm8937_defconfig b/arch/arm/configs/msm8937_defconfig
index 3c43fa3..87f915c 100644
--- a/arch/arm/configs/msm8937_defconfig
+++ b/arch/arm/configs/msm8937_defconfig
@@ -70,6 +70,7 @@
CONFIG_PREEMPT=y
CONFIG_AEABI=y
CONFIG_HIGHMEM=y
+CONFIG_ARM_MODULE_PLTS=y
CONFIG_CMA=y
CONFIG_CMA_DEBUGFS=y
CONFIG_ZSMALLOC=y
@@ -151,6 +152,7 @@
CONFIG_NETFILTER_XT_TARGET_TRACE=y
CONFIG_NETFILTER_XT_TARGET_SECMARK=y
CONFIG_NETFILTER_XT_TARGET_TCPMSS=y
+CONFIG_NETFILTER_XT_MATCH_BPF=y
CONFIG_NETFILTER_XT_MATCH_COMMENT=y
CONFIG_NETFILTER_XT_MATCH_CONNLIMIT=y
CONFIG_NETFILTER_XT_MATCH_CONNMARK=y
@@ -355,10 +357,10 @@
CONFIG_POWER_RESET=y
CONFIG_POWER_RESET_QCOM=y
CONFIG_QCOM_DLOAD_MODE=y
-CONFIG_POWER_RESET_SYSCON=y
CONFIG_POWER_SUPPLY=y
CONFIG_QPNP_FG=y
CONFIG_SMB135X_CHARGER=y
+CONFIG_SMB1355_SLAVE_CHARGER=y
CONFIG_SMB1351_USB_CHARGER=y
CONFIG_QPNP_SMB5=y
CONFIG_QPNP_SMBCHARGER=y
@@ -380,7 +382,9 @@
CONFIG_REGULATOR_COOLING_DEVICE=y
CONFIG_QTI_BCL_PMIC5=y
CONFIG_QTI_BCL_SOC_DRIVER=y
+CONFIG_MFD_I2C_PMIC=y
CONFIG_MFD_SPMI_PMIC=y
+CONFIG_MFD_SYSCON=y
CONFIG_REGULATOR=y
CONFIG_REGULATOR_FIXED_VOLTAGE=y
CONFIG_REGULATOR_PROXY_CONSUMER=y
@@ -561,7 +565,6 @@
CONFIG_MSM_L2_SPM=y
CONFIG_MSM_BOOT_STATS=y
CONFIG_MSM_CORE_HANG_DETECT=y
-CONFIG_MSM_GLADIATOR_HANG_DETECT=y
CONFIG_QCOM_WATCHDOG_V2=y
CONFIG_QCOM_MEMORY_DUMP_V2=y
CONFIG_MSM_DEBUG_LAR_UNLOCK=y
@@ -582,7 +585,6 @@
CONFIG_MSM_PIL=y
CONFIG_MSM_PIL_SSR_GENERIC=y
CONFIG_MSM_PIL_MSS_QDSP6V5=y
-CONFIG_ICNSS=y
CONFIG_MSM_PERFORMANCE=y
CONFIG_MSM_EVENT_TIMER=y
CONFIG_MSM_AVTIMER=y
@@ -596,15 +598,18 @@
CONFIG_WCNSS_CORE=y
CONFIG_WCNSS_CORE_PRONTO=y
CONFIG_WCNSS_REGISTER_DUMP_ON_BITE=y
+CONFIG_BIG_CLUSTER_MIN_FREQ_ADJUST=y
CONFIG_QCOM_BIMC_BWMON=y
CONFIG_DEVFREQ_GOV_QCOM_BW_HWMON=y
CONFIG_DEVFREQ_SIMPLE_DEV=y
CONFIG_QCOM_DEVFREQ_DEVBW=y
CONFIG_SPDM_SCM=y
CONFIG_DEVFREQ_SPDM=y
+CONFIG_IIO=y
CONFIG_PWM=y
CONFIG_PWM_QPNP=y
CONFIG_PWM_QTI_LPG=y
+CONFIG_QCOM_SHOW_RESUME_IRQ=y
CONFIG_QTI_MPM=y
CONFIG_ANDROID=y
CONFIG_ANDROID_BINDER_IPC=y
@@ -614,6 +619,7 @@
CONFIG_EXT4_FS_SECURITY=y
CONFIG_F2FS_FS=y
CONFIG_F2FS_FS_SECURITY=y
+CONFIG_F2FS_FS_ENCRYPTION=y
CONFIG_QUOTA=y
CONFIG_QUOTA_NETLINK_INTERFACE=y
CONFIG_QFMT_V2=y
@@ -643,7 +649,6 @@
CONFIG_DEBUG_OBJECTS_WORK=y
CONFIG_DEBUG_OBJECTS_RCU_HEAD=y
CONFIG_DEBUG_OBJECTS_PERCPU_COUNTER=y
-CONFIG_SLUB_DEBUG_ON=y
CONFIG_DEBUG_KMEMLEAK=y
CONFIG_DEBUG_KMEMLEAK_EARLY_LOG_SIZE=4000
CONFIG_DEBUG_KMEMLEAK_DEFAULT_OFF=y
@@ -694,13 +699,13 @@
CONFIG_CORESIGHT_CTI=y
CONFIG_CORESIGHT_EVENT=y
CONFIG_CORESIGHT_HWEVENT=y
+CONFIG_PFK=y
CONFIG_SECURITY_PERF_EVENTS_RESTRICT=y
CONFIG_SECURITY=y
CONFIG_LSM_MMAP_MIN_ADDR=4096
CONFIG_HARDENED_USERCOPY=y
CONFIG_SECURITY_SELINUX=y
CONFIG_SECURITY_SMACK=y
-CONFIG_CRYPTO_CTR=y
CONFIG_CRYPTO_XCBC=y
CONFIG_CRYPTO_MD4=y
CONFIG_CRYPTO_TWOFISH=y
diff --git a/arch/arm/configs/msm8953-batcam-perf_defconfig b/arch/arm/configs/msm8953-batcam-perf_defconfig
index 5b886a82..a6fe9b0 100644
--- a/arch/arm/configs/msm8953-batcam-perf_defconfig
+++ b/arch/arm/configs/msm8953-batcam-perf_defconfig
@@ -79,9 +79,11 @@
CONFIG_DMA_CMA=y
# CONFIG_OF_KOBJ is not set
CONFIG_QSEECOM=y
+CONFIG_SCSI=y
CONFIG_MD=y
CONFIG_BLK_DEV_DM=y
CONFIG_NETDEVICES=y
+CONFIG_USB_USBNET=y
CONFIG_INPUT_EVDEV=y
CONFIG_INPUT_MISC=y
CONFIG_INPUT_QPNP_POWER_ON=y
@@ -147,8 +149,43 @@
CONFIG_SOUND=y
CONFIG_SND=y
CONFIG_SND_DYNAMIC_MINORS=y
+CONFIG_SND_USB_AUDIO=y
CONFIG_SND_SOC=y
CONFIG_UHID=y
+CONFIG_USB_HIDDEV=y
+CONFIG_USB=y
+CONFIG_USB_ANNOUNCE_NEW_DEVICES=y
+CONFIG_USB_MON=y
+CONFIG_USB_XHCI_HCD=y
+CONFIG_USB_ACM=y
+CONFIG_USB_STORAGE=y
+CONFIG_USB_STORAGE_DATAFAB=y
+CONFIG_USB_STORAGE_FREECOM=y
+CONFIG_USB_STORAGE_ISD200=y
+CONFIG_USB_STORAGE_USBAT=y
+CONFIG_USB_STORAGE_SDDR09=y
+CONFIG_USB_STORAGE_SDDR55=y
+CONFIG_USB_STORAGE_JUMPSHOT=y
+CONFIG_USB_STORAGE_ALAUDA=y
+CONFIG_USB_STORAGE_ONETOUCH=y
+CONFIG_USB_STORAGE_KARMA=y
+CONFIG_USB_STORAGE_CYPRESS_ATACB=y
+CONFIG_USB_DWC3=y
+CONFIG_USB_DWC3_MSM=y
+CONFIG_USB_SERIAL=y
+CONFIG_USB_EHSET_TEST_FIXTURE=y
+CONFIG_NOP_USB_XCEIV=y
+CONFIG_DUAL_ROLE_USB_INTF=y
+CONFIG_USB_MSM_SSPHY_QMP=y
+CONFIG_MSM_QUSB_PHY=y
+CONFIG_USB_GADGET=y
+CONFIG_USB_GADGET_DEBUG_FILES=y
+CONFIG_USB_GADGET_DEBUG_FS=y
+CONFIG_USB_GADGET_VBUS_DRAW=500
+CONFIG_USB_CONFIGFS=y
+CONFIG_USB_CONFIGFS_F_FS=y
+CONFIG_USB_CONFIGFS_UEVENT=y
+CONFIG_USB_CONFIGFS_F_DIAG=y
CONFIG_MMC=y
CONFIG_MMC_PARANOID_SD_INIT=y
CONFIG_MMC_CLKGATE=y
@@ -189,6 +226,7 @@
CONFIG_SPS_SUPPORT_NDP_BAM=y
CONFIG_QPNP_COINCELL=y
CONFIG_QPNP_REVID=y
+CONFIG_USB_BAM=y
CONFIG_REMOTE_SPINLOCK_MSM=y
CONFIG_MAILBOX=y
CONFIG_ARM_SMMU=y
@@ -225,6 +263,7 @@
CONFIG_QCOM_DEVFREQ_DEVBW=y
CONFIG_SPDM_SCM=y
CONFIG_DEVFREQ_SPDM=y
+CONFIG_EXTCON_USB_GPIO=y
CONFIG_PWM=y
CONFIG_PWM_QPNP=y
CONFIG_PWM_QTI_LPG=y
diff --git a/arch/arm/configs/msm8953-batcam_defconfig b/arch/arm/configs/msm8953-batcam_defconfig
index dc6688c..cd86b01 100644
--- a/arch/arm/configs/msm8953-batcam_defconfig
+++ b/arch/arm/configs/msm8953-batcam_defconfig
@@ -78,9 +78,11 @@
CONFIG_DMA_CMA=y
# CONFIG_OF_KOBJ is not set
CONFIG_QSEECOM=y
+CONFIG_SCSI=y
CONFIG_MD=y
CONFIG_BLK_DEV_DM=y
CONFIG_NETDEVICES=y
+CONFIG_USB_USBNET=y
CONFIG_INPUT_EVDEV=y
CONFIG_INPUT_MISC=y
CONFIG_INPUT_QPNP_POWER_ON=y
@@ -148,8 +150,43 @@
CONFIG_SOUND=y
CONFIG_SND=y
CONFIG_SND_DYNAMIC_MINORS=y
+CONFIG_SND_USB_AUDIO=y
CONFIG_SND_SOC=y
CONFIG_UHID=y
+CONFIG_USB_HIDDEV=y
+CONFIG_USB=y
+CONFIG_USB_ANNOUNCE_NEW_DEVICES=y
+CONFIG_USB_MON=y
+CONFIG_USB_XHCI_HCD=y
+CONFIG_USB_ACM=y
+CONFIG_USB_STORAGE=y
+CONFIG_USB_STORAGE_DATAFAB=y
+CONFIG_USB_STORAGE_FREECOM=y
+CONFIG_USB_STORAGE_ISD200=y
+CONFIG_USB_STORAGE_USBAT=y
+CONFIG_USB_STORAGE_SDDR09=y
+CONFIG_USB_STORAGE_SDDR55=y
+CONFIG_USB_STORAGE_JUMPSHOT=y
+CONFIG_USB_STORAGE_ALAUDA=y
+CONFIG_USB_STORAGE_ONETOUCH=y
+CONFIG_USB_STORAGE_KARMA=y
+CONFIG_USB_STORAGE_CYPRESS_ATACB=y
+CONFIG_USB_DWC3=y
+CONFIG_USB_DWC3_MSM=y
+CONFIG_USB_SERIAL=y
+CONFIG_USB_EHSET_TEST_FIXTURE=y
+CONFIG_NOP_USB_XCEIV=y
+CONFIG_DUAL_ROLE_USB_INTF=y
+CONFIG_USB_MSM_SSPHY_QMP=y
+CONFIG_MSM_QUSB_PHY=y
+CONFIG_USB_GADGET=y
+CONFIG_USB_GADGET_DEBUG_FILES=y
+CONFIG_USB_GADGET_DEBUG_FS=y
+CONFIG_USB_GADGET_VBUS_DRAW=500
+CONFIG_USB_CONFIGFS=y
+CONFIG_USB_CONFIGFS_F_FS=y
+CONFIG_USB_CONFIGFS_UEVENT=y
+CONFIG_USB_CONFIGFS_F_DIAG=y
CONFIG_MMC=y
CONFIG_MMC_PARANOID_SD_INIT=y
CONFIG_MMC_CLKGATE=y
@@ -190,6 +227,7 @@
CONFIG_SPS_SUPPORT_NDP_BAM=y
CONFIG_QPNP_COINCELL=y
CONFIG_QPNP_REVID=y
+CONFIG_USB_BAM=y
CONFIG_REMOTE_SPINLOCK_MSM=y
CONFIG_MAILBOX=y
CONFIG_ARM_SMMU=y
@@ -226,6 +264,7 @@
CONFIG_QCOM_DEVFREQ_DEVBW=y
CONFIG_SPDM_SCM=y
CONFIG_DEVFREQ_SPDM=y
+CONFIG_EXTCON_USB_GPIO=y
CONFIG_PWM=y
CONFIG_PWM_QPNP=y
CONFIG_PWM_QTI_LPG=y
diff --git a/arch/arm/configs/msm8953-perf_defconfig b/arch/arm/configs/msm8953-perf_defconfig
index 06e5360..848cfce 100644
--- a/arch/arm/configs/msm8953-perf_defconfig
+++ b/arch/arm/configs/msm8953-perf_defconfig
@@ -64,6 +64,7 @@
CONFIG_PREEMPT=y
CONFIG_AEABI=y
CONFIG_HIGHMEM=y
+CONFIG_ARM_MODULE_PLTS=y
CONFIG_CMA=y
CONFIG_CMA_DEBUGFS=y
CONFIG_ZSMALLOC=y
@@ -145,6 +146,7 @@
CONFIG_NETFILTER_XT_TARGET_TRACE=y
CONFIG_NETFILTER_XT_TARGET_SECMARK=y
CONFIG_NETFILTER_XT_TARGET_TCPMSS=y
+CONFIG_NETFILTER_XT_MATCH_BPF=y
CONFIG_NETFILTER_XT_MATCH_COMMENT=y
CONFIG_NETFILTER_XT_MATCH_CONNLIMIT=y
CONFIG_NETFILTER_XT_MATCH_CONNMARK=y
@@ -345,10 +347,10 @@
CONFIG_POWER_RESET=y
CONFIG_POWER_RESET_QCOM=y
CONFIG_QCOM_DLOAD_MODE=y
-CONFIG_POWER_RESET_SYSCON=y
CONFIG_POWER_SUPPLY=y
CONFIG_QPNP_FG=y
CONFIG_SMB135X_CHARGER=y
+CONFIG_SMB1355_SLAVE_CHARGER=y
CONFIG_SMB1351_USB_CHARGER=y
CONFIG_QPNP_SMB5=y
CONFIG_QPNP_SMBCHARGER=y
@@ -370,7 +372,9 @@
CONFIG_REGULATOR_COOLING_DEVICE=y
CONFIG_QTI_BCL_PMIC5=y
CONFIG_QTI_BCL_SOC_DRIVER=y
+CONFIG_MFD_I2C_PMIC=y
CONFIG_MFD_SPMI_PMIC=y
+CONFIG_MFD_SYSCON=y
CONFIG_REGULATOR=y
CONFIG_REGULATOR_FIXED_VOLTAGE=y
CONFIG_REGULATOR_PROXY_CONSUMER=y
@@ -572,6 +576,7 @@
CONFIG_MSM_EVENT_TIMER=y
CONFIG_MSM_AVTIMER=y
CONFIG_MSM_PM=y
+CONFIG_QCOM_DCC=y
CONFIG_QTI_RPM_STATS_LOG=y
CONFIG_QCOM_FORCE_WDOG_BITE_ON_PANIC=y
CONFIG_MEM_SHARE_QMI_SERVICE=y
@@ -579,12 +584,14 @@
CONFIG_WCNSS_CORE=y
CONFIG_WCNSS_CORE_PRONTO=y
CONFIG_WCNSS_REGISTER_DUMP_ON_BITE=y
+CONFIG_BIG_CLUSTER_MIN_FREQ_ADJUST=y
CONFIG_QCOM_BIMC_BWMON=y
CONFIG_DEVFREQ_GOV_QCOM_BW_HWMON=y
CONFIG_DEVFREQ_SIMPLE_DEV=y
CONFIG_QCOM_DEVFREQ_DEVBW=y
CONFIG_SPDM_SCM=y
CONFIG_DEVFREQ_SPDM=y
+CONFIG_IIO=y
CONFIG_PWM=y
CONFIG_PWM_QPNP=y
CONFIG_PWM_QTI_LPG=y
@@ -620,8 +627,11 @@
CONFIG_IPC_LOGGING=y
CONFIG_CPU_FREQ_SWITCH_PROFILER=y
CONFIG_CORESIGHT=y
+CONFIG_CORESIGHT_LINK_AND_SINK_TMC=y
CONFIG_CORESIGHT_REMOTE_ETM=y
CONFIG_CORESIGHT_REMOTE_ETM_DEFAULT_ENABLE=0
+CONFIG_CORESIGHT_QCOM_REPLICATOR=y
+CONFIG_CORESIGHT_DBGUI=y
CONFIG_CORESIGHT_STM=y
CONFIG_CORESIGHT_TPDA=y
CONFIG_CORESIGHT_TPDM=y
diff --git a/arch/arm/configs/msm8953_defconfig b/arch/arm/configs/msm8953_defconfig
index 70adcf1..64b848b 100644
--- a/arch/arm/configs/msm8953_defconfig
+++ b/arch/arm/configs/msm8953_defconfig
@@ -67,6 +67,7 @@
CONFIG_PREEMPT=y
CONFIG_AEABI=y
CONFIG_HIGHMEM=y
+CONFIG_ARM_MODULE_PLTS=y
CONFIG_CMA=y
CONFIG_CMA_DEBUGFS=y
CONFIG_ZSMALLOC=y
@@ -149,6 +150,7 @@
CONFIG_NETFILTER_XT_TARGET_TRACE=y
CONFIG_NETFILTER_XT_TARGET_SECMARK=y
CONFIG_NETFILTER_XT_TARGET_TCPMSS=y
+CONFIG_NETFILTER_XT_MATCH_BPF=y
CONFIG_NETFILTER_XT_MATCH_COMMENT=y
CONFIG_NETFILTER_XT_MATCH_CONNLIMIT=y
CONFIG_NETFILTER_XT_MATCH_CONNMARK=y
@@ -352,10 +354,10 @@
CONFIG_POWER_RESET=y
CONFIG_POWER_RESET_QCOM=y
CONFIG_QCOM_DLOAD_MODE=y
-CONFIG_POWER_RESET_SYSCON=y
CONFIG_POWER_SUPPLY=y
CONFIG_QPNP_FG=y
CONFIG_SMB135X_CHARGER=y
+CONFIG_SMB1355_SLAVE_CHARGER=y
CONFIG_SMB1351_USB_CHARGER=y
CONFIG_QPNP_SMB5=y
CONFIG_QPNP_SMBCHARGER=y
@@ -377,7 +379,9 @@
CONFIG_REGULATOR_COOLING_DEVICE=y
CONFIG_QTI_BCL_PMIC5=y
CONFIG_QTI_BCL_SOC_DRIVER=y
+CONFIG_MFD_I2C_PMIC=y
CONFIG_MFD_SPMI_PMIC=y
+CONFIG_MFD_SYSCON=y
CONFIG_REGULATOR=y
CONFIG_REGULATOR_FIXED_VOLTAGE=y
CONFIG_REGULATOR_PROXY_CONSUMER=y
@@ -564,7 +568,6 @@
CONFIG_MSM_L2_SPM=y
CONFIG_MSM_BOOT_STATS=y
CONFIG_MSM_CORE_HANG_DETECT=y
-CONFIG_MSM_GLADIATOR_HANG_DETECT=y
CONFIG_QCOM_WATCHDOG_V2=y
CONFIG_QCOM_MEMORY_DUMP_V2=y
CONFIG_MSM_DEBUG_LAR_UNLOCK=y
@@ -590,6 +593,7 @@
CONFIG_MSM_EVENT_TIMER=y
CONFIG_MSM_AVTIMER=y
CONFIG_MSM_PM=y
+CONFIG_QCOM_DCC=y
CONFIG_QTI_RPM_STATS_LOG=y
CONFIG_QCOM_FORCE_WDOG_BITE_ON_PANIC=y
CONFIG_MEM_SHARE_QMI_SERVICE=y
@@ -597,12 +601,14 @@
CONFIG_WCNSS_CORE=y
CONFIG_WCNSS_CORE_PRONTO=y
CONFIG_WCNSS_REGISTER_DUMP_ON_BITE=y
+CONFIG_BIG_CLUSTER_MIN_FREQ_ADJUST=y
CONFIG_QCOM_BIMC_BWMON=y
CONFIG_DEVFREQ_GOV_QCOM_BW_HWMON=y
CONFIG_DEVFREQ_SIMPLE_DEV=y
CONFIG_QCOM_DEVFREQ_DEVBW=y
CONFIG_SPDM_SCM=y
CONFIG_DEVFREQ_SPDM=y
+CONFIG_IIO=y
CONFIG_PWM=y
CONFIG_PWM_QPNP=y
CONFIG_PWM_QTI_LPG=y
@@ -684,8 +690,12 @@
CONFIG_PID_IN_CONTEXTIDR=y
CONFIG_DEBUG_SET_MODULE_RONX=y
CONFIG_CORESIGHT=y
+CONFIG_CORESIGHT_LINK_AND_SINK_TMC=y
+CONFIG_CORESIGHT_SOURCE_ETM4X=y
CONFIG_CORESIGHT_REMOTE_ETM=y
CONFIG_CORESIGHT_REMOTE_ETM_DEFAULT_ENABLE=0
+CONFIG_CORESIGHT_QCOM_REPLICATOR=y
+CONFIG_CORESIGHT_DBGUI=y
CONFIG_CORESIGHT_STM=y
CONFIG_CORESIGHT_TPDA=y
CONFIG_CORESIGHT_TPDM=y
diff --git a/arch/arm/include/asm/assembler.h b/arch/arm/include/asm/assembler.h
index 12f99fd..3aed449 100644
--- a/arch/arm/include/asm/assembler.h
+++ b/arch/arm/include/asm/assembler.h
@@ -534,4 +534,14 @@
#endif
.endm
+#ifdef CONFIG_KPROBES
+#define _ASM_NOKPROBE(entry) \
+ .pushsection "_kprobe_blacklist", "aw" ; \
+ .balign 4 ; \
+ .long entry; \
+ .popsection
+#else
+#define _ASM_NOKPROBE(entry)
+#endif
+
#endif /* __ASM_ASSEMBLER_H__ */
diff --git a/arch/arm/include/asm/kvm_mmu.h b/arch/arm/include/asm/kvm_mmu.h
index d10e362..7f66b1b 100644
--- a/arch/arm/include/asm/kvm_mmu.h
+++ b/arch/arm/include/asm/kvm_mmu.h
@@ -223,6 +223,22 @@
return 8;
}
+/*
+ * We are not in the kvm->srcu critical section most of the time, so we take
+ * the SRCU read lock here. Since we copy the data from the user page, we
+ * can immediately drop the lock again.
+ */
+static inline int kvm_read_guest_lock(struct kvm *kvm,
+ gpa_t gpa, void *data, unsigned long len)
+{
+ int srcu_idx = srcu_read_lock(&kvm->srcu);
+ int ret = kvm_read_guest(kvm, gpa, data, len);
+
+ srcu_read_unlock(&kvm->srcu, srcu_idx);
+
+ return ret;
+}
+
static inline void *kvm_get_hyp_vector(void)
{
return kvm_ksym_ref(__kvm_hyp_vector);
diff --git a/arch/arm/kernel/perf_event_v7.c b/arch/arm/kernel/perf_event_v7.c
index 342efa6..f85665d 100644
--- a/arch/arm/kernel/perf_event_v7.c
+++ b/arch/arm/kernel/perf_event_v7.c
@@ -1279,6 +1279,16 @@
return armv7_probe_pmu(cpu_pmu);
}
+static int armv8_pmuv3_pmu_init(struct arm_pmu *cpu_pmu)
+{
+ armv7pmu_init(cpu_pmu);
+ cpu_pmu->name = "ARMv8 Cortex-A53";
+ cpu_pmu->map_event = armv7_a7_map_event;
+ armv7_read_num_pmnc_events(&cpu_pmu->num_events);
+ cpu_pmu->set_event_filter = armv7pmu_set_event_filter;
+ return 0;
+}
+
static int armv7_a7_pmu_init(struct arm_pmu *cpu_pmu)
{
armv7pmu_init(cpu_pmu);
@@ -2049,6 +2059,7 @@
{.compatible = "qcom,krait-pmu", .data = krait_pmu_init},
{.compatible = "qcom,scorpion-pmu", .data = scorpion_pmu_init},
{.compatible = "qcom,scorpion-mp-pmu", .data = scorpion_mp_pmu_init},
+ {.compatible = "arm,armv8-pmuv3", .data = armv8_pmuv3_pmu_init},
{},
};
diff --git a/arch/arm/kernel/traps.c b/arch/arm/kernel/traps.c
index 1b30489..aa316a7 100644
--- a/arch/arm/kernel/traps.c
+++ b/arch/arm/kernel/traps.c
@@ -19,6 +19,7 @@
#include <linux/uaccess.h>
#include <linux/hardirq.h>
#include <linux/kdebug.h>
+#include <linux/kprobes.h>
#include <linux/module.h>
#include <linux/kexec.h>
#include <linux/bug.h>
@@ -415,7 +416,8 @@
raw_spin_unlock_irqrestore(&undef_lock, flags);
}
-static int call_undef_hook(struct pt_regs *regs, unsigned int instr)
+static nokprobe_inline
+int call_undef_hook(struct pt_regs *regs, unsigned int instr)
{
struct undef_hook *hook;
unsigned long flags;
@@ -488,6 +490,7 @@
arm_notify_die("Oops - undefined instruction", regs, &info, 0, 6);
}
+NOKPROBE_SYMBOL(do_undefinstr)
/*
* Handle FIQ similarly to NMI on x86 systems.
diff --git a/arch/arm/lib/getuser.S b/arch/arm/lib/getuser.S
index df73914..746e780 100644
--- a/arch/arm/lib/getuser.S
+++ b/arch/arm/lib/getuser.S
@@ -38,6 +38,7 @@
mov r0, #0
ret lr
ENDPROC(__get_user_1)
+_ASM_NOKPROBE(__get_user_1)
ENTRY(__get_user_2)
check_uaccess r0, 2, r1, r2, __get_user_bad
@@ -58,6 +59,7 @@
mov r0, #0
ret lr
ENDPROC(__get_user_2)
+_ASM_NOKPROBE(__get_user_2)
ENTRY(__get_user_4)
check_uaccess r0, 4, r1, r2, __get_user_bad
@@ -65,6 +67,7 @@
mov r0, #0
ret lr
ENDPROC(__get_user_4)
+_ASM_NOKPROBE(__get_user_4)
ENTRY(__get_user_8)
check_uaccess r0, 8, r1, r2, __get_user_bad8
@@ -78,6 +81,7 @@
mov r0, #0
ret lr
ENDPROC(__get_user_8)
+_ASM_NOKPROBE(__get_user_8)
#ifdef __ARMEB__
ENTRY(__get_user_32t_8)
@@ -91,6 +95,7 @@
mov r0, #0
ret lr
ENDPROC(__get_user_32t_8)
+_ASM_NOKPROBE(__get_user_32t_8)
ENTRY(__get_user_64t_1)
check_uaccess r0, 1, r1, r2, __get_user_bad8
@@ -98,6 +103,7 @@
mov r0, #0
ret lr
ENDPROC(__get_user_64t_1)
+_ASM_NOKPROBE(__get_user_64t_1)
ENTRY(__get_user_64t_2)
check_uaccess r0, 2, r1, r2, __get_user_bad8
@@ -114,6 +120,7 @@
mov r0, #0
ret lr
ENDPROC(__get_user_64t_2)
+_ASM_NOKPROBE(__get_user_64t_2)
ENTRY(__get_user_64t_4)
check_uaccess r0, 4, r1, r2, __get_user_bad8
@@ -121,6 +128,7 @@
mov r0, #0
ret lr
ENDPROC(__get_user_64t_4)
+_ASM_NOKPROBE(__get_user_64t_4)
#endif
__get_user_bad8:
@@ -131,6 +139,8 @@
ret lr
ENDPROC(__get_user_bad)
ENDPROC(__get_user_bad8)
+_ASM_NOKPROBE(__get_user_bad)
+_ASM_NOKPROBE(__get_user_bad8)
.pushsection __ex_table, "a"
.long 1b, __get_user_bad
diff --git a/arch/arm/mach-qcom/board-msm8917.c b/arch/arm/mach-qcom/board-msm8917.c
index 63bc43b..0bd6984 100644
--- a/arch/arm/mach-qcom/board-msm8917.c
+++ b/arch/arm/mach-qcom/board-msm8917.c
@@ -17,6 +17,7 @@
static const char *msm8917_dt_match[] __initconst = {
"qcom,msm8917",
+ "qcom,apq8017",
NULL
};
diff --git a/arch/arm/probes/kprobes/opt-arm.c b/arch/arm/probes/kprobes/opt-arm.c
index bcdecc2..b2aa9b3 100644
--- a/arch/arm/probes/kprobes/opt-arm.c
+++ b/arch/arm/probes/kprobes/opt-arm.c
@@ -165,13 +165,14 @@
{
unsigned long flags;
struct kprobe *p = &op->kp;
- struct kprobe_ctlblk *kcb = get_kprobe_ctlblk();
+ struct kprobe_ctlblk *kcb;
/* Save skipped registers */
regs->ARM_pc = (unsigned long)op->kp.addr;
regs->ARM_ORIG_r0 = ~0UL;
local_irq_save(flags);
+ kcb = get_kprobe_ctlblk();
if (kprobe_running()) {
kprobes_inc_nmissed_count(&op->kp);
@@ -191,6 +192,7 @@
local_irq_restore(flags);
}
+NOKPROBE_SYMBOL(optimized_callback)
int arch_prepare_optimized_kprobe(struct optimized_kprobe *op, struct kprobe *orig)
{
diff --git a/arch/arm64/boot/dts/qcom/8909-pm8916.dtsi b/arch/arm64/boot/dts/qcom/8909-pm8916.dtsi
index 3247d0d..b073d99 100644
--- a/arch/arm64/boot/dts/qcom/8909-pm8916.dtsi
+++ b/arch/arm64/boot/dts/qcom/8909-pm8916.dtsi
@@ -185,16 +185,6 @@
qcom,mdss_dsi_pll@1ac8300 {
vddio-supply = <&pm8916_l6>;
};
-
- qcom,msm-thermal {
- vdd-dig-supply = <&pm8916_s1_floor_corner>;
-
- qcom,vdd-apps-rstr {
- qcom,vdd-rstr-reg = "vdd-apps";
- qcom,levels = <800000>;
- qcom,freq-req;
- };
- };
};
@@ -296,6 +286,7 @@
qcom,scale-function = <2>;
qcom,hw-settle-time = <2>;
qcom,fast-avg-setup = <0>;
+ qcom,vadc-thermal-node;
};
chan@32 {
@@ -307,6 +298,7 @@
qcom,scale-function = <4>;
qcom,hw-settle-time = <2>;
qcom,fast-avg-setup = <0>;
+ qcom,vadc-thermal-node;
};
chan@3c {
@@ -318,6 +310,7 @@
qcom,scale-function = <4>;
qcom,hw-settle-time = <2>;
qcom,fast-avg-setup = <0>;
+ qcom,vadc-thermal-node;
};
};
@@ -350,3 +343,86 @@
#include "msm8909-pm8916-pm.dtsi"
+&soc {
+ thermal-zones {
+ xo-therm-buf-adc {
+ polling-delay-passive = <0>;
+ polling-delay = <1000>;
+ thermal-sensors = <&pm8916_vadc 0x3c>;
+ thermal-governor = "user_space";
+
+ trips {
+ active-config0 {
+ temperature = <65000>;
+ hysteresis = <1000>;
+ type = "passive";
+ };
+ };
+ };
+
+ xo-therm-adc {
+ polling-delay-passive = <0>;
+ polling-delay = <1000>;
+ thermal-sensors = <&pm8916_vadc 0x32>;
+ thermal-governor = "user_space";
+
+ trips {
+ active-config0 {
+ temperature = <65000>;
+ hysteresis = <1000>;
+ type = "passive";
+ };
+ };
+ };
+
+ pa-therm0-adc {
+ polling-delay-passive = <0>;
+ polling-delay = <1000>;
+ thermal-sensors = <&pm8916_vadc 0x36>;
+ thermal-governor = "user_space";
+
+ trips {
+ active-config0 {
+ temperature = <65000>;
+ hysteresis = <1000>;
+ type = "passive";
+ };
+ };
+ };
+ mdm-lowf {
+ cooling-maps {
+ cx_vdd_cdev {
+ cooling-device = <&pm8916_cx_cdev 0 0>;
+ };
+ };
+ };
+ camera-lowf {
+ cooling-maps {
+ cx_vdd_cdev {
+ cooling-device = <&pm8916_cx_cdev 0 0>;
+ };
+ };
+ };
+ gpu-lowf {
+ cooling-maps {
+ cx_vdd_cdev {
+ cooling-device = <&pm8916_cx_cdev 0 0>;
+ };
+ };
+ };
+ cpu0-2-lowf {
+ cooling-maps {
+ cx_vdd_cdev {
+ cooling-device = <&pm8916_cx_cdev 0 0>;
+ };
+ };
+ };
+ cpu1-3-lowf {
+ cooling-maps {
+ cx_vdd_cdev {
+ cooling-device = <&pm8916_cx_cdev 0 0>;
+ };
+ };
+ };
+ };
+};
diff --git a/arch/arm64/boot/dts/qcom/Makefile b/arch/arm64/boot/dts/qcom/Makefile
index 1d845e8..3ad1c0e 100644
--- a/arch/arm64/boot/dts/qcom/Makefile
+++ b/arch/arm64/boot/dts/qcom/Makefile
@@ -142,11 +142,16 @@
sdm670-pm660a-tasha-codec-cdp-overlay.dtbo \
sdm670-aqt1000-cdp-overlay.dtbo \
sdm670-pm660a-aqt1000-cdp-overlay.dtbo \
+ sxr1120-lc-mtp-overlay.dtbo \
+ sxr1120-lc-external-codec-mtp-overlay.dtbo \
+ sxr1120-lc-cdp-overlay.dtbo \
+ sxr1120-lc-external-codec-cdp-overlay.dtbo \
qcs605-cdp-overlay.dtbo \
qcs605-mtp-overlay.dtbo \
qcs605-360camera-overlay.dtbo \
qcs605-external-codec-mtp-overlay.dtbo \
qcs605-lc-mtp-overlay.dtbo \
+ qcs605-lc-cdp-overlay.dtbo \
sdm710-cdp-overlay.dtbo \
sdm710-mtp-overlay.dtbo \
sdm710-qrd-overlay.dtbo \
@@ -198,11 +203,16 @@
sda670-hdk-overlay.dtbo-base := sda670.dtb
sda670-pm660a-cdp-overlay.dtbo-base := sda670.dtb
sda670-pm660a-mtp-overlay.dtbo-base := sda670.dtb
+sxr1120-lc-mtp-overlay.dtbo-base := sxr1120-lc.dtb
+sxr1120-lc-external-codec-mtp-overlay.dtbo-base := sxr1120-lc.dtb
+sxr1120-lc-cdp-overlay.dtbo-base := sxr1120-lc.dtb
+sxr1120-lc-external-codec-cdp-overlay.dtbo-base := sxr1120-lc.dtb
qcs605-cdp-overlay.dtbo-base := qcs605.dtb
qcs605-mtp-overlay.dtbo-base := qcs605.dtb
qcs605-external-codec-mtp-overlay.dtbo-base := qcs605.dtb
qcs605-lc-mtp-overlay.dtbo-base := qcs605-lc.dtb
qcs605-360camera-overlay.dtbo-base := qcs605.dtb
+qcs605-lc-cdp-overlay.dtbo-base := qcs605-lc-cdp-base.dtb
sdm710-cdp-overlay.dtbo-base := sdm710.dtb
sdm710-mtp-overlay.dtbo-base := sdm710.dtb
sdm710-qrd-overlay.dtbo-base := sdm710.dtb
@@ -253,11 +263,16 @@
sdm670-pm660a-tasha-codec-cdp.dtb \
sda670-pm660a-mtp.dtb \
sda670-pm660a-cdp.dtb \
+ sxr1120-lc-mtp.dtb \
+ sxr1120-lc-external-codec-mtp.dtb \
+ sxr1120-lc-cdp.dtb \
+ sxr1120-lc-external-codec-cdp.dtb \
qcs605-360camera.dtb \
qcs605-mtp.dtb \
qcs605-cdp.dtb \
qcs605-external-codec-mtp.dtb \
qcs605-lc-mtp.dtb \
+ qcs605-lc-cdp.dtb \
sdm710-mtp.dtb \
sdm710-cdp.dtb \
sdm710-qrd.dtb \
@@ -312,7 +327,8 @@
dtbo-$(CONFIG_ARCH_SDM439) += sdm439-mtp-overlay.dtbo \
sdm439-cdp-overlay.dtbo \
sdm439-qrd-overlay.dtbo \
- sdm439-external-codec-mtp-overlay.dtbo
+ sdm439-external-codec-mtp-overlay.dtbo \
+ sdm439-rcm-overlay.dtbo
dtbo-$(CONFIG_ARCH_SDM429) += sdm429-mtp-overlay.dtbo \
sdm429-cdp-overlay.dtbo \
@@ -380,6 +396,7 @@
sdm439-qrd-overlay.dtbo-base := sdm439.dtb \
msm8937-interposer-sdm439.dtb
sdm439-external-codec-mtp-overlay.dtbo-base := sdm439.dtb
+sdm439-rcm-overlay.dtbo-base := sdm439.dtb
sdm429-mtp-overlay.dtbo-base := sdm429.dtb \
sda429.dtb \
msm8937-interposer-sdm429.dtb
@@ -489,7 +506,8 @@
sdm439-qrd.dtb \
sda439-mtp.dtb \
sda439-cdp.dtb \
- sdm439-external-codec-mtp.dtb
+ sdm439-external-codec-mtp.dtb \
+ sdm439-rcm.dtb
dtb-$(CONFIG_ARCH_SDM429) += sdm429-mtp.dtb \
sdm429-cdp.dtb \
diff --git a/arch/arm64/boot/dts/qcom/apq8009-audio-external_codec.dtsi b/arch/arm64/boot/dts/qcom/apq8009-audio-external_codec.dtsi
index d28e139..9261dfe 100644
--- a/arch/arm64/boot/dts/qcom/apq8009-audio-external_codec.dtsi
+++ b/arch/arm64/boot/dts/qcom/apq8009-audio-external_codec.dtsi
@@ -19,6 +19,12 @@
};
&soc {
+ qcom,msm-audio-apr {
+ compatible = "qcom,msm-audio-apr";
+ msm_audio_apr_dummy {
+ compatible = "qcom,msm-audio-apr-dummy";
+ };
+ };
sound-9335 {
compatible = "qcom,apq8009-audio-i2s-codec";
qcom,model = "apq8009-tashalite-snd-card";
@@ -234,16 +240,17 @@
qcom,msm-cpudai-tdm-group-num-ports = <1>;
qcom,msm-cpudai-tdm-group-port-id = <36864>;
qcom,msm-cpudai-tdm-clk-rate = <12288000>;
+ qcom,msm-cpudai-tdm-clk-internal = <1>;
+ qcom,msm-cpudai-tdm-sync-mode = <0>;
+ qcom,msm-cpudai-tdm-sync-src = <1>;
+ qcom,msm-cpudai-tdm-data-out = <0>;
+ qcom,msm-cpudai-tdm-invert-sync = <0>;
+ qcom,msm-cpudai-tdm-data-delay = <1>;
qcom,msm-cpudai-tdm-sec-port-enable;
qcom,msm-cpudai-tdm-clk-attribute = /bits/ 16 <1>;
dai_pri_tdm_rx_0: qcom,msm-dai-q6-tdm-pri-rx-0 {
compatible = "qcom,msm-dai-q6-tdm";
qcom,msm-cpudai-tdm-dev-id = <36864>;
- qcom,msm-cpudai-tdm-sync-mode = <0>;
- qcom,msm-cpudai-tdm-sync-src = <1>;
- qcom,msm-cpudai-tdm-data-out = <0>;
- qcom,msm-cpudai-tdm-invert-sync = <0>;
- qcom,msm-cpudai-tdm-data-delay = <1>;
qcom,msm-cpudai-tdm-data-align = <0>;
};
};
@@ -254,17 +261,26 @@
qcom,msm-cpudai-tdm-group-num-ports = <1>;
qcom,msm-cpudai-tdm-group-port-id = <36865>;
qcom,msm-cpudai-tdm-clk-rate = <12288000>;
+ qcom,msm-cpudai-tdm-clk-internal = <1>;
+ qcom,msm-cpudai-tdm-sync-mode = <0>;
+ qcom,msm-cpudai-tdm-sync-src = <1>;
+ qcom,msm-cpudai-tdm-data-out = <0>;
+ qcom,msm-cpudai-tdm-invert-sync = <0>;
+ qcom,msm-cpudai-tdm-data-delay = <1>;
qcom,msm-cpudai-tdm-sec-port-enable;
qcom,msm-cpudai-tdm-clk-attribute = /bits/ 16 <1>;
dai_pri_tdm_tx_0: qcom,msm-dai-q6-tdm-pri-tx-0 {
compatible = "qcom,msm-dai-q6-tdm";
qcom,msm-cpudai-tdm-dev-id = <36865>;
- qcom,msm-cpudai-tdm-sync-mode = <0>;
- qcom,msm-cpudai-tdm-sync-src = <1>;
- qcom,msm-cpudai-tdm-data-out = <0>;
- qcom,msm-cpudai-tdm-invert-sync = <0>;
- qcom,msm-cpudai-tdm-data-delay = <1>;
qcom,msm-cpudai-tdm-data-align = <0>;
};
};
};
+
+&wcd9xxx_intc {
+ status = "okay";
+};
+
+&clock_audio {
+ status = "okay";
+};
diff --git a/arch/arm64/boot/dts/qcom/apq8009-dragon.dts b/arch/arm64/boot/dts/qcom/apq8009-dragon.dts
index 12a4363..ba12854 100644
--- a/arch/arm64/boot/dts/qcom/apq8009-dragon.dts
+++ b/arch/arm64/boot/dts/qcom/apq8009-dragon.dts
@@ -71,10 +71,88 @@
compatible = "qca,qca9379";
qca,bt-reset-gpio = <&msm_gpio 47 0>; /* BT_EN */
};
+
+ cnss_sdio: qcom,cnss_sdio {
+ compatible = "qcom,cnss_sdio";
+ subsys-name = "AR6320";
+ /**
+ * There is no vdd-wlan on board and this is not for DSRC.
+ * IO and XTAL share the same vreg.
+ **/
+ vdd-wlan-io-supply = <&pm8916_l5>;
+ qcom,cap-tsf-gpio = <&msm_gpio 42 1>;
+ qcom,wlan-ramdump-dynamic = <0x200000>;
+ qcom,msm-bus,name = "msm-cnss";
+ qcom,msm-bus,num-cases = <4>;
+ qcom,msm-bus,num-paths = <1>;
+ qcom,msm-bus,vectors-KBps =
+ <79 512 0 0>, /* No vote */
+ <79 512 6250 200000>, /* 50 Mbps */
+ <79 512 25000 200000>, /* 200 Mbps */
+ <79 512 2048000 4096000>; /* MAX */
+ };
+};
+
+&wcnss {
+ status = "disabled";
+};
+
+&msm_gpio {
+ sdc2_wlan_gpio_on: sdc2_wlan_gpio_on {
+ mux {
+ pins = "gpio43";
+ function = "gpio";
+ };
+ config {
+ pins = "gpio43";
+ drive-strength = <10>;
+ bias-pull-up;
+ output-high;
+ };
+ };
+
+ sdc2_wlan_gpio_off: sdc2_wlan_gpio_off {
+ mux {
+ pins = "gpio43";
+ function = "gpio";
+ };
+ config {
+ pins = "gpio43";
+ drive-strength = <2>;
+ bias-disable;
+ output-low;
+ };
+ };
};
&sdhc_2 {
- status = "disabled";
+ /delete-property/cd-gpios;
+ #address-cells = <0>;
+ interrupt-parent = <&sdhc_2>;
+ interrupts = <0 1 2>;
+ #interrupt-cells = <1>;
+ interrupt-map-mask = <0xffffffff>;
+ interrupt-map = <0 &intc 0 125 0
+ 1 &intc 0 221 0
+ 2 &msm_gpio 40 0x1>;
+ interrupt-names = "hc_irq", "pwr_irq", "sdiowakeup_irq";
+
+ qcom,vdd-voltage-level = <1800000 2950000>;
+ qcom,vdd-current-level = <15000 400000>;
+
+ qcom,vdd-io-voltage-level = <1800000 1800000>;
+ qcom,vdd-io-current-level = <200 50000>;
+ qcom,clk-rates = <400000 25000000 50000000 100000000 200000000>;
+ qcom,bus-speed-mode = "SDR12", "SDR25", "SDR50", "DDR50", "SDR104";
+
+ pinctrl-names = "active", "sleep";
+ pinctrl-0 = <&sdc2_clk_on &sdc2_cmd_on &sdc2_data_on
+ &sdc2_wlan_gpio_on>;
+ pinctrl-1 = <&sdc2_clk_off &sdc2_cmd_off &sdc2_data_off
+ &sdc2_wlan_gpio_off>;
+ qcom,nonremovable;
+ qcom,core_3_0v_support;
+ status = "ok";
};
&usb_otg {
diff --git a/arch/arm64/boot/dts/qcom/apq8009-mtp-wcd9326-refboard.dts b/arch/arm64/boot/dts/qcom/apq8009-mtp-wcd9326-refboard.dts
index 1866e2f..2afd5ac 100644
--- a/arch/arm64/boot/dts/qcom/apq8009-mtp-wcd9326-refboard.dts
+++ b/arch/arm64/boot/dts/qcom/apq8009-mtp-wcd9326-refboard.dts
@@ -95,7 +95,7 @@
};
&soc {
- sound-9335 {
+ ext_codec: sound-9335 {
qcom,audio-routing =
"AIF4 VI", "MCLK",
"RX_BIAS", "MCLK",
@@ -112,12 +112,22 @@
"MIC BIAS3", "Digital Mic3",
"SpkrLeft IN", "SPK1 OUT",
"SpkrRight IN", "SPK2 OUT";
- };
- i2c@78b8000 {
- wcd9xxx_codec@d {
- qcom,cdc-reset-gpio = <&msm_gpio 27 0>;
- };
+ qcom,msm-gpios =
+ "us_eu_gpio";
+ qcom,pinctrl-names =
+ "all_off",
+ "us_eu_gpio_act";
+ pinctrl-names =
+ "all_off",
+ "us_eu_gpio_act";
+ pinctrl-0 = <&cross_conn_det_sus>;
+ pinctrl-1 = <&cross_conn_det_act>;
+ qcom,pri-mi2s-gpios = <&cdc_pri_mi2s_gpios>;
+ qcom,quat-mi2s-gpios = <&cdc_quat_mi2s_gpios>;
+
+ qcom,wsa-aux-dev-prefix = "SpkrLeft", "SpkrRight",
+ "SpkrLeft", "SpkrRight";
};
i2c@78b9000 {
@@ -205,6 +215,36 @@
qcom,id-det-gpio = <&msm_gpio 110 0>;
qcom,dpdm_switch_gpio = <&pm8916_gpios 3 0>;
};
+
+ i2c@78b8000 {
+ wcd9xxx_codec@d {
+ status = "okay";
+ qcom,wcd-rst-gpio-node = <&wcd_rst_gpio>;
+ };
+ };
+
+ cdc_pri_mi2s_gpios: msm_cdc_pinctrl_pri {
+ compatible = "qcom,msm-cdc-pinctrl";
+ pinctrl-names = "aud_active", "aud_sleep";
+ pinctrl-0 = <&pri_mi2s_active &pri_mi2s_ws_active
+ &pri_mi2s_dout_active &pri_mi2s_din_active>;
+ pinctrl-1 = <&pri_mi2s_sleep &pri_mi2s_ws_sleep
+ &pri_mi2s_dout_sleep &pri_mi2s_din_sleep>;
+ };
+
+ cdc_quat_mi2s_gpios: msm_cdc_pinctrl_quat {
+ compatible = "qcom,msm-cdc-pinctrl";
+ pinctrl-names = "aud_active", "aud_sleep";
+ pinctrl-0 = <&quat_mi2s_active &quat_mi2s_din_active>;
+ pinctrl-1 = <&quat_mi2s_sleep &quat_mi2s_din_sleep>;
+ };
+
+ wcd_rst_gpio: wcd_gpio_ctrl {
+ compatible = "qcom,msm-cdc-pinctrl";
+ pinctrl-names = "aud_active", "aud_sleep";
+ pinctrl-0 = <&cdc_reset_active>;
+ pinctrl-1 = <&cdc_reset_sleep>;
+ };
};
&wcnss {
@@ -327,4 +367,16 @@
status = "disabled";
};
+&wcd_rst_gpio {
+ status = "okay";
+};
+
+&ext_codec {
+ status = "okay";
+};
+
+&blsp1_uart2_hs {
+ status = "disabled";
+};
+
/delete-node/ &cont_splash_mem;
diff --git a/arch/arm64/boot/dts/qcom/apq8009-robot-som-refboard.dts b/arch/arm64/boot/dts/qcom/apq8009-robot-som-refboard.dts
index 1314129..ec5715d 100644
--- a/arch/arm64/boot/dts/qcom/apq8009-robot-som-refboard.dts
+++ b/arch/arm64/boot/dts/qcom/apq8009-robot-som-refboard.dts
@@ -92,6 +92,28 @@
};
};
+&i2c_1 {
+ status = "okay";
+ icm20602@68 {
+ compatible = "invensense,icm20602";
+ reg = <0x68>;
+ interrupt-parent = <&msm_gpio>;
+ interrupts = <12 0>;
+ invensense,icm20602-gpio = <&msm_gpio 12 0x0>;
+ vdd-ldo-supply = <&pm8916_l6>;
+ interrupt-names = "icm20602_irq";
+ pinctrl-names = "imu_active","imu_suspend";
+ pinctrl-0 = <&imu_int_active>;
+ pinctrl-1 = <&imu_int_suspend>;
+ status = "ok";
+ };
+ vl53l0x@29 {
+ compatible = "st,stmvl53l0";
+ reg = <0x29>;
+ status = "ok";
+ };
+};
+
&wcnss {
status = "disabled";
};
diff --git a/arch/arm64/boot/dts/qcom/apq8053-iot-mtp.dts b/arch/arm64/boot/dts/qcom/apq8053-iot-mtp.dts
index 9f0edda..8782001 100644
--- a/arch/arm64/boot/dts/qcom/apq8053-iot-mtp.dts
+++ b/arch/arm64/boot/dts/qcom/apq8053-iot-mtp.dts
@@ -86,3 +86,12 @@
qcom,model = "msm8953-tasha-snd-card";
status = "okay";
};
+
+&soc {
+ usb_detect: usb_detect {
+ compatible = "linux,extcon-usb-gpio";
+ pintctrl-names = "default";
+ pinctrl-0 = <&ssusb_mode_sel>;
+ id-gpio = <&tlmm 12 0>;
+ };
+};
diff --git a/arch/arm64/boot/dts/qcom/apq8053-lite-dragon-v2.1.dtsi b/arch/arm64/boot/dts/qcom/apq8053-lite-dragon-v2.1.dtsi
index 4d9c40c..993799b 100644
--- a/arch/arm64/boot/dts/qcom/apq8053-lite-dragon-v2.1.dtsi
+++ b/arch/arm64/boot/dts/qcom/apq8053-lite-dragon-v2.1.dtsi
@@ -14,7 +14,7 @@
#include "apq8053-lite-dragon.dtsi"
&mdss_dsi0 {
- qcom,ext_vdd-gpio = <&tlmm 100 0>;
+ qcom,ext-vdd-gpio = <&tlmm 100 0>;
qcom,platform-bklight-en-gpio = <&tlmm 95 0>;
qcom,platform-lane-config = [00 00 ff 0f
diff --git a/arch/arm64/boot/dts/qcom/apq8053-lite-dragon-v2.2.dtsi b/arch/arm64/boot/dts/qcom/apq8053-lite-dragon-v2.2.dtsi
index 396fd55..1744c90 100644
--- a/arch/arm64/boot/dts/qcom/apq8053-lite-dragon-v2.2.dtsi
+++ b/arch/arm64/boot/dts/qcom/apq8053-lite-dragon-v2.2.dtsi
@@ -18,6 +18,41 @@
/delete-node/ himax_ts@48;
};
+&mdss_mdp {
+ qcom,mdss-pref-prim-intf = "dsi";
+};
+
+&mdss_dsi {
+ hw-config = "single_dsi";
+};
+
+&mdss_dsi0 {
+ qcom,dsi-pref-prim-pan = <&dsi_boent51021_1200p_video>;
+ pinctrl-names = "mdss_default", "mdss_sleep";
+ pinctrl-0 = <&mdss_dsi_active &mdss_te_active>;
+ pinctrl-1 = <&mdss_dsi_suspend &mdss_te_suspend>;
+
+ vdd-supply = <&pm8953_l10>;
+ vddio-supply = <&pm8953_l6>;
+ lab-supply = <&lab_regulator>;
+ ibb-supply = <&ibb_regulator>;
+
+ qcom,platform-te-gpio = <&tlmm 24 0>;
+ qcom,platform-reset-gpio = <&tlmm 61 0>;
+ qcom,ext-vdd-gpio = <&tlmm 100 0>;
+ qcom,platform-bklight-en-gpio = <&tlmm 95 0>;
+
+ qcom,platform-lane-config = [00 00 ff 0f
+ 00 00 ff 0f
+ 00 00 ff 0f
+ 00 00 ff 0f
+ 00 00 ff 8f];
+};
+
+&mdss_dsi1 {
+ status = "disabled";
+};
+
&eeprom0 {
gpios = <&tlmm 26 0>,
<&tlmm 40 0>,
diff --git a/arch/arm64/boot/dts/qcom/dsi-panel-boent51021-1200p-video.dtsi b/arch/arm64/boot/dts/qcom/dsi-panel-boent51021-1200p-video.dtsi
new file mode 100644
index 0000000..04accd8
--- /dev/null
+++ b/arch/arm64/boot/dts/qcom/dsi-panel-boent51021-1200p-video.dtsi
@@ -0,0 +1,92 @@
+/* Novatek Android Driver Sample Code for Novatek chipset
+ *
+ * Copyright (C) 2015-2018 Novatek Microelectronics Corp.
+ *
+ * This software is licensed under the terms of the GNU General Public
+ * License version 2, as published by the Free Software Foundation, and
+ * may be copied, distributed, and modified under those terms.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ */
+
+&mdss_mdp {
+ dsi_boent51021_1200p_video: qcom,mdss_dsi_boent51021_1200p_video {
+ qcom,mdss-dsi-panel-name =
+ "boent51021 1200p video mode dsi panel";
+ qcom,mdss-dsi-panel-controller = <&mdss_dsi0>;
+ qcom,mdss-dsi-panel-type = "dsi_video_mode";
+ qcom,mdss-dsi-panel-framerate = <60>;
+ qcom,mdss-dsi-virtual-channel-id = <0>;
+ qcom,mdss-dsi-stream = <0>;
+ qcom,mdss-dsi-panel-width = <1200>;
+ qcom,mdss-dsi-panel-height = <1920>;
+ qcom,mdss-dsi-h-front-porch = <100>;
+ qcom,mdss-dsi-h-back-porch = <32>;
+ qcom,mdss-dsi-h-pulse-width = <1>;
+ qcom,mdss-dsi-h-sync-skew = <0>;
+ qcom,mdss-dsi-v-back-porch = <14>;
+ qcom,mdss-dsi-v-front-porch = <25>;
+ qcom,mdss-dsi-v-pulse-width = <1>;
+ qcom,mdss-dsi-h-left-border = <0>;
+ qcom,mdss-dsi-h-right-border = <0>;
+ qcom,mdss-dsi-v-top-border = <0>;
+ qcom,mdss-dsi-v-bottom-border = <0>;
+ qcom,mdss-dsi-bpp = <24>;
+ qcom,mdss-dsi-underflow-color = <0xff>;
+ qcom,mdss-dsi-border-color = <0>;
+ qcom,mdss-dsi-on-command = [
+ 23 01 00 00 01 00 02 8f a5
+ 23 01 00 00 00 00 02 83 00
+ 23 01 00 00 00 00 02 84 00
+ 23 01 00 00 00 00 02 8c 80
+ 23 01 00 00 00 00 02 cd 6c
+ 23 01 00 00 00 00 02 c8 fc
+ 23 01 00 00 00 00 02 97 00
+ 23 01 00 00 00 00 02 8b 10
+ 23 01 00 00 00 00 02 a9 20
+ 23 01 00 00 00 00 02 83 aa
+ 23 01 00 00 00 00 02 84 11
+ 23 01 00 00 00 00 02 a9 4b
+ 23 01 00 00 00 00 02 85 04
+ 23 01 00 00 00 00 02 86 08
+ 23 01 00 00 00 00 02 9c 10
+ 05 01 00 00 00 00 02 11 00
+ 23 01 00 00 00 00 02 8f 00
+ ];
+ qcom,mdss-dsi-off-command = [
+ 23 01 00 00 00 00 02 83 00
+ 23 01 00 00 78 00 02 84 00
+ 05 01 00 00 78 00 02 10 00
+ ];
+ qcom,mdss-dsi-on-command-state = "dsi_lp_mode";
+ qcom,mdss-dsi-off-command-state = "dsi_lp_mode";
+ qcom,mdss-dsi-h-sync-pulse = <1>;
+ qcom,mdss-dsi-traffic-mode = "burst_mode";
+ qcom,mdss-dsi-lane-map = "lane_map_0123";
+ qcom,mdss-dsi-bllp-eof-power-mode;
+ qcom,mdss-dsi-bllp-power-mode;
+ qcom,mdss-dsi-lane-0-state;
+ qcom,mdss-dsi-lane-1-state;
+ qcom,mdss-dsi-lane-2-state;
+ qcom,mdss-dsi-lane-3-state;
+ qcom,mdss-dsi-panel-timings = [
+ f2 3a 28 00 6c 70 2c 3e 2e 03 04 00];
+ qcom,mdss-dsi-t-clk-post = <0x0e>;
+ qcom,mdss-dsi-t-clk-pre = <0x33>;
+ qcom,mdss-dsi-bl-min-level = <1>;
+ qcom,mdss-dsi-bl-max-level = <4095>;
+ qcom,panel-supply-entries = <&dsi_panel_pwr_supply>;
+ qcom,mdss-dsi-dma-trigger = "trigger_sw";
+ qcom,mdss-dsi-mdp-trigger = "none";
+ qcom,mdss-dsi-force-clock-lane-hs;
+ qcom,mdss-dsi-bl-pmic-control-type = "bl_ctrl_wled";
+ qcom,mdss-pan-physical-width-dimension = <135>;
+ qcom,mdss-pan-physical-height-dimension = <216>;
+ qcom,mdss-dsi-lp11-init;
+ qcom,mdss-dsi-post-init-delay = <1>;
+ };
+};
diff --git a/arch/arm64/boot/dts/qcom/dsi-panel-hx8399c-hd-plus-video.dtsi b/arch/arm64/boot/dts/qcom/dsi-panel-hx8399c-hd-plus-video.dtsi
index 91bf722..89c5178 100644
--- a/arch/arm64/boot/dts/qcom/dsi-panel-hx8399c-hd-plus-video.dtsi
+++ b/arch/arm64/boot/dts/qcom/dsi-panel-hx8399c-hd-plus-video.dtsi
@@ -20,13 +20,13 @@
qcom,mdss-dsi-stream = <0>;
qcom,mdss-dsi-panel-width = <720>;
qcom,mdss-dsi-panel-height = <1440>;
- qcom,mdss-dsi-h-front-porch = <24>;
- qcom,mdss-dsi-h-back-porch = <24>;
+ qcom,mdss-dsi-h-front-porch = <48>;
+ qcom,mdss-dsi-h-back-porch = <48>;
qcom,mdss-dsi-h-pulse-width = <16>;
qcom,mdss-dsi-h-sync-skew = <0>;
qcom,mdss-dsi-v-back-porch = <40>;
- qcom,mdss-dsi-v-front-porch = <36>;
- qcom,mdss-dsi-v-pulse-width = <2>;
+ qcom,mdss-dsi-v-front-porch = <60>;
+ qcom,mdss-dsi-v-pulse-width = <4>;
qcom,mdss-dsi-h-left-border = <0>;
qcom,mdss-dsi-h-right-border = <0>;
qcom,mdss-dsi-v-top-border = <0>;
diff --git a/arch/arm64/boot/dts/qcom/fg-gen3-batterydata-mlp466076-3250mah.dtsi b/arch/arm64/boot/dts/qcom/fg-gen3-batterydata-mlp466076-3250mah.dtsi
new file mode 100644
index 0000000..2f48301
--- /dev/null
+++ b/arch/arm64/boot/dts/qcom/fg-gen3-batterydata-mlp466076-3250mah.dtsi
@@ -0,0 +1,88 @@
+/*
+ * Copyright (c) 2018, The Linux Foundation. All rights reserved.
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ *GNU General Public License for more details.
+ */
+
+qcom,mlp466076_3250mah_averaged_masterslave_jun15th2018 {
+ /* #mlp466076_3250mAh_averaged_MasterSlave_Jun15th2018 */
+ qcom,max-voltage-uv = <4400000>;
+ qcom,nom-batt-capacity-mah = <3250>;
+ qcom,fastchg-current-ma = <6000000>;
+ qcom,jeita-fcc-ranges = <0 150 650000
+ 151 450 4875000
+ 451 550 1625000>;
+ qcom,jeita-fv-ranges = <0 150 4150000
+ 151 450 4400000
+ 451 550 4150000>;
+ qcom,batt-id-kohm = <133>;
+ qcom,battery-beta = <4250>;
+ qcom,fg-cc-cv-threshold-mv = <4390>;
+ qcom,battery-type = "mlp466076_3250mah_jun15th2018";
+ qcom,checksum = <0x8905>;
+ qcom,gui-version = "PM660GUI - 0.0.0.45";
+ qcom,fg-profile-data = [
+ 5E 21 D2 0D
+ E3 0B 04 05
+ EC 1C 8B 01
+ 4F 05 31 03
+ 80 18 D2 22
+ C2 45 73 52
+ 90 00 00 00
+ 13 00 00 00
+ 00 00 82 C3
+ A3 CC 92 BC
+ 2F 00 08 00
+ 14 DA CE E5
+ B0 04 41 02
+ C5 F4 C4 12
+ 0C 07 3F 32
+ 2B 06 09 20
+ 27 00 14 00
+ 4C 20 E0 04
+ 1A 0B A1 05
+ C4 1C E7 02
+ 3E 0C 02 12
+ 9D 18 4C 23
+ DC 44 15 5A
+ 70 00 00 00
+ 10 00 00 00
+ 00 00 F6 07
+ 1D CB 02 B4
+ 20 00 00 00
+ 5B E3 CE E5
+ C8 05 54 01
+ A6 06 BD FB
+ 35 F4 47 23
+ C5 33 CC FF
+ 07 10 00 00
+ 38 0D 66 46
+ 20 00 40 00
+ 61 01 0A FA
+ FF 00 00 00
+ 00 00 00 00
+ 00 00 00 00
+ 00 00 00 00
+ 00 00 00 00
+ 00 00 00 00
+ 00 00 00 00
+ 00 00 00 00
+ 00 00 00 00
+ 00 00 00 00
+ 00 00 00 00
+ 00 00 00 00
+ 00 00 00 00
+ 00 00 00 00
+ 00 00 00 00
+ 00 00 00 00
+ 00 00 00 00
+ 00 00 00 00
+ 00 00 00 00
+ ];
+};
diff --git a/arch/arm64/boot/dts/qcom/msm-audio-lpass.dtsi b/arch/arm64/boot/dts/qcom/msm-audio-lpass.dtsi
index 9467297..13e5187 100644
--- a/arch/arm64/boot/dts/qcom/msm-audio-lpass.dtsi
+++ b/arch/arm64/boot/dts/qcom/msm-audio-lpass.dtsi
@@ -304,6 +304,7 @@
audio_apr: qcom,msm-audio-apr {
compatible = "qcom,msm-audio-apr";
+ qcom,subsys-name = "apr_adsp";
};
dai_pri_auxpcm: qcom,msm-pri-auxpcm {
diff --git a/arch/arm64/boot/dts/qcom/msm8909-gpu.dtsi b/arch/arm64/boot/dts/qcom/msm8909-gpu.dtsi
index 180d6c3..96d9ea7 100644
--- a/arch/arm64/boot/dts/qcom/msm8909-gpu.dtsi
+++ b/arch/arm64/boot/dts/qcom/msm8909-gpu.dtsi
@@ -81,6 +81,9 @@
qcom,pm-qos-active-latency = <701>;
qcom,pm-qos-wakeup-latency = <701>;
+ /* Enable gpu cooling device */
+ #cooling-cells = <2>;
+
/* Power levels */
qcom,gpu-pwrlevels {
#address-cells = <1>;
diff --git a/arch/arm64/boot/dts/qcom/msm8909-pinctrl.dtsi b/arch/arm64/boot/dts/qcom/msm8909-pinctrl.dtsi
index c86da64..743cf1c 100644
--- a/arch/arm64/boot/dts/qcom/msm8909-pinctrl.dtsi
+++ b/arch/arm64/boot/dts/qcom/msm8909-pinctrl.dtsi
@@ -545,6 +545,33 @@
};
};
+ imu {
+ imu_int_active: imu_int_active{
+ mux {
+ pins = "gpio12";
+ function = "gpio";
+ };
+ config {
+ pins = "gpio12";
+ drive-strength = <6>;
+ bias-pull-up;
+ };
+ };
+
+ imu_int_suspend: imu_int_suspend{
+ mux {
+ pins = "gpio12";
+ function = "gpio";
+ };
+ config {
+ pins = "gpio12";
+ drive-strength = <6>;
+ bias-pull-up;
+ };
+ };
+
+ };
+
nfc {
nfcw_int_active: nfcw_int_active {
mux {
@@ -1890,6 +1917,34 @@
};
};
+ cdc_reset_ctrl {
+ cdc_reset_sleep: cdc_reset_sleep {
+ mux {
+ pins = "gpio27";
+ function = "gpio";
+ };
+ config {
+ pins = "gpio27";
+ drive-strength = <16>;
+ bias-disable;
+ output-low;
+ };
+ };
+ cdc_reset_active:cdc_reset_active {
+ mux {
+ pins = "gpio27";
+ function = "gpio";
+ };
+ config {
+ pins = "gpio27"; /* gpio67 old */
+ drive-strength = <16>;
+ bias-pull-down;
+ output-high;
+ };
+ };
+ };
+
+
cdc-dmic-lines {
cdc_dmic0_clk_act: dmic0_clk_on {
mux {
diff --git a/arch/arm64/boot/dts/qcom/msm8909-regulator.dtsi b/arch/arm64/boot/dts/qcom/msm8909-regulator.dtsi
index 7197f88..70d4939 100644
--- a/arch/arm64/boot/dts/qcom/msm8909-regulator.dtsi
+++ b/arch/arm64/boot/dts/qcom/msm8909-regulator.dtsi
@@ -48,6 +48,12 @@
qcom,init-voltage = <1>;
qcom,use-voltage-corner;
};
+ pm8909_cx_cdev: regulator-cx-cdev {
+ compatible = "qcom,regulator-cooling-device";
+ regulator-cdev-supply = <&pm8909_s1_floor_corner>;
+ regulator-levels = <5 1>;
+ #cooling-cells = <2>;
+ };
};
rpm-regulator-smpa2 {
diff --git a/arch/arm64/boot/dts/qcom/msm8909-thermal.dtsi b/arch/arm64/boot/dts/qcom/msm8909-thermal.dtsi
new file mode 100644
index 0000000..21c393b
--- /dev/null
+++ b/arch/arm64/boot/dts/qcom/msm8909-thermal.dtsi
@@ -0,0 +1,477 @@
+/* Copyright (c) 2018, The Linux Foundation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ */
+
+#include <dt-bindings/thermal/thermal.h>
+
+&soc {
+ qmi-tmd-devices {
+ compatible = "qcom,qmi_cooling_devices";
+
+ modem {
+ qcom,instance-id = <0x0>;
+
+ modem_pa: modem_pa {
+ qcom,qmi-dev-name = "pa";
+ #cooling-cells = <2>;
+ };
+
+ modem_proc: modem_proc {
+ qcom,qmi-dev-name = "modem";
+ #cooling-cells = <2>;
+ };
+
+ modem_current: modem_current {
+ qcom,qmi-dev-name = "modem_current";
+ #cooling-cells = <2>;
+ };
+
+ modem_vdd: modem_vdd {
+ qcom,qmi-dev-name = "cpuv_restriction_cold";
+ #cooling-cells = <2>;
+ };
+ };
+ };
+};
+
+&thermal_zones {
+ mdm-usr {
+ polling-delay-passive = <0>;
+ polling-delay = <0>;
+ thermal-governor = "user_space";
+ thermal-sensors = <&tsens0 0>;
+ trips {
+ active-config0 {
+ temperature = <125000>;
+ hysteresis = <1000>;
+ type = "passive";
+ };
+ };
+ };
+
+ camera-usr {
+ polling-delay-passive = <0>;
+ polling-delay = <0>;
+ thermal-governor = "user_space";
+ thermal-sensors = <&tsens0 1>;
+ trips {
+ active-config0 {
+ temperature = <125000>;
+ hysteresis = <1000>;
+ type = "passive";
+ };
+ };
+ };
+
+ gpu-usr {
+ polling-delay-passive = <0>;
+ polling-delay = <0>;
+ thermal-governor = "user_space";
+ thermal-sensors = <&tsens0 2>;
+ trips {
+ active-config0 {
+ temperature = <125000>;
+ hysteresis = <1000>;
+ type = "passive";
+ };
+ };
+ };
+
+ cpu0-2-usr {
+ polling-delay-passive = <0>;
+ polling-delay = <0>;
+ thermal-governor = "user_space";
+ thermal-sensors = <&tsens0 3>;
+ trips {
+ active-config0 {
+ temperature = <125000>;
+ hysteresis = <1000>;
+ type = "passive";
+ };
+ };
+ };
+
+ cpu1-3-usr {
+ polling-delay-passive = <0>;
+ polling-delay = <0>;
+ thermal-governor = "user_space";
+ thermal-sensors = <&tsens0 4>;
+ trips {
+ active-config0 {
+ temperature = <125000>;
+ hysteresis = <1000>;
+ type = "passive";
+ };
+ };
+ };
+
+ pop-mem-step {
+ polling-delay-passive = <250>;
+ polling-delay = <0>;
+ thermal-sensors = <&tsens0 0>;
+ thermal-governor = "step_wise";
+ trips {
+ pop_trip: pop-trip {
+ temperature = <75000>;
+ hysteresis = <0>;
+ type = "passive";
+ };
+ };
+ cooling-maps {
+ pop_cdev0 {
+ trip = <&pop_trip>;
+ cooling-device =
+ <&CPU0 THERMAL_NO_LIMIT
+ (THERMAL_MAX_LIMIT-1)>;
+ };
+ pop_cdev1 {
+ trip = <&pop_trip>;
+ cooling-device =
+ <&CPU1 THERMAL_NO_LIMIT
+ (THERMAL_MAX_LIMIT-1)>;
+ };
+ pop_cdev2 {
+ trip = <&pop_trip>;
+ cooling-device =
+ <&CPU2 THERMAL_NO_LIMIT
+ (THERMAL_MAX_LIMIT-1)>;
+ };
+ pop_cdev3 {
+ trip = <&pop_trip>;
+ cooling-device =
+ <&CPU3 THERMAL_NO_LIMIT
+ (THERMAL_MAX_LIMIT-1)>;
+ };
+ };
+ };
+
+ gpu-step {
+ polling-delay-passive = <250>;
+ polling-delay = <0>;
+ thermal-sensors = <&tsens0 2>;
+ thermal-governor = "step_wise";
+ trips {
+ gpu_step_trip: gpu-step-trip {
+ temperature = <80000>;
+ hysteresis = <0>;
+ type = "passive";
+ };
+ };
+ cooling-maps {
+ gpu_cdev0 {
+ trip = <&gpu_step_trip>;
+ cooling-device =
+ <&msm_gpu THERMAL_NO_LIMIT
+ THERMAL_NO_LIMIT>;
+ };
+ };
+ };
+
+ cpu0-2-step {
+ polling-delay-passive = <65>;
+ polling-delay = <0>;
+ thermal-sensors = <&tsens0 3>;
+ thermal-governor = "step_wise";
+ trips {
+ cpu0_2_step_trip: cpu0-2-step-trip {
+ temperature = <85000>;
+ hysteresis = <0>;
+ type = "passive";
+ };
+ };
+ cooling-maps {
+ cpu0_cdev {
+ trip = <&cpu0_2_step_trip>;
+ cooling-device =
+ <&CPU0 THERMAL_NO_LIMIT
+ (THERMAL_MAX_LIMIT-1)>;
+ };
+ cpu1_cdev {
+ trip = <&cpu0_2_step_trip>;
+ cooling-device =
+ <&CPU1 THERMAL_NO_LIMIT
+ (THERMAL_MAX_LIMIT-1)>;
+ };
+ cpu2_cdev {
+ trip = <&cpu0_2_step_trip>;
+ cooling-device =
+ <&CPU2 THERMAL_NO_LIMIT
+ (THERMAL_MAX_LIMIT-1)>;
+ };
+ cpu3_cdev {
+ trip = <&cpu0_2_step_trip>;
+ cooling-device =
+ <&CPU3 THERMAL_NO_LIMIT
+ (THERMAL_MAX_LIMIT-1)>;
+ };
+ };
+ };
+
+ cpu1-3-step {
+ polling-delay-passive = <65>;
+ polling-delay = <0>;
+ thermal-sensors = <&tsens0 4>;
+ thermal-governor = "step_wise";
+ trips {
+ cpu1_3_step_trip: cpu1-3-step-trip {
+ temperature = <85000>;
+ hysteresis = <0>;
+ type = "passive";
+ };
+ };
+ cooling-maps {
+ cpu0_cdev {
+ trip = <&cpu1_3_step_trip>;
+ cooling-device =
+ <&CPU0 THERMAL_NO_LIMIT
+ (THERMAL_MAX_LIMIT-1)>;
+ };
+ cpu1_cdev {
+ trip = <&cpu1_3_step_trip>;
+ cooling-device =
+ <&CPU1 THERMAL_NO_LIMIT
+ (THERMAL_MAX_LIMIT-1)>;
+ };
+ cpu2_cdev {
+ trip = <&cpu1_3_step_trip>;
+ cooling-device =
+ <&CPU2 THERMAL_NO_LIMIT
+ (THERMAL_MAX_LIMIT-1)>;
+ };
+ cpu3_cdev {
+ trip = <&cpu1_3_step_trip>;
+ cooling-device =
+ <&CPU3 THERMAL_NO_LIMIT
+ (THERMAL_MAX_LIMIT-1)>;
+ };
+ };
+ };
+ mdm-lowf {
+ polling-delay-passive = <0>;
+ polling-delay = <0>;
+ thermal-governor = "low_limits_floor";
+ thermal-sensors = <&tsens0 0>;
+ tracks-low;
+ trips {
+ mdm_trip: mdm-trip {
+ temperature = <5000>;
+ hysteresis = <5000>;
+ type = "passive";
+ };
+ };
+ cooling-maps {
+ cpu0_vdd_cdev {
+ trip = <&mdm_trip>;
+ cooling-device =
+ <&CPU0 (THERMAL_MAX_LIMIT-2)
+ (THERMAL_MAX_LIMIT-2)>;
+ };
+ cpu1_vdd_cdev {
+ trip = <&mdm_trip>;
+ cooling-device =
+ <&CPU1 (THERMAL_MAX_LIMIT-2)
+ (THERMAL_MAX_LIMIT-2)>;
+ };
+ cpu2_vdd_cdev {
+ trip = <&mdm_trip>;
+ cooling-device =
+ <&CPU2 (THERMAL_MAX_LIMIT-2)
+ (THERMAL_MAX_LIMIT-2)>;
+ };
+ cpu3_vdd_cdev {
+ trip = <&mdm_trip>;
+ cooling-device =
+ <&CPU3 (THERMAL_MAX_LIMIT-2)
+ (THERMAL_MAX_LIMIT-2)>;
+ };
+ cx_vdd_cdev {
+ trip = <&mdm_trip>;
+ cooling-device = <&pm8909_cx_cdev 0 0>;
+ };
+ };
+ };
+ camera-lowf {
+ polling-delay-passive = <0>;
+ polling-delay = <0>;
+ thermal-governor = "low_limits_floor";
+ thermal-sensors = <&tsens0 1>;
+ tracks-low;
+ trips {
+ camera_trip: camera-trip {
+ temperature = <5000>;
+ hysteresis = <5000>;
+ type = "passive";
+ };
+ };
+ cooling-maps {
+ cpu0_vdd_cdev {
+ trip = <&camera_trip>;
+ cooling-device =
+ <&CPU0 (THERMAL_MAX_LIMIT-2)
+ (THERMAL_MAX_LIMIT-2)>;
+ };
+ cpu1_vdd_cdev {
+ trip = <&camera_trip>;
+ cooling-device =
+ <&CPU1 (THERMAL_MAX_LIMIT-2)
+ (THERMAL_MAX_LIMIT-2)>;
+ };
+ cpu2_vdd_cdev {
+ trip = <&camera_trip>;
+ cooling-device =
+ <&CPU2 (THERMAL_MAX_LIMIT-2)
+ (THERMAL_MAX_LIMIT-2)>;
+ };
+ cpu3_vdd_cdev {
+ trip = <&camera_trip>;
+ cooling-device =
+ <&CPU3 (THERMAL_MAX_LIMIT-2)
+ (THERMAL_MAX_LIMIT-2)>;
+ };
+ cx_vdd_cdev {
+ trip = <&camera_trip>;
+ cooling-device = <&pm8909_cx_cdev 0 0>;
+ };
+ };
+ };
+ gpu-lowf {
+ polling-delay-passive = <0>;
+ polling-delay = <0>;
+ thermal-governor = "low_limits_floor";
+ thermal-sensors = <&tsens0 2>;
+ tracks-low;
+ trips {
+ gpu_trip: gpu-trip {
+ temperature = <5000>;
+ hysteresis = <5000>;
+ type = "passive";
+ };
+ };
+ cooling-maps {
+ cpu0_vdd_cdev {
+ trip = <&gpu_trip>;
+ cooling-device =
+ <&CPU0 (THERMAL_MAX_LIMIT-2)
+ (THERMAL_MAX_LIMIT-2)>;
+ };
+ cpu1_vdd_cdev {
+ trip = <&gpu_trip>;
+ cooling-device =
+ <&CPU1 (THERMAL_MAX_LIMIT-2)
+ (THERMAL_MAX_LIMIT-2)>;
+ };
+ cpu2_vdd_cdev {
+ trip = <&gpu_trip>;
+ cooling-device =
+ <&CPU2 (THERMAL_MAX_LIMIT-2)
+ (THERMAL_MAX_LIMIT-2)>;
+ };
+ cpu3_vdd_cdev {
+ trip = <&gpu_trip>;
+ cooling-device =
+ <&CPU3 (THERMAL_MAX_LIMIT-2)
+ (THERMAL_MAX_LIMIT-2)>;
+ };
+ cx_vdd_cdev {
+ trip = <&gpu_trip>;
+ cooling-device = <&pm8909_cx_cdev 0 0>;
+ };
+ };
+ };
+ cpu0-2-lowf {
+ polling-delay-passive = <0>;
+ polling-delay = <0>;
+ thermal-governor = "low_limits_floor";
+ thermal-sensors = <&tsens0 3>;
+ tracks-low;
+ trips {
+ cpu0_2_trip: cpu0-2-trip {
+ temperature = <5000>;
+ hysteresis = <5000>;
+ type = "passive";
+ };
+ };
+ cooling-maps {
+ cpu0_vdd_cdev {
+ trip = <&cpu0_2_trip>;
+ cooling-device =
+ <&CPU0 (THERMAL_MAX_LIMIT-2)
+ (THERMAL_MAX_LIMIT-2)>;
+ };
+ cpu1_vdd_cdev {
+ trip = <&cpu0_2_trip>;
+ cooling-device =
+ <&CPU1 (THERMAL_MAX_LIMIT-2)
+ (THERMAL_MAX_LIMIT-2)>;
+ };
+ cpu2_vdd_cdev {
+ trip = <&cpu0_2_trip>;
+ cooling-device =
+ <&CPU2 (THERMAL_MAX_LIMIT-2)
+ (THERMAL_MAX_LIMIT-2)>;
+ };
+ cpu3_vdd_cdev {
+ trip = <&cpu0_2_trip>;
+ cooling-device =
+ <&CPU3 (THERMAL_MAX_LIMIT-2)
+ (THERMAL_MAX_LIMIT-2)>;
+ };
+ cx_vdd_cdev {
+ trip = <&cpu0_2_trip>;
+ cooling-device = <&pm8909_cx_cdev 0 0>;
+ };
+ };
+ };
+ cpu1-3-lowf {
+ polling-delay-passive = <0>;
+ polling-delay = <0>;
+ thermal-governor = "low_limits_floor";
+ thermal-sensors = <&tsens0 4>;
+ tracks-low;
+ trips {
+ cpu1_3_trip: cpu1-3-trip {
+ temperature = <5000>;
+ hysteresis = <5000>;
+ type = "passive";
+ };
+ };
+ cooling-maps {
+ cpu0_vdd_cdev {
+ trip = <&cpu1_3_trip>;
+ cooling-device =
+ <&CPU0 (THERMAL_MAX_LIMIT-2)
+ (THERMAL_MAX_LIMIT-2)>;
+ };
+ cpu1_vdd_cdev {
+ trip = <&cpu1_3_trip>;
+ cooling-device =
+ <&CPU1 (THERMAL_MAX_LIMIT-2)
+ (THERMAL_MAX_LIMIT-2)>;
+ };
+ cpu2_vdd_cdev {
+ trip = <&cpu1_3_trip>;
+ cooling-device =
+ <&CPU2 (THERMAL_MAX_LIMIT-2)
+ (THERMAL_MAX_LIMIT-2)>;
+ };
+ cpu3_vdd_cdev {
+ trip = <&cpu1_3_trip>;
+ cooling-device =
+ <&CPU3 (THERMAL_MAX_LIMIT-2)
+ (THERMAL_MAX_LIMIT-2)>;
+ };
+ cx_vdd_cdev {
+ trip = <&cpu1_3_trip>;
+ cooling-device = <&pm8909_cx_cdev 0 0>;
+ };
+ };
+ };
+};
diff --git a/arch/arm64/boot/dts/qcom/msm8909.dtsi b/arch/arm64/boot/dts/qcom/msm8909.dtsi
index a72fdbf..c48756c 100644
--- a/arch/arm64/boot/dts/qcom/msm8909.dtsi
+++ b/arch/arm64/boot/dts/qcom/msm8909.dtsi
@@ -77,7 +77,7 @@
efficiency = <1024>;
sched-energy-costs = <&CPU_COST_0 &CLUSTER_COST_0>;
qcom,sleep-status = <&cpu0_slp_sts>;
- qcom,limits-info = <&mitigation_profile0>;
+ #cooling-cells = <2>;
};
CPU1: cpu@1 {
@@ -87,7 +87,7 @@
efficiency = <1024>;
sched-energy-costs = <&CPU_COST_0 &CLUSTER_COST_0>;
qcom,sleep-status = <&cpu1_slp_sts>;
- qcom,limits-info = <&mitigation_profile2>;
+ #cooling-cells = <2>;
};
CPU2: cpu@2 {
@@ -97,7 +97,7 @@
efficiency = <1024>;
sched-energy-costs = <&CPU_COST_0 &CLUSTER_COST_0>;
qcom,sleep-status = <&cpu2_slp_sts>;
- qcom,limits-info = <&mitigation_profile1>;
+ #cooling-cells = <2>;
};
CPU3: cpu@3 {
@@ -107,7 +107,7 @@
efficiency = <1024>;
sched-energy-costs = <&CPU_COST_0 &CLUSTER_COST_0>;
qcom,sleep-status = <&cpu3_slp_sts>;
- qcom,limits-info = <&mitigation_profile2>;
+ #cooling-cells = <2>;
};
};
@@ -357,6 +357,7 @@
reg = <0x1800000 0x80000>,
<0xb016000 0x00040>;
reg-names = "cc_base", "apcs_base";
+ qcom,gfx3d_clk_src-opp-store-vcorner = <&msm_gpu>;
vdd_dig-supply = <&pm8909_s1_corner>;
vdd_sr2_dig-supply = <&pm8909_s1_corner_ao>;
vdd_sr2_pll-supply = <&pm8909_l7_ao>;
@@ -559,77 +560,16 @@
};
- qcom,sensor-information {
- compatible = "qcom,sensor-information";
- sensor_information0: qcom,sensor-information-0 {
- qcom,sensor-type = "tsens";
- qcom,sensor-name = "tsens_tz_sensor0";
- qcom,alias-name = "pop_mem";
- };
-
- sensor_information1: qcom,sensor-information-1 {
- qcom,sensor-type = "tsens";
- qcom,sensor-name = "tsens_tz_sensor1";
- };
-
- sensor_information2: qcom,sensor-information-2 {
- qcom,sensor-type = "tsens";
- qcom,sensor-name = "tsens_tz_sensor2";
- };
-
- sensor_information3: qcom,sensor-information-3 {
- qcom,sensor-type = "tsens";
- qcom,sensor-name = "tsens_tz_sensor3";
- };
-
- sensor_information4: qcom,sensor-information-4 {
- qcom,sensor-type = "tsens";
- qcom,sensor-name = "tsens_tz_sensor4";
- };
-
- sensor_information5: qcom,sensor-information-5 {
- qcom,sensor-type = "adc";
- qcom,sensor-name = "pa_therm0";
- };
-
- sensor_information6: qcom,sensor-information-6 {
- qcom,sensor-type = "adc";
- qcom,sensor-name = "case_therm";
- };
-
- sensor_information7: qcom,sensor-information-7 {
- qcom,sensor-type = "alarm";
- qcom,sensor-name = "pm8909_tz";
- qcom,scaling-factor = <1000>;
- };
-
- sensor_information8: qcom,sensor-information-8 {
- qcom,sensor-type = "adc";
- qcom,sensor-name = "xo_therm";
- };
-
- sensor_information9: qcom,sensor-information-9 {
- qcom,sensor-type = "adc";
- qcom,sensor-name = "xo_therm_buf";
- };
- };
-
- mitigation_profile0: qcom,limit_info-0 {
- qcom,temperature-sensor = <&sensor_information3>;
- qcom,boot-frequency-mitigate;
- qcom,emergency-frequency-mitigate;
- };
-
- mitigation_profile1: qcom,limit_info-1 {
- qcom,temperature-sensor = <&sensor_information3>;
- qcom,boot-frequency-mitigate;
- qcom,hotplug-mitigation-enable;
- };
-
- mitigation_profile2: qcom,limit_info-2 {
- qcom,temperature-sensor = <&sensor_information4>;
- qcom,boot-frequency-mitigate;
- qcom,hotplug-mitigation-enable;
+ tsens0: tsens@4a8000 {
+ compatible = "qcom,msm8909-tsens";
+ reg = <0x4a8000 0x1000>,
+ <0x4a9000 0x1000>,
+ <0x5c000 0x1000>;
+ reg-names = "tsens_srot_physical",
+ "tsens_tm_physical", "tsens_eeprom_physical";
+ interrupts = <0 184 0>;
+ interrupt-names = "tsens-upper-lower";
+ #thermal-sensor-cells = <1>;
};
qcom,ipc-spinlock@1905000 {
@@ -1412,7 +1352,7 @@
clocks = <&clock_gcc clk_gcc_blsp1_ahb_clk>,
<&clock_gcc clk_gcc_blsp1_qup1_i2c_apps_clk>;
clock-names = "iface_clk", "core_clk";
- qcom,clk-freq-out = <100000>;
+ qcom,clk-freq-out = <400000>;
qcom,clk-freq-in = <19200000>;
pinctrl-names = "i2c_active", "i2c_sleep";
pinctrl-0 = <&i2c_1_active>;
@@ -2003,3 +1943,4 @@
clocks = <&clock_gcc clk_gcc_oxili_gfx3d_clk>;
status = "okay";
};
+#include "msm8909-thermal.dtsi"
diff --git a/arch/arm64/boot/dts/qcom/msm8909w-bg-wtp-v2.dts b/arch/arm64/boot/dts/qcom/msm8909w-bg-wtp-v2.dts
index 3a42017..255c146 100644
--- a/arch/arm64/boot/dts/qcom/msm8909w-bg-wtp-v2.dts
+++ b/arch/arm64/boot/dts/qcom/msm8909w-bg-wtp-v2.dts
@@ -54,6 +54,8 @@
synaptics,power-delay-ms = <200>;
synaptics,reset-delay-ms = <200>;
synaptics,max-y-for-2d = <389>;
+ synaptics,bus-lpm-cur-uA = <450>;
+ synaptics,do-not-disable-regulators;
synaptics,wakeup-gestures-en;
synaptics,resume-in-workqueue;
synaptics,x-flip;
diff --git a/arch/arm64/boot/dts/qcom/msm8909w-pm660-regulator.dtsi b/arch/arm64/boot/dts/qcom/msm8909w-pm660-regulator.dtsi
index 512b0fb..ecf28c5 100644
--- a/arch/arm64/boot/dts/qcom/msm8909w-pm660-regulator.dtsi
+++ b/arch/arm64/boot/dts/qcom/msm8909w-pm660-regulator.dtsi
@@ -52,6 +52,13 @@
qcom,init-voltage = <1>;
qcom,use-voltage-corner;
};
+
+ pm660_cx_cdev: regulator-cx-cdev {
+ compatible = "qcom,regulator-cooling-device";
+ regulator-cdev-supply = <&pm660_s2_floor_corner>;
+ regulator-levels = <5 1>;
+ #cooling-cells = <2>;
+ };
};
/* MX supply */
diff --git a/arch/arm64/boot/dts/qcom/msm8909w.dtsi b/arch/arm64/boot/dts/qcom/msm8909w.dtsi
index c2e28d1..7229564 100644
--- a/arch/arm64/boot/dts/qcom/msm8909w.dtsi
+++ b/arch/arm64/boot/dts/qcom/msm8909w.dtsi
@@ -105,3 +105,127 @@
qcom,platform-reset-gpio = <&msm_gpio 25 0>;
qcom,platform-bklight-en-gpio = <&msm_gpio 37 0>;
};
+
+&thermal_zones {
+ gpu-step {
+ trips {
+ gpu-step-trip {
+ temperature = <70000>;
+ };
+ };
+ };
+ cpu0-2-step {
+ trips {
+ cpu0-2-step-trip {
+ temperature = <60000>;
+ };
+ };
+ };
+ cpu1-3-step {
+ trips {
+ cpu1-3-step-trip {
+ temperature = <60000>;
+ };
+ };
+ };
+
+ case-therm-step {
+ polling-delay-passive = <5000>;
+ polling-delay = <0>;
+ thermal-sensors = <&pm660_adc_tm 0x51>;
+ thermal-governor = "step_wise";
+ trips {
+ cpu_freq_trip: cpu-freq-trip {
+ temperature = <40000>;
+ hysteresis = <0>;
+ type = "passive";
+ };
+ modem_mon_trip0: modem-mon-trip0 {
+ temperature = <47000>;
+ hysteresis = <2000>;
+ type = "passive";
+ };
+ modem_mon_trip1: modem-mon-trip1 {
+ temperature = <55000>;
+ hysteresis = <2000>;
+ type = "passive";
+ };
+ cpu1_hotplug_trip: cpu1-hotplug-trip {
+ temperature = <49000>;
+ hysteresis = <3000>;
+ type = "passive";
+ };
+ };
+ cooling-maps {
+ cpu0_cdev {
+ trip = <&cpu_freq_trip>;
+ cooling-device =
+ <&CPU0 THERMAL_NO_LIMIT 2>;
+ };
+ cpu1_cdev {
+ trip = <&cpu_freq_trip>;
+ cooling-device =
+ <&CPU1 THERMAL_NO_LIMIT 2>;
+ };
+ cpu2_cdev {
+ trip = <&cpu_freq_trip>;
+ cooling-device =
+ <&CPU2 THERMAL_NO_LIMIT 2>;
+ };
+ cpu3_cdev {
+ trip = <&cpu_freq_trip>;
+ cooling-device =
+ <&CPU3 THERMAL_NO_LIMIT 2>;
+ };
+ modem_lvl1 {
+ trip = <&modem_mon_trip0>;
+ cooling-device = <&modem_pa 2 2>;
+ };
+ modem_lvl2 {
+ trip = <&modem_mon_trip1>;
+ cooling-device = <&modem_pa 3 3>;
+ };
+ hotplug_cpu1_cdev {
+ trip = <&cpu1_hotplug_trip>;
+ cooling-device =
+ <&CPU1 THERMAL_MAX_LIMIT
+ THERMAL_MAX_LIMIT>;
+ };
+ };
+ };
+ mdm-lowf {
+ cooling-maps {
+ cx_vdd_cdev {
+ cooling-device = <&pm660_cx_cdev 0 0>;
+ };
+ };
+ };
+ camera-lowf {
+ cooling-maps {
+ cx_vdd_cdev {
+ cooling-device = <&pm660_cx_cdev 0 0>;
+ };
+ };
+ };
+ gpu-lowf {
+ cooling-maps {
+ cx_vdd_cdev {
+ cooling-device = <&pm660_cx_cdev 0 0>;
+ };
+ };
+ };
+ cpu0-2-lowf {
+ cooling-maps {
+ cx_vdd_cdev {
+ cooling-device = <&pm660_cx_cdev 0 0>;
+ };
+ };
+ };
+ cpu1-3-lowf {
+ cooling-maps {
+ cx_vdd_cdev {
+ cooling-device = <&pm660_cx_cdev 0 0>;
+ };
+ };
+ };
+};
diff --git a/arch/arm64/boot/dts/qcom/msm8916-regulator.dtsi b/arch/arm64/boot/dts/qcom/msm8916-regulator.dtsi
index 0313ebd..36a67af 100644
--- a/arch/arm64/boot/dts/qcom/msm8916-regulator.dtsi
+++ b/arch/arm64/boot/dts/qcom/msm8916-regulator.dtsi
@@ -141,6 +141,12 @@
qcom,use-voltage-floor-corner;
qcom,always-send-voltage;
};
+ pm8916_cx_cdev: regulator-cx-cdev {
+ compatible = "qcom,regulator-cooling-device";
+ regulator-cdev-supply = <&pm8916_s1_floor_corner>;
+ regulator-levels = <5 1>;
+ #cooling-cells = <2>;
+ };
};
rpm-regulator-smpa3 {
diff --git a/arch/arm64/boot/dts/qcom/msm8917-camera-pinctrl.dtsi b/arch/arm64/boot/dts/qcom/msm8917-camera-pinctrl.dtsi
new file mode 100644
index 0000000..33cc8ae
--- /dev/null
+++ b/arch/arm64/boot/dts/qcom/msm8917-camera-pinctrl.dtsi
@@ -0,0 +1,277 @@
+/*
+ * Copyright (c) 2015, 2018, The Linux Foundation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ */
+
+cci {
+ cci0_active: cci0_active {
+ /* cci0 active state */
+ mux {
+ /* CLK, DATA */
+ pins = "gpio29", "gpio30";
+ function = "cci_i2c";
+ };
+
+ config {
+ pins = "gpio29", "gpio30";
+ drive-strength = <2>; /* 2 MA */
+ bias-disable; /* No PULL */
+ };
+ };
+
+ cci0_suspend: cci0_suspend {
+ /* cci0 suspended state */
+ mux {
+ /* CLK, DATA */
+ pins = "gpio29", "gpio30";
+ function = "cci_i2c";
+ };
+
+ config {
+ pins = "gpio29", "gpio30";
+ drive-strength = <2>; /* 2 MA */
+ bias-disable; /* No PULL */
+ };
+ };
+
+ cci1_active: cci1_active {
+ /* cci1 active state */
+ mux {
+ /* CLK, DATA */
+ pins = "gpio31", "gpio32";
+ function = "cci_i2c";
+ };
+
+ config {
+ pins = "gpio31", "gpio32";
+ drive-strength = <2>; /* 2 MA */
+ bias-disable; /* No PULL */
+ };
+ };
+
+ cci1_suspend: cci1_suspend {
+ /* cci1 suspended state */
+ mux {
+ /* CLK, DATA */
+ pins = "gpio31", "gpio32";
+ function = "cci_i2c";
+ };
+
+ config {
+ pins = "gpio31", "gpio32";
+ drive-strength = <2>; /* 2 MA */
+ bias-disable; /* No PULL */
+ };
+ };
+};
+
+/*sensors */
+cam_sensor_mclk0_default: cam_sensor_mclk0_default {
+ /* MCLK0 */
+ mux {
+ /* CLK, DATA */
+ pins = "gpio26";
+ function = "cam_mclk";
+ };
+
+ config {
+ pins = "gpio26";
+ bias-disable; /* No PULL */
+ drive-strength = <2>; /* 2 MA */
+ };
+};
+
+cam_sensor_mclk0_sleep: cam_sensor_mclk0_sleep {
+ /* MCLK0 */
+ mux {
+ /* CLK, DATA */
+ pins = "gpio26";
+ function = "cam_mclk";
+ };
+
+ config {
+ pins = "gpio26";
+ bias-pull-down; /* PULL DOWN */
+ drive-strength = <2>; /* 2 MA */
+ };
+};
+
+cam_sensor_rear_default: cam_sensor_rear_default {
+ /* RESET, STANDBY */
+ mux {
+ pins = "gpio36", "gpio35";
+ function = "gpio";
+ };
+
+ config {
+ pins = "gpio36","gpio35";
+ bias-disable; /* No PULL */
+ drive-strength = <2>; /* 2 MA */
+ };
+};
+
+cam_sensor_rear_sleep: cam_sensor_rear_sleep {
+ /* RESET, STANDBY */
+ mux {
+ pins = "gpio36","gpio35";
+ function = "gpio";
+ };
+
+ config {
+ pins = "gpio36","gpio35";
+ bias-disable; /* No PULL */
+ drive-strength = <2>; /* 2 MA */
+ };
+};
+
+cam_sensor_rear_vdig: cam_sensor_rear_vdig {
+ /* VDIG */
+ mux {
+ pins = "gpio62";
+ function = "gpio";
+ };
+
+ config {
+ pins = "gpio62";
+ bias-disable; /* No PULL */
+ drive-strength = <2>; /* 2 MA */
+ };
+};
+
+cam_sensor_rear_vdig_sleep: cam_sensor_rear_vdig_sleep {
+ /* VDIG */
+ mux {
+ pins = "gpio62";
+ function = "gpio";
+ };
+
+ config {
+ pins = "gpio62";
+ bias-disable; /* No PULL */
+ drive-strength = <2>; /* 2 MA */
+ };
+};
+
+cam_sensor_mclk1_default: cam_sensor_mclk1_default {
+ /* MCLK1 */
+ mux {
+ /* CLK, DATA */
+ pins = "gpio27";
+ function = "cam_mclk";
+ };
+
+ config {
+ pins = "gpio27";
+ bias-disable; /* No PULL */
+ drive-strength = <2>; /* 2 MA */
+ };
+};
+
+cam_sensor_mclk1_sleep: cam_sensor_mclk1_sleep {
+ /* MCLK1 */
+ mux {
+ /* CLK, DATA */
+ pins = "gpio27";
+ function = "cam_mclk";
+ };
+
+ config {
+ pins = "gpio27";
+ bias-pull-down; /* PULL DOWN */
+ drive-strength = <2>; /* 2 MA */
+ };
+};
+
+cam_sensor_front_default: cam_sensor_front_default {
+ /* RESET, STANDBY */
+ mux {
+ pins = "gpio38","gpio50";
+ function = "gpio";
+ };
+
+ config {
+ pins = "gpio38","gpio50";
+ bias-disable; /* No PULL */
+ drive-strength = <2>; /* 2 MA */
+ };
+};
+
+cam_sensor_front_sleep: cam_sensor_front_sleep {
+ /* RESET, STANDBY */
+ mux {
+ pins = "gpio38","gpio50";
+ function = "gpio";
+ };
+
+ config {
+ pins = "gpio38","gpio50";
+ bias-disable; /* No PULL */
+ drive-strength = <2>; /* 2 MA */
+ };
+};
+
+cam_sensor_mclk2_default: cam_sensor_mclk2_default {
+ /* MCLK2 */
+ mux {
+ /* CLK, DATA */
+ pins = "gpio28";
+ function = "cam_mclk";
+ };
+
+ config {
+ pins = "gpio28";
+ bias-disable; /* No PULL */
+ drive-strength = <2>; /* 2 MA */
+ };
+};
+
+cam_sensor_mclk2_sleep: cam_sensor_mclk2_sleep {
+ /* MCLK2 */
+ mux {
+ /* CLK, DATA */
+ pins = "gpio28";
+ function = "cam_mclk";
+ };
+
+ config {
+ pins = "gpio28";
+ bias-pull-down; /* PULL DOWN */
+ drive-strength = <2>; /* 2 MA */
+ };
+};
+
+cam_sensor_front1_default: cam_sensor_front1_default {
+ /* RESET, STANDBY */
+ mux {
+ pins = "gpio40", "gpio39";
+ function = "gpio";
+ };
+
+ config {
+ pins = "gpio40", "gpio39";
+ bias-disable; /* No PULL */
+ drive-strength = <2>; /* 2 MA */
+ };
+};
+
+cam_sensor_front1_sleep: cam_sensor_front1_sleep {
+ /* RESET, STANDBY */
+ mux {
+ pins = "gpio40", "gpio39";
+ function = "gpio";
+ };
+
+ config {
+ pins = "gpio40", "gpio39";
+ bias-disable; /* No PULL */
+ drive-strength = <2>; /* 2 MA */
+ };
+};
diff --git a/arch/arm64/boot/dts/qcom/msm8917-camera-sensor-qrd.dtsi b/arch/arm64/boot/dts/qcom/msm8917-camera-sensor-qrd.dtsi
new file mode 100644
index 0000000..dbaccfa
--- /dev/null
+++ b/arch/arm64/boot/dts/qcom/msm8917-camera-sensor-qrd.dtsi
@@ -0,0 +1,181 @@
+/*
+ * Copyright (c) 2015-2016, 2018, The Linux Foundation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ */
+
+&cci {
+ actuator0: qcom,actuator@0 {
+ cell-index = <0>;
+ reg = <0x0>;
+ compatible = "qcom,actuator";
+ qcom,cci-master = <0>;
+ cam_vaf-supply = <&pm8937_l17>;
+ qcom,cam-vreg-name = "cam_vaf";
+ qcom,cam-vreg-min-voltage = <2850000>;
+ qcom,cam-vreg-max-voltage = <2850000>;
+ qcom,cam-vreg-op-mode = <80000>;
+ };
+
+ eeprom0: qcom,eeprom@0 {
+ cell-index = <0>;
+ compatible = "qcom,eeprom";
+ qcom,cci-master = <0>;
+ reg = <0x0>;
+ cam_vdig-supply = <&pm8937_l23>;
+ cam_vana-supply = <&pm8937_l22>;
+ cam_vio-supply = <&pm8937_l6>;
+ cam_vaf-supply = <&pm8937_l17>;
+ qcom,cam-vreg-name = "cam_vdig", "cam_vio", "cam_vana",
+ "cam_vaf";
+ qcom,cam-vreg-min-voltage = <1200000 0 2800000 2850000>;
+ qcom,cam-vreg-max-voltage = <1200000 0 2800000 2850000>;
+ qcom,cam-vreg-op-mode = <200000 0 80000 100000>;
+ pinctrl-names = "cam_default", "cam_suspend";
+ pinctrl-0 = <&cam_sensor_mclk0_default
+ &cam_sensor_rear_default>;
+ pinctrl-1 = <&cam_sensor_mclk0_sleep &cam_sensor_rear_sleep>;
+ gpios = <&tlmm 26 0>,
+ <&tlmm 36 0>,
+ <&tlmm 35 0>;
+ qcom,gpio-reset = <1>;
+ qcom,gpio-standby = <2>;
+ qcom,gpio-req-tbl-num = <0 1 2>;
+ qcom,gpio-req-tbl-flags = <1 0 0>;
+ qcom,gpio-req-tbl-label = "CAMIF_MCLK0",
+ "CAM_RESET0",
+ "CAM_STANDBY0";
+ status = "ok";
+ clocks = <&clock_gcc clk_mclk0_clk_src>,
+ <&clock_gcc clk_gcc_camss_mclk0_clk>;
+ clock-names = "cam_src_clk", "cam_clk";
+ qcom,clock-rates = <19200000 0>;
+ };
+
+ eeprom2: qcom,eeprom@2 {
+ cell-index = <2>;
+ compatible = "qcom,eeprom";
+ reg = <0x02>;
+ cam_vdig-supply = <&pm8937_l23>;
+ cam_vana-supply = <&pm8937_l22>;
+ cam_vio-supply = <&pm8937_l6>;
+ cam_vaf-supply = <&pm8937_l17>;
+ qcom,cam-vreg-name = "cam_vdig", "cam_vio", "cam_vana",
+ "cam_vaf";
+ qcom,cam-vreg-min-voltage = <1200000 0 2800000 2850000>;
+ qcom,cam-vreg-max-voltage = <1200000 0 2800000 2850000>;
+ qcom,cam-vreg-op-mode = <105000 0 80000 100000>;
+ qcom,gpio-no-mux = <0>;
+ pinctrl-names = "cam_default", "cam_suspend";
+ pinctrl-0 = <&cam_sensor_mclk2_default
+ &cam_sensor_front1_default>;
+ pinctrl-1 = <&cam_sensor_mclk2_sleep
+ &cam_sensor_front1_sleep>;
+ gpios = <&tlmm 28 0>,
+ <&tlmm 40 0>,
+ <&tlmm 39 0>;
+ qcom,gpio-reset = <1>;
+ qcom,gpio-standby = <2>;
+ qcom,gpio-req-tbl-num = <0 1 2>;
+ qcom,gpio-req-tbl-flags = <1 0 0>;
+ qcom,gpio-req-tbl-label = "CAMIF_MCLK2",
+ "CAM_RESET2",
+ "CAM_STANDBY2";
+ qcom,cci-master = <0>;
+ status = "ok";
+ clocks = <&clock_gcc clk_mclk2_clk_src>,
+ <&clock_gcc clk_gcc_camss_mclk2_clk>;
+ clock-names = "cam_src_clk", "cam_clk";
+ qcom,clock-rates = <19200000 0>;
+ };
+
+ qcom,camera@0 {
+ cell-index = <0>;
+ compatible = "qcom,camera";
+ reg = <0x0>;
+ qcom,csiphy-sd-index = <0>;
+ qcom,csid-sd-index = <0>;
+ qcom,mount-angle = <90>;
+ qcom,actuator-src = <&actuator0>;
+ qcom,led-flash-src = <&led_flash0>;
+ qcom,eeprom-src = <&eeprom0>;
+ cam_vdig-supply = <&pm8937_l23>;
+ cam_vana-supply = <&pm8937_l22>;
+ cam_vio-supply = <&pm8937_l6>;
+ cam_vaf-supply = <&pm8937_l17>;
+ qcom,cam-vreg-name = "cam_vdig", "cam_vio", "cam_vana",
+ "cam_vaf";
+ qcom,cam-vreg-min-voltage = <1200000 0 2800000 2850000>;
+ qcom,cam-vreg-max-voltage = <1200000 0 2800000 2850000>;
+ qcom,cam-vreg-op-mode = <200000 0 80000 100000>;
+ pinctrl-names = "cam_default", "cam_suspend";
+ pinctrl-0 = <&cam_sensor_mclk0_default
+ &cam_sensor_rear_default>;
+ pinctrl-1 = <&cam_sensor_mclk0_sleep
+ &cam_sensor_rear_sleep>;
+ gpios = <&tlmm 26 0>,
+ <&tlmm 36 0>,
+ <&tlmm 35 0>;
+ qcom,gpio-reset = <1>;
+ qcom,gpio-standby = <2>;
+ qcom,gpio-req-tbl-num = <0 1 2>;
+ qcom,gpio-req-tbl-flags = <1 0 0>;
+ qcom,gpio-req-tbl-label = "CAMIF_MCLK0",
+ "CAM_RESET0",
+ "CAM_STANDBY0";
+ qcom,sensor-position = <0>;
+ qcom,sensor-mode = <0>;
+ qcom,cci-master = <0>;
+ clocks = <&clock_gcc clk_mclk0_clk_src>,
+ <&clock_gcc clk_gcc_camss_mclk0_clk>;
+ clock-names = "cam_src_clk", "cam_clk";
+ qcom,clock-rates = <24000000 0>;
+ };
+
+ qcom,camera@2 {
+ cell-index = <2>;
+ compatible = "qcom,camera";
+ reg = <0x02>;
+ qcom,csiphy-sd-index = <1>;
+ qcom,csid-sd-index = <1>;
+ qcom,eeprom-src = <&eeprom2>;
+ qcom,mount-angle = <270>;
+ cam_vdig-supply = <&pm8937_l23>;
+ cam_vana-supply = <&pm8937_l22>;
+ cam_vio-supply = <&pm8937_l6>;
+ qcom,cam-vreg-name = "cam_vdig", "cam_vio", "cam_vana";
+ qcom,cam-vreg-min-voltage = <1200000 0 2800000>;
+ qcom,cam-vreg-max-voltage = <1200000 0 2800000>;
+ qcom,cam-vreg-op-mode = <105000 0 80000>;
+ qcom,gpio-no-mux = <0>;
+ pinctrl-names = "cam_default", "cam_suspend";
+ pinctrl-0 = <&cam_sensor_mclk2_default
+ &cam_sensor_front1_default>;
+ pinctrl-1 = <&cam_sensor_mclk2_sleep
+ &cam_sensor_front1_sleep>;
+ gpios = <&tlmm 28 0>,
+ <&tlmm 40 0>,
+ <&tlmm 39 0>;
+ qcom,gpio-reset = <1>;
+ qcom,gpio-standby = <2>;
+ qcom,gpio-req-tbl-num = <0 1 2>;
+ qcom,gpio-req-tbl-flags = <1 0 0>;
+ qcom,gpio-req-tbl-label = "CAMIF_MCLK2",
+ "CAM_RESET2",
+ "CAM_STANDBY2";
+ qcom,sensor-position = <1>;
+ qcom,sensor-mode = <0>;
+ qcom,cci-master = <0>;
+ clocks = <&clock_gcc clk_mclk2_clk_src>,
+ <&clock_gcc clk_gcc_camss_mclk2_clk>;
+ clock-names = "cam_src_clk", "cam_clk";
+ qcom,clock-rates = <24000000 0>;
+ };
+};
diff --git a/arch/arm64/boot/dts/qcom/msm8917-camera.dtsi b/arch/arm64/boot/dts/qcom/msm8917-camera.dtsi
new file mode 100644
index 0000000..4991ff7
--- /dev/null
+++ b/arch/arm64/boot/dts/qcom/msm8917-camera.dtsi
@@ -0,0 +1,533 @@
+/*
+ * Copyright (c) 2015-2018, The Linux Foundation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ */
+
+&soc {
+ qcom,msm-cam@1b00000 {
+ compatible = "qcom,msm-cam";
+ reg = <0x1b00000 0x40000>;
+ reg-names = "msm-cam";
+ status = "ok";
+ bus-vectors = "suspend", "svs", "nominal", "turbo";
+ qcom,bus-votes = <0 160000000 320000000 320000000>;
+ };
+
+ qcom,csiphy@1b34000 {
+ status = "ok";
+ cell-index = <0>;
+ compatible = "qcom,csiphy-v3.4.2", "qcom,csiphy";
+ reg = <0x1b34000 0x1000>,
+ <0x1b00030 0x4>;
+ reg-names = "csiphy", "csiphy_clk_mux";
+ interrupts = <0 78 0>;
+ interrupt-names = "csiphy";
+ clocks = <&clock_gcc clk_gcc_camss_top_ahb_clk>,
+ <&clock_gcc clk_gcc_camss_ispif_ahb_clk>,
+ <&clock_gcc clk_csi0phytimer_clk_src>,
+ <&clock_gcc clk_gcc_camss_csi0phytimer_clk>,
+ <&clock_gcc clk_camss_top_ahb_clk_src>,
+ <&clock_gcc clk_gcc_camss_csi0phy_clk>,
+ <&clock_gcc clk_gcc_camss_ahb_clk>;
+ clock-names = "camss_top_ahb_clk", "ispif_ahb_clk",
+ "csiphy_timer_src_clk", "csiphy_timer_clk",
+ "camss_ahb_src", "csi_phy_clk",
+ "camss_ahb_clk";
+ qcom,clock-rates = <0 61540000 200000000 0 0 0 0>;
+ };
+
+ qcom,csiphy@1b35000 {
+ status = "ok";
+ cell-index = <1>;
+ compatible = "qcom,csiphy-v3.4.2", "qcom,csiphy";
+ reg = <0x1b35000 0x1000>,
+ <0x1b00038 0x4>;
+ reg-names = "csiphy", "csiphy_clk_mux";
+ interrupts = <0 79 0>;
+ interrupt-names = "csiphy";
+ clocks = <&clock_gcc clk_gcc_camss_top_ahb_clk>,
+ <&clock_gcc clk_gcc_camss_ispif_ahb_clk>,
+ <&clock_gcc clk_csi1phytimer_clk_src>,
+ <&clock_gcc clk_gcc_camss_csi1phytimer_clk>,
+ <&clock_gcc clk_camss_top_ahb_clk_src>,
+ <&clock_gcc clk_gcc_camss_csi1phy_clk>,
+ <&clock_gcc clk_gcc_camss_ahb_clk>;
+ clock-names = "camss_top_ahb_clk", "ispif_ahb_clk",
+ "csiphy_timer_src_clk", "csiphy_timer_clk",
+ "camss_ahb_src", "csi_phy_clk",
+ "camss_ahb_clk";
+ qcom,clock-rates = <0 61540000 200000000 0 0 0 0>;
+ };
+
+ qcom,csid@1b30000 {
+ status = "ok";
+ cell-index = <0>;
+ compatible = "qcom,csid-v3.4.3", "qcom,csid";
+ reg = <0x1b30000 0x400>;
+ reg-names = "csid";
+ interrupts = <0 51 0>;
+ interrupt-names = "csid";
+ qcom,csi-vdd-voltage = <1200000>;
+ qcom,mipi-csi-vdd-supply = <&pm8937_l2>;
+ clocks = <&clock_gcc clk_gcc_camss_top_ahb_clk>,
+ <&clock_gcc clk_gcc_camss_ispif_ahb_clk>,
+ <&clock_gcc clk_gcc_camss_csi0_ahb_clk>,
+ <&clock_gcc clk_csi0_clk_src>,
+ <&clock_gcc clk_gcc_camss_csi0_clk>,
+ <&clock_gcc clk_gcc_camss_csi0pix_clk>,
+ <&clock_gcc clk_gcc_camss_csi0rdi_clk>,
+ <&clock_gcc clk_gcc_camss_ahb_clk>;
+ clock-names = "camss_top_ahb_clk",
+ "ispif_ahb_clk", "csi_ahb_clk", "csi_src_clk",
+ "csi_clk", "csi_pix_clk",
+ "csi_rdi_clk", "camss_ahb_clk";
+ qcom,clock-rates = <0 61540000 0 200000000 0 0 0 0>;
+ };
+
+ qcom,csid@1b30400 {
+ status = "ok";
+ cell-index = <1>;
+ compatible = "qcom,csid-v3.4.3", "qcom,csid";
+ reg = <0x1b30400 0x400>;
+ reg-names = "csid";
+ interrupts = <0 52 0>;
+ interrupt-names = "csid";
+ qcom,csi-vdd-voltage = <1200000>;
+ qcom,mipi-csi-vdd-supply = <&pm8937_l2>;
+ clocks = <&clock_gcc clk_gcc_camss_top_ahb_clk>,
+ <&clock_gcc clk_gcc_camss_ispif_ahb_clk>,
+ <&clock_gcc clk_gcc_camss_csi1_ahb_clk>,
+ <&clock_gcc clk_csi1_clk_src>,
+ <&clock_gcc clk_gcc_camss_csi1_clk>,
+ <&clock_gcc clk_gcc_camss_csi1pix_clk>,
+ <&clock_gcc clk_gcc_camss_csi1rdi_clk>,
+ <&clock_gcc clk_gcc_camss_ahb_clk>;
+ clock-names = "camss_top_ahb_clk",
+ "ispif_ahb_clk", "csi_ahb_clk", "csi_src_clk",
+ "csi_clk", "csi_pix_clk",
+ "csi_rdi_clk", "camss_ahb_clk";
+ qcom,clock-rates = <0 61540000 0 200000000 0 0 0 0>;
+ };
+
+ qcom,csid@1b30800 {
+ status = "ok";
+ cell-index = <2>;
+ compatible = "qcom,csid-v3.4.3", "qcom,csid";
+ reg = <0x1b30800 0x400>;
+ reg-names = "csid";
+ interrupts = <0 153 0>;
+ interrupt-names = "csid";
+ qcom,csi-vdd-voltage = <1200000>;
+ qcom,mipi-csi-vdd-supply = <&pm8937_l2>;
+ clocks = <&clock_gcc clk_gcc_camss_top_ahb_clk>,
+ <&clock_gcc clk_gcc_camss_ispif_ahb_clk>,
+ <&clock_gcc clk_gcc_camss_csi2_ahb_clk>,
+ <&clock_gcc clk_csi2_clk_src>,
+ <&clock_gcc clk_gcc_camss_csi2_clk>,
+ <&clock_gcc clk_gcc_camss_csi2pix_clk>,
+ <&clock_gcc clk_gcc_camss_csi2rdi_clk>,
+ <&clock_gcc clk_gcc_camss_ahb_clk>;
+ clock-names = "camss_top_ahb_clk",
+ "ispif_ahb_clk", "csi_ahb_clk", "csi_src_clk",
+ "csi_clk", "csi_pix_clk",
+ "csi_rdi_clk", "camss_ahb_clk";
+ qcom,clock-rates = <0 61540000 0 200000000 0 0 0 0>;
+ };
+
+ qcom,ispif@1b31000 {
+ cell-index = <0>;
+ compatible = "qcom,ispif-v3.0", "qcom,ispif";
+ reg = <0x1b31000 0x500>,
+ <0x1b00020 0x10>;
+ reg-names = "ispif", "csi_clk_mux";
+ interrupts = <0 55 0>;
+ interrupt-names = "ispif";
+ qcom,num-isps = <0x2>;
+ vfe0-vdd-supply = <&gdsc_vfe>;
+ vfe1-vdd-supply = <&gdsc_vfe1>;
+ qcom,vdd-names = "vfe0-vdd", "vfe1-vdd";
+ clocks = <&clock_gcc clk_gcc_camss_ispif_ahb_clk>,
+ <&clock_gcc clk_gcc_camss_ahb_clk>,
+ <&clock_gcc clk_gcc_camss_top_ahb_clk>,
+ <&clock_gcc clk_camss_top_ahb_clk_src>,
+ <&clock_gcc clk_csi0_clk_src>,
+ <&clock_gcc clk_gcc_camss_csi0_clk>,
+ <&clock_gcc clk_gcc_camss_csi0rdi_clk>,
+ <&clock_gcc clk_gcc_camss_csi0pix_clk>,
+ <&clock_gcc clk_csi1_clk_src>,
+ <&clock_gcc clk_gcc_camss_csi1_clk>,
+ <&clock_gcc clk_gcc_camss_csi1rdi_clk>,
+ <&clock_gcc clk_gcc_camss_csi1pix_clk>,
+ <&clock_gcc clk_csi2_clk_src>,
+ <&clock_gcc clk_gcc_camss_csi2_clk>,
+ <&clock_gcc clk_gcc_camss_csi2rdi_clk>,
+ <&clock_gcc clk_gcc_camss_csi2pix_clk>,
+ <&clock_gcc clk_vfe0_clk_src>,
+ <&clock_gcc clk_gcc_camss_vfe0_clk>,
+ <&clock_gcc clk_gcc_camss_csi_vfe0_clk>,
+ <&clock_gcc clk_vfe1_clk_src>,
+ <&clock_gcc clk_gcc_camss_vfe1_clk>,
+ <&clock_gcc clk_gcc_camss_csi_vfe1_clk>;
+ clock-names = "ispif_ahb_clk",
+ "camss_ahb_clk", "camss_top_ahb_clk",
+ "camss_ahb_src",
+ "csi0_src_clk", "csi0_clk",
+ "csi0_rdi_clk", "csi0_pix_clk",
+ "csi1_src_clk", "csi1_clk",
+ "csi1_rdi_clk", "csi1_pix_clk",
+ "csi2_src_clk", "csi2_clk",
+ "csi2_rdi_clk", "csi2_pix_clk",
+ "vfe0_clk_src", "camss_vfe_vfe0_clk",
+ "camss_csi_vfe0_clk", "vfe1_clk_src",
+ "camss_vfe_vfe1_clk", "camss_csi_vfe1_clk";
+ qcom,clock-rates = <61540000 0 0 0
+ 200000000 0 0 0
+ 200000000 0 0 0
+ 200000000 0 0 0
+ 0 0 0
+ 0 0 0>;
+ qcom,clock-cntl-support;
+ qcom,clock-control = "SET_RATE","NO_SET_RATE", "NO_SET_RATE",
+ "NO_SET_RATE", "SET_RATE", "NO_SET_RATE",
+ "NO_SET_RATE", "NO_SET_RATE", "SET_RATE",
+ "NO_SET_RATE", "NO_SET_RATE", "NO_SET_RATE",
+ "SET_RATE", "NO_SET_RATE", "NO_SET_RATE",
+ "NO_SET_RATE", "INIT_RATE", "NO_SET_RATE",
+ "NO_SET_RATE", "INIT_RATE", "NO_SET_RATE",
+ "NO_SET_RATE";
+ };
+
+ vfe0: qcom,vfe0@1b10000 {
+ cell-index = <0>;
+ compatible = "qcom,vfe40";
+ reg = <0x1b10000 0x1000>,
+ <0x1b40000 0x200>;
+ reg-names = "vfe", "vfe_vbif";
+ interrupts = <0 57 0>;
+ interrupt-names = "vfe";
+ vdd-supply = <&gdsc_vfe>;
+ clocks = <&clock_gcc clk_gcc_camss_top_ahb_clk>,
+ <&clock_gcc clk_gcc_camss_ahb_clk>,
+ <&clock_gcc clk_vfe0_clk_src>,
+ <&clock_gcc clk_gcc_camss_vfe0_clk>,
+ <&clock_gcc clk_gcc_camss_csi_vfe0_clk>,
+ <&clock_gcc clk_gcc_camss_vfe_ahb_clk>,
+ <&clock_gcc clk_gcc_camss_vfe_axi_clk>,
+ <&clock_gcc clk_gcc_camss_ispif_ahb_clk>;
+ clock-names = "camss_top_ahb_clk", "camss_ahb_clk",
+ "vfe_clk_src", "camss_vfe_vfe_clk",
+ "camss_csi_vfe_clk", "iface_clk",
+ "bus_clk", "iface_ahb_clk";
+ qcom,clock-rates = <0 0 266670000 0 0 0 0 0>;
+ qos-entries = <8>;
+ qos-regs = <0x2c4 0x2c8 0x2cc 0x2d0 0x2d4 0x2d8
+ 0x2dc 0x2e0>;
+ qos-settings = <0xaa55aa55
+ 0xaa55aa55 0xaa55aa55
+ 0xaa55aa55 0xaa55aa55
+ 0xaa55aa55 0xaa55aa55
+ 0xaa55aa55>;
+ vbif-entries = <1>;
+ vbif-regs = <0x124>;
+ vbif-settings = <0x3>;
+ ds-entries = <17>;
+ ds-regs = <0x988 0x98c 0x990 0x994 0x998
+ 0x99c 0x9a0 0x9a4 0x9a8 0x9ac 0x9b0
+ 0x9b4 0x9b8 0x9bc 0x9c0 0x9c4 0x9c8>;
+ ds-settings = <0xcccc1111
+ 0xcccc1111 0xcccc1111
+ 0xcccc1111 0xcccc1111
+ 0xcccc1111 0xcccc1111
+ 0xcccc1111 0xcccc1111
+ 0xcccc1111 0xcccc1111
+ 0xcccc1111 0xcccc1111
+ 0xcccc1111 0xcccc1111
+ 0xcccc1111 0x00000110>;
+ max-clk-nominal = <400000000>;
+ max-clk-turbo = <432000000>;
+ };
+
+ vfe1: qcom,vfe1@1b14000 {
+ cell-index = <1>;
+ compatible = "qcom,vfe40";
+ reg = <0x1b14000 0x1000>,
+ <0x1ba0000 0x200>;
+ reg-names = "vfe", "vfe_vbif";
+ interrupts = <0 29 0>;
+ interrupt-names = "vfe";
+ vdd-supply = <&gdsc_vfe1>;
+ clocks = <&clock_gcc clk_gcc_camss_top_ahb_clk>,
+ <&clock_gcc clk_gcc_camss_ahb_clk>,
+ <&clock_gcc clk_vfe1_clk_src>,
+ <&clock_gcc clk_gcc_camss_vfe1_clk>,
+ <&clock_gcc clk_gcc_camss_csi_vfe1_clk>,
+ <&clock_gcc clk_gcc_camss_vfe1_ahb_clk>,
+ <&clock_gcc clk_gcc_camss_vfe1_axi_clk>,
+ <&clock_gcc clk_gcc_camss_ispif_ahb_clk>;
+ clock-names = "camss_top_ahb_clk" , "camss_ahb_clk",
+ "vfe_clk_src", "camss_vfe_vfe_clk",
+ "camss_csi_vfe_clk", "iface_clk",
+ "bus_clk", "iface_ahb_clk";
+ qcom,clock-rates = <0 0 266670000 0 0 0 0 0>;
+ qos-entries = <8>;
+ qos-regs = <0x2c4 0x2c8 0x2cc 0x2d0 0x2d4 0x2d8
+ 0x2dc 0x2e0>;
+ qos-settings = <0xaa55aa55
+ 0xaa55aa55 0xaa55aa55
+ 0xaa55aa55 0xaa55aa55
+ 0xaa55aa55 0xaa55aa55
+ 0xaa55aa55>;
+ vbif-entries = <1>;
+ vbif-regs = <0x124>;
+ vbif-settings = <0x3>;
+ ds-entries = <17>;
+ ds-regs = <0x988 0x98c 0x990 0x994 0x998
+ 0x99c 0x9a0 0x9a4 0x9a8 0x9ac 0x9b0
+ 0x9b4 0x9b8 0x9bc 0x9c0 0x9c4 0x9c8>;
+ ds-settings = <0xcccc1111
+ 0xcccc1111 0xcccc1111
+ 0xcccc1111 0xcccc1111
+ 0xcccc1111 0xcccc1111
+ 0xcccc1111 0xcccc1111
+ 0xcccc1111 0xcccc1111
+ 0xcccc1111 0xcccc1111
+ 0xcccc1111 0xcccc1111
+ 0xcccc1111 0x00000110>;
+ max-clk-nominal = <400000000>;
+ max-clk-turbo = <432000000>;
+ };
+
+ qcom,vfe {
+ compatible = "qcom,vfe";
+ num_child = <2>;
+ };
+
+ qcom,cam_smmu {
+ status = "ok";
+ compatible = "qcom,msm-cam-smmu";
+ msm_cam_smmu_cb1: msm_cam_smmu_cb1 {
+ compatible = "qcom,msm-cam-smmu-cb";
+ iommus = <&apps_iommu 0x400 0x00>,
+ <&apps_iommu 0x2400 0x00>;
+ label = "vfe";
+ qcom,scratch-buf-support;
+ };
+
+ msm_cam_smmu_cb2: msm_cam_smmu_cb2 {
+ compatible = "qcom,msm-cam-smmu-cb";
+ label = "vfe_secure";
+ qcom,secure-context;
+ };
+
+ msm_cam_smmu_cb3: msm_cam_smmu_cb3 {
+ compatible = "qcom,msm-cam-smmu-cb";
+ iommus = <&apps_iommu 0x1c00 0x00>;
+ label = "cpp";
+ };
+
+ msm_cam_smmu_cb4: msm_cam_smmu_cb4 {
+ compatible = "qcom,msm-cam-smmu-cb";
+ iommus = <&apps_iommu 0x1800 0x00>;
+ label = "jpeg_enc0";
+ };
+ };
+
+ qcom,jpeg@1b1c000 {
+ status = "ok";
+ cell-index = <0>;
+ compatible = "qcom,jpeg";
+ reg = <0x1b1c000 0x400>,
+ <0x1b60000 0xc30>;
+ reg-names = "jpeg_hw", "jpeg_vbif";
+ interrupts = <0 59 0>;
+ interrupt-names = "jpeg";
+ vdd-supply = <&gdsc_jpeg>;
+ qcom,vdd-names = "vdd";
+ clock-names = "core_clk", "iface_clk", "bus_clk0",
+ "camss_top_ahb_clk", "camss_ahb_clk";
+ clocks = <&clock_gcc clk_gcc_camss_jpeg0_clk>,
+ <&clock_gcc clk_gcc_camss_jpeg_ahb_clk>,
+ <&clock_gcc clk_gcc_camss_jpeg_axi_clk>,
+ <&clock_gcc clk_gcc_camss_top_ahb_clk>,
+ <&clock_gcc clk_gcc_camss_ahb_clk>;
+ qcom,clock-rates = <266670000 0 0 0 0>;
+ qcom,qos-reg-settings = <0x28 0x0000555e>,
+ <0xc8 0x00005555>;
+ qcom,msm-bus,name = "msm_camera_jpeg0";
+ qcom,msm-bus,num-cases = <2>;
+ qcom,msm-bus,num-paths = <1>;
+ qcom,msm-bus,vectors-KBps = <62 512 0 0>,
+ <62 512 800000 800000>;
+ qcom,vbif-reg-settings = <0xc0 0x10101000>,
+ <0xb0 0x10100010>;
+ };
+
+ qcom,irqrouter@1b00000 {
+ status = "ok";
+ cell-index = <0>;
+ compatible = "qcom,irqrouter";
+ reg = <0x1b00000 0x100>;
+ reg-names = "irqrouter";
+ };
+
+ qcom,cpp@1b04000 {
+ status = "ok";
+ cell-index = <0>;
+ compatible = "qcom,cpp";
+ reg = <0x1b04000 0x100>,
+ <0x1b80000 0x200>,
+ <0x1b18000 0x018>,
+ <0x1858078 0x4>;
+ reg-names = "cpp", "cpp_vbif", "cpp_hw", "camss_cpp";
+ interrupts = <0 49 0>;
+ interrupt-names = "cpp";
+ vdd-supply = <&gdsc_cpp>;
+ qcom,vdd-names = "vdd";
+ clocks = <&clock_gcc clk_gcc_camss_ispif_ahb_clk>,
+ <&clock_gcc clk_cpp_clk_src>,
+ <&clock_gcc clk_gcc_camss_top_ahb_clk>,
+ <&clock_gcc clk_gcc_camss_cpp_ahb_clk>,
+ <&clock_gcc clk_gcc_camss_cpp_axi_clk>,
+ <&clock_gcc clk_gcc_camss_cpp_clk>,
+ <&clock_gcc clk_gcc_camss_micro_ahb_clk>,
+ <&clock_gcc clk_gcc_camss_ahb_clk>;
+ clock-names = "ispif_ahb_clk", "cpp_core_clk",
+ "camss_top_ahb_clk", "camss_vfe_cpp_ahb_clk",
+ "camss_vfe_cpp_axi_clk", "camss_vfe_cpp_clk",
+ "micro_iface_clk", "camss_ahb_clk";
+ qcom,clock-rates = <61540000 180000000 0 0 0 180000000 0 0>;
+ qcom,min-clock-rate = <133000000>;
+ resets = <&clock_gcc GCC_CAMSS_MICRO_BCR>;
+ reset-names = "micro_iface_reset";
+ qcom,bus-master = <1>;
+ qcom,msm-bus,name = "msm_camera_cpp";
+ qcom,msm-bus,num-cases = <2>;
+ qcom,msm-bus,num-paths = <1>;
+ qcom,msm-bus,vectors-KBps =
+ <106 512 0 0>,
+ <106 512 0 0>;
+ qcom,msm-bus-vector-dyn-vote;
+ qcom,micro-reset;
+ qcom,cpp-fw-payload-info {
+ qcom,stripe-base = <156>;
+ qcom,plane-base = <141>;
+ qcom,stripe-size = <27>;
+ qcom,plane-size = <5>;
+ qcom,fe-ptr-off = <5>;
+ qcom,we-ptr-off = <11>;
+ };
+ };
+
+ cci: qcom,cci@1b0c000 {
+ status = "ok";
+ cell-index = <0>;
+ compatible = "qcom,cci";
+ reg = <0x1b0c000 0x4000>;
+ #address-cells = <1>;
+ #size-cells = <0>;
+ reg-names = "cci";
+ interrupts = <0 50 0>;
+ interrupt-names = "cci";
+ clocks = <&clock_gcc clk_gcc_camss_ispif_ahb_clk>,
+ <&clock_gcc clk_cci_clk_src>,
+ <&clock_gcc clk_gcc_camss_cci_ahb_clk>,
+ <&clock_gcc clk_gcc_camss_cci_clk>,
+ <&clock_gcc clk_gcc_camss_ahb_clk>,
+ <&clock_gcc clk_gcc_camss_top_ahb_clk>;
+ clock-names = "ispif_ahb_clk", "cci_src_clk",
+ "cci_ahb_clk", "camss_cci_clk",
+ "camss_ahb_clk", "camss_top_ahb_clk";
+ qcom,clock-rates = <61540000 19200000 0 0 0 0>,
+ <61540000 37500000 0 0 0 0>;
+ pinctrl-names = "cci_default", "cci_suspend";
+ pinctrl-0 = <&cci0_active &cci1_active>;
+ pinctrl-1 = <&cci0_suspend &cci1_suspend>;
+ gpios = <&tlmm 29 0>,
+ <&tlmm 30 0>,
+ <&tlmm 31 0>,
+ <&tlmm 32 0>;
+ qcom,gpio-tbl-num = <0 1 2 3>;
+ qcom,gpio-tbl-flags = <1 1 1 1>;
+ qcom,gpio-tbl-label = "CCI_I2C_DATA0",
+ "CCI_I2C_CLK0",
+ "CCI_I2C_DATA1",
+ "CCI_I2C_CLK1";
+ i2c_freq_100Khz: qcom,i2c_standard_mode {
+ status = "disabled";
+ };
+ i2c_freq_400Khz: qcom,i2c_fast_mode {
+ status = "disabled";
+ };
+ i2c_freq_custom: qcom,i2c_custom_mode {
+ status = "disabled";
+ };
+
+ i2c_freq_1Mhz: qcom,i2c_fast_plus_mode {
+ status = "disabled";
+ };
+ };
+};
+
+&i2c_freq_100Khz {
+ qcom,hw-thigh = <78>;
+ qcom,hw-tlow = <114>;
+ qcom,hw-tsu-sto = <28>;
+ qcom,hw-tsu-sta = <28>;
+ qcom,hw-thd-dat = <10>;
+ qcom,hw-thd-sta = <77>;
+ qcom,hw-tbuf = <118>;
+ qcom,hw-scl-stretch-en = <0>;
+ qcom,hw-trdhld = <6>;
+ qcom,hw-tsp = <1>;
+};
+
+&i2c_freq_400Khz {
+ qcom,hw-thigh = <20>;
+ qcom,hw-tlow = <28>;
+ qcom,hw-tsu-sto = <21>;
+ qcom,hw-tsu-sta = <21>;
+ qcom,hw-thd-dat = <13>;
+ qcom,hw-thd-sta = <18>;
+ qcom,hw-tbuf = <32>;
+ qcom,hw-scl-stretch-en = <0>;
+ qcom,hw-trdhld = <6>;
+ qcom,hw-tsp = <3>;
+ status = "ok";
+};
+
+&i2c_freq_custom {
+ qcom,hw-thigh = <15>;
+ qcom,hw-tlow = <28>;
+ qcom,hw-tsu-sto = <21>;
+ qcom,hw-tsu-sta = <21>;
+ qcom,hw-thd-dat = <13>;
+ qcom,hw-thd-sta = <18>;
+ qcom,hw-tbuf = <25>;
+ qcom,hw-scl-stretch-en = <1>;
+ qcom,hw-trdhld = <6>;
+ qcom,hw-tsp = <3>;
+ status = "ok";
+};
+
+&i2c_freq_1Mhz {
+ qcom,hw-thigh = <16>;
+ qcom,hw-tlow = <22>;
+ qcom,hw-tsu-sto = <17>;
+ qcom,hw-tsu-sta = <18>;
+ qcom,hw-thd-dat = <16>;
+ qcom,hw-thd-sta = <15>;
+ qcom,hw-tbuf = <19>;
+ qcom,hw-scl-stretch-en = <1>;
+ qcom,hw-trdhld = <3>;
+ qcom,hw-tsp = <3>;
+ qcom,cci-clk-src = <37500000>;
+ status = "ok";
+};
diff --git a/arch/arm64/boot/dts/qcom/msm8917-pinctrl.dtsi b/arch/arm64/boot/dts/qcom/msm8917-pinctrl.dtsi
index 26fb25c..858936d 100644
--- a/arch/arm64/boot/dts/qcom/msm8917-pinctrl.dtsi
+++ b/arch/arm64/boot/dts/qcom/msm8917-pinctrl.dtsi
@@ -22,7 +22,7 @@
interrupt-parent = <&wakegpio>;
#interrupt-cells = <2>;
-
+#include "msm8917-camera-pinctrl.dtsi"
/* add pingrp for touchscreen */
pmx_ts_int_active {
ts_int_active: ts_int_active {
diff --git a/arch/arm64/boot/dts/qcom/msm8917-pmi8937-qrd-sku5.dts b/arch/arm64/boot/dts/qcom/msm8917-pmi8937-qrd-sku5.dts
index 29ef47c..832a0ab 100644
--- a/arch/arm64/boot/dts/qcom/msm8917-pmi8937-qrd-sku5.dts
+++ b/arch/arm64/boot/dts/qcom/msm8917-pmi8937-qrd-sku5.dts
@@ -114,4 +114,13 @@
qcom,key-codes = <139 172 158>;
qcom,y-offset = <0>;
};
+
+ led_flash0: qcom,camera-flash {
+ cell-index = <0>;
+ compatible = "qcom,camera-flash";
+ qcom,flash-type = <1>;
+ qcom,flash-source = <&pmi8937_flash0>;
+ qcom,torch-source = <&pmi8937_torch0>;
+ qcom,switch-source = <&pmi8937_switch>;
+ };
};
diff --git a/arch/arm64/boot/dts/qcom/msm8917-pmi8937.dtsi b/arch/arm64/boot/dts/qcom/msm8917-pmi8937.dtsi
index 3b24ab7..91a290f 100644
--- a/arch/arm64/boot/dts/qcom/msm8917-pmi8937.dtsi
+++ b/arch/arm64/boot/dts/qcom/msm8917-pmi8937.dtsi
@@ -16,7 +16,7 @@
&qpnp_smbcharger {
qcom,chg-led-sw-controls;
qcom,chg-led-support;
- /delete-property/ dpdm-supply;
+ dpdm-supply = <&usb_otg>;
};
&usb_otg {
diff --git a/arch/arm64/boot/dts/qcom/msm8917-pmi8940.dtsi b/arch/arm64/boot/dts/qcom/msm8917-pmi8940.dtsi
index 528bde4..90226da 100644
--- a/arch/arm64/boot/dts/qcom/msm8917-pmi8940.dtsi
+++ b/arch/arm64/boot/dts/qcom/msm8917-pmi8940.dtsi
@@ -16,7 +16,7 @@
&qpnp_smbcharger {
qcom,chg-led-sw-controls;
qcom,chg-led-support;
- /delete-property/ dpdm-supply;
+ dpdm-supply = <&usb_otg>;
};
&usb_otg {
diff --git a/arch/arm64/boot/dts/qcom/msm8917-pmi8950-cdp-mirror-lake-touch.dts b/arch/arm64/boot/dts/qcom/msm8917-pmi8950-cdp-mirror-lake-touch.dts
index ea6b24a..4a38b6f 100644
--- a/arch/arm64/boot/dts/qcom/msm8917-pmi8950-cdp-mirror-lake-touch.dts
+++ b/arch/arm64/boot/dts/qcom/msm8917-pmi8950-cdp-mirror-lake-touch.dts
@@ -14,6 +14,8 @@
/dts-v1/;
#include "msm8917.dtsi"
+#include "msm8917-cdp.dtsi"
+#include "msm8917-pmi8950.dtsi"
#include "msm8917-pmi8950-cdp-mirror-lake-touch.dtsi"
/ {
diff --git a/arch/arm64/boot/dts/qcom/msm8917-pmi8950-mtp.dtsi b/arch/arm64/boot/dts/qcom/msm8917-pmi8950-mtp.dtsi
index 4da1384..f882917 100644
--- a/arch/arm64/boot/dts/qcom/msm8917-pmi8950-mtp.dtsi
+++ b/arch/arm64/boot/dts/qcom/msm8917-pmi8950-mtp.dtsi
@@ -59,7 +59,7 @@
qcom,battery-data = <&mtp_batterydata>;
qcom,chg-led-sw-controls;
qcom,chg-led-support;
- /delete-property/ dpdm-supply;
+ dpdm-supply = <&usb_otg>;
};
&usb_otg {
diff --git a/arch/arm64/boot/dts/qcom/msm8917-pmi8950.dtsi b/arch/arm64/boot/dts/qcom/msm8917-pmi8950.dtsi
index 9543133..e86b9d7 100644
--- a/arch/arm64/boot/dts/qcom/msm8917-pmi8950.dtsi
+++ b/arch/arm64/boot/dts/qcom/msm8917-pmi8950.dtsi
@@ -16,7 +16,7 @@
&qpnp_smbcharger {
qcom,chg-led-sw-controls;
qcom,chg-led-support;
- /delete-property/ dpdm-supply;
+ dpdm-supply = <&usb_otg>;
};
&usb_otg {
diff --git a/arch/arm64/boot/dts/qcom/msm8917-qrd.dtsi b/arch/arm64/boot/dts/qcom/msm8917-qrd.dtsi
index fae258d0..431a5e5 100644
--- a/arch/arm64/boot/dts/qcom/msm8917-qrd.dtsi
+++ b/arch/arm64/boot/dts/qcom/msm8917-qrd.dtsi
@@ -12,6 +12,7 @@
*/
#include "msm8917-pinctrl.dtsi"
+#include "msm8917-camera-sensor-qrd.dtsi"
&blsp1_uart2 {
status = "ok";
diff --git a/arch/arm64/boot/dts/qcom/msm8917.dtsi b/arch/arm64/boot/dts/qcom/msm8917.dtsi
index d080539..1d5fe79 100644
--- a/arch/arm64/boot/dts/qcom/msm8917.dtsi
+++ b/arch/arm64/boot/dts/qcom/msm8917.dtsi
@@ -157,6 +157,7 @@
};
#include "msm8917-pinctrl.dtsi"
+#include "msm8917-camera.dtsi"
#include "msm8917-cpu.dtsi"
#include "msm8917-pm.dtsi"
#include "msm8917-ion.dtsi"
@@ -1639,6 +1640,10 @@
qcom,has-vsys-adc-channel;
qcom,wcnss-adc_tm = <&pm8937_adc_tm>;
};
+
+ ssc_sensors: qcom,msm-ssc-sensors {
+ compatible = "qcom,msm-ssc-sensors";
+ };
};
#include "pm8937-rpm-regulator.dtsi"
@@ -1711,3 +1716,141 @@
qcom,clk-dis-wait-val = <0x5>;
status = "okay";
};
+
+/* GPU overrides */
+&msm_gpu {
+
+ qcom,gpu-speed-bin = <0x6018 0x80000000 31>;
+ /delete-node/qcom,gpu-pwrlevels;
+
+ qcom,gpu-pwrlevel-bins {
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ compatible="qcom,gpu-pwrlevel-bins";
+
+ qcom,gpu-pwrlevels-0 {
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ qcom,speed-bin = <0>;
+ qcom,initial-pwrlevel = <3>;
+
+ /* TURBO */
+ qcom,gpu-pwrlevel@0 {
+ reg = <0>;
+ qcom,gpu-freq = <598000000>;
+ qcom,bus-freq = <7>;
+ qcom,bus-min = <7>;
+ qcom,bus-max = <7>;
+ };
+
+ /* NOM+ */
+ qcom,gpu-pwrlevel@1 {
+ reg = <1>;
+ qcom,gpu-freq = <523200000>;
+ qcom,bus-freq = <6>;
+ qcom,bus-min = <5>;
+ qcom,bus-max = <7>;
+ };
+
+ /* NOM */
+ qcom,gpu-pwrlevel@2 {
+ reg = <2>;
+ qcom,gpu-freq = <484800000>;
+ qcom,bus-freq = <5>;
+ qcom,bus-min = <4>;
+ qcom,bus-max = <6>;
+ };
+
+ /* SVS+ */
+ qcom,gpu-pwrlevel@3 {
+ reg = <3>;
+ qcom,gpu-freq = <400000000>;
+ qcom,bus-freq = <4>;
+ qcom,bus-min = <3>;
+ qcom,bus-max = <5>;
+ };
+
+ /* SVS */
+ qcom,gpu-pwrlevel@4 {
+ reg = <4>;
+ qcom,gpu-freq = <270000000>;
+ qcom,bus-freq = <3>;
+ qcom,bus-min = <1>;
+ qcom,bus-max = <3>;
+ };
+
+ /* XO */
+ qcom,gpu-pwrlevel@5 {
+ reg = <5>;
+ qcom,gpu-freq = <19200000>;
+ qcom,bus-freq = <0>;
+ qcom,bus-min = <0>;
+ qcom,bus-max = <0>;
+ };
+ };
+
+ qcom,gpu-pwrlevels-1 {
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ qcom,speed-bin = <1>;
+ qcom,initial-pwrlevel = <3>;
+
+ /* TURBO */
+ qcom,gpu-pwrlevel@0 {
+ reg = <0>;
+ qcom,gpu-freq = <650000000>;
+ qcom,bus-freq = <8>;
+ qcom,bus-min = <8>;
+ qcom,bus-max = <8>;
+ };
+
+ /* NOM+ */
+ qcom,gpu-pwrlevel@1 {
+ reg = <1>;
+ qcom,gpu-freq = <523200000>;
+ qcom,bus-freq = <6>;
+ qcom,bus-min = <5>;
+ qcom,bus-max = <7>;
+ };
+
+ /* NOM */
+ qcom,gpu-pwrlevel@2 {
+ reg = <2>;
+ qcom,gpu-freq = <484800000>;
+ qcom,bus-freq = <5>;
+ qcom,bus-min = <4>;
+ qcom,bus-max = <6>;
+ };
+
+ /* SVS+ */
+ qcom,gpu-pwrlevel@3 {
+ reg = <3>;
+ qcom,gpu-freq = <400000000>;
+ qcom,bus-freq = <4>;
+ qcom,bus-min = <3>;
+ qcom,bus-max = <5>;
+ };
+
+ /* SVS */
+ qcom,gpu-pwrlevel@4 {
+ reg = <4>;
+ qcom,gpu-freq = <270000000>;
+ qcom,bus-freq = <3>;
+ qcom,bus-min = <1>;
+ qcom,bus-max = <3>;
+ };
+
+ /* XO */
+ qcom,gpu-pwrlevel@5 {
+ reg = <5>;
+ qcom,gpu-freq = <19200000>;
+ qcom,bus-freq = <0>;
+ qcom,bus-min = <0>;
+ qcom,bus-max = <0>;
+ };
+ };
+ };
+};
diff --git a/arch/arm64/boot/dts/qcom/msm8937-coresight.dtsi b/arch/arm64/boot/dts/qcom/msm8937-coresight.dtsi
index b952908..e64af14 100644
--- a/arch/arm64/boot/dts/qcom/msm8937-coresight.dtsi
+++ b/arch/arm64/boot/dts/qcom/msm8937-coresight.dtsi
@@ -462,6 +462,8 @@
reg = <0x619c000 0x1000>;
cpu = <&CPU4>;
+
+ qcom,tupwr-disable;
coresight-name = "coresight-etm4";
clocks = <&clock_gcc clk_qdss_clk>,
@@ -481,6 +483,8 @@
reg = <0x619d000 0x1000>;
cpu = <&CPU5>;
+
+ qcom,tupwr-disable;
coresight-name = "coresight-etm5";
clocks = <&clock_gcc clk_qdss_clk>,
@@ -500,6 +504,8 @@
reg = <0x619e000 0x1000>;
cpu = <&CPU6>;
+
+ qcom,tupwr-disable;
coresight-name = "coresight-etm6";
clocks = <&clock_gcc clk_qdss_clk>,
@@ -519,6 +525,8 @@
reg = <0x619f000 0x1000>;
cpu = <&CPU7>;
+
+ qcom,tupwr-disable;
coresight-name = "coresight-etm7";
clocks = <&clock_gcc clk_qdss_clk>,
@@ -538,6 +546,8 @@
reg = <0x61bc000 0x1000>;
cpu = <&CPU0>;
+
+ qcom,tupwr-disable;
coresight-name = "coresight-etm0";
clocks = <&clock_gcc clk_qdss_clk>,
@@ -557,6 +567,8 @@
reg = <0x61bd000 0x1000>;
cpu = <&CPU1>;
+
+ qcom,tupwr-disable;
coresight-name = "coresight-etm1";
clocks = <&clock_gcc clk_qdss_clk>,
@@ -576,6 +588,8 @@
reg = <0x61be000 0x1000>;
cpu = <&CPU2>;
+
+ qcom,tupwr-disable;
coresight-name = "coresight-etm2";
clocks = <&clock_gcc clk_qdss_clk>,
@@ -594,6 +608,8 @@
arm,primecell-periphid = <0x000bb95d>;
reg = <0x61bf000 0x1000>;
+
+ qcom,tupwr-disable;
coresight-name = "coresight-etm3";
cpu = <&CPU3>;
@@ -957,26 +973,13 @@
clock-names = "apb_pclk";
};
- cti_modem_cpu0: cti@6128000 {
- compatible = "arm,primecell";
- arm,primecell-periphid = <0x0003b966>;
-
- reg = <0x6128000 0x1000>;
- reg-names = "cti-base";
- coresight-name = "coresight-cti-modem-cpu0";
-
- clocks = <&clock_gcc clk_qdss_clk>,
- <&clock_gcc clk_qdss_a_clk>;
- clock-names = "apb_pclk";
- };
-
- cti_modem_cpu1: cti@6124000{
+ cti_modem_cpu0: cti@6124000{
compatible = "arm,primecell";
arm,primecell-periphid = <0x0003b966>;
reg = <0x6124000 0x1000>;
reg-names = "cti-base";
- coresight-name = "coresight-cti-modem-cpu1";
+ coresight-name = "coresight-cti-modem-cpu0";
clocks = <&clock_gcc clk_qdss_clk>,
<&clock_gcc clk_qdss_a_clk>;
diff --git a/arch/arm64/boot/dts/qcom/msm8937-interposer-sdm439-qrd.dts b/arch/arm64/boot/dts/qcom/msm8937-interposer-sdm439-qrd.dts
index 71157e2..2bad28b 100644
--- a/arch/arm64/boot/dts/qcom/msm8937-interposer-sdm439-qrd.dts
+++ b/arch/arm64/boot/dts/qcom/msm8937-interposer-sdm439-qrd.dts
@@ -22,10 +22,3 @@
qcom,board-id = <0xb 2>;
qcom,pmic-id = <0x010016 0x25 0x0 0x0>;
};
-
-&pmi632_vadc {
- chan@4a {
- qcom,scale-function = <22>;
- };
-};
-
diff --git a/arch/arm64/boot/dts/qcom/msm8937-pinctrl.dtsi b/arch/arm64/boot/dts/qcom/msm8937-pinctrl.dtsi
index 86e41a3..a730287 100644
--- a/arch/arm64/boot/dts/qcom/msm8937-pinctrl.dtsi
+++ b/arch/arm64/boot/dts/qcom/msm8937-pinctrl.dtsi
@@ -319,6 +319,88 @@
};
};
+ spi7 {
+ spi7_default: spi7_default {
+ mux {
+ pins = "gpio85", "gpio86", "gpio88";
+ function = "blsp_spi7";
+ };
+
+ config {
+ pins = "gpio85", "gpio86", "gpio88";
+ drive-strength = <16>;
+ bias-disable = <0>;
+ };
+ };
+
+ spi7_sleep: spi7_sleep {
+ mux {
+ pins = "gpio85", "gpio86", "gpio88";
+ function = "blsp_spi7";
+ };
+
+ config {
+ pins = "gpio85", "gpio86", "gpio88";
+ drive-strength = <16>;
+ bias-disable = <0>;
+ };
+ };
+ spi7_cs0_active: cs0_active {
+ mux {
+ pins = "gpio87";
+ function = "blsp_spi7_cs0";
+ };
+
+ config {
+ pins = "gpio87";
+ drive-strength = <2>;
+ bias-disable = <0>;
+ };
+ };
+ };
+
+ fpc_reset_int {
+ fpc_reset_low: reset_low {
+ mux {
+ pins = "gpio124";
+ function = "fpc_reset_gpio_low";
+ };
+
+ config {
+ pins = "gpio124";
+ drive-strength = <2>;
+ bias-disable;
+ output-low;
+ };
+ };
+
+ fpc_reset_high: reset_high {
+ mux {
+ pins = "gpio124";
+ function = "fpc_reset_gpio_high";
+ };
+
+ config {
+ pins = "gpio124";
+ drive-strength = <2>;
+ bias-disable;
+ output-high;
+ };
+ };
+
+ fpc_int_low: int_low {
+ mux {
+ pins = "gpio48";
+ };
+ config {
+ pins = "gpio48";
+ drive-strength = <2>;
+ bias-pull-down;
+ input-enable;
+ };
+ };
+ };
+
wcnss_pmux_5wire {
/* Active configuration of bus pins */
wcnss_default: wcnss_default {
diff --git a/arch/arm64/boot/dts/qcom/msm8937-pmi8950-mtp.dtsi b/arch/arm64/boot/dts/qcom/msm8937-pmi8950-mtp.dtsi
index 1afa230..2d88ad1 100644
--- a/arch/arm64/boot/dts/qcom/msm8937-pmi8950-mtp.dtsi
+++ b/arch/arm64/boot/dts/qcom/msm8937-pmi8950-mtp.dtsi
@@ -30,7 +30,7 @@
qcom,battery-data = <&mtp_batterydata>;
qcom,chg-led-sw-controls;
qcom,chg-led-support;
- /delete-property/ dpdm-supply;
+ dpdm-supply = <&usb_otg>;
};
&usb_otg {
diff --git a/arch/arm64/boot/dts/qcom/msm8937.dtsi b/arch/arm64/boot/dts/qcom/msm8937.dtsi
index 67ec032..85e3043 100644
--- a/arch/arm64/boot/dts/qcom/msm8937.dtsi
+++ b/arch/arm64/boot/dts/qcom/msm8937.dtsi
@@ -998,7 +998,7 @@
reg-names = "wdt-base";
interrupts = <0 3 0>, <0 4 0>;
qcom,bark-time = <11000>;
- qcom,pet-time = <10000>;
+ qcom,pet-time = <9360>;
qcom,ipi-ping;
qcom,wakeup-enable;
status = "okay";
diff --git a/arch/arm64/boot/dts/qcom/msm8953-coresight.dtsi b/arch/arm64/boot/dts/qcom/msm8953-coresight.dtsi
index 196a526..d3c2e26 100644
--- a/arch/arm64/boot/dts/qcom/msm8953-coresight.dtsi
+++ b/arch/arm64/boot/dts/qcom/msm8953-coresight.dtsi
@@ -505,6 +505,8 @@
reg = <0x619c000 0x1000>;
cpu = <&CPU0>;
+
+ qcom,tupwr-disable;
coresight-name = "coresight-etm0";
clocks = <&clock_gcc clk_qdss_clk>,
diff --git a/arch/arm64/boot/dts/qcom/msm8953-ext-codec-mtp-overlay.dts b/arch/arm64/boot/dts/qcom/msm8953-ext-codec-mtp-overlay.dts
index b182a25..1b09b3c 100644
--- a/arch/arm64/boot/dts/qcom/msm8953-ext-codec-mtp-overlay.dts
+++ b/arch/arm64/boot/dts/qcom/msm8953-ext-codec-mtp-overlay.dts
@@ -23,6 +23,31 @@
qcom,pmic-id = <0x010016 0x010011 0x0 0x0>;
};
+&vendor {
+ mtp_batterydata: qcom,battery-data {
+ qcom,batt-id-range-pct = <15>;
+ #include "batterydata-itech-3000mah.dtsi"
+ #include "batterydata-ascent-3450mAh.dtsi"
+ };
+};
+
+&qpnp_fg {
+ qcom,battery-data = <&mtp_batterydata>;
+};
+
+&pmi_haptic{
+ qcom,lra-auto-res-mode="qwd";
+ qcom,lra-high-z="opt1";
+ qcom,lra-res-cal-period = <0>;
+ qcom,wave-play-rate-us = <4165>;
+};
+
+&qpnp_smbcharger {
+ qcom,battery-data = <&mtp_batterydata>;
+ qcom,chg-led-sw-controls;
+ qcom,chg-led-support;
+};
+
&int_codec {
status = "disabled";
};
diff --git a/arch/arm64/boot/dts/qcom/msm8953-gpu.dtsi b/arch/arm64/boot/dts/qcom/msm8953-gpu.dtsi
index f82b68d..14c4d2b 100644
--- a/arch/arm64/boot/dts/qcom/msm8953-gpu.dtsi
+++ b/arch/arm64/boot/dts/qcom/msm8953-gpu.dtsi
@@ -231,8 +231,8 @@
qcom,gpu-pwrlevel@5 {
reg = <5>;
qcom,gpu-freq = <216000000>;
- qcom,bus-freq = <1>;
- qcom,bus-min = <1>;
+ qcom,bus-freq = <3>;
+ qcom,bus-min = <2>;
qcom,bus-max = <4>;
};
@@ -240,7 +240,7 @@
qcom,gpu-pwrlevel@6 {
reg = <6>;
qcom,gpu-freq = <133300000>;
- qcom,bus-freq = <1>;
+ qcom,bus-freq = <3>;
qcom,bus-min = <1>;
qcom,bus-max = <4>;
};
diff --git a/arch/arm64/boot/dts/qcom/msm8953-mdss-panels.dtsi b/arch/arm64/boot/dts/qcom/msm8953-mdss-panels.dtsi
index 7ee30f6..a80b4fe 100644
--- a/arch/arm64/boot/dts/qcom/msm8953-mdss-panels.dtsi
+++ b/arch/arm64/boot/dts/qcom/msm8953-mdss-panels.dtsi
@@ -25,6 +25,7 @@
#include "dsi-panel-lt8912-1080p-video.dtsi"
#include "dsi-panel-hx8399c-fhd-plus-video.dtsi"
#include "dsi-panel-hx83100a-800p-video.dtsi"
+#include "dsi-panel-boent51021-1200p-video.dtsi"
&soc {
dsi_panel_pwr_supply: dsi_panel_pwr_supply {
@@ -169,3 +170,11 @@
1f 1c 05 06 03 03 04 a0
1f 10 05 06 03 03 04 a0];
};
+
+&dsi_boent51021_1200p_video {
+ qcom,mdss-dsi-panel-timings-phy-v2 = [25 20 08 0a 06 03 04 a0
+ 25 20 08 0a 06 03 04 a0
+ 25 20 08 0a 06 03 04 a0
+ 25 20 08 0a 06 03 04 a0
+ 25 1d 08 0a 06 03 04 a0];
+};
diff --git a/arch/arm64/boot/dts/qcom/msm8953-mtp-overlay.dts b/arch/arm64/boot/dts/qcom/msm8953-mtp-overlay.dts
index c6ae512..00614b2 100644
--- a/arch/arm64/boot/dts/qcom/msm8953-mtp-overlay.dts
+++ b/arch/arm64/boot/dts/qcom/msm8953-mtp-overlay.dts
@@ -21,7 +21,7 @@
qcom,board-id = <8 0>;
};
-/{
+&vendor {
mtp_batterydata: qcom,battery-data {
qcom,batt-id-range-pct = <15>;
#include "batterydata-itech-3000mah.dtsi"
@@ -33,6 +33,13 @@
qcom,battery-data = <&mtp_batterydata>;
};
+&pmi_haptic{
+ qcom,lra-auto-res-mode="qwd";
+ qcom,lra-high-z="opt1";
+ qcom,lra-res-cal-period = <0>;
+ qcom,wave-play-rate-us = <4165>;
+};
+
&qpnp_smbcharger {
qcom,battery-data = <&mtp_batterydata>;
qcom,chg-led-sw-controls;
diff --git a/arch/arm64/boot/dts/qcom/msm8953-pinctrl.dtsi b/arch/arm64/boot/dts/qcom/msm8953-pinctrl.dtsi
index cc3c392..e8de4ef 100644
--- a/arch/arm64/boot/dts/qcom/msm8953-pinctrl.dtsi
+++ b/arch/arm64/boot/dts/qcom/msm8953-pinctrl.dtsi
@@ -1731,5 +1731,19 @@
bias-disable;
};
};
+
+ ssusb_mode_sel: ssusb_mode_sel {
+ mux {
+ pins = "gpio12";
+ function = "gpio";
+ };
+
+ config {
+ pins = "gpio12";
+ drive-strength = <2>;
+ bias-disable;
+ input-disable;
+ };
+ };
};
};
diff --git a/arch/arm64/boot/dts/qcom/msm8953.dtsi b/arch/arm64/boot/dts/qcom/msm8953.dtsi
index d25d5b3..c3178e0 100644
--- a/arch/arm64/boot/dts/qcom/msm8953.dtsi
+++ b/arch/arm64/boot/dts/qcom/msm8953.dtsi
@@ -30,9 +30,21 @@
bootargs = "core_ctl_disable_cpumask=0-7 kpti=0";
};
+ vendor: vendor {
+ #address-cells = <1>;
+ #size-cells = <1>;
+ ranges = <0 0 0 0xffffffff>;
+ compatible = "simple-bus";
+ };
+
firmware: firmware {
android {
compatible = "android,firmware";
+ vbmeta {
+ compatible = "android,vbmeta";
+ parts = "vbmeta,boot,system,vendor,dtbo,recovery";
+ };
+
fstab {
compatible = "android,fstab";
vendor {
@@ -40,7 +52,7 @@
dev = "/dev/block/platform/soc/7824900.sdhci/by-name/vendor";
type = "ext4";
mnt_flags = "ro,barrier=1,discard";
- fsmgr_flags = "wait";
+ fsmgr_flags = "wait,avb";
status = "ok";
};
system {
@@ -48,7 +60,7 @@
dev = "/dev/block/platform/soc/7824900.sdhci/by-name/system";
type = "ext4";
mnt_flags = "ro,barrier=1,discard";
- fsmgr_flags = "wait";
+ fsmgr_flags = "wait,avb";
status = "ok";
};
@@ -97,7 +109,7 @@
compatible = "shared-dma-pool";
reusable;
alignment = <0 0x400000>;
- size = <0 0x09800000>;
+ size = <0 0x0b400000>;
};
qseecom_mem: qseecom_region@0 {
@@ -1230,7 +1242,7 @@
reg-names = "wdt-base";
interrupts = <0 3 0>, <0 4 0>;
qcom,bark-time = <11000>;
- qcom,pet-time = <10000>;
+ qcom,pet-time = <9360>;
qcom,ipi-ping;
qcom,wakeup-enable;
qcom,scandump-size = <0x40000>;
diff --git a/arch/arm64/boot/dts/qcom/pm8916.dtsi b/arch/arm64/boot/dts/qcom/pm8916.dtsi
index af29080..5204137 100644
--- a/arch/arm64/boot/dts/qcom/pm8916.dtsi
+++ b/arch/arm64/boot/dts/qcom/pm8916.dtsi
@@ -101,12 +101,13 @@
reg = <0x3100 0x100>;
#address-cells = <1>;
#size-cells = <0>;
- interrupts = <0x0 0x31 0x0 IRQ_TYPE_NONE>;
+ interrupts = <0x0 0x31 0x0 IRQ_TYPE_EDGE_RISING>;
interrupt-names = "eoc-int-en-set";
qcom,adc-bit-resolution = <15>;
qcom,adc-vdd-reference = <1800>;
qcom,vadc-poll-eoc;
qcom,pmic-revid = <&pm8916_revid>;
+ #thermal-sensor-cells = <1>;
chan@8 {
label = "die_temp";
@@ -145,11 +146,12 @@
pm8916_tz: qcom,temp-alarm@2400 {
compatible = "qcom,qpnp-temp-alarm";
reg = <0x2400 0x100>;
- interrupts = <0x0 0x24 0x0 IRQ_TYPE_NONE>;
+ interrupts = <0x0 0x24 0x0 IRQ_TYPE_EDGE_RISING>;
label = "pm8916_tz";
qcom,channel-num = <8>;
qcom,threshold-set = <0>;
qcom,temp_alarm-vadc = <&pm8916_vadc>;
+ #thermal-sensor-cells = <0>;
};
pm8916_adc_tm: vadc@3400 {
@@ -157,9 +159,9 @@
reg = <0x3400 0x100>;
#address-cells = <1>;
#size-cells = <0>;
- interrupts = <0x0 0x34 0x0 IRQ_TYPE_NONE>,
- <0x0 0x34 0x3 IRQ_TYPE_NONE>,
- <0x0 0x34 0x4 IRQ_TYPE_NONE>;
+ interrupts = <0x0 0x34 0x0 IRQ_TYPE_EDGE_RISING>,
+ <0x0 0x34 0x3 IRQ_TYPE_EDGE_RISING>,
+ <0x0 0x34 0x4 IRQ_TYPE_EDGE_RISING>;
interrupt-names = "eoc-int-en-set",
"high-thr-en-set",
"low-thr-en-set";
diff --git a/arch/arm64/boot/dts/qcom/pmi632.dtsi b/arch/arm64/boot/dts/qcom/pmi632.dtsi
index d77d55d..53147eb 100644
--- a/arch/arm64/boot/dts/qcom/pmi632.dtsi
+++ b/arch/arm64/boot/dts/qcom/pmi632.dtsi
@@ -289,20 +289,20 @@
pmi632_gpios: pinctrl@c000 {
compatible = "qcom,spmi-gpio";
reg = <0xc000 0x800>;
- interrupts = <0x2 0xc1 0 IRQ_TYPE_NONE>,
+ interrupts = <0x2 0xc0 0 IRQ_TYPE_NONE>,
+ <0x2 0xc1 0 IRQ_TYPE_NONE>,
<0x2 0xc2 0 IRQ_TYPE_NONE>,
<0x2 0xc3 0 IRQ_TYPE_NONE>,
<0x2 0xc4 0 IRQ_TYPE_NONE>,
<0x2 0xc5 0 IRQ_TYPE_NONE>,
<0x2 0xc6 0 IRQ_TYPE_NONE>,
<0x2 0xc7 0 IRQ_TYPE_NONE>;
- interrupt-names = "pmi632_gpio2", "pmi632_gpio3",
- "pmi632_gpio4", "pmi632_gpio5",
- "pmi632_gpio6", "pmi632_gpio7",
- "pmi632_gpio8";
+ interrupt-names = "pmi632_gpio1", "pmi632_gpio2",
+ "pmi632_gpio3", "pmi632_gpio4",
+ "pmi632_gpio5", "pmi632_gpio6",
+ "pmi632_gpio7", "pmi632_gpio8";
gpio-controller;
#gpio-cells = <2>;
- qcom,gpios-disallowed = <1>;
};
pmi632_charger: qcom,qpnp-smb5 {
@@ -318,6 +318,9 @@
qcom,flash-disable-soc = <10>;
qcom,sw-jeita-enable;
qcom,step-charging-enable;
+ qcom,hw-die-temp-mitigation;
+ qcom,hw-connector-mitigation;
+ qcom,connector-internal-pull-kohm = <100>;
qcom,thermal-mitigation
= <3000000 2500000 2000000 1500000
@@ -527,6 +530,16 @@
compatible = "qcom,msm-bcl-soc";
#thermal-sensor-cells = <0>;
};
+
+ pmi632_pbs_client3: qcom,pbs@7400 {
+ compatible = "qcom,qpnp-pbs";
+ reg = <0x7400 0x100>;
+ };
+
+ pmi632_sdam7: qcom,sdam@b600 {
+ compatible = "qcom,spmi-sdam";
+ reg = <0xb600 0x100>;
+ };
};
pmi632_3: qcom,pmi632@3 {
@@ -539,7 +552,7 @@
compatible = "qcom,qpnp-vibrator-ldo";
reg = <0x5700 0x100>;
qcom,vib-ldo-volt-uv = <3000000>;
- qcom,vib-overdrive-volt-uv = <3544000>;
+ qcom,disable-overdrive;
};
pmi632_pwm: qcom,pwms@b300 {
@@ -547,6 +560,36 @@
reg = <0xb300 0x500>;
reg-names = "lpg-base";
#pwm-cells = <2>;
+ nvmem-names = "ppg_sdam";
+ nvmem = <&pmi632_sdam7>;
+ qcom,pbs-client = <&pmi632_pbs_client3>;
+ qcom,lut-sdam-base = <0x80>;
+ qcom,lut-patterns = <0 0 0 14 28 42 56 70 84 100
+ 100 84 70 56 42 28 14 0 0 0>;
+ lpg@1 {
+ qcom,lpg-chan-id = <1>;
+ qcom,ramp-step-ms = <200>;
+ qcom,ramp-low-index = <0>;
+ qcom,ramp-high-index = <19>;
+ qcom,ramp-pattern-repeat;
+ qcom,lpg-sdam-base = <0x48>;
+ };
+ lpg@2 {
+ qcom,lpg-chan-id = <2>;
+ qcom,ramp-step-ms = <200>;
+ qcom,ramp-low-index = <0>;
+ qcom,ramp-high-index = <19>;
+ qcom,ramp-pattern-repeat;
+ qcom,lpg-sdam-base = <0x56>;
+ };
+ lpg@3 {
+ qcom,lpg-chan-id = <3>;
+ qcom,ramp-step-ms = <200>;
+ qcom,ramp-low-index = <0>;
+ qcom,ramp-high-index = <19>;
+ qcom,ramp-pattern-repeat;
+ qcom,lpg-sdam-base = <0x64>;
+ };
};
pmi632_rgb: qcom,leds@d000 {
diff --git a/arch/arm64/boot/dts/qcom/qcs605-lc-cdp-base.dts b/arch/arm64/boot/dts/qcom/qcs605-lc-cdp-base.dts
new file mode 100644
index 0000000..e08acea
--- /dev/null
+++ b/arch/arm64/boot/dts/qcom/qcs605-lc-cdp-base.dts
@@ -0,0 +1,22 @@
+/*
+ * Copyright (c) 2018, The Linux Foundation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ */
+
+/dts-v1/;
+
+#include "qcs605-lc.dtsi"
+
+/ {
+ model = "Qualcomm Technologies, Inc. QCS605 LC CDP Base SoC";
+ compatible = "qcom,qcs605";
+ qcom,board-id = <1 4>;
+};
diff --git a/arch/arm64/boot/dts/qcom/qcs605-lc-cdp-overlay.dts b/arch/arm64/boot/dts/qcom/qcs605-lc-cdp-overlay.dts
new file mode 100644
index 0000000..5987fb3
--- /dev/null
+++ b/arch/arm64/boot/dts/qcom/qcs605-lc-cdp-overlay.dts
@@ -0,0 +1,26 @@
+/*
+ * Copyright (c) 2018, The Linux Foundation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ */
+
+/dts-v1/;
+/plugin/;
+
+#include <dt-bindings/interrupt-controller/arm-gic.h>
+#include "qcs605-lc-cdp.dtsi"
+#include "qcs605-lc-audio-overlay.dtsi"
+
+/ {
+ model = "Qualcomm Technologies, Inc. QC605 LC Groot + PM8005 CDP";
+ compatible = "qcom,qcs605-cdp", "qcom,qcs605", "qcom,cdp";
+ qcom,msm-id = <347 0x0>;
+ qcom,board-id = <1 4>;
+};
diff --git a/arch/arm64/boot/dts/qcom/qcs605-lc-cdp.dts b/arch/arm64/boot/dts/qcom/qcs605-lc-cdp.dts
new file mode 100644
index 0000000..753b496
--- /dev/null
+++ b/arch/arm64/boot/dts/qcom/qcs605-lc-cdp.dts
@@ -0,0 +1,25 @@
+/*
+ * Copyright (c) 2018, The Linux Foundation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ */
+
+
+/dts-v1/;
+
+#include "qcs605-lc.dtsi"
+#include "qcs605-lc-cdp.dtsi"
+#include "qcs605-lc-audio-overlay.dtsi"
+
+/ {
+ model = "Qualcomm Technologies, Inc. QC605 LC Groot + PM8005 CDP";
+ compatible = "qcom,qcs605-cdp", "qcom,qcs605", "qcom,cdp";
+ qcom,board-id = <1 4>;
+};
diff --git a/arch/arm64/boot/dts/qcom/qcs605-lc-cdp.dtsi b/arch/arm64/boot/dts/qcom/qcs605-lc-cdp.dtsi
new file mode 100644
index 0000000..e32128c
--- /dev/null
+++ b/arch/arm64/boot/dts/qcom/qcs605-lc-cdp.dtsi
@@ -0,0 +1,87 @@
+/*
+ * Copyright (c) 2018, The Linux Foundation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ */
+
+#include "qcs605-lc-pmic-overlay.dtsi"
+
+&qupv3_se9_2uart {
+ status = "disabled";
+};
+
+&qupv3_se12_2uart {
+ status = "ok";
+};
+
+&qupv3_se8_spi {
+ status = "disabled";
+};
+
+&sdhc_1 {
+ vdd-supply = <&pm660_l19>;
+ qcom,vdd-voltage-level = <2960000 2960000>;
+ qcom,vdd-current-level = <0 570000>;
+
+ vdd-io-supply = <&pm660_l8>;
+ qcom,vdd-io-always-on;
+ qcom,vdd-io-lpm-sup;
+ qcom,vdd-io-voltage-level = <1800000 1800000>;
+ qcom,vdd-io-current-level = <0 325000>;
+
+ pinctrl-names = "active", "sleep";
+ pinctrl-0 = <&sdc1_clk_on &sdc1_cmd_on &sdc1_data_on &sdc1_rclk_on>;
+ pinctrl-1 = <&sdc1_clk_off &sdc1_cmd_off &sdc1_data_off &sdc1_rclk_off>;
+
+ status = "ok";
+};
+
+&tlmm {
+ sdc2_cd_on: cd_on {
+ mux {
+ pins = "gpio116";
+ function = "gpio";
+ };
+
+ config {
+ pins = "gpio116";
+ drive-strength = <2>;
+ bias-pull-up;
+ };
+ };
+
+ sdc2_cd_off: cd_off {
+ mux {
+ pins = "gpio116";
+ function = "gpio";
+ };
+
+ config {
+ pins = "gpio116";
+ drive-strength = <2>;
+ bias-disable;
+ };
+ };
+};
+
+&sdhc_2 {
+ /* VDD external regulator is enabled/disabled by pm660_l18 regulator */
+ vdd-io-supply = <&pm660_l18>;
+ qcom,vdd-io-voltage-level = <1800000 2960000>;
+ qcom,vdd-io-current-level = <0 22000>;
+
+ pinctrl-names = "active", "sleep";
+ pinctrl-0 = <&sdc2_clk_on &sdc2_cmd_on &sdc2_data_on &sdc2_cd_on>;
+ pinctrl-1 = <&sdc2_clk_off &sdc2_cmd_off &sdc2_data_off &sdc2_cd_off>;
+
+ cd-gpios = <&tlmm 116 0x1>;
+
+ status = "ok";
+};
diff --git a/arch/arm64/boot/dts/qcom/qcs605.dtsi b/arch/arm64/boot/dts/qcom/qcs605.dtsi
index 16ae8de..61a812c 100644
--- a/arch/arm64/boot/dts/qcom/qcs605.dtsi
+++ b/arch/arm64/boot/dts/qcom/qcs605.dtsi
@@ -90,8 +90,8 @@
lmh-dcvs-00 {
trips {
active-config {
- temperature = <105000>;
- hysteresis = <40000>;
+ temperature = <100000>;
+ hysteresis = <35000>;
};
};
};
@@ -99,8 +99,8 @@
lmh-dcvs-01 {
trips {
active-config {
- temperature = <105000>;
- hysteresis = <40000>;
+ temperature = <100000>;
+ hysteresis = <35000>;
};
};
};
diff --git a/arch/arm64/boot/dts/qcom/sda670-camera-sensor-hdk.dtsi b/arch/arm64/boot/dts/qcom/sda670-camera-sensor-hdk.dtsi
new file mode 100644
index 0000000..484ed64
--- /dev/null
+++ b/arch/arm64/boot/dts/qcom/sda670-camera-sensor-hdk.dtsi
@@ -0,0 +1,412 @@
+/*
+ * Copyright (c) 2018, The Linux Foundation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ */
+
+&soc {
+ com,camera-flash@0 {
+ cell-index = <0>;
+ reg = <0x00 0x00>;
+ compatible = "qcom,camera-flash";
+ flash-source = <&pm660l_flash0 &pm660l_flash1>;
+ torch-source = <&pm660l_torch0 &pm660l_torch1>;
+ switch-source = <&pm660l_switch0>;
+ status = "ok";
+ };
+
+ qcom,camera-flash@1 {
+ cell-index = <1>;
+ reg = <0x01 0x00>;
+ compatible = "qcom,camera-flash";
+ flash-source = <&pm660l_flash0 &pm660l_flash1>;
+ torch-source = <&pm660l_torch0 &pm660l_torch1>;
+ switch-source = <&pm660l_switch0>;
+ status = "ok";
+ };
+
+ led_flash_front: qcom,camera-flash@2 {
+ cell-index = <2>;
+ reg = <0x02 0x00>;
+ compatible = "qcom,camera-flash";
+ flash-source = <&pm660l_flash2>;
+ torch-source = <&pm660l_torch2>;
+ switch-source = <&pm660l_switch1>;
+ status = "ok";
+ };
+
+ gpio-regulator@0 {
+ compatible = "regulator-fixed";
+ reg = <0x00 0x00>;
+ regulator-name = "actuator_regulator";
+ regulator-min-microvolt = <2800000>;
+ regulator-max-microvolt = <2800000>;
+ regulator-enable-ramp-delay = <100>;
+ enable-active-high;
+ gpio = <&tlmm 27 0>;
+ };
+
+ camera_ldo: gpio-regulator@2 {
+ compatible = "regulator-fixed";
+ reg = <0x02 0x00>;
+ regulator-name = "camera_ldo";
+ regulator-min-microvolt = <1352000>;
+ regulator-max-microvolt = <1352000>;
+ regulator-enable-ramp-delay = <233>;
+ enable-active-high;
+ gpio = <&pm660l_gpios 3 0>;
+ pinctrl-names = "default";
+ pinctrl-0 = <&camera_dvdd_en_default>;
+ vin-supply = <&pm660_s6>;
+ };
+
+ camera_rear_ldo: gpio-regulator@1 {
+ compatible = "regulator-fixed";
+ reg = <0x01 0x00>;
+ regulator-name = "camera_rear_ldo";
+ regulator-min-microvolt = <1352000>;
+ regulator-max-microvolt = <1352000>;
+ regulator-enable-ramp-delay = <135>;
+ enable-active-high;
+ gpio = <&pm660l_gpios 4 0>;
+ pinctrl-names = "default";
+ pinctrl-0 = <&camera_rear_dvdd_en_default>;
+ vin-supply = <&pm660_s6>;
+ };
+
+ camera_vio_ldo: gpio-regulator@3 {
+ compatible = "regulator-fixed";
+ reg = <0x03 0x00>;
+ regulator-name = "camera_vio_ldo";
+ regulator-min-microvolt = <1800000>;
+ regulator-max-microvolt = <1800000>;
+ regulator-enable-ramp-delay = <233>;
+ enable-active-high;
+ gpio = <&tlmm 29 0>;
+ pinctrl-names = "default";
+ pinctrl-0 = <&cam_sensor_rear_vio>;
+ vin-supply = <&pm660_s4>;
+ };
+
+ camera_vana_ldo: gpio-regulator@4 {
+ compatible = "regulator-fixed";
+ reg = <0x04 0x00>;
+ regulator-name = "camera_vana_ldo";
+ regulator-min-microvolt = <2850000>;
+ regulator-max-microvolt = <2850000>;
+ regulator-enable-ramp-delay = <233>;
+ enable-active-high;
+ gpio = <&tlmm 8 0>;
+ pinctrl-names = "default";
+ pinctrl-0 = <&cam_sensor_rear_vana>;
+ vin-supply = <&pm660l_bob>;
+ };
+};
+
+&cam_cci {
+ qcom,cam-res-mgr {
+ compatible = "qcom,cam-res-mgr";
+ status = "ok";
+ };
+
+ qcom,actuator@0 {
+ cell-index = <0>;
+ reg = <0x0>;
+ compatible = "qcom,actuator";
+ cci-master = <0>;
+ cam_vaf-supply = <&actuator_regulator>;
+ regulator-names = "cam_vaf";
+ rgltr-cntrl-support;
+ rgltr-min-voltage = <2800000>;
+ rgltr-max-voltage = <2800000>;
+ rgltr-load-current = <0>;
+ };
+
+ qcom,actuator@1 {
+ cell-index = <1>;
+ reg = <0x1>;
+ compatible = "qcom,actuator";
+ cci-master = <1>;
+ cam_vaf-supply = <&actuator_regulator>;
+ regulator-names = "cam_vaf";
+ rgltr-cntrl-support;
+ rgltr-min-voltage = <2800000>;
+ rgltr-max-voltage = <2800000>;
+ rgltr-load-current = <0>;
+ };
+
+ qcom,actuator@2 {
+ cell-index = <2>;
+ reg = <0x2>;
+ compatible = "qcom,actuator";
+ cci-master = <1>;
+ cam_vaf-supply = <&actuator_regulator>;
+ regulator-names = "cam_vaf";
+ rgltr-cntrl-support;
+ rgltr-min-voltage = <2800000>;
+ rgltr-max-voltage = <2800000>;
+ rgltr-load-current = <0>;
+ };
+
+ ois_rear: qcom,ois@0 {
+ cell-index = <0>;
+ reg = <0x0>;
+ compatible = "qcom,ois";
+ cci-master = <0>;
+ cam_vaf-supply = <&actuator_regulator>;
+ regulator-names = "cam_vaf";
+ rgltr-cntrl-support;
+ rgltr-min-voltage = <2800000>;
+ rgltr-max-voltage = <2800000>;
+ rgltr-load-current = <0>;
+ status = "disabled";
+ };
+
+ qcom,eeprom@0 {
+ cell-index = <0>;
+ reg = <0>;
+ compatible = "qcom,eeprom";
+ cam_vio-supply = <&camera_vio_ldo>;
+ cam_vana-supply = <&camera_vana_ldo>;
+ cam_vdig-supply = <&camera_rear_ldo>;
+ cam_clk-supply = <&titan_top_gdsc>;
+ cam_vaf-supply = <&actuator_regulator>;
+ regulator-names = "cam_vio", "cam_vana", "cam_vdig",
+ "cam_clk", "cam_vaf";
+ rgltr-cntrl-support;
+ rgltr-min-voltage = <1800000 2850000 1352000 0 2800000>;
+ rgltr-max-voltage = <1800000 2850000 1352000 0 2800000>;
+ rgltr-load-current = <0 80000 105000 0 0>;
+ gpio-no-mux = <0>;
+ pinctrl-names = "cam_default", "cam_suspend";
+ pinctrl-0 = <&cam_sensor_mclk0_active
+ &cam_sensor_rear_active>;
+ pinctrl-1 = <&cam_sensor_mclk0_suspend
+ &cam_sensor_rear_suspend>;
+ gpios = <&tlmm 13 0>,
+ <&tlmm 30 0>;
+ gpio-reset = <1>;
+ gpio-req-tbl-num = <0 1>;
+ gpio-req-tbl-flags = <1 0>;
+ gpio-req-tbl-label = "CAMIF_MCLK0",
+ "CAM_RESET0";
+ sensor-mode = <0>;
+ cci-master = <0>;
+ status = "ok";
+ clocks = <&clock_camcc CAM_CC_MCLK0_CLK>;
+ clock-names = "cam_clk";
+ clock-cntl-level = "turbo";
+ clock-rates = <24000000>;
+ };
+
+ qcom,eeprom@1 {
+ cell-index = <1>;
+ reg = <0x1>;
+ compatible = "qcom,eeprom";
+ cam_vio-supply = <&camera_vio_ldo>;
+ cam_vana-supply = <&camera_vana_ldo>;
+ cam_vdig-supply = <&camera_ldo>;
+ cam_clk-supply = <&titan_top_gdsc>;
+ cam_vaf-supply = <&actuator_regulator>;
+ regulator-names = "cam_vdig", "cam_vio", "cam_vana",
+ "cam_clk", "cam_vaf";
+ rgltr-cntrl-support;
+ rgltr-min-voltage = <1352000 1800000 2850000 0 2800000>;
+ rgltr-max-voltage = <1352000 1800000 2850000 0 2800000>;
+ rgltr-load-current = <105000 0 80000 0 0>;
+ gpio-no-mux = <0>;
+ pinctrl-names = "cam_default", "cam_suspend";
+ pinctrl-0 = <&cam_sensor_mclk1_active
+ &cam_sensor_rear2_active>;
+ pinctrl-1 = <&cam_sensor_mclk1_suspend
+ &cam_sensor_rear2_suspend>;
+ gpios = <&tlmm 14 0>,
+ <&tlmm 28 0>;
+ gpio-reset = <1>;
+ gpio-req-tbl-num = <0 1>;
+ gpio-req-tbl-flags = <1 0>;
+ gpio-req-tbl-label = "CAMIF_MCLK1",
+ "CAM_RESET1";
+ sensor-position = <0>;
+ sensor-mode = <0>;
+ cci-master = <1>;
+ status = "ok";
+ clock-names = "cam_clk";
+ clock-cntl-level = "turbo";
+ clock-rates = <24000000>;
+ };
+
+ qcom,eeprom@2 {
+ cell-index = <2>;
+ reg = <0x2>;
+ compatible = "qcom,eeprom";
+ cam_vio-supply = <&camera_vio_ldo>;
+ cam_vana-supply = <&camera_vana_ldo>;
+ cam_vdig-supply = <&camera_ldo>;
+ cam_clk-supply = <&titan_top_gdsc>;
+ cam_vaf-supply = <&actuator_regulator>;
+ regulator-names = "cam_vdig", "cam_vio", "cam_vana",
+ "cam_clk", "cam_vaf";
+ rgltr-cntrl-support;
+ rgltr-min-voltage = <1352000 1800000 2850000 0 2800000>;
+ rgltr-max-voltage = <1352000 1800000 2850000 0 2800000>;
+ rgltr-load-current = <105000 0 80000 0 0>;
+ gpio-no-mux = <0>;
+ pinctrl-names = "cam_default", "cam_suspend";
+ pinctrl-0 = <&cam_sensor_mclk1_active
+ &cam_sensor_rear2_active>;
+ pinctrl-1 = <&cam_sensor_mclk1_suspend
+ &cam_sensor_rear2_suspend>;
+ gpios = <&tlmm 14 0>,
+ <&tlmm 28 0>;
+ gpio-reset = <1>;
+ gpio-req-tbl-num = <0 1>;
+ gpio-req-tbl-flags = <1 0>;
+ gpio-req-tbl-label = "CAMIF_MCLK1",
+ "CAM_RESET1";
+ sensor-mode = <0>;
+ cci-master = <1>;
+ status = "ok";
+ clocks = <&clock_camcc CAM_CC_MCLK1_CLK>;
+ clock-names = "cam_clk";
+ clock-cntl-level = "turbo";
+ clock-rates = <24000000>;
+ };
+
+ qcom,cam-sensor@0 {
+ cell-index = <0>;
+ compatible = "qcom,cam-sensor";
+ reg = <0x0>;
+ csiphy-sd-index = <0>;
+ sensor-position-roll = <270>;
+ sensor-position-pitch = <0>;
+ sensor-position-yaw = <180>;
+ led-flash-src = <&led_flash_rear>;
+ actuator-src = <&actuator_rear>;
+ ois-src = <&ois_rear>;
+ eeprom-src = <&eeprom_rear>;
+ cam_vio-supply = <&camera_vio_ldo>;
+ cam_vana-supply = <&camera_vana_ldo>;
+ cam_vdig-supply = <&camera_rear_ldo>;
+ cam_clk-supply = <&titan_top_gdsc>;
+ regulator-names = "cam_vio", "cam_vana", "cam_vdig",
+ "cam_clk";
+ rgltr-cntrl-support;
+ rgltr-min-voltage = <1800000 2850000 1352000 0>;
+ rgltr-max-voltage = <1800000 2850000 1352000 0>;
+ rgltr-load-current = <0 80000 105000 0>;
+ gpio-no-mux = <0>;
+ pinctrl-names = "cam_default", "cam_suspend";
+ pinctrl-0 = <&cam_sensor_mclk0_active
+ &cam_sensor_rear_active>;
+ pinctrl-1 = <&cam_sensor_mclk0_suspend
+ &cam_sensor_rear_suspend>;
+ gpios = <&tlmm 13 0>,
+ <&tlmm 30 0>;
+ gpio-reset = <1>;
+ gpio-req-tbl-num = <0 1>;
+ gpio-req-tbl-flags = <1 0>;
+ gpio-req-tbl-label = "CAMIF_MCLK0",
+ "CAM_RESET0";
+ sensor-mode = <0>;
+ cci-master = <0>;
+ status = "ok";
+ clocks = <&clock_camcc CAM_CC_MCLK0_CLK>;
+ clock-names = "cam_clk";
+ clock-cntl-level = "turbo";
+ clock-rates = <24000000>;
+ };
+
+ qcom,cam-sensor@1 {
+ cell-index = <1>;
+ compatible = "qcom,cam-sensor";
+ reg = <0x1>;
+ csiphy-sd-index = <1>;
+ sensor-position-roll = <270>;
+ sensor-position-pitch = <0>;
+ sensor-position-yaw = <180>;
+ led-flash-src = <&led_flash_rear_aux>;
+ actuator-src = <&actuator_rear_aux>;
+ eeprom-src = <&eeprom_rear_aux>;
+ cam_vio-supply = <&camera_vio_ldo>;
+ cam_vana-supply = <&camera_vana_ldo>;
+ cam_vdig-supply = <&camera_ldo>;
+ cam_clk-supply = <&titan_top_gdsc>;
+ regulator-names = "cam_vdig", "cam_vio", "cam_vana",
+ "cam_clk";
+ rgltr-cntrl-support;
+ rgltr-min-voltage = <1352000 1800000 2850000 0>;
+ rgltr-max-voltage = <1352000 1800000 2850000 0>;
+ rgltr-load-current = <105000 0 80000 0>;
+ gpio-no-mux = <0>;
+ pinctrl-names = "cam_default", "cam_suspend";
+ pinctrl-0 = <&cam_sensor_mclk1_active
+ &cam_sensor_rear2_active>;
+ pinctrl-1 = <&cam_sensor_mclk1_suspend
+ &cam_sensor_rear2_suspend>;
+ gpios = <&tlmm 14 0>,
+ <&tlmm 28 0>;
+ gpio-reset = <1>;
+ gpio-req-tbl-num = <0 1>;
+ gpio-req-tbl-flags = <1 0>;
+ gpio-req-tbl-label = "CAMIF_MCLK1",
+ "CAM_RESET1";
+ sensor-mode = <0>;
+ cci-master = <1>;
+ status = "ok";
+ clocks = <&clock_camcc CAM_CC_MCLK1_CLK>;
+ clock-names = "cam_clk";
+ clock-cntl-level = "turbo";
+ clock-rates = <24000000>;
+ };
+
+ qcom,cam-sensor@2 {
+ cell-index = <2>;
+ compatible = "qcom,cam-sensor";
+ reg = <0x02>;
+ csiphy-sd-index = <2>;
+ sensor-position-roll = <270>;
+ sensor-position-pitch = <0>;
+ sensor-position-yaw = <0>;
+ eeprom-src = <&eeprom_front>;
+ actuator-src = <&actuator_front>;
+ led-flash-src = <&led_flash_front>;
+ cam_vio-supply = <&camera_vio_ldo>;
+ cam_vana-supply = <&camera_vana_ldo>;
+ cam_vdig-supply = <&camera_ldo>;
+ cam_clk-supply = <&titan_top_gdsc>;
+ regulator-names = "cam_vdig", "cam_vio", "cam_vana",
+ "cam_clk";
+ rgltr-cntrl-support;
+ rgltr-min-voltage = <1352000 1800000 2850000 0>;
+ rgltr-max-voltage = <1352000 1800000 2850000 0>;
+ rgltr-load-current = <105000 0 80000 0>;
+ gpio-no-mux = <0>;
+ pinctrl-names = "cam_default", "cam_suspend";
+ pinctrl-0 = <&cam_sensor_mclk1_active
+ &cam_sensor_rear2_active>;
+ pinctrl-1 = <&cam_sensor_mclk1_suspend
+ &cam_sensor_rear2_suspend>;
+ gpios = <&tlmm 14 0>,
+ <&tlmm 28 0>;
+ gpio-reset = <1>;
+ gpio-req-tbl-num = <0 1>;
+ gpio-req-tbl-flags = <1 0>;
+ gpio-req-tbl-label = "CAMIF_MCLK1",
+ "CAM_RESET1";
+ sensor-mode = <0>;
+ cci-master = <1>;
+ status = "ok";
+ clocks = <&clock_camcc CAM_CC_MCLK1_CLK>;
+ clock-names = "cam_clk";
+ clock-cntl-level = "turbo";
+ clock-rates = <24000000>;
+ };
+};
diff --git a/arch/arm64/boot/dts/qcom/sda670-hdk.dtsi b/arch/arm64/boot/dts/qcom/sda670-hdk.dtsi
index 4daf8b4..eec80f6 100644
--- a/arch/arm64/boot/dts/qcom/sda670-hdk.dtsi
+++ b/arch/arm64/boot/dts/qcom/sda670-hdk.dtsi
@@ -11,11 +11,16 @@
*/
#include "sdm670-qrd.dtsi"
#include "sdm670-external-codec.dtsi"
+#include "sda670-camera-sensor-hdk.dtsi"
&dsi_dual_nt36850_truly_cmd_display {
/delete-property/ qcom,dsi-display-active;
};
+&qrd_batterydata {
+ #include "fg-gen3-batterydata-mlp466076-3250mah.dtsi"
+};
+
&dsi_hx8399_truly_cmd {
qcom,panel-supply-entries = <&dsi_panel_pwr_supply>;
qcom,mdss-dsi-bl-pmic-control-type = "bl_ctrl_wled";
@@ -30,3 +35,29 @@
&dsi_hx8399_truly_cmd_display {
qcom,dsi-display-active;
};
+
+&ufsphy_mem {
+ compatible = "qcom,ufs-phy-qmp-v3";
+
+ vdda-phy-supply = <&pm660l_l1>; /* 0.88v */
+ vdda-pll-supply = <&pm660_l1>; /* 1.2v */
+ vdda-phy-max-microamp = <62900>;
+ vdda-pll-max-microamp = <18300>;
+
+ status = "ok";
+};
+
+&ufshc_mem {
+ vdd-hba-supply = <&ufs_phy_gdsc>;
+ vdd-hba-fixed-regulator;
+ vcc-supply = <&pm660l_l4>;
+ vcc-voltage-level = <2960000 2960000>;
+ vccq2-supply = <&pm660_l8>;
+ vcc-max-microamp = <600000>;
+ vccq2-max-microamp = <600000>;
+
+ qcom,vddp-ref-clk-supply = <&pm660_l1>;
+ qcom,vddp-ref-clk-max-microamp = <100>;
+
+ status = "ok";
+};
diff --git a/arch/arm64/boot/dts/qcom/sdm429-cdp-overlay.dts b/arch/arm64/boot/dts/qcom/sdm429-cdp-overlay.dts
index c55c2a5..5f0db81 100644
--- a/arch/arm64/boot/dts/qcom/sdm429-cdp-overlay.dts
+++ b/arch/arm64/boot/dts/qcom/sdm429-cdp-overlay.dts
@@ -14,9 +14,6 @@
/dts-v1/;
/plugin/;
-#include <dt-bindings/gpio/gpio.h>
-#include <dt-bindings/clock/msm-clocks-8953.h>
-#include <dt-bindings/interrupt-controller/arm-gic.h>
#include "sdm429-cdp.dtsi"
/ {
diff --git a/arch/arm64/boot/dts/qcom/sdm429-mtp-overlay.dts b/arch/arm64/boot/dts/qcom/sdm429-mtp-overlay.dts
index 7735b35..571f0fc 100644
--- a/arch/arm64/boot/dts/qcom/sdm429-mtp-overlay.dts
+++ b/arch/arm64/boot/dts/qcom/sdm429-mtp-overlay.dts
@@ -14,9 +14,6 @@
/dts-v1/;
/plugin/;
-#include <dt-bindings/gpio/gpio.h>
-#include <dt-bindings/clock/msm-clocks-8953.h>
-#include <dt-bindings/interrupt-controller/arm-gic.h>
#include "sdm429-mtp.dtsi"
/ {
diff --git a/arch/arm64/boot/dts/qcom/sdm429-qrd-overlay.dts b/arch/arm64/boot/dts/qcom/sdm429-qrd-overlay.dts
index fae68c9..8e12295 100644
--- a/arch/arm64/boot/dts/qcom/sdm429-qrd-overlay.dts
+++ b/arch/arm64/boot/dts/qcom/sdm429-qrd-overlay.dts
@@ -14,9 +14,6 @@
/dts-v1/;
/plugin/;
-#include <dt-bindings/gpio/gpio.h>
-#include <dt-bindings/clock/msm-clocks-8953.h>
-#include <dt-bindings/interrupt-controller/arm-gic.h>
#include "sdm429-qrd.dtsi"
/ {
diff --git a/arch/arm64/boot/dts/qcom/sdm439-camera-sensor-cdp.dtsi b/arch/arm64/boot/dts/qcom/sdm439-camera-sensor-cdp.dtsi
index 5e2c740..eae8c56 100644
--- a/arch/arm64/boot/dts/qcom/sdm439-camera-sensor-cdp.dtsi
+++ b/arch/arm64/boot/dts/qcom/sdm439-camera-sensor-cdp.dtsi
@@ -11,6 +11,8 @@
* GNU General Public License for more details.
*/
+#include <dt-bindings/clock/msm-clocks-8952.h>
+
&cci {
actuator0: qcom,actuator@0 {
cell-index = <0>;
diff --git a/arch/arm64/boot/dts/qcom/sdm439-camera-sensor-mtp.dtsi b/arch/arm64/boot/dts/qcom/sdm439-camera-sensor-mtp.dtsi
index 5e2c740..eae8c56 100644
--- a/arch/arm64/boot/dts/qcom/sdm439-camera-sensor-mtp.dtsi
+++ b/arch/arm64/boot/dts/qcom/sdm439-camera-sensor-mtp.dtsi
@@ -11,6 +11,8 @@
* GNU General Public License for more details.
*/
+#include <dt-bindings/clock/msm-clocks-8952.h>
+
&cci {
actuator0: qcom,actuator@0 {
cell-index = <0>;
diff --git a/arch/arm64/boot/dts/qcom/sdm439-camera-sensor-qrd.dtsi b/arch/arm64/boot/dts/qcom/sdm439-camera-sensor-qrd.dtsi
index c2c9c79..ef0e977 100644
--- a/arch/arm64/boot/dts/qcom/sdm439-camera-sensor-qrd.dtsi
+++ b/arch/arm64/boot/dts/qcom/sdm439-camera-sensor-qrd.dtsi
@@ -11,6 +11,8 @@
* GNU General Public License for more details.
*/
+#include <dt-bindings/clock/msm-clocks-8952.h>
+
&cci {
actuator0: qcom,actuator@0 {
cell-index = <0>;
diff --git a/arch/arm64/boot/dts/qcom/sdm439-cdp-overlay.dts b/arch/arm64/boot/dts/qcom/sdm439-cdp-overlay.dts
index 5e86672..87239b9 100644
--- a/arch/arm64/boot/dts/qcom/sdm439-cdp-overlay.dts
+++ b/arch/arm64/boot/dts/qcom/sdm439-cdp-overlay.dts
@@ -14,9 +14,6 @@
/dts-v1/;
/plugin/;
-#include <dt-bindings/gpio/gpio.h>
-#include <dt-bindings/clock/msm-clocks-8953.h>
-#include <dt-bindings/interrupt-controller/arm-gic.h>
#include "sdm439-cdp.dtsi"
/ {
diff --git a/arch/arm64/boot/dts/qcom/sdm439-cdp.dtsi b/arch/arm64/boot/dts/qcom/sdm439-cdp.dtsi
index 6ecd0dd..d1a8a48 100644
--- a/arch/arm64/boot/dts/qcom/sdm439-cdp.dtsi
+++ b/arch/arm64/boot/dts/qcom/sdm439-cdp.dtsi
@@ -233,7 +233,7 @@
&dsi_hx8399c_hd_vid {
/delete-property/ qcom,mdss-dsi-panel-timings;
- qcom,mdss-dsi-panel-timings-phy-12nm = [08 06 0a 02 00 04 02 08];
+ qcom,mdss-dsi-panel-timings-phy-12nm = [09 06 0a 02 00 05 02 08];
qcom,panel-supply-entries = <&dsi_panel_pwr_supply>;
qcom,mdss-dsi-bl-pmic-control-type = "bl_ctrl_pwm";
qcom,mdss-dsi-bl-pmic-pwm-frequency = <100>;
diff --git a/arch/arm64/boot/dts/qcom/sdm439-external-codec-mtp-overlay.dts b/arch/arm64/boot/dts/qcom/sdm439-external-codec-mtp-overlay.dts
index 468f514..37741b2 100644
--- a/arch/arm64/boot/dts/qcom/sdm439-external-codec-mtp-overlay.dts
+++ b/arch/arm64/boot/dts/qcom/sdm439-external-codec-mtp-overlay.dts
@@ -14,10 +14,6 @@
/dts-v1/;
/plugin/;
-#include <dt-bindings/gpio/gpio.h>
-#include <dt-bindings/clock/msm-clocks-8953.h>
-#include <dt-bindings/interrupt-controller/arm-gic.h>
-
#include "sdm439-mtp.dtsi"
#include "sdm439-external-codec.dtsi"
diff --git a/arch/arm64/boot/dts/qcom/sdm439-mtp-overlay.dts b/arch/arm64/boot/dts/qcom/sdm439-mtp-overlay.dts
index 8b6c6fb..a7c5f4e 100644
--- a/arch/arm64/boot/dts/qcom/sdm439-mtp-overlay.dts
+++ b/arch/arm64/boot/dts/qcom/sdm439-mtp-overlay.dts
@@ -14,9 +14,6 @@
/dts-v1/;
/plugin/;
-#include <dt-bindings/gpio/gpio.h>
-#include <dt-bindings/clock/msm-clocks-8953.h>
-#include <dt-bindings/interrupt-controller/arm-gic.h>
#include "sdm439-mtp.dtsi"
/ {
diff --git a/arch/arm64/boot/dts/qcom/sdm439-mtp.dtsi b/arch/arm64/boot/dts/qcom/sdm439-mtp.dtsi
index 7a61a7a..5580762 100644
--- a/arch/arm64/boot/dts/qcom/sdm439-mtp.dtsi
+++ b/arch/arm64/boot/dts/qcom/sdm439-mtp.dtsi
@@ -208,7 +208,7 @@
&dsi_hx8399c_hd_vid {
/delete-property/ qcom,mdss-dsi-panel-timings;
- qcom,mdss-dsi-panel-timings-phy-12nm = [08 06 0a 02 00 04 02 08];
+ qcom,mdss-dsi-panel-timings-phy-12nm = [09 06 0a 02 00 05 02 08];
qcom,panel-supply-entries = <&dsi_panel_pwr_supply>;
qcom,mdss-dsi-bl-pmic-control-type = "bl_ctrl_pwm";
qcom,mdss-dsi-bl-pmic-pwm-frequency = <100>;
@@ -565,16 +565,25 @@
bias-disable; /* no-pull */
};
};
+
+ pmi632_ctm {
+ /* Disable GPIO1 for h/w base mitigation */
+ pmi632_ctm_default: pmi632_ctm_default {
+ pins = "gpio1";
+ bias-high-impedance; /* disable the GPIO */
+ bias-disable; /* no-pull */
+ };
+ };
};
&tlmm {
smb_int_default: smb_int_default {
mux {
- pins = "gpio59";
+ pins = "gpio61";
function = "gpio";
};
config {
- pins = "gpio59";
+ pins = "gpio61";
drive-strength = <2>;
bias-pull-up;
input-enable;
@@ -585,27 +594,31 @@
&smb1355_0 {
pinctrl-names = "default";
pinctrl-0 = <&smb_int_default
- &smb_en_default &pmi632_sense_default>;
+ &smb_en_default &pmi632_sense_default &pmi632_ctm_default>;
interrupt-parent = <&tlmm>;
- interrupts = <59 IRQ_TYPE_LEVEL_LOW>;
+ interrupts = <61 IRQ_TYPE_LEVEL_LOW>;
smb1355_charger_0: qcom,smb1355-charger@1000 {
status ="ok";
/delete-property/ io-channels;
/delete-property/ io-channels-names;
qcom,parallel-mode = <1>;
+ qcom,disable-ctm;
+ qcom,hw-die-temp-mitigation;
};
};
&smb1355_1 {
pinctrl-names = "default";
pinctrl-0 = <&smb_int_default
- &smb_en_default &pmi632_sense_default>;
+ &smb_en_default &pmi632_sense_default &pmi632_ctm_default>;
interrupt-parent = <&tlmm>;
- interrupts = <59 IRQ_TYPE_LEVEL_LOW>;
+ interrupts = <61 IRQ_TYPE_LEVEL_LOW>;
smb1355_charger_1: qcom,smb1355-charger@1000 {
status ="ok";
/delete-property/ io-channels;
/delete-property/ io-channels-names;
qcom,parallel-mode = <1>;
+ qcom,disable-ctm;
+ qcom,hw-die-temp-mitigation;
};
};
diff --git a/arch/arm64/boot/dts/qcom/sdm439-pmi632.dtsi b/arch/arm64/boot/dts/qcom/sdm439-pmi632.dtsi
index 2bfab8f..9c4120c 100644
--- a/arch/arm64/boot/dts/qcom/sdm439-pmi632.dtsi
+++ b/arch/arm64/boot/dts/qcom/sdm439-pmi632.dtsi
@@ -134,73 +134,151 @@
thermal-governor = "step_wise";
trips {
- batt_trip1: batt-trip1 {
- temperature = <41000>;
- hysteresis = <2000>;
- type = "passive";
- };
- cpus_trip: cpus-trip {
+ quiet_modem_439_trip1: quiet-modem-trip0 {
temperature = <44000>;
- hysteresis = <0>;
- type = "passive";
- };
- batt_trip2: batt-trip2 {
- temperature = <45000>;
hysteresis = <4000>;
type = "passive";
};
- gpu_trip: gpu-trip {
+ quiet_modem_439_trip2: quiet-modem-trip1 {
+ temperature = <46000>;
+ hysteresis = <4000>;
+ type = "passive";
+ };
+ quiet_cpus_439_trip: quiet-cpus-trip {
+ temperature = <48000>;
+ hysteresis = <0>;
+ type = "passive";
+ };
+ quiet_modem_439_trip3: quiet-modem-trip2 {
+ temperature = <48000>;
+ hysteresis = <2000>;
+ type = "passive";
+ };
+ quiet_batt_439_trip1: quiet-batt-trip1 {
+ temperature = <48000>;
+ hysteresis = <4000>;
+ type = "passive";
+ };
+ quiet_gpu_439_trip: quiet-gpu-trip {
temperature = <50000>;
hysteresis = <0>;
type = "passive";
};
+ quiet_batt_439_trip2: quiet-batt-trip2 {
+ temperature = <50000>;
+ hysteresis = <2000>;
+ type = "passive";
+ };
+ quiet_batt_439_trip3: quiet-batt-trip3 {
+ temperature = <52000>;
+ hysteresis = <2000>;
+ type = "passive";
+ };
+
+ quiet_batt_439_trip4: quiet-batt-trip4 {
+ temperature = <54000>;
+ hysteresis = <2000>;
+ type = "passive";
+ };
+ quiet_modem_439_trip4: quiet-modem-trip3 {
+ temperature = <55000>;
+ hysteresis = <5000>;
+ type = "passive";
+ };
+ quiet_batt_439_trip5: quiet-batt-trip5 {
+ temperature = <56000>;
+ hysteresis = <2000>;
+ type = "passive";
+ };
};
cooling-maps {
skin_cpu0 {
- trip = <&cpus_trip>;
- /* throttle from fmax to 1094400KHz */
- cooling-device = <&CPU0 THERMAL_NO_LIMIT 5>;
+ trip = <&quiet_cpus_439_trip>;
+ /* throttle from fmax to 1497600KHz */
+ cooling-device = <&CPU0 THERMAL_NO_LIMIT
+ (THERMAL_MAX_LIMIT-3)>;
};
skin_cpu1 {
- trip = <&cpus_trip>;
- cooling-device = <&CPU1 THERMAL_NO_LIMIT 5>;
+ trip = <&quiet_cpus_439_trip>;
+ cooling-device = <&CPU1 THERMAL_NO_LIMIT
+ (THERMAL_MAX_LIMIT-3)>;
};
skin_cpu2 {
- trip = <&cpus_trip>;
- cooling-device = <&CPU2 THERMAL_NO_LIMIT 5>;
+ trip = <&quiet_cpus_439_trip>;
+ cooling-device = <&CPU2 THERMAL_NO_LIMIT
+ (THERMAL_MAX_LIMIT-3)>;
};
skin_cpu3 {
- trip = <&cpus_trip>;
- cooling-device = <&CPU3 THERMAL_NO_LIMIT 5>;
+ trip = <&quiet_cpus_439_trip>;
+ cooling-device = <&CPU3 THERMAL_NO_LIMIT
+ (THERMAL_MAX_LIMIT-3)>;
};
skin_cpu4 {
- trip = <&cpus_trip>;
- cooling-device = <&CPU4 THERMAL_NO_LIMIT 3>;
+ trip = <&quiet_cpus_439_trip>;
+ /* throttle from fmax to 1171200KHz */
+ cooling-device = <&CPU4 THERMAL_NO_LIMIT
+ (THERMAL_MAX_LIMIT-3)>;
};
skin_cpu5 {
- trip = <&cpus_trip>;
- cooling-device = <&CPU5 THERMAL_NO_LIMIT 3>;
+ trip = <&quiet_cpus_439_trip>;
+ cooling-device = <&CPU5 THERMAL_NO_LIMIT
+ (THERMAL_MAX_LIMIT-3)>;
};
skin_cpu6 {
- trip = <&cpus_trip>;
- cooling-device = <&CPU6 THERMAL_NO_LIMIT 3>;
+ trip = <&quiet_cpus_439_trip>;
+ cooling-device = <&CPU6 THERMAL_NO_LIMIT
+ (THERMAL_MAX_LIMIT-3)>;
};
skin_cpu7 {
- trip = <&cpus_trip>;
- cooling-device = <&CPU7 THERMAL_NO_LIMIT 3>;
+ trip = <&quiet_cpus_439_trip>;
+ cooling-device = <&CPU7 THERMAL_NO_LIMIT
+ (THERMAL_MAX_LIMIT-3)>;
};
skin_gpu {
- trip = <&gpu_trip>;
- /* throttle from fmax to 375000000Hz */
- cooling-device = <&msm_gpu THERMAL_NO_LIMIT 2>;
+ trip = <&quiet_gpu_439_trip>;
+ /* throttle from fmax to 510000000Hz */
+ cooling-device = <&msm_gpu THERMAL_NO_LIMIT
+ (THERMAL_MAX_LIMIT-2)>;
+ };
+ modem_proc_lvl1 {
+ trip = <&quiet_modem_439_trip1>;
+ cooling-device = <&modem_proc 1 1>;
+ };
+ modem_proc_lvl2 {
+ trip = <&quiet_modem_439_trip4>;
+ cooling-device = <&modem_proc 3 3>;
+ };
+ modem_lvl1 {
+ trip = <&quiet_modem_439_trip2>;
+ cooling-device = <&modem_pa 1 1>;
+ };
+ modem_lvl2 {
+ trip = <&quiet_modem_439_trip3>;
+ cooling-device = <&modem_pa 2 2>;
+ };
+ modem_lvl3 {
+ trip = <&quiet_modem_439_trip4>;
+ cooling-device = <&modem_pa 3 3>;
};
battery_lvl1 {
- trip = <&batt_trip1>;
- cooling-device = <&pmi632_charger 4 4>;
+ trip = <&quiet_batt_439_trip1>;
+ cooling-device = <&pmi632_charger 1 1>;
};
battery_lvl2 {
- trip = <&batt_trip2>;
+ trip = <&quiet_batt_439_trip2>;
+ cooling-device = <&pmi632_charger 2 2>;
+ };
+ battery_lvl3 {
+ trip = <&quiet_batt_439_trip3>;
+ cooling-device = <&pmi632_charger 3 3>;
+ };
+ battery_lvl4 {
+ trip = <&quiet_batt_439_trip4>;
+ cooling-device = <&pmi632_charger 4 4>;
+ };
+ battery_lvl5 {
+ trip = <&quiet_batt_439_trip5>;
cooling-device = <&pmi632_charger 5 5>;
};
};
diff --git a/arch/arm64/boot/dts/qcom/sdm439-qrd-overlay.dts b/arch/arm64/boot/dts/qcom/sdm439-qrd-overlay.dts
index ed6b2ad..46a7856 100644
--- a/arch/arm64/boot/dts/qcom/sdm439-qrd-overlay.dts
+++ b/arch/arm64/boot/dts/qcom/sdm439-qrd-overlay.dts
@@ -14,9 +14,6 @@
/dts-v1/;
/plugin/;
- #include <dt-bindings/gpio/gpio.h>
- #include <dt-bindings/clock/msm-clocks-8953.h>
- #include <dt-bindings/interrupt-controller/arm-gic.h>
#include "sdm439-qrd.dtsi"
/ {
diff --git a/arch/arm64/boot/dts/qcom/sdm439-qrd.dts b/arch/arm64/boot/dts/qcom/sdm439-qrd.dts
index b8a9f2b..4a2fbff 100644
--- a/arch/arm64/boot/dts/qcom/sdm439-qrd.dts
+++ b/arch/arm64/boot/dts/qcom/sdm439-qrd.dts
@@ -22,10 +22,3 @@
qcom,board-id = <0xb 2>;
qcom,pmic-id = <0x010016 0x25 0x0 0x0>;
};
-
-&pmi632_vadc {
- chan@4a {
- qcom,scale-function = <22>;
- };
-};
-
diff --git a/arch/arm64/boot/dts/qcom/sdm439-qrd.dtsi b/arch/arm64/boot/dts/qcom/sdm439-qrd.dtsi
index 5097b7f..a3c5b1f 100644
--- a/arch/arm64/boot/dts/qcom/sdm439-qrd.dtsi
+++ b/arch/arm64/boot/dts/qcom/sdm439-qrd.dtsi
@@ -115,7 +115,7 @@
pinctrl-0 = <&sdc2_clk_on &sdc2_cmd_on &sdc2_data_on &sdc2_cd_on>;
pinctrl-1 = <&sdc2_clk_off &sdc2_cmd_off &sdc2_data_off>;
- cd-gpios = <&tlmm 67 0x1>;
+ cd-gpios = <&tlmm 67 0x0>;
qcom,clk-rates = <400000 20000000 25000000 50000000 100000000
200000000>;
@@ -141,6 +141,24 @@
gpio-key,wakeup;
};
};
+
+ fpc1020 {
+ compatible = "fpc,fpc1020";
+ interrupt-parent = <&tlmm>;
+ interrupts = <48 0>;
+ fpc,gpio_rst = <&tlmm 124 0x0>;
+ fpc,gpio_irq = <&tlmm 48 0>;
+ vcc_spi-supply = <&pm8953_l5>;
+ vdd_io-supply = <&pm8953_l5>;
+ vdd_ana-supply = <&pm8953_l5>;
+ fpc,enable-on-boot;
+ pinctrl-names = "fpc1020_reset_reset",
+ "fpc1020_reset_active",
+ "fpc1020_irq_active";
+ pinctrl-0 = <&fpc_reset_low>;
+ pinctrl-1 = <&fpc_reset_high>;
+ pinctrl-2 = <&fpc_int_low>;
+ };
};
&tlmm {
@@ -305,7 +323,7 @@
&dsi_hx8399c_hd_vid {
/delete-property/ qcom,mdss-dsi-panel-timings;
- qcom,mdss-dsi-panel-timings-phy-12nm = [08 06 0a 02 00 04 02 08];
+ qcom,mdss-dsi-panel-timings-phy-12nm = [09 06 0a 02 00 05 02 08];
qcom,panel-supply-entries = <&dsi_panel_pwr_supply>;
qcom,mdss-dsi-bl-pmic-control-type = "bl_ctrl_pwm";
qcom,mdss-dsi-bl-pmic-pwm-frequency = <100>;
@@ -330,6 +348,12 @@
#include "smb1355.dtsi"
};
+&pmi632_vadc {
+ chan@4a {
+ qcom,scale-function = <22>;
+ };
+};
+
&pmi632_gpios {
smb_en {
smb_en_default: smb_en_default {
@@ -347,16 +371,25 @@
bias-disable; /* no-pull */
};
};
+
+ pmi632_ctm {
+ /* Disable GPIO1 for h/w base mitigation */
+ pmi632_ctm_default: pmi632_ctm_default {
+ pins = "gpio1";
+ bias-high-impedance; /* disable the GPIO */
+ bias-disable; /* no-pull */
+ };
+ };
};
&tlmm {
smb_int_default: smb_int_default {
mux {
- pins = "gpio59";
+ pins = "gpio61";
function = "gpio";
};
config {
- pins = "gpio59";
+ pins = "gpio61";
drive-strength = <2>;
bias-pull-up;
input-enable;
@@ -367,27 +400,31 @@
&smb1355_0 {
pinctrl-names = "default";
pinctrl-0 = <&smb_int_default
- &smb_en_default &pmi632_sense_default>;
+ &smb_en_default &pmi632_sense_default &pmi632_ctm_default>;
interrupt-parent = <&tlmm>;
- interrupts = <59 IRQ_TYPE_LEVEL_LOW>;
+ interrupts = <61 IRQ_TYPE_LEVEL_LOW>;
smb1355_charger_0: qcom,smb1355-charger@1000 {
status ="ok";
/delete-property/ io-channels;
/delete-property/ io-channels-names;
qcom,parallel-mode = <1>;
+ qcom,disable-ctm;
+ qcom,hw-die-temp-mitigation;
};
};
&smb1355_1 {
pinctrl-names = "default";
pinctrl-0 = <&smb_int_default
- &smb_en_default &pmi632_sense_default>;
+ &smb_en_default &pmi632_sense_default &pmi632_ctm_default>;
interrupt-parent = <&tlmm>;
- interrupts = <59 IRQ_TYPE_LEVEL_LOW>;
+ interrupts = <61 IRQ_TYPE_LEVEL_LOW>;
smb1355_charger_1: qcom,smb1355-charger@1000 {
status ="ok";
/delete-property/ io-channels;
/delete-property/ io-channels-names;
qcom,parallel-mode = <1>;
+ qcom,disable-ctm;
+ qcom,hw-die-temp-mitigation;
};
};
diff --git a/arch/arm64/boot/dts/qcom/sdm439-rcm-overlay.dts b/arch/arm64/boot/dts/qcom/sdm439-rcm-overlay.dts
new file mode 100644
index 0000000..be0de06
--- /dev/null
+++ b/arch/arm64/boot/dts/qcom/sdm439-rcm-overlay.dts
@@ -0,0 +1,22 @@
+/*
+ * Copyright (c) 2018, The Linux Foundation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ */
+
+/dts-v1/;
+/plugin/;
+
+#include "sdm439-rcm.dtsi"
+
+/ {
+ model = "RCM";
+ qcom,board-id = <21 1>;
+};
diff --git a/arch/arm64/boot/dts/qcom/sdm439-rcm.dts b/arch/arm64/boot/dts/qcom/sdm439-rcm.dts
new file mode 100644
index 0000000..71d02a0
--- /dev/null
+++ b/arch/arm64/boot/dts/qcom/sdm439-rcm.dts
@@ -0,0 +1,24 @@
+/*
+ * Copyright (c) 2018, The Linux Foundation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ */
+
+/dts-v1/;
+
+#include "sdm439.dtsi"
+#include "sdm439-rcm.dtsi"
+
+/ {
+ model = "Qualcomm Technologies, Inc. SDM439 RCM";
+ compatible = "qcom,sdm439-cdp", "qcom,sdm439", "qcom,cdp";
+ qcom,board-id = <21 1>;
+ qcom,pmic-id = <0x010016 0x25 0x0 0x0>;
+};
diff --git a/arch/arm64/boot/dts/qcom/sdm439-rcm.dtsi b/arch/arm64/boot/dts/qcom/sdm439-rcm.dtsi
new file mode 100644
index 0000000..4ba4c00
--- /dev/null
+++ b/arch/arm64/boot/dts/qcom/sdm439-rcm.dtsi
@@ -0,0 +1,14 @@
+/*
+ * Copyright (c) 2018, The Linux Foundation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ */
+
+#include "sdm439-cdp.dtsi"
diff --git a/arch/arm64/boot/dts/qcom/sdm439-regulator.dtsi b/arch/arm64/boot/dts/qcom/sdm439-regulator.dtsi
index b97e66e..414e8fe 100644
--- a/arch/arm64/boot/dts/qcom/sdm439-regulator.dtsi
+++ b/arch/arm64/boot/dts/qcom/sdm439-regulator.dtsi
@@ -378,12 +378,12 @@
reg = <0x2000 0x100>;
regulator-name = "pm8953_s5";
regulator-min-microvolt = <490000>;
- regulator-max-microvolt = <910000>;
+ regulator-max-microvolt = <960000>;
pm8953_s5_limit: avs-limit-regulator {
regulator-name = "pm8953_s5_avs_limit";
regulator-min-microvolt = <490000>;
- regulator-max-microvolt = <910000>;
+ regulator-max-microvolt = <960000>;
};
};
};
@@ -421,7 +421,7 @@
regulator-max-microvolt = <5>;
qcom,cpr-fuse-corners = <3>;
- qcom,cpr-voltage-ceiling = <760000 795000 910000>;
+ qcom,cpr-voltage-ceiling = <810000 845000 960000>;
qcom,cpr-voltage-floor = <700000 700000 790000>;
vdd-apc-supply = <&pm8953_s5>;
mem-acc-supply = <&apc_mem_acc_vreg>;
@@ -472,11 +472,18 @@
qcom,cpr-fuse-version-map =
/* <Speed-bin pvs-version cpr-rev ... ... ...> */
<(-1) (-1) ( 0) (-1) (-1) (-1)>,
+ <(-1) (-1) ( 1) (-1) (-1) (-1)>,
<(-1) (-1) (-1) (-1) (-1) (-1)>;
qcom,cpr-quotient-adjustment =
- <66 77 66>, /* SVSP_30mV, NOM_35mV, TUR_30mV */
- <0 0 0>;
+ <66 77 66>, /* SVSP/NOM/TUR:30/35/30 mV */
+ <(-74) (-57) (-30)>, /* SVSP/NOM/TUR:-34/-26/-14 mV */
+ <0 0 0>;
+
+ qcom,cpr-floor-to-ceiling-max-range =
+ <50000 50000 50000 65000 65000>,
+ <50000 50000 50000 65000 65000>,
+ <50000 50000 50000 65000 65000>;
qcom,cpr-voltage-ceiling-override =
<(-1) (-1) 810000 845000 885000 960000 960000>;
diff --git a/arch/arm64/boot/dts/qcom/sdm439.dtsi b/arch/arm64/boot/dts/qcom/sdm439.dtsi
index 1448a65..be05b6e 100644
--- a/arch/arm64/boot/dts/qcom/sdm439.dtsi
+++ b/arch/arm64/boot/dts/qcom/sdm439.dtsi
@@ -639,3 +639,13 @@
&mdss_mdp {
qcom,vbif-settings = <0xd0 0x20>;
};
+
+&thermal_zones {
+ hexa-cpu-max-step {
+ trips {
+ cpu-trip {
+ temperature = <95000>;
+ };
+ };
+ };
+};
diff --git a/arch/arm64/boot/dts/qcom/sdm450-pmi632-mtp-s3.dtsi b/arch/arm64/boot/dts/qcom/sdm450-pmi632-mtp-s3.dtsi
index 07d2e08..5db626b 100644
--- a/arch/arm64/boot/dts/qcom/sdm450-pmi632-mtp-s3.dtsi
+++ b/arch/arm64/boot/dts/qcom/sdm450-pmi632-mtp-s3.dtsi
@@ -68,6 +68,15 @@
bias-disable; /* no-pull */
};
};
+
+ pmi632_ctm {
+ /* Disable GPIO1 for h/w base mitigation */
+ pmi632_ctm_default: pmi632_ctm_default {
+ pins = "gpio1";
+ bias-high-impedance; /* disable the GPIO */
+ bias-disable; /* no-pull */
+ };
+ };
};
&tlmm {
@@ -88,7 +97,7 @@
&smb1355_0 {
pinctrl-names = "default";
pinctrl-0 = <&smb_int_default
- &smb_en_default &pmi632_sense_default>;
+ &smb_en_default &pmi632_sense_default &pmi632_ctm_default>;
interrupt-parent = <&tlmm>;
interrupts = <59 IRQ_TYPE_LEVEL_LOW>;
smb1355_charger_0: qcom,smb1355-charger@1000 {
@@ -96,13 +105,15 @@
/delete-property/ io-channels;
/delete-property/ io-channels-names;
qcom,parallel-mode = <1>;
+ qcom,disable-ctm;
+ qcom,hw-die-temp-mitigation;
};
};
&smb1355_1 {
pinctrl-names = "default";
pinctrl-0 = <&smb_int_default
- &smb_en_default &pmi632_sense_default>;
+ &smb_en_default &pmi632_sense_default &pmi632_ctm_default>;
interrupt-parent = <&tlmm>;
interrupts = <59 IRQ_TYPE_LEVEL_LOW>;
smb1355_charger_1: qcom,smb1355-charger@1000 {
@@ -110,5 +121,7 @@
/delete-property/ io-channels;
/delete-property/ io-channels-names;
qcom,parallel-mode = <1>;
+ qcom,disable-ctm;
+ qcom,hw-die-temp-mitigation;
};
};
diff --git a/arch/arm64/boot/dts/qcom/sdm450-qrd-sku4.dtsi b/arch/arm64/boot/dts/qcom/sdm450-qrd-sku4.dtsi
index a2bd5cd..40fdb91 100644
--- a/arch/arm64/boot/dts/qcom/sdm450-qrd-sku4.dtsi
+++ b/arch/arm64/boot/dts/qcom/sdm450-qrd-sku4.dtsi
@@ -198,6 +198,15 @@
bias-disable; /* no-pull */
};
};
+
+ pmi632_ctm {
+ /* Disable GPIO1 for h/w base mitigation */
+ pmi632_ctm_default: pmi632_ctm_default {
+ pins = "gpio1";
+ bias-high-impedance; /* disable the GPIO */
+ bias-disable; /* no-pull */
+ };
+ };
};
&tlmm {
@@ -218,7 +227,7 @@
&smb1355_0 {
pinctrl-names = "default";
pinctrl-0 = <&smb_int_default
- &smb_en_default &pmi632_sense_default>;
+ &smb_en_default &pmi632_sense_default &pmi632_ctm_default>;
interrupt-parent = <&tlmm>;
interrupts = <59 IRQ_TYPE_LEVEL_LOW>;
smb1355_charger_0: qcom,smb1355-charger@1000 {
@@ -226,13 +235,15 @@
/delete-property/ io-channels;
/delete-property/ io-channels-names;
qcom,parallel-mode = <1>;
+ qcom,disable-ctm;
+ qcom,hw-die-temp-mitigation;
};
};
&smb1355_1 {
pinctrl-names = "default";
pinctrl-0 = <&smb_int_default
- &smb_en_default &pmi632_sense_default>;
+ &smb_en_default &pmi632_sense_default &pmi632_ctm_default>;
interrupt-parent = <&tlmm>;
interrupts = <59 IRQ_TYPE_LEVEL_LOW>;
smb1355_charger_1: qcom,smb1355-charger@1000 {
@@ -240,5 +251,7 @@
/delete-property/ io-channels;
/delete-property/ io-channels-names;
qcom,parallel-mode = <1>;
+ qcom,disable-ctm;
+ qcom,hw-die-temp-mitigation;
};
};
diff --git a/arch/arm64/boot/dts/qcom/sdm632.dtsi b/arch/arm64/boot/dts/qcom/sdm632.dtsi
index 4bc1c67..ee2476e 100644
--- a/arch/arm64/boot/dts/qcom/sdm632.dtsi
+++ b/arch/arm64/boot/dts/qcom/sdm632.dtsi
@@ -1087,15 +1087,15 @@
qcom,gpu-pwrlevel@6 {
reg = <6>;
qcom,gpu-freq = <216000000>;
- qcom,bus-freq = <1>;
- qcom,bus-min = <1>;
+ qcom,bus-freq = <3>;
+ qcom,bus-min = <2>;
qcom,bus-max = <4>;
};
qcom,gpu-pwrlevel@7 {
reg = <7>;
qcom,gpu-freq = <133300000>;
- qcom,bus-freq = <1>;
+ qcom,bus-freq = <3>;
qcom,bus-min = <1>;
qcom,bus-max = <4>;
};
diff --git a/arch/arm64/boot/dts/qcom/sdm670-cdp.dtsi b/arch/arm64/boot/dts/qcom/sdm670-cdp.dtsi
index 00a1498..95fb25a 100644
--- a/arch/arm64/boot/dts/qcom/sdm670-cdp.dtsi
+++ b/arch/arm64/boot/dts/qcom/sdm670-cdp.dtsi
@@ -38,6 +38,8 @@
qcom,vddp-ref-clk-supply = <&pm660_l1>;
qcom,vddp-ref-clk-max-microamp = <100>;
+ force-ufshc-probe;
+
status = "ok";
};
diff --git a/arch/arm64/boot/dts/qcom/sdm670-vidc.dtsi b/arch/arm64/boot/dts/qcom/sdm670-vidc.dtsi
index a0b4a22..f5e9489 100644
--- a/arch/arm64/boot/dts/qcom/sdm670-vidc.dtsi
+++ b/arch/arm64/boot/dts/qcom/sdm670-vidc.dtsi
@@ -129,15 +129,19 @@
/* Clocks */
clock-names = "core_clk", "iface_clk", "bus_clk",
- "core0_clk", "core0_bus_clk";
+ "core0_clk", "core0_bus_clk", "core1_clk",
+ "core1_bus_clk";
clocks = <&clock_videocc VIDEO_CC_VENUS_CTL_CORE_CLK>,
<&clock_videocc VIDEO_CC_VENUS_AHB_CLK>,
<&clock_videocc VIDEO_CC_VENUS_CTL_AXI_CLK>,
<&clock_videocc VIDEO_CC_VCODEC0_CORE_CLK>,
- <&clock_videocc VIDEO_CC_VCODEC0_AXI_CLK>;
+ <&clock_videocc VIDEO_CC_VCODEC0_AXI_CLK>,
+ <&clock_videocc VIDEO_CC_VCODEC1_CORE_CLK>,
+ <&clock_videocc VIDEO_CC_VCODEC1_AXI_CLK>;
qcom,proxy-clock-names = "core_clk", "iface_clk",
- "bus_clk", "core0_clk", "core0_bus_clk";
- qcom,clock-configs = <0x1 0x0 0x0 0x1 0x0>;
+ "bus_clk", "core0_clk", "core0_bus_clk",
+ "core1_clk", "core1_bus_clk";
+ qcom,clock-configs = <0x1 0x0 0x0 0x1 0x0 0x4 0x4>;
qcom,allowed-clock-rates = <100000000 200000000 330000000
364700000>;
diff --git a/arch/arm64/boot/dts/qcom/sdm670.dtsi b/arch/arm64/boot/dts/qcom/sdm670.dtsi
index 8ba878b..c962b42 100644
--- a/arch/arm64/boot/dts/qcom/sdm670.dtsi
+++ b/arch/arm64/boot/dts/qcom/sdm670.dtsi
@@ -1881,7 +1881,7 @@
"rx_lane0_sync_clk";
clocks =
<&clock_gcc GCC_UFS_PHY_AXI_HW_CTL_CLK>,
- <&clock_gcc GCC_AGGRE_UFS_PHY_AXI_HW_CTL_CLK>,
+ <&clock_gcc UFS_PHY_AXI_UFS_VOTE_CLK>,
<&clock_gcc GCC_UFS_PHY_AHB_CLK>,
<&clock_gcc GCC_UFS_PHY_UNIPRO_CORE_HW_CTL_CLK>,
<&clock_gcc GCC_UFS_PHY_ICE_CORE_HW_CTL_CLK>,
@@ -2385,7 +2385,7 @@
clocks = <&clock_gcc GCC_SDCC1_AHB_CLK>,
<&clock_gcc GCC_SDCC1_APPS_CLK>,
<&clock_gcc GCC_SDCC1_ICE_CORE_CLK>,
- <&clock_gcc GCC_AGGRE_UFS_PHY_AXI_CLK>;
+ <&clock_gcc UFS_PHY_AXI_EMMC_VOTE_CLK>;
clock-names = "iface_clk", "core_clk", "ice_core_clk",
"bus_aggr_clk";
diff --git a/arch/arm64/boot/dts/qcom/sdm845-670-usb-common.dtsi b/arch/arm64/boot/dts/qcom/sdm845-670-usb-common.dtsi
index 0c37bf1..bf09b67 100644
--- a/arch/arm64/boot/dts/qcom/sdm845-670-usb-common.dtsi
+++ b/arch/arm64/boot/dts/qcom/sdm845-670-usb-common.dtsi
@@ -129,6 +129,7 @@
vdd-supply = <&pm8998_l1>;
vdda18-supply = <&pm8998_l12>;
vdda33-supply = <&pm8998_l24>;
+ qcom,override-bias-ctrl2;
qcom,vdd-voltage-level = <0 880000 880000>;
qcom,qusb-phy-reg-offset =
<0x240 /* QUSB2PHY_PORT_TUNE1 */
@@ -417,6 +418,7 @@
vdd-supply = <&pm8998_l1>;
vdda18-supply = <&pm8998_l12>;
vdda33-supply = <&pm8998_l24>;
+ qcom,override-bias-ctrl2;
qcom,vdd-voltage-level = <0 880000 880000>;
qcom,qusb-phy-reg-offset =
<0x240 /* QUSB2PHY_PORT_TUNE1 */
diff --git a/arch/arm64/boot/dts/qcom/sdm845.dtsi b/arch/arm64/boot/dts/qcom/sdm845.dtsi
index 6c71212..26b0385 100644
--- a/arch/arm64/boot/dts/qcom/sdm845.dtsi
+++ b/arch/arm64/boot/dts/qcom/sdm845.dtsi
@@ -2975,7 +2975,6 @@
<DCC_READ 0x011360b0 1 0>,
<DCC_READ 0x0113e030 2 0>,
<DCC_READ 0x01141000 1 0>,
- <DCC_READ 0x01142028 1 0>,
<DCC_READ 0x01148058 4 0>,
<DCC_READ 0x01160410 3 0>,
<DCC_READ 0x011604a0 1 0>,
@@ -2986,7 +2985,6 @@
<DCC_READ 0x011b6044 4 0>,
<DCC_READ 0x011be030 2 0>,
<DCC_READ 0x011c1000 1 0>,
- <DCC_READ 0x011c2028 1 0>,
<DCC_READ 0x011c8058 4 0>,
<DCC_READ 0x011e0410 3 0>,
<DCC_READ 0x011e04a0 1 0>,
@@ -2998,7 +2996,6 @@
<DCC_READ 0x012360B0 1 0>,
<DCC_READ 0x0123E030 2 0>,
<DCC_READ 0x01241000 1 0>,
- <DCC_READ 0x01242028 1 0>,
<DCC_READ 0x01248058 4 0>,
<DCC_READ 0x01260410 3 0>,
<DCC_READ 0x012604a0 1 0>,
@@ -3011,7 +3008,6 @@
<DCC_READ 0x012b60b0 1 0>,
<DCC_READ 0x012be030 2 0>,
<DCC_READ 0x012c1000 1 0>,
- <DCC_READ 0x012c2028 1 0>,
<DCC_READ 0x012c8058 4 0>,
<DCC_READ 0x012e0410 3 0>,
<DCC_READ 0x012e04a0 1 0>,
@@ -3020,7 +3016,6 @@
<DCC_READ 0x012e6418 1 0>,
<DCC_READ 0x01380900 8 0>,
<DCC_READ 0x01380d00 5 0>,
- <DCC_READ 0x01350110 4 0>,
<DCC_READ 0x01430280 1 0>,
<DCC_READ 0x01430288 1 0>,
<DCC_READ 0x0143028c 7 0>,
@@ -3029,7 +3024,6 @@
<DCC_READ 0x011360b0 1 0>,
<DCC_READ 0x0113e030 2 0>,
<DCC_READ 0x01141000 1 0>,
- <DCC_READ 0x01142028 1 0>,
<DCC_READ 0x01148058 4 0>,
<DCC_READ 0x01160410 3 0>,
<DCC_READ 0x011604a0 1 0>,
@@ -3040,7 +3034,6 @@
<DCC_READ 0x011b6044 4 0>,
<DCC_READ 0x011be030 2 0>,
<DCC_READ 0x011c1000 1 0>,
- <DCC_READ 0x011c2028 1 0>,
<DCC_READ 0x011c8058 4 0>,
<DCC_READ 0x011e0410 3 0>,
<DCC_READ 0x011e04a0 1 0>,
@@ -3052,7 +3045,6 @@
<DCC_READ 0x012360b0 1 0>,
<DCC_READ 0x0123e030 2 0>,
<DCC_READ 0x01241000 1 0>,
- <DCC_READ 0x01242028 1 0>,
<DCC_READ 0x01248058 4 0>,
<DCC_READ 0x01260410 3 0>,
<DCC_READ 0x012604a0 1 0>,
@@ -3065,7 +3057,6 @@
<DCC_READ 0x012b60b0 1 0>,
<DCC_READ 0x012be030 2 0>,
<DCC_READ 0x012C1000 1 0>,
- <DCC_READ 0x012C2028 1 0>,
<DCC_READ 0x012C8058 4 0>,
<DCC_READ 0x012e0410 3 0>,
<DCC_READ 0x012e04a0 1 0>,
@@ -3074,7 +3065,6 @@
<DCC_READ 0x012e6418 1 0>,
<DCC_READ 0x01380900 8 0>,
<DCC_READ 0x01380d00 5 0>,
- <DCC_READ 0x01350110 4 0>,
<DCC_READ 0x01430280 1 0>,
<DCC_READ 0x01430288 1 0>,
<DCC_READ 0x0143028c 7 0>,
diff --git a/arch/arm64/boot/dts/qcom/sxr1120-lc-cdp-overlay.dts b/arch/arm64/boot/dts/qcom/sxr1120-lc-cdp-overlay.dts
new file mode 100644
index 0000000..c3aa763
--- /dev/null
+++ b/arch/arm64/boot/dts/qcom/sxr1120-lc-cdp-overlay.dts
@@ -0,0 +1,31 @@
+/*
+ * Copyright (c) 2018, The Linux Foundation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ */
+
+/dts-v1/;
+/plugin/;
+
+#include <dt-bindings/clock/qcom,gcc-sdm845.h>
+#include <dt-bindings/clock/qcom,camcc-sdm845.h>
+#include <dt-bindings/clock/qcom,dispcc-sdm845.h>
+#include <dt-bindings/clock/qcom,rpmh.h>
+#include <dt-bindings/interrupt-controller/arm-gic.h>
+
+#include "sxr1120-lc-cdp.dtsi"
+#include "qcs605-lc-audio-overlay.dtsi"
+
+/ {
+ model = "Qualcomm Technologies, Inc. SXR1120 LC Groot+PM8005 CDP";
+ compatible = "qcom,sxr1120-cdp", "qcom,sxr1120", "qcom,cdp";
+ qcom,msm-id = <370 0x0>;
+ qcom,board-id = <1 0>;
+};
diff --git a/arch/arm64/boot/dts/qcom/sxr1120-lc-cdp.dts b/arch/arm64/boot/dts/qcom/sxr1120-lc-cdp.dts
new file mode 100644
index 0000000..6237873
--- /dev/null
+++ b/arch/arm64/boot/dts/qcom/sxr1120-lc-cdp.dts
@@ -0,0 +1,25 @@
+/*
+ * Copyright (c) 2018, The Linux Foundation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ */
+
+
+/dts-v1/;
+
+#include "sxr1120-lc.dtsi"
+#include "sxr1120-lc-cdp.dtsi"
+#include "qcs605-lc-audio-overlay.dtsi"
+
+/ {
+ model = "Qualcomm Technologies, Inc. SXR1120 LC Groot+PM8005 CDP";
+ compatible = "qcom,sxr1120-cdp", "qcom,sxr1120", "qcom,cdp";
+ qcom,board-id = <1 0>;
+};
diff --git a/arch/arm64/boot/dts/qcom/sxr1120-lc-cdp.dtsi b/arch/arm64/boot/dts/qcom/sxr1120-lc-cdp.dtsi
new file mode 100644
index 0000000..d4d42c5
--- /dev/null
+++ b/arch/arm64/boot/dts/qcom/sxr1120-lc-cdp.dtsi
@@ -0,0 +1,14 @@
+/*
+ * Copyright (c) 2018, The Linux Foundation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ */
+
+#include "qcs605-lc-cdp.dtsi"
diff --git a/arch/arm64/boot/dts/qcom/sxr1120-lc-external-codec-cdp-overlay.dts b/arch/arm64/boot/dts/qcom/sxr1120-lc-external-codec-cdp-overlay.dts
new file mode 100644
index 0000000..e90f3b4
--- /dev/null
+++ b/arch/arm64/boot/dts/qcom/sxr1120-lc-external-codec-cdp-overlay.dts
@@ -0,0 +1,30 @@
+/*
+ * Copyright (c) 2018, The Linux Foundation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ */
+
+/dts-v1/;
+/plugin/;
+
+#include <dt-bindings/clock/qcom,gcc-sdm845.h>
+#include <dt-bindings/clock/qcom,camcc-sdm845.h>
+#include <dt-bindings/clock/qcom,dispcc-sdm845.h>
+#include <dt-bindings/clock/qcom,rpmh.h>
+#include <dt-bindings/interrupt-controller/arm-gic.h>
+
+#include "sxr1120-lc-cdp.dtsi"
+
+/ {
+ model = "Qualcomm Technologies, Inc. SXR1120 LC Groot+PM8005 Ext. Audio Codec CDP";
+ compatible = "qcom,sxr1120-cdp", "qcom,sxr1120", "qcom,cdp";
+ qcom,msm-id = <370 0x0>;
+ qcom,board-id = <1 1>;
+};
diff --git a/arch/arm64/boot/dts/qcom/sxr1120-lc-external-codec-cdp.dts b/arch/arm64/boot/dts/qcom/sxr1120-lc-external-codec-cdp.dts
new file mode 100644
index 0000000..76c424d
--- /dev/null
+++ b/arch/arm64/boot/dts/qcom/sxr1120-lc-external-codec-cdp.dts
@@ -0,0 +1,24 @@
+/*
+ * Copyright (c) 2018, The Linux Foundation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ */
+
+
+/dts-v1/;
+
+#include "sxr1120-lc.dtsi"
+#include "sxr1120-lc-cdp.dtsi"
+
+/ {
+ model = "Qualcomm Technologies, Inc. SXR1120 LC Groot+PM8005 Ext. Audio Codec CDP";
+ compatible = "qcom,sxr1120-cdp", "qcom,sxr1120", "qcom,cdp";
+ qcom,board-id = <1 1>;
+};
diff --git a/arch/arm64/boot/dts/qcom/sxr1120-lc-external-codec-mtp-overlay.dts b/arch/arm64/boot/dts/qcom/sxr1120-lc-external-codec-mtp-overlay.dts
new file mode 100644
index 0000000..946298f
--- /dev/null
+++ b/arch/arm64/boot/dts/qcom/sxr1120-lc-external-codec-mtp-overlay.dts
@@ -0,0 +1,30 @@
+/*
+ * Copyright (c) 2018, The Linux Foundation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ */
+
+/dts-v1/;
+/plugin/;
+
+#include <dt-bindings/clock/qcom,gcc-sdm845.h>
+#include <dt-bindings/clock/qcom,camcc-sdm845.h>
+#include <dt-bindings/clock/qcom,dispcc-sdm845.h>
+#include <dt-bindings/clock/qcom,rpmh.h>
+#include <dt-bindings/interrupt-controller/arm-gic.h>
+
+#include "sxr1120-lc-mtp.dtsi"
+
+/ {
+ model = "Qualcomm Technologies, Inc. SXR1120 LC Groot+PM8005 Ext. Audio Codec MTP";
+ compatible = "qcom,sxr1120-mtp", "qcom,sxr1120", "qcom,mtp";
+ qcom,msm-id = <370 0x0>;
+ qcom,board-id = <8 1>;
+};
diff --git a/arch/arm64/boot/dts/qcom/sxr1120-lc-external-codec-mtp.dts b/arch/arm64/boot/dts/qcom/sxr1120-lc-external-codec-mtp.dts
new file mode 100644
index 0000000..e53bbe3
--- /dev/null
+++ b/arch/arm64/boot/dts/qcom/sxr1120-lc-external-codec-mtp.dts
@@ -0,0 +1,24 @@
+/*
+ * Copyright (c) 2018, The Linux Foundation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ */
+
+
+/dts-v1/;
+
+#include "sxr1120-lc.dtsi"
+#include "sxr1120-lc-mtp.dtsi"
+
+/ {
+ model = "Qualcomm Technologies, Inc. SXR1120 LC Groot+PM8005 Ext. Audio Codec MTP";
+ compatible = "qcom,sxr1120-mtp", "qcom,sxr1120", "qcom,mtp";
+ qcom,board-id = <8 1>;
+};
diff --git a/arch/arm64/boot/dts/qcom/sxr1120-lc-mtp-overlay.dts b/arch/arm64/boot/dts/qcom/sxr1120-lc-mtp-overlay.dts
new file mode 100644
index 0000000..8af46ef
--- /dev/null
+++ b/arch/arm64/boot/dts/qcom/sxr1120-lc-mtp-overlay.dts
@@ -0,0 +1,31 @@
+/*
+ * Copyright (c) 2018, The Linux Foundation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ */
+
+/dts-v1/;
+/plugin/;
+
+#include <dt-bindings/clock/qcom,gcc-sdm845.h>
+#include <dt-bindings/clock/qcom,camcc-sdm845.h>
+#include <dt-bindings/clock/qcom,dispcc-sdm845.h>
+#include <dt-bindings/clock/qcom,rpmh.h>
+#include <dt-bindings/interrupt-controller/arm-gic.h>
+
+#include "sxr1120-lc-mtp.dtsi"
+#include "qcs605-lc-audio-overlay.dtsi"
+
+/ {
+ model = "Qualcomm Technologies, Inc. SXR1120 LC Groot+PM8005 MTP";
+ compatible = "qcom,sxr1120-mtp", "qcom,sxr1120", "qcom,mtp";
+ qcom,msm-id = <370 0x0>;
+ qcom,board-id = <8 0>;
+};
diff --git a/arch/arm64/boot/dts/qcom/sxr1120-lc-mtp.dts b/arch/arm64/boot/dts/qcom/sxr1120-lc-mtp.dts
new file mode 100644
index 0000000..ffcdeda
--- /dev/null
+++ b/arch/arm64/boot/dts/qcom/sxr1120-lc-mtp.dts
@@ -0,0 +1,25 @@
+/*
+ * Copyright (c) 2018, The Linux Foundation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ */
+
+
+/dts-v1/;
+
+#include "sxr1120-lc.dtsi"
+#include "sxr1120-lc-mtp.dtsi"
+#include "qcs605-lc-audio-overlay.dtsi"
+
+/ {
+ model = "Qualcomm Technologies, Inc. SXR1120 LC Groot+PM8005 MTP";
+ compatible = "qcom,sxr1120-mtp", "qcom,sxr1120", "qcom,mtp";
+ qcom,board-id = <8 0>;
+};
diff --git a/arch/arm64/boot/dts/qcom/sxr1120-lc-mtp.dtsi b/arch/arm64/boot/dts/qcom/sxr1120-lc-mtp.dtsi
new file mode 100644
index 0000000..270aa0e
--- /dev/null
+++ b/arch/arm64/boot/dts/qcom/sxr1120-lc-mtp.dtsi
@@ -0,0 +1,14 @@
+/*
+ * Copyright (c) 2018, The Linux Foundation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ */
+
+#include "qcs605-lc-mtp.dtsi"
diff --git a/arch/arm64/boot/dts/qcom/sxr1120-lc.dts b/arch/arm64/boot/dts/qcom/sxr1120-lc.dts
new file mode 100644
index 0000000..5967388
--- /dev/null
+++ b/arch/arm64/boot/dts/qcom/sxr1120-lc.dts
@@ -0,0 +1,22 @@
+/*
+ * Copyright (c) 2018, The Linux Foundation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ */
+
+/dts-v1/;
+
+#include "sxr1120-lc.dtsi"
+
+/ {
+ model = "Qualcomm Technologies, Inc. SXR1120 LC SoC";
+ compatible = "qcom,sxr1120";
+ qcom,board-id = <0 0>;
+};
diff --git a/arch/arm64/boot/dts/qcom/sxr1120-lc.dtsi b/arch/arm64/boot/dts/qcom/sxr1120-lc.dtsi
new file mode 100644
index 0000000..1413e2c
--- /dev/null
+++ b/arch/arm64/boot/dts/qcom/sxr1120-lc.dtsi
@@ -0,0 +1,20 @@
+/*
+ * Copyright (c) 2018, The Linux Foundation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ */
+
+#include "qcs605-lc.dtsi"
+
+/ {
+ model = "Qualcomm Technologies, Inc. SXR1120 SoC";
+ compatible = "qcom,sxr1120";
+ qcom,msm-id = <370 0x0>;
+};
diff --git a/arch/arm64/configs/msm8937-perf_defconfig b/arch/arm64/configs/msm8937-perf_defconfig
index a33d09a..6aa47eb 100644
--- a/arch/arm64/configs/msm8937-perf_defconfig
+++ b/arch/arm64/configs/msm8937-perf_defconfig
@@ -246,6 +246,7 @@
CONFIG_HDCP_QSEECOM=y
CONFIG_QSEECOM=y
CONFIG_UID_SYS_STATS=y
+CONFIG_FPR_FPC=y
CONFIG_SCSI=y
CONFIG_BLK_DEV_SD=y
CONFIG_CHR_DEV_SG=y
@@ -348,7 +349,6 @@
CONFIG_GPIO_QPNP_PIN=y
CONFIG_POWER_RESET_QCOM=y
CONFIG_QCOM_DLOAD_MODE=y
-CONFIG_POWER_RESET_SYSCON=y
CONFIG_QPNP_FG=y
CONFIG_SMB135X_CHARGER=y
CONFIG_SMB1355_SLAVE_CHARGER=y
@@ -375,6 +375,7 @@
CONFIG_QTI_BCL_SOC_DRIVER=y
CONFIG_MFD_I2C_PMIC=y
CONFIG_MFD_SPMI_PMIC=y
+CONFIG_MFD_SYSCON=y
CONFIG_REGULATOR=y
CONFIG_REGULATOR_FIXED_VOLTAGE=y
CONFIG_REGULATOR_CPR=y
@@ -394,9 +395,7 @@
CONFIG_VIDEO_V4L2_SUBDEV_API=y
CONFIG_V4L_PLATFORM_DRIVERS=y
CONFIG_MSM_CAMERA=y
-CONFIG_MSM_CAMERA_DEBUG=y
CONFIG_MSMB_CAMERA=y
-CONFIG_MSMB_CAMERA_DEBUG=y
CONFIG_MSM_CAMERA_SENSOR=y
CONFIG_MSM_CPP=y
CONFIG_MSM_CCI=y
@@ -565,7 +564,6 @@
CONFIG_MSM_PIL=y
CONFIG_MSM_PIL_SSR_GENERIC=y
CONFIG_MSM_PIL_MSS_QDSP6V5=y
-CONFIG_ICNSS=y
CONFIG_MSM_PERFORMANCE=y
CONFIG_MSM_EVENT_TIMER=y
CONFIG_MSM_AVTIMER=y
@@ -578,6 +576,7 @@
CONFIG_WCNSS_CORE=y
CONFIG_WCNSS_CORE_PRONTO=y
CONFIG_WCNSS_REGISTER_DUMP_ON_BITE=y
+CONFIG_BIG_CLUSTER_MIN_FREQ_ADJUST=y
CONFIG_QCOM_BIMC_BWMON=y
CONFIG_DEVFREQ_GOV_QCOM_BW_HWMON=y
CONFIG_DEVFREQ_SIMPLE_DEV=y
diff --git a/arch/arm64/configs/msm8937_defconfig b/arch/arm64/configs/msm8937_defconfig
index ded6e42..02e4d68 100644
--- a/arch/arm64/configs/msm8937_defconfig
+++ b/arch/arm64/configs/msm8937_defconfig
@@ -252,6 +252,7 @@
CONFIG_HDCP_QSEECOM=y
CONFIG_QSEECOM=y
CONFIG_UID_SYS_STATS=y
+CONFIG_FPR_FPC=y
CONFIG_SCSI=y
CONFIG_BLK_DEV_SD=y
CONFIG_CHR_DEV_SG=y
@@ -356,7 +357,6 @@
CONFIG_GPIO_QPNP_PIN=y
CONFIG_POWER_RESET_QCOM=y
CONFIG_QCOM_DLOAD_MODE=y
-CONFIG_POWER_RESET_SYSCON=y
CONFIG_QPNP_FG=y
CONFIG_SMB135X_CHARGER=y
CONFIG_SMB1355_SLAVE_CHARGER=y
@@ -383,6 +383,7 @@
CONFIG_QTI_BCL_SOC_DRIVER=y
CONFIG_MFD_I2C_PMIC=y
CONFIG_MFD_SPMI_PMIC=y
+CONFIG_MFD_SYSCON=y
CONFIG_REGULATOR=y
CONFIG_REGULATOR_FIXED_VOLTAGE=y
CONFIG_REGULATOR_CPR=y
@@ -562,7 +563,6 @@
CONFIG_QCOM_SCM=y
CONFIG_MSM_BOOT_STATS=y
CONFIG_MSM_CORE_HANG_DETECT=y
-CONFIG_MSM_GLADIATOR_HANG_DETECT=y
CONFIG_QCOM_WATCHDOG_V2=y
CONFIG_QCOM_MEMORY_DUMP_V2=y
CONFIG_MSM_DEBUG_LAR_UNLOCK=y
@@ -583,7 +583,6 @@
CONFIG_MSM_PIL=y
CONFIG_MSM_PIL_SSR_GENERIC=y
CONFIG_MSM_PIL_MSS_QDSP6V5=y
-CONFIG_ICNSS=y
CONFIG_MSM_PERFORMANCE=y
CONFIG_MSM_EVENT_TIMER=y
CONFIG_MSM_AVTIMER=y
@@ -596,6 +595,7 @@
CONFIG_WCNSS_CORE=y
CONFIG_WCNSS_CORE_PRONTO=y
CONFIG_WCNSS_REGISTER_DUMP_ON_BITE=y
+CONFIG_BIG_CLUSTER_MIN_FREQ_ADJUST=y
CONFIG_QCOM_BIMC_BWMON=y
CONFIG_DEVFREQ_GOV_QCOM_BW_HWMON=y
CONFIG_DEVFREQ_SIMPLE_DEV=y
@@ -644,7 +644,6 @@
CONFIG_DEBUG_OBJECTS_WORK=y
CONFIG_DEBUG_OBJECTS_RCU_HEAD=y
CONFIG_DEBUG_OBJECTS_PERCPU_COUNTER=y
-CONFIG_SLUB_DEBUG_ON=y
CONFIG_DEBUG_KMEMLEAK=y
CONFIG_DEBUG_KMEMLEAK_EARLY_LOG_SIZE=4000
CONFIG_DEBUG_KMEMLEAK_DEFAULT_OFF=y
diff --git a/arch/arm64/configs/msm8953-perf_defconfig b/arch/arm64/configs/msm8953-perf_defconfig
index b46317b..9ac93aa 100644
--- a/arch/arm64/configs/msm8953-perf_defconfig
+++ b/arch/arm64/configs/msm8953-perf_defconfig
@@ -73,7 +73,6 @@
CONFIG_SWP_EMULATION=y
CONFIG_CP15_BARRIER_EMULATION=y
CONFIG_SETEND_EMULATION=y
-CONFIG_ARM64_SW_TTBR0_PAN=y
# CONFIG_ARM64_VHE is not set
CONFIG_RANDOMIZE_BASE=y
CONFIG_BUILD_ARM64_APPENDED_DTB_IMAGE=y
@@ -346,7 +345,6 @@
CONFIG_GPIO_QPNP_PIN=y
CONFIG_POWER_RESET_QCOM=y
CONFIG_QCOM_DLOAD_MODE=y
-CONFIG_POWER_RESET_SYSCON=y
CONFIG_QPNP_FG=y
CONFIG_SMB135X_CHARGER=y
CONFIG_SMB1355_SLAVE_CHARGER=y
@@ -373,6 +371,7 @@
CONFIG_QTI_BCL_SOC_DRIVER=y
CONFIG_MFD_I2C_PMIC=y
CONFIG_MFD_SPMI_PMIC=y
+CONFIG_MFD_SYSCON=y
CONFIG_REGULATOR=y
CONFIG_REGULATOR_FIXED_VOLTAGE=y
CONFIG_REGULATOR_CPR=y
@@ -547,6 +546,7 @@
CONFIG_MSM_RMNET_BAM=y
CONFIG_MSM_MDSS_PLL=y
CONFIG_REMOTE_SPINLOCK_MSM=y
+CONFIG_MSM_TIMER_LEAP=y
CONFIG_MAILBOX=y
CONFIG_ARM_SMMU=y
CONFIG_QCOM_LAZY_MAPPING=y
diff --git a/arch/arm64/configs/msm8953_defconfig b/arch/arm64/configs/msm8953_defconfig
index 22e3510..af1bd0e 100644
--- a/arch/arm64/configs/msm8953_defconfig
+++ b/arch/arm64/configs/msm8953_defconfig
@@ -76,7 +76,6 @@
CONFIG_SWP_EMULATION=y
CONFIG_CP15_BARRIER_EMULATION=y
CONFIG_SETEND_EMULATION=y
-CONFIG_ARM64_SW_TTBR0_PAN=y
# CONFIG_ARM64_VHE is not set
CONFIG_RANDOMIZE_BASE=y
CONFIG_BUILD_ARM64_APPENDED_DTB_IMAGE=y
@@ -355,7 +354,6 @@
CONFIG_GPIO_QPNP_PIN=y
CONFIG_POWER_RESET_QCOM=y
CONFIG_QCOM_DLOAD_MODE=y
-CONFIG_POWER_RESET_SYSCON=y
CONFIG_QPNP_FG=y
CONFIG_SMB135X_CHARGER=y
CONFIG_SMB1355_SLAVE_CHARGER=y
@@ -382,6 +380,7 @@
CONFIG_QTI_BCL_SOC_DRIVER=y
CONFIG_MFD_I2C_PMIC=y
CONFIG_MFD_SPMI_PMIC=y
+CONFIG_MFD_SYSCON=y
CONFIG_REGULATOR=y
CONFIG_REGULATOR_FIXED_VOLTAGE=y
CONFIG_REGULATOR_CPR=y
@@ -558,6 +557,7 @@
CONFIG_MSM_RMNET_BAM=y
CONFIG_MSM_MDSS_PLL=y
CONFIG_REMOTE_SPINLOCK_MSM=y
+CONFIG_MSM_TIMER_LEAP=y
CONFIG_MAILBOX=y
CONFIG_ARM_SMMU=y
CONFIG_QCOM_LAZY_MAPPING=y
@@ -571,7 +571,6 @@
CONFIG_QCOM_SCM=y
CONFIG_MSM_BOOT_STATS=y
CONFIG_MSM_CORE_HANG_DETECT=y
-CONFIG_MSM_GLADIATOR_HANG_DETECT=y
CONFIG_QCOM_WATCHDOG_V2=y
CONFIG_QCOM_MEMORY_DUMP_V2=y
CONFIG_MSM_DEBUG_LAR_UNLOCK=y
diff --git a/arch/arm64/configs/sdm670-perf_defconfig b/arch/arm64/configs/sdm670-perf_defconfig
index bf43e36..956bcc5 100644
--- a/arch/arm64/configs/sdm670-perf_defconfig
+++ b/arch/arm64/configs/sdm670-perf_defconfig
@@ -305,7 +305,6 @@
CONFIG_INPUT_QPNP_POWER_ON=y
CONFIG_INPUT_UINPUT=y
# CONFIG_SERIO_SERPORT is not set
-# CONFIG_VT is not set
# CONFIG_LEGACY_PTYS is not set
# CONFIG_DEVMEM is not set
# CONFIG_DEVKMEM is not set
diff --git a/arch/arm64/configs/sdm670_defconfig b/arch/arm64/configs/sdm670_defconfig
index 72604a5..f6895a5 100644
--- a/arch/arm64/configs/sdm670_defconfig
+++ b/arch/arm64/configs/sdm670_defconfig
@@ -312,7 +312,6 @@
CONFIG_INPUT_QPNP_POWER_ON=y
CONFIG_INPUT_UINPUT=y
# CONFIG_SERIO_SERPORT is not set
-# CONFIG_VT is not set
# CONFIG_LEGACY_PTYS is not set
CONFIG_SERIAL_MSM_GENI=y
CONFIG_SERIAL_MSM_GENI_CONSOLE=y
diff --git a/arch/arm64/configs/sdm845-perf_defconfig b/arch/arm64/configs/sdm845-perf_defconfig
index dceaafd..e35e571 100644
--- a/arch/arm64/configs/sdm845-perf_defconfig
+++ b/arch/arm64/configs/sdm845-perf_defconfig
@@ -83,6 +83,7 @@
# CONFIG_PM_WAKELOCKS_GC is not set
CONFIG_CPU_IDLE=y
CONFIG_CPU_FREQ=y
+CONFIG_CPU_FREQ_STAT=y
CONFIG_CPU_FREQ_GOV_POWERSAVE=y
CONFIG_CPU_FREQ_GOV_USERSPACE=y
CONFIG_CPU_FREQ_GOV_ONDEMAND=y
diff --git a/arch/arm64/configs/sdm845_defconfig b/arch/arm64/configs/sdm845_defconfig
index 946e4f4..ab983e0 100644
--- a/arch/arm64/configs/sdm845_defconfig
+++ b/arch/arm64/configs/sdm845_defconfig
@@ -86,6 +86,7 @@
CONFIG_PM_DEBUG=y
CONFIG_CPU_IDLE=y
CONFIG_CPU_FREQ=y
+CONFIG_CPU_FREQ_STAT=y
CONFIG_CPU_FREQ_GOV_POWERSAVE=y
CONFIG_CPU_FREQ_GOV_USERSPACE=y
CONFIG_CPU_FREQ_GOV_ONDEMAND=y
@@ -469,7 +470,6 @@
CONFIG_EDAC=y
CONFIG_EDAC_MM_EDAC=y
CONFIG_EDAC_KRYO3XX_ARM64=y
-CONFIG_EDAC_KRYO3XX_ARM64_PANIC_ON_CE=y
CONFIG_EDAC_KRYO3XX_ARM64_PANIC_ON_UE=y
CONFIG_RTC_CLASS=y
CONFIG_RTC_DRV_QPNP=y
diff --git a/arch/arm64/include/asm/arch_timer.h b/arch/arm64/include/asm/arch_timer.h
index eaa5bbe..f95235a 100644
--- a/arch/arm64/include/asm/arch_timer.h
+++ b/arch/arm64/include/asm/arch_timer.h
@@ -148,8 +148,17 @@
static inline u64 arch_counter_get_cntvct(void)
{
+ u64 cval;
isb();
- return arch_timer_reg_read_stable(cntvct_el0);
+#if IS_ENABLED(CONFIG_MSM_TIMER_LEAP)
+#define L32_BITS 0x00000000FFFFFFFF
+ do {
+ cval = arch_timer_reg_read_stable(cntvct_el0);
+ } while ((cval & L32_BITS) == L32_BITS);
+#else
+ cval = arch_timer_reg_read_stable(cntvct_el0);
+#endif
+ return cval;
}
static inline int arch_timer_arch_init(void)
diff --git a/arch/arm64/include/asm/io.h b/arch/arm64/include/asm/io.h
index 5c0c57e..388a0ca 100644
--- a/arch/arm64/include/asm/io.h
+++ b/arch/arm64/include/asm/io.h
@@ -167,9 +167,9 @@
#define readq_relaxed_no_log(c) ({ u64 __v = le64_to_cpu((__force __le64)__raw_readq_no_log(c)); __v; })
#define writeb_relaxed_no_log(v, c) ((void)__raw_writeb_no_log((v), (c)))
-#define writew_relaxed_no_log(v, c) ((void)__raw_writew_no_log((__force u16)cpu_to_le32(v), (c)))
+#define writew_relaxed_no_log(v, c) ((void)__raw_writew_no_log((__force u16)cpu_to_le16(v), (c)))
#define writel_relaxed_no_log(v, c) ((void)__raw_writel_no_log((__force u32)cpu_to_le32(v), (c)))
-#define writeq_relaxed_no_log(v, c) ((void)__raw_writeq_no_log((__force u64)cpu_to_le32(v), (c)))
+#define writeq_relaxed_no_log(v, c) ((void)__raw_writeq_no_log((__force u64)cpu_to_le64(v), (c)))
/*
* I/O memory access primitives. Reads are ordered relative to any
diff --git a/arch/arm64/include/asm/kvm_mmu.h b/arch/arm64/include/asm/kvm_mmu.h
index 36d2aba..24a8369 100644
--- a/arch/arm64/include/asm/kvm_mmu.h
+++ b/arch/arm64/include/asm/kvm_mmu.h
@@ -313,6 +313,22 @@
return (cpuid_feature_extract_unsigned_field(reg, ID_AA64MMFR1_VMIDBITS_SHIFT) == 2) ? 16 : 8;
}
+/*
+ * We are not in the kvm->srcu critical section most of the time, so we take
+ * the SRCU read lock here. Since we copy the data from the user page, we
+ * can immediately drop the lock again.
+ */
+static inline int kvm_read_guest_lock(struct kvm *kvm,
+ gpa_t gpa, void *data, unsigned long len)
+{
+ int srcu_idx = srcu_read_lock(&kvm->srcu);
+ int ret = kvm_read_guest(kvm, gpa, data, len);
+
+ srcu_read_unlock(&kvm->srcu, srcu_idx);
+
+ return ret;
+}
+
#ifdef CONFIG_HARDEN_BRANCH_PREDICTOR
#include <asm/mmu.h>
diff --git a/arch/arm64/kernel/vdso/gettimeofday.S b/arch/arm64/kernel/vdso/gettimeofday.S
index c39872a..2bd7426 100644
--- a/arch/arm64/kernel/vdso/gettimeofday.S
+++ b/arch/arm64/kernel/vdso/gettimeofday.S
@@ -66,7 +66,16 @@
.macro get_clock_shifted_nsec res, cycle_last, mult
/* Read the virtual counter. */
isb
+#if IS_ENABLED(CONFIG_MSM_TIMER_LEAP)
+#define LEAST_32BITS 0x00000000FFFFFFFF
+9999:
+ mrs x_tmp, cntvct_el0
+ and \res, x_tmp, #LEAST_32BITS
+ eor \res, \res, #LEAST_32BITS
+ cbz \res, 9999b
+#else
mrs x_tmp, cntvct_el0
+#endif
/* Calculate cycle delta and convert to ns. */
sub \res, x_tmp, \cycle_last
/* We can only guarantee 56 bits of precision. */
diff --git a/arch/powerpc/kernel/setup-common.c b/arch/powerpc/kernel/setup-common.c
index f516ac5..bf0f712 100644
--- a/arch/powerpc/kernel/setup-common.c
+++ b/arch/powerpc/kernel/setup-common.c
@@ -228,14 +228,6 @@
unsigned short maj;
unsigned short min;
- /* We only show online cpus: disable preempt (overzealous, I
- * knew) to prevent cpu going down. */
- preempt_disable();
- if (!cpu_online(cpu_id)) {
- preempt_enable();
- return 0;
- }
-
#ifdef CONFIG_SMP
pvr = per_cpu(cpu_pvr, cpu_id);
#else
@@ -340,9 +332,6 @@
#ifdef CONFIG_SMP
seq_printf(m, "\n");
#endif
-
- preempt_enable();
-
/* If this is the last cpu, print the summary */
if (cpumask_next(cpu_id, cpu_online_mask) >= nr_cpu_ids)
show_cpuinfo_summary(m);
diff --git a/arch/powerpc/platforms/powernv/opal-nvram.c b/arch/powerpc/platforms/powernv/opal-nvram.c
index 1bceb95..5584247 100644
--- a/arch/powerpc/platforms/powernv/opal-nvram.c
+++ b/arch/powerpc/platforms/powernv/opal-nvram.c
@@ -44,6 +44,10 @@
return count;
}
+/*
+ * This can be called in the panic path with interrupts off, so use
+ * mdelay in that case.
+ */
static ssize_t opal_nvram_write(char *buf, size_t count, loff_t *index)
{
s64 rc = OPAL_BUSY;
@@ -58,10 +62,16 @@
while (rc == OPAL_BUSY || rc == OPAL_BUSY_EVENT) {
rc = opal_write_nvram(__pa(buf), count, off);
if (rc == OPAL_BUSY_EVENT) {
- msleep(OPAL_BUSY_DELAY_MS);
+ if (in_interrupt() || irqs_disabled())
+ mdelay(OPAL_BUSY_DELAY_MS);
+ else
+ msleep(OPAL_BUSY_DELAY_MS);
opal_poll_events(NULL);
} else if (rc == OPAL_BUSY) {
- msleep(OPAL_BUSY_DELAY_MS);
+ if (in_interrupt() || irqs_disabled())
+ mdelay(OPAL_BUSY_DELAY_MS);
+ else
+ msleep(OPAL_BUSY_DELAY_MS);
}
}
diff --git a/arch/s390/crypto/crc32be-vx.S b/arch/s390/crypto/crc32be-vx.S
index 8013989..096affb 100644
--- a/arch/s390/crypto/crc32be-vx.S
+++ b/arch/s390/crypto/crc32be-vx.S
@@ -12,6 +12,7 @@
*/
#include <linux/linkage.h>
+#include <asm/nospec-insn.h>
#include <asm/vx-insn.h>
/* Vector register range containing CRC-32 constants */
@@ -66,6 +67,8 @@
.previous
+ GEN_BR_THUNK %r14
+
.text
/*
* The CRC-32 function(s) use these calling conventions:
@@ -202,6 +205,6 @@
.Ldone:
VLGVF %r2,%v2,3
- br %r14
+ BR_EX %r14
.previous
diff --git a/arch/s390/crypto/crc32le-vx.S b/arch/s390/crypto/crc32le-vx.S
index 17f2504..8dc98c1 100644
--- a/arch/s390/crypto/crc32le-vx.S
+++ b/arch/s390/crypto/crc32le-vx.S
@@ -13,6 +13,7 @@
*/
#include <linux/linkage.h>
+#include <asm/nospec-insn.h>
#include <asm/vx-insn.h>
/* Vector register range containing CRC-32 constants */
@@ -75,6 +76,7 @@
.previous
+ GEN_BR_THUNK %r14
.text
@@ -263,6 +265,6 @@
.Ldone:
VLGVF %r2,%v2,2
- br %r14
+ BR_EX %r14
.previous
diff --git a/arch/s390/include/asm/alternative-asm.h b/arch/s390/include/asm/alternative-asm.h
new file mode 100644
index 0000000..955d620
--- /dev/null
+++ b/arch/s390/include/asm/alternative-asm.h
@@ -0,0 +1,108 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+#ifndef _ASM_S390_ALTERNATIVE_ASM_H
+#define _ASM_S390_ALTERNATIVE_ASM_H
+
+#ifdef __ASSEMBLY__
+
+/*
+ * Check the length of an instruction sequence. The length may not be larger
+ * than 254 bytes and it has to be divisible by 2.
+ */
+.macro alt_len_check start,end
+ .if ( \end - \start ) > 254
+ .error "cpu alternatives does not support instructions blocks > 254 bytes\n"
+ .endif
+ .if ( \end - \start ) % 2
+ .error "cpu alternatives instructions length is odd\n"
+ .endif
+.endm
+
+/*
+ * Issue one struct alt_instr descriptor entry (need to put it into
+ * the section .altinstructions, see below). This entry contains
+ * enough information for the alternatives patching code to patch an
+ * instruction. See apply_alternatives().
+ */
+.macro alt_entry orig_start, orig_end, alt_start, alt_end, feature
+ .long \orig_start - .
+ .long \alt_start - .
+ .word \feature
+ .byte \orig_end - \orig_start
+ .byte \alt_end - \alt_start
+.endm
+
+/*
+ * Fill up @bytes with nops. The macro emits 6-byte nop instructions
+ * for the bulk of the area, possibly followed by a 4-byte and/or
+ * a 2-byte nop if the size of the area is not divisible by 6.
+ */
+.macro alt_pad_fill bytes
+ .fill ( \bytes ) / 6, 6, 0xc0040000
+ .fill ( \bytes ) % 6 / 4, 4, 0x47000000
+ .fill ( \bytes ) % 6 % 4 / 2, 2, 0x0700
+.endm
+
+/*
+ * Fill up @bytes with nops. If the number of bytes is larger
+ * than 6, emit a jg instruction to branch over all nops, then
+ * fill an area of size (@bytes - 6) with nop instructions.
+ */
+.macro alt_pad bytes
+ .if ( \bytes > 0 )
+ .if ( \bytes > 6 )
+ jg . + \bytes
+ alt_pad_fill \bytes - 6
+ .else
+ alt_pad_fill \bytes
+ .endif
+ .endif
+.endm
+
+/*
+ * Define an alternative between two instructions. If @feature is
+ * present, early code in apply_alternatives() replaces @oldinstr with
+ * @newinstr. ".skip" directive takes care of proper instruction padding
+ * in case @newinstr is longer than @oldinstr.
+ */
+.macro ALTERNATIVE oldinstr, newinstr, feature
+ .pushsection .altinstr_replacement,"ax"
+770: \newinstr
+771: .popsection
+772: \oldinstr
+773: alt_len_check 770b, 771b
+ alt_len_check 772b, 773b
+ alt_pad ( ( 771b - 770b ) - ( 773b - 772b ) )
+774: .pushsection .altinstructions,"a"
+ alt_entry 772b, 774b, 770b, 771b, \feature
+ .popsection
+.endm
+
+/*
+ * Define an alternative between two instructions. If @feature is
+ * present, early code in apply_alternatives() replaces @oldinstr with
+ * @newinstr. ".skip" directive takes care of proper instruction padding
+ * in case @newinstr is longer than @oldinstr.
+ */
+.macro ALTERNATIVE_2 oldinstr, newinstr1, feature1, newinstr2, feature2
+ .pushsection .altinstr_replacement,"ax"
+770: \newinstr1
+771: \newinstr2
+772: .popsection
+773: \oldinstr
+774: alt_len_check 770b, 771b
+ alt_len_check 771b, 772b
+ alt_len_check 773b, 774b
+ .if ( 771b - 770b > 772b - 771b )
+ alt_pad ( ( 771b - 770b ) - ( 774b - 773b ) )
+ .else
+ alt_pad ( ( 772b - 771b ) - ( 774b - 773b ) )
+ .endif
+775: .pushsection .altinstructions,"a"
+ alt_entry 773b, 775b, 770b, 771b,\feature1
+ alt_entry 773b, 775b, 771b, 772b,\feature2
+ .popsection
+.endm
+
+#endif /* __ASSEMBLY__ */
+
+#endif /* _ASM_S390_ALTERNATIVE_ASM_H */
diff --git a/arch/s390/include/asm/nospec-insn.h b/arch/s390/include/asm/nospec-insn.h
new file mode 100644
index 0000000..9a56e73
--- /dev/null
+++ b/arch/s390/include/asm/nospec-insn.h
@@ -0,0 +1,195 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+#ifndef _ASM_S390_NOSPEC_ASM_H
+#define _ASM_S390_NOSPEC_ASM_H
+
+#include <asm/alternative-asm.h>
+#include <asm/asm-offsets.h>
+
+#ifdef __ASSEMBLY__
+
+#ifdef CONFIG_EXPOLINE
+
+_LC_BR_R1 = __LC_BR_R1
+
+/*
+ * The expoline macros are used to create thunks in the same format
+ * as gcc generates them. The 'comdat' section flag makes sure that
+ * the various thunks are merged into a single copy.
+ */
+ .macro __THUNK_PROLOG_NAME name
+ .pushsection .text.\name,"axG",@progbits,\name,comdat
+ .globl \name
+ .hidden \name
+ .type \name,@function
+\name:
+ .cfi_startproc
+ .endm
+
+ .macro __THUNK_EPILOG
+ .cfi_endproc
+ .popsection
+ .endm
+
+ .macro __THUNK_PROLOG_BR r1,r2
+ __THUNK_PROLOG_NAME __s390x_indirect_jump_r\r2\()use_r\r1
+ .endm
+
+ .macro __THUNK_PROLOG_BC d0,r1,r2
+ __THUNK_PROLOG_NAME __s390x_indirect_branch_\d0\()_\r2\()use_\r1
+ .endm
+
+ .macro __THUNK_BR r1,r2
+ jg __s390x_indirect_jump_r\r2\()use_r\r1
+ .endm
+
+ .macro __THUNK_BC d0,r1,r2
+ jg __s390x_indirect_branch_\d0\()_\r2\()use_\r1
+ .endm
+
+ .macro __THUNK_BRASL r1,r2,r3
+ brasl \r1,__s390x_indirect_jump_r\r3\()use_r\r2
+ .endm
+
+ .macro __DECODE_RR expand,reg,ruse
+ .set __decode_fail,1
+ .irp r1,0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15
+ .ifc \reg,%r\r1
+ .irp r2,0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15
+ .ifc \ruse,%r\r2
+ \expand \r1,\r2
+ .set __decode_fail,0
+ .endif
+ .endr
+ .endif
+ .endr
+ .if __decode_fail == 1
+ .error "__DECODE_RR failed"
+ .endif
+ .endm
+
+ .macro __DECODE_RRR expand,rsave,rtarget,ruse
+ .set __decode_fail,1
+ .irp r1,0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15
+ .ifc \rsave,%r\r1
+ .irp r2,0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15
+ .ifc \rtarget,%r\r2
+ .irp r3,0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15
+ .ifc \ruse,%r\r3
+ \expand \r1,\r2,\r3
+ .set __decode_fail,0
+ .endif
+ .endr
+ .endif
+ .endr
+ .endif
+ .endr
+ .if __decode_fail == 1
+ .error "__DECODE_RRR failed"
+ .endif
+ .endm
+
+ .macro __DECODE_DRR expand,disp,reg,ruse
+ .set __decode_fail,1
+ .irp r1,0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15
+ .ifc \reg,%r\r1
+ .irp r2,0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15
+ .ifc \ruse,%r\r2
+ \expand \disp,\r1,\r2
+ .set __decode_fail,0
+ .endif
+ .endr
+ .endif
+ .endr
+ .if __decode_fail == 1
+ .error "__DECODE_DRR failed"
+ .endif
+ .endm
+
+ .macro __THUNK_EX_BR reg,ruse
+ # Be very careful when adding instructions to this macro!
+ # The ALTERNATIVE replacement code has a .+10 which targets
+ # the "br \reg" after the code has been patched.
+#ifdef CONFIG_HAVE_MARCH_Z10_FEATURES
+ exrl 0,555f
+ j .
+#else
+ .ifc \reg,%r1
+ ALTERNATIVE "ex %r0,_LC_BR_R1", ".insn ril,0xc60000000000,0,.+10", 35
+ j .
+ .else
+ larl \ruse,555f
+ ex 0,0(\ruse)
+ j .
+ .endif
+#endif
+555: br \reg
+ .endm
+
+ .macro __THUNK_EX_BC disp,reg,ruse
+#ifdef CONFIG_HAVE_MARCH_Z10_FEATURES
+ exrl 0,556f
+ j .
+#else
+ larl \ruse,556f
+ ex 0,0(\ruse)
+ j .
+#endif
+556: b \disp(\reg)
+ .endm
+
+ .macro GEN_BR_THUNK reg,ruse=%r1
+ __DECODE_RR __THUNK_PROLOG_BR,\reg,\ruse
+ __THUNK_EX_BR \reg,\ruse
+ __THUNK_EPILOG
+ .endm
+
+ .macro GEN_B_THUNK disp,reg,ruse=%r1
+ __DECODE_DRR __THUNK_PROLOG_BC,\disp,\reg,\ruse
+ __THUNK_EX_BC \disp,\reg,\ruse
+ __THUNK_EPILOG
+ .endm
+
+ .macro BR_EX reg,ruse=%r1
+557: __DECODE_RR __THUNK_BR,\reg,\ruse
+ .pushsection .s390_indirect_branches,"a",@progbits
+ .long 557b-.
+ .popsection
+ .endm
+
+ .macro B_EX disp,reg,ruse=%r1
+558: __DECODE_DRR __THUNK_BC,\disp,\reg,\ruse
+ .pushsection .s390_indirect_branches,"a",@progbits
+ .long 558b-.
+ .popsection
+ .endm
+
+ .macro BASR_EX rsave,rtarget,ruse=%r1
+559: __DECODE_RRR __THUNK_BRASL,\rsave,\rtarget,\ruse
+ .pushsection .s390_indirect_branches,"a",@progbits
+ .long 559b-.
+ .popsection
+ .endm
+
+#else
+ .macro GEN_BR_THUNK reg,ruse=%r1
+ .endm
+
+ .macro GEN_B_THUNK disp,reg,ruse=%r1
+ .endm
+
+ .macro BR_EX reg,ruse=%r1
+ br \reg
+ .endm
+
+ .macro B_EX disp,reg,ruse=%r1
+ b \disp(\reg)
+ .endm
+
+ .macro BASR_EX rsave,rtarget,ruse=%r1
+ basr \rsave,\rtarget
+ .endm
+#endif
+
+#endif /* __ASSEMBLY__ */
+
+#endif /* _ASM_S390_NOSPEC_ASM_H */
diff --git a/arch/s390/kernel/Makefile b/arch/s390/kernel/Makefile
index 0501cac..5b13997 100644
--- a/arch/s390/kernel/Makefile
+++ b/arch/s390/kernel/Makefile
@@ -63,6 +63,7 @@
extra-y += head.o head64.o vmlinux.lds
+obj-$(CONFIG_SYSFS) += nospec-sysfs.o
CFLAGS_REMOVE_nospec-branch.o += $(CC_FLAGS_EXPOLINE)
obj-$(CONFIG_MODULES) += module.o
diff --git a/arch/s390/kernel/asm-offsets.c b/arch/s390/kernel/asm-offsets.c
index f3df9e0..85c8ead 100644
--- a/arch/s390/kernel/asm-offsets.c
+++ b/arch/s390/kernel/asm-offsets.c
@@ -175,6 +175,7 @@
OFFSET(__LC_MACHINE_FLAGS, lowcore, machine_flags);
OFFSET(__LC_GMAP, lowcore, gmap);
OFFSET(__LC_PASTE, lowcore, paste);
+ OFFSET(__LC_BR_R1, lowcore, br_r1_trampoline);
/* software defined ABI-relevant lowcore locations 0xe00 - 0xe20 */
OFFSET(__LC_DUMP_REIPL, lowcore, ipib);
/* hardware defined lowcore locations 0x1000 - 0x18ff */
diff --git a/arch/s390/kernel/base.S b/arch/s390/kernel/base.S
index 326f717..61fca54 100644
--- a/arch/s390/kernel/base.S
+++ b/arch/s390/kernel/base.S
@@ -8,18 +8,22 @@
#include <linux/linkage.h>
#include <asm/asm-offsets.h>
+#include <asm/nospec-insn.h>
#include <asm/ptrace.h>
#include <asm/sigp.h>
+ GEN_BR_THUNK %r9
+ GEN_BR_THUNK %r14
+
ENTRY(s390_base_mcck_handler)
basr %r13,0
0: lg %r15,__LC_PANIC_STACK # load panic stack
aghi %r15,-STACK_FRAME_OVERHEAD
larl %r1,s390_base_mcck_handler_fn
- lg %r1,0(%r1)
- ltgr %r1,%r1
+ lg %r9,0(%r1)
+ ltgr %r9,%r9
jz 1f
- basr %r14,%r1
+ BASR_EX %r14,%r9
1: la %r1,4095
lmg %r0,%r15,__LC_GPREGS_SAVE_AREA-4095(%r1)
lpswe __LC_MCK_OLD_PSW
@@ -36,10 +40,10 @@
basr %r13,0
0: aghi %r15,-STACK_FRAME_OVERHEAD
larl %r1,s390_base_ext_handler_fn
- lg %r1,0(%r1)
- ltgr %r1,%r1
+ lg %r9,0(%r1)
+ ltgr %r9,%r9
jz 1f
- basr %r14,%r1
+ BASR_EX %r14,%r9
1: lmg %r0,%r15,__LC_SAVE_AREA_ASYNC
ni __LC_EXT_OLD_PSW+1,0xfd # clear wait state bit
lpswe __LC_EXT_OLD_PSW
@@ -56,10 +60,10 @@
basr %r13,0
0: aghi %r15,-STACK_FRAME_OVERHEAD
larl %r1,s390_base_pgm_handler_fn
- lg %r1,0(%r1)
- ltgr %r1,%r1
+ lg %r9,0(%r1)
+ ltgr %r9,%r9
jz 1f
- basr %r14,%r1
+ BASR_EX %r14,%r9
lmg %r0,%r15,__LC_SAVE_AREA_SYNC
lpswe __LC_PGM_OLD_PSW
1: lpswe disabled_wait_psw-0b(%r13)
@@ -116,7 +120,7 @@
larl %r4,.Lcontinue_psw # Restore PSW flags
lpswe 0(%r4)
.Lcontinue:
- br %r14
+ BR_EX %r14
.align 16
.Lrestart_psw:
.long 0x00080000,0x80000000 + .Lrestart_part2
diff --git a/arch/s390/kernel/entry.S b/arch/s390/kernel/entry.S
index 1996afe..a4fd000 100644
--- a/arch/s390/kernel/entry.S
+++ b/arch/s390/kernel/entry.S
@@ -24,6 +24,7 @@
#include <asm/setup.h>
#include <asm/nmi.h>
#include <asm/export.h>
+#include <asm/nospec-insn.h>
__PT_R0 = __PT_GPRS
__PT_R1 = __PT_GPRS + 8
@@ -226,67 +227,9 @@
.popsection
.endm
-#ifdef CONFIG_EXPOLINE
-
- .macro GEN_BR_THUNK name,reg,tmp
- .section .text.\name,"axG",@progbits,\name,comdat
- .globl \name
- .hidden \name
- .type \name,@function
-\name:
- .cfi_startproc
-#ifdef CONFIG_HAVE_MARCH_Z10_FEATURES
- exrl 0,0f
-#else
- larl \tmp,0f
- ex 0,0(\tmp)
-#endif
- j .
-0: br \reg
- .cfi_endproc
- .endm
-
- GEN_BR_THUNK __s390x_indirect_jump_r1use_r9,%r9,%r1
- GEN_BR_THUNK __s390x_indirect_jump_r1use_r14,%r14,%r1
- GEN_BR_THUNK __s390x_indirect_jump_r11use_r14,%r14,%r11
-
- .macro BASR_R14_R9
-0: brasl %r14,__s390x_indirect_jump_r1use_r9
- .pushsection .s390_indirect_branches,"a",@progbits
- .long 0b-.
- .popsection
- .endm
-
- .macro BR_R1USE_R14
-0: jg __s390x_indirect_jump_r1use_r14
- .pushsection .s390_indirect_branches,"a",@progbits
- .long 0b-.
- .popsection
- .endm
-
- .macro BR_R11USE_R14
-0: jg __s390x_indirect_jump_r11use_r14
- .pushsection .s390_indirect_branches,"a",@progbits
- .long 0b-.
- .popsection
- .endm
-
-#else /* CONFIG_EXPOLINE */
-
- .macro BASR_R14_R9
- basr %r14,%r9
- .endm
-
- .macro BR_R1USE_R14
- br %r14
- .endm
-
- .macro BR_R11USE_R14
- br %r14
- .endm
-
-#endif /* CONFIG_EXPOLINE */
-
+ GEN_BR_THUNK %r9
+ GEN_BR_THUNK %r14
+ GEN_BR_THUNK %r14,%r11
.section .kprobes.text, "ax"
.Ldummy:
@@ -303,7 +246,7 @@
ENTRY(__bpon)
.globl __bpon
BPON
- BR_R1USE_R14
+ BR_EX %r14
/*
* Scheduler resume function, called by switch_to
@@ -333,7 +276,7 @@
TSTMSK __LC_MACHINE_FLAGS,MACHINE_FLAG_LPP
jz 0f
.insn s,0xb2800000,__LC_LPP # set program parameter
-0: BR_R1USE_R14
+0: BR_EX %r14
.L__critical_start:
@@ -399,7 +342,7 @@
xgr %r5,%r5
lmg %r6,%r14,__SF_GPRS(%r15) # restore kernel registers
lg %r2,__SF_EMPTY+16(%r15) # return exit reason code
- BR_R1USE_R14
+ BR_EX %r14
.Lsie_fault:
lghi %r14,-EFAULT
stg %r14,__SF_EMPTY+16(%r15) # set exit reason code
@@ -458,7 +401,7 @@
lgf %r9,0(%r8,%r10) # get system call add.
TSTMSK __TI_flags(%r12),_TIF_TRACE
jnz .Lsysc_tracesys
- BASR_R14_R9 # call sys_xxxx
+ BASR_EX %r14,%r9 # call sys_xxxx
stg %r2,__PT_R2(%r11) # store return value
.Lsysc_return:
@@ -598,7 +541,7 @@
lmg %r3,%r7,__PT_R3(%r11)
stg %r7,STACK_FRAME_OVERHEAD(%r15)
lg %r2,__PT_ORIG_GPR2(%r11)
- BASR_R14_R9 # call sys_xxx
+ BASR_EX %r14,%r9 # call sys_xxx
stg %r2,__PT_R2(%r11) # store return value
.Lsysc_tracenogo:
TSTMSK __TI_flags(%r12),_TIF_TRACE
@@ -622,7 +565,7 @@
lmg %r9,%r10,__PT_R9(%r11) # load gprs
ENTRY(kernel_thread_starter)
la %r2,0(%r10)
- BASR_R14_R9
+ BASR_EX %r14,%r9
j .Lsysc_tracenogo
/*
@@ -698,7 +641,7 @@
je .Lpgm_return
lgf %r9,0(%r10,%r1) # load address of handler routine
lgr %r2,%r11 # pass pointer to pt_regs
- BASR_R14_R9 # branch to interrupt-handler
+ BASR_EX %r14,%r9 # branch to interrupt-handler
.Lpgm_return:
LOCKDEP_SYS_EXIT
tm __PT_PSW+1(%r11),0x01 # returning to user ?
@@ -976,7 +919,7 @@
stpt __TIMER_IDLE_ENTER(%r2)
.Lpsw_idle_lpsw:
lpswe __SF_EMPTY(%r15)
- BR_R1USE_R14
+ BR_EX %r14
.Lpsw_idle_end:
/*
@@ -1021,7 +964,7 @@
.Lsave_fpu_regs_done:
oi __LC_CPU_FLAGS+7,_CIF_FPU
.Lsave_fpu_regs_exit:
- BR_R1USE_R14
+ BR_EX %r14
.Lsave_fpu_regs_end:
#if IS_ENABLED(CONFIG_KVM)
EXPORT_SYMBOL(save_fpu_regs)
@@ -1071,7 +1014,7 @@
.Lload_fpu_regs_done:
ni __LC_CPU_FLAGS+7,255-_CIF_FPU
.Lload_fpu_regs_exit:
- BR_R1USE_R14
+ BR_EX %r14
.Lload_fpu_regs_end:
.L__critical_end:
@@ -1244,7 +1187,7 @@
jl 0f
clg %r9,BASED(.Lcleanup_table+104) # .Lload_fpu_regs_end
jl .Lcleanup_load_fpu_regs
-0: BR_R11USE_R14
+0: BR_EX %r14
.align 8
.Lcleanup_table:
@@ -1274,7 +1217,7 @@
ni __SIE_PROG0C+3(%r9),0xfe # no longer in SIE
lctlg %c1,%c1,__LC_USER_ASCE # load primary asce
larl %r9,sie_exit # skip forward to sie_exit
- BR_R11USE_R14
+ BR_EX %r14
#endif
.Lcleanup_system_call:
@@ -1332,7 +1275,7 @@
stg %r15,56(%r11) # r15 stack pointer
# set new psw address and exit
larl %r9,.Lsysc_do_svc
- BR_R11USE_R14
+ BR_EX %r14,%r11
.Lcleanup_system_call_insn:
.quad system_call
.quad .Lsysc_stmg
@@ -1342,7 +1285,7 @@
.Lcleanup_sysc_tif:
larl %r9,.Lsysc_tif
- BR_R11USE_R14
+ BR_EX %r14,%r11
.Lcleanup_sysc_restore:
# check if stpt has been executed
@@ -1359,14 +1302,14 @@
mvc 0(64,%r11),__PT_R8(%r9)
lmg %r0,%r7,__PT_R0(%r9)
1: lmg %r8,%r9,__LC_RETURN_PSW
- BR_R11USE_R14
+ BR_EX %r14,%r11
.Lcleanup_sysc_restore_insn:
.quad .Lsysc_exit_timer
.quad .Lsysc_done - 4
.Lcleanup_io_tif:
larl %r9,.Lio_tif
- BR_R11USE_R14
+ BR_EX %r14,%r11
.Lcleanup_io_restore:
# check if stpt has been executed
@@ -1380,7 +1323,7 @@
mvc 0(64,%r11),__PT_R8(%r9)
lmg %r0,%r7,__PT_R0(%r9)
1: lmg %r8,%r9,__LC_RETURN_PSW
- BR_R11USE_R14
+ BR_EX %r14,%r11
.Lcleanup_io_restore_insn:
.quad .Lio_exit_timer
.quad .Lio_done - 4
@@ -1433,17 +1376,17 @@
# prepare return psw
nihh %r8,0xfcfd # clear irq & wait state bits
lg %r9,48(%r11) # return from psw_idle
- BR_R11USE_R14
+ BR_EX %r14,%r11
.Lcleanup_idle_insn:
.quad .Lpsw_idle_lpsw
.Lcleanup_save_fpu_regs:
larl %r9,save_fpu_regs
- BR_R11USE_R14
+ BR_EX %r14,%r11
.Lcleanup_load_fpu_regs:
larl %r9,load_fpu_regs
- BR_R11USE_R14
+ BR_EX %r14,%r11
/*
* Integer constants
diff --git a/arch/s390/kernel/irq.c b/arch/s390/kernel/irq.c
index 285d656..7ff9767 100644
--- a/arch/s390/kernel/irq.c
+++ b/arch/s390/kernel/irq.c
@@ -173,10 +173,9 @@
new -= STACK_FRAME_OVERHEAD;
((struct stack_frame *) new)->back_chain = old;
asm volatile(" la 15,0(%0)\n"
- " basr 14,%2\n"
+ " brasl 14,__do_softirq\n"
" la 15,0(%1)\n"
- : : "a" (new), "a" (old),
- "a" (__do_softirq)
+ : : "a" (new), "a" (old)
: "0", "1", "2", "3", "4", "5", "14",
"cc", "memory" );
} else {
diff --git a/arch/s390/kernel/mcount.S b/arch/s390/kernel/mcount.S
index 9a17e44..be75e8e 100644
--- a/arch/s390/kernel/mcount.S
+++ b/arch/s390/kernel/mcount.S
@@ -8,13 +8,17 @@
#include <linux/linkage.h>
#include <asm/asm-offsets.h>
#include <asm/ftrace.h>
+#include <asm/nospec-insn.h>
#include <asm/ptrace.h>
#include <asm/export.h>
+ GEN_BR_THUNK %r1
+ GEN_BR_THUNK %r14
+
.section .kprobes.text, "ax"
ENTRY(ftrace_stub)
- br %r14
+ BR_EX %r14
#define STACK_FRAME_SIZE (STACK_FRAME_OVERHEAD + __PT_SIZE)
#define STACK_PTREGS (STACK_FRAME_OVERHEAD)
@@ -22,7 +26,7 @@
#define STACK_PTREGS_PSW (STACK_PTREGS + __PT_PSW)
ENTRY(_mcount)
- br %r14
+ BR_EX %r14
EXPORT_SYMBOL(_mcount)
@@ -52,7 +56,7 @@
#endif
lgr %r3,%r14
la %r5,STACK_PTREGS(%r15)
- basr %r14,%r1
+ BASR_EX %r14,%r1
#ifdef CONFIG_FUNCTION_GRAPH_TRACER
# The j instruction gets runtime patched to a nop instruction.
# See ftrace_enable_ftrace_graph_caller.
@@ -67,7 +71,7 @@
#endif
lg %r1,(STACK_PTREGS_PSW+8)(%r15)
lmg %r2,%r15,(STACK_PTREGS_GPRS+2*8)(%r15)
- br %r1
+ BR_EX %r1
#ifdef CONFIG_FUNCTION_GRAPH_TRACER
@@ -80,6 +84,6 @@
aghi %r15,STACK_FRAME_OVERHEAD
lgr %r14,%r2
lmg %r2,%r5,32(%r15)
- br %r14
+ BR_EX %r14
#endif
diff --git a/arch/s390/kernel/nospec-branch.c b/arch/s390/kernel/nospec-branch.c
index 9f3b5b3..d5eed65 100644
--- a/arch/s390/kernel/nospec-branch.c
+++ b/arch/s390/kernel/nospec-branch.c
@@ -44,24 +44,6 @@
}
arch_initcall(nospec_report);
-#ifdef CONFIG_SYSFS
-ssize_t cpu_show_spectre_v1(struct device *dev,
- struct device_attribute *attr, char *buf)
-{
- return sprintf(buf, "Mitigation: __user pointer sanitization\n");
-}
-
-ssize_t cpu_show_spectre_v2(struct device *dev,
- struct device_attribute *attr, char *buf)
-{
- if (IS_ENABLED(CC_USING_EXPOLINE) && !nospec_disable)
- return sprintf(buf, "Mitigation: execute trampolines\n");
- if (__test_facility(82, S390_lowcore.alt_stfle_fac_list))
- return sprintf(buf, "Mitigation: limited branch prediction.\n");
- return sprintf(buf, "Vulnerable\n");
-}
-#endif
-
#ifdef CONFIG_EXPOLINE
int nospec_disable = IS_ENABLED(CONFIG_EXPOLINE_OFF);
@@ -112,7 +94,6 @@
s32 *epo;
/* Second part of the instruction replace is always a nop */
- memcpy(insnbuf + 2, (char[]) { 0x47, 0x00, 0x00, 0x00 }, 4);
for (epo = start; epo < end; epo++) {
instr = (u8 *) epo + *epo;
if (instr[0] == 0xc0 && (instr[1] & 0x0f) == 0x04)
@@ -133,18 +114,34 @@
br = thunk + (*(int *)(thunk + 2)) * 2;
else
continue;
- if (br[0] != 0x07 || (br[1] & 0xf0) != 0xf0)
+ /* Check for unconditional branch 0x07f? or 0x47f???? */
+ if ((br[0] & 0xbf) != 0x07 || (br[1] & 0xf0) != 0xf0)
continue;
+
+ memcpy(insnbuf + 2, (char[]) { 0x47, 0x00, 0x07, 0x00 }, 4);
switch (type) {
case BRCL_EXPOLINE:
- /* brcl to thunk, replace with br + nop */
insnbuf[0] = br[0];
insnbuf[1] = (instr[1] & 0xf0) | (br[1] & 0x0f);
+ if (br[0] == 0x47) {
+ /* brcl to b, replace with bc + nopr */
+ insnbuf[2] = br[2];
+ insnbuf[3] = br[3];
+ } else {
+ /* brcl to br, replace with bcr + nop */
+ }
break;
case BRASL_EXPOLINE:
- /* brasl to thunk, replace with basr + nop */
- insnbuf[0] = 0x0d;
insnbuf[1] = (instr[1] & 0xf0) | (br[1] & 0x0f);
+ if (br[0] == 0x47) {
+ /* brasl to b, replace with bas + nopr */
+ insnbuf[0] = 0x4d;
+ insnbuf[2] = br[2];
+ insnbuf[3] = br[3];
+ } else {
+ /* brasl to br, replace with basr + nop */
+ insnbuf[0] = 0x0d;
+ }
break;
}
diff --git a/arch/s390/kernel/nospec-sysfs.c b/arch/s390/kernel/nospec-sysfs.c
new file mode 100644
index 0000000..8affad5
--- /dev/null
+++ b/arch/s390/kernel/nospec-sysfs.c
@@ -0,0 +1,21 @@
+// SPDX-License-Identifier: GPL-2.0
+#include <linux/device.h>
+#include <linux/cpu.h>
+#include <asm/facility.h>
+#include <asm/nospec-branch.h>
+
+ssize_t cpu_show_spectre_v1(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ return sprintf(buf, "Mitigation: __user pointer sanitization\n");
+}
+
+ssize_t cpu_show_spectre_v2(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ if (IS_ENABLED(CC_USING_EXPOLINE) && !nospec_disable)
+ return sprintf(buf, "Mitigation: execute trampolines\n");
+ if (__test_facility(82, S390_lowcore.alt_stfle_fac_list))
+ return sprintf(buf, "Mitigation: limited branch prediction\n");
+ return sprintf(buf, "Vulnerable\n");
+}
diff --git a/arch/s390/kernel/perf_cpum_sf.c b/arch/s390/kernel/perf_cpum_sf.c
index fcc634c..96e4fca 100644
--- a/arch/s390/kernel/perf_cpum_sf.c
+++ b/arch/s390/kernel/perf_cpum_sf.c
@@ -739,6 +739,10 @@
*/
rate = 0;
if (attr->freq) {
+ if (!attr->sample_freq) {
+ err = -EINVAL;
+ goto out;
+ }
rate = freq_to_sample_rate(&si, attr->sample_freq);
rate = hw_limit_rate(&si, rate);
attr->freq = 0;
diff --git a/arch/s390/kernel/reipl.S b/arch/s390/kernel/reipl.S
index 89ea8c2..70d635d 100644
--- a/arch/s390/kernel/reipl.S
+++ b/arch/s390/kernel/reipl.S
@@ -6,8 +6,11 @@
#include <linux/linkage.h>
#include <asm/asm-offsets.h>
+#include <asm/nospec-insn.h>
#include <asm/sigp.h>
+ GEN_BR_THUNK %r9
+
#
# Issue "store status" for the current CPU to its prefix page
# and call passed function afterwards
@@ -66,9 +69,9 @@
st %r4,0(%r1)
st %r5,4(%r1)
stg %r2,8(%r1)
- lgr %r1,%r2
+ lgr %r9,%r2
lgr %r2,%r3
- br %r1
+ BR_EX %r9
.section .bss
.align 8
diff --git a/arch/s390/kernel/swsusp.S b/arch/s390/kernel/swsusp.S
index 2d6b6e8..4e76aaf 100644
--- a/arch/s390/kernel/swsusp.S
+++ b/arch/s390/kernel/swsusp.S
@@ -12,6 +12,7 @@
#include <asm/ptrace.h>
#include <asm/thread_info.h>
#include <asm/asm-offsets.h>
+#include <asm/nospec-insn.h>
#include <asm/sigp.h>
/*
@@ -23,6 +24,8 @@
* (see below) in the resume process.
* This function runs with disabled interrupts.
*/
+ GEN_BR_THUNK %r14
+
.section .text
ENTRY(swsusp_arch_suspend)
stmg %r6,%r15,__SF_GPRS(%r15)
@@ -102,7 +105,7 @@
spx 0x318(%r1)
lmg %r6,%r15,STACK_FRAME_OVERHEAD + __SF_GPRS(%r15)
lghi %r2,0
- br %r14
+ BR_EX %r14
/*
* Restore saved memory image to correct place and restore register context.
@@ -200,7 +203,7 @@
lghi %r1,0
sam31
sigp %r1,%r0,SIGP_SET_ARCHITECTURE
- basr %r14,%r3
+ brasl %r14,_sclp_print_early
larl %r3,.Ldisabled_wait_31
lpsw 0(%r3)
4:
@@ -266,7 +269,7 @@
/* Return 0 */
lmg %r6,%r15,STACK_FRAME_OVERHEAD + __SF_GPRS(%r15)
lghi %r2,0
- br %r14
+ BR_EX %r14
.section .data..nosave,"aw",@progbits
.align 8
diff --git a/arch/s390/lib/mem.S b/arch/s390/lib/mem.S
index be9fa65..e7672ed 100644
--- a/arch/s390/lib/mem.S
+++ b/arch/s390/lib/mem.S
@@ -6,6 +6,9 @@
#include <linux/linkage.h>
#include <asm/export.h>
+#include <asm/nospec-insn.h>
+
+ GEN_BR_THUNK %r14
/*
* memset implementation
@@ -39,7 +42,7 @@
.Lmemset_clear_rest:
larl %r3,.Lmemset_xc
ex %r4,0(%r3)
- br %r14
+ BR_EX %r14
.Lmemset_fill:
stc %r3,0(%r2)
cghi %r4,1
@@ -56,7 +59,7 @@
.Lmemset_fill_rest:
larl %r3,.Lmemset_mvc
ex %r4,0(%r3)
- br %r14
+ BR_EX %r14
.Lmemset_xc:
xc 0(1,%r1),0(%r1)
.Lmemset_mvc:
@@ -79,7 +82,7 @@
.Lmemcpy_rest:
larl %r5,.Lmemcpy_mvc
ex %r4,0(%r5)
- br %r14
+ BR_EX %r14
.Lmemcpy_loop:
mvc 0(256,%r1),0(%r3)
la %r1,256(%r1)
diff --git a/arch/s390/net/bpf_jit.S b/arch/s390/net/bpf_jit.S
index a1c917d..fa716f2 100644
--- a/arch/s390/net/bpf_jit.S
+++ b/arch/s390/net/bpf_jit.S
@@ -8,6 +8,7 @@
*/
#include <linux/linkage.h>
+#include <asm/nospec-insn.h>
#include "bpf_jit.h"
/*
@@ -53,7 +54,7 @@
clg %r3,STK_OFF_HLEN(%r15); /* Offset + SIZE > hlen? */ \
jh sk_load_##NAME##_slow; \
LOAD %r14,-SIZE(%r3,%r12); /* Get data from skb */ \
- b OFF_OK(%r6); /* Return */ \
+ B_EX OFF_OK,%r6; /* Return */ \
\
sk_load_##NAME##_slow:; \
lgr %r2,%r7; /* Arg1 = skb pointer */ \
@@ -63,11 +64,14 @@
brasl %r14,skb_copy_bits; /* Get data from skb */ \
LOAD %r14,STK_OFF_TMP(%r15); /* Load from temp bufffer */ \
ltgr %r2,%r2; /* Set cc to (%r2 != 0) */ \
- br %r6; /* Return */
+ BR_EX %r6; /* Return */
sk_load_common(word, 4, llgf) /* r14 = *(u32 *) (skb->data+offset) */
sk_load_common(half, 2, llgh) /* r14 = *(u16 *) (skb->data+offset) */
+ GEN_BR_THUNK %r6
+ GEN_B_THUNK OFF_OK,%r6
+
/*
* Load 1 byte from SKB (optimized version)
*/
@@ -79,7 +83,7 @@
clg %r3,STK_OFF_HLEN(%r15) # Offset >= hlen?
jnl sk_load_byte_slow
llgc %r14,0(%r3,%r12) # Get byte from skb
- b OFF_OK(%r6) # Return OK
+ B_EX OFF_OK,%r6 # Return OK
sk_load_byte_slow:
lgr %r2,%r7 # Arg1 = skb pointer
@@ -89,7 +93,7 @@
brasl %r14,skb_copy_bits # Get data from skb
llgc %r14,STK_OFF_TMP(%r15) # Load result from temp buffer
ltgr %r2,%r2 # Set cc to (%r2 != 0)
- br %r6 # Return cc
+ BR_EX %r6 # Return cc
#define sk_negative_common(NAME, SIZE, LOAD) \
sk_load_##NAME##_slow_neg:; \
@@ -103,7 +107,7 @@
jz bpf_error; \
LOAD %r14,0(%r2); /* Get data from pointer */ \
xr %r3,%r3; /* Set cc to zero */ \
- br %r6; /* Return cc */
+ BR_EX %r6; /* Return cc */
sk_negative_common(word, 4, llgf)
sk_negative_common(half, 2, llgh)
@@ -112,4 +116,4 @@
bpf_error:
# force a return 0 from jit handler
ltgr %r15,%r15 # Set condition code
- br %r6
+ BR_EX %r6
diff --git a/arch/s390/net/bpf_jit_comp.c b/arch/s390/net/bpf_jit_comp.c
index e8dee62..e7ce257 100644
--- a/arch/s390/net/bpf_jit_comp.c
+++ b/arch/s390/net/bpf_jit_comp.c
@@ -24,6 +24,8 @@
#include <linux/bpf.h>
#include <asm/cacheflush.h>
#include <asm/dis.h>
+#include <asm/facility.h>
+#include <asm/nospec-branch.h>
#include "bpf_jit.h"
int bpf_jit_enable __read_mostly;
@@ -41,6 +43,8 @@
int base_ip; /* Base address for literal pool */
int ret0_ip; /* Address of return 0 */
int exit_ip; /* Address of exit */
+ int r1_thunk_ip; /* Address of expoline thunk for 'br %r1' */
+ int r14_thunk_ip; /* Address of expoline thunk for 'br %r14' */
int tail_call_start; /* Tail call start offset */
int labels[1]; /* Labels for local jumps */
};
@@ -251,6 +255,19 @@
REG_SET_SEEN(b2); \
})
+#define EMIT6_PCREL_RILB(op, b, target) \
+({ \
+ int rel = (target - jit->prg) / 2; \
+ _EMIT6(op | reg_high(b) << 16 | rel >> 16, rel & 0xffff); \
+ REG_SET_SEEN(b); \
+})
+
+#define EMIT6_PCREL_RIL(op, target) \
+({ \
+ int rel = (target - jit->prg) / 2; \
+ _EMIT6(op | rel >> 16, rel & 0xffff); \
+})
+
#define _EMIT6_IMM(op, imm) \
({ \
unsigned int __imm = (imm); \
@@ -470,8 +487,45 @@
EMIT4(0xb9040000, REG_2, BPF_REG_0);
/* Restore registers */
save_restore_regs(jit, REGS_RESTORE);
+ if (IS_ENABLED(CC_USING_EXPOLINE) && !nospec_disable) {
+ jit->r14_thunk_ip = jit->prg;
+ /* Generate __s390_indirect_jump_r14 thunk */
+ if (test_facility(35)) {
+ /* exrl %r0,.+10 */
+ EMIT6_PCREL_RIL(0xc6000000, jit->prg + 10);
+ } else {
+ /* larl %r1,.+14 */
+ EMIT6_PCREL_RILB(0xc0000000, REG_1, jit->prg + 14);
+ /* ex 0,0(%r1) */
+ EMIT4_DISP(0x44000000, REG_0, REG_1, 0);
+ }
+ /* j . */
+ EMIT4_PCREL(0xa7f40000, 0);
+ }
/* br %r14 */
_EMIT2(0x07fe);
+
+ if (IS_ENABLED(CC_USING_EXPOLINE) && !nospec_disable &&
+ (jit->seen & SEEN_FUNC)) {
+ jit->r1_thunk_ip = jit->prg;
+ /* Generate __s390_indirect_jump_r1 thunk */
+ if (test_facility(35)) {
+ /* exrl %r0,.+10 */
+ EMIT6_PCREL_RIL(0xc6000000, jit->prg + 10);
+ /* j . */
+ EMIT4_PCREL(0xa7f40000, 0);
+ /* br %r1 */
+ _EMIT2(0x07f1);
+ } else {
+ /* larl %r1,.+14 */
+ EMIT6_PCREL_RILB(0xc0000000, REG_1, jit->prg + 14);
+ /* ex 0,S390_lowcore.br_r1_tampoline */
+ EMIT4_DISP(0x44000000, REG_0, REG_0,
+ offsetof(struct lowcore, br_r1_trampoline));
+ /* j . */
+ EMIT4_PCREL(0xa7f40000, 0);
+ }
+ }
}
/*
@@ -977,8 +1031,13 @@
/* lg %w1,<d(imm)>(%l) */
EMIT6_DISP_LH(0xe3000000, 0x0004, REG_W1, REG_0, REG_L,
EMIT_CONST_U64(func));
- /* basr %r14,%w1 */
- EMIT2(0x0d00, REG_14, REG_W1);
+ if (IS_ENABLED(CC_USING_EXPOLINE) && !nospec_disable) {
+ /* brasl %r14,__s390_indirect_jump_r1 */
+ EMIT6_PCREL_RILB(0xc0050000, REG_14, jit->r1_thunk_ip);
+ } else {
+ /* basr %r14,%w1 */
+ EMIT2(0x0d00, REG_14, REG_W1);
+ }
/* lgr %b0,%r2: load return value into %b0 */
EMIT4(0xb9040000, BPF_REG_0, REG_2);
if (bpf_helper_changes_skb_data((void *)func)) {
diff --git a/arch/x86/boot/compressed/eboot.c b/arch/x86/boot/compressed/eboot.c
index cc69e37..c0ad1bb 100644
--- a/arch/x86/boot/compressed/eboot.c
+++ b/arch/x86/boot/compressed/eboot.c
@@ -330,7 +330,8 @@
if (status != EFI_SUCCESS)
goto free_struct;
- memcpy(rom->romdata, pci->romimage, pci->romsize);
+ memcpy(rom->romdata, (void *)(unsigned long)pci->romimage,
+ pci->romsize);
return status;
free_struct:
@@ -436,7 +437,8 @@
if (status != EFI_SUCCESS)
goto free_struct;
- memcpy(rom->romdata, pci->romimage, pci->romsize);
+ memcpy(rom->romdata, (void *)(unsigned long)pci->romimage,
+ pci->romsize);
return status;
free_struct:
diff --git a/arch/x86/entry/vdso/Makefile b/arch/x86/entry/vdso/Makefile
index d540966..51a858e 100644
--- a/arch/x86/entry/vdso/Makefile
+++ b/arch/x86/entry/vdso/Makefile
@@ -171,7 +171,8 @@
sh $(srctree)/$(src)/checkundef.sh '$(NM)' '$@'
VDSO_LDFLAGS = -fPIC -shared $(call cc-ldoption, -Wl$(comma)--hash-style=both) \
- $(call cc-ldoption, -Wl$(comma)--build-id) -Wl,-Bsymbolic $(LTO_CFLAGS)
+ $(call cc-ldoption, -Wl$(comma)--build-id) -Wl,-Bsymbolic $(LTO_CFLAGS) \
+ $(filter --target=% --gcc-toolchain=%,$(KBUILD_CFLAGS))
GCOV_PROFILE := n
#
diff --git a/arch/x86/include/asm/cpufeatures.h b/arch/x86/include/asm/cpufeatures.h
index a248531..c278f27 100644
--- a/arch/x86/include/asm/cpufeatures.h
+++ b/arch/x86/include/asm/cpufeatures.h
@@ -197,6 +197,9 @@
#define X86_FEATURE_RETPOLINE ( 7*32+12) /* "" Generic Retpoline mitigation for Spectre variant 2 */
#define X86_FEATURE_RETPOLINE_AMD ( 7*32+13) /* "" AMD Retpoline mitigation for Spectre variant 2 */
+#define X86_FEATURE_MSR_SPEC_CTRL ( 7*32+16) /* "" MSR SPEC_CTRL is implemented */
+#define X86_FEATURE_SSBD ( 7*32+17) /* Speculative Store Bypass Disable */
+
#define X86_FEATURE_RSB_CTXSW ( 7*32+19) /* "" Fill RSB on context switches */
/* Because the ALTERNATIVE scheme is for members of the X86_FEATURE club... */
@@ -204,6 +207,13 @@
#define X86_FEATURE_USE_IBPB ( 7*32+21) /* "" Indirect Branch Prediction Barrier enabled */
#define X86_FEATURE_USE_IBRS_FW ( 7*32+22) /* "" Use IBRS during runtime firmware calls */
+#define X86_FEATURE_SPEC_STORE_BYPASS_DISABLE ( 7*32+23) /* "" Disable Speculative Store Bypass. */
+#define X86_FEATURE_LS_CFG_SSBD ( 7*32+24) /* "" AMD SSBD implementation */
+#define X86_FEATURE_IBRS ( 7*32+25) /* Indirect Branch Restricted Speculation */
+#define X86_FEATURE_IBPB ( 7*32+26) /* Indirect Branch Prediction Barrier */
+#define X86_FEATURE_STIBP ( 7*32+27) /* Single Thread Indirect Branch Predictors */
+#define X86_FEATURE_ZEN ( 7*32+28) /* "" CPU is AMD family 0x17 (Zen) */
+
/* Virtualization flags: Linux defined, word 8 */
#define X86_FEATURE_TPR_SHADOW ( 8*32+ 0) /* Intel TPR Shadow */
@@ -261,9 +271,10 @@
/* AMD-defined CPU features, CPUID level 0x80000008 (ebx), word 13 */
#define X86_FEATURE_CLZERO (13*32+0) /* CLZERO instruction */
#define X86_FEATURE_IRPERF (13*32+1) /* Instructions Retired Count */
-#define X86_FEATURE_IBPB (13*32+12) /* Indirect Branch Prediction Barrier */
-#define X86_FEATURE_IBRS (13*32+14) /* Indirect Branch Restricted Speculation */
-#define X86_FEATURE_STIBP (13*32+15) /* Single Thread Indirect Branch Predictors */
+#define X86_FEATURE_AMD_IBPB (13*32+12) /* Indirect Branch Prediction Barrier */
+#define X86_FEATURE_AMD_IBRS (13*32+14) /* Indirect Branch Restricted Speculation */
+#define X86_FEATURE_AMD_STIBP (13*32+15) /* Single Thread Indirect Branch Predictors */
+#define X86_FEATURE_VIRT_SSBD (13*32+25) /* Virtualized Speculative Store Bypass Disable */
/* Thermal and Power Management Leaf, CPUID level 0x00000006 (eax), word 14 */
#define X86_FEATURE_DTHERM (14*32+ 0) /* Digital Thermal Sensor */
@@ -299,6 +310,7 @@
#define X86_FEATURE_SUCCOR (17*32+1) /* Uncorrectable error containment and recovery */
#define X86_FEATURE_SMCA (17*32+3) /* Scalable MCA */
+
/* Intel-defined CPU features, CPUID level 0x00000007:0 (EDX), word 18 */
#define X86_FEATURE_AVX512_4VNNIW (18*32+ 2) /* AVX-512 Neural Network Instructions */
#define X86_FEATURE_AVX512_4FMAPS (18*32+ 3) /* AVX-512 Multiply Accumulation Single precision */
@@ -306,6 +318,7 @@
#define X86_FEATURE_SPEC_CTRL (18*32+26) /* "" Speculation Control (IBRS + IBPB) */
#define X86_FEATURE_INTEL_STIBP (18*32+27) /* "" Single Thread Indirect Branch Predictors */
#define X86_FEATURE_ARCH_CAPABILITIES (18*32+29) /* IA32_ARCH_CAPABILITIES MSR (Intel) */
+#define X86_FEATURE_SPEC_CTRL_SSBD (18*32+31) /* "" Speculative Store Bypass Disable */
/*
* BUG word(s)
@@ -335,5 +348,6 @@
#define X86_BUG_CPU_MELTDOWN X86_BUG(14) /* CPU is affected by meltdown attack and needs kernel page table isolation */
#define X86_BUG_SPECTRE_V1 X86_BUG(15) /* CPU is affected by Spectre variant 1 attack with conditional branches */
#define X86_BUG_SPECTRE_V2 X86_BUG(16) /* CPU is affected by Spectre variant 2 attack with indirect branches */
+#define X86_BUG_SPEC_STORE_BYPASS X86_BUG(17) /* CPU is affected by speculative store bypass attack */
#endif /* _ASM_X86_CPUFEATURES_H */
diff --git a/arch/x86/include/asm/kvm_host.h b/arch/x86/include/asm/kvm_host.h
index 20cfeeb..7598a6c 100644
--- a/arch/x86/include/asm/kvm_host.h
+++ b/arch/x86/include/asm/kvm_host.h
@@ -864,7 +864,7 @@
int (*hardware_setup)(void); /* __init */
void (*hardware_unsetup)(void); /* __exit */
bool (*cpu_has_accelerated_tpr)(void);
- bool (*cpu_has_high_real_mode_segbase)(void);
+ bool (*has_emulated_msr)(int index);
void (*cpuid_update)(struct kvm_vcpu *vcpu);
int (*vm_init)(struct kvm *kvm);
diff --git a/arch/x86/include/asm/mmu_context.h b/arch/x86/include/asm/mmu_context.h
index 5a295bb..7336508 100644
--- a/arch/x86/include/asm/mmu_context.h
+++ b/arch/x86/include/asm/mmu_context.h
@@ -113,7 +113,7 @@
#ifdef CONFIG_X86_INTEL_MEMORY_PROTECTION_KEYS
if (cpu_feature_enabled(X86_FEATURE_OSPKE)) {
- /* pkey 0 is the default and always allocated */
+ /* pkey 0 is the default and allocated implicitly */
mm->context.pkey_allocation_map = 0x1;
/* -1 means unallocated or invalid */
mm->context.execute_only_pkey = -1;
diff --git a/arch/x86/include/asm/msr-index.h b/arch/x86/include/asm/msr-index.h
index c768bc1..1ec13e2 100644
--- a/arch/x86/include/asm/msr-index.h
+++ b/arch/x86/include/asm/msr-index.h
@@ -40,6 +40,8 @@
#define MSR_IA32_SPEC_CTRL 0x00000048 /* Speculation Control */
#define SPEC_CTRL_IBRS (1 << 0) /* Indirect Branch Restricted Speculation */
#define SPEC_CTRL_STIBP (1 << 1) /* Single Thread Indirect Branch Predictors */
+#define SPEC_CTRL_SSBD_SHIFT 2 /* Speculative Store Bypass Disable bit */
+#define SPEC_CTRL_SSBD (1 << SPEC_CTRL_SSBD_SHIFT) /* Speculative Store Bypass Disable */
#define MSR_IA32_PRED_CMD 0x00000049 /* Prediction Command */
#define PRED_CMD_IBPB (1 << 0) /* Indirect Branch Prediction Barrier */
@@ -61,6 +63,11 @@
#define MSR_IA32_ARCH_CAPABILITIES 0x0000010a
#define ARCH_CAP_RDCL_NO (1 << 0) /* Not susceptible to Meltdown */
#define ARCH_CAP_IBRS_ALL (1 << 1) /* Enhanced IBRS support */
+#define ARCH_CAP_SSB_NO (1 << 4) /*
+ * Not susceptible to Speculative Store Bypass
+ * attack, so no Speculative Store Bypass
+ * control required.
+ */
#define MSR_IA32_BBL_CR_CTL 0x00000119
#define MSR_IA32_BBL_CR_CTL3 0x0000011e
@@ -135,6 +142,7 @@
/* DEBUGCTLMSR bits (others vary by model): */
#define DEBUGCTLMSR_LBR (1UL << 0) /* last branch recording */
+#define DEBUGCTLMSR_BTF_SHIFT 1
#define DEBUGCTLMSR_BTF (1UL << 1) /* single-step on branches */
#define DEBUGCTLMSR_TR (1UL << 6)
#define DEBUGCTLMSR_BTS (1UL << 7)
@@ -315,6 +323,8 @@
#define MSR_AMD64_IBSOPDATA4 0xc001103d
#define MSR_AMD64_IBS_REG_COUNT_MAX 8 /* includes MSR_AMD64_IBSBRTARGET */
+#define MSR_AMD64_VIRT_SPEC_CTRL 0xc001011f
+
/* Fam 17h MSRs */
#define MSR_F17H_IRPERF 0xc00000e9
diff --git a/arch/x86/include/asm/nospec-branch.h b/arch/x86/include/asm/nospec-branch.h
index f928ad9..8b38df9 100644
--- a/arch/x86/include/asm/nospec-branch.h
+++ b/arch/x86/include/asm/nospec-branch.h
@@ -217,6 +217,14 @@
SPECTRE_V2_IBRS,
};
+/* The Speculative Store Bypass disable variants */
+enum ssb_mitigation {
+ SPEC_STORE_BYPASS_NONE,
+ SPEC_STORE_BYPASS_DISABLE,
+ SPEC_STORE_BYPASS_PRCTL,
+ SPEC_STORE_BYPASS_SECCOMP,
+};
+
extern char __indirect_thunk_start[];
extern char __indirect_thunk_end[];
@@ -241,22 +249,27 @@
#endif
}
-#define alternative_msr_write(_msr, _val, _feature) \
- asm volatile(ALTERNATIVE("", \
- "movl %[msr], %%ecx\n\t" \
- "movl %[val], %%eax\n\t" \
- "movl $0, %%edx\n\t" \
- "wrmsr", \
- _feature) \
- : : [msr] "i" (_msr), [val] "i" (_val) \
- : "eax", "ecx", "edx", "memory")
+static __always_inline
+void alternative_msr_write(unsigned int msr, u64 val, unsigned int feature)
+{
+ asm volatile(ALTERNATIVE("", "wrmsr", %c[feature])
+ : : "c" (msr),
+ "a" ((u32)val),
+ "d" ((u32)(val >> 32)),
+ [feature] "i" (feature)
+ : "memory");
+}
static inline void indirect_branch_prediction_barrier(void)
{
- alternative_msr_write(MSR_IA32_PRED_CMD, PRED_CMD_IBPB,
- X86_FEATURE_USE_IBPB);
+ u64 val = PRED_CMD_IBPB;
+
+ alternative_msr_write(MSR_IA32_PRED_CMD, val, X86_FEATURE_USE_IBPB);
}
+/* The Intel SPEC CTRL MSR base value cache */
+extern u64 x86_spec_ctrl_base;
+
/*
* With retpoline, we must use IBRS to restrict branch prediction
* before calling into firmware.
@@ -265,14 +278,18 @@
*/
#define firmware_restrict_branch_speculation_start() \
do { \
+ u64 val = x86_spec_ctrl_base | SPEC_CTRL_IBRS; \
+ \
preempt_disable(); \
- alternative_msr_write(MSR_IA32_SPEC_CTRL, SPEC_CTRL_IBRS, \
+ alternative_msr_write(MSR_IA32_SPEC_CTRL, val, \
X86_FEATURE_USE_IBRS_FW); \
} while (0)
#define firmware_restrict_branch_speculation_end() \
do { \
- alternative_msr_write(MSR_IA32_SPEC_CTRL, 0, \
+ u64 val = x86_spec_ctrl_base; \
+ \
+ alternative_msr_write(MSR_IA32_SPEC_CTRL, val, \
X86_FEATURE_USE_IBRS_FW); \
preempt_enable(); \
} while (0)
diff --git a/arch/x86/include/asm/pkeys.h b/arch/x86/include/asm/pkeys.h
index b3b09b9..c50d6dc 100644
--- a/arch/x86/include/asm/pkeys.h
+++ b/arch/x86/include/asm/pkeys.h
@@ -1,6 +1,8 @@
#ifndef _ASM_X86_PKEYS_H
#define _ASM_X86_PKEYS_H
+#define ARCH_DEFAULT_PKEY 0
+
#define arch_max_pkey() (boot_cpu_has(X86_FEATURE_OSPKE) ? 16 : 1)
extern int arch_set_user_pkey_access(struct task_struct *tsk, int pkey,
@@ -14,7 +16,7 @@
static inline int execute_only_pkey(struct mm_struct *mm)
{
if (!boot_cpu_has(X86_FEATURE_OSPKE))
- return 0;
+ return ARCH_DEFAULT_PKEY;
return __execute_only_pkey(mm);
}
@@ -48,13 +50,21 @@
{
/*
* "Allocated" pkeys are those that have been returned
- * from pkey_alloc(). pkey 0 is special, and never
- * returned from pkey_alloc().
+ * from pkey_alloc() or pkey 0 which is allocated
+ * implicitly when the mm is created.
*/
- if (pkey <= 0)
+ if (pkey < 0)
return false;
if (pkey >= arch_max_pkey())
return false;
+ /*
+ * The exec-only pkey is set in the allocation map, but
+ * is not available to any of the user interfaces like
+ * mprotect_pkey().
+ */
+ if (pkey == mm->context.execute_only_pkey)
+ return false;
+
return mm_pkey_allocation_map(mm) & (1U << pkey);
}
diff --git a/arch/x86/include/asm/spec-ctrl.h b/arch/x86/include/asm/spec-ctrl.h
new file mode 100644
index 0000000..ae7c2c5
--- /dev/null
+++ b/arch/x86/include/asm/spec-ctrl.h
@@ -0,0 +1,80 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+#ifndef _ASM_X86_SPECCTRL_H_
+#define _ASM_X86_SPECCTRL_H_
+
+#include <linux/thread_info.h>
+#include <asm/nospec-branch.h>
+
+/*
+ * On VMENTER we must preserve whatever view of the SPEC_CTRL MSR
+ * the guest has, while on VMEXIT we restore the host view. This
+ * would be easier if SPEC_CTRL were architecturally maskable or
+ * shadowable for guests but this is not (currently) the case.
+ * Takes the guest view of SPEC_CTRL MSR as a parameter and also
+ * the guest's version of VIRT_SPEC_CTRL, if emulated.
+ */
+extern void x86_virt_spec_ctrl(u64 guest_spec_ctrl, u64 guest_virt_spec_ctrl, bool guest);
+
+/**
+ * x86_spec_ctrl_set_guest - Set speculation control registers for the guest
+ * @guest_spec_ctrl: The guest content of MSR_SPEC_CTRL
+ * @guest_virt_spec_ctrl: The guest controlled bits of MSR_VIRT_SPEC_CTRL
+ * (may get translated to MSR_AMD64_LS_CFG bits)
+ *
+ * Avoids writing to the MSR if the content/bits are the same
+ */
+static inline
+void x86_spec_ctrl_set_guest(u64 guest_spec_ctrl, u64 guest_virt_spec_ctrl)
+{
+ x86_virt_spec_ctrl(guest_spec_ctrl, guest_virt_spec_ctrl, true);
+}
+
+/**
+ * x86_spec_ctrl_restore_host - Restore host speculation control registers
+ * @guest_spec_ctrl: The guest content of MSR_SPEC_CTRL
+ * @guest_virt_spec_ctrl: The guest controlled bits of MSR_VIRT_SPEC_CTRL
+ * (may get translated to MSR_AMD64_LS_CFG bits)
+ *
+ * Avoids writing to the MSR if the content/bits are the same
+ */
+static inline
+void x86_spec_ctrl_restore_host(u64 guest_spec_ctrl, u64 guest_virt_spec_ctrl)
+{
+ x86_virt_spec_ctrl(guest_spec_ctrl, guest_virt_spec_ctrl, false);
+}
+
+/* AMD specific Speculative Store Bypass MSR data */
+extern u64 x86_amd_ls_cfg_base;
+extern u64 x86_amd_ls_cfg_ssbd_mask;
+
+static inline u64 ssbd_tif_to_spec_ctrl(u64 tifn)
+{
+ BUILD_BUG_ON(TIF_SSBD < SPEC_CTRL_SSBD_SHIFT);
+ return (tifn & _TIF_SSBD) >> (TIF_SSBD - SPEC_CTRL_SSBD_SHIFT);
+}
+
+static inline unsigned long ssbd_spec_ctrl_to_tif(u64 spec_ctrl)
+{
+ BUILD_BUG_ON(TIF_SSBD < SPEC_CTRL_SSBD_SHIFT);
+ return (spec_ctrl & SPEC_CTRL_SSBD) << (TIF_SSBD - SPEC_CTRL_SSBD_SHIFT);
+}
+
+static inline u64 ssbd_tif_to_amd_ls_cfg(u64 tifn)
+{
+ return (tifn & _TIF_SSBD) ? x86_amd_ls_cfg_ssbd_mask : 0ULL;
+}
+
+#ifdef CONFIG_SMP
+extern void speculative_store_bypass_ht_init(void);
+#else
+static inline void speculative_store_bypass_ht_init(void) { }
+#endif
+
+extern void speculative_store_bypass_update(unsigned long tif);
+
+static inline void speculative_store_bypass_update_current(void)
+{
+ speculative_store_bypass_update(current_thread_info()->flags);
+}
+
+#endif
diff --git a/arch/x86/include/asm/thread_info.h b/arch/x86/include/asm/thread_info.h
index 89978b9..2d8788a 100644
--- a/arch/x86/include/asm/thread_info.h
+++ b/arch/x86/include/asm/thread_info.h
@@ -83,6 +83,7 @@
#define TIF_SIGPENDING 2 /* signal pending */
#define TIF_NEED_RESCHED 3 /* rescheduling necessary */
#define TIF_SINGLESTEP 4 /* reenable singlestep on user return*/
+#define TIF_SSBD 5 /* Reduced data speculation */
#define TIF_SYSCALL_EMU 6 /* syscall emulation active */
#define TIF_SYSCALL_AUDIT 7 /* syscall auditing active */
#define TIF_SECCOMP 8 /* secure computing */
@@ -104,8 +105,9 @@
#define _TIF_SYSCALL_TRACE (1 << TIF_SYSCALL_TRACE)
#define _TIF_NOTIFY_RESUME (1 << TIF_NOTIFY_RESUME)
#define _TIF_SIGPENDING (1 << TIF_SIGPENDING)
-#define _TIF_SINGLESTEP (1 << TIF_SINGLESTEP)
#define _TIF_NEED_RESCHED (1 << TIF_NEED_RESCHED)
+#define _TIF_SINGLESTEP (1 << TIF_SINGLESTEP)
+#define _TIF_SSBD (1 << TIF_SSBD)
#define _TIF_SYSCALL_EMU (1 << TIF_SYSCALL_EMU)
#define _TIF_SYSCALL_AUDIT (1 << TIF_SYSCALL_AUDIT)
#define _TIF_SECCOMP (1 << TIF_SECCOMP)
@@ -139,7 +141,7 @@
/* flags to check in __switch_to() */
#define _TIF_WORK_CTXSW \
- (_TIF_IO_BITMAP|_TIF_NOTSC|_TIF_BLOCKSTEP)
+ (_TIF_IO_BITMAP|_TIF_NOTSC|_TIF_BLOCKSTEP|_TIF_SSBD)
#define _TIF_WORK_CTXSW_PREV (_TIF_WORK_CTXSW|_TIF_USER_RETURN_NOTIFY)
#define _TIF_WORK_CTXSW_NEXT (_TIF_WORK_CTXSW)
diff --git a/arch/x86/include/asm/tlbflush.h b/arch/x86/include/asm/tlbflush.h
index 99185a0..686a58d 100644
--- a/arch/x86/include/asm/tlbflush.h
+++ b/arch/x86/include/asm/tlbflush.h
@@ -111,6 +111,16 @@
}
}
+static inline void cr4_toggle_bits(unsigned long mask)
+{
+ unsigned long cr4;
+
+ cr4 = this_cpu_read(cpu_tlbstate.cr4);
+ cr4 ^= mask;
+ this_cpu_write(cpu_tlbstate.cr4, cr4);
+ __write_cr4(cr4);
+}
+
/* Read the CR4 shadow. */
static inline unsigned long cr4_read_shadow(void)
{
diff --git a/arch/x86/kernel/cpu/amd.c b/arch/x86/kernel/cpu/amd.c
index c375bc6..4c2be99 100644
--- a/arch/x86/kernel/cpu/amd.c
+++ b/arch/x86/kernel/cpu/amd.c
@@ -9,6 +9,7 @@
#include <asm/processor.h>
#include <asm/apic.h>
#include <asm/cpu.h>
+#include <asm/spec-ctrl.h>
#include <asm/smp.h>
#include <asm/pci-direct.h>
#include <asm/delay.h>
@@ -542,6 +543,26 @@
rdmsrl(MSR_FAM10H_NODE_ID, value);
nodes_per_socket = ((value >> 3) & 7) + 1;
}
+
+ if (c->x86 >= 0x15 && c->x86 <= 0x17) {
+ unsigned int bit;
+
+ switch (c->x86) {
+ case 0x15: bit = 54; break;
+ case 0x16: bit = 33; break;
+ case 0x17: bit = 10; break;
+ default: return;
+ }
+ /*
+ * Try to cache the base value so further operations can
+ * avoid RMW. If that faults, do not enable SSBD.
+ */
+ if (!rdmsrl_safe(MSR_AMD64_LS_CFG, &x86_amd_ls_cfg_base)) {
+ setup_force_cpu_cap(X86_FEATURE_LS_CFG_SSBD);
+ setup_force_cpu_cap(X86_FEATURE_SSBD);
+ x86_amd_ls_cfg_ssbd_mask = 1ULL << bit;
+ }
+ }
}
static void early_init_amd(struct cpuinfo_x86 *c)
@@ -728,6 +749,17 @@
}
}
+static void init_amd_zn(struct cpuinfo_x86 *c)
+{
+ set_cpu_cap(c, X86_FEATURE_ZEN);
+ /*
+ * Fix erratum 1076: CPB feature bit not being set in CPUID. It affects
+ * all up to and including B1.
+ */
+ if (c->x86_model <= 1 && c->x86_stepping <= 1)
+ set_cpu_cap(c, X86_FEATURE_CPB);
+}
+
static void init_amd(struct cpuinfo_x86 *c)
{
u32 dummy;
@@ -758,6 +790,7 @@
case 0x10: init_amd_gh(c); break;
case 0x12: init_amd_ln(c); break;
case 0x15: init_amd_bd(c); break;
+ case 0x17: init_amd_zn(c); break;
}
/* Enable workaround for FXSAVE leak */
@@ -824,8 +857,9 @@
if (cpu_has(c, X86_FEATURE_3DNOW) || cpu_has(c, X86_FEATURE_LM))
set_cpu_cap(c, X86_FEATURE_3DNOWPREFETCH);
- /* AMD CPUs don't reset SS attributes on SYSRET */
- set_cpu_bug(c, X86_BUG_SYSRET_SS_ATTRS);
+ /* AMD CPUs don't reset SS attributes on SYSRET, Xen does. */
+ if (!cpu_has(c, X86_FEATURE_XENPV))
+ set_cpu_bug(c, X86_BUG_SYSRET_SS_ATTRS);
}
#ifdef CONFIG_X86_32
diff --git a/arch/x86/kernel/cpu/bugs.c b/arch/x86/kernel/cpu/bugs.c
index b8b0b6e..86af9b1 100644
--- a/arch/x86/kernel/cpu/bugs.c
+++ b/arch/x86/kernel/cpu/bugs.c
@@ -11,8 +11,10 @@
#include <linux/utsname.h>
#include <linux/cpu.h>
#include <linux/module.h>
+#include <linux/nospec.h>
+#include <linux/prctl.h>
-#include <asm/nospec-branch.h>
+#include <asm/spec-ctrl.h>
#include <asm/cmdline.h>
#include <asm/bugs.h>
#include <asm/processor.h>
@@ -26,6 +28,27 @@
#include <asm/intel-family.h>
static void __init spectre_v2_select_mitigation(void);
+static void __init ssb_select_mitigation(void);
+
+/*
+ * Our boot-time value of the SPEC_CTRL MSR. We read it once so that any
+ * writes to SPEC_CTRL contain whatever reserved bits have been set.
+ */
+u64 __ro_after_init x86_spec_ctrl_base;
+EXPORT_SYMBOL_GPL(x86_spec_ctrl_base);
+
+/*
+ * The vendor and possibly platform specific bits which can be modified in
+ * x86_spec_ctrl_base.
+ */
+static u64 __ro_after_init x86_spec_ctrl_mask = SPEC_CTRL_IBRS;
+
+/*
+ * AMD specific MSR info for Speculative Store Bypass control.
+ * x86_amd_ls_cfg_ssbd_mask is initialized in identify_boot_cpu().
+ */
+u64 __ro_after_init x86_amd_ls_cfg_base;
+u64 __ro_after_init x86_amd_ls_cfg_ssbd_mask;
void __init check_bugs(void)
{
@@ -36,9 +59,27 @@
print_cpu_info(&boot_cpu_data);
}
+ /*
+ * Read the SPEC_CTRL MSR to account for reserved bits which may
+ * have unknown values. AMD64_LS_CFG MSR is cached in the early AMD
+ * init code as it is not enumerated and depends on the family.
+ */
+ if (boot_cpu_has(X86_FEATURE_MSR_SPEC_CTRL))
+ rdmsrl(MSR_IA32_SPEC_CTRL, x86_spec_ctrl_base);
+
+ /* Allow STIBP in MSR_SPEC_CTRL if supported */
+ if (boot_cpu_has(X86_FEATURE_STIBP))
+ x86_spec_ctrl_mask |= SPEC_CTRL_STIBP;
+
/* Select the proper spectre mitigation before patching alternatives */
spectre_v2_select_mitigation();
+ /*
+ * Select proper mitigation for any exposure to the Speculative Store
+ * Bypass vulnerability.
+ */
+ ssb_select_mitigation();
+
#ifdef CONFIG_X86_32
/*
* Check whether we are able to run this kernel safely on SMP.
@@ -92,7 +133,76 @@
#undef pr_fmt
#define pr_fmt(fmt) "Spectre V2 : " fmt
-static enum spectre_v2_mitigation spectre_v2_enabled = SPECTRE_V2_NONE;
+static enum spectre_v2_mitigation spectre_v2_enabled __ro_after_init =
+ SPECTRE_V2_NONE;
+
+void
+x86_virt_spec_ctrl(u64 guest_spec_ctrl, u64 guest_virt_spec_ctrl, bool setguest)
+{
+ u64 msrval, guestval, hostval = x86_spec_ctrl_base;
+ struct thread_info *ti = current_thread_info();
+
+ /* Is MSR_SPEC_CTRL implemented ? */
+ if (static_cpu_has(X86_FEATURE_MSR_SPEC_CTRL)) {
+ /*
+ * Restrict guest_spec_ctrl to supported values. Clear the
+ * modifiable bits in the host base value and or the
+ * modifiable bits from the guest value.
+ */
+ guestval = hostval & ~x86_spec_ctrl_mask;
+ guestval |= guest_spec_ctrl & x86_spec_ctrl_mask;
+
+ /* SSBD controlled in MSR_SPEC_CTRL */
+ if (static_cpu_has(X86_FEATURE_SPEC_CTRL_SSBD))
+ hostval |= ssbd_tif_to_spec_ctrl(ti->flags);
+
+ if (hostval != guestval) {
+ msrval = setguest ? guestval : hostval;
+ wrmsrl(MSR_IA32_SPEC_CTRL, msrval);
+ }
+ }
+
+ /*
+ * If SSBD is not handled in MSR_SPEC_CTRL on AMD, update
+ * MSR_AMD64_L2_CFG or MSR_VIRT_SPEC_CTRL if supported.
+ */
+ if (!static_cpu_has(X86_FEATURE_LS_CFG_SSBD) &&
+ !static_cpu_has(X86_FEATURE_VIRT_SSBD))
+ return;
+
+ /*
+ * If the host has SSBD mitigation enabled, force it in the host's
+ * virtual MSR value. If its not permanently enabled, evaluate
+ * current's TIF_SSBD thread flag.
+ */
+ if (static_cpu_has(X86_FEATURE_SPEC_STORE_BYPASS_DISABLE))
+ hostval = SPEC_CTRL_SSBD;
+ else
+ hostval = ssbd_tif_to_spec_ctrl(ti->flags);
+
+ /* Sanitize the guest value */
+ guestval = guest_virt_spec_ctrl & SPEC_CTRL_SSBD;
+
+ if (hostval != guestval) {
+ unsigned long tif;
+
+ tif = setguest ? ssbd_spec_ctrl_to_tif(guestval) :
+ ssbd_spec_ctrl_to_tif(hostval);
+
+ speculative_store_bypass_update(tif);
+ }
+}
+EXPORT_SYMBOL_GPL(x86_virt_spec_ctrl);
+
+static void x86_amd_ssb_disable(void)
+{
+ u64 msrval = x86_amd_ls_cfg_base | x86_amd_ls_cfg_ssbd_mask;
+
+ if (boot_cpu_has(X86_FEATURE_VIRT_SSBD))
+ wrmsrl(MSR_AMD64_VIRT_SPEC_CTRL, SPEC_CTRL_SSBD);
+ else if (boot_cpu_has(X86_FEATURE_LS_CFG_SSBD))
+ wrmsrl(MSR_AMD64_LS_CFG, msrval);
+}
#ifdef RETPOLINE
static bool spectre_v2_bad_module;
@@ -311,32 +421,289 @@
}
#undef pr_fmt
+#define pr_fmt(fmt) "Speculative Store Bypass: " fmt
+
+static enum ssb_mitigation ssb_mode __ro_after_init = SPEC_STORE_BYPASS_NONE;
+
+/* The kernel command line selection */
+enum ssb_mitigation_cmd {
+ SPEC_STORE_BYPASS_CMD_NONE,
+ SPEC_STORE_BYPASS_CMD_AUTO,
+ SPEC_STORE_BYPASS_CMD_ON,
+ SPEC_STORE_BYPASS_CMD_PRCTL,
+ SPEC_STORE_BYPASS_CMD_SECCOMP,
+};
+
+static const char *ssb_strings[] = {
+ [SPEC_STORE_BYPASS_NONE] = "Vulnerable",
+ [SPEC_STORE_BYPASS_DISABLE] = "Mitigation: Speculative Store Bypass disabled",
+ [SPEC_STORE_BYPASS_PRCTL] = "Mitigation: Speculative Store Bypass disabled via prctl",
+ [SPEC_STORE_BYPASS_SECCOMP] = "Mitigation: Speculative Store Bypass disabled via prctl and seccomp",
+};
+
+static const struct {
+ const char *option;
+ enum ssb_mitigation_cmd cmd;
+} ssb_mitigation_options[] = {
+ { "auto", SPEC_STORE_BYPASS_CMD_AUTO }, /* Platform decides */
+ { "on", SPEC_STORE_BYPASS_CMD_ON }, /* Disable Speculative Store Bypass */
+ { "off", SPEC_STORE_BYPASS_CMD_NONE }, /* Don't touch Speculative Store Bypass */
+ { "prctl", SPEC_STORE_BYPASS_CMD_PRCTL }, /* Disable Speculative Store Bypass via prctl */
+ { "seccomp", SPEC_STORE_BYPASS_CMD_SECCOMP }, /* Disable Speculative Store Bypass via prctl and seccomp */
+};
+
+static enum ssb_mitigation_cmd __init ssb_parse_cmdline(void)
+{
+ enum ssb_mitigation_cmd cmd = SPEC_STORE_BYPASS_CMD_AUTO;
+ char arg[20];
+ int ret, i;
+
+ if (cmdline_find_option_bool(boot_command_line, "nospec_store_bypass_disable")) {
+ return SPEC_STORE_BYPASS_CMD_NONE;
+ } else {
+ ret = cmdline_find_option(boot_command_line, "spec_store_bypass_disable",
+ arg, sizeof(arg));
+ if (ret < 0)
+ return SPEC_STORE_BYPASS_CMD_AUTO;
+
+ for (i = 0; i < ARRAY_SIZE(ssb_mitigation_options); i++) {
+ if (!match_option(arg, ret, ssb_mitigation_options[i].option))
+ continue;
+
+ cmd = ssb_mitigation_options[i].cmd;
+ break;
+ }
+
+ if (i >= ARRAY_SIZE(ssb_mitigation_options)) {
+ pr_err("unknown option (%s). Switching to AUTO select\n", arg);
+ return SPEC_STORE_BYPASS_CMD_AUTO;
+ }
+ }
+
+ return cmd;
+}
+
+static enum ssb_mitigation __init __ssb_select_mitigation(void)
+{
+ enum ssb_mitigation mode = SPEC_STORE_BYPASS_NONE;
+ enum ssb_mitigation_cmd cmd;
+
+ if (!boot_cpu_has(X86_FEATURE_SSBD))
+ return mode;
+
+ cmd = ssb_parse_cmdline();
+ if (!boot_cpu_has_bug(X86_BUG_SPEC_STORE_BYPASS) &&
+ (cmd == SPEC_STORE_BYPASS_CMD_NONE ||
+ cmd == SPEC_STORE_BYPASS_CMD_AUTO))
+ return mode;
+
+ switch (cmd) {
+ case SPEC_STORE_BYPASS_CMD_AUTO:
+ case SPEC_STORE_BYPASS_CMD_SECCOMP:
+ /*
+ * Choose prctl+seccomp as the default mode if seccomp is
+ * enabled.
+ */
+ if (IS_ENABLED(CONFIG_SECCOMP))
+ mode = SPEC_STORE_BYPASS_SECCOMP;
+ else
+ mode = SPEC_STORE_BYPASS_PRCTL;
+ break;
+ case SPEC_STORE_BYPASS_CMD_ON:
+ mode = SPEC_STORE_BYPASS_DISABLE;
+ break;
+ case SPEC_STORE_BYPASS_CMD_PRCTL:
+ mode = SPEC_STORE_BYPASS_PRCTL;
+ break;
+ case SPEC_STORE_BYPASS_CMD_NONE:
+ break;
+ }
+
+ /*
+ * We have three CPU feature flags that are in play here:
+ * - X86_BUG_SPEC_STORE_BYPASS - CPU is susceptible.
+ * - X86_FEATURE_SSBD - CPU is able to turn off speculative store bypass
+ * - X86_FEATURE_SPEC_STORE_BYPASS_DISABLE - engage the mitigation
+ */
+ if (mode == SPEC_STORE_BYPASS_DISABLE) {
+ setup_force_cpu_cap(X86_FEATURE_SPEC_STORE_BYPASS_DISABLE);
+ /*
+ * Intel uses the SPEC CTRL MSR Bit(2) for this, while AMD uses
+ * a completely different MSR and bit dependent on family.
+ */
+ switch (boot_cpu_data.x86_vendor) {
+ case X86_VENDOR_INTEL:
+ x86_spec_ctrl_base |= SPEC_CTRL_SSBD;
+ x86_spec_ctrl_mask |= SPEC_CTRL_SSBD;
+ wrmsrl(MSR_IA32_SPEC_CTRL, x86_spec_ctrl_base);
+ break;
+ case X86_VENDOR_AMD:
+ x86_amd_ssb_disable();
+ break;
+ }
+ }
+
+ return mode;
+}
+
+static void ssb_select_mitigation(void)
+{
+ ssb_mode = __ssb_select_mitigation();
+
+ if (boot_cpu_has_bug(X86_BUG_SPEC_STORE_BYPASS))
+ pr_info("%s\n", ssb_strings[ssb_mode]);
+}
+
+#undef pr_fmt
+#define pr_fmt(fmt) "Speculation prctl: " fmt
+
+static int ssb_prctl_set(struct task_struct *task, unsigned long ctrl)
+{
+ bool update;
+
+ if (ssb_mode != SPEC_STORE_BYPASS_PRCTL &&
+ ssb_mode != SPEC_STORE_BYPASS_SECCOMP)
+ return -ENXIO;
+
+ switch (ctrl) {
+ case PR_SPEC_ENABLE:
+ /* If speculation is force disabled, enable is not allowed */
+ if (task_spec_ssb_force_disable(task))
+ return -EPERM;
+ task_clear_spec_ssb_disable(task);
+ update = test_and_clear_tsk_thread_flag(task, TIF_SSBD);
+ break;
+ case PR_SPEC_DISABLE:
+ task_set_spec_ssb_disable(task);
+ update = !test_and_set_tsk_thread_flag(task, TIF_SSBD);
+ break;
+ case PR_SPEC_FORCE_DISABLE:
+ task_set_spec_ssb_disable(task);
+ task_set_spec_ssb_force_disable(task);
+ update = !test_and_set_tsk_thread_flag(task, TIF_SSBD);
+ break;
+ default:
+ return -ERANGE;
+ }
+
+ /*
+ * If being set on non-current task, delay setting the CPU
+ * mitigation until it is next scheduled.
+ */
+ if (task == current && update)
+ speculative_store_bypass_update_current();
+
+ return 0;
+}
+
+int arch_prctl_spec_ctrl_set(struct task_struct *task, unsigned long which,
+ unsigned long ctrl)
+{
+ switch (which) {
+ case PR_SPEC_STORE_BYPASS:
+ return ssb_prctl_set(task, ctrl);
+ default:
+ return -ENODEV;
+ }
+}
+
+#ifdef CONFIG_SECCOMP
+void arch_seccomp_spec_mitigate(struct task_struct *task)
+{
+ if (ssb_mode == SPEC_STORE_BYPASS_SECCOMP)
+ ssb_prctl_set(task, PR_SPEC_FORCE_DISABLE);
+}
+#endif
+
+static int ssb_prctl_get(struct task_struct *task)
+{
+ switch (ssb_mode) {
+ case SPEC_STORE_BYPASS_DISABLE:
+ return PR_SPEC_DISABLE;
+ case SPEC_STORE_BYPASS_SECCOMP:
+ case SPEC_STORE_BYPASS_PRCTL:
+ if (task_spec_ssb_force_disable(task))
+ return PR_SPEC_PRCTL | PR_SPEC_FORCE_DISABLE;
+ if (task_spec_ssb_disable(task))
+ return PR_SPEC_PRCTL | PR_SPEC_DISABLE;
+ return PR_SPEC_PRCTL | PR_SPEC_ENABLE;
+ default:
+ if (boot_cpu_has_bug(X86_BUG_SPEC_STORE_BYPASS))
+ return PR_SPEC_ENABLE;
+ return PR_SPEC_NOT_AFFECTED;
+ }
+}
+
+int arch_prctl_spec_ctrl_get(struct task_struct *task, unsigned long which)
+{
+ switch (which) {
+ case PR_SPEC_STORE_BYPASS:
+ return ssb_prctl_get(task);
+ default:
+ return -ENODEV;
+ }
+}
+
+void x86_spec_ctrl_setup_ap(void)
+{
+ if (boot_cpu_has(X86_FEATURE_MSR_SPEC_CTRL))
+ wrmsrl(MSR_IA32_SPEC_CTRL, x86_spec_ctrl_base);
+
+ if (ssb_mode == SPEC_STORE_BYPASS_DISABLE)
+ x86_amd_ssb_disable();
+}
#ifdef CONFIG_SYSFS
+
+static ssize_t cpu_show_common(struct device *dev, struct device_attribute *attr,
+ char *buf, unsigned int bug)
+{
+ if (!boot_cpu_has_bug(bug))
+ return sprintf(buf, "Not affected\n");
+
+ switch (bug) {
+ case X86_BUG_CPU_MELTDOWN:
+ if (boot_cpu_has(X86_FEATURE_KAISER))
+ return sprintf(buf, "Mitigation: PTI\n");
+
+ break;
+
+ case X86_BUG_SPECTRE_V1:
+ return sprintf(buf, "Mitigation: __user pointer sanitization\n");
+
+ case X86_BUG_SPECTRE_V2:
+ return sprintf(buf, "%s%s%s%s\n", spectre_v2_strings[spectre_v2_enabled],
+ boot_cpu_has(X86_FEATURE_USE_IBPB) ? ", IBPB" : "",
+ boot_cpu_has(X86_FEATURE_USE_IBRS_FW) ? ", IBRS_FW" : "",
+ spectre_v2_module_string());
+
+ case X86_BUG_SPEC_STORE_BYPASS:
+ return sprintf(buf, "%s\n", ssb_strings[ssb_mode]);
+
+ default:
+ break;
+ }
+
+ return sprintf(buf, "Vulnerable\n");
+}
+
ssize_t cpu_show_meltdown(struct device *dev, struct device_attribute *attr, char *buf)
{
- if (!boot_cpu_has_bug(X86_BUG_CPU_MELTDOWN))
- return sprintf(buf, "Not affected\n");
- if (boot_cpu_has(X86_FEATURE_KAISER))
- return sprintf(buf, "Mitigation: PTI\n");
- return sprintf(buf, "Vulnerable\n");
+ return cpu_show_common(dev, attr, buf, X86_BUG_CPU_MELTDOWN);
}
ssize_t cpu_show_spectre_v1(struct device *dev, struct device_attribute *attr, char *buf)
{
- if (!boot_cpu_has_bug(X86_BUG_SPECTRE_V1))
- return sprintf(buf, "Not affected\n");
- return sprintf(buf, "Mitigation: __user pointer sanitization\n");
+ return cpu_show_common(dev, attr, buf, X86_BUG_SPECTRE_V1);
}
ssize_t cpu_show_spectre_v2(struct device *dev, struct device_attribute *attr, char *buf)
{
- if (!boot_cpu_has_bug(X86_BUG_SPECTRE_V2))
- return sprintf(buf, "Not affected\n");
+ return cpu_show_common(dev, attr, buf, X86_BUG_SPECTRE_V2);
+}
- return sprintf(buf, "%s%s%s%s\n", spectre_v2_strings[spectre_v2_enabled],
- boot_cpu_has(X86_FEATURE_USE_IBPB) ? ", IBPB" : "",
- boot_cpu_has(X86_FEATURE_USE_IBRS_FW) ? ", IBRS_FW" : "",
- spectre_v2_module_string());
+ssize_t cpu_show_spec_store_bypass(struct device *dev, struct device_attribute *attr, char *buf)
+{
+ return cpu_show_common(dev, attr, buf, X86_BUG_SPEC_STORE_BYPASS);
}
#endif
diff --git a/arch/x86/kernel/cpu/common.c b/arch/x86/kernel/cpu/common.c
index 301bbd1..b0fd028 100644
--- a/arch/x86/kernel/cpu/common.c
+++ b/arch/x86/kernel/cpu/common.c
@@ -725,17 +725,32 @@
* and they also have a different bit for STIBP support. Also,
* a hypervisor might have set the individual AMD bits even on
* Intel CPUs, for finer-grained selection of what's available.
- *
- * We use the AMD bits in 0x8000_0008 EBX as the generic hardware
- * features, which are visible in /proc/cpuinfo and used by the
- * kernel. So set those accordingly from the Intel bits.
*/
if (cpu_has(c, X86_FEATURE_SPEC_CTRL)) {
set_cpu_cap(c, X86_FEATURE_IBRS);
set_cpu_cap(c, X86_FEATURE_IBPB);
+ set_cpu_cap(c, X86_FEATURE_MSR_SPEC_CTRL);
}
+
if (cpu_has(c, X86_FEATURE_INTEL_STIBP))
set_cpu_cap(c, X86_FEATURE_STIBP);
+
+ if (cpu_has(c, X86_FEATURE_SPEC_CTRL_SSBD) ||
+ cpu_has(c, X86_FEATURE_VIRT_SSBD))
+ set_cpu_cap(c, X86_FEATURE_SSBD);
+
+ if (cpu_has(c, X86_FEATURE_AMD_IBRS)) {
+ set_cpu_cap(c, X86_FEATURE_IBRS);
+ set_cpu_cap(c, X86_FEATURE_MSR_SPEC_CTRL);
+ }
+
+ if (cpu_has(c, X86_FEATURE_AMD_IBPB))
+ set_cpu_cap(c, X86_FEATURE_IBPB);
+
+ if (cpu_has(c, X86_FEATURE_AMD_STIBP)) {
+ set_cpu_cap(c, X86_FEATURE_STIBP);
+ set_cpu_cap(c, X86_FEATURE_MSR_SPEC_CTRL);
+ }
}
void get_cpu_cap(struct cpuinfo_x86 *c)
@@ -879,21 +894,55 @@
{}
};
-static bool __init cpu_vulnerable_to_meltdown(struct cpuinfo_x86 *c)
+static const __initconst struct x86_cpu_id cpu_no_spec_store_bypass[] = {
+ { X86_VENDOR_INTEL, 6, INTEL_FAM6_ATOM_PINEVIEW },
+ { X86_VENDOR_INTEL, 6, INTEL_FAM6_ATOM_LINCROFT },
+ { X86_VENDOR_INTEL, 6, INTEL_FAM6_ATOM_PENWELL },
+ { X86_VENDOR_INTEL, 6, INTEL_FAM6_ATOM_CLOVERVIEW },
+ { X86_VENDOR_INTEL, 6, INTEL_FAM6_ATOM_CEDARVIEW },
+ { X86_VENDOR_INTEL, 6, INTEL_FAM6_ATOM_SILVERMONT1 },
+ { X86_VENDOR_INTEL, 6, INTEL_FAM6_ATOM_AIRMONT },
+ { X86_VENDOR_INTEL, 6, INTEL_FAM6_ATOM_SILVERMONT2 },
+ { X86_VENDOR_INTEL, 6, INTEL_FAM6_ATOM_MERRIFIELD },
+ { X86_VENDOR_INTEL, 6, INTEL_FAM6_CORE_YONAH },
+ { X86_VENDOR_INTEL, 6, INTEL_FAM6_XEON_PHI_KNL },
+ { X86_VENDOR_INTEL, 6, INTEL_FAM6_XEON_PHI_KNM },
+ { X86_VENDOR_CENTAUR, 5, },
+ { X86_VENDOR_INTEL, 5, },
+ { X86_VENDOR_NSC, 5, },
+ { X86_VENDOR_AMD, 0x12, },
+ { X86_VENDOR_AMD, 0x11, },
+ { X86_VENDOR_AMD, 0x10, },
+ { X86_VENDOR_AMD, 0xf, },
+ { X86_VENDOR_ANY, 4, },
+ {}
+};
+
+static void __init cpu_set_bug_bits(struct cpuinfo_x86 *c)
{
u64 ia32_cap = 0;
- if (x86_match_cpu(cpu_no_meltdown))
- return false;
-
if (cpu_has(c, X86_FEATURE_ARCH_CAPABILITIES))
rdmsrl(MSR_IA32_ARCH_CAPABILITIES, ia32_cap);
+ if (!x86_match_cpu(cpu_no_spec_store_bypass) &&
+ !(ia32_cap & ARCH_CAP_SSB_NO))
+ setup_force_cpu_bug(X86_BUG_SPEC_STORE_BYPASS);
+
+ if (x86_match_cpu(cpu_no_speculation))
+ return;
+
+ setup_force_cpu_bug(X86_BUG_SPECTRE_V1);
+ setup_force_cpu_bug(X86_BUG_SPECTRE_V2);
+
+ if (x86_match_cpu(cpu_no_meltdown))
+ return;
+
/* Rogue Data Cache Load? No! */
if (ia32_cap & ARCH_CAP_RDCL_NO)
- return false;
+ return;
- return true;
+ setup_force_cpu_bug(X86_BUG_CPU_MELTDOWN);
}
/*
@@ -942,12 +991,7 @@
setup_force_cpu_cap(X86_FEATURE_ALWAYS);
- if (!x86_match_cpu(cpu_no_speculation)) {
- if (cpu_vulnerable_to_meltdown(c))
- setup_force_cpu_bug(X86_BUG_CPU_MELTDOWN);
- setup_force_cpu_bug(X86_BUG_SPECTRE_V1);
- setup_force_cpu_bug(X86_BUG_SPECTRE_V2);
- }
+ cpu_set_bug_bits(c);
fpu__init_system(c);
@@ -1315,6 +1359,7 @@
#endif
mtrr_ap_init();
validate_apic_and_package_id(c);
+ x86_spec_ctrl_setup_ap();
}
struct msr_range {
diff --git a/arch/x86/kernel/cpu/cpu.h b/arch/x86/kernel/cpu/cpu.h
index 2584265..3b19d82 100644
--- a/arch/x86/kernel/cpu/cpu.h
+++ b/arch/x86/kernel/cpu/cpu.h
@@ -46,4 +46,7 @@
extern void get_cpu_cap(struct cpuinfo_x86 *c);
extern void cpu_detect_cache_sizes(struct cpuinfo_x86 *c);
+
+extern void x86_spec_ctrl_setup_ap(void);
+
#endif /* ARCH_X86_CPU_H */
diff --git a/arch/x86/kernel/cpu/intel.c b/arch/x86/kernel/cpu/intel.c
index 8fb1d65..93781e3 100644
--- a/arch/x86/kernel/cpu/intel.c
+++ b/arch/x86/kernel/cpu/intel.c
@@ -153,7 +153,10 @@
setup_clear_cpu_cap(X86_FEATURE_IBPB);
setup_clear_cpu_cap(X86_FEATURE_STIBP);
setup_clear_cpu_cap(X86_FEATURE_SPEC_CTRL);
+ setup_clear_cpu_cap(X86_FEATURE_MSR_SPEC_CTRL);
setup_clear_cpu_cap(X86_FEATURE_INTEL_STIBP);
+ setup_clear_cpu_cap(X86_FEATURE_SSBD);
+ setup_clear_cpu_cap(X86_FEATURE_SPEC_CTRL_SSBD);
}
/*
diff --git a/arch/x86/kernel/machine_kexec_32.c b/arch/x86/kernel/machine_kexec_32.c
index 469b23d..fd7e993 100644
--- a/arch/x86/kernel/machine_kexec_32.c
+++ b/arch/x86/kernel/machine_kexec_32.c
@@ -71,12 +71,17 @@
static void machine_kexec_free_page_tables(struct kimage *image)
{
free_page((unsigned long)image->arch.pgd);
+ image->arch.pgd = NULL;
#ifdef CONFIG_X86_PAE
free_page((unsigned long)image->arch.pmd0);
+ image->arch.pmd0 = NULL;
free_page((unsigned long)image->arch.pmd1);
+ image->arch.pmd1 = NULL;
#endif
free_page((unsigned long)image->arch.pte0);
+ image->arch.pte0 = NULL;
free_page((unsigned long)image->arch.pte1);
+ image->arch.pte1 = NULL;
}
static int machine_kexec_alloc_page_tables(struct kimage *image)
@@ -93,7 +98,6 @@
!image->arch.pmd0 || !image->arch.pmd1 ||
#endif
!image->arch.pte0 || !image->arch.pte1) {
- machine_kexec_free_page_tables(image);
return -ENOMEM;
}
return 0;
diff --git a/arch/x86/kernel/machine_kexec_64.c b/arch/x86/kernel/machine_kexec_64.c
index a5784a1..eae59ca 100644
--- a/arch/x86/kernel/machine_kexec_64.c
+++ b/arch/x86/kernel/machine_kexec_64.c
@@ -37,8 +37,11 @@
static void free_transition_pgtable(struct kimage *image)
{
free_page((unsigned long)image->arch.pud);
+ image->arch.pud = NULL;
free_page((unsigned long)image->arch.pmd);
+ image->arch.pmd = NULL;
free_page((unsigned long)image->arch.pte);
+ image->arch.pte = NULL;
}
static int init_transition_pgtable(struct kimage *image, pgd_t *pgd)
@@ -79,7 +82,6 @@
set_pte(pte, pfn_pte(paddr >> PAGE_SHIFT, PAGE_KERNEL_EXEC));
return 0;
err:
- free_transition_pgtable(image);
return result;
}
diff --git a/arch/x86/kernel/process.c b/arch/x86/kernel/process.c
index 54b2711..e9195a1 100644
--- a/arch/x86/kernel/process.c
+++ b/arch/x86/kernel/process.c
@@ -33,6 +33,7 @@
#include <asm/mce.h>
#include <asm/vm86.h>
#include <asm/switch_to.h>
+#include <asm/spec-ctrl.h>
/*
* per-CPU TSS segments. Threads are completely 'soft' on Linux,
@@ -121,11 +122,6 @@
fpu__clear(&tsk->thread.fpu);
}
-static void hard_disable_TSC(void)
-{
- cr4_set_bits(X86_CR4_TSD);
-}
-
void disable_TSC(void)
{
preempt_disable();
@@ -134,15 +130,10 @@
* Must flip the CPU state synchronously with
* TIF_NOTSC in the current running context.
*/
- hard_disable_TSC();
+ cr4_set_bits(X86_CR4_TSD);
preempt_enable();
}
-static void hard_enable_TSC(void)
-{
- cr4_clear_bits(X86_CR4_TSD);
-}
-
static void enable_TSC(void)
{
preempt_disable();
@@ -151,7 +142,7 @@
* Must flip the CPU state synchronously with
* TIF_NOTSC in the current running context.
*/
- hard_enable_TSC();
+ cr4_clear_bits(X86_CR4_TSD);
preempt_enable();
}
@@ -179,48 +170,199 @@
return 0;
}
-void __switch_to_xtra(struct task_struct *prev_p, struct task_struct *next_p,
- struct tss_struct *tss)
+static inline void switch_to_bitmap(struct tss_struct *tss,
+ struct thread_struct *prev,
+ struct thread_struct *next,
+ unsigned long tifp, unsigned long tifn)
{
- struct thread_struct *prev, *next;
-
- prev = &prev_p->thread;
- next = &next_p->thread;
-
- if (test_tsk_thread_flag(prev_p, TIF_BLOCKSTEP) ^
- test_tsk_thread_flag(next_p, TIF_BLOCKSTEP)) {
- unsigned long debugctl = get_debugctlmsr();
-
- debugctl &= ~DEBUGCTLMSR_BTF;
- if (test_tsk_thread_flag(next_p, TIF_BLOCKSTEP))
- debugctl |= DEBUGCTLMSR_BTF;
-
- update_debugctlmsr(debugctl);
- }
-
- if (test_tsk_thread_flag(prev_p, TIF_NOTSC) ^
- test_tsk_thread_flag(next_p, TIF_NOTSC)) {
- /* prev and next are different */
- if (test_tsk_thread_flag(next_p, TIF_NOTSC))
- hard_disable_TSC();
- else
- hard_enable_TSC();
- }
-
- if (test_tsk_thread_flag(next_p, TIF_IO_BITMAP)) {
+ if (tifn & _TIF_IO_BITMAP) {
/*
* Copy the relevant range of the IO bitmap.
* Normally this is 128 bytes or less:
*/
memcpy(tss->io_bitmap, next->io_bitmap_ptr,
max(prev->io_bitmap_max, next->io_bitmap_max));
- } else if (test_tsk_thread_flag(prev_p, TIF_IO_BITMAP)) {
+ } else if (tifp & _TIF_IO_BITMAP) {
/*
* Clear any possible leftover bits:
*/
memset(tss->io_bitmap, 0xff, prev->io_bitmap_max);
}
+}
+
+#ifdef CONFIG_SMP
+
+struct ssb_state {
+ struct ssb_state *shared_state;
+ raw_spinlock_t lock;
+ unsigned int disable_state;
+ unsigned long local_state;
+};
+
+#define LSTATE_SSB 0
+
+static DEFINE_PER_CPU(struct ssb_state, ssb_state);
+
+void speculative_store_bypass_ht_init(void)
+{
+ struct ssb_state *st = this_cpu_ptr(&ssb_state);
+ unsigned int this_cpu = smp_processor_id();
+ unsigned int cpu;
+
+ st->local_state = 0;
+
+ /*
+ * Shared state setup happens once on the first bringup
+ * of the CPU. It's not destroyed on CPU hotunplug.
+ */
+ if (st->shared_state)
+ return;
+
+ raw_spin_lock_init(&st->lock);
+
+ /*
+ * Go over HT siblings and check whether one of them has set up the
+ * shared state pointer already.
+ */
+ for_each_cpu(cpu, topology_sibling_cpumask(this_cpu)) {
+ if (cpu == this_cpu)
+ continue;
+
+ if (!per_cpu(ssb_state, cpu).shared_state)
+ continue;
+
+ /* Link it to the state of the sibling: */
+ st->shared_state = per_cpu(ssb_state, cpu).shared_state;
+ return;
+ }
+
+ /*
+ * First HT sibling to come up on the core. Link shared state of
+ * the first HT sibling to itself. The siblings on the same core
+ * which come up later will see the shared state pointer and link
+ * themself to the state of this CPU.
+ */
+ st->shared_state = st;
+}
+
+/*
+ * Logic is: First HT sibling enables SSBD for both siblings in the core
+ * and last sibling to disable it, disables it for the whole core. This how
+ * MSR_SPEC_CTRL works in "hardware":
+ *
+ * CORE_SPEC_CTRL = THREAD0_SPEC_CTRL | THREAD1_SPEC_CTRL
+ */
+static __always_inline void amd_set_core_ssb_state(unsigned long tifn)
+{
+ struct ssb_state *st = this_cpu_ptr(&ssb_state);
+ u64 msr = x86_amd_ls_cfg_base;
+
+ if (!static_cpu_has(X86_FEATURE_ZEN)) {
+ msr |= ssbd_tif_to_amd_ls_cfg(tifn);
+ wrmsrl(MSR_AMD64_LS_CFG, msr);
+ return;
+ }
+
+ if (tifn & _TIF_SSBD) {
+ /*
+ * Since this can race with prctl(), block reentry on the
+ * same CPU.
+ */
+ if (__test_and_set_bit(LSTATE_SSB, &st->local_state))
+ return;
+
+ msr |= x86_amd_ls_cfg_ssbd_mask;
+
+ raw_spin_lock(&st->shared_state->lock);
+ /* First sibling enables SSBD: */
+ if (!st->shared_state->disable_state)
+ wrmsrl(MSR_AMD64_LS_CFG, msr);
+ st->shared_state->disable_state++;
+ raw_spin_unlock(&st->shared_state->lock);
+ } else {
+ if (!__test_and_clear_bit(LSTATE_SSB, &st->local_state))
+ return;
+
+ raw_spin_lock(&st->shared_state->lock);
+ st->shared_state->disable_state--;
+ if (!st->shared_state->disable_state)
+ wrmsrl(MSR_AMD64_LS_CFG, msr);
+ raw_spin_unlock(&st->shared_state->lock);
+ }
+}
+#else
+static __always_inline void amd_set_core_ssb_state(unsigned long tifn)
+{
+ u64 msr = x86_amd_ls_cfg_base | ssbd_tif_to_amd_ls_cfg(tifn);
+
+ wrmsrl(MSR_AMD64_LS_CFG, msr);
+}
+#endif
+
+static __always_inline void amd_set_ssb_virt_state(unsigned long tifn)
+{
+ /*
+ * SSBD has the same definition in SPEC_CTRL and VIRT_SPEC_CTRL,
+ * so ssbd_tif_to_spec_ctrl() just works.
+ */
+ wrmsrl(MSR_AMD64_VIRT_SPEC_CTRL, ssbd_tif_to_spec_ctrl(tifn));
+}
+
+static __always_inline void intel_set_ssb_state(unsigned long tifn)
+{
+ u64 msr = x86_spec_ctrl_base | ssbd_tif_to_spec_ctrl(tifn);
+
+ wrmsrl(MSR_IA32_SPEC_CTRL, msr);
+}
+
+static __always_inline void __speculative_store_bypass_update(unsigned long tifn)
+{
+ if (static_cpu_has(X86_FEATURE_VIRT_SSBD))
+ amd_set_ssb_virt_state(tifn);
+ else if (static_cpu_has(X86_FEATURE_LS_CFG_SSBD))
+ amd_set_core_ssb_state(tifn);
+ else
+ intel_set_ssb_state(tifn);
+}
+
+void speculative_store_bypass_update(unsigned long tif)
+{
+ preempt_disable();
+ __speculative_store_bypass_update(tif);
+ preempt_enable();
+}
+
+void __switch_to_xtra(struct task_struct *prev_p, struct task_struct *next_p,
+ struct tss_struct *tss)
+{
+ struct thread_struct *prev, *next;
+ unsigned long tifp, tifn;
+
+ prev = &prev_p->thread;
+ next = &next_p->thread;
+
+ tifn = READ_ONCE(task_thread_info(next_p)->flags);
+ tifp = READ_ONCE(task_thread_info(prev_p)->flags);
+ switch_to_bitmap(tss, prev, next, tifp, tifn);
+
propagate_user_return_notify(prev_p, next_p);
+
+ if ((tifp & _TIF_BLOCKSTEP || tifn & _TIF_BLOCKSTEP) &&
+ arch_has_block_step()) {
+ unsigned long debugctl, msk;
+
+ rdmsrl(MSR_IA32_DEBUGCTLMSR, debugctl);
+ debugctl &= ~DEBUGCTLMSR_BTF;
+ msk = tifn & _TIF_BLOCKSTEP;
+ debugctl |= (msk >> TIF_BLOCKSTEP) << DEBUGCTLMSR_BTF_SHIFT;
+ wrmsrl(MSR_IA32_DEBUGCTLMSR, debugctl);
+ }
+
+ if ((tifp ^ tifn) & _TIF_NOTSC)
+ cr4_toggle_bits(X86_CR4_TSD);
+
+ if ((tifp ^ tifn) & _TIF_SSBD)
+ __speculative_store_bypass_update(tifn);
}
/*
diff --git a/arch/x86/kernel/smpboot.c b/arch/x86/kernel/smpboot.c
index 83929cc4..cb94514 100644
--- a/arch/x86/kernel/smpboot.c
+++ b/arch/x86/kernel/smpboot.c
@@ -75,6 +75,7 @@
#include <asm/i8259.h>
#include <asm/realmode.h>
#include <asm/misc.h>
+#include <asm/spec-ctrl.h>
/* Number of siblings per CPU package */
int smp_num_siblings = 1;
@@ -229,6 +230,8 @@
*/
check_tsc_sync_target();
+ speculative_store_bypass_ht_init();
+
/*
* Lock vector_lock and initialize the vectors on this cpu
* before setting the cpu online. We must set it online with
@@ -1325,6 +1328,8 @@
set_mtrr_aps_delayed_init();
smp_quirk_init_udelay();
+
+ speculative_store_bypass_ht_init();
}
void arch_enable_nonboot_cpus_begin(void)
diff --git a/arch/x86/kvm/cpuid.c b/arch/x86/kvm/cpuid.c
index 93f924d..a69f18d 100644
--- a/arch/x86/kvm/cpuid.c
+++ b/arch/x86/kvm/cpuid.c
@@ -357,7 +357,7 @@
/* cpuid 0x80000008.ebx */
const u32 kvm_cpuid_8000_0008_ebx_x86_features =
- F(IBPB) | F(IBRS);
+ F(AMD_IBPB) | F(AMD_IBRS) | F(VIRT_SSBD);
/* cpuid 0xC0000001.edx */
const u32 kvm_cpuid_C000_0001_edx_x86_features =
@@ -382,7 +382,7 @@
/* cpuid 7.0.edx*/
const u32 kvm_cpuid_7_0_edx_x86_features =
- F(SPEC_CTRL) | F(ARCH_CAPABILITIES);
+ F(SPEC_CTRL) | F(SSBD) | F(ARCH_CAPABILITIES);
/* all calls to cpuid_count() should be made on the same cpu */
get_cpu();
@@ -618,13 +618,20 @@
g_phys_as = phys_as;
entry->eax = g_phys_as | (virt_as << 8);
entry->edx = 0;
- /* IBRS and IBPB aren't necessarily present in hardware cpuid */
- if (boot_cpu_has(X86_FEATURE_IBPB))
- entry->ebx |= F(IBPB);
- if (boot_cpu_has(X86_FEATURE_IBRS))
- entry->ebx |= F(IBRS);
+ /*
+ * IBRS, IBPB and VIRT_SSBD aren't necessarily present in
+ * hardware cpuid
+ */
+ if (boot_cpu_has(X86_FEATURE_AMD_IBPB))
+ entry->ebx |= F(AMD_IBPB);
+ if (boot_cpu_has(X86_FEATURE_AMD_IBRS))
+ entry->ebx |= F(AMD_IBRS);
+ if (boot_cpu_has(X86_FEATURE_VIRT_SSBD))
+ entry->ebx |= F(VIRT_SSBD);
entry->ebx &= kvm_cpuid_8000_0008_ebx_x86_features;
cpuid_mask(&entry->ebx, CPUID_8000_0008_EBX);
+ if (boot_cpu_has(X86_FEATURE_LS_CFG_SSBD))
+ entry->ebx |= F(VIRT_SSBD);
break;
}
case 0x80000019:
diff --git a/arch/x86/kvm/cpuid.h b/arch/x86/kvm/cpuid.h
index d1beb71..c383697 100644
--- a/arch/x86/kvm/cpuid.h
+++ b/arch/x86/kvm/cpuid.h
@@ -165,21 +165,21 @@
struct kvm_cpuid_entry2 *best;
best = kvm_find_cpuid_entry(vcpu, 0x80000008, 0);
- if (best && (best->ebx & bit(X86_FEATURE_IBPB)))
+ if (best && (best->ebx & bit(X86_FEATURE_AMD_IBPB)))
return true;
best = kvm_find_cpuid_entry(vcpu, 7, 0);
return best && (best->edx & bit(X86_FEATURE_SPEC_CTRL));
}
-static inline bool guest_cpuid_has_ibrs(struct kvm_vcpu *vcpu)
+static inline bool guest_cpuid_has_spec_ctrl(struct kvm_vcpu *vcpu)
{
struct kvm_cpuid_entry2 *best;
best = kvm_find_cpuid_entry(vcpu, 0x80000008, 0);
- if (best && (best->ebx & bit(X86_FEATURE_IBRS)))
+ if (best && (best->ebx & bit(X86_FEATURE_AMD_IBRS)))
return true;
best = kvm_find_cpuid_entry(vcpu, 7, 0);
- return best && (best->edx & bit(X86_FEATURE_SPEC_CTRL));
+ return best && (best->edx & (bit(X86_FEATURE_SPEC_CTRL) | bit(X86_FEATURE_SSBD)));
}
static inline bool guest_cpuid_has_arch_capabilities(struct kvm_vcpu *vcpu)
@@ -190,6 +190,15 @@
return best && (best->edx & bit(X86_FEATURE_ARCH_CAPABILITIES));
}
+static inline bool guest_cpuid_has_virt_ssbd(struct kvm_vcpu *vcpu)
+{
+ struct kvm_cpuid_entry2 *best;
+
+ best = kvm_find_cpuid_entry(vcpu, 0x80000008, 0);
+ return best && (best->ebx & bit(X86_FEATURE_VIRT_SSBD));
+}
+
+
/*
* NRIPS is provided through cpuidfn 0x8000000a.edx bit 3
diff --git a/arch/x86/kvm/svm.c b/arch/x86/kvm/svm.c
index aaa93b4..a27f9e4 100644
--- a/arch/x86/kvm/svm.c
+++ b/arch/x86/kvm/svm.c
@@ -45,7 +45,7 @@
#include <asm/kvm_para.h>
#include <asm/irq_remapping.h>
#include <asm/microcode.h>
-#include <asm/nospec-branch.h>
+#include <asm/spec-ctrl.h>
#include <asm/virtext.h>
#include "trace.h"
@@ -185,6 +185,12 @@
} host;
u64 spec_ctrl;
+ /*
+ * Contains guest-controlled bits of VIRT_SPEC_CTRL, which will be
+ * translated into the appropriate L2_CFG bits on the host to
+ * perform speculative control.
+ */
+ u64 virt_spec_ctrl;
u32 *msrpm;
@@ -1561,6 +1567,7 @@
u32 eax = 1;
svm->spec_ctrl = 0;
+ svm->virt_spec_ctrl = 0;
if (!init_event) {
svm->vcpu.arch.apic_base = APIC_DEFAULT_PHYS_BASE |
@@ -3545,11 +3552,18 @@
break;
case MSR_IA32_SPEC_CTRL:
if (!msr_info->host_initiated &&
- !guest_cpuid_has_ibrs(vcpu))
+ !guest_cpuid_has_spec_ctrl(vcpu))
return 1;
msr_info->data = svm->spec_ctrl;
break;
+ case MSR_AMD64_VIRT_SPEC_CTRL:
+ if (!msr_info->host_initiated &&
+ !guest_cpuid_has_virt_ssbd(vcpu))
+ return 1;
+
+ msr_info->data = svm->virt_spec_ctrl;
+ break;
case MSR_IA32_UCODE_REV:
msr_info->data = 0x01000065;
break;
@@ -3643,7 +3657,7 @@
break;
case MSR_IA32_SPEC_CTRL:
if (!msr->host_initiated &&
- !guest_cpuid_has_ibrs(vcpu))
+ !guest_cpuid_has_spec_ctrl(vcpu))
return 1;
/* The STIBP bit doesn't fault even if it's not advertised */
@@ -3684,6 +3698,16 @@
break;
set_msr_interception(svm->msrpm, MSR_IA32_PRED_CMD, 0, 1);
break;
+ case MSR_AMD64_VIRT_SPEC_CTRL:
+ if (!msr->host_initiated &&
+ !guest_cpuid_has_virt_ssbd(vcpu))
+ return 1;
+
+ if (data & ~SPEC_CTRL_SSBD)
+ return 1;
+
+ svm->virt_spec_ctrl = data;
+ break;
case MSR_STAR:
svm->vmcb->save.star = data;
break;
@@ -4917,8 +4941,7 @@
* is no need to worry about the conditional branch over the wrmsr
* being speculatively taken.
*/
- if (svm->spec_ctrl)
- native_wrmsrl(MSR_IA32_SPEC_CTRL, svm->spec_ctrl);
+ x86_spec_ctrl_set_guest(svm->spec_ctrl, svm->virt_spec_ctrl);
asm volatile (
"push %%" _ASM_BP "; \n\t"
@@ -5012,6 +5035,18 @@
#endif
);
+ /* Eliminate branch target predictions from guest mode */
+ vmexit_fill_RSB();
+
+#ifdef CONFIG_X86_64
+ wrmsrl(MSR_GS_BASE, svm->host.gs_base);
+#else
+ loadsegment(fs, svm->host.fs);
+#ifndef CONFIG_X86_32_LAZY_GS
+ loadsegment(gs, svm->host.gs);
+#endif
+#endif
+
/*
* We do not use IBRS in the kernel. If this vCPU has used the
* SPEC_CTRL MSR it may have left it on; save the value and
@@ -5030,20 +5065,7 @@
if (unlikely(!msr_write_intercepted(vcpu, MSR_IA32_SPEC_CTRL)))
svm->spec_ctrl = native_read_msr(MSR_IA32_SPEC_CTRL);
- if (svm->spec_ctrl)
- native_wrmsrl(MSR_IA32_SPEC_CTRL, 0);
-
- /* Eliminate branch target predictions from guest mode */
- vmexit_fill_RSB();
-
-#ifdef CONFIG_X86_64
- wrmsrl(MSR_GS_BASE, svm->host.gs_base);
-#else
- loadsegment(fs, svm->host.fs);
-#ifndef CONFIG_X86_32_LAZY_GS
- loadsegment(gs, svm->host.gs);
-#endif
-#endif
+ x86_spec_ctrl_restore_host(svm->spec_ctrl, svm->virt_spec_ctrl);
reload_tss(vcpu);
@@ -5145,7 +5167,7 @@
return false;
}
-static bool svm_has_high_real_mode_segbase(void)
+static bool svm_has_emulated_msr(int index)
{
return true;
}
@@ -5462,7 +5484,7 @@
.hardware_enable = svm_hardware_enable,
.hardware_disable = svm_hardware_disable,
.cpu_has_accelerated_tpr = svm_cpu_has_accelerated_tpr,
- .cpu_has_high_real_mode_segbase = svm_has_high_real_mode_segbase,
+ .has_emulated_msr = svm_has_emulated_msr,
.vcpu_create = svm_create_vcpu,
.vcpu_free = svm_free_vcpu,
diff --git a/arch/x86/kvm/vmx.c b/arch/x86/kvm/vmx.c
index ff2030f..c263708 100644
--- a/arch/x86/kvm/vmx.c
+++ b/arch/x86/kvm/vmx.c
@@ -50,7 +50,7 @@
#include <asm/apic.h>
#include <asm/irq_remapping.h>
#include <asm/microcode.h>
-#include <asm/nospec-branch.h>
+#include <asm/spec-ctrl.h>
#include "trace.h"
#include "pmu.h"
@@ -3020,7 +3020,7 @@
break;
case MSR_IA32_SPEC_CTRL:
if (!msr_info->host_initiated &&
- !guest_cpuid_has_ibrs(vcpu))
+ !guest_cpuid_has_spec_ctrl(vcpu))
return 1;
msr_info->data = to_vmx(vcpu)->spec_ctrl;
@@ -3137,11 +3137,11 @@
break;
case MSR_IA32_SPEC_CTRL:
if (!msr_info->host_initiated &&
- !guest_cpuid_has_ibrs(vcpu))
+ !guest_cpuid_has_spec_ctrl(vcpu))
return 1;
/* The STIBP bit doesn't fault even if it's not advertised */
- if (data & ~(SPEC_CTRL_IBRS | SPEC_CTRL_STIBP))
+ if (data & ~(SPEC_CTRL_IBRS | SPEC_CTRL_STIBP | SPEC_CTRL_SSBD))
return 1;
vmx->spec_ctrl = data;
@@ -8690,9 +8690,21 @@
}
}
-static bool vmx_has_high_real_mode_segbase(void)
+static bool vmx_has_emulated_msr(int index)
{
- return enable_unrestricted_guest || emulate_invalid_guest_state;
+ switch (index) {
+ case MSR_IA32_SMBASE:
+ /*
+ * We cannot do SMM unless we can run the guest in big
+ * real mode.
+ */
+ return enable_unrestricted_guest || emulate_invalid_guest_state;
+ case MSR_AMD64_VIRT_SPEC_CTRL:
+ /* This is AMD only. */
+ return false;
+ default:
+ return true;
+ }
}
static bool vmx_mpx_supported(void)
@@ -8915,10 +8927,10 @@
* is no need to worry about the conditional branch over the wrmsr
* being speculatively taken.
*/
- if (vmx->spec_ctrl)
- native_wrmsrl(MSR_IA32_SPEC_CTRL, vmx->spec_ctrl);
+ x86_spec_ctrl_set_guest(vmx->spec_ctrl, 0);
vmx->__launched = vmx->loaded_vmcs->launched;
+
asm(
/* Store host registers */
"push %%" _ASM_DX "; push %%" _ASM_BP ";"
@@ -9054,8 +9066,7 @@
if (unlikely(!msr_write_intercepted(vcpu, MSR_IA32_SPEC_CTRL)))
vmx->spec_ctrl = native_read_msr(MSR_IA32_SPEC_CTRL);
- if (vmx->spec_ctrl)
- native_wrmsrl(MSR_IA32_SPEC_CTRL, 0);
+ x86_spec_ctrl_restore_host(vmx->spec_ctrl, 0);
/* Eliminate branch target predictions from guest mode */
vmexit_fill_RSB();
@@ -11346,7 +11357,7 @@
.hardware_enable = hardware_enable,
.hardware_disable = hardware_disable,
.cpu_has_accelerated_tpr = report_flexpriority,
- .cpu_has_high_real_mode_segbase = vmx_has_high_real_mode_segbase,
+ .has_emulated_msr = vmx_has_emulated_msr,
.vcpu_create = vmx_create_vcpu,
.vcpu_free = vmx_free_vcpu,
diff --git a/arch/x86/kvm/x86.c b/arch/x86/kvm/x86.c
index 3aaaf30..a0cb85f 100644
--- a/arch/x86/kvm/x86.c
+++ b/arch/x86/kvm/x86.c
@@ -1002,6 +1002,7 @@
MSR_IA32_MCG_CTL,
MSR_IA32_MCG_EXT_CTL,
MSR_IA32_SMBASE,
+ MSR_AMD64_VIRT_SPEC_CTRL,
};
static unsigned num_emulated_msrs;
@@ -2664,7 +2665,7 @@
* fringe case that is not enabled except via specific settings
* of the module parameters.
*/
- r = kvm_x86_ops->cpu_has_high_real_mode_segbase();
+ r = kvm_x86_ops->has_emulated_msr(MSR_IA32_SMBASE);
break;
case KVM_CAP_COALESCED_MMIO:
r = KVM_COALESCED_MMIO_PAGE_OFFSET;
@@ -4226,14 +4227,8 @@
num_msrs_to_save = j;
for (i = j = 0; i < ARRAY_SIZE(emulated_msrs); i++) {
- switch (emulated_msrs[i]) {
- case MSR_IA32_SMBASE:
- if (!kvm_x86_ops->cpu_has_high_real_mode_segbase())
- continue;
- break;
- default:
- break;
- }
+ if (!kvm_x86_ops->has_emulated_msr(emulated_msrs[i]))
+ continue;
if (j < i)
emulated_msrs[j] = emulated_msrs[i];
diff --git a/arch/x86/mm/pkeys.c b/arch/x86/mm/pkeys.c
index f88ce0e..0bbec04 100644
--- a/arch/x86/mm/pkeys.c
+++ b/arch/x86/mm/pkeys.c
@@ -95,26 +95,27 @@
*/
if (pkey != -1)
return pkey;
- /*
- * Look for a protection-key-drive execute-only mapping
- * which is now being given permissions that are not
- * execute-only. Move it back to the default pkey.
- */
- if (vma_is_pkey_exec_only(vma) &&
- (prot & (PROT_READ|PROT_WRITE))) {
- return 0;
- }
+
/*
* The mapping is execute-only. Go try to get the
* execute-only protection key. If we fail to do that,
* fall through as if we do not have execute-only
- * support.
+ * support in this mm.
*/
if (prot == PROT_EXEC) {
pkey = execute_only_pkey(vma->vm_mm);
if (pkey > 0)
return pkey;
+ } else if (vma_is_pkey_exec_only(vma)) {
+ /*
+ * Protections are *not* PROT_EXEC, but the mapping
+ * is using the exec-only pkey. This mapping was
+ * PROT_EXEC and will no longer be. Move back to
+ * the default pkey.
+ */
+ return ARCH_DEFAULT_PKEY;
}
+
/*
* This is a vanilla, non-pkey mprotect (or we failed to
* setup execute-only), inherit the pkey from the VMA we
diff --git a/arch/x86/xen/enlighten.c b/arch/x86/xen/enlighten.c
index 2bea87c..081437b 100644
--- a/arch/x86/xen/enlighten.c
+++ b/arch/x86/xen/enlighten.c
@@ -1977,10 +1977,8 @@
static void xen_set_cpu_features(struct cpuinfo_x86 *c)
{
- if (xen_pv_domain()) {
- clear_cpu_bug(c, X86_BUG_SYSRET_SS_ATTRS);
+ if (xen_pv_domain())
set_cpu_cap(c, X86_FEATURE_XENPV);
- }
}
static void xen_pin_vcpu(int cpu)
diff --git a/arch/x86/xen/mmu.c b/arch/x86/xen/mmu.c
index 418f1b8..c92f75f 100644
--- a/arch/x86/xen/mmu.c
+++ b/arch/x86/xen/mmu.c
@@ -1317,8 +1317,6 @@
struct mmuext_op *op;
struct multicall_space mcs;
- trace_xen_mmu_flush_tlb_all(0);
-
preempt_disable();
mcs = xen_mc_entry(sizeof(*op));
@@ -1336,8 +1334,6 @@
struct mmuext_op *op;
struct multicall_space mcs;
- trace_xen_mmu_flush_tlb(0);
-
preempt_disable();
mcs = xen_mc_entry(sizeof(*op));
diff --git a/build.config.cuttlefish.x86_64 b/build.config.cuttlefish.x86_64
index edfa150..8d56143 100644
--- a/build.config.cuttlefish.x86_64
+++ b/build.config.cuttlefish.x86_64
@@ -6,7 +6,7 @@
EXTRA_CMDS=''
KERNEL_DIR=common
POST_DEFCONFIG_CMDS="check_defconfig"
-CLANG_PREBUILT_BIN=prebuilts/clang/host/linux-x86/clang-4630689/bin
+CLANG_PREBUILT_BIN=prebuilts-master/clang/host/linux-x86/clang-r328903/bin
LINUX_GCC_CROSS_COMPILE_PREBUILTS_BIN=prebuilts/gcc/linux-x86/x86/x86_64-linux-android-4.9/bin
FILES="
arch/x86/boot/bzImage
diff --git a/drivers/base/cpu.c b/drivers/base/cpu.c
index 4fe86f7..f9e1010 100644
--- a/drivers/base/cpu.c
+++ b/drivers/base/cpu.c
@@ -610,14 +610,22 @@
return sprintf(buf, "Not affected\n");
}
+ssize_t __weak cpu_show_spec_store_bypass(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ return sprintf(buf, "Not affected\n");
+}
+
static DEVICE_ATTR(meltdown, 0444, cpu_show_meltdown, NULL);
static DEVICE_ATTR(spectre_v1, 0444, cpu_show_spectre_v1, NULL);
static DEVICE_ATTR(spectre_v2, 0444, cpu_show_spectre_v2, NULL);
+static DEVICE_ATTR(spec_store_bypass, 0444, cpu_show_spec_store_bypass, NULL);
static struct attribute *cpu_root_vulnerabilities_attrs[] = {
&dev_attr_meltdown.attr,
&dev_attr_spectre_v1.attr,
&dev_attr_spectre_v2.attr,
+ &dev_attr_spec_store_bypass.attr,
NULL
};
diff --git a/drivers/bluetooth/btusb.c b/drivers/bluetooth/btusb.c
index 3257647..bff67c5 100644
--- a/drivers/bluetooth/btusb.c
+++ b/drivers/bluetooth/btusb.c
@@ -345,6 +345,9 @@
{ USB_DEVICE(0x13d3, 0x3459), .driver_info = BTUSB_REALTEK },
{ USB_DEVICE(0x13d3, 0x3494), .driver_info = BTUSB_REALTEK },
+ /* Additional Realtek 8723BU Bluetooth devices */
+ { USB_DEVICE(0x7392, 0xa611), .driver_info = BTUSB_REALTEK },
+
/* Additional Realtek 8821AE Bluetooth devices */
{ USB_DEVICE(0x0b05, 0x17dc), .driver_info = BTUSB_REALTEK },
{ USB_DEVICE(0x13d3, 0x3414), .driver_info = BTUSB_REALTEK },
@@ -352,6 +355,9 @@
{ USB_DEVICE(0x13d3, 0x3461), .driver_info = BTUSB_REALTEK },
{ USB_DEVICE(0x13d3, 0x3462), .driver_info = BTUSB_REALTEK },
+ /* Additional Realtek 8822BE Bluetooth devices */
+ { USB_DEVICE(0x0b05, 0x185c), .driver_info = BTUSB_REALTEK },
+
/* Silicon Wave based devices */
{ USB_DEVICE(0x0c10, 0x0000), .driver_info = BTUSB_SWAVE },
diff --git a/drivers/char/adsprpc.c b/drivers/char/adsprpc.c
index 7d8605b..d52c80c 100644
--- a/drivers/char/adsprpc.c
+++ b/drivers/char/adsprpc.c
@@ -1567,9 +1567,18 @@
if (map && (map->attr & FASTRPC_ATTR_COHERENT))
continue;
- if (rpra && rpra[i].buf.len && ctx->overps[oix]->mstart)
- dmac_flush_range(uint64_to_ptr(rpra[i].buf.pv),
- uint64_to_ptr(rpra[i].buf.pv + rpra[i].buf.len));
+ if (rpra && rpra[i].buf.len && ctx->overps[oix]->mstart) {
+ if (map && map->handle)
+ msm_ion_do_cache_op(ctx->fl->apps->client,
+ map->handle,
+ uint64_to_ptr(rpra[i].buf.pv),
+ rpra[i].buf.len,
+ ION_IOC_CLEAN_INV_CACHES);
+ else
+ dmac_flush_range(uint64_to_ptr(rpra[i].buf.pv),
+ uint64_to_ptr(rpra[i].buf.pv
+ + rpra[i].buf.len));
+ }
}
PERF_END);
for (i = bufs; rpra && i < bufs + handles; i++) {
@@ -1578,11 +1587,6 @@
rpra[i].dma.offset = (uint32_t)(uintptr_t)lpra[i].buf.pv;
}
- if (!ctx->fl->sctx->smmu.coherent) {
- PERF(ctx->fl->profile, GET_COUNTER(perf_counter, PERF_FLUSH),
- dmac_flush_range((char *)rpra, (char *)rpra + ctx->used);
- PERF_END);
- }
bail:
return err;
}
@@ -1671,14 +1675,33 @@
if (buf_page_start(ptr_to_uint64((void *)rpra)) ==
buf_page_start(rpra[i].buf.pv))
continue;
- if (!IS_CACHE_ALIGNED((uintptr_t)uint64_to_ptr(rpra[i].buf.pv)))
- dmac_flush_range(uint64_to_ptr(rpra[i].buf.pv),
- (char *)(uint64_to_ptr(rpra[i].buf.pv + 1)));
+ if (!IS_CACHE_ALIGNED((uintptr_t)
+ uint64_to_ptr(rpra[i].buf.pv))) {
+ if (map && map->handle)
+ msm_ion_do_cache_op(ctx->fl->apps->client,
+ map->handle,
+ uint64_to_ptr(rpra[i].buf.pv),
+ sizeof(uintptr_t),
+ ION_IOC_CLEAN_INV_CACHES);
+ else
+ dmac_flush_range(
+ uint64_to_ptr(rpra[i].buf.pv), (char *)
+ uint64_to_ptr(rpra[i].buf.pv + 1));
+ }
+
end = (uintptr_t)uint64_to_ptr(rpra[i].buf.pv +
rpra[i].buf.len);
- if (!IS_CACHE_ALIGNED(end))
- dmac_flush_range((char *)end,
- (char *)end + 1);
+ if (!IS_CACHE_ALIGNED(end)) {
+ if (map && map->handle)
+ msm_ion_do_cache_op(ctx->fl->apps->client,
+ map->handle,
+ uint64_to_ptr(end),
+ sizeof(uintptr_t),
+ ION_IOC_CLEAN_INV_CACHES);
+ else
+ dmac_flush_range((char *)end,
+ (char *)end + 1);
+ }
}
}
@@ -1687,7 +1710,6 @@
int i, inbufs, outbufs;
uint32_t sc = ctx->sc;
remote_arg64_t *rpra = ctx->rpra;
- int used = ctx->used;
inbufs = REMOTE_SCALARS_INBUFS(sc);
outbufs = REMOTE_SCALARS_OUTBUFS(sc);
@@ -1718,8 +1740,6 @@
+ rpra[i].buf.len));
}
- if (rpra)
- dmac_inv_range(rpra, (char *)rpra + used);
}
static int fastrpc_invoke_send(struct smq_invoke_ctx *ctx,
diff --git a/drivers/char/diag/diagfwd.c b/drivers/char/diag/diagfwd.c
index 6247503..f1bc1c5 100644
--- a/drivers/char/diag/diagfwd.c
+++ b/drivers/char/diag/diagfwd.c
@@ -48,6 +48,7 @@
#define STM_RSP_SUPPORTED_INDEX 7
#define STM_RSP_STATUS_INDEX 8
#define STM_RSP_NUM_BYTES 9
+#define RETRY_MAX_COUNT 1000
struct diag_md_hdlc_reset_work {
int pid;
@@ -277,28 +278,22 @@
* if its supporting qshrink4 feature.
*/
if (info && info->peripheral_mask) {
- if (info->peripheral_mask == DIAG_CON_ALL ||
- (info->peripheral_mask & (1 << APPS_DATA)) ||
- (info->peripheral_mask & (1 << PERIPHERAL_MODEM))) {
- rsp_ctxt = SET_BUF_CTXT(APPS_DATA, TYPE_CMD, 1);
- } else {
- for (i = 0; i < NUM_MD_SESSIONS; i++) {
- if (info->peripheral_mask & (1 << i))
- break;
- }
- rsp_ctxt = SET_BUF_CTXT(i, TYPE_CMD, 1);
+ for (i = 0; i < NUM_MD_SESSIONS; i++) {
+ if (info->peripheral_mask & (1 << i))
+ break;
}
+ rsp_ctxt = SET_BUF_CTXT(i, TYPE_CMD, TYPE_CMD);
} else
rsp_ctxt = driver->rsp_buf_ctxt;
mutex_unlock(&driver->md_session_lock);
/*
* Keep trying till we get the buffer back. It should probably
- * take one or two iterations. When this loops till UINT_MAX, it
+ * take one or two iterations. When this loops till RETRY_MAX_COUNT, it
* means we did not get a write complete for the previous
* response.
*/
- while (retry_count < UINT_MAX) {
+ while (retry_count < RETRY_MAX_COUNT) {
if (!driver->rsp_buf_busy)
break;
/*
@@ -376,27 +371,21 @@
* if its supporting qshrink4 feature.
*/
if (info && info->peripheral_mask) {
- if (info->peripheral_mask == DIAG_CON_ALL ||
- (info->peripheral_mask & (1 << APPS_DATA)) ||
- (info->peripheral_mask & (1 << PERIPHERAL_MODEM))) {
- rsp_ctxt = SET_BUF_CTXT(APPS_DATA, TYPE_CMD, 1);
- } else {
- for (i = 0; i < NUM_MD_SESSIONS; i++) {
- if (info->peripheral_mask & (1 << i))
- break;
- }
- rsp_ctxt = SET_BUF_CTXT(i, TYPE_CMD, 1);
+ for (i = 0; i < NUM_MD_SESSIONS; i++) {
+ if (info->peripheral_mask & (1 << i))
+ break;
}
+ rsp_ctxt = SET_BUF_CTXT(i, TYPE_CMD, TYPE_CMD);
} else
rsp_ctxt = driver->rsp_buf_ctxt;
mutex_unlock(&driver->md_session_lock);
/*
* Keep trying till we get the buffer back. It should probably
- * take one or two iterations. When this loops till UINT_MAX, it
+ * take one or two iterations. When this loops till RETRY_MAX_COUNT, it
* means we did not get a write complete for the previous
* response.
*/
- while (retry_count < UINT_MAX) {
+ while (retry_count < RETRY_MAX_COUNT) {
if (!driver->rsp_buf_busy)
break;
/*
@@ -1843,14 +1832,18 @@
}
break;
case TYPE_CMD:
- if (peripheral >= 0 && peripheral < NUM_PERIPHERALS) {
+ if (peripheral >= 0 && peripheral < NUM_PERIPHERALS &&
+ num != TYPE_CMD) {
DIAG_LOG(DIAG_DEBUG_PERIPHERALS,
"Marking buffer as free after write done p: %d, t: %d, buf_num: %d\n",
- peripheral, type, num);
+ peripheral, type, num);
diagfwd_write_done(peripheral, type, num);
- }
- if (peripheral == APPS_DATA ||
- ctxt == DIAG_MEMORY_DEVICE_MODE) {
+ } else if (peripheral == APPS_DATA ||
+ (peripheral >= 0 && peripheral < NUM_PERIPHERALS &&
+ num == TYPE_CMD)) {
+ DIAG_LOG(DIAG_DEBUG_PERIPHERALS,
+ "Marking APPS response buffer free after write done for p: %d, t: %d, buf_num: %d\n",
+ peripheral, type, num);
spin_lock_irqsave(&driver->rsp_buf_busy_lock, flags);
driver->rsp_buf_busy = 0;
driver->encoded_rsp_len = 0;
diff --git a/drivers/clk/clk.c b/drivers/clk/clk.c
index f41307d..0426ff7 100644
--- a/drivers/clk/clk.c
+++ b/drivers/clk/clk.c
@@ -2280,6 +2280,9 @@
int ret;
clk_prepare_lock();
+ /* Always try to update cached phase if possible */
+ if (core->ops->get_phase)
+ core->phase = core->ops->get_phase(core->hw);
ret = core->phase;
clk_prepare_unlock();
diff --git a/drivers/clk/msm/clock-cpu-8939.c b/drivers/clk/msm/clock-cpu-8939.c
index 5ba6bd0..5b8b8f3 100644
--- a/drivers/clk/msm/clock-cpu-8939.c
+++ b/drivers/clk/msm/clock-cpu-8939.c
@@ -999,7 +999,7 @@
return rc;
}
-late_initcall(clock_cpu_lpm_get_latency);
+late_initcall_sync(clock_cpu_lpm_get_latency);
#define APCS_C0_PLL 0xb116000
#define C0_PLL_MODE 0x0
diff --git a/drivers/clk/rockchip/clk-mmc-phase.c b/drivers/clk/rockchip/clk-mmc-phase.c
index 077fcdc..fe7d9ed 100644
--- a/drivers/clk/rockchip/clk-mmc-phase.c
+++ b/drivers/clk/rockchip/clk-mmc-phase.c
@@ -58,6 +58,12 @@
u16 degrees;
u32 delay_num = 0;
+ /* See the comment for rockchip_mmc_set_phase below */
+ if (!rate) {
+ pr_err("%s: invalid clk rate\n", __func__);
+ return -EINVAL;
+ }
+
raw_value = readl(mmc_clock->reg) >> (mmc_clock->shift);
degrees = (raw_value & ROCKCHIP_MMC_DEGREE_MASK) * 90;
@@ -84,6 +90,23 @@
u32 raw_value;
u32 delay;
+ /*
+ * The below calculation is based on the output clock from
+ * MMC host to the card, which expects the phase clock inherits
+ * the clock rate from its parent, namely the output clock
+ * provider of MMC host. However, things may go wrong if
+ * (1) It is orphan.
+ * (2) It is assigned to the wrong parent.
+ *
+ * This check help debug the case (1), which seems to be the
+ * most likely problem we often face and which makes it difficult
+ * for people to debug unstable mmc tuning results.
+ */
+ if (!rate) {
+ pr_err("%s: invalid clk rate\n", __func__);
+ return -EINVAL;
+ }
+
nineties = degrees / 90;
remainder = (degrees % 90);
diff --git a/drivers/clk/rockchip/clk-rk3228.c b/drivers/clk/rockchip/clk-rk3228.c
index db6e5a9..53f16ef 100644
--- a/drivers/clk/rockchip/clk-rk3228.c
+++ b/drivers/clk/rockchip/clk-rk3228.c
@@ -369,7 +369,7 @@
RK2928_CLKSEL_CON(23), 5, 2, MFLAGS, 0, 6, DFLAGS,
RK2928_CLKGATE_CON(2), 15, GFLAGS),
- COMPOSITE(SCLK_SDMMC, "sclk_sdmmc0", mux_mmc_src_p, 0,
+ COMPOSITE(SCLK_SDMMC, "sclk_sdmmc", mux_mmc_src_p, 0,
RK2928_CLKSEL_CON(11), 8, 2, MFLAGS, 0, 8, DFLAGS,
RK2928_CLKGATE_CON(2), 11, GFLAGS),
diff --git a/drivers/clk/samsung/clk-exynos3250.c b/drivers/clk/samsung/clk-exynos3250.c
index 1b81e28..ed36728 100644
--- a/drivers/clk/samsung/clk-exynos3250.c
+++ b/drivers/clk/samsung/clk-exynos3250.c
@@ -698,7 +698,7 @@
PLL_36XX_RATE(144000000, 96, 2, 3, 0),
PLL_36XX_RATE( 96000000, 128, 2, 4, 0),
PLL_36XX_RATE( 84000000, 112, 2, 4, 0),
- PLL_36XX_RATE( 80000004, 106, 2, 4, 43691),
+ PLL_36XX_RATE( 80000003, 106, 2, 4, 43691),
PLL_36XX_RATE( 73728000, 98, 2, 4, 19923),
PLL_36XX_RATE( 67737598, 270, 3, 5, 62285),
PLL_36XX_RATE( 65535999, 174, 2, 5, 49982),
@@ -734,7 +734,7 @@
PLL_36XX_RATE(148352005, 98, 2, 3, 59070),
PLL_36XX_RATE(108000000, 144, 2, 4, 0),
PLL_36XX_RATE( 74250000, 99, 2, 4, 0),
- PLL_36XX_RATE( 74176002, 98, 3, 4, 59070),
+ PLL_36XX_RATE( 74176002, 98, 2, 4, 59070),
PLL_36XX_RATE( 54054000, 216, 3, 5, 14156),
PLL_36XX_RATE( 54000000, 144, 2, 5, 0),
{ /* sentinel */ }
diff --git a/drivers/clk/samsung/clk-exynos5250.c b/drivers/clk/samsung/clk-exynos5250.c
index 27a227d..6a0cb8a 100644
--- a/drivers/clk/samsung/clk-exynos5250.c
+++ b/drivers/clk/samsung/clk-exynos5250.c
@@ -711,13 +711,13 @@
/* sorted in descending order */
/* PLL_36XX_RATE(rate, m, p, s, k) */
PLL_36XX_RATE(192000000, 64, 2, 2, 0),
- PLL_36XX_RATE(180633600, 90, 3, 2, 20762),
+ PLL_36XX_RATE(180633605, 90, 3, 2, 20762),
PLL_36XX_RATE(180000000, 90, 3, 2, 0),
PLL_36XX_RATE(73728000, 98, 2, 4, 19923),
- PLL_36XX_RATE(67737600, 90, 2, 4, 20762),
+ PLL_36XX_RATE(67737602, 90, 2, 4, 20762),
PLL_36XX_RATE(49152000, 98, 3, 4, 19923),
- PLL_36XX_RATE(45158400, 90, 3, 4, 20762),
- PLL_36XX_RATE(32768000, 131, 3, 5, 4719),
+ PLL_36XX_RATE(45158401, 90, 3, 4, 20762),
+ PLL_36XX_RATE(32768001, 131, 3, 5, 4719),
{ },
};
diff --git a/drivers/clk/samsung/clk-exynos5260.c b/drivers/clk/samsung/clk-exynos5260.c
index fd1d9bf..8eae175 100644
--- a/drivers/clk/samsung/clk-exynos5260.c
+++ b/drivers/clk/samsung/clk-exynos5260.c
@@ -65,7 +65,7 @@
PLL_36XX_RATE(480000000, 160, 2, 2, 0),
PLL_36XX_RATE(432000000, 144, 2, 2, 0),
PLL_36XX_RATE(400000000, 200, 3, 2, 0),
- PLL_36XX_RATE(394073130, 459, 7, 2, 49282),
+ PLL_36XX_RATE(394073128, 459, 7, 2, 49282),
PLL_36XX_RATE(333000000, 111, 2, 2, 0),
PLL_36XX_RATE(300000000, 100, 2, 2, 0),
PLL_36XX_RATE(266000000, 266, 3, 3, 0),
diff --git a/drivers/clk/samsung/clk-exynos5433.c b/drivers/clk/samsung/clk-exynos5433.c
index 2fe0573..09cdd35 100644
--- a/drivers/clk/samsung/clk-exynos5433.c
+++ b/drivers/clk/samsung/clk-exynos5433.c
@@ -725,7 +725,7 @@
PLL_35XX_RATE(800000000U, 400, 6, 1),
PLL_35XX_RATE(733000000U, 733, 12, 1),
PLL_35XX_RATE(700000000U, 175, 3, 1),
- PLL_35XX_RATE(667000000U, 222, 4, 1),
+ PLL_35XX_RATE(666000000U, 222, 4, 1),
PLL_35XX_RATE(633000000U, 211, 4, 1),
PLL_35XX_RATE(600000000U, 500, 5, 2),
PLL_35XX_RATE(552000000U, 460, 5, 2),
@@ -751,12 +751,12 @@
/* AUD_PLL */
static const struct samsung_pll_rate_table exynos5443_aud_pll_rates[] __initconst = {
PLL_36XX_RATE(400000000U, 200, 3, 2, 0),
- PLL_36XX_RATE(393216000U, 197, 3, 2, -25690),
+ PLL_36XX_RATE(393216003U, 197, 3, 2, -25690),
PLL_36XX_RATE(384000000U, 128, 2, 2, 0),
- PLL_36XX_RATE(368640000U, 246, 4, 2, -15729),
- PLL_36XX_RATE(361507200U, 181, 3, 2, -16148),
- PLL_36XX_RATE(338688000U, 113, 2, 2, -6816),
- PLL_36XX_RATE(294912000U, 98, 1, 3, 19923),
+ PLL_36XX_RATE(368639991U, 246, 4, 2, -15729),
+ PLL_36XX_RATE(361507202U, 181, 3, 2, -16148),
+ PLL_36XX_RATE(338687988U, 113, 2, 2, -6816),
+ PLL_36XX_RATE(294912002U, 98, 1, 3, 19923),
PLL_36XX_RATE(288000000U, 96, 1, 3, 0),
PLL_36XX_RATE(252000000U, 84, 1, 3, 0),
{ /* sentinel */ }
diff --git a/drivers/clk/samsung/clk-exynos7.c b/drivers/clk/samsung/clk-exynos7.c
index 5931a41..bbfa57b 100644
--- a/drivers/clk/samsung/clk-exynos7.c
+++ b/drivers/clk/samsung/clk-exynos7.c
@@ -140,7 +140,7 @@
};
static const struct samsung_pll_rate_table pll1460x_24mhz_tbl[] __initconst = {
- PLL_36XX_RATE(491520000, 20, 1, 0, 31457),
+ PLL_36XX_RATE(491519897, 20, 1, 0, 31457),
{},
};
diff --git a/drivers/clk/samsung/clk-s3c2410.c b/drivers/clk/samsung/clk-s3c2410.c
index d7a1e77..5f50037 100644
--- a/drivers/clk/samsung/clk-s3c2410.c
+++ b/drivers/clk/samsung/clk-s3c2410.c
@@ -168,7 +168,7 @@
PLL_35XX_RATE(226000000, 105, 1, 1),
PLL_35XX_RATE(210000000, 132, 2, 1),
/* 2410 common */
- PLL_35XX_RATE(203000000, 161, 3, 1),
+ PLL_35XX_RATE(202800000, 161, 3, 1),
PLL_35XX_RATE(192000000, 88, 1, 1),
PLL_35XX_RATE(186000000, 85, 1, 1),
PLL_35XX_RATE(180000000, 82, 1, 1),
@@ -178,18 +178,18 @@
PLL_35XX_RATE(147000000, 90, 2, 1),
PLL_35XX_RATE(135000000, 82, 2, 1),
PLL_35XX_RATE(124000000, 116, 1, 2),
- PLL_35XX_RATE(118000000, 150, 2, 2),
+ PLL_35XX_RATE(118500000, 150, 2, 2),
PLL_35XX_RATE(113000000, 105, 1, 2),
- PLL_35XX_RATE(101000000, 127, 2, 2),
+ PLL_35XX_RATE(101250000, 127, 2, 2),
PLL_35XX_RATE(90000000, 112, 2, 2),
- PLL_35XX_RATE(85000000, 105, 2, 2),
+ PLL_35XX_RATE(84750000, 105, 2, 2),
PLL_35XX_RATE(79000000, 71, 1, 2),
- PLL_35XX_RATE(68000000, 82, 2, 2),
- PLL_35XX_RATE(56000000, 142, 2, 3),
+ PLL_35XX_RATE(67500000, 82, 2, 2),
+ PLL_35XX_RATE(56250000, 142, 2, 3),
PLL_35XX_RATE(48000000, 120, 2, 3),
- PLL_35XX_RATE(51000000, 161, 3, 3),
+ PLL_35XX_RATE(50700000, 161, 3, 3),
PLL_35XX_RATE(45000000, 82, 1, 3),
- PLL_35XX_RATE(34000000, 82, 2, 3),
+ PLL_35XX_RATE(33750000, 82, 2, 3),
{ /* sentinel */ },
};
diff --git a/drivers/clk/tegra/clk-pll.c b/drivers/clk/tegra/clk-pll.c
index b385536..66d1fc7 100644
--- a/drivers/clk/tegra/clk-pll.c
+++ b/drivers/clk/tegra/clk-pll.c
@@ -1145,6 +1145,8 @@
.enable = clk_pllu_enable,
.disable = clk_pll_disable,
.recalc_rate = clk_pll_recalc_rate,
+ .round_rate = clk_pll_round_rate,
+ .set_rate = clk_pll_set_rate,
};
static int _pll_fixed_mdiv(struct tegra_clk_pll_params *pll_params,
diff --git a/drivers/clocksource/Kconfig b/drivers/clocksource/Kconfig
index cd6d307..91cf857 100644
--- a/drivers/clocksource/Kconfig
+++ b/drivers/clocksource/Kconfig
@@ -331,6 +331,15 @@
This option enables support for reading the ARM architected timer's
virtual counter in userspace.
+config MSM_TIMER_LEAP
+ bool "ARCH TIMER counter rollover"
+ default n
+ depends on ARM_ARCH_TIMER && ARM64
+ help
+ This option enables a check for least significant 32 bits of
+ counter rollover. On every counter read if least significant
+ 32 bits are set, reread counter.
+
config ARM_GLOBAL_TIMER
bool "Support for the ARM global timer" if COMPILE_TEST
select CLKSRC_OF if OF
diff --git a/drivers/cpufreq/cpufreq.c b/drivers/cpufreq/cpufreq.c
index 7279448..5474ae7 100644
--- a/drivers/cpufreq/cpufreq.c
+++ b/drivers/cpufreq/cpufreq.c
@@ -1506,6 +1506,9 @@
policy->freq_table = NULL;
}
+ blocking_notifier_call_chain(&cpufreq_policy_notifier_list,
+ CPUFREQ_STOP, policy);
+
unlock:
up_write(&policy->rwsem);
return 0;
diff --git a/drivers/cpuidle/lpm-levels.c b/drivers/cpuidle/lpm-levels.c
index 463589a..c7ec868 100644
--- a/drivers/cpuidle/lpm-levels.c
+++ b/drivers/cpuidle/lpm-levels.c
@@ -159,7 +159,7 @@
uint32_t latency = 0;
int i;
- if (!cluster->list.next) {
+ if (list_empty(&cluster->list)) {
for (i = 0; i < cluster->nlevels; i++) {
level = &cluster->levels[i];
pwr_params = &level->pwr;
diff --git a/drivers/crypto/sunxi-ss/sun4i-ss-core.c b/drivers/crypto/sunxi-ss/sun4i-ss-core.c
index 3ac6c6c..16bb660 100644
--- a/drivers/crypto/sunxi-ss/sun4i-ss-core.c
+++ b/drivers/crypto/sunxi-ss/sun4i-ss-core.c
@@ -422,6 +422,7 @@
module_platform_driver(sun4i_ss_driver);
+MODULE_ALIAS("platform:sun4i-ss");
MODULE_DESCRIPTION("Allwinner Security System cryptographic accelerator");
MODULE_LICENSE("GPL");
MODULE_AUTHOR("Corentin LABBE <clabbe.montjoie@gmail.com>");
diff --git a/drivers/extcon/extcon-usb-gpio.c b/drivers/extcon/extcon-usb-gpio.c
index 2e093c3..2b108fa 100644
--- a/drivers/extcon/extcon-usb-gpio.c
+++ b/drivers/extcon/extcon-usb-gpio.c
@@ -277,9 +277,8 @@
if (info->vbus_gpiod)
enable_irq(info->vbus_irq);
- if (!device_may_wakeup(dev))
- queue_delayed_work(system_power_efficient_wq,
- &info->wq_detcable, 0);
+ queue_delayed_work(system_power_efficient_wq,
+ &info->wq_detcable, 0);
return ret;
}
diff --git a/drivers/gpu/drm/msm/dp/dp_display.c b/drivers/gpu/drm/msm/dp/dp_display.c
index 1b92261..d9839e7 100644
--- a/drivers/gpu/drm/msm/dp/dp_display.c
+++ b/drivers/gpu/drm/msm/dp/dp_display.c
@@ -1488,6 +1488,7 @@
.driver = {
.name = "msm-dp-display",
.of_match_table = dp_dt_match,
+ .suppress_bind_attrs = true,
},
};
diff --git a/drivers/gpu/drm/msm/dsi-staging/dsi_ctrl.c b/drivers/gpu/drm/msm/dsi-staging/dsi_ctrl.c
index 92e08e0..c0652dd 100644
--- a/drivers/gpu/drm/msm/dsi-staging/dsi_ctrl.c
+++ b/drivers/gpu/drm/msm/dsi-staging/dsi_ctrl.c
@@ -1797,6 +1797,7 @@
.driver = {
.name = "drm_dsi_ctrl",
.of_match_table = msm_dsi_of_match,
+ .suppress_bind_attrs = true,
},
};
diff --git a/drivers/gpu/drm/msm/dsi-staging/dsi_display.c b/drivers/gpu/drm/msm/dsi-staging/dsi_display.c
index 75bbbfd..9a75de6 100644
--- a/drivers/gpu/drm/msm/dsi-staging/dsi_display.c
+++ b/drivers/gpu/drm/msm/dsi-staging/dsi_display.c
@@ -48,13 +48,16 @@
static char dsi_display_primary[MAX_CMDLINE_PARAM_LEN];
static char dsi_display_secondary[MAX_CMDLINE_PARAM_LEN];
static struct dsi_display_boot_param boot_displays[MAX_DSI_ACTIVE_DISPLAY];
-static struct device_node *default_active_node;
+static struct device_node *primary_active_node;
+static struct device_node *secondary_active_node;
+
static const struct of_device_id dsi_display_dt_match[] = {
{.compatible = "qcom,dsi-display"},
{}
};
-static struct dsi_display *main_display;
+static struct dsi_display *primary_display;
+static struct dsi_display *secondary_display;
static void dsi_display_mask_ctrl_error_interrupts(struct dsi_display *display)
{
@@ -568,6 +571,8 @@
for (i = 0; i < count; ++i) {
memset(config->status_buf, 0x0, SZ_4K);
+ if (config->status_cmd.state == DSI_CMD_SET_STATE_LP)
+ cmds[i].msg.flags |= MIPI_DSI_MSG_USE_LPM;
if (cmds[i].last_command) {
cmds[i].msg.flags |= MIPI_DSI_MSG_LASTCOMMAND;
flags |= DSI_CTRL_CMD_LAST_COMMAND;
@@ -1163,7 +1168,7 @@
rc = dsi_panel_trigger_esd_attack(display->panel);
if (rc) {
pr_err("Failed to trigger ESD attack\n");
- return rc;
+ goto error;
}
}
@@ -2017,11 +2022,9 @@
boot_displays[i].name[j] = *(disp_buf + j);
boot_displays[i].name[j] = '\0';
- if (i == DSI_PRIMARY) {
+ if (i == DSI_PRIMARY)
boot_displays[i].is_primary = true;
- /* Currently, secondary DSI display is not supported */
- boot_displays[i].boot_disp_en = true;
- }
+ boot_displays[i].boot_disp_en = true;
}
return 0;
}
@@ -2044,6 +2047,8 @@
for (i = 0; i < MAX_DSI_ACTIVE_DISPLAY; i++) {
node = boot_displays[i].node;
+ if (!node)
+ continue;
ctrl_count = of_count_phandle_with_args(node, "qcom,dsi-ctrl",
NULL);
@@ -2085,11 +2090,12 @@
pr_err("index = %d\n", index);
- if (boot_displays[index].node)
- return boot_displays[index].node;
- else if ((index == (MAX_DSI_ACTIVE_DISPLAY - 1))
- && (default_active_node))
- return default_active_node;
+ if ((index == DSI_PRIMARY)
+ && (primary_active_node))
+ return primary_active_node;
+ else if ((index == DSI_SECONDARY)
+ && (secondary_active_node))
+ return secondary_active_node;
else
return NULL;
}
@@ -3148,9 +3154,6 @@
__func__, rc);
goto error;
}
-
- /* enable dsi to serve irqs */
- dsi_display_ctrl_irq_update(display, true);
}
if ((clk & DSI_LINK_CLK) && (l_type & DSI_LINK_HS_CLK)) {
@@ -3172,6 +3175,11 @@
}
}
}
+
+ /* enable dsi to serve irqs */
+ if (clk & DSI_CORE_CLK)
+ dsi_display_ctrl_irq_update(display, true);
+
error:
return rc;
}
@@ -4637,6 +4645,7 @@
.driver = {
.name = "msm-dsi-display",
.of_match_table = dsi_display_dt_match,
+ .suppress_bind_attrs = true,
},
};
@@ -4644,8 +4653,7 @@
{
int rc = 0;
struct dsi_display *display;
- static bool display_from_cmdline, boot_displays_parsed;
- static bool comp_add_success;
+ static bool boot_displays_parsed;
static struct device_node *primary_np, *secondary_np;
if (!pdev || !pdev->dev.of_node) {
@@ -4674,55 +4682,53 @@
display->cmdline_topology = NO_OVERRIDE;
display->cmdline_timing = 0;
- if ((!display_from_cmdline) &&
- (boot_displays[DSI_PRIMARY].boot_disp_en)) {
- display->is_active = dsi_display_name_compare(pdev->dev.of_node,
- display->name, DSI_PRIMARY);
- if (display->is_active) {
- if (comp_add_success) {
- (void)_dsi_display_dev_deinit(main_display);
- component_del(&main_display->pdev->dev,
- &dsi_display_comp_ops);
- mutex_lock(&dsi_display_list_lock);
- list_del(&main_display->list);
- mutex_unlock(&dsi_display_list_lock);
- comp_add_success = false;
- default_active_node = NULL;
- pr_debug("removed the existing comp ops\n");
- }
- /*
- * Need to add component for
- * the secondary DSI display
- * when more than one DSI display
- * is supported.
- */
- pr_debug("cmdline primary dsi: %s\n",
- display->name);
- display_from_cmdline = true;
- dsi_display_parse_cmdline_topology(display,
- DSI_PRIMARY);
- primary_np = pdev->dev.of_node;
+ if (boot_displays[DSI_PRIMARY].boot_disp_en && !primary_np &&
+ dsi_display_name_compare(pdev->dev.of_node,
+ display->name, DSI_PRIMARY)) {
+ if (primary_display) {
+ (void)_dsi_display_dev_deinit(primary_display);
+ component_del(&primary_display->pdev->dev,
+ &dsi_display_comp_ops);
+ mutex_lock(&dsi_display_list_lock);
+ list_del(&primary_display->list);
+ mutex_unlock(&dsi_display_list_lock);
+ primary_active_node = NULL;
+ pr_debug("removed the existing comp ops\n");
}
+ /*
+ * Need to add component for
+ * the secondary DSI display
+ * when more than one DSI display
+ * is supported.
+ */
+ pr_debug("cmdline primary dsi: %s\n", display->name);
+ display->is_active = true;
+ dsi_display_parse_cmdline_topology(display, DSI_PRIMARY);
+ primary_np = pdev->dev.of_node;
}
- if (boot_displays[DSI_SECONDARY].boot_disp_en) {
- if (!secondary_np) {
- if (dsi_display_name_compare(pdev->dev.of_node,
- display->name, DSI_SECONDARY)) {
- pr_debug("cmdline secondary dsi: %s\n",
- display->name);
- secondary_np = pdev->dev.of_node;
- if (primary_np) {
- if (validate_dsi_display_selection()) {
- display->is_active = true;
- dsi_display_parse_cmdline_topology
- (display, DSI_SECONDARY);
- } else {
- boot_displays[DSI_SECONDARY]
- .boot_disp_en = false;
- }
- }
+ if (boot_displays[DSI_SECONDARY].boot_disp_en && !secondary_np &&
+ dsi_display_name_compare(pdev->dev.of_node,
+ display->name, DSI_SECONDARY)) {
+ pr_debug("cmdline secondary dsi: %s\n", display->name);
+ if (validate_dsi_display_selection()) {
+ if (secondary_display) {
+ (void)_dsi_display_dev_deinit(
+ secondary_display);
+ component_del(&secondary_display->pdev->dev,
+ &dsi_display_comp_ops);
+ mutex_lock(&dsi_display_list_lock);
+ list_del(&secondary_display->list);
+ mutex_unlock(&dsi_display_list_lock);
+ secondary_active_node = NULL;
+ pr_debug("removed the existing comp ops\n");
}
+ display->is_active = true;
+ dsi_display_parse_cmdline_topology(display,
+ DSI_SECONDARY);
+ secondary_np = pdev->dev.of_node;
+ } else {
+ boot_displays[DSI_SECONDARY].boot_disp_en = false;
}
}
display->display_type = of_get_property(pdev->dev.of_node,
@@ -4737,12 +4743,18 @@
list_add(&display->list, &dsi_display_list);
mutex_unlock(&dsi_display_list_lock);
- if (!display_from_cmdline)
+ if (!strcmp(display->display_type, "primary") && !primary_np)
+ display->is_active = of_property_read_bool(pdev->dev.of_node,
+ "qcom,dsi-display-active");
+ else if (strcmp(display->display_type, "primary") && !secondary_np)
display->is_active = of_property_read_bool(pdev->dev.of_node,
"qcom,dsi-display-active");
if (display->is_active) {
- main_display = display;
+ if (!strcmp(display->display_type, "primary"))
+ primary_display = display;
+ else
+ secondary_display = display;
rc = _dsi_display_dev_init(display);
if (rc) {
pr_err("device init failed, rc=%d\n", rc);
@@ -4753,10 +4765,11 @@
if (rc)
pr_err("component add failed, rc=%d\n", rc);
- comp_add_success = true;
pr_debug("Component_add success: %s\n", display->name);
- if (!display_from_cmdline)
- default_active_node = pdev->dev.of_node;
+ if (!strcmp(display->display_type, "primary"))
+ primary_active_node = pdev->dev.of_node;
+ else
+ secondary_active_node = pdev->dev.of_node;
}
return rc;
}
@@ -4995,7 +5008,10 @@
info->h_tile_instance[i] = display->ctrl[i].ctrl->cell_index;
info->is_connected = true;
- info->is_primary = true;
+ info->is_primary = false;
+ if (!strcmp(display->display_type, "primary"))
+ info->is_primary = true;
+
info->width_mm = phy_props.panel_width_mm;
info->height_mm = phy_props.panel_height_mm;
info->max_width = 1920;
diff --git a/drivers/gpu/drm/msm/dsi/dsi.c b/drivers/gpu/drm/msm/dsi/dsi.c
index ec572f8..e457322 100644
--- a/drivers/gpu/drm/msm/dsi/dsi.c
+++ b/drivers/gpu/drm/msm/dsi/dsi.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2015, The Linux Foundation. All rights reserved.
+ * Copyright (c) 2015, 2018 The Linux Foundation. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 and
@@ -169,6 +169,7 @@
.driver = {
.name = "msm_dsi",
.of_match_table = dt_match,
+ .suppress_bind_attrs = true,
},
};
diff --git a/drivers/gpu/drm/msm/edp/edp.c b/drivers/gpu/drm/msm/edp/edp.c
index 2c9d116..3a0f180 100644
--- a/drivers/gpu/drm/msm/edp/edp.c
+++ b/drivers/gpu/drm/msm/edp/edp.c
@@ -128,6 +128,7 @@
.driver = {
.name = "msm_edp",
.of_match_table = dt_match,
+ .suppress_bind_attrs = true,
},
};
diff --git a/drivers/gpu/drm/msm/hdmi/hdmi.c b/drivers/gpu/drm/msm/hdmi/hdmi.c
index 6279084..b8f5469 100644
--- a/drivers/gpu/drm/msm/hdmi/hdmi.c
+++ b/drivers/gpu/drm/msm/hdmi/hdmi.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2014, 2016 The Linux Foundation. All rights reserved.
+ * Copyright (c) 2014, 2016, 2018 The Linux Foundation. All rights reserved.
* Copyright (C) 2013 Red Hat
* Author: Rob Clark <robdclark@gmail.com>
*
@@ -646,6 +646,7 @@
.driver = {
.name = "hdmi_msm",
.of_match_table = msm_hdmi_dt_match,
+ .suppress_bind_attrs = true,
},
};
diff --git a/drivers/gpu/drm/msm/mdp/mdp5/mdp5_kms.c b/drivers/gpu/drm/msm/mdp/mdp5/mdp5_kms.c
index f05d760..46b60b1 100644
--- a/drivers/gpu/drm/msm/mdp/mdp5/mdp5_kms.c
+++ b/drivers/gpu/drm/msm/mdp/mdp5/mdp5_kms.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2014, 2016-2017 The Linux Foundation. All rights reserved.
+ * Copyright (c) 2014, 2016-2018 The Linux Foundation. All rights reserved.
* Copyright (C) 2013 Red Hat
* Author: Rob Clark <robdclark@gmail.com>
*
@@ -827,6 +827,7 @@
.driver = {
.name = "msm_mdp",
.of_match_table = mdp5_dt_match,
+ .suppress_bind_attrs = true,
},
};
diff --git a/drivers/gpu/drm/msm/msm_drv.c b/drivers/gpu/drm/msm/msm_drv.c
index 9eb62fe..0f565d3 100644
--- a/drivers/gpu/drm/msm/msm_drv.c
+++ b/drivers/gpu/drm/msm/msm_drv.c
@@ -1994,6 +1994,7 @@
.name = "msm_drm",
.of_match_table = dt_match,
.pm = &msm_pm_ops,
+ .suppress_bind_attrs = true,
},
};
diff --git a/drivers/gpu/drm/msm/msm_smmu.c b/drivers/gpu/drm/msm/msm_smmu.c
index 85867b2..ccd5e20 100644
--- a/drivers/gpu/drm/msm/msm_smmu.c
+++ b/drivers/gpu/drm/msm/msm_smmu.c
@@ -636,6 +636,7 @@
.driver = {
.name = "msmdrm_smmu",
.of_match_table = msm_smmu_dt_match,
+ .suppress_bind_attrs = true,
},
};
diff --git a/drivers/gpu/drm/msm/sde/sde_crtc.c b/drivers/gpu/drm/msm/sde/sde_crtc.c
index f5c24e2..34a3d5f 100644
--- a/drivers/gpu/drm/msm/sde/sde_crtc.c
+++ b/drivers/gpu/drm/msm/sde/sde_crtc.c
@@ -2380,7 +2380,6 @@
struct sde_crtc *sde_crtc;
struct sde_kms *sde_kms;
unsigned long flags;
- bool frame_done = false;
bool in_clone_mode = false;
if (!work) {
@@ -2435,10 +2434,6 @@
SDE_EVT32_VERBOSE(DRMID(crtc), fevent->event,
SDE_EVTLOG_FUNC_CASE3);
}
-
- if (fevent->event & (SDE_ENCODER_FRAME_EVENT_DONE
- | SDE_ENCODER_FRAME_EVENT_ERROR))
- frame_done = true;
}
if (fevent->event & SDE_ENCODER_FRAME_EVENT_SIGNAL_RELEASE_FENCE) {
@@ -2459,9 +2454,6 @@
SDE_ERROR("crtc%d ts:%lld received panel dead event\n",
crtc->base.id, ktime_to_ns(fevent->ts));
- if (frame_done)
- complete_all(&sde_crtc->frame_done_comp);
-
spin_lock_irqsave(&sde_crtc->spin_lock, flags);
list_add_tail(&fevent->list, &sde_crtc->frame_event_list);
spin_unlock_irqrestore(&sde_crtc->spin_lock, flags);
@@ -3341,10 +3333,10 @@
&cstate->property_state);
}
-static int _sde_crtc_wait_for_frame_done(struct drm_crtc *crtc)
+static int _sde_crtc_flush_event_thread(struct drm_crtc *crtc)
{
struct sde_crtc *sde_crtc;
- int ret, rc = 0, i;
+ int i;
if (!crtc) {
SDE_ERROR("invalid argument\n");
@@ -3368,17 +3360,9 @@
kthread_flush_work(&sde_crtc->frame_events[i].work);
}
- ret = wait_for_completion_timeout(&sde_crtc->frame_done_comp,
- msecs_to_jiffies(SDE_FRAME_DONE_TIMEOUT));
- if (!ret) {
- SDE_ERROR("frame done completion wait timed out, ret:%d\n",
- ret);
- SDE_EVT32(DRMID(crtc), SDE_EVTLOG_FATAL);
- rc = -ETIMEDOUT;
- }
SDE_EVT32_VERBOSE(DRMID(crtc), SDE_EVTLOG_FUNC_EXIT);
- return rc;
+ return 0;
}
static int _sde_crtc_commit_kickoff_rot(struct drm_crtc *crtc,
@@ -3705,7 +3689,6 @@
struct sde_kms *sde_kms;
struct sde_crtc_state *cstate;
bool is_error, reset_req;
- int ret;
if (!crtc) {
SDE_ERROR("invalid argument\n");
@@ -3764,23 +3747,11 @@
}
sde_crtc->reset_request = reset_req;
- /* wait for frame_event_done completion */
- SDE_ATRACE_BEGIN("wait_for_frame_done_event");
- ret = _sde_crtc_wait_for_frame_done(crtc);
- SDE_ATRACE_END("wait_for_frame_done_event");
+ SDE_ATRACE_BEGIN("flush_event_thread");
+ _sde_crtc_flush_event_thread(crtc);
+ SDE_ATRACE_END("flush_event_thread");
sde_crtc_calc_fps(sde_crtc);
- if (ret) {
- SDE_ERROR("crtc%d wait for frame done failed;frame_pending%d\n",
- crtc->base.id,
- atomic_read(&sde_crtc->frame_pending));
-
- is_error = true;
-
- /* force offline rotation mode since the commit has no pipes */
- cstate->sbuf_cfg.rot_op_mode = SDE_CTL_ROT_OP_MODE_OFFLINE;
- }
-
if (atomic_inc_return(&sde_crtc->frame_pending) == 1) {
/* acquire bandwidth and other resources */
SDE_DEBUG("crtc%d first commit\n", crtc->base.id);
@@ -3818,7 +3789,6 @@
sde_encoder_kickoff(encoder, false);
}
- reinit_completion(&sde_crtc->frame_done_comp);
SDE_ATRACE_END("crtc_commit");
return;
}
@@ -4219,11 +4189,7 @@
if (cstate->num_ds_enabled)
sde_crtc->ds_reconfig = true;
- /* wait for frame_event_done completion */
- if (_sde_crtc_wait_for_frame_done(crtc))
- SDE_ERROR("crtc%d wait for frame done failed;frame_pending%d\n",
- crtc->base.id,
- atomic_read(&sde_crtc->frame_pending));
+ _sde_crtc_flush_event_thread(crtc);
SDE_EVT32(DRMID(crtc), sde_crtc->enabled, sde_crtc->suspend,
sde_crtc->vblank_requested,
@@ -4238,6 +4204,8 @@
sde_crtc->enabled = false;
if (atomic_read(&sde_crtc->frame_pending)) {
+ SDE_ERROR("crtc%d frame_pending%d\n", crtc->base.id,
+ atomic_read(&sde_crtc->frame_pending));
SDE_EVT32(DRMID(crtc), atomic_read(&sde_crtc->frame_pending),
SDE_EVTLOG_FUNC_CASE2);
sde_core_perf_crtc_release_bw(crtc);
@@ -4731,8 +4699,6 @@
for (i = 1; i < SSPP_MAX; i++) {
if (pipe_staged[i]) {
- sde_plane_clear_multirect(pipe_staged[i]);
-
if (is_sde_plane_virtual(pipe_staged[i]->plane)) {
SDE_ERROR(
"r1 only virt plane:%d not supported\n",
@@ -4740,6 +4706,7 @@
rc = -EINVAL;
goto end;
}
+ sde_plane_clear_multirect(pipe_staged[i]);
}
}
@@ -6097,7 +6064,6 @@
mutex_init(&sde_crtc->rp_lock);
INIT_LIST_HEAD(&sde_crtc->rp_head);
- init_completion(&sde_crtc->frame_done_comp);
sde_crtc->enabled = false;
INIT_LIST_HEAD(&sde_crtc->frame_event_list);
diff --git a/drivers/gpu/drm/msm/sde/sde_crtc.h b/drivers/gpu/drm/msm/sde/sde_crtc.h
index c02a81e..99177b1 100644
--- a/drivers/gpu/drm/msm/sde/sde_crtc.h
+++ b/drivers/gpu/drm/msm/sde/sde_crtc.h
@@ -190,7 +190,6 @@
* @frame_events : static allocation of in-flight frame events
* @frame_event_list : available frame event list
* @spin_lock : spin lock for frame event, transaction status, etc...
- * @frame_done_comp : for frame_event_done synchronization
* @event_thread : Pointer to event handler thread
* @event_worker : Event worker queue
* @event_cache : Local cache of event worker structures
@@ -262,7 +261,6 @@
struct sde_crtc_frame_event frame_events[SDE_CRTC_FRAME_EVENT_SIZE];
struct list_head frame_event_list;
spinlock_t spin_lock;
- struct completion frame_done_comp;
/* for handling internal event thread */
struct sde_crtc_event event_cache[SDE_CRTC_MAX_EVENT_COUNT];
diff --git a/drivers/gpu/drm/msm/sde/sde_encoder.c b/drivers/gpu/drm/msm/sde/sde_encoder.c
index b54c152..73864b6 100644
--- a/drivers/gpu/drm/msm/sde/sde_encoder.c
+++ b/drivers/gpu/drm/msm/sde/sde_encoder.c
@@ -1489,12 +1489,13 @@
vsync_cfg.pp_count = sde_enc->num_phys_encs;
vsync_cfg.frame_rate = mode_info.frame_rate;
+ vsync_cfg.vsync_source =
+ sde_enc->cur_master->hw_pp->caps->te_source;
if (is_dummy)
vsync_cfg.vsync_source = SDE_VSYNC_SOURCE_WD_TIMER_1;
else if (disp_info->is_te_using_watchdog_timer)
vsync_cfg.vsync_source = SDE_VSYNC_SOURCE_WD_TIMER_0;
- else
- vsync_cfg.vsync_source = SDE_VSYNC0_SOURCE_GPIO;
+
vsync_cfg.is_dummy = is_dummy;
hw_mdptop->ops.setup_vsync_source(hw_mdptop, &vsync_cfg);
@@ -1887,7 +1888,7 @@
{
struct drm_encoder *drm_enc = NULL;
struct sde_encoder_virt *sde_enc = NULL;
- struct msm_drm_thread *disp_thread = NULL;
+ struct msm_drm_thread *event_thread = NULL;
struct msm_drm_private *priv = NULL;
if (!handle || !handle->handler || !handle->handler->private) {
@@ -1904,7 +1905,7 @@
priv = drm_enc->dev->dev_private;
sde_enc = to_sde_encoder_virt(drm_enc);
if (!sde_enc->crtc || (sde_enc->crtc->index
- >= ARRAY_SIZE(priv->disp_thread))) {
+ >= ARRAY_SIZE(priv->event_thread))) {
SDE_DEBUG_ENC(sde_enc,
"invalid cached CRTC: %d or crtc index: %d\n",
sde_enc->crtc == NULL,
@@ -1914,9 +1915,10 @@
SDE_EVT32_VERBOSE(DRMID(drm_enc));
- disp_thread = &priv->disp_thread[sde_enc->crtc->index];
+ event_thread = &priv->event_thread[sde_enc->crtc->index];
- kthread_queue_work(&disp_thread->worker,
+ /* Queue input event work to event thread */
+ kthread_queue_work(&event_thread->worker,
&sde_enc->input_event_work);
}
@@ -4008,6 +4010,7 @@
}
if (sde_enc->disp_info.intf_type == DRM_MODE_CONNECTOR_DSI &&
+ sde_enc->disp_info.is_primary &&
!_sde_encoder_wakeup_time(drm_enc, &wakeup_time)) {
SDE_EVT32_VERBOSE(ktime_to_ms(wakeup_time));
mod_timer(&sde_enc->vsync_event_timer,
diff --git a/drivers/gpu/drm/msm/sde/sde_hw_catalog.c b/drivers/gpu/drm/msm/sde/sde_hw_catalog.c
index 475f8d0..baec526 100644
--- a/drivers/gpu/drm/msm/sde/sde_hw_catalog.c
+++ b/drivers/gpu/drm/msm/sde/sde_hw_catalog.c
@@ -249,6 +249,7 @@
DITHER_OFF,
DITHER_LEN,
DITHER_VER,
+ TE_SOURCE,
PP_PROP_MAX,
};
@@ -589,6 +590,7 @@
{DITHER_OFF, "qcom,sde-dither-off", false, PROP_TYPE_U32_ARRAY},
{DITHER_LEN, "qcom,sde-dither-size", false, PROP_TYPE_U32},
{DITHER_VER, "qcom,sde-dither-version", false, PROP_TYPE_U32},
+ {TE_SOURCE, "qcom,sde-te-source", false, PROP_TYPE_U32_ARRAY},
};
static struct sde_prop_type dsc_prop[] = {
@@ -2628,6 +2630,10 @@
snprintf(pp->name, SDE_HW_BLK_NAME_LEN, "pingpong_%u",
pp->id - PINGPONG_0);
pp->len = PROP_VALUE_ACCESS(prop_value, PP_LEN, 0);
+ pp->te_source = PROP_VALUE_ACCESS(prop_value, TE_SOURCE, i);
+ if (!prop_exists[TE_SOURCE] ||
+ pp->te_source > SDE_VSYNC_SOURCE_WD_TIMER_0)
+ pp->te_source = SDE_VSYNC0_SOURCE_GPIO;
sblk->te.base = PROP_VALUE_ACCESS(prop_value, TE_OFF, i);
sblk->te.id = SDE_PINGPONG_TE;
diff --git a/drivers/gpu/drm/msm/sde/sde_hw_catalog.h b/drivers/gpu/drm/msm/sde/sde_hw_catalog.h
index 65919e9..52bdc78 100644
--- a/drivers/gpu/drm/msm/sde/sde_hw_catalog.h
+++ b/drivers/gpu/drm/msm/sde/sde_hw_catalog.h
@@ -653,6 +653,7 @@
*/
struct sde_pingpong_cfg {
SDE_HW_BLK_INFO;
+ u32 te_source;
const struct sde_pingpong_sub_blks *sblk;
};
diff --git a/drivers/gpu/drm/msm/sde/sde_plane.c b/drivers/gpu/drm/msm/sde/sde_plane.c
index 2e46599..dc55ad5 100644
--- a/drivers/gpu/drm/msm/sde/sde_plane.c
+++ b/drivers/gpu/drm/msm/sde/sde_plane.c
@@ -3449,6 +3449,25 @@
src_w, src_h);
return -EINVAL;
}
+
+ /*
+ * SSPP fetch , unpack output and QSEED3 input lines need
+ * to match for Y plane
+ */
+ if (i == 0 &&
+ (sde_plane_get_property(pstate, PLANE_PROP_SRC_CONFIG) &
+ BIT(SDE_DRM_DEINTERLACE)) &&
+ ((pstate->scaler3_cfg.src_height[i] != (src_h/2)) ||
+ (pstate->pixel_ext.roi_h[i] != (src_h/2)))) {
+ SDE_ERROR_PLANE(psde,
+ "de-interlace fail roi[%d] %d/%d, src %dx%d, src %dx%d\n",
+ i, pstate->pixel_ext.roi_w[i],
+ pstate->pixel_ext.roi_h[i],
+ pstate->scaler3_cfg.src_width[i],
+ pstate->scaler3_cfg.src_height[i],
+ src_w, src_h);
+ return -EINVAL;
+ }
}
pstate->scaler_check_state = SDE_PLANE_SCLCHECK_SCALER_V2;
diff --git a/drivers/gpu/drm/msm/sde/sde_wb.c b/drivers/gpu/drm/msm/sde/sde_wb.c
index 71c8b63..61588bd9 100644
--- a/drivers/gpu/drm/msm/sde/sde_wb.c
+++ b/drivers/gpu/drm/msm/sde/sde_wb.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2015-2017, The Linux Foundation. All rights reserved.
+ * Copyright (c) 2015-2018, The Linux Foundation. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 and
@@ -816,6 +816,7 @@
.driver = {
.name = "sde_wb",
.of_match_table = dt_match,
+ .suppress_bind_attrs = true,
},
};
diff --git a/drivers/gpu/drm/msm/sde_rsc.c b/drivers/gpu/drm/msm/sde_rsc.c
index 8179b10..721e278 100644
--- a/drivers/gpu/drm/msm/sde_rsc.c
+++ b/drivers/gpu/drm/msm/sde_rsc.c
@@ -579,8 +579,12 @@
msecs_to_jiffies(PRIMARY_VBLANK_WORST_CASE_MS*2));
if (!rc) {
pr_err("Timeout waiting for vsync\n");
- SDE_EVT32(atomic_read(&rsc->rsc_vsync_wait),
+ rc = -ETIMEDOUT;
+ SDE_EVT32(atomic_read(&rsc->rsc_vsync_wait), rc,
SDE_EVTLOG_ERROR);
+ } else {
+ SDE_EVT32(atomic_read(&rsc->rsc_vsync_wait), rc);
+ rc = 0;
}
}
end:
@@ -635,8 +639,12 @@
msecs_to_jiffies(PRIMARY_VBLANK_WORST_CASE_MS*2));
if (!rc) {
pr_err("Timeout waiting for vsync\n");
- SDE_EVT32(atomic_read(&rsc->rsc_vsync_wait),
+ rc = -ETIMEDOUT;
+ SDE_EVT32(atomic_read(&rsc->rsc_vsync_wait), rc,
SDE_EVTLOG_ERROR);
+ } else {
+ SDE_EVT32(atomic_read(&rsc->rsc_vsync_wait), rc);
+ rc = 0;
}
}
@@ -1446,6 +1454,7 @@
.driver = {
.name = "sde_rsc",
.of_match_table = dt_match,
+ .suppress_bind_attrs = true,
},
};
diff --git a/drivers/gpu/msm/adreno.h b/drivers/gpu/msm/adreno.h
index 8e21958..fbf298d 100644
--- a/drivers/gpu/msm/adreno.h
+++ b/drivers/gpu/msm/adreno.h
@@ -1873,8 +1873,11 @@
ret = gpudev->oob_set(adreno_dev, OOB_PERFCNTR_SET_MASK,
OOB_PERFCNTR_CHECK_MASK,
OOB_PERFCNTR_CLEAR_MASK);
- if (ret)
+ if (ret) {
+ adreno_set_gpu_fault(adreno_dev, ADRENO_GMU_FAULT);
+ adreno_dispatcher_schedule(KGSL_DEVICE(adreno_dev));
kgsl_active_count_put(KGSL_DEVICE(adreno_dev));
+ }
}
return ret;
diff --git a/drivers/gpu/msm/adreno_a5xx.c b/drivers/gpu/msm/adreno_a5xx.c
index 2a3ae3e..68a7c2a 100644
--- a/drivers/gpu/msm/adreno_a5xx.c
+++ b/drivers/gpu/msm/adreno_a5xx.c
@@ -2281,6 +2281,7 @@
switch (ADRENO_GPUREV(adreno_dev)) {
case ADRENO_REV_A510:
return 0x00000001; /* Ucode workaround for token end syncs */
+ case ADRENO_REV_A504:
case ADRENO_REV_A505:
case ADRENO_REV_A506:
case ADRENO_REV_A530:
diff --git a/drivers/gpu/msm/adreno_a6xx_preempt.c b/drivers/gpu/msm/adreno_a6xx_preempt.c
index 6c8e664..132fb02 100644
--- a/drivers/gpu/msm/adreno_a6xx_preempt.c
+++ b/drivers/gpu/msm/adreno_a6xx_preempt.c
@@ -49,8 +49,13 @@
OOB_PREEMPTION_SET_MASK,
OOB_PREEMPTION_CHECK_MASK,
OOB_PREEMPTION_CLEAR_MASK);
- if (status)
+ if (status) {
+ adreno_set_gpu_fault(adreno_dev,
+ ADRENO_GMU_FAULT);
+ adreno_dispatcher_schedule(
+ KGSL_DEVICE(adreno_dev));
return;
+ }
}
}
diff --git a/drivers/hwtracing/coresight/coresight-etm3x.c b/drivers/hwtracing/coresight/coresight-etm3x.c
index 3bbcc95..04870ce 100644
--- a/drivers/hwtracing/coresight/coresight-etm3x.c
+++ b/drivers/hwtracing/coresight/coresight-etm3x.c
@@ -712,10 +712,6 @@
CS_UNLOCK(drvdata->base);
- /* check the state of the fuse */
- if (!coresight_authstatus_enabled(drvdata->base))
- goto out;
-
/* First dummy read */
(void)etm_readl(drvdata, ETMPDSR);
/* Provide power to ETM: ETMPDCR[3] == 1 */
@@ -725,6 +721,11 @@
* certain registers might be ignored.
*/
etm_clr_pwrdwn(drvdata);
+
+ /* check the state of the fuse */
+ if (!coresight_authstatus_enabled(drvdata->base))
+ goto out;
+
/*
* Set prog bit. It will be set from reset but this is included to
* ensure it is set
diff --git a/drivers/hwtracing/coresight/coresight-etm4x.c b/drivers/hwtracing/coresight/coresight-etm4x.c
index 5db74f0..95d13a9 100644
--- a/drivers/hwtracing/coresight/coresight-etm4x.c
+++ b/drivers/hwtracing/coresight/coresight-etm4x.c
@@ -27,6 +27,7 @@
#include <linux/cpu.h>
#include <linux/coresight.h>
#include <linux/coresight-pmu.h>
+#include <linux/of.h>
#include <linux/pm_wakeup.h>
#include <linux/amba/bus.h>
#include <linux/seq_file.h>
@@ -167,12 +168,14 @@
writel_relaxed(config->vmid_mask0, drvdata->base + TRCVMIDCCTLR0);
writel_relaxed(config->vmid_mask1, drvdata->base + TRCVMIDCCTLR1);
- /*
- * Request to keep the trace unit powered and also
- * emulation of powerdown
- */
- writel_relaxed(readl_relaxed(drvdata->base + TRCPDCR) | TRCPDCR_PU,
- drvdata->base + TRCPDCR);
+ if (!drvdata->tupwr_disable) {
+ /*
+ * Request to keep the trace unit powered and also
+ * emulation of powerdown
+ */
+ writel_relaxed(readl_relaxed(drvdata->base + TRCPDCR)
+ | TRCPDCR_PU, drvdata->base + TRCPDCR);
+ }
/* Enable the trace unit */
writel_relaxed(1, drvdata->base + TRCPRGCTLR);
@@ -313,10 +316,12 @@
CS_UNLOCK(drvdata->base);
- /* power can be removed from the trace unit now */
- control = readl_relaxed(drvdata->base + TRCPDCR);
- control &= ~TRCPDCR_PU;
- writel_relaxed(control, drvdata->base + TRCPDCR);
+ if (!drvdata->tupwr_disable) {
+ /* power can be removed from the trace unit now */
+ control = readl_relaxed(drvdata->base + TRCPDCR);
+ control &= ~TRCPDCR_PU;
+ writel_relaxed(control, drvdata->base + TRCPDCR);
+ }
control = readl_relaxed(drvdata->base + TRCPRGCTLR);
@@ -1041,6 +1046,9 @@
etmdrvdata[drvdata->cpu] = drvdata;
+ drvdata->tupwr_disable = of_property_read_bool(drvdata->dev->of_node,
+ "qcom,tupwr-disable");
+
dev_info(dev, "CPU%d: %s initialized\n",
drvdata->cpu, (char *)id->data);
diff --git a/drivers/hwtracing/coresight/coresight-etm4x.h b/drivers/hwtracing/coresight/coresight-etm4x.h
index 4e51ecdc..5f34bdc 100644
--- a/drivers/hwtracing/coresight/coresight-etm4x.h
+++ b/drivers/hwtracing/coresight/coresight-etm4x.h
@@ -1,4 +1,4 @@
-/* Copyright (c) 2014-2015, 2017, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2014-2015, 2017-2018, The Linux Foundation. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 and
@@ -345,6 +345,7 @@
* @nooverflow: Indicate if overflow prevention is supported.
* @atbtrig: If the implementation can support ATB triggers
* @lpoverride: If the implementation can support low-power state over.
+ * @tupwr_disable: If disable the support of keeping trace unit powered.
* @config: structure holding configuration parameters.
*/
struct etmv4_drvdata {
@@ -391,6 +392,7 @@
bool nooverflow;
bool atbtrig;
bool lpoverride;
+ bool tupwr_disable;
struct etmv4_config config;
};
diff --git a/drivers/hwtracing/coresight/coresight-tmc-etr.c b/drivers/hwtracing/coresight/coresight-tmc-etr.c
index 9d2ab01..e369ea1 100644
--- a/drivers/hwtracing/coresight/coresight-tmc-etr.c
+++ b/drivers/hwtracing/coresight/coresight-tmc-etr.c
@@ -845,7 +845,6 @@
}
drvdata->enable = true;
- drvdata->sticky_enable = true;
out:
spin_unlock_irqrestore(&drvdata->spinlock, flags);
if (drvdata->out_mode == TMC_ETR_OUT_MODE_MEM)
diff --git a/drivers/hwtracing/coresight/coresight-tmc.c b/drivers/hwtracing/coresight/coresight-tmc.c
index 287f901..8aed31a 100644
--- a/drivers/hwtracing/coresight/coresight-tmc.c
+++ b/drivers/hwtracing/coresight/coresight-tmc.c
@@ -139,7 +139,6 @@
void tmc_enable_hw(struct tmc_drvdata *drvdata)
{
drvdata->enable = true;
- drvdata->sticky_enable = true;
writel_relaxed(TMC_CTL_CAPT_EN, drvdata->base + TMC_CTL);
if (drvdata->force_reg_dump)
__tmc_reg_dump(drvdata);
@@ -155,7 +154,7 @@
{
int ret = 0;
- if (!drvdata->sticky_enable)
+ if (!drvdata->enable)
return -EPERM;
switch (drvdata->config_type) {
diff --git a/drivers/hwtracing/coresight/coresight.c b/drivers/hwtracing/coresight/coresight.c
index 85a16b1..21c74ec 100644
--- a/drivers/hwtracing/coresight/coresight.c
+++ b/drivers/hwtracing/coresight/coresight.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2012, 2017, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2012, 2017-2018, The Linux Foundation. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 and
@@ -181,8 +181,10 @@
if (atomic_inc_return(&csdev->refcnt[refport]) == 1) {
if (link_ops(csdev)->enable) {
ret = link_ops(csdev)->enable(csdev, inport, outport);
- if (ret)
+ if (ret) {
+ atomic_dec(&csdev->refcnt[refport]);
return ret;
+ }
}
}
@@ -263,42 +265,66 @@
}
}
-void coresight_disable_path(struct list_head *path)
+static void coresigh_disable_list_node(struct list_head *path,
+ struct coresight_node *nd)
{
u32 type;
- struct coresight_node *nd;
struct coresight_device *csdev, *parent, *child;
+ csdev = nd->csdev;
+ type = csdev->type;
+
+ /*
+ * ETF devices are tricky... They can be a link or a sink,
+ * depending on how they are configured. If an ETF has been
+ * "activated" it will be configured as a sink, otherwise
+ * go ahead with the link configuration.
+ */
+ if (type == CORESIGHT_DEV_TYPE_LINKSINK)
+ type = (csdev == coresight_get_sink(path)) ?
+ CORESIGHT_DEV_TYPE_SINK :
+ CORESIGHT_DEV_TYPE_LINK;
+
+ switch (type) {
+ case CORESIGHT_DEV_TYPE_SINK:
+ coresight_disable_sink(csdev);
+ break;
+ case CORESIGHT_DEV_TYPE_SOURCE:
+ /* sources are disabled from either sysFS or Perf */
+ break;
+ case CORESIGHT_DEV_TYPE_LINK:
+ parent = list_prev_entry(nd, link)->csdev;
+ child = list_next_entry(nd, link)->csdev;
+ coresight_disable_link(csdev, parent, child);
+ break;
+ default:
+ break;
+ }
+}
+
+/**
+ * During enabling path, if it is failed, then only those enabled
+ * devices need to be disabled. This function is to disable devices
+ * which is enabled before the failed device.
+ *
+ * @path the head of the list
+ * @nd the failed device node
+ */
+static void coresight_disable_previous_devs(struct list_head *path,
+ struct coresight_node *nd)
+{
+
+ list_for_each_entry_continue(nd, path, link) {
+ coresigh_disable_list_node(path, nd);
+ }
+}
+
+void coresight_disable_path(struct list_head *path)
+{
+ struct coresight_node *nd;
+
list_for_each_entry(nd, path, link) {
- csdev = nd->csdev;
- type = csdev->type;
-
- /*
- * ETF devices are tricky... They can be a link or a sink,
- * depending on how they are configured. If an ETF has been
- * "activated" it will be configured as a sink, otherwise
- * go ahead with the link configuration.
- */
- if (type == CORESIGHT_DEV_TYPE_LINKSINK)
- type = (csdev == coresight_get_sink(path)) ?
- CORESIGHT_DEV_TYPE_SINK :
- CORESIGHT_DEV_TYPE_LINK;
-
- switch (type) {
- case CORESIGHT_DEV_TYPE_SINK:
- coresight_disable_sink(csdev);
- break;
- case CORESIGHT_DEV_TYPE_SOURCE:
- /* sources are disabled from either sysFS or Perf */
- break;
- case CORESIGHT_DEV_TYPE_LINK:
- parent = list_prev_entry(nd, link)->csdev;
- child = list_next_entry(nd, link)->csdev;
- coresight_disable_link(csdev, parent, child);
- break;
- default:
- break;
- }
+ coresigh_disable_list_node(path, nd);
}
}
@@ -349,7 +375,7 @@
out:
return ret;
err:
- coresight_disable_path(path);
+ coresight_disable_previous_devs(path, nd);
goto out;
}
diff --git a/drivers/hwtracing/stm/core.c b/drivers/hwtracing/stm/core.c
index 2dd60ee..b8e2992 100644
--- a/drivers/hwtracing/stm/core.c
+++ b/drivers/hwtracing/stm/core.c
@@ -174,8 +174,9 @@
{
struct stp_master *master;
size_t size;
+ unsigned long align = sizeof(unsigned long);
- size = ALIGN(stm->data->sw_nchannels, 8) / 8;
+ size = ALIGN(stm->data->sw_nchannels, align) / align;
size += sizeof(struct stp_master);
master = kzalloc(size, GFP_ATOMIC);
if (!master)
diff --git a/drivers/i2c/busses/i2c-designware-core.c b/drivers/i2c/busses/i2c-designware-core.c
index 340e037..884c1ec 100644
--- a/drivers/i2c/busses/i2c-designware-core.c
+++ b/drivers/i2c/busses/i2c-designware-core.c
@@ -507,7 +507,10 @@
i2c_dw_disable_int(dev);
/* Enable the adapter */
- __i2c_dw_enable_and_wait(dev, true);
+ __i2c_dw_enable(dev, true);
+
+ /* Dummy read to avoid the register getting stuck on Bay Trail */
+ dw_readl(dev, DW_IC_ENABLE_STATUS);
/* Clear and enable interrupts */
dw_readl(dev, DW_IC_CLR_INTR);
diff --git a/drivers/iio/imu/inv_icm20602/inv_icm20602_bsp.c b/drivers/iio/imu/inv_icm20602/inv_icm20602_bsp.c
index 9968e44..03e9670 100644
--- a/drivers/iio/imu/inv_icm20602/inv_icm20602_bsp.c
+++ b/drivers/iio/imu/inv_icm20602/inv_icm20602_bsp.c
@@ -99,7 +99,6 @@
{
int result = MPU_SUCCESS;
char tx_buf[2] = {0x0, 0x0};
- int tmp_size = size;
u8 *tmp_buf = buf;
struct i2c_msg msg[2];
@@ -225,7 +224,7 @@
{
struct struct_icm20602_raw_data raw_data;
- if (type & ACCEL != 0) {
+ if ((type & ACCEL) != 0) {
icm20602_read_reg(st,
reg_set_20602.ACCEL_XOUT_H.address,
&raw_data.ACCEL_XOUT_H);
@@ -257,7 +256,7 @@
raw_data.ACCEL_ZOUT_L);
}
- if (type & GYRO != 0) {
+ if ((type & GYRO) != 0) {
icm20602_read_reg(st,
reg_set_20602.GYRO_XOUT_H.address,
&raw_data.GYRO_XOUT_H);
@@ -327,7 +326,7 @@
return MPU_SUCCESS;
}
-static int icm20602_stop_fifo(struct inv_icm20602_state *st)
+int icm20602_stop_fifo(struct inv_icm20602_state *st)
{
struct icm20602_user_config *config = NULL;
@@ -433,11 +432,7 @@
static int icm20602_set_self_test(struct inv_icm20602_state *st)
{
- uint8_t raw_data[6] = {0, 0, 0, 0, 0, 0};
- uint8_t selfTest[6];
- float factory_trim[6];
int result = 0;
- int ii;
reg_set_20602.SMPLRT_DIV.reg_u.REG.SMPLRT_DIV = 0;
result |= icm20602_write_reg_simple(st, reg_set_20602.SMPLRT_DIV);
@@ -456,7 +451,7 @@
reg_set_20602.ACCEL_CONFIG.reg_u.REG.ACCEL_FS_SEL = ICM20602_ACC_FSR_2G;
result |= icm20602_write_reg_simple(st, reg_set_20602.ACCEL_CONFIG);
- //icm20602_read_ST_code(st);
+ icm20602_read_ST_code(st);
return 0;
}
@@ -466,8 +461,7 @@
{
struct struct_icm20602_real_data *real_data =
kmalloc(sizeof(struct inv_icm20602_state), GFP_ATOMIC);
- struct icm20602_user_config *config = st->config;
- int i, j;
+ int i;
for (i = 0; i < SELFTEST_COUNT; i++) {
icm20602_read_raw(st, real_data, ACCEL);
@@ -514,7 +508,7 @@
{
struct struct_icm20602_real_data *real_data =
kmalloc(sizeof(struct inv_icm20602_state), GFP_ATOMIC);
- int i, j;
+ int i;
for (i = 0; i < SELFTEST_COUNT; i++) {
icm20602_read_raw(st, real_data, GYRO);
@@ -570,7 +564,7 @@
st_otp.Y = (st_otp.Y != 0) ? mpu_st_tb[acc_ST_code.Y - 1] : 0;
st_otp.Z = (st_otp.Z != 0) ? mpu_st_tb[acc_ST_code.Z - 1] : 0;
- if (st_otp.X & st_otp.Y & st_otp.Z == 0)
+ if ((st_otp.X & st_otp.Y & st_otp.Z) == 0)
otp_value_zero = true;
st_shift_cust.X = acc_st->X - acc->X;
@@ -627,11 +621,11 @@
gyro_ST_code.Y = st->config->gyro_self_test.Y;
gyro_ST_code.Z = st->config->gyro_self_test.Z;
- st_otp.X = (st_otp.X != 0) ? mpu_st_tb[gyro_ST_code.X - 1] : 0;
- st_otp.Y = (st_otp.Y != 0) ? mpu_st_tb[gyro_ST_code.Y - 1] : 0;
- st_otp.Z = (st_otp.Z != 0) ? mpu_st_tb[gyro_ST_code.Z - 1] : 0;
+ st_otp.X = (gyro_ST_code.X != 0) ? mpu_st_tb[gyro_ST_code.X - 1] : 0;
+ st_otp.Y = (gyro_ST_code.Y != 0) ? mpu_st_tb[gyro_ST_code.Y - 1] : 0;
+ st_otp.Z = (gyro_ST_code.Z != 0) ? mpu_st_tb[gyro_ST_code.Z - 1] : 0;
- if (st_otp.X & st_otp.Y & st_otp.Z == 0)
+ if ((st_otp.X & st_otp.Y & st_otp.Z) == 0)
otp_value_zero = true;
st_shift_cust.X = gyro_st->X - gyro->X;
@@ -741,8 +735,6 @@
{
struct icm20602_user_config *config = NULL;
int result = MPU_SUCCESS;
- int sample_rate;
- uint8_t fchoice_b;
if (st == NULL)
return -MPU_FAIL;
@@ -928,7 +920,6 @@
{
int result = MPU_SUCCESS;
uint8_t retry = 0, val = 0;
- uint8_t usr_ctrl = 0;
pr_debug("icm20602_detect\n");
/* reset to make sure previous state are not there */
diff --git a/drivers/iio/imu/inv_icm20602/inv_icm20602_core.c b/drivers/iio/imu/inv_icm20602/inv_icm20602_core.c
index 15df447..7dda14e 100644
--- a/drivers/iio/imu/inv_icm20602/inv_icm20602_core.c
+++ b/drivers/iio/imu/inv_icm20602/inv_icm20602_core.c
@@ -29,6 +29,7 @@
#include <linux/of.h>
#include <linux/of_gpio.h>
#include "inv_icm20602_iio.h"
+#include <linux/regulator/consumer.h>
/* Attribute of icm20602 device init show */
static ssize_t inv_icm20602_init_show(struct device *dev,
@@ -89,7 +90,10 @@
static ssize_t inv_gyro_lpf_show(struct device *dev,
struct device_attribute *attr, char *buf)
{
- return 0;
+ struct iio_dev *indio_dev = dev_to_iio_dev(dev);
+ struct inv_icm20602_state *st = iio_priv(indio_dev);
+
+ return snprintf(buf, 4, "%d\n", st->config->gyro_lpf);
}
static ssize_t inv_gyro_lpf_store(struct device *dev,
@@ -105,6 +109,7 @@
if (gyro_lpf > INV_ICM20602_GYRO_LFP_NUM)
return -EINVAL;
config->gyro_lpf = gyro_lpf;
+
return count;
}
static IIO_DEVICE_ATTR(
@@ -118,7 +123,10 @@
static ssize_t inv_gyro_fsr_show(struct device *dev,
struct device_attribute *attr, char *buf)
{
- return 0;
+ struct iio_dev *indio_dev = dev_to_iio_dev(dev);
+ struct inv_icm20602_state *st = iio_priv(indio_dev);
+
+ return snprintf(buf, 4, "%d\n", st->config->gyro_fsr);
}
static ssize_t inv_gyro_fsr_store(struct device *dev,
@@ -145,30 +153,37 @@
inv_gyro_fsr_store,
0);
-/* Attribute of gyro_self_test */
-static ssize_t inv_gyro_self_test_show(struct device *dev,
+/* Attribute of self_test */
+static ssize_t inv_self_test_show(struct device *dev,
struct device_attribute *attr, char *buf)
{
return 0;
}
-static ssize_t inv_gyro_self_test_store(struct device *dev,
+static ssize_t inv_self_test_store(struct device *dev,
struct device_attribute *attr, const char *buf, size_t count)
{
- return 0;
+ struct iio_dev *indio_dev = dev_to_iio_dev(dev);
+ struct inv_icm20602_state *st = iio_priv(indio_dev);
+
+ icm20602_self_test(st);
+ return count;
}
static IIO_DEVICE_ATTR(
- inv_icm20602_gyro_self_test,
+ inv_icm20602_self_test,
0644,
- inv_gyro_self_test_show,
- inv_gyro_self_test_store,
+ inv_self_test_show,
+ inv_self_test_store,
0);
/* Attribute of gyro fsr base on enum inv_icm20602_acc_fsr_e */
static ssize_t inv_gyro_acc_fsr_show(struct device *dev,
struct device_attribute *attr, char *buf)
{
- return 0;
+ struct iio_dev *indio_dev = dev_to_iio_dev(dev);
+ struct inv_icm20602_state *st = iio_priv(indio_dev);
+
+ return snprintf(buf, 4, "%d\n", st->config->acc_fsr);
}
static ssize_t inv_gyro_acc_fsr_store(struct device *dev,
@@ -198,7 +213,10 @@
static ssize_t inv_gyro_acc_lpf_show(struct device *dev,
struct device_attribute *attr, char *buf)
{
- return 0;
+ struct iio_dev *indio_dev = dev_to_iio_dev(dev);
+ struct inv_icm20602_state *st = iio_priv(indio_dev);
+
+ return snprintf(buf, 4, "%d\n", st->config->acc_lpf);
}
static ssize_t inv_gyro_acc_lpf_store(struct device *dev,
@@ -224,30 +242,14 @@
inv_gyro_acc_lpf_store,
0);
-/* Attribute of acc_self_test */
-static ssize_t inv_acc_self_test_show(struct device *dev,
- struct device_attribute *attr, char *buf)
-{
- return 0;
-}
-
-static ssize_t inv_acc_self_test_store(struct device *dev,
- struct device_attribute *attr, const char *buf, size_t count)
-{
- return 0;
-}
-static IIO_DEVICE_ATTR(
- inv_icm20602_acc_self_test,
- 0644,
- inv_acc_self_test_show,
- inv_acc_self_test_store,
- 0);
-
/* Attribute of user_fps_in_ms */
static ssize_t inv_user_fps_in_ms_show(struct device *dev,
struct device_attribute *attr, char *buf)
{
- return 0;
+ struct iio_dev *indio_dev = dev_to_iio_dev(dev);
+ struct inv_icm20602_state *st = iio_priv(indio_dev);
+
+ return snprintf(buf, 4, "%d\n", st->config->user_fps_in_ms);
}
static ssize_t inv_user_fps_in_ms_store(struct device *dev,
@@ -277,13 +279,27 @@
static ssize_t inv_sampling_frequency_show(struct device *dev,
struct device_attribute *attr, char *buf)
{
- return 0;
+ struct iio_dev *indio_dev = dev_to_iio_dev(dev);
+ struct inv_icm20602_state *st = iio_priv(indio_dev);
+
+ return snprintf(buf, 4, "%d\n", st->config->gyro_accel_sample_rate);
}
static ssize_t inv_sampling_frequency_store(struct device *dev,
struct device_attribute *attr, const char *buf, size_t count)
{
- return 0;
+ struct iio_dev *indio_dev = dev_to_iio_dev(dev);
+ struct inv_icm20602_state *st = iio_priv(indio_dev);
+ struct icm20602_user_config *config = st->config;
+ int gyro_accel_sample_rate;
+
+ if (kstrtoint(buf, 10, &gyro_accel_sample_rate))
+ return -EINVAL;
+ if (gyro_accel_sample_rate < 10)
+ return -EINVAL;
+
+ config->gyro_accel_sample_rate = gyro_accel_sample_rate;
+ return count;
}
static IIO_DEV_ATTR_SAMP_FREQ(
0644,
@@ -293,11 +309,11 @@
static struct attribute *inv_icm20602_attributes[] = {
&iio_dev_attr_inv_icm20602_init.dev_attr.attr,
- &iio_dev_attr_inv_icm20602_gyro_self_test.dev_attr.attr,
&iio_dev_attr_inv_icm20602_gyro_fsr.dev_attr.attr,
&iio_dev_attr_inv_icm20602_gyro_lpf.dev_attr.attr,
- &iio_dev_attr_inv_icm20602_acc_self_test.dev_attr.attr,
+ &iio_dev_attr_inv_icm20602_self_test.dev_attr.attr,
+
&iio_dev_attr_inv_icm20602_acc_fsr.dev_attr.attr,
&iio_dev_attr_inv_icm20602_acc_lpf.dev_attr.attr,
@@ -363,6 +379,44 @@
.validate_trigger = inv_icm20602_validate_trigger,
};
+static int icm20602_ldo_work(struct inv_icm20602_state *st, bool enable)
+{
+ int ret = 0;
+
+ if (enable) {
+ ret = regulator_set_voltage(st->reg_ldo,
+ ICM20602_LDO_VTG_MIN_UV, ICM20602_LDO_VTG_MAX_UV);
+ if (ret)
+ pr_err("Failed to request LDO voltage.\n");
+
+ ret = regulator_enable(st->reg_ldo);
+ if (ret)
+ pr_err("Failed to enable LDO %d\n", ret);
+ } else {
+ ret = regulator_disable(st->reg_ldo);
+ if (ret)
+ pr_err("Failed to disable LDO %d\n", ret);
+ regulator_set_load(st->reg_ldo, 0);
+ }
+
+ return MPU_SUCCESS;
+}
+
+static int icm20602_init_regulators(struct inv_icm20602_state *st)
+{
+ struct regulator *reg;
+
+ reg = regulator_get(&st->client->dev, "vdd-ldo");
+ if (IS_ERR_OR_NULL(reg)) {
+ pr_err("Unable to get regulator for LDO\n");
+ return -MPU_FAIL;
+ }
+
+ st->reg_ldo = reg;
+
+ return MPU_SUCCESS;
+}
+
static int of_populate_icm20602_dt(struct inv_icm20602_state *st)
{
int result = MPU_SUCCESS;
@@ -450,6 +504,8 @@
result);
goto out_remove_trigger;
}
+ icm20602_init_regulators(st);
+ icm20602_ldo_work(st, true);
result = inv_icm20602_probe_trigger(indio_dev);
if (result) {
@@ -471,7 +527,6 @@
inv_icm20602_remove_trigger(st);
out_unreg_ring:
iio_triggered_buffer_cleanup(indio_dev);
-out_free:
iio_device_free(indio_dev);
gpio_free(st->gpio);
@@ -494,11 +549,24 @@
static int inv_icm20602_suspend(struct device *dev)
{
+ struct iio_dev *indio_dev = dev_to_iio_dev(dev);
+ struct inv_icm20602_state *st = iio_priv(indio_dev);
+
+ icm20602_stop_fifo(st);
+ icm20602_ldo_work(st, false);
return 0;
}
static int inv_icm20602_resume(struct device *dev)
{
+ struct iio_dev *indio_dev = dev_to_iio_dev(dev);
+ struct inv_icm20602_state *st = iio_priv(indio_dev);
+
+ icm20602_ldo_work(st, true);
+ icm20602_detect(st);
+ icm20602_init_device(st);
+ icm20602_start_fifo(st);
+
return 0;
}
diff --git a/drivers/iio/imu/inv_icm20602/inv_icm20602_iio.h b/drivers/iio/imu/inv_icm20602/inv_icm20602_iio.h
index 9ea5ae5..b369ae4 100644
--- a/drivers/iio/imu/inv_icm20602/inv_icm20602_iio.h
+++ b/drivers/iio/imu/inv_icm20602/inv_icm20602_iio.h
@@ -41,6 +41,9 @@
#define INV20602_SMD_IRQ_TRIGGER 1
#endif
+#define ICM20602_LDO_VTG_MIN_UV 3300000
+#define ICM20602_LDO_VTG_MAX_UV 3300000
+
#define INV_ICM20602_TIME_STAMP_TOR 5
#define ICM20602_PACKAGE_SIZE 14
@@ -217,6 +220,7 @@
struct struct_icm20602_data *data_push;
enum inv_devices chip_type;
int gpio;
+ struct regulator *reg_ldo;
DECLARE_KFIFO(timestamps, long long, TIMESTAMP_FIFO_SIZE);
};
@@ -281,4 +285,6 @@
int icm20602_read_fifo(struct inv_icm20602_state *st,
void *buf, const int size);
int icm20602_start_fifo(struct inv_icm20602_state *st);
+int icm20602_stop_fifo(struct inv_icm20602_state *st);
+bool icm20602_self_test(struct inv_icm20602_state *st);
#endif
diff --git a/drivers/iio/imu/inv_icm20602/inv_icm20602_ring.c b/drivers/iio/imu/inv_icm20602/inv_icm20602_ring.c
index de02656..081bec9 100644
--- a/drivers/iio/imu/inv_icm20602/inv_icm20602_ring.c
+++ b/drivers/iio/imu/inv_icm20602/inv_icm20602_ring.c
@@ -67,9 +67,8 @@
struct icm20602_user_config *config = st->config;
int package_count;
char *buf = st->buf;
- struct struct_icm20602_data *data_push = st->data_push;
s64 timestamp;
- u8 int_status, int_wm_status;
+ u8 int_status;
u16 fifo_count;
int i;
@@ -81,6 +80,7 @@
if (int_status & BIT_FIFO_OFLOW_INT) {
icm20602_fifo_count(st, &fifo_count);
pr_debug("fifo_count = %d\n", fifo_count);
+ inv_clear_kfifo(st);
icm20602_reset_fifo(st);
goto end_session;
}
@@ -105,14 +105,6 @@
mutex_unlock(&indio_dev->mlock);
iio_trigger_notify_done(indio_dev->trig);
return MPU_SUCCESS;
-
-flush_fifo:
- /* Flush HW and SW FIFOs. */
- inv_clear_kfifo(st);
- icm20602_reset_fifo(st);
- mutex_unlock(&indio_dev->mlock);
- iio_trigger_notify_done(indio_dev->trig);
- return MPU_SUCCESS;
}
/*
diff --git a/drivers/infiniband/hw/hfi1/debugfs.c b/drivers/infiniband/hw/hfi1/debugfs.c
index 632ba21..0022660 100644
--- a/drivers/infiniband/hw/hfi1/debugfs.c
+++ b/drivers/infiniband/hw/hfi1/debugfs.c
@@ -67,13 +67,13 @@
loff_t *ppos)
{
struct dentry *d = file->f_path.dentry;
- int srcu_idx;
ssize_t r;
- r = debugfs_use_file_start(d, &srcu_idx);
- if (likely(!r))
- r = seq_read(file, buf, size, ppos);
- debugfs_use_file_finish(srcu_idx);
+ r = debugfs_file_get(d);
+ if (unlikely(r))
+ return r;
+ r = seq_read(file, buf, size, ppos);
+ debugfs_file_put(d);
return r;
}
@@ -83,13 +83,13 @@
int whence)
{
struct dentry *d = file->f_path.dentry;
- int srcu_idx;
loff_t r;
- r = debugfs_use_file_start(d, &srcu_idx);
- if (likely(!r))
- r = seq_lseek(file, offset, whence);
- debugfs_use_file_finish(srcu_idx);
+ r = debugfs_file_get(d);
+ if (unlikely(r))
+ return r;
+ r = seq_lseek(file, offset, whence);
+ debugfs_file_put(d);
return r;
}
diff --git a/drivers/input/misc/vl53l0x/src/vl53l0x_api_calibration.c b/drivers/input/misc/vl53l0x/src/vl53l0x_api_calibration.c
index 08b5ce2..3905bd2 100644
--- a/drivers/input/misc/vl53l0x/src/vl53l0x_api_calibration.c
+++ b/drivers/input/misc/vl53l0x/src/vl53l0x_api_calibration.c
@@ -506,7 +506,7 @@
*pIsAperture = 1;
if ((byteIndex < 2) && (bitIndex < 4))
*pIsAperture = 0;
- spadTypeIdentified = 1;
+ spadTypeIdentified = 1;
}
}
tempByte >>= 1;
diff --git a/drivers/input/misc/vl53l0x/src/vl53l0x_api_core.c b/drivers/input/misc/vl53l0x/src/vl53l0x_api_core.c
index ceb3585..6824c02 100644
--- a/drivers/input/misc/vl53l0x/src/vl53l0x_api_core.c
+++ b/drivers/input/misc/vl53l0x/src/vl53l0x_api_core.c
@@ -182,7 +182,7 @@
Status = VL_RdByte(Dev, 0x83, &strobe);
if ((strobe != 0x00) || Status != VL_ERROR_NONE)
break;
- LoopNb = LoopNb + 1;
+ LoopNb = LoopNb + 1;
} while (LoopNb < VL_DEFAULT_MAX_LOOP);
if (LoopNb >= VL_DEFAULT_MAX_LOOP)
diff --git a/drivers/input/misc/vl53l0x/stmvl53l0x_module.c b/drivers/input/misc/vl53l0x/stmvl53l0x_module.c
index 78ca637..99cbc11 100644
--- a/drivers/input/misc/vl53l0x/stmvl53l0x_module.c
+++ b/drivers/input/misc/vl53l0x/stmvl53l0x_module.c
@@ -777,18 +777,18 @@
size_t count)
{
struct vl_data *data = dev_get_drvdata(dev);
-
+ int ret;
unsigned int val;
- kstrtoint(buf, 10, &val);
+ ret = kstrtoint(buf, 10, &val);
if ((val != 0) && (val != 1)) {
- err("store unvalid value=%ld\n", val);
+ err("store unvalid value=%d\n", val);
return count;
}
mutex_lock(&data->work_mutex);
dbg("Enter, enable_ps_sensor flag:%d\n",
data->enable_ps_sensor);
- dbg("enable ps senosr ( %ld)\n", val);
+ dbg("enable ps senosr ( %d)\n", val);
if (val == 1) {
/* turn on tof sensor */
@@ -831,10 +831,11 @@
{
struct vl_data *data = dev_get_drvdata(dev);
int on;
+ int ret;
- kstrtoint(buf, 10, &on);
+ ret = kstrtoint(buf, 10, &on);
if ((on != 0) && (on != 1)) {
- err("set debug=%ld\n", on);
+ err("set debug=%d\n", on);
return count;
}
data->enableDebug = on;
@@ -862,10 +863,11 @@
{
struct vl_data *data = dev_get_drvdata(dev);
int delay_ms;
+ int ret;
- kstrtoint(buf, 10, &delay_ms);
+ ret = kstrtoint(buf, 10, &delay_ms);
if (delay_ms == 0) {
- err("set delay_ms=%ld\n", delay_ms);
+ err("set delay_ms=%d\n", delay_ms);
return count;
}
mutex_lock(&data->work_mutex);
@@ -895,10 +897,11 @@
{
struct vl_data *data = dev_get_drvdata(dev);
int timingBudget;
+ int ret;
- kstrtoint(buf, 10, &timingBudget);
+ ret = kstrtoint(buf, 10, &timingBudget);
if (timingBudget == 0) {
- err("set timingBudget=%ld\n", timingBudget);
+ err("set timingBudget=%d\n", timingBudget);
return count;
}
mutex_lock(&data->work_mutex);
@@ -929,10 +932,11 @@
{
struct vl_data *data = dev_get_drvdata(dev);
int useLongRange;
+ int ret;
- kstrtoint(buf, 10, &useLongRange);
+ ret = kstrtoint(buf, 10, &useLongRange);
if ((useLongRange != 0) && (useLongRange != 1)) {
- err("set useLongRange=%ld\n", useLongRange);
+ err("set useLongRange=%d\n", useLongRange);
return count;
}
@@ -960,7 +964,6 @@
struct VL_RangingMeasurementData_t Measure;
papi_func_tbl->PerformSingleRangingMeasurement(data, &Measure);
- dbg("Measure = %d\n", Measure.RangeMilliMeter);
return snprintf(buf, 4, "%d\n", Measure.RangeMilliMeter);
}
@@ -972,11 +975,7 @@
static ssize_t stmvl53l0x_show_xtalk(struct device *dev,
struct device_attribute *attr, char *buf)
{
- struct vl_data *data = dev_get_drvdata(dev);
- struct VL_RangingMeasurementData_t Measure;
-
- dbg("Measure = %d\n", Measure.RangeMilliMeter);
- return snprintf(buf, 4, "%d\n", Measure.RangeMilliMeter);
+ return 0;
}
static ssize_t stmvl53l0x_set_xtalk(struct device *dev,
@@ -985,8 +984,9 @@
{
struct vl_data *data = dev_get_drvdata(dev);
unsigned int targetDistance;
+ int ret;
- kstrtoint(buf, 10, &targetDistance);
+ ret = kstrtoint(buf, 10, &targetDistance);
data->xtalkCalDistance = targetDistance;
stmvl53l0x_start(data, 3, XTALKCALIB_MODE);
return count;
@@ -1004,7 +1004,6 @@
struct VL_RangingMeasurementData_t Measure;
papi_func_tbl->PerformSingleRangingMeasurement(data, &Measure);
- dbg("Measure = %d\n", Measure.RangeMilliMeter);
return snprintf(buf, 4, "%d\n", Measure.RangeMilliMeter);
}
@@ -1014,8 +1013,9 @@
{
struct vl_data *data = dev_get_drvdata(dev);
unsigned int targetDistance;
+ int ret;
- kstrtoint(buf, 10, &targetDistance);
+ ret = kstrtoint(buf, 10, &targetDistance);
data->offsetCalDistance = targetDistance;
stmvl53l0x_start(data, 3, OFFSETCALIB_MODE);
return count;
@@ -1067,9 +1067,9 @@
papi_func_tbl->GetOffsetCalibrationDataMicroMeter(data,
&offset_calibration_data);
- dbg("GetOffsetCalibrationDataMicroMeter = %ld\n",
+ dbg("GetOffsetCalibrationDataMicroMeter = %d\n",
offset_calibration_data);
- return snprintf(buf, 2, "%ld\n",
+ return snprintf(buf, 2, "%d\n",
offset_calibration_data);
}
@@ -1079,8 +1079,9 @@
{
struct vl_data *data = dev_get_drvdata(dev);
int32_t offset_calibration_data;
+ int ret;
- kstrtoint(buf, 10, &offset_calibration_data);
+ ret = kstrtoint(buf, 10, &offset_calibration_data);
papi_func_tbl->SetOffsetCalibrationDataMicroMeter(data,
offset_calibration_data);
return count;
@@ -1100,9 +1101,9 @@
papi_func_tbl->GetXTalkCompensationRateMegaCps(data,
&xtalk_compensation_rate);
- dbg("xtalk_compensation_rate = %ld\n",
+ dbg("xtalk_compensation_rate = %d\n",
xtalk_compensation_rate);
- return snprintf(buf, 2, "%ld\n", xtalk_compensation_rate);
+ return snprintf(buf, 2, "%d\n", xtalk_compensation_rate);
}
@@ -1112,8 +1113,9 @@
{
struct vl_data *data = dev_get_drvdata(dev);
unsigned int xtalk_compensation_rate;
+ int ret;
- kstrtoint(buf, 10, &xtalk_compensation_rate);
+ ret = kstrtoint(buf, 10, &xtalk_compensation_rate);
papi_func_tbl->SetXTalkCompensationRateMegaCps(data,
xtalk_compensation_rate);
return count;
@@ -1689,7 +1691,7 @@
vl53l0x_dev,
&ref_spad_count,
&is_aperture_spads);
- dbg("SPAD calibration:%lu,%u\n", ref_spad_count,
+ dbg("SPAD calibration:%d,%d\n", ref_spad_count,
(unsigned int)is_aperture_spads);
return rc;
} else if (mode == REFCALIB_MODE) {
diff --git a/drivers/leds/led-class.c b/drivers/leds/led-class.c
index 8cb3265..2522a3d 100644
--- a/drivers/leds/led-class.c
+++ b/drivers/leds/led-class.c
@@ -56,6 +56,7 @@
if (state == LED_OFF && !(led_cdev->flags & LED_KEEP_TRIGGER))
led_trigger_remove(led_cdev);
led_set_brightness(led_cdev, state);
+ led_cdev->usr_brightness_req = state;
ret = size;
unlock:
@@ -71,7 +72,24 @@
return sprintf(buf, "%u\n", led_cdev->max_brightness);
}
-static DEVICE_ATTR_RO(max_brightness);
+
+static ssize_t max_brightness_store(struct device *dev,
+ struct device_attribute *attr, const char *buf, size_t size)
+{
+ struct led_classdev *led_cdev = dev_get_drvdata(dev);
+ unsigned long state;
+ ssize_t ret = -EINVAL;
+
+ ret = kstrtoul(buf, 10, &state);
+ if (ret)
+ return ret;
+
+ led_cdev->max_brightness = state;
+ led_set_brightness(led_cdev, led_cdev->usr_brightness_req);
+
+ return size;
+}
+static DEVICE_ATTR_RW(max_brightness);
#ifdef CONFIG_LEDS_TRIGGERS
static DEVICE_ATTR(trigger, 0644, led_trigger_show, led_trigger_store);
diff --git a/drivers/leds/leds-qpnp-flash-v2.c b/drivers/leds/leds-qpnp-flash-v2.c
index 759d853..d773ec5 100644
--- a/drivers/leds/leds-qpnp-flash-v2.c
+++ b/drivers/leds/leds-qpnp-flash-v2.c
@@ -123,6 +123,7 @@
#define FLASH_LED_REG_MULTI_STROBE_CTRL(base) (base + 0x71)
#define LED3_FLASH_ONCE_ONLY_BIT BIT(1)
+#define LED1N2_FLASH_ONCE_ONLY_BIT BIT(0)
#define FLASH_LED_REG_LPG_INPUT_CTRL(base) (base + 0x72)
#define LPG_INPUT_SEL_BIT BIT(0)
@@ -425,7 +426,7 @@
static int qpnp_flash_led_init_settings(struct qpnp_flash_led *led)
{
int rc, i, addr_offset;
- u8 val = 0, mask;
+ u8 val = 0, mask, strobe_mask = 0, strobe_ctrl;
for (i = 0; i < led->num_fnodes; i++) {
addr_offset = led->fnode[i].id;
@@ -436,6 +437,51 @@
return rc;
val |= 0x1 << led->fnode[i].id;
+
+ if (led->fnode[i].strobe_sel == HW_STROBE) {
+ if (led->fnode[i].id == LED3)
+ strobe_mask |= LED3_FLASH_ONCE_ONLY_BIT;
+ else
+ strobe_mask |= LED1N2_FLASH_ONCE_ONLY_BIT;
+ }
+
+ if (led->fnode[i].id == LED3 &&
+ led->fnode[i].strobe_sel == LPG_STROBE)
+ strobe_mask |= LED3_FLASH_ONCE_ONLY_BIT;
+ /*
+ * As per the hardware recommendation, to use LED2/LED3 in HW
+ * strobe mode, LED1 should be set to HW strobe mode as well.
+ */
+ if (led->fnode[i].strobe_sel == HW_STROBE &&
+ (led->fnode[i].id == LED2 || led->fnode[i].id == LED3)) {
+ mask = FLASH_HW_STROBE_MASK;
+ addr_offset = led->fnode[LED1].id;
+ /*
+ * HW_STROBE: enable, TRIGGER: level,
+ * POLARITY: active high
+ */
+ strobe_ctrl = BIT(2) | BIT(0);
+ rc = qpnp_flash_led_masked_write(led,
+ FLASH_LED_REG_STROBE_CTRL(
+ led->base + addr_offset),
+ mask, strobe_ctrl);
+ if (rc < 0)
+ return rc;
+ }
+ }
+
+ rc = qpnp_flash_led_masked_write(led,
+ FLASH_LED_REG_MULTI_STROBE_CTRL(led->base),
+ strobe_mask, 0);
+ if (rc < 0)
+ return rc;
+
+ if (led->fnode[LED3].strobe_sel == LPG_STROBE) {
+ rc = qpnp_flash_led_masked_write(led,
+ FLASH_LED_REG_LPG_INPUT_CTRL(led->base),
+ LPG_INPUT_SEL_BIT, LPG_INPUT_SEL_BIT);
+ if (rc < 0)
+ return rc;
}
rc = qpnp_flash_led_write(led,
@@ -629,19 +675,6 @@
return rc;
}
- if (led->fnode[LED3].strobe_sel == LPG_STROBE) {
- rc = qpnp_flash_led_masked_write(led,
- FLASH_LED_REG_MULTI_STROBE_CTRL(led->base),
- LED3_FLASH_ONCE_ONLY_BIT, 0);
- if (rc < 0)
- return rc;
-
- rc = qpnp_flash_led_masked_write(led,
- FLASH_LED_REG_LPG_INPUT_CTRL(led->base),
- LPG_INPUT_SEL_BIT, LPG_INPUT_SEL_BIT);
- if (rc < 0)
- return rc;
- }
return 0;
}
diff --git a/drivers/leds/leds-qpnp-vibrator-ldo.c b/drivers/leds/leds-qpnp-vibrator-ldo.c
index 6a14324..dd19dd1 100644
--- a/drivers/leds/leds-qpnp-vibrator-ldo.c
+++ b/drivers/leds/leds-qpnp-vibrator-ldo.c
@@ -65,9 +65,29 @@
bool disable_overdrive;
};
-static int qpnp_vib_ldo_set_voltage(struct vib_ldo_chip *chip, int new_uV)
+static inline int qpnp_vib_ldo_poll_status(struct vib_ldo_chip *chip)
{
unsigned int val;
+ int ret;
+
+ ret = regmap_read_poll_timeout(chip->regmap,
+ chip->base + QPNP_VIB_LDO_REG_STATUS1, val,
+ val & QPNP_VIB_LDO_VREG_READY, 100, 1000);
+ if (ret < 0) {
+ pr_err("Vibrator LDO vreg_ready timeout, status=0x%02x, ret=%d\n",
+ val, ret);
+
+ /* Keep VIB_LDO disabled */
+ regmap_update_bits(chip->regmap,
+ chip->base + QPNP_VIB_LDO_REG_EN_CTL,
+ QPNP_VIB_LDO_EN, 0);
+ }
+
+ return ret;
+}
+
+static int qpnp_vib_ldo_set_voltage(struct vib_ldo_chip *chip, int new_uV)
+{
u32 vlevel;
u8 reg[2];
int ret;
@@ -86,13 +106,9 @@
}
if (chip->vib_enabled) {
- ret = regmap_read_poll_timeout(chip->regmap,
- chip->base + QPNP_VIB_LDO_REG_STATUS1,
- val, val & QPNP_VIB_LDO_VREG_READY,
- 100, 1000);
+ ret = qpnp_vib_ldo_poll_status(chip);
if (ret < 0) {
- pr_err("Vibrator LDO vreg_ready timeout, status=0x%02x, ret=%d\n",
- val, ret);
+ pr_err("Vibrator LDO status polling timedout\n");
return ret;
}
}
@@ -103,7 +119,6 @@
static inline int qpnp_vib_ldo_enable(struct vib_ldo_chip *chip, bool enable)
{
- unsigned int val;
int ret;
if (chip->vib_enabled == enable)
@@ -120,13 +135,9 @@
}
if (enable) {
- ret = regmap_read_poll_timeout(chip->regmap,
- chip->base + QPNP_VIB_LDO_REG_STATUS1,
- val, val & QPNP_VIB_LDO_VREG_READY,
- 100, 1000);
+ ret = qpnp_vib_ldo_poll_status(chip);
if (ret < 0) {
- pr_err("Vibrator LDO vreg_ready timeout, status=0x%02x, ret=%d\n",
- val, ret);
+ pr_err("Vibrator LDO status polling timedout\n");
return ret;
}
}
@@ -430,6 +441,7 @@
}
hrtimer_cancel(&chip->stop_timer);
cancel_work_sync(&chip->vib_work);
+ qpnp_vib_ldo_enable(chip, false);
mutex_unlock(&chip->lock);
return 0;
diff --git a/drivers/mailbox/qcom-rpmh-mailbox.c b/drivers/mailbox/qcom-rpmh-mailbox.c
index 00ebed9..c81fe52 100644
--- a/drivers/mailbox/qcom-rpmh-mailbox.c
+++ b/drivers/mailbox/qcom-rpmh-mailbox.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2016-2017, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2016-2018, The Linux Foundation. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 and
@@ -129,6 +129,7 @@
unsigned long addr;
void __iomem *base; /* start address of the RSC's registers */
void __iomem *reg_base; /* start address for DRV specific register */
+ int irq;
int drv_id;
struct platform_device *pdev;
struct tcs_mbox tcs[TCS_TYPE_NR];
@@ -878,6 +879,8 @@
{
int i;
unsigned long long curr = arch_counter_get_cntvct();
+ struct irq_data *rsc_irq_data = irq_get_irq_data(drv->irq);
+ bool irq_sts;
for (i = 0; i < drv->num_tcs; i++) {
if (!atomic_read(&drv->tcs_in_use[i]))
@@ -891,6 +894,20 @@
print_tcs_regs(drv, i);
print_response(drv, i);
}
+
+ if (rsc_irq_data) {
+ irq_get_irqchip_state(drv->irq, IRQCHIP_STATE_PENDING,
+ &irq_sts);
+ pr_warn("HW IRQ %lu is %s at GIC\n", rsc_irq_data->hwirq,
+ irq_sts ? "PENDING" : "NOT PENDING");
+ }
+
+ if (test_bit(TASKLET_STATE_SCHED, &drv->tasklet.state))
+ pr_warn("Tasklet is scheduled for execution\n");
+ else if (test_bit(TASKLET_STATE_RUN, &drv->tasklet.state))
+ pr_warn("Tasklet is running\n");
+ else
+ pr_warn("Tasklet is not active\n");
}
static void chan_debug(struct mbox_chan *chan)
@@ -980,7 +997,8 @@
/* If we were just busy waiting for TCS, dump the state and return */
if (ret == -EBUSY) {
- pr_info_ratelimited("TCS Busy, retrying RPMH message send\n");
+ dev_err_ratelimited(chan->cl->dev,
+ "TCS Busy, retrying RPMH message send\n");
ret = -EAGAIN;
}
@@ -1261,6 +1279,8 @@
if (ret)
return ret;
+ drv->irq = irq;
+
/* Enable interrupts for AMC TCS */
write_tcs_reg(drv->reg_base, RSC_DRV_IRQ_ENABLE, 0, 0,
drv->tcs[ACTIVE_TCS].tcs_mask);
diff --git a/drivers/md/dm-bufio.c b/drivers/md/dm-bufio.c
index 3ec647e..809a4df 100644
--- a/drivers/md/dm-bufio.c
+++ b/drivers/md/dm-bufio.c
@@ -827,7 +827,8 @@
* dm-bufio is resistant to allocation failures (it just keeps
* one buffer reserved in cases all the allocations fail).
* So set flags to not try too hard:
- * GFP_NOIO: don't recurse into the I/O layer
+ * GFP_NOWAIT: don't wait; if we need to sleep we'll release our
+ * mutex and wait ourselves.
* __GFP_NORETRY: don't retry and rather return failure
* __GFP_NOMEMALLOC: don't use emergency reserves
* __GFP_NOWARN: don't print a warning in case of failure
@@ -837,7 +838,7 @@
*/
while (1) {
if (dm_bufio_cache_size_latch != 1) {
- b = alloc_buffer(c, GFP_NOIO | __GFP_NORETRY | __GFP_NOMEMALLOC | __GFP_NOWARN);
+ b = alloc_buffer(c, GFP_NOWAIT | __GFP_NORETRY | __GFP_NOMEMALLOC | __GFP_NOWARN);
if (b)
return b;
}
diff --git a/drivers/media/pci/cx23885/cx23885-cards.c b/drivers/media/pci/cx23885/cx23885-cards.c
index 99ba8d6..427ece1 100644
--- a/drivers/media/pci/cx23885/cx23885-cards.c
+++ b/drivers/media/pci/cx23885/cx23885-cards.c
@@ -2282,6 +2282,10 @@
&dev->i2c_bus[2].i2c_adap,
"cx25840", 0x88 >> 1, NULL);
if (dev->sd_cx25840) {
+ /* set host data for clk_freq configuration */
+ v4l2_set_subdev_hostdata(dev->sd_cx25840,
+ &dev->clk_freq);
+
dev->sd_cx25840->grp_id = CX23885_HW_AV_CORE;
v4l2_subdev_call(dev->sd_cx25840, core, load_fw);
}
diff --git a/drivers/media/pci/cx23885/cx23885-core.c b/drivers/media/pci/cx23885/cx23885-core.c
index c86b109..dcbb3a2 100644
--- a/drivers/media/pci/cx23885/cx23885-core.c
+++ b/drivers/media/pci/cx23885/cx23885-core.c
@@ -872,6 +872,16 @@
if (cx23885_boards[dev->board].clk_freq > 0)
dev->clk_freq = cx23885_boards[dev->board].clk_freq;
+ if (dev->board == CX23885_BOARD_HAUPPAUGE_IMPACTVCBE &&
+ dev->pci->subsystem_device == 0x7137) {
+ /* Hauppauge ImpactVCBe device ID 0x7137 is populated
+ * with an 888, and a 25Mhz crystal, instead of the
+ * usual third overtone 50Mhz. The default clock rate must
+ * be overridden so the cx25840 is properly configured
+ */
+ dev->clk_freq = 25000000;
+ }
+
dev->pci_bus = dev->pci->bus->number;
dev->pci_slot = PCI_SLOT(dev->pci->devfn);
cx23885_irq_add(dev, 0x001f00);
diff --git a/drivers/media/pci/cx25821/cx25821-core.c b/drivers/media/pci/cx25821/cx25821-core.c
index 9a5f912..0d4cacb 100644
--- a/drivers/media/pci/cx25821/cx25821-core.c
+++ b/drivers/media/pci/cx25821/cx25821-core.c
@@ -871,6 +871,10 @@
dev->nr = ++cx25821_devcount;
sprintf(dev->name, "cx25821[%d]", dev->nr);
+ if (dev->nr >= ARRAY_SIZE(card)) {
+ CX25821_INFO("dev->nr >= %zd", ARRAY_SIZE(card));
+ return -ENODEV;
+ }
if (dev->pci->device != 0x8210) {
pr_info("%s(): Exiting. Incorrect Hardware device = 0x%02x\n",
__func__, dev->pci->device);
@@ -886,9 +890,6 @@
dev->channels[i].sram_channels = &cx25821_sram_channels[i];
}
- if (dev->nr > 1)
- CX25821_INFO("dev->nr > 1!");
-
/* board config */
dev->board = 1; /* card[dev->nr]; */
dev->_max_num_decoders = MAX_DECODERS;
diff --git a/drivers/media/platform/msm/camera/cam_core/cam_context.c b/drivers/media/platform/msm/camera/cam_core/cam_context.c
index 8beffc4..891b738 100644
--- a/drivers/media/platform/msm/camera/cam_core/cam_context.c
+++ b/drivers/media/platform/msm/camera/cam_core/cam_context.c
@@ -355,7 +355,7 @@
{
int rc = 0;
- if (!ctx->state_machine) {
+ if (!ctx || !ctx->state_machine) {
CAM_ERR(CAM_CORE, "Context is not ready");
return -EINVAL;
}
@@ -384,7 +384,7 @@
{
int rc = 0;
- if (!ctx->state_machine) {
+ if (!ctx || !ctx->state_machine) {
CAM_ERR(CAM_CORE, "Context is not ready");
return -EINVAL;
}
diff --git a/drivers/media/platform/msm/camera/cam_isp/cam_isp_context.c b/drivers/media/platform/msm/camera/cam_isp/cam_isp_context.c
index 50cdc7d..7b02aac 100644
--- a/drivers/media/platform/msm/camera/cam_isp/cam_isp_context.c
+++ b/drivers/media/platform/msm/camera/cam_isp/cam_isp_context.c
@@ -504,6 +504,18 @@
}
+static int __cam_isp_ctx_reg_upd_in_epoch_state(
+ struct cam_isp_context *ctx_isp, void *evt_data)
+{
+ if (ctx_isp->frame_id == 1)
+ CAM_DBG(CAM_ISP, "Reg update for early PCR");
+ else
+ CAM_WARN(CAM_ISP,
+ "Unexpected reg update in activated substate:%d for frame_id:%lld",
+ ctx_isp->substate_activated, ctx_isp->frame_id);
+ return 0;
+}
+
static int __cam_isp_ctx_reg_upd_in_activated_state(
struct cam_isp_context *ctx_isp, void *evt_data)
{
@@ -1119,7 +1131,7 @@
.irq_ops = {
__cam_isp_ctx_handle_error,
__cam_isp_ctx_sof_in_epoch,
- NULL,
+ __cam_isp_ctx_reg_upd_in_epoch_state,
__cam_isp_ctx_notify_sof_in_actived_state,
__cam_isp_ctx_notify_eof_in_actived_state,
__cam_isp_ctx_buf_done_in_epoch,
diff --git a/drivers/media/platform/msm/camera/cam_isp/isp_hw_mgr/cam_ife_hw_mgr.c b/drivers/media/platform/msm/camera/cam_isp/isp_hw_mgr/cam_ife_hw_mgr.c
index 12c37863..c1aa501 100644
--- a/drivers/media/platform/msm/camera/cam_isp/isp_hw_mgr/cam_ife_hw_mgr.c
+++ b/drivers/media/platform/msm/camera/cam_isp/isp_hw_mgr/cam_ife_hw_mgr.c
@@ -1367,6 +1367,7 @@
uint32_t num_rdi_port_per_in = 0;
uint32_t total_pix_port = 0;
uint32_t total_rdi_port = 0;
+ uint32_t in_port_length = 0;
CAM_DBG(CAM_ISP, "Enter...");
@@ -1427,9 +1428,27 @@
isp_resource[i].res_hdl,
isp_resource[i].length);
+ in_port_length = sizeof(struct cam_isp_in_port_info);
+
+ if (in_port_length > isp_resource[i].length) {
+ CAM_ERR(CAM_ISP, "buffer size is not enough");
+ rc = -EINVAL;
+ goto free_res;
+ }
+
in_port = memdup_user((void __user *)isp_resource[i].res_hdl,
isp_resource[i].length);
if (!IS_ERR(in_port)) {
+ in_port_length = sizeof(struct cam_isp_in_port_info) +
+ (in_port->num_out_res - 1) *
+ sizeof(struct cam_isp_out_port_info);
+ if (in_port_length > isp_resource[i].length) {
+ CAM_ERR(CAM_ISP, "buffer size is not enough");
+ rc = -EINVAL;
+ kfree(in_port);
+ goto free_res;
+ }
+
rc = cam_ife_mgr_acquire_hw_for_ctx(ife_ctx, in_port,
&num_pix_port_per_in, &num_rdi_port_per_in);
total_pix_port += num_pix_port_per_in;
diff --git a/drivers/media/platform/msm/camera/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_top/cam_vfe_camif_ver2.c b/drivers/media/platform/msm/camera/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_top/cam_vfe_camif_ver2.c
index 90c8006..8bc9bd2 100644
--- a/drivers/media/platform/msm/camera/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_top/cam_vfe_camif_ver2.c
+++ b/drivers/media/platform/msm/camera/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_top/cam_vfe_camif_ver2.c
@@ -204,6 +204,9 @@
{
struct cam_vfe_mux_camif_data *rsrc_data;
uint32_t val = 0;
+ uint32_t epoch0_irq_mask;
+ uint32_t epoch1_irq_mask;
+ uint32_t computed_epoch_line_cfg;
if (!camif_res) {
CAM_ERR(CAM_ISP, "Error! Invalid input arguments");
@@ -243,9 +246,16 @@
rsrc_data->common_reg->module_ctrl[
CAM_VFE_TOP_VER2_MODULE_STATS]->cgc_ovd);
- /* epoch config with 20 line */
- cam_io_w_mb(rsrc_data->reg_data->epoch_line_cfg,
+ /* epoch config */
+ epoch0_irq_mask = ((rsrc_data->last_line - rsrc_data->first_line) / 2) +
+ rsrc_data->first_line;
+ epoch1_irq_mask = rsrc_data->reg_data->epoch_line_cfg & 0xFFFF;
+ computed_epoch_line_cfg = (epoch0_irq_mask << 16) | epoch1_irq_mask;
+ cam_io_w_mb(computed_epoch_line_cfg,
rsrc_data->mem_base + rsrc_data->camif_reg->epoch_irq);
+ CAM_DBG(CAM_ISP, "first_line:%u last_line:%u epoch_line_cfg: 0x%x",
+ rsrc_data->first_line, rsrc_data->last_line,
+ computed_epoch_line_cfg);
camif_res->res_state = CAM_ISP_RESOURCE_STATE_STREAMING;
diff --git a/drivers/media/platform/msm/camera/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_top/cam_vfe_top_ver2.c b/drivers/media/platform/msm/camera/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_top/cam_vfe_top_ver2.c
index 5d6045b..be0ca18 100644
--- a/drivers/media/platform/msm/camera/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_top/cam_vfe_top_ver2.c
+++ b/drivers/media/platform/msm/camera/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_top/cam_vfe_top_ver2.c
@@ -34,11 +34,12 @@
struct cam_vfe_top_ver2_common_data common_data;
struct cam_isp_resource_node mux_rsrc[CAM_VFE_TOP_VER2_MUX_MAX];
unsigned long hw_clk_rate;
- struct cam_axi_vote to_be_applied_axi_vote;
struct cam_axi_vote applied_axi_vote;
- uint32_t counter_to_update_axi_vote;
struct cam_axi_vote req_axi_vote[CAM_VFE_TOP_VER2_MUX_MAX];
unsigned long req_clk_rate[CAM_VFE_TOP_VER2_MUX_MAX];
+ struct cam_axi_vote last_vote[CAM_VFE_TOP_VER2_MUX_MAX *
+ CAM_VFE_DELAY_BW_REDUCTION_NUM_FRAMES];
+ uint32_t last_counter;
enum cam_vfe_bw_control_action
axi_vote_control[CAM_VFE_TOP_VER2_MUX_MAX];
};
@@ -128,6 +129,7 @@
bool start_stop)
{
struct cam_axi_vote sum = {0, 0};
+ struct cam_axi_vote to_be_applied_axi_vote = {0, 0};
int i, rc = 0;
struct cam_hw_soc_info *soc_info =
top_priv->common_data.soc_info;
@@ -156,6 +158,11 @@
sum.uncompressed_bw,
sum.compressed_bw);
+ top_priv->last_vote[top_priv->last_counter] = sum;
+ top_priv->last_counter = (top_priv->last_counter + 1) %
+ (CAM_VFE_TOP_VER2_MUX_MAX *
+ CAM_VFE_DELAY_BW_REDUCTION_NUM_FRAMES);
+
if ((top_priv->applied_axi_vote.uncompressed_bw ==
sum.uncompressed_bw) &&
(top_priv->applied_axi_vote.compressed_bw ==
@@ -163,77 +170,60 @@
CAM_DBG(CAM_ISP, "BW config unchanged %llu %llu",
top_priv->applied_axi_vote.uncompressed_bw,
top_priv->applied_axi_vote.compressed_bw);
- top_priv->counter_to_update_axi_vote = 0;
return 0;
}
- if ((top_priv->to_be_applied_axi_vote.uncompressed_bw !=
- sum.uncompressed_bw) ||
- (top_priv->to_be_applied_axi_vote.compressed_bw !=
- sum.compressed_bw)) {
- // we got a new bw value to apply
- top_priv->counter_to_update_axi_vote = 0;
-
- top_priv->to_be_applied_axi_vote.uncompressed_bw =
- sum.uncompressed_bw;
- top_priv->to_be_applied_axi_vote.compressed_bw =
- sum.compressed_bw;
- }
-
if (start_stop == true) {
- CAM_DBG(CAM_ISP,
- "New bw in start/stop, applying bw now, counter=%d",
- top_priv->counter_to_update_axi_vote);
- top_priv->counter_to_update_axi_vote = 0;
- apply_bw_update = true;
- } else if ((top_priv->to_be_applied_axi_vote.uncompressed_bw <
- top_priv->applied_axi_vote.uncompressed_bw) ||
- (top_priv->to_be_applied_axi_vote.compressed_bw <
- top_priv->applied_axi_vote.compressed_bw)) {
- if (top_priv->counter_to_update_axi_vote >=
+ /* need to vote current request immediately */
+ to_be_applied_axi_vote = sum;
+ /* Reset everything, we can start afresh */
+ memset(top_priv->last_vote, 0x0, sizeof(struct cam_axi_vote) *
(CAM_VFE_TOP_VER2_MUX_MAX *
- CAM_VFE_DELAY_BW_REDUCTION_NUM_FRAMES)) {
- CAM_DBG(CAM_ISP,
- "New bw is less, applying bw now, counter=%d",
- top_priv->counter_to_update_axi_vote);
- top_priv->counter_to_update_axi_vote = 0;
- apply_bw_update = true;
- } else {
- CAM_DBG(CAM_ISP,
- "New bw is less, Defer applying bw, counter=%d",
- top_priv->counter_to_update_axi_vote);
-
- top_priv->counter_to_update_axi_vote++;
- apply_bw_update = false;
- }
+ CAM_VFE_DELAY_BW_REDUCTION_NUM_FRAMES));
+ top_priv->last_counter = 0;
+ top_priv->last_vote[top_priv->last_counter] = sum;
+ top_priv->last_counter = (top_priv->last_counter + 1) %
+ (CAM_VFE_TOP_VER2_MUX_MAX *
+ CAM_VFE_DELAY_BW_REDUCTION_NUM_FRAMES);
} else {
- CAM_DBG(CAM_ISP,
- "New bw is more, applying bw now, counter=%d",
- top_priv->counter_to_update_axi_vote);
- top_priv->counter_to_update_axi_vote = 0;
- apply_bw_update = true;
+ /*
+ * Find max bw request in last few frames. This will the bw
+ *that we want to vote to CPAS now.
+ */
+ for (i = 0; i < (CAM_VFE_TOP_VER2_MUX_MAX *
+ CAM_VFE_DELAY_BW_REDUCTION_NUM_FRAMES); i++) {
+ if (to_be_applied_axi_vote.compressed_bw <
+ top_priv->last_vote[i].compressed_bw)
+ to_be_applied_axi_vote.compressed_bw =
+ top_priv->last_vote[i].compressed_bw;
+
+ if (to_be_applied_axi_vote.uncompressed_bw <
+ top_priv->last_vote[i].uncompressed_bw)
+ to_be_applied_axi_vote.uncompressed_bw =
+ top_priv->last_vote[i].uncompressed_bw;
+ }
}
- CAM_DBG(CAM_ISP,
- "counter=%d, apply_bw_update=%d",
- top_priv->counter_to_update_axi_vote,
- apply_bw_update);
+ if ((to_be_applied_axi_vote.uncompressed_bw !=
+ top_priv->applied_axi_vote.uncompressed_bw) ||
+ (to_be_applied_axi_vote.compressed_bw !=
+ top_priv->applied_axi_vote.compressed_bw))
+ apply_bw_update = true;
+
+ CAM_DBG(CAM_ISP, "apply_bw_update=%d", apply_bw_update);
if (apply_bw_update == true) {
rc = cam_cpas_update_axi_vote(
soc_private->cpas_handle,
- &top_priv->to_be_applied_axi_vote);
+ &to_be_applied_axi_vote);
if (!rc) {
top_priv->applied_axi_vote.uncompressed_bw =
- top_priv->
- to_be_applied_axi_vote.uncompressed_bw;
+ to_be_applied_axi_vote.uncompressed_bw;
top_priv->applied_axi_vote.compressed_bw =
- top_priv->
to_be_applied_axi_vote.compressed_bw;
} else {
CAM_ERR(CAM_ISP, "BW request failed, rc=%d", rc);
}
- top_priv->counter_to_update_axi_vote = 0;
}
return rc;
@@ -706,11 +696,12 @@
}
vfe_top->top_priv = top_priv;
top_priv->hw_clk_rate = 0;
- top_priv->to_be_applied_axi_vote.compressed_bw = 0;
- top_priv->to_be_applied_axi_vote.uncompressed_bw = 0;
top_priv->applied_axi_vote.compressed_bw = 0;
top_priv->applied_axi_vote.uncompressed_bw = 0;
- top_priv->counter_to_update_axi_vote = 0;
+ memset(top_priv->last_vote, 0x0, sizeof(struct cam_axi_vote) *
+ (CAM_VFE_TOP_VER2_MUX_MAX *
+ CAM_VFE_DELAY_BW_REDUCTION_NUM_FRAMES));
+ top_priv->last_counter = 0;
for (i = 0, j = 0; i < CAM_VFE_TOP_VER2_MUX_MAX; i++) {
top_priv->mux_rsrc[i].res_type = CAM_ISP_RESOURCE_VFE_IN;
diff --git a/drivers/media/platform/msm/camera/cam_jpeg/jpeg_hw/cam_jpeg_hw_mgr.c b/drivers/media/platform/msm/camera/cam_jpeg/jpeg_hw/cam_jpeg_hw_mgr.c
index f172a79..97d076a 100644
--- a/drivers/media/platform/msm/camera/cam_jpeg/jpeg_hw/cam_jpeg_hw_mgr.c
+++ b/drivers/media/platform/msm/camera/cam_jpeg/jpeg_hw/cam_jpeg_hw_mgr.c
@@ -770,13 +770,6 @@
} else {
CAM_ERR(CAM_JPEG, "process_cmd null ");
}
- rc = hw_mgr->devices[dev_type][0]->hw_ops.process_cmd(
- hw_mgr->devices[dev_type][0]->hw_priv,
- CAM_JPEG_CMD_SET_IRQ_CB,
- &irq_cb, sizeof(irq_cb));
- if (rc)
- CAM_ERR(CAM_JPEG,
- "CMD_SET_IRQ_CB failed %d", rc);
if (hw_mgr->devices[dev_type][0]->hw_ops.stop) {
rc = hw_mgr->devices[dev_type][0]->hw_ops.stop(
diff --git a/drivers/media/platform/msm/camera/cam_lrme/lrme_hw_mgr/cam_lrme_hw_mgr.c b/drivers/media/platform/msm/camera/cam_lrme/lrme_hw_mgr/cam_lrme_hw_mgr.c
index 898997a..a60661e 100644
--- a/drivers/media/platform/msm/camera/cam_lrme/lrme_hw_mgr/cam_lrme_hw_mgr.c
+++ b/drivers/media/platform/msm/camera/cam_lrme/lrme_hw_mgr/cam_lrme_hw_mgr.c
@@ -879,6 +879,7 @@
if (args->num_in_map_entries == 0 || args->num_out_map_entries == 0) {
CAM_ERR(CAM_LRME, "Error in port number in %d, out %d",
args->num_in_map_entries, args->num_out_map_entries);
+ rc = -EINVAL;
goto error;
}
diff --git a/drivers/media/platform/msm/camera/cam_req_mgr/cam_req_mgr_core.c b/drivers/media/platform/msm/camera/cam_req_mgr/cam_req_mgr_core.c
index ff18fa74..4602d6c 100644
--- a/drivers/media/platform/msm/camera/cam_req_mgr/cam_req_mgr_core.c
+++ b/drivers/media/platform/msm/camera/cam_req_mgr/cam_req_mgr_core.c
@@ -163,6 +163,34 @@
}
/**
+ * __cam_req_mgr_validate_inject_delay()
+ *
+ * @brief : Check if any pd device is introducing inject delay
+ * @tbl : cam_req_mgr_req_tbl
+ * @curr_idx : slot idx
+ *
+ * @return : 0 for success, negative for failure
+ */
+static int __cam_req_mgr_validate_inject_delay(
+ struct cam_req_mgr_req_tbl *tbl,
+ int32_t curr_idx)
+{
+ struct cam_req_mgr_tbl_slot *slot = NULL;
+
+ while (tbl) {
+ slot = &tbl->slot[curr_idx];
+ if (slot->inject_delay > 0) {
+ slot->inject_delay--;
+ return -EAGAIN;
+ }
+ __cam_req_mgr_dec_idx(&curr_idx, tbl->pd_delta,
+ tbl->num_slots);
+ tbl = tbl->next;
+ }
+ return 0;
+}
+
+/**
* __cam_req_mgr_traverse()
*
* @brief : Traverse through pd tables, it will internally cover all linked
@@ -201,14 +229,17 @@
tbl->skip_traverse, traverse_data->in_q->slot[curr_idx].status,
traverse_data->in_q->slot[curr_idx].skip_idx);
- if ((slot->inject_delay > 0) &&
- (traverse_data->self_link == true)) {
- CAM_DBG(CAM_CRM, "Injecting Delay of one frame");
- apply_data[tbl->pd].req_id = -1;
- slot->inject_delay--;
- /* This pd table is not ready to proceed with asked idx */
- SET_FAILURE_BIT(traverse_data->result, tbl->pd);
- return -EAGAIN;
+ if ((traverse_data->self_link == true) &&
+ (!traverse_data->inject_delay_chk)) {
+ rc = __cam_req_mgr_validate_inject_delay(tbl, curr_idx);
+ if (rc) {
+ CAM_DBG(CAM_CRM, "Injecting Delay of one frame");
+ apply_data[tbl->pd].req_id = -1;
+ /* This pd tbl not ready to proceed with asked idx */
+ SET_FAILURE_BIT(traverse_data->result, tbl->pd);
+ return -EAGAIN;
+ }
+ traverse_data->inject_delay_chk = true;
}
/* Check if req is ready or in skip mode or pd tbl is in skip mode */
@@ -520,6 +551,7 @@
traverse_data.result = 0;
traverse_data.validate_only = validate_only;
traverse_data.self_link = self_link;
+ traverse_data.inject_delay_chk = false;
traverse_data.open_req_cnt = link->open_req_cnt;
/*
* Traverse through all pd tables, if result is success,
diff --git a/drivers/media/platform/msm/camera/cam_req_mgr/cam_req_mgr_core.h b/drivers/media/platform/msm/camera/cam_req_mgr/cam_req_mgr_core.h
index 73ffb81..025c16a 100644
--- a/drivers/media/platform/msm/camera/cam_req_mgr/cam_req_mgr_core.h
+++ b/drivers/media/platform/msm/camera/cam_req_mgr/cam_req_mgr_core.h
@@ -126,15 +126,16 @@
/**
* struct cam_req_mgr_traverse
- * @idx : slot index
- * @result : contains which all tables were able to apply successfully
- * @tbl : pointer of pipeline delay based request table
- * @apply_data : pointer which various tables will update during traverse
- * @in_q : input request queue pointer
- * @validate_only : Whether to validate only and/or update settings
- * @self_link : To indicate whether the check is for the given link or the
- * other sync link
- * @open_req_cnt : Count of open requests yet to be serviced in the kernel.
+ * @idx : slot index
+ * @result : contains which all tables were able to apply successfully
+ * @tbl : pointer of pipeline delay based request table
+ * @apply_data : pointer which various tables will update during traverse
+ * @in_q : input request queue pointer
+ * @validate_only : Whether to validate only and/or update settings
+ * @self_link : To indicate whether the check is for the given link or
+ * the other sync link
+ * @inject_delay_chk : if inject delay has been validated for all pd devices
+ * @open_req_cnt : Count of open requests yet to be serviced in the kernel.
*/
struct cam_req_mgr_traverse {
int32_t idx;
@@ -144,7 +145,8 @@
struct cam_req_mgr_req_queue *in_q;
bool validate_only;
bool self_link;
- int32_t open_req_cnt;
+ bool inject_delay_chk;
+ int32_t open_req_cnt;
};
/**
diff --git a/drivers/media/platform/msm/camera/cam_req_mgr/cam_req_mgr_workq.c b/drivers/media/platform/msm/camera/cam_req_mgr/cam_req_mgr_workq.c
index 966b573..066efd6 100644
--- a/drivers/media/platform/msm/camera/cam_req_mgr/cam_req_mgr_workq.c
+++ b/drivers/media/platform/msm/camera/cam_req_mgr/cam_req_mgr_workq.c
@@ -59,11 +59,11 @@
(struct cam_req_mgr_core_workq *)task->parent;
unsigned long flags = 0;
- WORKQ_ACQUIRE_LOCK(workq, flags);
list_del_init(&task->entry);
task->cancel = 0;
task->process_cb = NULL;
task->priv = NULL;
+ WORKQ_ACQUIRE_LOCK(workq, flags);
list_add_tail(&task->entry,
&workq->task.empty_head);
atomic_add(1, &workq->task.free_cnt);
@@ -127,28 +127,6 @@
}
}
-void crm_workq_clear_q(struct cam_req_mgr_core_workq *workq)
-{
- int32_t i = CRM_TASK_PRIORITY_0;
- struct crm_workq_task *task, *task_save;
-
- CAM_DBG(CAM_CRM, "pending_cnt %d",
- atomic_read(&workq->task.pending_cnt));
-
- while (i < CRM_TASK_PRIORITY_MAX) {
- if (!list_empty(&workq->task.process_head[i])) {
- list_for_each_entry_safe(task, task_save,
- &workq->task.process_head[i], entry) {
- cam_req_mgr_workq_put_task(task);
- CAM_WARN(CAM_CRM, "flush task %pK, %d, cnt %d",
- task, i, atomic_read(
- &workq->task.free_cnt));
- }
- }
- i++;
- }
-}
-
int cam_req_mgr_workq_enqueue_task(struct crm_workq_task *task,
void *priv, int32_t prio)
{
@@ -167,10 +145,6 @@
rc = -EINVAL;
goto end;
}
- if (!workq->job) {
- rc = -EINVAL;
- goto end;
- }
if (task->cancel == 1) {
cam_req_mgr_workq_put_task(task);
@@ -184,16 +158,21 @@
? prio : CRM_TASK_PRIORITY_0;
WORKQ_ACQUIRE_LOCK(workq, flags);
+ if (!workq->job) {
+ rc = -EINVAL;
+ WORKQ_RELEASE_LOCK(workq, flags);
+ goto end;
+ }
+
list_add_tail(&task->entry,
&workq->task.process_head[task->priority]);
- WORKQ_RELEASE_LOCK(workq, flags);
atomic_add(1, &workq->task.pending_cnt);
CAM_DBG(CAM_CRM, "enq task %pK pending_cnt %d",
task, atomic_read(&workq->task.pending_cnt));
queue_work(workq->job, &workq->work);
-
+ WORKQ_RELEASE_LOCK(workq, flags);
end:
return rc;
}
@@ -252,8 +231,7 @@
task = &crm_workq->task.pool[i];
task->parent = (void *)crm_workq;
/* Put all tasks in free pool */
- list_add_tail(&task->entry,
- &crm_workq->task.process_head[CRM_TASK_PRIORITY_0]);
+ INIT_LIST_HEAD(&task->entry);
cam_req_mgr_workq_put_task(task);
}
*workq = crm_workq;
@@ -266,13 +244,18 @@
void cam_req_mgr_workq_destroy(struct cam_req_mgr_core_workq **crm_workq)
{
+ unsigned long flags = 0;
+ struct workqueue_struct *job;
CAM_DBG(CAM_CRM, "destroy workque %pK", crm_workq);
if (*crm_workq) {
- crm_workq_clear_q(*crm_workq);
+ WORKQ_ACQUIRE_LOCK(*crm_workq, flags);
if ((*crm_workq)->job) {
- destroy_workqueue((*crm_workq)->job);
+ job = (*crm_workq)->job;
(*crm_workq)->job = NULL;
- }
+ WORKQ_RELEASE_LOCK(*crm_workq, flags);
+ destroy_workqueue(job);
+ } else
+ WORKQ_RELEASE_LOCK(*crm_workq, flags);
kfree((*crm_workq)->task.pool);
kfree(*crm_workq);
*crm_workq = NULL;
diff --git a/drivers/media/platform/msm/camera/cam_sensor_module/cam_actuator/cam_actuator_core.c b/drivers/media/platform/msm/camera/cam_sensor_module/cam_actuator/cam_actuator_core.c
index 2f74765..a34d70c 100644
--- a/drivers/media/platform/msm/camera/cam_sensor_module/cam_actuator/cam_actuator_core.c
+++ b/drivers/media/platform/msm/camera/cam_sensor_module/cam_actuator/cam_actuator_core.c
@@ -603,7 +603,11 @@
void cam_actuator_shutdown(struct cam_actuator_ctrl_t *a_ctrl)
{
- int rc;
+ int rc = 0;
+ struct cam_actuator_soc_private *soc_private =
+ (struct cam_actuator_soc_private *)a_ctrl->soc_info.soc_private;
+ struct cam_sensor_power_ctrl_t *power_info =
+ &soc_private->power_info;
if (a_ctrl->cam_act_state == CAM_ACTUATOR_INIT)
return;
@@ -612,6 +616,7 @@
rc = cam_actuator_power_down(a_ctrl);
if (rc < 0)
CAM_ERR(CAM_ACTUATOR, "Actuator Power down failed");
+ a_ctrl->cam_act_state = CAM_ACTUATOR_ACQUIRE;
}
if (a_ctrl->cam_act_state >= CAM_ACTUATOR_ACQUIRE) {
@@ -622,6 +627,12 @@
a_ctrl->bridge_intf.link_hdl = -1;
a_ctrl->bridge_intf.session_hdl = -1;
}
+
+ kfree(power_info->power_setting);
+ kfree(power_info->power_down_setting);
+ power_info->power_setting = NULL;
+ power_info->power_down_setting = NULL;
+
a_ctrl->cam_act_state = CAM_ACTUATOR_INIT;
}
diff --git a/drivers/media/platform/msm/camera/cam_sensor_module/cam_csiphy/cam_csiphy_core.c b/drivers/media/platform/msm/camera/cam_sensor_module/cam_csiphy/cam_csiphy_core.c
index dbbac08..2688cd5 100644
--- a/drivers/media/platform/msm/camera/cam_sensor_module/cam_csiphy/cam_csiphy_core.c
+++ b/drivers/media/platform/msm/camera/cam_sensor_module/cam_csiphy/cam_csiphy_core.c
@@ -614,6 +614,13 @@
if (csiphy_dev->acquire_count == 0)
csiphy_dev->csiphy_state = CAM_CSIPHY_INIT;
+
+ if (csiphy_dev->config_count == 0) {
+ CAM_DBG(CAM_CSIPHY, "reset csiphy_info");
+ csiphy_dev->csiphy_info.lane_mask = 0;
+ csiphy_dev->csiphy_info.lane_cnt = 0;
+ csiphy_dev->csiphy_info.combo_mode = 0;
+ }
}
break;
case CAM_CONFIG_DEV: {
diff --git a/drivers/media/platform/msm/camera/cam_sensor_module/cam_csiphy/include/cam_csiphy_1_0_hwreg.h b/drivers/media/platform/msm/camera/cam_sensor_module/cam_csiphy/include/cam_csiphy_1_0_hwreg.h
index 3f743fc..3245093 100644
--- a/drivers/media/platform/msm/camera/cam_sensor_module/cam_csiphy/include/cam_csiphy_1_0_hwreg.h
+++ b/drivers/media/platform/msm/camera/cam_sensor_module/cam_csiphy/include/cam_csiphy_1_0_hwreg.h
@@ -152,7 +152,7 @@
{0x0008, 0x00, 0x00, CSIPHY_SETTLE_CNT_LOWER_BYTE},
{0x0010, 0x52, 0x00, CSIPHY_DEFAULT_PARAMS},
{0x0038, 0xFE, 0x00, CSIPHY_DEFAULT_PARAMS},
- {0x0060, 0x01, 0x00, CSIPHY_DEFAULT_PARAMS},
+ {0x0060, 0x00, 0x00, CSIPHY_DEFAULT_PARAMS},
{0x0064, 0x7F, 0x00, CSIPHY_DEFAULT_PARAMS},
},
{
@@ -168,7 +168,7 @@
{0x070C, 0xA5, 0x00, CSIPHY_DEFAULT_PARAMS},
{0x0710, 0x52, 0x00, CSIPHY_DEFAULT_PARAMS},
{0x0738, 0x1F, 0x00, CSIPHY_DEFAULT_PARAMS},
- {0x0760, 0x01, 0x00, CSIPHY_DEFAULT_PARAMS},
+ {0x0760, 0x00, 0x00, CSIPHY_DEFAULT_PARAMS},
{0x0764, 0x7F, 0x00, CSIPHY_DEFAULT_PARAMS},
},
{
@@ -183,7 +183,7 @@
{0x0208, 0x00, 0x00, CSIPHY_SETTLE_CNT_LOWER_BYTE},
{0x0210, 0x52, 0x00, CSIPHY_DEFAULT_PARAMS},
{0x0238, 0xFE, 0x00, CSIPHY_DEFAULT_PARAMS},
- {0x0260, 0x01, 0x00, CSIPHY_DEFAULT_PARAMS},
+ {0x0260, 0x00, 0x00, CSIPHY_DEFAULT_PARAMS},
{0x0264, 0x7F, 0x00, CSIPHY_DEFAULT_PARAMS},
},
{
@@ -198,7 +198,7 @@
{0x0408, 0x00, 0x00, CSIPHY_SETTLE_CNT_LOWER_BYTE},
{0x0410, 0x52, 0x00, CSIPHY_DEFAULT_PARAMS},
{0x0438, 0xFE, 0x00, CSIPHY_DEFAULT_PARAMS},
- {0x0460, 0x01, 0x00, CSIPHY_DEFAULT_PARAMS},
+ {0x0460, 0x00, 0x00, CSIPHY_DEFAULT_PARAMS},
{0x0464, 0x7F, 0x00, CSIPHY_DEFAULT_PARAMS},
},
{
@@ -214,7 +214,7 @@
{0x060C, 0xA5, 0x00, CSIPHY_DEFAULT_PARAMS},
{0x0610, 0x52, 0x00, CSIPHY_DEFAULT_PARAMS},
{0x0638, 0x1F, 0x00, CSIPHY_DEFAULT_PARAMS},
- {0x0660, 0x01, 0x00, CSIPHY_DEFAULT_PARAMS},
+ {0x0660, 0x00, 0x00, CSIPHY_DEFAULT_PARAMS},
{0x0664, 0x7F, 0x00, CSIPHY_DEFAULT_PARAMS},
},
};
diff --git a/drivers/media/platform/msm/camera/cam_sensor_module/cam_eeprom/cam_eeprom_core.c b/drivers/media/platform/msm/camera/cam_sensor_module/cam_eeprom/cam_eeprom_core.c
index 6523607..7f94f8d 100644
--- a/drivers/media/platform/msm/camera/cam_sensor_module/cam_eeprom/cam_eeprom_core.c
+++ b/drivers/media/platform/msm/camera/cam_sensor_module/cam_eeprom/cam_eeprom_core.c
@@ -315,8 +315,8 @@
power_down:
cam_eeprom_power_down(e_ctrl);
data_mem_free:
- kfree(e_ctrl->cal_data.mapdata);
- kfree(e_ctrl->cal_data.map);
+ vfree(e_ctrl->cal_data.mapdata);
+ vfree(e_ctrl->cal_data.map);
e_ctrl->cal_data.num_data = 0;
e_ctrl->cal_data.num_map = 0;
e_ctrl->cam_eeprom_state = CAM_EEPROM_ACQUIRE;
@@ -543,9 +543,9 @@
(struct cam_eeprom_soc_private *)e_ctrl->soc_info.soc_private;
struct cam_sensor_power_ctrl_t *power_info = &soc_private->power_info;
- e_ctrl->cal_data.map = kcalloc((MSM_EEPROM_MEMORY_MAP_MAX_SIZE *
- MSM_EEPROM_MAX_MEM_MAP_CNT),
- (sizeof(struct cam_eeprom_memory_map_t)), GFP_KERNEL);
+ e_ctrl->cal_data.map = vzalloc((MSM_EEPROM_MEMORY_MAP_MAX_SIZE *
+ MSM_EEPROM_MAX_MEM_MAP_CNT) *
+ (sizeof(struct cam_eeprom_memory_map_t)));
if (!e_ctrl->cal_data.map) {
rc = -ENOMEM;
CAM_ERR(CAM_EEPROM, "failed");
@@ -738,8 +738,8 @@
return rc;
}
rc = cam_eeprom_get_cal_data(e_ctrl, csl_packet);
- kfree(e_ctrl->cal_data.mapdata);
- kfree(e_ctrl->cal_data.map);
+ vfree(e_ctrl->cal_data.mapdata);
+ vfree(e_ctrl->cal_data.map);
e_ctrl->cal_data.num_data = 0;
e_ctrl->cal_data.num_map = 0;
CAM_DBG(CAM_EEPROM,
@@ -754,7 +754,7 @@
}
e_ctrl->cal_data.mapdata =
- kzalloc(e_ctrl->cal_data.num_data, GFP_KERNEL);
+ vzalloc(e_ctrl->cal_data.num_data);
if (!e_ctrl->cal_data.mapdata) {
rc = -ENOMEM;
CAM_ERR(CAM_EEPROM, "failed");
@@ -779,8 +779,12 @@
rc = cam_eeprom_get_cal_data(e_ctrl, csl_packet);
rc = cam_eeprom_power_down(e_ctrl);
e_ctrl->cam_eeprom_state = CAM_EEPROM_ACQUIRE;
- kfree(e_ctrl->cal_data.mapdata);
- kfree(e_ctrl->cal_data.map);
+ vfree(e_ctrl->cal_data.mapdata);
+ vfree(e_ctrl->cal_data.map);
+ kfree(power_info->power_setting);
+ kfree(power_info->power_down_setting);
+ power_info->power_setting = NULL;
+ power_info->power_down_setting = NULL;
e_ctrl->cal_data.num_data = 0;
e_ctrl->cal_data.num_map = 0;
break;
@@ -791,11 +795,13 @@
power_down:
cam_eeprom_power_down(e_ctrl);
memdata_free:
- kfree(e_ctrl->cal_data.mapdata);
+ vfree(e_ctrl->cal_data.mapdata);
error:
kfree(power_info->power_setting);
kfree(power_info->power_down_setting);
- kfree(e_ctrl->cal_data.map);
+ power_info->power_setting = NULL;
+ power_info->power_down_setting = NULL;
+ vfree(e_ctrl->cal_data.map);
e_ctrl->cal_data.num_data = 0;
e_ctrl->cal_data.num_map = 0;
e_ctrl->cam_eeprom_state = CAM_EEPROM_INIT;
@@ -830,6 +836,8 @@
kfree(power_info->power_setting);
kfree(power_info->power_down_setting);
+ power_info->power_setting = NULL;
+ power_info->power_down_setting = NULL;
}
e_ctrl->cam_eeprom_state = CAM_EEPROM_INIT;
diff --git a/drivers/media/platform/msm/camera/cam_sensor_module/cam_ois/cam_ois_core.c b/drivers/media/platform/msm/camera/cam_sensor_module/cam_ois/cam_ois_core.c
index 196df08..dfcb9fc 100644
--- a/drivers/media/platform/msm/camera/cam_sensor_module/cam_ois/cam_ois_core.c
+++ b/drivers/media/platform/msm/camera/cam_sensor_module/cam_ois/cam_ois_core.c
@@ -636,7 +636,11 @@
void cam_ois_shutdown(struct cam_ois_ctrl_t *o_ctrl)
{
- int rc;
+ int rc = 0;
+ struct cam_ois_soc_private *soc_private =
+ (struct cam_ois_soc_private *)o_ctrl->soc_info.soc_private;
+ struct cam_sensor_power_ctrl_t *power_info =
+ &soc_private->power_info;
if (o_ctrl->cam_ois_state == CAM_OIS_INIT)
return;
@@ -645,6 +649,7 @@
rc = cam_ois_power_down(o_ctrl);
if (rc < 0)
CAM_ERR(CAM_OIS, "OIS Power down failed");
+ o_ctrl->cam_ois_state = CAM_OIS_ACQUIRE;
}
if (o_ctrl->cam_ois_state >= CAM_OIS_ACQUIRE) {
@@ -656,6 +661,11 @@
o_ctrl->bridge_intf.session_hdl = -1;
}
+ kfree(power_info->power_setting);
+ kfree(power_info->power_down_setting);
+ power_info->power_setting = NULL;
+ power_info->power_down_setting = NULL;
+
o_ctrl->cam_ois_state = CAM_OIS_INIT;
}
diff --git a/drivers/media/platform/msm/camera/cam_sensor_module/cam_sensor/cam_sensor_core.c b/drivers/media/platform/msm/camera/cam_sensor_module/cam_sensor/cam_sensor_core.c
index d58834c..2133932 100644
--- a/drivers/media/platform/msm/camera/cam_sensor_module/cam_sensor/cam_sensor_core.c
+++ b/drivers/media/platform/msm/camera/cam_sensor_module/cam_sensor/cam_sensor_core.c
@@ -518,6 +518,8 @@
kfree(power_info->power_setting);
kfree(power_info->power_down_setting);
+ power_info->power_setting = NULL;
+ power_info->power_down_setting = NULL;
s_ctrl->streamon_count = 0;
s_ctrl->streamoff_count = 0;
@@ -584,24 +586,6 @@
"Already Sensor Probed in the slot");
break;
}
- /* Allocate memory for power up setting */
- pu = kzalloc(sizeof(struct cam_sensor_power_setting) *
- MAX_POWER_CONFIG, GFP_KERNEL);
- if (!pu) {
- rc = -ENOMEM;
- goto release_mutex;
- }
-
- pd = kzalloc(sizeof(struct cam_sensor_power_setting) *
- MAX_POWER_CONFIG, GFP_KERNEL);
- if (!pd) {
- kfree(pu);
- rc = -ENOMEM;
- goto release_mutex;
- }
-
- power_info->power_setting = pu;
- power_info->power_down_setting = pd;
if (cmd->handle_type ==
CAM_HANDLE_MEM_HANDLE) {
@@ -618,6 +602,9 @@
return -EINVAL;
}
+ pu = power_info->power_setting;
+ pd = power_info->power_down_setting;
+
/* Parse and fill vreg params for powerup settings */
rc = msm_camera_fill_vreg_params(
&s_ctrl->soc_info,
diff --git a/drivers/media/platform/msm/camera/cam_sensor_module/cam_sensor_utils/cam_sensor_util.c b/drivers/media/platform/msm/camera/cam_sensor_module/cam_sensor_utils/cam_sensor_util.c
index 10d29c9..73a0cf7 100644
--- a/drivers/media/platform/msm/camera/cam_sensor_module/cam_sensor_utils/cam_sensor_util.c
+++ b/drivers/media/platform/msm/camera/cam_sensor_module/cam_sensor_utils/cam_sensor_util.c
@@ -860,8 +860,10 @@
return rc;
free_power_down_settings:
kfree(power_info->power_down_setting);
+ power_info->power_down_setting = NULL;
free_power_settings:
kfree(power_info->power_setting);
+ power_info->power_setting = NULL;
return rc;
}
@@ -1304,7 +1306,9 @@
CAM_DBG(CAM_SENSOR, "index: %d", index);
power_setting = &ctrl->power_setting[index];
if (!power_setting) {
- CAM_ERR(CAM_SENSOR, "Invalid power up settings");
+ CAM_ERR(CAM_SENSOR,
+ "Invalid power up settings for index %d",
+ index);
return -EINVAL;
}
@@ -1548,7 +1552,7 @@
if (ret)
CAM_ERR(CAM_SENSOR, "cannot set pin to suspend state");
cam_res_mgr_shared_pinctrl_select_state(false);
- pinctrl_put(ctrl->pinctrl_info.pinctrl);
+ devm_pinctrl_put(ctrl->pinctrl_info.pinctrl);
cam_res_mgr_shared_pinctrl_put();
}
@@ -1594,11 +1598,6 @@
pd = &ctrl->power_down_setting[index];
- if (!pd) {
- CAM_ERR(CAM_SENSOR, "Invalid power down setting");
- return -EINVAL;
- }
-
for (j = 0; j < num_vreg; j++) {
if (!strcmp(soc_info->rgltr_name[j], "cam_clk")) {
@@ -1641,7 +1640,7 @@
{
int index = 0, ret = 0, num_vreg = 0, i;
struct cam_sensor_power_setting *pd = NULL;
- struct cam_sensor_power_setting *ps;
+ struct cam_sensor_power_setting *ps = NULL;
struct msm_camera_gpio_num_info *gpio_num_info = NULL;
CAM_DBG(CAM_SENSOR, "Enter");
@@ -1661,6 +1660,13 @@
for (index = 0; index < ctrl->power_down_setting_size; index++) {
CAM_DBG(CAM_SENSOR, "index %d", index);
pd = &ctrl->power_down_setting[index];
+ if (!pd) {
+ CAM_ERR(CAM_SENSOR,
+ "Invalid power down settings for index %d",
+ index);
+ return -EINVAL;
+ }
+
ps = NULL;
CAM_DBG(CAM_SENSOR, "type %d", pd->seq_type);
switch (pd->seq_type) {
@@ -1760,7 +1766,7 @@
CAM_ERR(CAM_SENSOR, "cannot set pin to suspend state");
cam_res_mgr_shared_pinctrl_select_state(false);
- pinctrl_put(ctrl->pinctrl_info.pinctrl);
+ devm_pinctrl_put(ctrl->pinctrl_info.pinctrl);
cam_res_mgr_shared_pinctrl_put();
}
diff --git a/drivers/media/platform/msm/camera/cam_smmu/cam_smmu_api.c b/drivers/media/platform/msm/camera/cam_smmu/cam_smmu_api.c
index ecfc566..5cd3008 100644
--- a/drivers/media/platform/msm/camera/cam_smmu/cam_smmu_api.c
+++ b/drivers/media/platform/msm/camera/cam_smmu/cam_smmu_api.c
@@ -3343,6 +3343,7 @@
rc = cam_populate_smmu_context_banks(dev, CAM_ARM_SMMU);
if (rc < 0) {
CAM_ERR(CAM_SMMU, "Error: populating context banks");
+ cam_smmu_release_cb(pdev);
return -ENOMEM;
}
return rc;
diff --git a/drivers/media/platform/msm/camera_v2/isp/msm_isp40.c b/drivers/media/platform/msm/camera_v2/isp/msm_isp40.c
index 19b1aac..72ab3ba 100644
--- a/drivers/media/platform/msm/camera_v2/isp/msm_isp40.c
+++ b/drivers/media/platform/msm/camera_v2/isp/msm_isp40.c
@@ -889,8 +889,6 @@
msm_camera_io_w(temp | (framedrop_period - 1) << 2,
vfe_base + VFE40_WM_BASE(stream_info->wm[vfe_idx][i]) + 0xC);
}
-
- msm_camera_io_w_mb(0x1, vfe_base + 0x378);
}
static void msm_vfe40_clear_framedrop(struct vfe_device *vfe_dev,
diff --git a/drivers/media/platform/msm/camera_v2/isp/msm_isp_axi_util.c b/drivers/media/platform/msm/camera_v2/isp/msm_isp_axi_util.c
index 0b84327..f50e257 100644
--- a/drivers/media/platform/msm/camera_v2/isp/msm_isp_axi_util.c
+++ b/drivers/media/platform/msm/camera_v2/isp/msm_isp_axi_util.c
@@ -3847,7 +3847,7 @@
int msm_isp_update_axi_stream(struct vfe_device *vfe_dev, void *arg)
{
- int rc = 0, i;
+ int rc = 0, i, j, k;
struct msm_vfe_axi_stream *stream_info;
struct msm_vfe_axi_stream_update_cmd *update_cmd = arg;
struct msm_vfe_axi_stream_cfg_update_info *update_info = NULL;
@@ -4126,8 +4126,16 @@
}
vfe_idx = msm_isp_get_vfe_idx_for_stream(
vfe_dev, stream_info);
- msm_isp_stream_axi_cfg_update(vfe_dev, stream_info,
- update_info);
+ for (j = 0; j < stream_info->num_planes; j++) {
+ stream_info->plane_cfg[vfe_idx][j] =
+ update_info->plane_cfg[j];
+ for (k = 0; k < stream_info->num_isp; k++) {
+ vfe_dev = stream_info->vfe_dev[k];
+ vfe_dev->hw_info->vfe_ops.axi_ops.
+ cfg_wm_reg(vfe_dev,
+ stream_info, j);
+ }
+ }
}
break;
}
diff --git a/drivers/media/platform/msm/camera_v2/isp/msm_isp_util.c b/drivers/media/platform/msm/camera_v2/isp/msm_isp_util.c
index b589afa..e671122 100644
--- a/drivers/media/platform/msm/camera_v2/isp/msm_isp_util.c
+++ b/drivers/media/platform/msm/camera_v2/isp/msm_isp_util.c
@@ -410,8 +410,12 @@
pr_err("%s: Fetch engine config failed\n", __func__);
return -EINVAL;
}
- for (i = 0; i < stream_info->num_planes; i++)
+ for (i = 0; i < stream_info->num_planes; i++) {
+ vfe_dev->hw_info->vfe_ops.axi_ops.enable_wm(
+ vfe_dev->vfe_base,
+ stream_info->wm[vfe_idx][i], 1);
wm_reload_mask |= (1 << stream_info->wm[vfe_idx][i]);
+ }
vfe_dev->hw_info->vfe_ops.core_ops.reg_update(vfe_dev,
VFE_SRC_MAX);
vfe_dev->hw_info->vfe_ops.axi_ops.reload_wm(vfe_dev,
diff --git a/drivers/media/platform/msm/camera_v2/sensor/csid/include/msm_csid_3_4_3_hwreg.h b/drivers/media/platform/msm/camera_v2/sensor/csid/include/msm_csid_3_4_3_hwreg.h
new file mode 100644
index 0000000..ac0a989
--- /dev/null
+++ b/drivers/media/platform/msm/camera_v2/sensor/csid/include/msm_csid_3_4_3_hwreg.h
@@ -0,0 +1,63 @@
+/* Copyright (c) 2018, The Linux Foundation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ */
+
+#ifndef MSM_CSID_3_4_3_HWREG_H
+#define MSM_CSID_3_4_3_HWREG_H
+
+#include <sensor/csid/msm_csid.h>
+
+static uint8_t csid_lane_assign_v3_4_3[PHY_LANE_MAX] = {0, 4, 1, 2, 3};
+static struct csid_reg_parms_t csid_v3_4_3 = {
+ /* MIPI CSID registers */
+ 0x0,
+ 0x4,
+ 0x8,
+ 0xC,
+ 0x10,
+ 0x14,
+ 0x18,
+ 0x1C,
+ 0x20,
+ 0x60,
+ 0x64,
+ 0x68,
+ 0x6C,
+ 0x70,
+ 0x74,
+ 0x78,
+ 0x7C,
+ 0x80,
+ 0x84,
+ 0x88,
+ 0x8C,
+ 0x90,
+ 0x94,
+ 0x98,
+ 0xA0,
+ 0xA4,
+ 0xAC,
+ 0xB0,
+ 0xB4,
+ 11,
+ 0x7FFF,
+ 0x4,
+ 17,
+ 0x30040003,
+ 0xFFFFFFFF,
+ 0xFFFFFFFF,
+ 0xFFFFFFFF,
+ 0x7f010800,
+ 20,
+ 0xFFFFFFFF,
+ 0xFFFFFFFF,
+};
+#endif
diff --git a/drivers/media/platform/msm/camera_v2/sensor/csid/msm_csid.c b/drivers/media/platform/msm/camera_v2/sensor/csid/msm_csid.c
index d5e7989..9d3184e 100644
--- a/drivers/media/platform/msm/camera_v2/sensor/csid/msm_csid.c
+++ b/drivers/media/platform/msm/camera_v2/sensor/csid/msm_csid.c
@@ -26,6 +26,7 @@
#include "include/msm_csid_3_5_hwreg.h"
#include "include/msm_csid_3_4_1_hwreg.h"
#include "include/msm_csid_3_4_2_hwreg.h"
+#include "include/msm_csid_3_4_3_hwreg.h"
#include "include/msm_csid_3_6_0_hwreg.h"
#include "include/msm_csid_3_5_1_hwreg.h"
#include "cam_hw_ops.h"
@@ -42,6 +43,7 @@
#define CSID_VERSION_V34 0x30040000
#define CSID_VERSION_V34_1 0x30040001
#define CSID_VERSION_V34_2 0x30040002
+#define CSID_VERSION_V34_3 0x30040003
#define CSID_VERSION_V36 0x30060000
#define CSID_VERSION_V37 0x30070000
#define CSID_VERSION_V35 0x30050000
@@ -1179,6 +1181,12 @@
new_csid_dev->ctrl_reg->csid_lane_assign =
csid_lane_assign_v3_4_2;
} else if (of_device_is_compatible(new_csid_dev->pdev->dev.of_node,
+ "qcom,csid-v3.4.3")) {
+ new_csid_dev->ctrl_reg->csid_reg = csid_v3_4_3;
+ new_csid_dev->hw_dts_version = CSID_VERSION_V34_3;
+ new_csid_dev->ctrl_reg->csid_lane_assign =
+ csid_lane_assign_v3_4_3;
+ } else if (of_device_is_compatible(new_csid_dev->pdev->dev.of_node,
"qcom,csid-v3.6.0")) {
new_csid_dev->ctrl_reg->csid_reg = csid_v3_6_0;
new_csid_dev->hw_dts_version = CSID_VERSION_V36;
diff --git a/drivers/media/platform/msm/camera_v2/sensor/csiphy/msm_csiphy.c b/drivers/media/platform/msm/camera_v2/sensor/csiphy/msm_csiphy.c
index 5f56676..0cfddb3 100644
--- a/drivers/media/platform/msm/camera_v2/sensor/csiphy/msm_csiphy.c
+++ b/drivers/media/platform/msm/camera_v2/sensor/csiphy/msm_csiphy.c
@@ -2089,7 +2089,10 @@
rc = -EFAULT;
break;
}
- csiphy_dev->csiphy_sof_debug = SOF_DEBUG_DISABLE;
+ if (csiphy_dev->csiphy_sof_debug == SOF_DEBUG_ENABLE) {
+ csiphy_dev->csiphy_sof_debug = SOF_DEBUG_DISABLE;
+ rc = msm_camera_enable_irq(csiphy_dev->irq, false);
+ }
rc = msm_csiphy_lane_config(csiphy_dev, &csiphy_params);
break;
case CSIPHY_RELEASE:
diff --git a/drivers/media/platform/msm/camera_v2/sensor/msm_sensor.c b/drivers/media/platform/msm/camera_v2/sensor/msm_sensor.c
index c0c83e5..6f39956 100644
--- a/drivers/media/platform/msm/camera_v2/sensor/msm_sensor.c
+++ b/drivers/media/platform/msm/camera_v2/sensor/msm_sensor.c
@@ -82,9 +82,13 @@
int32_t msm_sensor_free_sensor_data(struct msm_sensor_ctrl_t *s_ctrl)
{
+ struct msm_camera_sensor_slave_info *slave_info = NULL;
+
if (!s_ctrl->pdev && !s_ctrl->sensor_i2c_client->client)
return 0;
kfree(s_ctrl->sensordata->slave_info);
+ slave_info = s_ctrl->sensordata->cam_slave_info;
+ kfree(slave_info->sensor_id_info.setting.reg_setting);
kfree(s_ctrl->sensordata->cam_slave_info);
kfree(s_ctrl->sensordata->actuator_info);
kfree(s_ctrl->sensordata->power_info.gpio_conf->gpio_num_info);
@@ -261,6 +265,17 @@
return -EINVAL;
}
+ if (slave_info->setting && slave_info->setting->size > 0) {
+ rc = s_ctrl->sensor_i2c_client->i2c_func_tbl->
+ i2c_write_table(s_ctrl->sensor_i2c_client,
+ slave_info->setting);
+ if (rc < 0)
+ pr_err("Write array failed prior to probe\n");
+
+ } else {
+ CDBG("No writes needed for this sensor before probe\n");
+ }
+
rc = sensor_i2c_client->i2c_func_tbl->i2c_read(
sensor_i2c_client, slave_info->sensor_id_reg_addr,
&chipid, MSM_CAMERA_I2C_WORD_DATA);
diff --git a/drivers/media/platform/msm/camera_v2/sensor/msm_sensor_driver.c b/drivers/media/platform/msm/camera_v2/sensor/msm_sensor_driver.c
index f80de3a..7832181 100644
--- a/drivers/media/platform/msm/camera_v2/sensor/msm_sensor_driver.c
+++ b/drivers/media/platform/msm/camera_v2/sensor/msm_sensor_driver.c
@@ -757,6 +757,8 @@
unsigned long mount_pos = 0;
uint32_t is_yuv;
+ struct msm_camera_i2c_reg_array *reg_setting = NULL;
+ struct msm_sensor_id_info_t *id_info = NULL;
/* Validate input parameters */
if (!setting) {
@@ -805,7 +807,54 @@
slave_info->camera_id = slave_info32->camera_id;
slave_info->i2c_freq_mode = slave_info32->i2c_freq_mode;
- slave_info->sensor_id_info = slave_info32->sensor_id_info;
+ slave_info->sensor_id_info.sensor_id_reg_addr =
+ slave_info32->sensor_id_info.sensor_id_reg_addr;
+ slave_info->sensor_id_info.sensor_id_mask =
+ slave_info32->sensor_id_info.sensor_id_mask;
+ slave_info->sensor_id_info.sensor_id =
+ slave_info32->sensor_id_info.sensor_id;
+
+ slave_info->sensor_id_info.setting.addr_type =
+ slave_info32->sensor_id_info.setting.addr_type;
+ slave_info->sensor_id_info.setting.data_type =
+ slave_info32->sensor_id_info.setting.data_type;
+ slave_info->sensor_id_info.setting.delay =
+ slave_info32->sensor_id_info.setting.delay;
+ slave_info->sensor_id_info.setting.size =
+ slave_info32->sensor_id_info.setting.size;
+
+ if (!slave_info->sensor_id_info.setting.size ||
+ (slave_info->sensor_id_info.setting.size >
+ I2C_REG_DATA_MAX)) {
+ CDBG("%s:No writes needed to probe\n", __func__);
+ slave_info->sensor_id_info.setting.reg_setting = NULL;
+ } else {
+ id_info = &(slave_info->sensor_id_info);
+ reg_setting =
+ kzalloc(id_info->setting.size *
+ (sizeof
+ (struct msm_camera_i2c_reg_array)),
+ GFP_KERNEL);
+ if (!reg_setting) {
+ rc = -ENOMEM;
+ goto free_slave_info;
+ }
+ if (copy_from_user(reg_setting,
+ (void __user *)
+ compat_ptr(slave_info32->sensor_id_info.
+ setting.reg_setting),
+ slave_info->sensor_id_info.setting.size *
+ sizeof(struct msm_camera_i2c_reg_array))) {
+ pr_err("%s:%d: sensor id info copy failed\n",
+ __func__, __LINE__);
+ kfree(reg_setting);
+ rc = -EFAULT;
+ goto free_slave_info;
+ }
+
+ slave_info->sensor_id_info.setting.reg_setting =
+ reg_setting;
+ }
slave_info->slave_addr = slave_info32->slave_addr;
slave_info->power_setting_array.size =
@@ -841,6 +890,37 @@
rc = -EFAULT;
goto free_slave_info;
}
+ if (!slave_info->sensor_id_info.setting.size ||
+ slave_info->sensor_id_info.setting.size >
+ I2C_REG_DATA_MAX) {
+ CDBG("%s:No writes needed to probe\n", __func__);
+ slave_info->sensor_id_info.setting.reg_setting = NULL;
+ } else {
+ id_info = &(slave_info->sensor_id_info);
+ reg_setting =
+ kzalloc(id_info->setting.size *
+ (sizeof
+ (struct msm_camera_i2c_reg_array)),
+ GFP_KERNEL);
+ if (!reg_setting) {
+ rc = -ENOMEM;
+ goto free_slave_info;
+ }
+ if (copy_from_user(reg_setting,
+ (void __user *)
+ slave_info->sensor_id_info.setting.reg_setting,
+ slave_info->sensor_id_info.setting.size *
+ sizeof(struct msm_camera_i2c_reg_array))) {
+ pr_err("%s:%d: sensor id info copy failed\n",
+ __func__, __LINE__);
+ kfree(reg_setting);
+ rc = -EFAULT;
+ goto free_slave_info;
+ }
+
+ slave_info->sensor_id_info.setting.reg_setting =
+ reg_setting;
+ }
}
if (strlen(slave_info->sensor_name) >= MAX_SENSOR_NAME ||
@@ -956,6 +1036,7 @@
slave_info->sensor_id_info.sensor_id_reg_addr;
camera_info->sensor_id = slave_info->sensor_id_info.sensor_id;
camera_info->sensor_id_mask = slave_info->sensor_id_info.sensor_id_mask;
+ camera_info->setting = &(slave_info->sensor_id_info.setting);
/* Fill CCI master, slave address and CCI default params */
if (!s_ctrl->sensor_i2c_client) {
@@ -1116,6 +1197,7 @@
free_camera_info:
kfree(camera_info);
free_slave_info:
+ kfree(slave_info->sensor_id_info.setting.reg_setting);
kfree(slave_info);
return rc;
}
diff --git a/drivers/media/platform/msm/sde/rotator/sde_rotator_dev.c b/drivers/media/platform/msm/sde/rotator/sde_rotator_dev.c
index 48ef46c..c0566a3 100644
--- a/drivers/media/platform/msm/sde/rotator/sde_rotator_dev.c
+++ b/drivers/media/platform/msm/sde/rotator/sde_rotator_dev.c
@@ -3733,6 +3733,7 @@
.name = SDE_ROTATOR_DRV_NAME,
.of_match_table = sde_rotator_dt_match,
.pm = &sde_rotator_pm_ops,
+ .suppress_bind_attrs = true,
},
};
diff --git a/drivers/media/platform/msm/vidc/msm_venc.c b/drivers/media/platform/msm/vidc/msm_venc.c
index ee643b1..e6a4ed30 100644
--- a/drivers/media/platform/msm/vidc/msm_venc.c
+++ b/drivers/media/platform/msm/vidc/msm_venc.c
@@ -1548,10 +1548,6 @@
}
case V4L2_CID_MPEG_VIDC_IMG_GRID_DIMENSION:
{
- int i = 0, j = 0;
- u32 width = 0, height = 0;
- u32 trows, tcols;
-
property_id = HAL_CONFIG_HEIC_GRID_ENABLE;
if (inst->fmts[CAPTURE_PORT].fourcc != V4L2_PIX_FMT_HEVC) {
dprintk(VIDC_ERR, "Grid is supported only for HEVC\n");
@@ -1566,38 +1562,6 @@
grid_enable.grid_enable = ctrl->val;
inst->img_grid_dimension = ctrl->val;
pdata = &grid_enable;
-
- /* Update tile info table */
- width = inst->prop.width[OUTPUT_PORT];
- height = inst->prop.height[OUTPUT_PORT];
- tcols = (width + inst->img_grid_dimension - 1) /
- inst->img_grid_dimension;
- trows = (height + inst->img_grid_dimension - 1) /
- inst->img_grid_dimension;
- inst->tinfo.count = trows * tcols;
- if (inst->tinfo.count > MAX_HEIC_TILES_COUNT) {
- dprintk(VIDC_ERR, "Tiles count exceeds maximum\n");
- rc = -ENOTSUPP;
- break;
- }
-
- dprintk(VIDC_DBG,
- "Grid dimension %d width %d height %d row %d col %d\n",
- inst->img_grid_dimension, width, height,
- trows, tcols);
-
- for (j = 0; j < trows; ++j) {
- for (i = 0; i < tcols; ++i) {
- inst->tinfo.tile_rects[j*tcols+i].left =
- (i * inst->img_grid_dimension);
- inst->tinfo.tile_rects[j*tcols+i].top =
- (j * inst->img_grid_dimension);
- inst->tinfo.tile_rects[j*tcols+i].width =
- inst->img_grid_dimension;
- inst->tinfo.tile_rects[j*tcols+i].height =
- inst->img_grid_dimension;
- }
- }
break;
}
case V4L2_CID_MPEG_VIDEO_BITRATE_PEAK:
diff --git a/drivers/media/platform/msm/vidc/msm_vidc.c b/drivers/media/platform/msm/vidc/msm_vidc.c
index 8e32504..651d0a2 100644
--- a/drivers/media/platform/msm/vidc/msm_vidc.c
+++ b/drivers/media/platform/msm/vidc/msm_vidc.c
@@ -901,6 +901,51 @@
return rc;
}
+static int msm_vidc_create_tile_info_table(struct msm_vidc_inst *inst)
+{
+ int i = 0, j = 0;
+ u32 width = 0, height = 0;
+ u32 trows = 0, tcols = 0;
+
+ /* Don't create table for non-HEIC formats*/
+ if (inst->img_grid_dimension <= 0 ||
+ inst->fmts[CAPTURE_PORT].fourcc != V4L2_PIX_FMT_HEVC)
+ return 0;
+
+ width = inst->prop.width[OUTPUT_PORT];
+ height = inst->prop.height[OUTPUT_PORT];
+ tcols = (width + inst->img_grid_dimension - 1) /
+ inst->img_grid_dimension;
+ trows = (height + inst->img_grid_dimension - 1) /
+ inst->img_grid_dimension;
+ inst->tinfo.count = trows * tcols;
+ if (inst->tinfo.count > MAX_HEIC_TILES_COUNT) {
+ dprintk(VIDC_ERR,
+ "Tiles count (%d) exceeds maximum\n",
+ inst->tinfo.count);
+ return -ENOTSUPP;
+ }
+
+ dprintk(VIDC_DBG,
+ "Grid dimension %d width %d height %d row %d col %d\n",
+ inst->img_grid_dimension, width, height,
+ trows, tcols);
+
+ for (j = 0; j < trows; ++j) {
+ for (i = 0; i < tcols; ++i) {
+ inst->tinfo.tile_rects[j*tcols+i].left =
+ (i * inst->img_grid_dimension);
+ inst->tinfo.tile_rects[j*tcols+i].top =
+ (j * inst->img_grid_dimension);
+ inst->tinfo.tile_rects[j*tcols+i].width =
+ inst->img_grid_dimension;
+ inst->tinfo.tile_rects[j*tcols+i].height =
+ inst->img_grid_dimension;
+ }
+ }
+ return 0;
+}
+
static inline int start_streaming(struct msm_vidc_inst *inst)
{
int rc = 0;
@@ -909,6 +954,13 @@
hdev = inst->core->device;
+ /* Create tile info table */
+ rc = msm_vidc_create_tile_info_table(inst);
+ if (rc) {
+ dprintk(VIDC_ERR, "Tile info table was not generated\n");
+ goto fail_start;
+ }
+
/* Check if current session is under HW capability */
rc = msm_vidc_check_session_supported(inst);
if (rc) {
diff --git a/drivers/media/platform/msm/vidc/msm_vidc_common.c b/drivers/media/platform/msm/vidc/msm_vidc_common.c
index 40c9862..d77ea21 100644
--- a/drivers/media/platform/msm/vidc/msm_vidc_common.c
+++ b/drivers/media/platform/msm/vidc/msm_vidc_common.c
@@ -2361,6 +2361,17 @@
return 0;
}
+static bool is_heic_encode_session(struct msm_vidc_inst *inst)
+{
+ if (inst->session_type == MSM_VIDC_ENCODER &&
+ (get_hal_codec(inst->fmts[CAPTURE_PORT].fourcc) ==
+ HAL_VIDEO_CODEC_HEVC) &&
+ (inst->img_grid_dimension > 0))
+ return true;
+ else
+ return false;
+}
+
static bool is_eos_buffer(struct msm_vidc_inst *inst, u32 device_addr)
{
struct eos_buf *temp, *next;
@@ -2406,10 +2417,7 @@
}
empty_buf_done = (struct vidc_hal_ebd *)&response->input_done;
- if (inst->session_type == MSM_VIDC_ENCODER &&
- (get_hal_codec(inst->fmts[CAPTURE_PORT].fourcc) ==
- HAL_VIDEO_CODEC_HEVC) &&
- (inst->img_grid_dimension > 0) &&
+ if (is_heic_encode_session(inst) &&
(empty_buf_done->input_tag < inst->tinfo.count - 1)) {
dprintk(VIDC_DBG, "Wait for last tile. Current tile no: %d\n",
empty_buf_done->input_tag);
@@ -3154,10 +3162,11 @@
static void msm_vidc_print_running_insts(struct msm_vidc_core *core)
{
struct msm_vidc_inst *temp;
+ int op_rate = 0;
dprintk(VIDC_ERR, "Running instances:\n");
- dprintk(VIDC_ERR, "%4s|%4s|%4s|%4s|%4s\n",
- "type", "w", "h", "fps", "prop");
+ dprintk(VIDC_ERR, "%4s|%4s|%4s|%4s|%6s|%4s\n",
+ "type", "w", "h", "fps", "opr", "prop");
mutex_lock(&core->lock);
list_for_each_entry(temp, &core->instances, list) {
@@ -3171,13 +3180,21 @@
if (msm_comm_turbo_session(temp))
strlcat(properties, "T", sizeof(properties));
- dprintk(VIDC_ERR, "%4d|%4d|%4d|%4d|%4s\n",
+ if (is_realtime_session(temp))
+ strlcat(properties, "R", sizeof(properties));
+
+ if (temp->clk_data.operating_rate)
+ op_rate = temp->clk_data.operating_rate >> 16;
+ else
+ op_rate = temp->prop.fps;
+
+ dprintk(VIDC_ERR, "%4d|%4d|%4d|%4d|%6d|%4s\n",
temp->session_type,
max(temp->prop.width[CAPTURE_PORT],
temp->prop.width[OUTPUT_PORT]),
max(temp->prop.height[CAPTURE_PORT],
temp->prop.height[OUTPUT_PORT]),
- temp->prop.fps, properties);
+ temp->prop.fps, op_rate, properties);
}
}
mutex_unlock(&core->lock);
@@ -4425,10 +4442,7 @@
for (c = 0; c < etbs.count; ++c) {
struct vidc_frame_data *frame_data = &etbs.data[c];
- if (inst->session_type == MSM_VIDC_ENCODER &&
- get_hal_codec(inst->fmts[CAPTURE_PORT].fourcc)
- == HAL_VIDEO_CODEC_HEVC &&
- (inst->img_grid_dimension > 0)) {
+ if (is_heic_encode_session(inst)) {
rc = msm_comm_qbuf_heic_tiles(inst, frame_data);
if (rc) {
dprintk(VIDC_ERR,
@@ -5506,6 +5520,11 @@
u32 input_height, input_width, output_height, output_width;
u32 rotation;
+ if (is_heic_encode_session(inst)) {
+ dprintk(VIDC_DBG, "Skip downscale check for HEIC\n");
+ return 0;
+ }
+
input_height = inst->prop.height[OUTPUT_PORT];
input_width = inst->prop.width[OUTPUT_PORT];
output_height = inst->prop.height[CAPTURE_PORT];
diff --git a/drivers/media/platform/msm/vidc/msm_vidc_res_parse.c b/drivers/media/platform/msm/vidc/msm_vidc_res_parse.c
index 530fe3a..1dc6723 100644
--- a/drivers/media/platform/msm/vidc/msm_vidc_res_parse.c
+++ b/drivers/media/platform/msm/vidc/msm_vidc_res_parse.c
@@ -25,6 +25,7 @@
enum clock_properties {
CLOCK_PROP_HAS_SCALING = 1 << 0,
CLOCK_PROP_HAS_MEM_RETENTION = 1 << 1,
+ CLOCK_PROP_DISABLE_MEMCORE_ONLY = 1 << 2,
};
#define PERF_GOV "performance"
@@ -666,6 +667,11 @@
else
vc->has_mem_retention = false;
+ if (clock_props[c] & CLOCK_PROP_DISABLE_MEMCORE_ONLY)
+ vc->disable_memcore_only = true;
+ else
+ vc->disable_memcore_only = false;
+
dprintk(VIDC_DBG, "Found clock %s: scale-able = %s\n", vc->name,
vc->count ? "yes" : "no");
}
diff --git a/drivers/media/platform/msm/vidc/msm_vidc_resources.h b/drivers/media/platform/msm/vidc/msm_vidc_resources.h
index 23e33fe..06d8fa5 100644
--- a/drivers/media/platform/msm/vidc/msm_vidc_resources.h
+++ b/drivers/media/platform/msm/vidc/msm_vidc_resources.h
@@ -1,4 +1,4 @@
-/* Copyright (c) 2013-2017, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2013-2018, The Linux Foundation. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 and
@@ -90,6 +90,7 @@
u32 count;
bool has_scaling;
bool has_mem_retention;
+ bool disable_memcore_only;
};
struct clock_set {
diff --git a/drivers/media/platform/msm/vidc/venus_hfi.c b/drivers/media/platform/msm/vidc/venus_hfi.c
index ade04e3..79ed798 100644
--- a/drivers/media/platform/msm/vidc/venus_hfi.c
+++ b/drivers/media/platform/msm/vidc/venus_hfi.c
@@ -1097,6 +1097,8 @@
int rc = 0;
venus_hfi_for_each_clock(device, cl) {
+ if (cl->disable_memcore_only)
+ continue;
if (cl->has_scaling) {/* has_scaling */
device->clk_freq = freq;
rc = clk_set_rate(cl->clk, freq);
@@ -3362,6 +3364,8 @@
}
venus_hfi_for_each_clock_reverse(device, cl) {
+ if (cl->disable_memcore_only)
+ continue;
dprintk(VIDC_DBG, "Clock: %s disable and unprepare\n",
cl->name);
rc = clk_set_flags(cl->clk, CLKFLAG_NORETAIN_PERIPH);
@@ -3391,6 +3395,11 @@
}
venus_hfi_for_each_clock(device, cl) {
+ /* MEM CORE is ON by default. Unset it for unused clocks*/
+ if (cl->disable_memcore_only) {
+ clk_set_flags(cl->clk, CLKFLAG_NORETAIN_MEM);
+ continue;
+ }
/*
* For the clocks we control, set the rate prior to preparing
* them. Since we don't really have a load at this point, scale
@@ -3428,6 +3437,8 @@
fail_clk_enable:
venus_hfi_for_each_clock_reverse_continue(device, cl, c) {
+ if (cl->disable_memcore_only)
+ continue;
dprintk(VIDC_ERR, "Clock: %s disable and unprepare\n",
cl->name);
clk_disable_unprepare(cl->clk);
@@ -3521,7 +3532,6 @@
devfreq_suspend_device(bus->devfreq);
}
- device->bus_vote = DEFAULT_BUS_VOTE;
return 0;
err_add_dev:
diff --git a/drivers/media/platform/msm/vidc/vidc_hfi_helper.h b/drivers/media/platform/msm/vidc/vidc_hfi_helper.h
index f4ea86b..dd94a88 100644
--- a/drivers/media/platform/msm/vidc/vidc_hfi_helper.h
+++ b/drivers/media/platform/msm/vidc/vidc_hfi_helper.h
@@ -492,6 +492,7 @@
struct hfi_heic_frame_quality {
u32 frame_quality;
+ u32 reserved[3];
};
struct hfi_heic_grid_enable {
diff --git a/drivers/media/platform/s3c-camif/camif-capture.c b/drivers/media/platform/s3c-camif/camif-capture.c
index 0413a86..5c9db09 100644
--- a/drivers/media/platform/s3c-camif/camif-capture.c
+++ b/drivers/media/platform/s3c-camif/camif-capture.c
@@ -1256,16 +1256,17 @@
{
const struct s3c_camif_variant *variant = camif->variant;
const struct vp_pix_limits *pix_lim;
- int i = ARRAY_SIZE(camif_mbus_formats);
+ unsigned int i;
/* FIXME: constraints against codec or preview path ? */
pix_lim = &variant->vp_pix_limits[VP_CODEC];
- while (i-- >= 0)
+ for (i = 0; i < ARRAY_SIZE(camif_mbus_formats); i++)
if (camif_mbus_formats[i] == mf->code)
break;
- mf->code = camif_mbus_formats[i];
+ if (i == ARRAY_SIZE(camif_mbus_formats))
+ mf->code = camif_mbus_formats[0];
if (pad == CAMIF_SD_PAD_SINK) {
v4l_bound_align_image(&mf->width, 8, CAMIF_MAX_PIX_WIDTH,
diff --git a/drivers/media/platform/vivid/vivid-ctrls.c b/drivers/media/platform/vivid/vivid-ctrls.c
index aceb38d..b1c3725 100644
--- a/drivers/media/platform/vivid/vivid-ctrls.c
+++ b/drivers/media/platform/vivid/vivid-ctrls.c
@@ -1167,6 +1167,7 @@
v4l2_ctrl_activate(dev->radio_rx_rds_ta, dev->radio_rx_rds_controls);
v4l2_ctrl_activate(dev->radio_rx_rds_tp, dev->radio_rx_rds_controls);
v4l2_ctrl_activate(dev->radio_rx_rds_ms, dev->radio_rx_rds_controls);
+ dev->radio_rx_dev.device_caps = dev->radio_rx_caps;
break;
case V4L2_CID_RDS_RECEPTION:
dev->radio_rx_rds_enabled = ctrl->val;
@@ -1241,6 +1242,7 @@
dev->radio_tx_caps &= ~V4L2_CAP_READWRITE;
if (!dev->radio_tx_rds_controls)
dev->radio_tx_caps |= V4L2_CAP_READWRITE;
+ dev->radio_tx_dev.device_caps = dev->radio_tx_caps;
break;
case V4L2_CID_RDS_TX_PTY:
if (dev->radio_rx_rds_controls)
diff --git a/drivers/media/usb/em28xx/em28xx.h b/drivers/media/usb/em28xx/em28xx.h
index d148463..6bf48a7 100644
--- a/drivers/media/usb/em28xx/em28xx.h
+++ b/drivers/media/usb/em28xx/em28xx.h
@@ -189,7 +189,7 @@
USB 2.0 spec says bulk packet size is always 512 bytes
*/
#define EM28XX_BULK_PACKET_MULTIPLIER 384
-#define EM28XX_DVB_BULK_PACKET_MULTIPLIER 384
+#define EM28XX_DVB_BULK_PACKET_MULTIPLIER 94
#define EM28XX_INTERLACED_DEFAULT 1
diff --git a/drivers/media/v4l2-core/videobuf2-vmalloc.c b/drivers/media/v4l2-core/videobuf2-vmalloc.c
index ab3227b..760cbf2 100644
--- a/drivers/media/v4l2-core/videobuf2-vmalloc.c
+++ b/drivers/media/v4l2-core/videobuf2-vmalloc.c
@@ -104,7 +104,7 @@
if (nums[i-1] + 1 != nums[i])
goto fail_map;
buf->vaddr = (__force void *)
- ioremap_nocache(nums[0] << PAGE_SHIFT, size);
+ ioremap_nocache(__pfn_to_phys(nums[0]), size + offset);
} else {
buf->vaddr = vm_map_ram(frame_vector_pages(vec), n_pages, -1,
PAGE_KERNEL);
diff --git a/drivers/message/fusion/mptctl.c b/drivers/message/fusion/mptctl.c
index 02b5f69..14cf6df 100644
--- a/drivers/message/fusion/mptctl.c
+++ b/drivers/message/fusion/mptctl.c
@@ -2698,6 +2698,8 @@
__FILE__, __LINE__, iocnum);
return -ENODEV;
}
+ if (karg.hdr.id >= MPT_MAX_FC_DEVICES)
+ return -EINVAL;
dctlprintk(ioc, printk(MYIOC_s_DEBUG_FMT "mptctl_hp_targetinfo called.\n",
ioc->name));
diff --git a/drivers/misc/fpr_FingerprintCard/fpc1020_platform_tee.c b/drivers/misc/fpr_FingerprintCard/fpc1020_platform_tee.c
index 887c8eb..a6ed374 100644
--- a/drivers/misc/fpr_FingerprintCard/fpc1020_platform_tee.c
+++ b/drivers/misc/fpr_FingerprintCard/fpc1020_platform_tee.c
@@ -75,8 +75,8 @@
struct fpc1020_data {
struct device *dev;
struct pinctrl *fingerprint_pinctrl;
- struct pinctrl_state **pinctrl_state;
- struct regulator **vreg;
+ struct pinctrl_state *pinctrl_state[ARRAY_SIZE(pctl_names)];
+ struct regulator *vreg[ARRAY_SIZE(vreg_conf)];
struct wakeup_source ttw_wl;
struct mutex lock; /* To set/get exported values in sysfs */
int irq_gpio;
diff --git a/drivers/misc/qseecom.c b/drivers/misc/qseecom.c
index d61f20e..07ae56f 100644
--- a/drivers/misc/qseecom.c
+++ b/drivers/misc/qseecom.c
@@ -4061,8 +4061,11 @@
int retry = 0;
do {
- if (retry++)
+ if (retry++) {
+ mutex_unlock(&app_access_lock);
msleep(QSEECOM_TA_ION_ALLOCATE_DELAY);
+ mutex_lock(&app_access_lock);
+ }
ihandle = ion_alloc(qseecom.ion_clnt, fw_size,
SZ_4K, ION_HEAP(ION_QSECOM_TA_HEAP_ID), 0);
} while (IS_ERR_OR_NULL(ihandle) &&
@@ -4212,8 +4215,12 @@
ret = qseecom_scm_call(SCM_SVC_TZSCHEDULER, 1, cmd_buf, cmd_len,
&resp, sizeof(resp));
if (ret) {
- pr_err("scm_call to load failed : ret %d\n", ret);
- ret = -EIO;
+ pr_err("scm_call to load failed : ret %d, result %x\n",
+ ret, resp.result);
+ if (resp.result == QSEOS_RESULT_FAIL_APP_ALREADY_LOADED)
+ ret = -EEXIST;
+ else
+ ret = -EIO;
goto exit_disable_clk_vote;
}
@@ -4465,6 +4472,7 @@
}
mutex_lock(&app_access_lock);
+recheck:
app_ireq.qsee_cmd_id = QSEOS_APP_LOOKUP_COMMAND;
strlcpy(app_ireq.app_name, app_name, MAX_APP_NAME_SIZE);
ret = __qseecom_check_app_exists(app_ireq, &app_id);
@@ -4494,7 +4502,10 @@
pr_debug("%s: Loading app for the first time'\n",
qseecom.pdev->init_name);
ret = __qseecom_load_fw(data, app_name, &app_id);
- if (ret < 0)
+ if (ret == -EEXIST) {
+ pr_err("recheck if TA %s is loaded\n", app_name);
+ goto recheck;
+ } else if (ret < 0)
goto exit_ion_free;
}
data->client.app_id = app_id;
@@ -8767,6 +8778,7 @@
static int qseecom_remove(struct platform_device *pdev)
{
struct qseecom_registered_kclient_list *kclient = NULL;
+ struct qseecom_registered_kclient_list *kclient_tmp = NULL;
unsigned long flags = 0;
int ret = 0;
int i;
@@ -8776,10 +8788,8 @@
atomic_set(&qseecom.qseecom_state, QSEECOM_STATE_NOT_READY);
spin_lock_irqsave(&qseecom.registered_kclient_list_lock, flags);
- list_for_each_entry(kclient, &qseecom.registered_kclient_list_head,
- list) {
- if (!kclient)
- goto exit_irqrestore;
+ list_for_each_entry_safe(kclient, kclient_tmp,
+ &qseecom.registered_kclient_list_head, list) {
/* Break the loop if client handle is NULL */
if (!kclient->handle)
@@ -8803,7 +8813,7 @@
kzfree(kclient->handle);
exit_free_kclient:
kzfree(kclient);
-exit_irqrestore:
+
spin_unlock_irqrestore(&qseecom.registered_kclient_list_lock, flags);
if (qseecom.qseos_version > QSEEE_VERSION_00)
diff --git a/drivers/mmc/card/block.c b/drivers/mmc/card/block.c
index e1cced6..f78b659 100644
--- a/drivers/mmc/card/block.c
+++ b/drivers/mmc/card/block.c
@@ -4099,6 +4099,13 @@
if (ret == -EBUSY || ret == -EAGAIN) {
mmc_blk_cmdq_requeue_rw_rq(mq, req);
mmc_put_card(host->card);
+ } else if (ret == -ENOMEM) {
+ /*
+ * Elaborate error handling is not needed for
+ * system errors. Let the higher layer decide
+ * on the next steps.
+ */
+ goto out;
}
}
}
@@ -4694,9 +4701,7 @@
dev_set_drvdata(&card->dev, md);
-#ifdef CONFIG_MMC_BLOCK_DEFERRED_RESUME
mmc_set_bus_resume_policy(card->host, 1);
-#endif
if (mmc_add_disk(md))
goto out;
@@ -4741,9 +4746,7 @@
pm_runtime_put_noidle(&card->dev);
mmc_blk_remove_req(md);
dev_set_drvdata(&card->dev, NULL);
-#ifdef CONFIG_MMC_BLOCK_DEFERRED_RESUME
mmc_set_bus_resume_policy(card->host, 0);
-#endif
}
static int _mmc_blk_suspend(struct mmc_card *card, bool wait)
diff --git a/drivers/mmc/core/core.c b/drivers/mmc/core/core.c
index 60f8a6d..69465f8 100644
--- a/drivers/mmc/core/core.c
+++ b/drivers/mmc/core/core.c
@@ -1972,10 +1972,9 @@
*/
void mmc_wait_for_req(struct mmc_host *host, struct mmc_request *mrq)
{
-#ifdef CONFIG_MMC_BLOCK_DEFERRED_RESUME
if (mmc_bus_needs_resume(host))
mmc_resume_bus(host);
-#endif
+
__mmc_start_req(host, mrq);
if (!mrq->cap_cmd_during_tfr)
@@ -2418,10 +2417,9 @@
{
pm_runtime_get_sync(&card->dev);
mmc_claim_host(card->host);
-#ifdef CONFIG_MMC_BLOCK_DEFERRED_RESUME
+
if (mmc_bus_needs_resume(card->host))
mmc_resume_bus(card->host);
-#endif
}
EXPORT_SYMBOL(mmc_get_card);
@@ -3380,6 +3378,7 @@
{
unsigned long flags;
int err = 0;
+ int card_present = true;
if (!mmc_bus_needs_resume(host))
return -EINVAL;
@@ -3390,7 +3389,10 @@
spin_unlock_irqrestore(&host->lock, flags);
mmc_bus_get(host);
- if (host->bus_ops && !host->bus_dead && host->card) {
+ if (host->ops->get_cd)
+ card_present = host->ops->get_cd(host);
+
+ if (host->bus_ops && !host->bus_dead && host->card && card_present) {
mmc_power_up(host, host->card->ocr);
BUG_ON(!host->bus_ops->resume);
err = host->bus_ops->resume(host);
@@ -4718,7 +4720,7 @@
struct mmc_host *host = container_of(
notify_block, struct mmc_host, pm_notify);
unsigned long flags;
- int err = 0;
+ int err = 0, present = 0;
switch (mode) {
case PM_RESTORE_PREPARE:
@@ -4765,8 +4767,12 @@
spin_lock_irqsave(&host->lock, flags);
host->rescan_disable = 0;
+ if (host->ops->get_cd)
+ present = host->ops->get_cd(host);
+
if (mmc_bus_manual_resume(host) &&
- !host->ignore_bus_resume_flags) {
+ !host->ignore_bus_resume_flags &&
+ present) {
spin_unlock_irqrestore(&host->lock, flags);
break;
}
diff --git a/drivers/mmc/core/sd.c b/drivers/mmc/core/sd.c
index 245493e..71a1cfb 100644
--- a/drivers/mmc/core/sd.c
+++ b/drivers/mmc/core/sd.c
@@ -1169,6 +1169,9 @@
*/
static int mmc_sd_alive(struct mmc_host *host)
{
+ if (host->ops->get_cd && !host->ops->get_cd(host))
+ return -ENOMEDIUM;
+
return mmc_send_status(host->card, NULL);
}
@@ -1197,6 +1200,16 @@
return;
}
+ if (mmc_bus_needs_resume(host))
+ mmc_resume_bus(host);
+
+ if (host->ops->get_cd && !host->ops->get_cd(host)) {
+ err = -ENOMEDIUM;
+ mmc_card_set_removed(host->card);
+ mmc_card_clr_suspended(host->card);
+ goto out;
+ }
+
/*
* Just check if our card has been removed.
*/
@@ -1219,6 +1232,7 @@
err = _mmc_detect_card_removed(host);
#endif
+out:
mmc_put_card(host->card);
if (err) {
@@ -1303,6 +1317,11 @@
if (!mmc_card_suspended(host->card))
goto out;
+ if (host->ops->get_cd && !host->ops->get_cd(host)) {
+ mmc_card_clr_suspended(host->card);
+ goto out;
+ }
+
mmc_power_up(host, host->card->ocr);
#ifdef CONFIG_MMC_PARANOID_SD_INIT
retries = 5;
@@ -1400,6 +1419,9 @@
static int mmc_sd_reset(struct mmc_host *host)
{
+ if (host->ops->get_cd && !host->ops->get_cd(host))
+ return -ENOMEDIUM;
+
mmc_power_cycle(host, host->card->ocr);
return mmc_sd_init_card(host, host->card->ocr, host->card);
}
diff --git a/drivers/mmc/core/slot-gpio.c b/drivers/mmc/core/slot-gpio.c
index 91ad946..090f64da 100644
--- a/drivers/mmc/core/slot-gpio.c
+++ b/drivers/mmc/core/slot-gpio.c
@@ -35,6 +35,10 @@
{
/* Schedule a card detection after a debounce timeout */
struct mmc_host *host = dev_id;
+ int present = host->ops->get_cd(host);
+
+ pr_debug("%s: cd gpio irq, gpio state %d (CARD_%s)\n",
+ mmc_hostname(host), present, present?"INSERT":"REMOVAL");
host->trigger_card_event = true;
mmc_detect_change(host, msecs_to_jiffies(200));
diff --git a/drivers/net/ethernet/mellanox/mlx4/main.c b/drivers/net/ethernet/mellanox/mlx4/main.c
index 5411ca4..cb7c3ef 100644
--- a/drivers/net/ethernet/mellanox/mlx4/main.c
+++ b/drivers/net/ethernet/mellanox/mlx4/main.c
@@ -2983,6 +2983,7 @@
mlx4_err(dev, "Failed to create file for port %d\n", port);
devlink_port_unregister(&info->devlink_port);
info->port = -1;
+ return err;
}
sprintf(info->dev_mtu_name, "mlx4_port%d_mtu", port);
@@ -3004,9 +3005,10 @@
&info->port_attr);
devlink_port_unregister(&info->devlink_port);
info->port = -1;
+ return err;
}
- return err;
+ return 0;
}
static void mlx4_cleanup_port_info(struct mlx4_port_info *info)
diff --git a/drivers/net/usb/qmi_wwan.c b/drivers/net/usb/qmi_wwan.c
index 3e893fe..8daf5db 100644
--- a/drivers/net/usb/qmi_wwan.c
+++ b/drivers/net/usb/qmi_wwan.c
@@ -810,6 +810,9 @@
{QMI_FIXED_INTF(0x0846, 0x68a2, 8)},
{QMI_FIXED_INTF(0x12d1, 0x140c, 1)}, /* Huawei E173 */
{QMI_FIXED_INTF(0x12d1, 0x14ac, 1)}, /* Huawei E1820 */
+ {QMI_FIXED_INTF(0x1435, 0xd181, 3)}, /* Wistron NeWeb D18Q1 */
+ {QMI_FIXED_INTF(0x1435, 0xd181, 4)}, /* Wistron NeWeb D18Q1 */
+ {QMI_FIXED_INTF(0x1435, 0xd181, 5)}, /* Wistron NeWeb D18Q1 */
{QMI_FIXED_INTF(0x16d8, 0x6003, 0)}, /* CMOTech 6003 */
{QMI_FIXED_INTF(0x16d8, 0x6007, 0)}, /* CMOTech CHE-628S */
{QMI_FIXED_INTF(0x16d8, 0x6008, 0)}, /* CMOTech CMU-301 */
@@ -942,6 +945,7 @@
{QMI_FIXED_INTF(0x413c, 0x81b6, 8)}, /* Dell Wireless 5811e */
{QMI_FIXED_INTF(0x413c, 0x81b6, 10)}, /* Dell Wireless 5811e */
{QMI_FIXED_INTF(0x03f0, 0x4e1d, 8)}, /* HP lt4111 LTE/EV-DO/HSPA+ Gobi 4G Module */
+ {QMI_FIXED_INTF(0x03f0, 0x9d1d, 1)}, /* HP lt4120 Snapdragon X5 LTE */
{QMI_FIXED_INTF(0x22de, 0x9061, 3)}, /* WeTelecom WPD-600N */
{QMI_FIXED_INTF(0x1e0e, 0x9001, 5)}, /* SIMCom 7230E */
{QMI_QUIRK_SET_DTR(0x2c7c, 0x0125, 4)}, /* Quectel EC25, EC20 R2.0 Mini PCIe */
diff --git a/drivers/net/vmxnet3/vmxnet3_drv.c b/drivers/net/vmxnet3/vmxnet3_drv.c
index f809eed..c999b10 100644
--- a/drivers/net/vmxnet3/vmxnet3_drv.c
+++ b/drivers/net/vmxnet3/vmxnet3_drv.c
@@ -369,6 +369,11 @@
gdesc = tq->comp_ring.base + tq->comp_ring.next2proc;
while (VMXNET3_TCD_GET_GEN(&gdesc->tcd) == tq->comp_ring.gen) {
+ /* Prevent any &gdesc->tcd field from being (speculatively)
+ * read before (&gdesc->tcd)->gen is read.
+ */
+ dma_rmb();
+
completed += vmxnet3_unmap_pkt(VMXNET3_TCD_GET_TXIDX(
&gdesc->tcd), tq, adapter->pdev,
adapter);
@@ -1099,6 +1104,11 @@
gdesc->txd.tci = skb_vlan_tag_get(skb);
}
+ /* Ensure that the write to (&gdesc->txd)->gen will be observed after
+ * all other writes to &gdesc->txd.
+ */
+ dma_wmb();
+
/* finally flips the GEN bit of the SOP desc. */
gdesc->dword[2] = cpu_to_le32(le32_to_cpu(gdesc->dword[2]) ^
VMXNET3_TXD_GEN);
@@ -1286,6 +1296,12 @@
*/
break;
}
+
+ /* Prevent any rcd field from being (speculatively) read before
+ * rcd->gen is read.
+ */
+ dma_rmb();
+
BUG_ON(rcd->rqID != rq->qid && rcd->rqID != rq->qid2 &&
rcd->rqID != rq->dataRingQid);
idx = rcd->rxdIdx;
@@ -1515,6 +1531,12 @@
ring->next2comp = idx;
num_to_alloc = vmxnet3_cmd_ring_desc_avail(ring);
ring = rq->rx_ring + ring_idx;
+
+ /* Ensure that the writes to rxd->gen bits will be observed
+ * after all other writes to rxd objects.
+ */
+ dma_wmb();
+
while (num_to_alloc) {
vmxnet3_getRxDesc(rxd, &ring->base[ring->next2fill].rxd,
&rxCmdDesc);
@@ -2675,7 +2697,7 @@
/* ==================== initialization and cleanup routines ============ */
static int
-vmxnet3_alloc_pci_resources(struct vmxnet3_adapter *adapter, bool *dma64)
+vmxnet3_alloc_pci_resources(struct vmxnet3_adapter *adapter)
{
int err;
unsigned long mmio_start, mmio_len;
@@ -2687,30 +2709,12 @@
return err;
}
- if (pci_set_dma_mask(pdev, DMA_BIT_MASK(64)) == 0) {
- if (pci_set_consistent_dma_mask(pdev, DMA_BIT_MASK(64)) != 0) {
- dev_err(&pdev->dev,
- "pci_set_consistent_dma_mask failed\n");
- err = -EIO;
- goto err_set_mask;
- }
- *dma64 = true;
- } else {
- if (pci_set_dma_mask(pdev, DMA_BIT_MASK(32)) != 0) {
- dev_err(&pdev->dev,
- "pci_set_dma_mask failed\n");
- err = -EIO;
- goto err_set_mask;
- }
- *dma64 = false;
- }
-
err = pci_request_selected_regions(pdev, (1 << 2) - 1,
vmxnet3_driver_name);
if (err) {
dev_err(&pdev->dev,
"Failed to request region for adapter: error %d\n", err);
- goto err_set_mask;
+ goto err_enable_device;
}
pci_set_master(pdev);
@@ -2738,7 +2742,7 @@
iounmap(adapter->hw_addr0);
err_ioremap:
pci_release_selected_regions(pdev, (1 << 2) - 1);
-err_set_mask:
+err_enable_device:
pci_disable_device(pdev);
return err;
}
@@ -3246,7 +3250,7 @@
#endif
};
int err;
- bool dma64 = false; /* stupid gcc */
+ bool dma64;
u32 ver;
struct net_device *netdev;
struct vmxnet3_adapter *adapter;
@@ -3292,6 +3296,24 @@
adapter->rx_ring_size = VMXNET3_DEF_RX_RING_SIZE;
adapter->rx_ring2_size = VMXNET3_DEF_RX_RING2_SIZE;
+ if (pci_set_dma_mask(pdev, DMA_BIT_MASK(64)) == 0) {
+ if (pci_set_consistent_dma_mask(pdev, DMA_BIT_MASK(64)) != 0) {
+ dev_err(&pdev->dev,
+ "pci_set_consistent_dma_mask failed\n");
+ err = -EIO;
+ goto err_set_mask;
+ }
+ dma64 = true;
+ } else {
+ if (pci_set_dma_mask(pdev, DMA_BIT_MASK(32)) != 0) {
+ dev_err(&pdev->dev,
+ "pci_set_dma_mask failed\n");
+ err = -EIO;
+ goto err_set_mask;
+ }
+ dma64 = false;
+ }
+
spin_lock_init(&adapter->cmd_lock);
adapter->adapter_pa = dma_map_single(&adapter->pdev->dev, adapter,
sizeof(struct vmxnet3_adapter),
@@ -3299,7 +3321,7 @@
if (dma_mapping_error(&adapter->pdev->dev, adapter->adapter_pa)) {
dev_err(&pdev->dev, "Failed to map dma\n");
err = -EFAULT;
- goto err_dma_map;
+ goto err_set_mask;
}
adapter->shared = dma_alloc_coherent(
&adapter->pdev->dev,
@@ -3350,7 +3372,7 @@
}
#endif /* VMXNET3_RSS */
- err = vmxnet3_alloc_pci_resources(adapter, &dma64);
+ err = vmxnet3_alloc_pci_resources(adapter);
if (err < 0)
goto err_alloc_pci;
@@ -3492,7 +3514,7 @@
err_alloc_shared:
dma_unmap_single(&adapter->pdev->dev, adapter->adapter_pa,
sizeof(struct vmxnet3_adapter), PCI_DMA_TODEVICE);
-err_dma_map:
+err_set_mask:
free_netdev(netdev);
return err;
}
diff --git a/drivers/net/wireless/cnss2/bus.c b/drivers/net/wireless/cnss2/bus.c
index 834ae8a..6a8e67c 100644
--- a/drivers/net/wireless/cnss2/bus.c
+++ b/drivers/net/wireless/cnss2/bus.c
@@ -41,6 +41,38 @@
}
}
+void *cnss_bus_dev_to_bus_priv(struct device *dev)
+{
+ if (!dev)
+ return NULL;
+
+ switch (cnss_get_dev_bus_type(dev)) {
+ case CNSS_BUS_PCI:
+ return cnss_get_pci_priv(to_pci_dev(dev));
+ default:
+ return NULL;
+ }
+}
+
+struct cnss_plat_data *cnss_bus_dev_to_plat_priv(struct device *dev)
+{
+ void *bus_priv;
+
+ if (!dev)
+ return cnss_get_plat_priv(NULL);
+
+ bus_priv = cnss_bus_dev_to_bus_priv(dev);
+ if (!bus_priv)
+ return NULL;
+
+ switch (cnss_get_dev_bus_type(dev)) {
+ case CNSS_BUS_PCI:
+ return cnss_pci_priv_to_plat_priv(bus_priv);
+ default:
+ return NULL;
+ }
+}
+
int cnss_bus_init(struct cnss_plat_data *plat_priv)
{
if (!plat_priv)
@@ -163,3 +195,140 @@
return;
}
}
+
+int cnss_bus_call_driver_probe(struct cnss_plat_data *plat_priv)
+{
+ if (!plat_priv)
+ return -ENODEV;
+
+ switch (plat_priv->bus_type) {
+ case CNSS_BUS_PCI:
+ return cnss_pci_call_driver_probe(plat_priv->bus_priv);
+ default:
+ cnss_pr_err("Unsupported bus type: %d\n",
+ plat_priv->bus_type);
+ return -EINVAL;
+ }
+}
+
+int cnss_bus_call_driver_remove(struct cnss_plat_data *plat_priv)
+{
+ if (!plat_priv)
+ return -ENODEV;
+
+ switch (plat_priv->bus_type) {
+ case CNSS_BUS_PCI:
+ return cnss_pci_call_driver_remove(plat_priv->bus_priv);
+ default:
+ cnss_pr_err("Unsupported bus type: %d\n",
+ plat_priv->bus_type);
+ return -EINVAL;
+ }
+}
+
+int cnss_bus_dev_powerup(struct cnss_plat_data *plat_priv)
+{
+ if (!plat_priv)
+ return -ENODEV;
+
+ switch (plat_priv->bus_type) {
+ case CNSS_BUS_PCI:
+ return cnss_pci_dev_powerup(plat_priv->bus_priv);
+ default:
+ cnss_pr_err("Unsupported bus type: %d\n",
+ plat_priv->bus_type);
+ return -EINVAL;
+ }
+}
+
+int cnss_bus_dev_shutdown(struct cnss_plat_data *plat_priv)
+{
+ if (!plat_priv)
+ return -ENODEV;
+
+ switch (plat_priv->bus_type) {
+ case CNSS_BUS_PCI:
+ return cnss_pci_dev_shutdown(plat_priv->bus_priv);
+ default:
+ cnss_pr_err("Unsupported bus type: %d\n",
+ plat_priv->bus_type);
+ return -EINVAL;
+ }
+}
+
+int cnss_bus_dev_crash_shutdown(struct cnss_plat_data *plat_priv)
+{
+ if (!plat_priv)
+ return -ENODEV;
+
+ switch (plat_priv->bus_type) {
+ case CNSS_BUS_PCI:
+ return cnss_pci_dev_crash_shutdown(plat_priv->bus_priv);
+ default:
+ cnss_pr_err("Unsupported bus type: %d\n",
+ plat_priv->bus_type);
+ return -EINVAL;
+ }
+}
+
+int cnss_bus_dev_ramdump(struct cnss_plat_data *plat_priv)
+{
+ if (!plat_priv)
+ return -ENODEV;
+
+ switch (plat_priv->bus_type) {
+ case CNSS_BUS_PCI:
+ return cnss_pci_dev_ramdump(plat_priv->bus_priv);
+ default:
+ cnss_pr_err("Unsupported bus type: %d\n",
+ plat_priv->bus_type);
+ return -EINVAL;
+ }
+}
+
+int cnss_bus_register_driver_hdlr(struct cnss_plat_data *plat_priv, void *data)
+{
+ if (!plat_priv)
+ return -ENODEV;
+
+ switch (plat_priv->bus_type) {
+ case CNSS_BUS_PCI:
+ return cnss_pci_register_driver_hdlr(plat_priv->bus_priv, data);
+ default:
+ cnss_pr_err("Unsupported bus type: %d\n",
+ plat_priv->bus_type);
+ return -EINVAL;
+ }
+}
+
+int cnss_bus_unregister_driver_hdlr(struct cnss_plat_data *plat_priv)
+{
+ if (!plat_priv)
+ return -ENODEV;
+
+ switch (plat_priv->bus_type) {
+ case CNSS_BUS_PCI:
+ return cnss_pci_unregister_driver_hdlr(plat_priv->bus_priv);
+ default:
+ cnss_pr_err("Unsupported bus type: %d\n",
+ plat_priv->bus_type);
+ return -EINVAL;
+ }
+}
+
+int cnss_bus_call_driver_modem_status(struct cnss_plat_data *plat_priv,
+ int modem_current_status)
+{
+ if (!plat_priv)
+ return -ENODEV;
+
+ switch (plat_priv->bus_type) {
+ case CNSS_BUS_PCI:
+ return cnss_pci_call_driver_modem_status(plat_priv->bus_priv,
+ modem_current_status);
+ default:
+ cnss_pr_err("Unsupported bus type: %d\n",
+ plat_priv->bus_type);
+ return -EINVAL;
+ }
+}
diff --git a/drivers/net/wireless/cnss2/bus.h b/drivers/net/wireless/cnss2/bus.h
index b7aeafa..532438a 100644
--- a/drivers/net/wireless/cnss2/bus.h
+++ b/drivers/net/wireless/cnss2/bus.h
@@ -27,6 +27,8 @@
enum cnss_dev_bus_type cnss_get_dev_bus_type(struct device *dev);
enum cnss_dev_bus_type cnss_get_bus_type(unsigned long device_id);
+void *cnss_bus_dev_to_bus_priv(struct device *dev);
+struct cnss_plat_data *cnss_bus_dev_to_plat_priv(struct device *dev);
int cnss_bus_init(struct cnss_plat_data *plat_priv);
void cnss_bus_deinit(struct cnss_plat_data *plat_priv);
int cnss_bus_load_m3(struct cnss_plat_data *plat_priv);
@@ -36,5 +38,15 @@
void cnss_bus_fw_boot_timeout_hdlr(unsigned long data);
void cnss_bus_collect_dump_info(struct cnss_plat_data *plat_priv,
bool in_panic);
+int cnss_bus_call_driver_probe(struct cnss_plat_data *plat_priv);
+int cnss_bus_call_driver_remove(struct cnss_plat_data *plat_priv);
+int cnss_bus_dev_powerup(struct cnss_plat_data *plat_priv);
+int cnss_bus_dev_shutdown(struct cnss_plat_data *plat_priv);
+int cnss_bus_dev_crash_shutdown(struct cnss_plat_data *plat_priv);
+int cnss_bus_dev_ramdump(struct cnss_plat_data *plat_priv);
+int cnss_bus_register_driver_hdlr(struct cnss_plat_data *plat_priv, void *data);
+int cnss_bus_unregister_driver_hdlr(struct cnss_plat_data *plat_priv);
+int cnss_bus_call_driver_modem_status(struct cnss_plat_data *plat_priv,
+ int modem_current_status);
#endif /* _CNSS_BUS_H */
diff --git a/drivers/net/wireless/cnss2/main.c b/drivers/net/wireless/cnss2/main.c
index 8b4b985..76ad51c 100644
--- a/drivers/net/wireless/cnss2/main.c
+++ b/drivers/net/wireless/cnss2/main.c
@@ -25,7 +25,6 @@
#include "main.h"
#include "bus.h"
#include "debug.h"
-#include "pci.h"
#define CNSS_DUMP_FORMAT_VER 0x11
#define CNSS_DUMP_FORMAT_VER_V2 0x22
@@ -55,13 +54,6 @@
MODULE_PARM_DESC(enable_waltest, "Enable to handle firmware waltest");
#endif
-enum cnss_debug_quirks {
- LINK_DOWN_SELF_RECOVERY,
- SKIP_DEVICE_BOOT,
- USE_CORE_ONLY_FW,
- SKIP_RECOVERY,
-};
-
unsigned long quirks;
#ifdef CONFIG_CNSS2_DEBUG
module_param(quirks, ulong, 0600);
@@ -93,44 +85,11 @@
plat_env = plat_priv;
}
-static struct cnss_plat_data *cnss_get_plat_priv(struct platform_device
- *plat_dev)
+struct cnss_plat_data *cnss_get_plat_priv(struct platform_device *plat_dev)
{
return plat_env;
}
-void *cnss_bus_dev_to_bus_priv(struct device *dev)
-{
- if (!dev)
- return NULL;
-
- switch (cnss_get_dev_bus_type(dev)) {
- case CNSS_BUS_PCI:
- return cnss_get_pci_priv(to_pci_dev(dev));
- default:
- return NULL;
- }
-}
-
-struct cnss_plat_data *cnss_bus_dev_to_plat_priv(struct device *dev)
-{
- void *bus_priv;
-
- if (!dev)
- return cnss_get_plat_priv(NULL);
-
- bus_priv = cnss_bus_dev_to_bus_priv(dev);
- if (!bus_priv)
- return NULL;
-
- switch (cnss_get_dev_bus_type(dev)) {
- case CNSS_BUS_PCI:
- return cnss_pci_priv_to_plat_priv(bus_priv);
- default:
- return NULL;
- }
-}
-
static int cnss_pm_notify(struct notifier_block *b,
unsigned long event, void *p)
{
@@ -475,6 +434,16 @@
}
EXPORT_SYMBOL(cnss_set_fw_log_mode);
+bool *cnss_get_qmi_bypass(void)
+{
+ return &qmi_bypass;
+}
+
+unsigned long *cnss_get_debug_quirks(void)
+{
+ return &quirks;
+}
+
static int cnss_fw_mem_ready_hdlr(struct cnss_plat_data *plat_priv)
{
int ret = 0;
@@ -505,79 +474,6 @@
return ret;
}
-static int cnss_driver_call_probe(struct cnss_plat_data *plat_priv)
-{
- int ret = 0;
- struct cnss_pci_data *pci_priv = plat_priv->bus_priv;
-
- if (test_bit(CNSS_DRIVER_DEBUG, &plat_priv->driver_state)) {
- clear_bit(CNSS_DRIVER_RECOVERY, &plat_priv->driver_state);
- cnss_pr_dbg("Skip driver probe\n");
- goto out;
- }
-
- if (!plat_priv->driver_ops) {
- cnss_pr_err("driver_ops is NULL\n");
- ret = -EINVAL;
- goto out;
- }
-
- if (test_bit(CNSS_DRIVER_RECOVERY, &plat_priv->driver_state) &&
- test_bit(CNSS_DRIVER_PROBED, &plat_priv->driver_state)) {
- ret = plat_priv->driver_ops->reinit(pci_priv->pci_dev,
- pci_priv->pci_device_id);
- if (ret) {
- cnss_pr_err("Failed to reinit host driver, err = %d\n",
- ret);
- goto out;
- }
- clear_bit(CNSS_DRIVER_RECOVERY, &plat_priv->driver_state);
- } else if (test_bit(CNSS_DRIVER_LOADING, &plat_priv->driver_state)) {
- ret = plat_priv->driver_ops->probe(pci_priv->pci_dev,
- pci_priv->pci_device_id);
- if (ret) {
- cnss_pr_err("Failed to probe host driver, err = %d\n",
- ret);
- goto out;
- }
- clear_bit(CNSS_DRIVER_RECOVERY, &plat_priv->driver_state);
- clear_bit(CNSS_DRIVER_LOADING, &plat_priv->driver_state);
- set_bit(CNSS_DRIVER_PROBED, &plat_priv->driver_state);
- }
-
- return 0;
-
-out:
- return ret;
-}
-
-static int cnss_driver_call_remove(struct cnss_plat_data *plat_priv)
-{
- struct cnss_pci_data *pci_priv = plat_priv->bus_priv;
-
- if (test_bit(CNSS_COLD_BOOT_CAL, &plat_priv->driver_state) ||
- test_bit(CNSS_FW_BOOT_RECOVERY, &plat_priv->driver_state) ||
- test_bit(CNSS_DRIVER_DEBUG, &plat_priv->driver_state)) {
- cnss_pr_dbg("Skip driver remove\n");
- return 0;
- }
-
- if (!plat_priv->driver_ops) {
- cnss_pr_err("driver_ops is NULL\n");
- return -EINVAL;
- }
-
- if (test_bit(CNSS_DRIVER_RECOVERY, &plat_priv->driver_state) &&
- test_bit(CNSS_DRIVER_PROBED, &plat_priv->driver_state)) {
- plat_priv->driver_ops->shutdown(pci_priv->pci_dev);
- } else if (test_bit(CNSS_DRIVER_UNLOADING, &plat_priv->driver_state)) {
- plat_priv->driver_ops->remove(pci_priv->pci_dev);
- clear_bit(CNSS_DRIVER_PROBED, &plat_priv->driver_state);
- }
-
- return 0;
-}
-
static int cnss_fw_ready_hdlr(struct cnss_plat_data *plat_priv)
{
int ret = 0;
@@ -601,7 +497,7 @@
QMI_WLFW_CALIBRATION_V01);
} else if (test_bit(CNSS_DRIVER_LOADING, &plat_priv->driver_state) ||
test_bit(CNSS_DRIVER_RECOVERY, &plat_priv->driver_state)) {
- ret = cnss_driver_call_probe(plat_priv);
+ ret = cnss_bus_call_driver_probe(plat_priv);
} else {
complete(&plat_priv->power_up_complete);
}
@@ -614,9 +510,7 @@
return 0;
shutdown:
- cnss_pci_stop_mhi(plat_priv->bus_priv);
- cnss_suspend_pci_link(plat_priv->bus_priv);
- cnss_power_off_device(plat_priv);
+ cnss_bus_dev_shutdown(plat_priv);
clear_bit(CNSS_FW_READY, &plat_priv->driver_state);
clear_bit(CNSS_FW_MEM_READY, &plat_priv->driver_state);
@@ -788,44 +682,6 @@
}
EXPORT_SYMBOL(cnss_power_down);
-int cnss_wlan_register_driver(struct cnss_wlan_driver *driver_ops)
-{
- int ret = 0;
- struct cnss_plat_data *plat_priv = cnss_get_plat_priv(NULL);
-
- if (!plat_priv) {
- cnss_pr_err("plat_priv is NULL!\n");
- return -ENODEV;
- }
-
- if (plat_priv->driver_ops) {
- cnss_pr_err("Driver has already registered!\n");
- return -EEXIST;
- }
-
- ret = cnss_driver_event_post(plat_priv,
- CNSS_DRIVER_EVENT_REGISTER_DRIVER,
- CNSS_EVENT_SYNC_UNINTERRUPTIBLE,
- driver_ops);
- return ret;
-}
-EXPORT_SYMBOL(cnss_wlan_register_driver);
-
-void cnss_wlan_unregister_driver(struct cnss_wlan_driver *driver_ops)
-{
- struct cnss_plat_data *plat_priv = cnss_get_plat_priv(NULL);
-
- if (!plat_priv) {
- cnss_pr_err("plat_priv is NULL!\n");
- return;
- }
-
- cnss_driver_event_post(plat_priv,
- CNSS_DRIVER_EVENT_UNREGISTER_DRIVER,
- CNSS_EVENT_SYNC_UNINTERRUPTIBLE, NULL);
-}
-EXPORT_SYMBOL(cnss_wlan_unregister_driver);
-
static int cnss_get_resources(struct cnss_plat_data *plat_priv)
{
int ret = 0;
@@ -857,13 +713,11 @@
{
struct cnss_plat_data *plat_priv =
container_of(nb, struct cnss_plat_data, modem_nb);
- struct cnss_pci_data *pci_priv = plat_priv->bus_priv;
struct cnss_esoc_info *esoc_info;
- struct cnss_wlan_driver *driver_ops;
cnss_pr_dbg("Modem notifier: event %lu\n", code);
- if (!pci_priv)
+ if (!plat_priv)
return NOTIFY_DONE;
esoc_info = &plat_priv->esoc_info;
@@ -875,13 +729,10 @@
else
return NOTIFY_DONE;
- driver_ops = plat_priv->driver_ops;
- if (!driver_ops || !driver_ops->modem_status)
+ if (!cnss_bus_call_driver_modem_status(plat_priv,
+ esoc_info->modem_current_status))
return NOTIFY_DONE;
- driver_ops->modem_status(pci_priv->pci_dev,
- esoc_info->modem_current_status);
-
return NOTIFY_OK;
}
@@ -955,237 +806,6 @@
devm_unregister_esoc_client(dev, esoc_info->esoc_desc);
}
-static int cnss_qca6174_powerup(struct cnss_plat_data *plat_priv)
-{
- int ret = 0;
- struct cnss_pci_data *pci_priv = plat_priv->bus_priv;
-
- if (!pci_priv) {
- cnss_pr_err("pci_priv is NULL!\n");
- return -ENODEV;
- }
-
- ret = cnss_power_on_device(plat_priv);
- if (ret) {
- cnss_pr_err("Failed to power on device, err = %d\n", ret);
- goto out;
- }
-
- ret = cnss_resume_pci_link(pci_priv);
- if (ret) {
- cnss_pr_err("Failed to resume PCI link, err = %d\n", ret);
- goto power_off;
- }
-
- ret = cnss_driver_call_probe(plat_priv);
- if (ret)
- goto suspend_link;
-
- return 0;
-suspend_link:
- cnss_suspend_pci_link(pci_priv);
-power_off:
- cnss_power_off_device(plat_priv);
-out:
- return ret;
-}
-
-static int cnss_qca6174_shutdown(struct cnss_plat_data *plat_priv)
-{
- int ret = 0;
- struct cnss_pci_data *pci_priv = plat_priv->bus_priv;
-
- if (!pci_priv)
- return -ENODEV;
-
- cnss_pm_request_resume(pci_priv);
-
- cnss_driver_call_remove(plat_priv);
-
- cnss_request_bus_bandwidth(&plat_priv->plat_dev->dev,
- CNSS_BUS_WIDTH_NONE);
- cnss_pci_set_monitor_wake_intr(pci_priv, false);
- cnss_pci_set_auto_suspended(pci_priv, 0);
-
- ret = cnss_suspend_pci_link(pci_priv);
- if (ret)
- cnss_pr_err("Failed to suspend PCI link, err = %d\n", ret);
-
- cnss_power_off_device(plat_priv);
-
- clear_bit(CNSS_DRIVER_UNLOADING, &plat_priv->driver_state);
-
- return ret;
-}
-
-static void cnss_qca6174_crash_shutdown(struct cnss_plat_data *plat_priv)
-{
- struct cnss_pci_data *pci_priv = plat_priv->bus_priv;
-
- if (!plat_priv->driver_ops)
- return;
-
- plat_priv->driver_ops->crash_shutdown(pci_priv->pci_dev);
-}
-
-static int cnss_qca6290_powerup(struct cnss_plat_data *plat_priv)
-{
- int ret = 0;
- struct cnss_pci_data *pci_priv = plat_priv->bus_priv;
- unsigned int timeout;
-
- if (!pci_priv) {
- cnss_pr_err("pci_priv is NULL!\n");
- return -ENODEV;
- }
-
- if (plat_priv->ramdump_info_v2.dump_data_valid ||
- test_bit(CNSS_DRIVER_RECOVERY, &plat_priv->driver_state)) {
- cnss_pci_set_mhi_state(pci_priv, CNSS_MHI_DEINIT);
- cnss_pci_clear_dump_info(pci_priv);
- }
-
- ret = cnss_power_on_device(plat_priv);
- if (ret) {
- cnss_pr_err("Failed to power on device, err = %d\n", ret);
- goto out;
- }
-
- ret = cnss_resume_pci_link(pci_priv);
- if (ret) {
- cnss_pr_err("Failed to resume PCI link, err = %d\n", ret);
- goto power_off;
- }
-
- timeout = cnss_get_qmi_timeout();
-
- ret = cnss_pci_start_mhi(pci_priv);
- if (ret) {
- cnss_pr_err("Failed to start MHI, err = %d\n", ret);
- if (!test_bit(CNSS_DEV_ERR_NOTIFY, &plat_priv->driver_state) &&
- !pci_priv->pci_link_down_ind && timeout)
- mod_timer(&plat_priv->fw_boot_timer,
- jiffies + msecs_to_jiffies(timeout >> 1));
- return 0;
- }
-
- if (test_bit(USE_CORE_ONLY_FW, &quirks)) {
- clear_bit(CNSS_FW_BOOT_RECOVERY, &plat_priv->driver_state);
- clear_bit(CNSS_DRIVER_RECOVERY, &plat_priv->driver_state);
- return 0;
- }
-
- cnss_set_pin_connect_status(plat_priv);
-
- if (qmi_bypass) {
- ret = cnss_driver_call_probe(plat_priv);
- if (ret)
- goto stop_mhi;
- } else if (timeout) {
- mod_timer(&plat_priv->fw_boot_timer,
- jiffies + msecs_to_jiffies(timeout << 1));
- }
-
- return 0;
-
-stop_mhi:
- cnss_pci_stop_mhi(pci_priv);
- cnss_suspend_pci_link(pci_priv);
-power_off:
- cnss_power_off_device(plat_priv);
-out:
- return ret;
-}
-
-static int cnss_qca6290_shutdown(struct cnss_plat_data *plat_priv)
-{
- int ret = 0;
- struct cnss_pci_data *pci_priv = plat_priv->bus_priv;
-
- if (!pci_priv)
- return -ENODEV;
-
- cnss_pm_request_resume(pci_priv);
-
- cnss_driver_call_remove(plat_priv);
-
- cnss_request_bus_bandwidth(&plat_priv->plat_dev->dev,
- CNSS_BUS_WIDTH_NONE);
- cnss_pci_set_monitor_wake_intr(pci_priv, false);
- cnss_pci_set_auto_suspended(pci_priv, 0);
-
- cnss_pci_stop_mhi(pci_priv);
-
- ret = cnss_suspend_pci_link(pci_priv);
- if (ret)
- cnss_pr_err("Failed to suspend PCI link, err = %d\n", ret);
-
- cnss_power_off_device(plat_priv);
-
- clear_bit(CNSS_FW_READY, &plat_priv->driver_state);
- clear_bit(CNSS_FW_MEM_READY, &plat_priv->driver_state);
- clear_bit(CNSS_DRIVER_UNLOADING, &plat_priv->driver_state);
-
- return ret;
-}
-
-static void cnss_qca6290_crash_shutdown(struct cnss_plat_data *plat_priv)
-{
- struct cnss_pci_data *pci_priv = plat_priv->bus_priv;
-
- cnss_pr_dbg("Crash shutdown with driver_state 0x%lx\n",
- plat_priv->driver_state);
-
- if (test_bit(CNSS_DRIVER_RECOVERY, &plat_priv->driver_state)) {
- cnss_pr_dbg("Ignore crash shutdown\n");
- return;
- }
-
- cnss_pci_collect_dump_info(pci_priv, true);
-}
-
-static int cnss_powerup(struct cnss_plat_data *plat_priv)
-{
- int ret;
-
- switch (plat_priv->device_id) {
- case QCA6174_DEVICE_ID:
- ret = cnss_qca6174_powerup(plat_priv);
- break;
- case QCA6290_EMULATION_DEVICE_ID:
- case QCA6290_DEVICE_ID:
- ret = cnss_qca6290_powerup(plat_priv);
- break;
- default:
- cnss_pr_err("Unknown device_id found: 0x%lx\n",
- plat_priv->device_id);
- ret = -ENODEV;
- }
-
- return ret;
-}
-
-static int cnss_shutdown(struct cnss_plat_data *plat_priv)
-{
- int ret;
-
- switch (plat_priv->device_id) {
- case QCA6174_DEVICE_ID:
- ret = cnss_qca6174_shutdown(plat_priv);
- break;
- case QCA6290_EMULATION_DEVICE_ID:
- case QCA6290_DEVICE_ID:
- ret = cnss_qca6290_shutdown(plat_priv);
- break;
- default:
- cnss_pr_err("Unknown device_id found: 0x%lx\n",
- plat_priv->device_id);
- ret = -ENODEV;
- }
-
- return ret;
-}
-
static int cnss_subsys_powerup(const struct subsys_desc *subsys_desc)
{
struct cnss_plat_data *plat_priv;
@@ -1206,7 +826,7 @@
return 0;
}
- return cnss_powerup(plat_priv);
+ return cnss_bus_dev_powerup(plat_priv);
}
static int cnss_subsys_shutdown(const struct subsys_desc *subsys_desc,
@@ -1230,110 +850,9 @@
return 0;
}
- return cnss_shutdown(plat_priv);
+ return cnss_bus_dev_shutdown(plat_priv);
}
-static int cnss_qca6290_ramdump(struct cnss_plat_data *plat_priv)
-{
- struct cnss_ramdump_info_v2 *info_v2 = &plat_priv->ramdump_info_v2;
- struct cnss_dump_data *dump_data = &info_v2->dump_data;
- struct cnss_dump_seg *dump_seg = info_v2->dump_data_vaddr;
- struct ramdump_segment *ramdump_segs, *s;
- int i, ret = 0;
-
- if (!info_v2->dump_data_valid ||
- dump_data->nentries == 0)
- return 0;
-
- ramdump_segs = kcalloc(dump_data->nentries,
- sizeof(*ramdump_segs),
- GFP_KERNEL);
- if (!ramdump_segs)
- return -ENOMEM;
-
- s = ramdump_segs;
- for (i = 0; i < dump_data->nentries; i++) {
- s->address = dump_seg->address;
- s->v_address = dump_seg->v_address;
- s->size = dump_seg->size;
- s++;
- dump_seg++;
- }
-
- ret = do_elf_ramdump(info_v2->ramdump_dev, ramdump_segs,
- dump_data->nentries);
- kfree(ramdump_segs);
-
- cnss_pci_set_mhi_state(plat_priv->bus_priv, CNSS_MHI_DEINIT);
- cnss_pci_clear_dump_info(plat_priv->bus_priv);
-
- return ret;
-}
-
-static int cnss_qca6174_ramdump(struct cnss_plat_data *plat_priv)
-{
- int ret = 0;
- struct cnss_ramdump_info *ramdump_info;
- struct ramdump_segment segment;
-
- ramdump_info = &plat_priv->ramdump_info;
- if (!ramdump_info->ramdump_size)
- return -EINVAL;
-
- memset(&segment, 0, sizeof(segment));
- segment.v_address = ramdump_info->ramdump_va;
- segment.size = ramdump_info->ramdump_size;
- ret = do_ramdump(ramdump_info->ramdump_dev, &segment, 1);
-
- return ret;
-}
-
-static int cnss_subsys_ramdump(int enable,
- const struct subsys_desc *subsys_desc)
-{
- int ret = 0;
- struct cnss_plat_data *plat_priv = dev_get_drvdata(subsys_desc->dev);
-
- if (!plat_priv) {
- cnss_pr_err("plat_priv is NULL!\n");
- return -ENODEV;
- }
-
- if (!enable)
- return 0;
-
- switch (plat_priv->device_id) {
- case QCA6174_DEVICE_ID:
- ret = cnss_qca6174_ramdump(plat_priv);
- break;
- case QCA6290_EMULATION_DEVICE_ID:
- case QCA6290_DEVICE_ID:
- ret = cnss_qca6290_ramdump(plat_priv);
- break;
- default:
- cnss_pr_err("Unknown device_id found: 0x%lx\n",
- plat_priv->device_id);
- ret = -ENODEV;
- }
-
- return ret;
-}
-
-void *cnss_get_virt_ramdump_mem(struct device *dev, unsigned long *size)
-{
- struct cnss_plat_data *plat_priv = cnss_bus_dev_to_plat_priv(dev);
- struct cnss_ramdump_info *ramdump_info;
-
- if (!plat_priv)
- return NULL;
-
- ramdump_info = &plat_priv->ramdump_info;
- *size = ramdump_info->ramdump_size;
-
- return ramdump_info->ramdump_va;
-}
-EXPORT_SYMBOL(cnss_get_virt_ramdump_mem);
-
void cnss_device_crashed(struct device *dev)
{
struct cnss_plat_data *plat_priv = cnss_bus_dev_to_plat_priv(dev);
@@ -1356,24 +875,44 @@
struct cnss_plat_data *plat_priv = dev_get_drvdata(subsys_desc->dev);
if (!plat_priv) {
- cnss_pr_err("plat_priv is NULL!\n");
+ cnss_pr_err("plat_priv is NULL\n");
return;
}
- switch (plat_priv->device_id) {
- case QCA6174_DEVICE_ID:
- cnss_qca6174_crash_shutdown(plat_priv);
- break;
- case QCA6290_EMULATION_DEVICE_ID:
- case QCA6290_DEVICE_ID:
- cnss_qca6290_crash_shutdown(plat_priv);
- break;
- default:
- cnss_pr_err("Unknown device_id found: 0x%lx\n",
- plat_priv->device_id);
- }
+ cnss_bus_dev_crash_shutdown(plat_priv);
}
+static int cnss_subsys_ramdump(int enable,
+ const struct subsys_desc *subsys_desc)
+{
+ struct cnss_plat_data *plat_priv = dev_get_drvdata(subsys_desc->dev);
+
+ if (!plat_priv) {
+ cnss_pr_err("plat_priv is NULL\n");
+ return -ENODEV;
+ }
+
+ if (!enable)
+ return 0;
+
+ return cnss_bus_dev_ramdump(plat_priv);
+}
+
+void *cnss_get_virt_ramdump_mem(struct device *dev, unsigned long *size)
+{
+ struct cnss_plat_data *plat_priv = cnss_bus_dev_to_plat_priv(dev);
+ struct cnss_ramdump_info *ramdump_info;
+
+ if (!plat_priv)
+ return NULL;
+
+ ramdump_info = &plat_priv->ramdump_info;
+ *size = ramdump_info->ramdump_size;
+
+ return ramdump_info->ramdump_va;
+}
+EXPORT_SYMBOL(cnss_get_virt_ramdump_mem);
+
static const char *cnss_recovery_reason_to_str(enum cnss_recovery_reason reason)
{
switch (reason) {
@@ -1433,8 +972,8 @@
return 0;
self_recovery:
- cnss_shutdown(plat_priv);
- cnss_powerup(plat_priv);
+ cnss_bus_dev_shutdown(plat_priv);
+ cnss_bus_dev_powerup(plat_priv);
return 0;
}
@@ -1547,38 +1086,12 @@
}
EXPORT_SYMBOL(cnss_force_fw_assert);
-static int cnss_register_driver_hdlr(struct cnss_plat_data *plat_priv,
- void *data)
-{
- int ret = 0;
-
- set_bit(CNSS_DRIVER_LOADING, &plat_priv->driver_state);
- plat_priv->driver_ops = data;
-
- ret = cnss_powerup(plat_priv);
- if (ret) {
- clear_bit(CNSS_DRIVER_LOADING, &plat_priv->driver_state);
- plat_priv->driver_ops = NULL;
- }
-
- return ret;
-}
-
-static int cnss_unregister_driver_hdlr(struct cnss_plat_data *plat_priv)
-{
- set_bit(CNSS_DRIVER_UNLOADING, &plat_priv->driver_state);
- cnss_shutdown(plat_priv);
- plat_priv->driver_ops = NULL;
-
- return 0;
-}
-
static int cnss_cold_boot_cal_start_hdlr(struct cnss_plat_data *plat_priv)
{
int ret = 0;
set_bit(CNSS_COLD_BOOT_CAL, &plat_priv->driver_state);
- ret = cnss_powerup(plat_priv);
+ ret = cnss_bus_dev_powerup(plat_priv);
if (ret)
clear_bit(CNSS_COLD_BOOT_CAL, &plat_priv->driver_state);
@@ -1589,7 +1102,7 @@
{
plat_priv->cal_done = true;
cnss_wlfw_wlan_mode_send_sync(plat_priv, QMI_WLFW_OFF_V01);
- cnss_shutdown(plat_priv);
+ cnss_bus_dev_shutdown(plat_priv);
clear_bit(CNSS_COLD_BOOT_CAL, &plat_priv->driver_state);
return 0;
@@ -1597,12 +1110,12 @@
static int cnss_power_up_hdlr(struct cnss_plat_data *plat_priv)
{
- return cnss_powerup(plat_priv);
+ return cnss_bus_dev_powerup(plat_priv);
}
static int cnss_power_down_hdlr(struct cnss_plat_data *plat_priv)
{
- cnss_shutdown(plat_priv);
+ cnss_bus_dev_shutdown(plat_priv);
return 0;
}
@@ -1661,11 +1174,11 @@
ret = cnss_cold_boot_cal_done_hdlr(plat_priv);
break;
case CNSS_DRIVER_EVENT_REGISTER_DRIVER:
- ret = cnss_register_driver_hdlr(plat_priv,
- event->data);
+ ret = cnss_bus_register_driver_hdlr(plat_priv,
+ event->data);
break;
case CNSS_DRIVER_EVENT_UNREGISTER_DRIVER:
- ret = cnss_unregister_driver_hdlr(plat_priv);
+ ret = cnss_bus_unregister_driver_hdlr(plat_priv);
break;
case CNSS_DRIVER_EVENT_RECOVERY:
ret = cnss_driver_recovery_hdlr(plat_priv,
@@ -1774,7 +1287,7 @@
return msm_dump_data_register(MSM_DUMP_TABLE_APPS, &dump_entry);
}
-static int cnss_qca6174_register_ramdump(struct cnss_plat_data *plat_priv)
+static int cnss_register_ramdump_v1(struct cnss_plat_data *plat_priv)
{
int ret = 0;
struct device *dev;
@@ -1825,7 +1338,7 @@
return ret;
}
-static void cnss_qca6174_unregister_ramdump(struct cnss_plat_data *plat_priv)
+static void cnss_unregister_ramdump_v1(struct cnss_plat_data *plat_priv)
{
struct device *dev;
struct cnss_ramdump_info *ramdump_info;
@@ -1842,7 +1355,7 @@
ramdump_info->ramdump_pa);
}
-static int cnss_qca6290_register_ramdump(struct cnss_plat_data *plat_priv)
+static int cnss_register_ramdump_v2(struct cnss_plat_data *plat_priv)
{
int ret = 0;
struct cnss_subsys_info *subsys_info;
@@ -1898,7 +1411,7 @@
return ret;
}
-static void cnss_qca6290_unregister_ramdump(struct cnss_plat_data *plat_priv)
+static void cnss_unregister_ramdump_v2(struct cnss_plat_data *plat_priv)
{
struct cnss_ramdump_info_v2 *info_v2;
@@ -1918,11 +1431,11 @@
switch (plat_priv->device_id) {
case QCA6174_DEVICE_ID:
- ret = cnss_qca6174_register_ramdump(plat_priv);
+ ret = cnss_register_ramdump_v1(plat_priv);
break;
case QCA6290_EMULATION_DEVICE_ID:
case QCA6290_DEVICE_ID:
- ret = cnss_qca6290_register_ramdump(plat_priv);
+ ret = cnss_register_ramdump_v2(plat_priv);
break;
default:
cnss_pr_err("Unknown device ID: 0x%lx\n", plat_priv->device_id);
@@ -1936,11 +1449,11 @@
{
switch (plat_priv->device_id) {
case QCA6174_DEVICE_ID:
- cnss_qca6174_unregister_ramdump(plat_priv);
+ cnss_unregister_ramdump_v1(plat_priv);
break;
case QCA6290_EMULATION_DEVICE_ID:
case QCA6290_DEVICE_ID:
- cnss_qca6290_unregister_ramdump(plat_priv);
+ cnss_unregister_ramdump_v2(plat_priv);
break;
default:
cnss_pr_err("Unknown device ID: 0x%lx\n", plat_priv->device_id);
diff --git a/drivers/net/wireless/cnss2/main.h b/drivers/net/wireless/cnss2/main.h
index f27f3ea7..509974a0 100644
--- a/drivers/net/wireless/cnss2/main.h
+++ b/drivers/net/wireless/cnss2/main.h
@@ -170,6 +170,13 @@
u32 host_pin_result;
};
+enum cnss_debug_quirks {
+ LINK_DOWN_SELF_RECOVERY,
+ SKIP_DEVICE_BOOT,
+ USE_CORE_ONLY_FW,
+ SKIP_RECOVERY,
+};
+
struct cnss_plat_data {
struct platform_device *plat_dev;
void *bus_priv;
@@ -185,7 +192,6 @@
struct cnss_platform_cap cap;
struct pm_qos_request qos_request;
unsigned long device_id;
- struct cnss_wlan_driver *driver_ops;
enum cnss_driver_status driver_status;
u32 recovery_count;
unsigned long driver_state;
@@ -216,8 +222,9 @@
bool cal_done;
};
-void *cnss_bus_dev_to_bus_priv(struct device *dev);
-struct cnss_plat_data *cnss_bus_dev_to_plat_priv(struct device *dev);
+struct cnss_plat_data *cnss_get_plat_priv(struct platform_device *plat_dev);
+bool *cnss_get_qmi_bypass(void);
+unsigned long *cnss_get_debug_quirks(void);
int cnss_driver_event_post(struct cnss_plat_data *plat_priv,
enum cnss_driver_event_type type,
u32 flags, void *data);
diff --git a/drivers/net/wireless/cnss2/pci.c b/drivers/net/wireless/cnss2/pci.c
index b9efe4d..e1704fb 100644
--- a/drivers/net/wireless/cnss2/pci.c
+++ b/drivers/net/wireless/cnss2/pci.c
@@ -17,6 +17,7 @@
#include <linux/of.h>
#include <linux/pm_runtime.h>
#include <linux/memblock.h>
+#include <soc/qcom/ramdump.h>
#include "main.h"
#include "bus.h"
@@ -227,6 +228,510 @@
}
EXPORT_SYMBOL(cnss_pci_link_down);
+int cnss_pci_call_driver_probe(struct cnss_pci_data *pci_priv)
+{
+ int ret = 0;
+ struct cnss_plat_data *plat_priv;
+
+ if (!pci_priv)
+ return -ENODEV;
+
+ plat_priv = pci_priv->plat_priv;
+
+ if (test_bit(CNSS_DRIVER_DEBUG, &plat_priv->driver_state)) {
+ clear_bit(CNSS_DRIVER_RECOVERY, &plat_priv->driver_state);
+ cnss_pr_dbg("Skip driver probe\n");
+ goto out;
+ }
+
+ if (!pci_priv->driver_ops) {
+ cnss_pr_err("driver_ops is NULL\n");
+ ret = -EINVAL;
+ goto out;
+ }
+
+ if (test_bit(CNSS_DRIVER_RECOVERY, &plat_priv->driver_state) &&
+ test_bit(CNSS_DRIVER_PROBED, &plat_priv->driver_state)) {
+ ret = pci_priv->driver_ops->reinit(pci_priv->pci_dev,
+ pci_priv->pci_device_id);
+ if (ret) {
+ cnss_pr_err("Failed to reinit host driver, err = %d\n",
+ ret);
+ goto out;
+ }
+ clear_bit(CNSS_DRIVER_RECOVERY, &plat_priv->driver_state);
+ } else if (test_bit(CNSS_DRIVER_LOADING, &plat_priv->driver_state)) {
+ ret = pci_priv->driver_ops->probe(pci_priv->pci_dev,
+ pci_priv->pci_device_id);
+ if (ret) {
+ cnss_pr_err("Failed to probe host driver, err = %d\n",
+ ret);
+ goto out;
+ }
+ clear_bit(CNSS_DRIVER_RECOVERY, &plat_priv->driver_state);
+ clear_bit(CNSS_DRIVER_LOADING, &plat_priv->driver_state);
+ set_bit(CNSS_DRIVER_PROBED, &plat_priv->driver_state);
+ }
+
+ return 0;
+
+out:
+ return ret;
+}
+
+int cnss_pci_call_driver_remove(struct cnss_pci_data *pci_priv)
+{
+ struct cnss_plat_data *plat_priv;
+
+ if (!pci_priv)
+ return -ENODEV;
+
+ plat_priv = pci_priv->plat_priv;
+
+ if (test_bit(CNSS_COLD_BOOT_CAL, &plat_priv->driver_state) ||
+ test_bit(CNSS_FW_BOOT_RECOVERY, &plat_priv->driver_state) ||
+ test_bit(CNSS_DRIVER_DEBUG, &plat_priv->driver_state)) {
+ cnss_pr_dbg("Skip driver remove\n");
+ return 0;
+ }
+
+ if (!pci_priv->driver_ops) {
+ cnss_pr_err("driver_ops is NULL\n");
+ return -EINVAL;
+ }
+
+ if (test_bit(CNSS_DRIVER_RECOVERY, &plat_priv->driver_state) &&
+ test_bit(CNSS_DRIVER_PROBED, &plat_priv->driver_state)) {
+ pci_priv->driver_ops->shutdown(pci_priv->pci_dev);
+ } else if (test_bit(CNSS_DRIVER_UNLOADING, &plat_priv->driver_state)) {
+ pci_priv->driver_ops->remove(pci_priv->pci_dev);
+ clear_bit(CNSS_DRIVER_PROBED, &plat_priv->driver_state);
+ }
+
+ return 0;
+}
+
+int cnss_pci_call_driver_modem_status(struct cnss_pci_data *pci_priv,
+ int modem_current_status)
+{
+ struct cnss_wlan_driver *driver_ops;
+
+ if (!pci_priv)
+ return -ENODEV;
+
+ driver_ops = pci_priv->driver_ops;
+ if (!driver_ops || !driver_ops->modem_status)
+ return -EINVAL;
+
+ driver_ops->modem_status(pci_priv->pci_dev, modem_current_status);
+
+ return 0;
+}
+
+static int cnss_qca6174_powerup(struct cnss_pci_data *pci_priv)
+{
+ int ret = 0;
+ struct cnss_plat_data *plat_priv = pci_priv->plat_priv;
+
+ ret = cnss_power_on_device(plat_priv);
+ if (ret) {
+ cnss_pr_err("Failed to power on device, err = %d\n", ret);
+ goto out;
+ }
+
+ ret = cnss_resume_pci_link(pci_priv);
+ if (ret) {
+ cnss_pr_err("Failed to resume PCI link, err = %d\n", ret);
+ goto power_off;
+ }
+
+ ret = cnss_pci_call_driver_probe(pci_priv);
+ if (ret)
+ goto suspend_link;
+
+ return 0;
+suspend_link:
+ cnss_suspend_pci_link(pci_priv);
+power_off:
+ cnss_power_off_device(plat_priv);
+out:
+ return ret;
+}
+
+static int cnss_qca6174_shutdown(struct cnss_pci_data *pci_priv)
+{
+ int ret = 0;
+ struct cnss_plat_data *plat_priv = pci_priv->plat_priv;
+
+ cnss_pm_request_resume(pci_priv);
+
+ cnss_pci_call_driver_remove(pci_priv);
+
+ cnss_request_bus_bandwidth(&plat_priv->plat_dev->dev,
+ CNSS_BUS_WIDTH_NONE);
+ cnss_pci_set_monitor_wake_intr(pci_priv, false);
+ cnss_pci_set_auto_suspended(pci_priv, 0);
+
+ ret = cnss_suspend_pci_link(pci_priv);
+ if (ret)
+ cnss_pr_err("Failed to suspend PCI link, err = %d\n", ret);
+
+ cnss_power_off_device(plat_priv);
+
+ clear_bit(CNSS_DRIVER_UNLOADING, &plat_priv->driver_state);
+
+ return ret;
+}
+
+static void cnss_qca6174_crash_shutdown(struct cnss_pci_data *pci_priv)
+{
+ if (pci_priv->driver_ops && pci_priv->driver_ops->crash_shutdown)
+ pci_priv->driver_ops->crash_shutdown(pci_priv->pci_dev);
+}
+
+static int cnss_qca6174_ramdump(struct cnss_pci_data *pci_priv)
+{
+ int ret = 0;
+ struct cnss_plat_data *plat_priv = pci_priv->plat_priv;
+ struct cnss_ramdump_info *ramdump_info;
+ struct ramdump_segment segment;
+
+ ramdump_info = &plat_priv->ramdump_info;
+ if (!ramdump_info->ramdump_size)
+ return -EINVAL;
+
+ memset(&segment, 0, sizeof(segment));
+ segment.v_address = ramdump_info->ramdump_va;
+ segment.size = ramdump_info->ramdump_size;
+ ret = do_ramdump(ramdump_info->ramdump_dev, &segment, 1);
+
+ return ret;
+}
+
+static int cnss_qca6290_powerup(struct cnss_pci_data *pci_priv)
+{
+ int ret = 0;
+ struct cnss_plat_data *plat_priv = pci_priv->plat_priv;
+ unsigned int timeout;
+
+ if (plat_priv->ramdump_info_v2.dump_data_valid ||
+ test_bit(CNSS_DRIVER_RECOVERY, &plat_priv->driver_state)) {
+ cnss_pci_set_mhi_state(pci_priv, CNSS_MHI_DEINIT);
+ cnss_pci_clear_dump_info(pci_priv);
+ }
+
+ ret = cnss_power_on_device(plat_priv);
+ if (ret) {
+ cnss_pr_err("Failed to power on device, err = %d\n", ret);
+ goto out;
+ }
+
+ ret = cnss_resume_pci_link(pci_priv);
+ if (ret) {
+ cnss_pr_err("Failed to resume PCI link, err = %d\n", ret);
+ goto power_off;
+ }
+
+ timeout = cnss_get_qmi_timeout();
+
+ ret = cnss_pci_start_mhi(pci_priv);
+ if (ret) {
+ cnss_pr_err("Failed to start MHI, err = %d\n", ret);
+ if (!test_bit(CNSS_DEV_ERR_NOTIFY, &plat_priv->driver_state) &&
+ !pci_priv->pci_link_down_ind && timeout)
+ mod_timer(&plat_priv->fw_boot_timer,
+ jiffies + msecs_to_jiffies(timeout >> 1));
+ return 0;
+ }
+
+ if (test_bit(USE_CORE_ONLY_FW, cnss_get_debug_quirks())) {
+ clear_bit(CNSS_FW_BOOT_RECOVERY, &plat_priv->driver_state);
+ clear_bit(CNSS_DRIVER_RECOVERY, &plat_priv->driver_state);
+ return 0;
+ }
+
+ cnss_set_pin_connect_status(plat_priv);
+
+ if (*cnss_get_qmi_bypass()) {
+ ret = cnss_pci_call_driver_probe(pci_priv);
+ if (ret)
+ goto stop_mhi;
+ } else if (timeout) {
+ mod_timer(&plat_priv->fw_boot_timer,
+ jiffies + msecs_to_jiffies(timeout << 1));
+ }
+
+ return 0;
+
+stop_mhi:
+ cnss_pci_stop_mhi(pci_priv);
+ cnss_suspend_pci_link(pci_priv);
+power_off:
+ cnss_power_off_device(plat_priv);
+out:
+ return ret;
+}
+
+static int cnss_qca6290_shutdown(struct cnss_pci_data *pci_priv)
+{
+ int ret = 0;
+ struct cnss_plat_data *plat_priv = pci_priv->plat_priv;
+
+ cnss_pm_request_resume(pci_priv);
+
+ cnss_pci_call_driver_remove(pci_priv);
+
+ cnss_request_bus_bandwidth(&plat_priv->plat_dev->dev,
+ CNSS_BUS_WIDTH_NONE);
+ cnss_pci_set_monitor_wake_intr(pci_priv, false);
+ cnss_pci_set_auto_suspended(pci_priv, 0);
+
+ cnss_pci_stop_mhi(pci_priv);
+
+ ret = cnss_suspend_pci_link(pci_priv);
+ if (ret)
+ cnss_pr_err("Failed to suspend PCI link, err = %d\n", ret);
+
+ cnss_power_off_device(plat_priv);
+
+ clear_bit(CNSS_FW_READY, &plat_priv->driver_state);
+ clear_bit(CNSS_FW_MEM_READY, &plat_priv->driver_state);
+ clear_bit(CNSS_DRIVER_UNLOADING, &plat_priv->driver_state);
+
+ return ret;
+}
+
+static void cnss_qca6290_crash_shutdown(struct cnss_pci_data *pci_priv)
+{
+ struct cnss_plat_data *plat_priv = pci_priv->plat_priv;
+
+ cnss_pr_dbg("Crash shutdown with driver_state 0x%lx\n",
+ plat_priv->driver_state);
+
+ if (test_bit(CNSS_DRIVER_RECOVERY, &plat_priv->driver_state)) {
+ cnss_pr_dbg("Ignore crash shutdown\n");
+ return;
+ }
+
+ cnss_pci_collect_dump_info(pci_priv, true);
+}
+
+static int cnss_qca6290_ramdump(struct cnss_pci_data *pci_priv)
+{
+ struct cnss_plat_data *plat_priv = pci_priv->plat_priv;
+ struct cnss_ramdump_info_v2 *info_v2 = &plat_priv->ramdump_info_v2;
+ struct cnss_dump_data *dump_data = &info_v2->dump_data;
+ struct cnss_dump_seg *dump_seg = info_v2->dump_data_vaddr;
+ struct ramdump_segment *ramdump_segs, *s;
+ int i, ret = 0;
+
+ if (!info_v2->dump_data_valid ||
+ dump_data->nentries == 0)
+ return 0;
+
+ ramdump_segs = kcalloc(dump_data->nentries,
+ sizeof(*ramdump_segs),
+ GFP_KERNEL);
+ if (!ramdump_segs)
+ return -ENOMEM;
+
+ s = ramdump_segs;
+ for (i = 0; i < dump_data->nentries; i++) {
+ s->address = dump_seg->address;
+ s->v_address = dump_seg->v_address;
+ s->size = dump_seg->size;
+ s++;
+ dump_seg++;
+ }
+
+ ret = do_elf_ramdump(info_v2->ramdump_dev, ramdump_segs,
+ dump_data->nentries);
+ kfree(ramdump_segs);
+
+ cnss_pci_set_mhi_state(plat_priv->bus_priv, CNSS_MHI_DEINIT);
+ cnss_pci_clear_dump_info(plat_priv->bus_priv);
+
+ return ret;
+}
+
+int cnss_pci_dev_powerup(struct cnss_pci_data *pci_priv)
+{
+ int ret = 0;
+
+ if (!pci_priv) {
+ cnss_pr_err("pci_priv is NULL\n");
+ return -ENODEV;
+ }
+
+ switch (pci_priv->device_id) {
+ case QCA6174_DEVICE_ID:
+ ret = cnss_qca6174_powerup(pci_priv);
+ break;
+ case QCA6290_EMULATION_DEVICE_ID:
+ case QCA6290_DEVICE_ID:
+ ret = cnss_qca6290_powerup(pci_priv);
+ break;
+ default:
+ cnss_pr_err("Unknown device_id found: 0x%x\n",
+ pci_priv->device_id);
+ ret = -ENODEV;
+ }
+
+ return ret;
+}
+
+int cnss_pci_dev_shutdown(struct cnss_pci_data *pci_priv)
+{
+ int ret = 0;
+
+ if (!pci_priv) {
+ cnss_pr_err("pci_priv is NULL\n");
+ return -ENODEV;
+ }
+
+ switch (pci_priv->device_id) {
+ case QCA6174_DEVICE_ID:
+ ret = cnss_qca6174_shutdown(pci_priv);
+ break;
+ case QCA6290_EMULATION_DEVICE_ID:
+ case QCA6290_DEVICE_ID:
+ ret = cnss_qca6290_shutdown(pci_priv);
+ break;
+ default:
+ cnss_pr_err("Unknown device_id found: 0x%x\n",
+ pci_priv->device_id);
+ ret = -ENODEV;
+ }
+
+ return ret;
+}
+
+int cnss_pci_dev_crash_shutdown(struct cnss_pci_data *pci_priv)
+{
+ int ret = 0;
+
+ if (!pci_priv) {
+ cnss_pr_err("pci_priv is NULL\n");
+ return -ENODEV;
+ }
+
+ switch (pci_priv->device_id) {
+ case QCA6174_DEVICE_ID:
+ cnss_qca6174_crash_shutdown(pci_priv);
+ break;
+ case QCA6290_EMULATION_DEVICE_ID:
+ case QCA6290_DEVICE_ID:
+ cnss_qca6290_crash_shutdown(pci_priv);
+ break;
+ default:
+ cnss_pr_err("Unknown device_id found: 0x%x\n",
+ pci_priv->device_id);
+ ret = -ENODEV;
+ }
+
+ return ret;
+}
+
+int cnss_pci_dev_ramdump(struct cnss_pci_data *pci_priv)
+{
+ int ret = 0;
+
+ if (!pci_priv) {
+ cnss_pr_err("pci_priv is NULL\n");
+ return -ENODEV;
+ }
+
+ switch (pci_priv->device_id) {
+ case QCA6174_DEVICE_ID:
+ ret = cnss_qca6174_ramdump(pci_priv);
+ break;
+ case QCA6290_EMULATION_DEVICE_ID:
+ case QCA6290_DEVICE_ID:
+ ret = cnss_qca6290_ramdump(pci_priv);
+ break;
+ default:
+ cnss_pr_err("Unknown device_id found: 0x%x\n",
+ pci_priv->device_id);
+ ret = -ENODEV;
+ }
+
+ return ret;
+}
+
+int cnss_wlan_register_driver(struct cnss_wlan_driver *driver_ops)
+{
+ int ret = 0;
+ struct cnss_plat_data *plat_priv = cnss_bus_dev_to_plat_priv(NULL);
+ struct cnss_pci_data *pci_priv;
+
+ if (!plat_priv) {
+ cnss_pr_err("plat_priv is NULL\n");
+ return -ENODEV;
+ }
+
+ pci_priv = plat_priv->bus_priv;
+ if (!pci_priv) {
+ cnss_pr_err("pci_priv is NULL\n");
+ return -ENODEV;
+ }
+
+ if (pci_priv->driver_ops) {
+ cnss_pr_err("Driver has already registered\n");
+ return -EEXIST;
+ }
+
+ ret = cnss_driver_event_post(plat_priv,
+ CNSS_DRIVER_EVENT_REGISTER_DRIVER,
+ CNSS_EVENT_SYNC_UNINTERRUPTIBLE,
+ driver_ops);
+ return ret;
+}
+EXPORT_SYMBOL(cnss_wlan_register_driver);
+
+void cnss_wlan_unregister_driver(struct cnss_wlan_driver *driver_ops)
+{
+ struct cnss_plat_data *plat_priv = cnss_bus_dev_to_plat_priv(NULL);
+
+ if (!plat_priv) {
+ cnss_pr_err("plat_priv is NULL\n");
+ return;
+ }
+
+ cnss_driver_event_post(plat_priv,
+ CNSS_DRIVER_EVENT_UNREGISTER_DRIVER,
+ CNSS_EVENT_SYNC_UNINTERRUPTIBLE, NULL);
+}
+EXPORT_SYMBOL(cnss_wlan_unregister_driver);
+
+int cnss_pci_register_driver_hdlr(struct cnss_pci_data *pci_priv,
+ void *data)
+{
+ int ret = 0;
+ struct cnss_plat_data *plat_priv = pci_priv->plat_priv;
+
+ set_bit(CNSS_DRIVER_LOADING, &plat_priv->driver_state);
+ pci_priv->driver_ops = data;
+
+ ret = cnss_pci_dev_powerup(pci_priv);
+ if (ret) {
+ clear_bit(CNSS_DRIVER_LOADING, &plat_priv->driver_state);
+ pci_priv->driver_ops = NULL;
+ }
+
+ return ret;
+}
+
+int cnss_pci_unregister_driver_hdlr(struct cnss_pci_data *pci_priv)
+{
+ struct cnss_plat_data *plat_priv = pci_priv->plat_priv;
+
+ set_bit(CNSS_DRIVER_UNLOADING, &plat_priv->driver_state);
+ cnss_pci_dev_shutdown(pci_priv);
+ pci_priv->driver_ops = NULL;
+
+ return 0;
+}
+
static int cnss_pci_init_smmu(struct cnss_pci_data *pci_priv)
{
int ret = 0;
@@ -382,7 +887,6 @@
int ret = 0;
struct pci_dev *pci_dev = to_pci_dev(dev);
struct cnss_pci_data *pci_priv = cnss_get_pci_priv(pci_dev);
- struct cnss_plat_data *plat_priv;
struct cnss_wlan_driver *driver_ops;
pm_message_t state = { .event = PM_EVENT_SUSPEND };
@@ -390,11 +894,7 @@
if (!pci_priv)
goto out;
- plat_priv = pci_priv->plat_priv;
- if (!plat_priv)
- goto out;
-
- driver_ops = plat_priv->driver_ops;
+ driver_ops = pci_priv->driver_ops;
if (driver_ops && driver_ops->suspend) {
ret = driver_ops->suspend(pci_dev, state);
if (ret) {
@@ -405,7 +905,7 @@
}
}
- if (pci_priv->pci_link_state) {
+ if (pci_priv->pci_link_state == PCI_LINK_UP) {
ret = cnss_pci_set_mhi_state(pci_priv, CNSS_MHI_SUSPEND);
if (ret) {
if (driver_ops && driver_ops->resume)
@@ -437,31 +937,29 @@
int ret = 0;
struct pci_dev *pci_dev = to_pci_dev(dev);
struct cnss_pci_data *pci_priv = cnss_get_pci_priv(pci_dev);
- struct cnss_plat_data *plat_priv;
struct cnss_wlan_driver *driver_ops;
if (!pci_priv)
goto out;
- plat_priv = pci_priv->plat_priv;
- if (!plat_priv)
- goto out;
-
if (pci_priv->pci_link_down_ind)
goto out;
- ret = pci_enable_device(pci_dev);
- if (ret)
- cnss_pr_err("Failed to enable PCI device, err = %d\n", ret);
+ if (pci_priv->pci_link_state == PCI_LINK_UP) {
+ ret = pci_enable_device(pci_dev);
+ if (ret)
+ cnss_pr_err("Failed to enable PCI device, err = %d\n",
+ ret);
- if (pci_priv->saved_state)
- cnss_set_pci_config_space(pci_priv,
- RESTORE_PCI_CONFIG_SPACE);
+ if (pci_priv->saved_state)
+ cnss_set_pci_config_space(pci_priv,
+ RESTORE_PCI_CONFIG_SPACE);
- pci_set_master(pci_dev);
- cnss_pci_set_mhi_state(pci_priv, CNSS_MHI_RESUME);
+ pci_set_master(pci_dev);
+ cnss_pci_set_mhi_state(pci_priv, CNSS_MHI_RESUME);
+ }
- driver_ops = plat_priv->driver_ops;
+ driver_ops = pci_priv->driver_ops;
if (driver_ops && driver_ops->resume) {
ret = driver_ops->resume(pci_dev);
if (ret)
@@ -480,20 +978,20 @@
int ret = 0;
struct pci_dev *pci_dev = to_pci_dev(dev);
struct cnss_pci_data *pci_priv = cnss_get_pci_priv(pci_dev);
- struct cnss_plat_data *plat_priv;
struct cnss_wlan_driver *driver_ops;
if (!pci_priv)
goto out;
- plat_priv = pci_priv->plat_priv;
- if (!plat_priv)
- goto out;
-
- driver_ops = plat_priv->driver_ops;
+ driver_ops = pci_priv->driver_ops;
if (driver_ops && driver_ops->suspend_noirq)
ret = driver_ops->suspend_noirq(pci_dev);
+ ret = cnss_set_pci_link(pci_priv, PCI_LINK_DOWN);
+ if (ret)
+ goto out;
+ pci_priv->pci_link_state = PCI_LINK_DOWN;
+
out:
return ret;
}
@@ -503,17 +1001,17 @@
int ret = 0;
struct pci_dev *pci_dev = to_pci_dev(dev);
struct cnss_pci_data *pci_priv = cnss_get_pci_priv(pci_dev);
- struct cnss_plat_data *plat_priv;
struct cnss_wlan_driver *driver_ops;
if (!pci_priv)
goto out;
- plat_priv = pci_priv->plat_priv;
- if (!plat_priv)
+ ret = cnss_set_pci_link(pci_priv, PCI_LINK_UP);
+ if (ret)
goto out;
+ pci_priv->pci_link_state = PCI_LINK_UP;
- driver_ops = plat_priv->driver_ops;
+ driver_ops = pci_priv->driver_ops;
if (driver_ops && driver_ops->resume_noirq &&
!pci_priv->pci_link_down_ind)
ret = driver_ops->resume_noirq(pci_dev);
@@ -527,16 +1025,11 @@
int ret = 0;
struct pci_dev *pci_dev = to_pci_dev(dev);
struct cnss_pci_data *pci_priv = cnss_get_pci_priv(pci_dev);
- struct cnss_plat_data *plat_priv;
struct cnss_wlan_driver *driver_ops;
if (!pci_priv)
return -EAGAIN;
- plat_priv = pci_priv->plat_priv;
- if (!plat_priv)
- return -EAGAIN;
-
if (pci_priv->pci_link_down_ind) {
cnss_pr_dbg("PCI link down recovery is in progress!\n");
return -EAGAIN;
@@ -544,7 +1037,7 @@
cnss_pr_dbg("Runtime suspend start\n");
- driver_ops = plat_priv->driver_ops;
+ driver_ops = pci_priv->driver_ops;
if (driver_ops && driver_ops->runtime_ops &&
driver_ops->runtime_ops->runtime_suspend)
ret = driver_ops->runtime_ops->runtime_suspend(pci_dev);
@@ -559,16 +1052,11 @@
int ret = 0;
struct pci_dev *pci_dev = to_pci_dev(dev);
struct cnss_pci_data *pci_priv = cnss_get_pci_priv(pci_dev);
- struct cnss_plat_data *plat_priv;
struct cnss_wlan_driver *driver_ops;
if (!pci_priv)
return -EAGAIN;
- plat_priv = pci_priv->plat_priv;
- if (!plat_priv)
- return -EAGAIN;
-
if (pci_priv->pci_link_down_ind) {
cnss_pr_dbg("PCI link down recovery is in progress!\n");
return -EAGAIN;
@@ -576,7 +1064,7 @@
cnss_pr_dbg("Runtime resume start\n");
- driver_ops = plat_priv->driver_ops;
+ driver_ops = pci_priv->driver_ops;
if (driver_ops && driver_ops->runtime_ops &&
driver_ops->runtime_ops->runtime_resume)
ret = driver_ops->runtime_ops->runtime_resume(pci_dev);
@@ -1278,9 +1766,9 @@
cnss_pr_dbg("MHI status cb is called with reason %d\n", reason);
- if (plat_priv->driver_ops && plat_priv->driver_ops->update_status)
- plat_priv->driver_ops->update_status(pci_priv->pci_dev,
- CNSS_FW_DOWN);
+ if (pci_priv->driver_ops && pci_priv->driver_ops->update_status)
+ pci_priv->driver_ops->update_status(pci_priv->pci_dev,
+ CNSS_FW_DOWN);
switch (reason) {
case MHI_CB_EE_RDDM:
diff --git a/drivers/net/wireless/cnss2/pci.h b/drivers/net/wireless/cnss2/pci.h
index 70cf445..79f66ac 100644
--- a/drivers/net/wireless/cnss2/pci.h
+++ b/drivers/net/wireless/cnss2/pci.h
@@ -51,6 +51,7 @@
const struct pci_device_id *pci_device_id;
u32 device_id;
u16 revision_id;
+ struct cnss_wlan_driver *driver_ops;
bool pci_link_state;
bool pci_link_down_ind;
struct pci_saved_state *saved_state;
@@ -130,5 +131,15 @@
u32 cnss_pci_get_wake_msi(struct cnss_pci_data *pci_priv);
int cnss_pci_force_fw_assert_hdlr(struct cnss_pci_data *pci_priv);
void cnss_pci_fw_boot_timeout_hdlr(struct cnss_pci_data *pci_priv);
+int cnss_pci_call_driver_probe(struct cnss_pci_data *pci_priv);
+int cnss_pci_call_driver_remove(struct cnss_pci_data *pci_priv);
+int cnss_pci_dev_powerup(struct cnss_pci_data *pci_priv);
+int cnss_pci_dev_shutdown(struct cnss_pci_data *pci_priv);
+int cnss_pci_dev_crash_shutdown(struct cnss_pci_data *pci_priv);
+int cnss_pci_dev_ramdump(struct cnss_pci_data *pci_priv);
+int cnss_pci_register_driver_hdlr(struct cnss_pci_data *pci_priv, void *data);
+int cnss_pci_unregister_driver_hdlr(struct cnss_pci_data *pci_priv);
+int cnss_pci_call_driver_modem_status(struct cnss_pci_data *pci_priv,
+ int modem_current_status);
#endif /* _CNSS_PCI_H */
diff --git a/drivers/platform/msm/ep_pcie/ep_pcie_com.h b/drivers/platform/msm/ep_pcie/ep_pcie_com.h
index 33e0314..36d49e4 100644
--- a/drivers/platform/msm/ep_pcie/ep_pcie_com.h
+++ b/drivers/platform/msm/ep_pcie/ep_pcie_com.h
@@ -359,7 +359,7 @@
ulong global_irq_counter;
bool dump_conf;
-
+ bool config_mmio_init;
bool enumerated;
enum ep_pcie_link_status link_status;
bool perst_deast;
diff --git a/drivers/platform/msm/ep_pcie/ep_pcie_core.c b/drivers/platform/msm/ep_pcie/ep_pcie_core.c
index 4558530..0ada0bf 100644
--- a/drivers/platform/msm/ep_pcie/ep_pcie_core.c
+++ b/drivers/platform/msm/ep_pcie/ep_pcie_core.c
@@ -503,6 +503,13 @@
"Initial version of MMIO is:0x%x\n",
readl_relaxed(dev->mmio + PCIE20_MHIVER));
+ if (dev->config_mmio_init) {
+ EP_PCIE_DBG(dev,
+ "PCIe V%d: MMIO already initialized, return\n",
+ dev->rev);
+ return;
+ }
+
ep_pcie_write_reg(dev->mmio, PCIE20_MHICFG, 0x02800880);
ep_pcie_write_reg(dev->mmio, PCIE20_BHI_EXECENV, 0x2);
ep_pcie_write_reg(dev->mmio, PCIE20_MHICTRL, 0x0);
@@ -511,6 +518,8 @@
ep_pcie_write_reg(dev->mmio, PCIE20_BHI_VERSION_LOWER, 0x2);
ep_pcie_write_reg(dev->mmio, PCIE20_BHI_VERSION_UPPER, 0x1);
ep_pcie_write_reg(dev->mmio, PCIE20_BHI_INTVEC, 0xffffffff);
+
+ dev->config_mmio_init = true;
}
static void ep_pcie_core_init(struct ep_pcie_dev_t *dev, bool configured)
diff --git a/drivers/platform/msm/gsi/gsi.c b/drivers/platform/msm/gsi/gsi.c
index 1af3447..2c29538 100644
--- a/drivers/platform/msm/gsi/gsi.c
+++ b/drivers/platform/msm/gsi/gsi.c
@@ -1292,6 +1292,7 @@
if (!props->evchid_valid)
clear_bit(evt_id, &gsi_ctx->evt_bmap);
mutex_unlock(&gsi_ctx->mlock);
+ BUG();
return -GSI_STATUS_RES_ALLOC_FAILURE;
}
@@ -1876,6 +1877,32 @@
}
EXPORT_SYMBOL(gsi_alloc_channel);
+static void __gsi_read_channel_scratch(unsigned long chan_hdl,
+ union __packed gsi_channel_scratch * val)
+{
+ uint32_t reg;
+
+ reg = gsi_readl(gsi_ctx->base +
+ GSI_EE_n_GSI_CH_k_SCRATCH_0_OFFS(chan_hdl,
+ gsi_ctx->per.ee));
+ val->data.word1 = reg;
+
+ reg = gsi_readl(gsi_ctx->base +
+ GSI_EE_n_GSI_CH_k_SCRATCH_1_OFFS(chan_hdl,
+ gsi_ctx->per.ee));
+ val->data.word2 = reg;
+
+ reg = gsi_readl(gsi_ctx->base +
+ GSI_EE_n_GSI_CH_k_SCRATCH_2_OFFS(chan_hdl,
+ gsi_ctx->per.ee));
+ val->data.word3 = reg;
+
+ reg = gsi_readl(gsi_ctx->base +
+ GSI_EE_n_GSI_CH_k_SCRATCH_3_OFFS(chan_hdl,
+ gsi_ctx->per.ee));
+ val->data.word4 = reg;
+}
+
static void __gsi_write_channel_scratch(unsigned long chan_hdl,
union __packed gsi_channel_scratch val)
{
@@ -1936,6 +1963,40 @@
}
EXPORT_SYMBOL(gsi_write_channel_scratch);
+int gsi_read_channel_scratch(unsigned long chan_hdl,
+ union __packed gsi_channel_scratch * ch_scratch)
+{
+ struct gsi_chan_ctx *ctx;
+
+ if (!gsi_ctx) {
+ pr_err("%s:%d gsi context not allocated\n", __func__, __LINE__);
+ return -GSI_STATUS_NODEV;
+ }
+
+ if (chan_hdl >= gsi_ctx->max_ch) {
+ GSIERR("bad params chan_hdl=%lu\n", chan_hdl);
+ return -GSI_STATUS_INVALID_PARAMS;
+ }
+
+ if (gsi_ctx->chan[chan_hdl].state != GSI_CHAN_STATE_ALLOCATED &&
+ gsi_ctx->chan[chan_hdl].state != GSI_CHAN_STATE_STARTED &&
+ gsi_ctx->chan[chan_hdl].state != GSI_CHAN_STATE_STOPPED) {
+ GSIERR("bad state %d\n",
+ gsi_ctx->chan[chan_hdl].state);
+ return -GSI_STATUS_UNSUPPORTED_OP;
+ }
+
+ ctx = &gsi_ctx->chan[chan_hdl];
+
+ mutex_lock(&ctx->mlock);
+ __gsi_read_channel_scratch(chan_hdl, ch_scratch);
+ ctx->restore_scratch = *ch_scratch;
+ mutex_unlock(&ctx->mlock);
+
+ return GSI_STATUS_SUCCESS;
+}
+EXPORT_SYMBOL(gsi_read_channel_scratch);
+
int gsi_query_channel_db_addr(unsigned long chan_hdl,
uint32_t *db_addr_wp_lsb, uint32_t *db_addr_wp_msb)
{
@@ -2618,7 +2679,7 @@
return -GSI_STATUS_UNSUPPORTED_OP;
}
- if (ctx->state != GSI_CHAN_STATE_STARTED) {
+ if (ctx->state == GSI_CHAN_STATE_NOT_ALLOCATED) {
GSIERR("bad state %d\n", ctx->state);
return -GSI_STATUS_UNSUPPORTED_OP;
}
@@ -2727,21 +2788,27 @@
return -GSI_STATUS_UNSUPPORTED_OP;
}
- spin_lock_irqsave(&gsi_ctx->slock, flags);
if (curr == GSI_CHAN_MODE_CALLBACK &&
mode == GSI_CHAN_MODE_POLL) {
+ spin_lock_irqsave(&gsi_ctx->slock, flags);
__gsi_config_ieob_irq(gsi_ctx->per.ee, 1 << ctx->evtr->id, 0);
+ spin_unlock_irqrestore(&gsi_ctx->slock, flags);
+ spin_lock_irqsave(&ctx->ring.slock, flags);
atomic_set(&ctx->poll_mode, mode);
+ spin_unlock_irqrestore(&ctx->ring.slock, flags);
ctx->stats.callback_to_poll++;
}
if (curr == GSI_CHAN_MODE_POLL &&
mode == GSI_CHAN_MODE_CALLBACK) {
+ spin_lock_irqsave(&ctx->ring.slock, flags);
atomic_set(&ctx->poll_mode, mode);
+ spin_unlock_irqrestore(&ctx->ring.slock, flags);
+ spin_lock_irqsave(&gsi_ctx->slock, flags);
__gsi_config_ieob_irq(gsi_ctx->per.ee, 1 << ctx->evtr->id, ~0);
+ spin_unlock_irqrestore(&gsi_ctx->slock, flags);
ctx->stats.poll_to_callback++;
}
- spin_unlock_irqrestore(&gsi_ctx->slock, flags);
return GSI_STATUS_SUCCESS;
}
diff --git a/drivers/platform/msm/gsi/gsi.h b/drivers/platform/msm/gsi/gsi.h
index 92849d9..4a3f4ec 100644
--- a/drivers/platform/msm/gsi/gsi.h
+++ b/drivers/platform/msm/gsi/gsi.h
@@ -137,6 +137,7 @@
bool allocated;
atomic_t poll_mode;
union __packed gsi_channel_scratch scratch;
+ union __packed gsi_channel_scratch restore_scratch;
struct gsi_chan_stats stats;
bool enable_dp_stats;
bool print_dp_stats;
diff --git a/drivers/platform/msm/ipa/ipa_clients/ipa_gsb.c b/drivers/platform/msm/ipa/ipa_clients/ipa_gsb.c
index df19384..5812d8d 100644
--- a/drivers/platform/msm/ipa/ipa_clients/ipa_gsb.c
+++ b/drivers/platform/msm/ipa/ipa_clients/ipa_gsb.c
@@ -67,7 +67,8 @@
static char dbg_buff[IPA_GSB_MAX_MSG_LEN];
#define IPA_GSB_SKB_HEADROOM 256
-#define IPA_GSB_AGGR_BYTE_LIMIT 6
+#define IPA_GSB_SKB_DUMMY_HEADER 42
+#define IPA_GSB_AGGR_BYTE_LIMIT 14
#define IPA_GSB_AGGR_TIME_LIMIT 1
static struct dentry *dent;
@@ -278,22 +279,36 @@
"%s_ipv4", iface_info->netdev_name);
snprintf(hdr->hdr[1].name, sizeof(hdr->hdr[1].name),
"%s_ipv6", iface_info->netdev_name);
- /* partial header: [hdl][QMAP ID][pkt size][ETH header] */
+ /*
+ * partial header:
+ * [hdl][QMAP ID][pkt size][Dummy Header][ETH header]
+ */
for (i = IPA_IP_v4; i < IPA_IP_MAX; i++) {
- hdr->hdr[i].hdr_len = ETH_HLEN + sizeof(struct ipa_gsb_mux_hdr);
+ /*
+ * Optimization: add dummy header to reserve space
+ * for rndis header, so we can do the skb_clone
+ * instead of deep copy.
+ */
+ hdr->hdr[i].hdr_len = ETH_HLEN +
+ sizeof(struct ipa_gsb_mux_hdr) +
+ IPA_GSB_SKB_DUMMY_HEADER;
hdr->hdr[i].type = IPA_HDR_L2_ETHERNET_II;
hdr->hdr[i].is_partial = 1;
hdr->hdr[i].is_eth2_ofst_valid = 1;
- hdr->hdr[i].eth2_ofst = sizeof(struct ipa_gsb_mux_hdr);
+ hdr->hdr[i].eth2_ofst = sizeof(struct ipa_gsb_mux_hdr) +
+ IPA_GSB_SKB_DUMMY_HEADER;
/* populate iface handle */
hdr->hdr[i].hdr[0] = iface_info->iface_hdl;
/* populate src ETH address */
- memcpy(&hdr->hdr[i].hdr[10], iface_info->device_ethaddr, 6);
+ memcpy(&hdr->hdr[i].hdr[10 + IPA_GSB_SKB_DUMMY_HEADER],
+ iface_info->device_ethaddr, 6);
/* populate Ethertype */
if (i == IPA_IP_v4)
- *(u16 *)(hdr->hdr[i].hdr + 16) = htons(ETH_P_IP);
+ *(u16 *)(hdr->hdr[i].hdr + 16 +
+ IPA_GSB_SKB_DUMMY_HEADER) = htons(ETH_P_IP);
else
- *(u16 *)(hdr->hdr[i].hdr + 16) = htons(ETH_P_IPV6);
+ *(u16 *)(hdr->hdr[i].hdr + 16 +
+ IPA_GSB_SKB_DUMMY_HEADER) = htons(ETH_P_IPV6);
}
if (ipa_add_hdr(hdr)) {
@@ -410,7 +425,7 @@
return;
}
- IPA_GSB_DBG("wake up clients\n");
+ IPA_GSB_DBG_LOW("wake up clients\n");
for (i = 0; i < MAX_SUPPORTED_IFACE; i++)
if (ipa_gsb_ctx->iface[i] != NULL)
ipa_gsb_ctx->iface[i]->wakeup_request(
@@ -629,21 +644,6 @@
}
EXPORT_SYMBOL(ipa_bridge_cleanup);
-static struct sk_buff *ipa_gsb_skb_copy(struct sk_buff *skb, int len)
-{
- struct sk_buff *skb2 = NULL;
-
- skb2 = __dev_alloc_skb(len + IPA_GSB_SKB_HEADROOM, GFP_KERNEL);
- if (likely(skb2)) {
- skb_reserve(skb2, IPA_GSB_SKB_HEADROOM);
- memcpy(skb2->data, skb->data, len);
- skb2->len = len;
- skb_set_tail_pointer(skb2, len);
- }
-
- return skb2;
-}
-
static void ipa_gsb_cons_cb(void *priv, enum ipa_dp_evt_type evt,
unsigned long data)
{
@@ -665,21 +665,33 @@
mux_hdr = (struct ipa_gsb_mux_hdr *)skb->data;
pkt_size = mux_hdr->pkt_size;
/* 4-byte padding */
- pad_byte = ((pkt_size + sizeof(*mux_hdr) + ETH_HLEN + 3) & ~3)
- - (pkt_size + sizeof(*mux_hdr) + ETH_HLEN);
+ pad_byte = ((pkt_size + sizeof(*mux_hdr) + ETH_HLEN +
+ 3 + IPA_GSB_SKB_DUMMY_HEADER) & ~3) -
+ (pkt_size + sizeof(*mux_hdr) +
+ ETH_HLEN + IPA_GSB_SKB_DUMMY_HEADER);
hdl = mux_hdr->iface_hdl;
- IPA_GSB_DBG("pkt_size: %d, pad_byte: %d, hdl: %d\n",
+ IPA_GSB_DBG_LOW("pkt_size: %d, pad_byte: %d, hdl: %d\n",
pkt_size, pad_byte, hdl);
- /* remove 4 byte mux header */
- skb_pull(skb, sizeof(*mux_hdr));
- skb2 = ipa_gsb_skb_copy(skb, pkt_size + ETH_HLEN);
+ /* remove 4 byte mux header AND dummy header*/
+ skb_pull(skb, sizeof(*mux_hdr) + IPA_GSB_SKB_DUMMY_HEADER);
+
+ skb2 = skb_clone(skb, GFP_KERNEL);
+ if (!skb2) {
+ IPA_GSB_ERR("skb_clone failed\n");
+ WARN_ON(1);
+ break;
+ }
+ skb_trim(skb2, pkt_size + ETH_HLEN);
ipa_gsb_ctx->iface[hdl]->send_dl_skb(
ipa_gsb_ctx->iface[hdl]->priv, skb2);
ipa_gsb_ctx->iface[hdl]->iface_stats.num_dl_packets++;
-
skb_pull(skb, pkt_size + ETH_HLEN + pad_byte);
}
+ if (skb) {
+ dev_kfree_skb_any(skb);
+ skb = NULL;
+ }
}
static void ipa_gsb_tx_dp_notify(void *priv, enum ipa_dp_evt_type evt,
@@ -702,7 +714,7 @@
/* change to host order */
*(u32 *)mux_hdr = ntohl(*(u32 *)mux_hdr);
hdl = mux_hdr->iface_hdl;
- IPA_GSB_DBG("evt: %d, hdl in tx_dp_notify: %d\n", evt, hdl);
+ IPA_GSB_DBG_LOW("evt: %d, hdl in tx_dp_notify: %d\n", evt, hdl);
/* remove 4 byte mux header */
skb_pull(skb, sizeof(struct ipa_gsb_mux_hdr));
@@ -740,7 +752,8 @@
/* configure TX EP */
cons_params.client = IPA_CLIENT_ODU_EMB_CONS;
cons_params.ipa_ep_cfg.hdr.hdr_len =
- ETH_HLEN + sizeof(struct ipa_gsb_mux_hdr);
+ ETH_HLEN + sizeof(struct ipa_gsb_mux_hdr) +
+ IPA_GSB_SKB_DUMMY_HEADER;
cons_params.ipa_ep_cfg.hdr.hdr_ofst_pkt_size_valid = 1;
cons_params.ipa_ep_cfg.hdr.hdr_ofst_pkt_size = 2;
cons_params.ipa_ep_cfg.hdr_ext.hdr_pad_to_alignment = 2;
@@ -911,7 +924,7 @@
return -EFAULT;
}
- IPA_GSB_DBG("client hdl: %d\n", hdl);
+ IPA_GSB_DBG_LOW("client hdl: %d\n", hdl);
if (!ipa_gsb_ctx->iface[hdl]->is_connected) {
IPA_GSB_ERR("iface is not connected\n");
@@ -919,7 +932,7 @@
}
if (ipa_gsb_ctx->iface[hdl]->is_resumed) {
- IPA_GSB_DBG("iface was already resumed\n");
+ IPA_GSB_DBG_LOW("iface was already resumed\n");
return 0;
}
@@ -946,7 +959,7 @@
ipa_gsb_ctx->iface[hdl]->is_resumed = true;
ipa_gsb_ctx->num_resumed_iface++;
- IPA_GSB_DBG("num resumed iface: %d\n",
+ IPA_GSB_DBG_LOW("num resumed iface: %d\n",
ipa_gsb_ctx->num_resumed_iface);
mutex_unlock(&ipa_gsb_ctx->lock);
@@ -963,7 +976,7 @@
return -EFAULT;
}
- IPA_GSB_DBG("client hdl: %d\n", hdl);
+ IPA_GSB_DBG_LOW("client hdl: %d\n", hdl);
if (!ipa_gsb_ctx->iface[hdl]->is_connected) {
IPA_GSB_ERR("iface is not connected\n");
@@ -971,7 +984,7 @@
}
if (!ipa_gsb_ctx->iface[hdl]->is_resumed) {
- IPA_GSB_DBG("iface was already suspended\n");
+ IPA_GSB_DBG_LOW("iface was already suspended\n");
return 0;
}
@@ -999,7 +1012,7 @@
ipa_gsb_ctx->iface[hdl]->is_resumed = false;
ipa_gsb_ctx->num_resumed_iface--;
- IPA_GSB_DBG("num resumed iface: %d\n",
+ IPA_GSB_DBG_LOW("num resumed iface: %d\n",
ipa_gsb_ctx->num_resumed_iface);
mutex_unlock(&ipa_gsb_ctx->lock);
@@ -1032,11 +1045,11 @@
struct sk_buff *skb2;
int ret;
- IPA_GSB_DBG("client hdl: %d\n", hdl);
+ IPA_GSB_DBG_LOW("client hdl: %d\n", hdl);
/* make sure skb has enough headroom */
if (unlikely(skb_headroom(skb) < sizeof(struct ipa_gsb_mux_hdr))) {
- IPA_GSB_DBG("skb doesn't have enough headroom\n");
+ IPA_GSB_DBG_LOW("skb doesn't have enough headroom\n");
skb2 = skb_copy_expand(skb, sizeof(struct ipa_gsb_mux_hdr),
0, GFP_ATOMIC);
if (!skb2) {
diff --git a/drivers/platform/msm/ipa/ipa_clients/ipa_mhi_client.c b/drivers/platform/msm/ipa/ipa_clients/ipa_mhi_client.c
index 906e911..b4af0a09 100644
--- a/drivers/platform/msm/ipa/ipa_clients/ipa_mhi_client.c
+++ b/drivers/platform/msm/ipa/ipa_clients/ipa_mhi_client.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2015, 2017 The Linux Foundation. All rights reserved.
+/* Copyright (c) 2015, 2017-2018 The Linux Foundation. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 and
@@ -24,13 +24,39 @@
#endif
#define IPA_MHI_DRV_NAME "ipa_mhi_client"
+
#define IPA_MHI_DBG(fmt, args...) \
- pr_debug(IPA_MHI_DRV_NAME " %s:%d " fmt, \
- __func__, __LINE__, ## args)
+ do { \
+ pr_debug(IPA_MHI_DRV_NAME " %s:%d " fmt, \
+ __func__, __LINE__, ## args); \
+ IPA_IPC_LOGGING(ipa_get_ipc_logbuf(), \
+ IPA_MHI_DRV_NAME " %s:%d " fmt, ## args); \
+ IPA_IPC_LOGGING(ipa_get_ipc_logbuf_low(), \
+ IPA_MHI_DRV_NAME " %s:%d " fmt, ## args); \
+ } while (0)
+
+#define IPA_MHI_DBG_LOW(fmt, args...) \
+ do { \
+ pr_debug(IPA_MHI_DRV_NAME " %s:%d " fmt, \
+ __func__, __LINE__, ## args); \
+ IPA_IPC_LOGGING(ipa_get_ipc_logbuf_low(), \
+ IPA_MHI_DRV_NAME " %s:%d " fmt, ## args); \
+ } while (0)
+
+
#define IPA_MHI_ERR(fmt, args...) \
- pr_err(IPA_MHI_DRV_NAME " %s:%d " fmt, __func__, __LINE__, ## args)
+ do { \
+ pr_err(IPA_MHI_DRV_NAME " %s:%d " fmt, \
+ __func__, __LINE__, ## args); \
+ IPA_IPC_LOGGING(ipa_get_ipc_logbuf(), \
+ IPA_MHI_DRV_NAME " %s:%d " fmt, ## args); \
+ IPA_IPC_LOGGING(ipa_get_ipc_logbuf_low(), \
+ IPA_MHI_DRV_NAME " %s:%d " fmt, ## args); \
+ } while (0)
+
#define IPA_MHI_FUNC_ENTRY() \
IPA_MHI_DBG("ENTRY\n")
+
#define IPA_MHI_FUNC_EXIT() \
IPA_MHI_DBG("EXIT\n")
diff --git a/drivers/platform/msm/ipa/ipa_clients/ipa_usb.c b/drivers/platform/msm/ipa/ipa_clients/ipa_usb.c
index c7df5cf..704308f 100644
--- a/drivers/platform/msm/ipa/ipa_clients/ipa_usb.c
+++ b/drivers/platform/msm/ipa/ipa_clients/ipa_usb.c
@@ -1336,7 +1336,12 @@
chan_params.chan_params.ring_base_addr =
params->xfer_ring_base_addr_iova;
chan_params.chan_params.ring_base_vaddr = NULL;
- chan_params.chan_params.use_db_eng = GSI_CHAN_DB_MODE;
+ if (ipa3_ctx->ipa_hw_type >= IPA_HW_v4_0)
+ chan_params.chan_params.use_db_eng = GSI_CHAN_DIRECT_MODE;
+ else
+ chan_params.chan_params.use_db_eng = GSI_CHAN_DB_MODE;
+ chan_params.chan_params.prefetch_mode =
+ ipa_get_ep_prefetch_mode(chan_params.client);
chan_params.chan_params.max_prefetch = GSI_ONE_PREFETCH_SEG;
if (params->dir == GSI_CHAN_DIR_FROM_GSI)
chan_params.chan_params.low_weight =
@@ -2947,6 +2952,7 @@
int i;
unsigned long flags;
int res;
+ struct ipa3_usb_pm_context *pm_ctx;
pr_debug("entry\n");
ipa3_usb_ctx = kzalloc(sizeof(struct ipa3_usb_context), GFP_KERNEL);
@@ -2966,19 +2972,13 @@
ipa3_usb_ctx->dl_data_pending = false;
mutex_init(&ipa3_usb_ctx->general_mutex);
- if (ipa_pm_is_used()) {
- struct ipa3_usb_pm_context *pm_ctx;
-
- pm_ctx =
- &ipa3_usb_ctx->ttype_ctx[IPA_USB_TRANSPORT_TETH].pm_ctx;
- pm_ctx->hdl = ~0;
- pm_ctx->remote_wakeup_work =
- &ipa3_usb_notify_remote_wakeup_work;
- pm_ctx = &ipa3_usb_ctx->ttype_ctx[IPA_USB_TRANSPORT_DPL].pm_ctx;
- pm_ctx->hdl = ~0;
- pm_ctx->remote_wakeup_work =
- &ipa3_usb_dpl_notify_remote_wakeup_work;
- }
+ /* init PM related members */
+ pm_ctx = &ipa3_usb_ctx->ttype_ctx[IPA_USB_TRANSPORT_TETH].pm_ctx;
+ pm_ctx->hdl = ~0;
+ pm_ctx->remote_wakeup_work = &ipa3_usb_notify_remote_wakeup_work;
+ pm_ctx = &ipa3_usb_ctx->ttype_ctx[IPA_USB_TRANSPORT_DPL].pm_ctx;
+ pm_ctx->hdl = ~0;
+ pm_ctx->remote_wakeup_work = &ipa3_usb_dpl_notify_remote_wakeup_work;
for (i = 0; i < IPA_USB_TRANSPORT_MAX; i++) {
ipa3_usb_ctx->ttype_ctx[i].rm_ctx.prod_valid = false;
diff --git a/drivers/platform/msm/ipa/ipa_v2/ipa_dp.c b/drivers/platform/msm/ipa/ipa_v2/ipa_dp.c
index 9f71d7b..ba98228 100644
--- a/drivers/platform/msm/ipa/ipa_v2/ipa_dp.c
+++ b/drivers/platform/msm/ipa/ipa_v2/ipa_dp.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2012-2017, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2012-2018, The Linux Foundation. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 and
@@ -2115,8 +2115,10 @@
goto fail_dma_mapping;
}
+ spin_lock_bh(&sys->spinlock);
list_add_tail(&rx_pkt->link, &sys->head_desc_list);
rx_len_cached = ++sys->len;
+ spin_unlock_bh(&sys->spinlock);
ret = sps_transfer_one(sys->ep->ep_hdl,
rx_pkt->data.dma_addr, sys->rx_buff_sz, rx_pkt, 0);
@@ -2130,8 +2132,10 @@
return;
fail_sps_transfer:
+ spin_lock_bh(&sys->spinlock);
list_del(&rx_pkt->link);
rx_len_cached = --sys->len;
+ spin_unlock_bh(&sys->spinlock);
dma_unmap_single(ipa_ctx->pdev, rx_pkt->data.dma_addr,
sys->rx_buff_sz, DMA_FROM_DEVICE);
fail_dma_mapping:
@@ -2171,8 +2175,10 @@
goto fail_dma_mapping;
}
+ spin_lock_bh(&sys->spinlock);
list_add_tail(&rx_pkt->link, &sys->head_desc_list);
rx_len_cached = ++sys->len;
+ spin_unlock_bh(&sys->spinlock);
ret = sps_transfer_one(sys->ep->ep_hdl,
rx_pkt->data.dma_addr, sys->rx_buff_sz, rx_pkt, 0);
@@ -2185,9 +2191,11 @@
return;
fail_sps_transfer:
+ spin_lock_bh(&sys->spinlock);
rx_len_cached = --sys->len;
list_del(&rx_pkt->link);
INIT_LIST_HEAD(&rx_pkt->link);
+ spin_unlock_bh(&sys->spinlock);
dma_unmap_single(ipa_ctx->pdev, rx_pkt->data.dma_addr,
sys->rx_buff_sz, DMA_FROM_DEVICE);
fail_dma_mapping:
@@ -2219,7 +2227,9 @@
}
rx_pkt = sys->repl.cache[curr];
+ spin_lock_bh(&sys->spinlock);
list_add_tail(&rx_pkt->link, &sys->head_desc_list);
+ spin_unlock_bh(&sys->spinlock);
ret = sps_transfer_one(sys->ep->ep_hdl,
rx_pkt->data.dma_addr, sys->rx_buff_sz, rx_pkt, 0);
@@ -2278,6 +2288,7 @@
u32 head;
u32 tail;
+ spin_lock_bh(&sys->spinlock);
list_for_each_entry_safe(rx_pkt, r,
&sys->head_desc_list, link) {
list_del(&rx_pkt->link);
@@ -2295,6 +2306,7 @@
sys->free_skb(rx_pkt->data.skb);
kmem_cache_free(ipa_ctx->rx_pkt_wrapper_cache, rx_pkt);
}
+ spin_unlock_bh(&sys->spinlock);
if (sys->repl.cache) {
head = atomic_read(&sys->repl.head_idx);
@@ -2976,8 +2988,10 @@
struct ipa_rx_pkt_wrapper *rx_pkt_expected;
struct sk_buff *rx_skb;
+ spin_lock_bh(&sys->spinlock);
if (unlikely(list_empty(&sys->head_desc_list))) {
WARN_ON(1);
+ spin_unlock_bh(&sys->spinlock);
return;
}
rx_pkt_expected = list_first_entry(&sys->head_desc_list,
@@ -2985,6 +2999,7 @@
link);
list_del(&rx_pkt_expected->link);
sys->len--;
+ spin_unlock_bh(&sys->spinlock);
if (size)
rx_pkt_expected->len = size;
rx_skb = rx_pkt_expected->data.skb;
@@ -3005,8 +3020,10 @@
struct ipa_rx_pkt_wrapper *rx_pkt_expected;
struct sk_buff *rx_skb;
+ spin_lock_bh(&sys->spinlock);
if (unlikely(list_empty(&sys->head_desc_list))) {
WARN_ON(1);
+ spin_unlock_bh(&sys->spinlock);
return;
}
rx_pkt_expected = list_first_entry(&sys->head_desc_list,
@@ -3014,6 +3031,7 @@
link);
list_del(&rx_pkt_expected->link);
sys->len--;
+ spin_unlock_bh(&sys->spinlock);
if (size)
rx_pkt_expected->len = size;
diff --git a/drivers/platform/msm/ipa/ipa_v3/ipa.c b/drivers/platform/msm/ipa/ipa_v3/ipa.c
index 82c8709..b46da99 100644
--- a/drivers/platform/msm/ipa/ipa_v3/ipa.c
+++ b/drivers/platform/msm/ipa/ipa_v3/ipa.c
@@ -2472,9 +2472,12 @@
/* disable statuses for all modem controlled prod pipes */
if (IPA_CLIENT_IS_Q6_PROD(client_idx) ||
(ipa3_ctx->ep[ep_idx].valid &&
- ipa3_ctx->ep[ep_idx].skip_ep_cfg)) {
+ ipa3_ctx->ep[ep_idx].skip_ep_cfg) ||
+ (ipa3_ctx->ep[ep_idx].client == IPA_CLIENT_APPS_WAN_PROD
+ && ipa3_ctx->modem_cfg_emb_pipe_flt)) {
ipa_assert_on(num_descs >= ipa3_ctx->ipa_num_pipes);
+ ipa3_ctx->ep[ep_idx].status.status_en = false;
reg_write.skip_pipeline_clear = false;
reg_write.pipeline_clear_options =
IPAHAL_HPS_CLEAR;
@@ -4279,7 +4282,7 @@
IPAERR("uC panic handler failed %d\n", res);
if (atomic_read(&ipa3_ctx->ipa3_active_clients.cnt) != 0)
- ipahal_print_all_regs();
+ ipahal_print_all_regs(false);
return NOTIFY_DONE;
}
@@ -5038,6 +5041,7 @@
ipa3_ctx->apply_rg10_wa = resource_p->apply_rg10_wa;
ipa3_ctx->gsi_ch20_wa = resource_p->gsi_ch20_wa;
ipa3_ctx->use_ipa_pm = resource_p->use_ipa_pm;
+ ipa3_ctx->wdi_over_pcie = resource_p->wdi_over_pcie;
ipa3_ctx->ipa3_active_clients_logging.log_rdy = false;
ipa3_ctx->ipa_config_is_mhi = resource_p->ipa_mhi_dynamic_config;
ipa3_ctx->mhi_evid_limits[0] = resource_p->mhi_evid_limits[0];
@@ -5869,6 +5873,12 @@
return result;
}
+ ipa_drv_res->wdi_over_pcie =
+ of_property_read_bool(pdev->dev.of_node,
+ "qcom,wlan-ce-db-over-pcie");
+ IPADBG("Is wdi_over_pcie ? (%s)\n",
+ ipa3_ctx->wdi_over_pcie ? "Yes":"No");
+
/*
* If we're on emulator, get its interrupt controller's mem
* start and size
@@ -6270,7 +6280,7 @@
iova_p, &pa_p, size_p);
ipa3_iommu_map(cb->mapping->domain,
iova_p, pa_p, size_p,
- IOMMU_READ | IOMMU_WRITE | IOMMU_MMIO);
+ IOMMU_READ | IOMMU_WRITE);
}
diff --git a/drivers/platform/msm/ipa/ipa_v3/ipa_debugfs.c b/drivers/platform/msm/ipa/ipa_v3/ipa_debugfs.c
index e10383c..10abdcf 100644
--- a/drivers/platform/msm/ipa/ipa_v3/ipa_debugfs.c
+++ b/drivers/platform/msm/ipa/ipa_v3/ipa_debugfs.c
@@ -1952,7 +1952,7 @@
size_t count, loff_t *ppos)
{
IPA_ACTIVE_CLIENTS_INC_SIMPLE();
- ipahal_print_all_regs();
+ ipahal_print_all_regs(true);
IPA_ACTIVE_CLIENTS_DEC_SIMPLE();
return 0;
diff --git a/drivers/platform/msm/ipa/ipa_v3/ipa_dp.c b/drivers/platform/msm/ipa/ipa_v3/ipa_dp.c
index 34f3265..7603152 100644
--- a/drivers/platform/msm/ipa/ipa_v3/ipa_dp.c
+++ b/drivers/platform/msm/ipa/ipa_v3/ipa_dp.c
@@ -35,6 +35,9 @@
#define IPA_GENERIC_AGGR_TIME_LIMIT 1
#define IPA_GENERIC_AGGR_PKT_LIMIT 0
+#define IPA_GSB_AGGR_BYTE_LIMIT 14
+#define IPA_GSB_RX_BUFF_BASE_SZ 16384
+
#define IPA_GENERIC_RX_BUFF_BASE_SZ 8192
#define IPA_REAL_GENERIC_RX_BUFF_SZ(X) (SKB_DATA_ALIGN(\
(X) + NET_SKB_PAD) +\
@@ -1061,6 +1064,13 @@
goto fail_gen2;
}
+ result = gsi_start_channel(ep->gsi_chan_hdl);
+ if (result != GSI_STATUS_SUCCESS) {
+ IPAERR("gsi_start_channel failed res=%d ep=%d.\n", result,
+ ipa_ep_idx);
+ goto fail_gen2;
+ }
+
if (!ep->keep_ipa_awake)
IPA_ACTIVE_CLIENTS_DEC_EP(sys_in->client);
@@ -2946,11 +2956,14 @@
/* recycle skb for GSB use case */
if (ipa3_ctx->ipa_hw_type >= IPA_HW_v4_0) {
sys->free_rx_wrapper =
- ipa3_recycle_rx_wrapper;
+ ipa3_free_rx_wrapper;
sys->repl_hdlr =
- ipa3_replenish_rx_cache_recycle;
+ ipa3_replenish_rx_cache;
+ /* Overwrite buffer size & aggr limit for GSB */
sys->rx_buff_sz = IPA_GENERIC_RX_BUFF_SZ(
- IPA_GENERIC_RX_BUFF_BASE_SZ);
+ IPA_GSB_RX_BUFF_BASE_SZ);
+ in->ipa_ep_cfg.aggr.aggr_byte_limit =
+ IPA_GSB_AGGR_BYTE_LIMIT;
} else {
sys->free_rx_wrapper =
ipa3_free_rx_wrapper;
@@ -3695,8 +3708,13 @@
ep->gsi_mem_info.chan_ring_base_vaddr =
gsi_channel_props.ring_base_vaddr;
- gsi_channel_props.use_db_eng = GSI_CHAN_DB_MODE;
+ if (ipa3_ctx->ipa_hw_type >= IPA_HW_v4_0)
+ gsi_channel_props.use_db_eng = GSI_CHAN_DIRECT_MODE;
+ else
+ gsi_channel_props.use_db_eng = GSI_CHAN_DB_MODE;
gsi_channel_props.max_prefetch = GSI_ONE_PREFETCH_SEG;
+ gsi_channel_props.prefetch_mode =
+ ipa_get_ep_prefetch_mode(ep->client);
if (ep->client == IPA_CLIENT_APPS_CMD_PROD)
gsi_channel_props.low_weight = IPA_GSI_MAX_CH_LOW_WEIGHT;
else
@@ -3730,15 +3748,11 @@
goto fail_write_channel_scratch;
}
- result = gsi_start_channel(ep->gsi_chan_hdl);
- if (result != GSI_STATUS_SUCCESS)
- goto fail_start_channel;
if (ep->client == IPA_CLIENT_MEMCPY_DMA_SYNC_CONS)
gsi_config_channel_mode(ep->gsi_chan_hdl,
GSI_CHAN_MODE_POLL);
return 0;
-fail_start_channel:
fail_write_channel_scratch:
if (gsi_dealloc_channel(ep->gsi_chan_hdl)
!= GSI_STATUS_SUCCESS) {
@@ -3935,7 +3949,12 @@
dma_alloc_coherent(ipa3_ctx->pdev, gsi_channel_props.ring_len,
&dma_addr, 0);
gsi_channel_props.ring_base_addr = dma_addr;
- gsi_channel_props.use_db_eng = GSI_CHAN_DB_MODE;
+
+ if (ipa3_ctx->ipa_hw_type >= IPA_HW_v4_0)
+ gsi_channel_props.use_db_eng = GSI_CHAN_DIRECT_MODE;
+ else
+ gsi_channel_props.use_db_eng = GSI_CHAN_DB_MODE;
+
gsi_channel_props.max_prefetch = GSI_ONE_PREFETCH_SEG;
gsi_channel_props.low_weight = 1;
gsi_channel_props.err_cb = ipa_gsi_chan_err_cb;
diff --git a/drivers/platform/msm/ipa/ipa_v3/ipa_flt.c b/drivers/platform/msm/ipa/ipa_v3/ipa_flt.c
index 6703bf5..b090151 100644
--- a/drivers/platform/msm/ipa/ipa_v3/ipa_flt.c
+++ b/drivers/platform/msm/ipa/ipa_v3/ipa_flt.c
@@ -1014,41 +1014,12 @@
goto error;
}
+ if (__ipa_validate_flt_rule(&frule->rule, &rt_tbl, ip))
+ goto error;
+
if (entry->rt_tbl)
entry->rt_tbl->ref_cnt--;
- if (frule->rule.action != IPA_PASS_TO_EXCEPTION) {
- if (!frule->rule.eq_attrib_type) {
- if (!frule->rule.rt_tbl_hdl) {
- IPAERR_RL("invalid RT tbl\n");
- goto error;
- }
-
- rt_tbl = ipa3_id_find(frule->rule.rt_tbl_hdl);
- if (rt_tbl == NULL) {
- IPAERR_RL("RT tbl not found\n");
- goto error;
- }
-
- if (rt_tbl->cookie != IPA_RT_TBL_COOKIE) {
- IPAERR_RL("RT table cookie is invalid\n");
- goto error;
- }
- } else {
- if (frule->rule.rt_tbl_idx > ((ip == IPA_IP_v4) ?
- IPA_MEM_PART(v4_modem_rt_index_hi) :
- IPA_MEM_PART(v6_modem_rt_index_hi))) {
- IPAERR_RL("invalid RT tbl\n");
- goto error;
- }
- }
- } else {
- if (frule->rule.rt_tbl_idx > 0) {
- IPAERR_RL("invalid RT tbl\n");
- goto error;
- }
- }
-
entry->rule = frule->rule;
entry->rt_tbl = rt_tbl;
if (entry->rt_tbl)
diff --git a/drivers/platform/msm/ipa/ipa_v3/ipa_i.h b/drivers/platform/msm/ipa/ipa_v3/ipa_i.h
index 268f5fa..43f4c74 100644
--- a/drivers/platform/msm/ipa/ipa_v3/ipa_i.h
+++ b/drivers/platform/msm/ipa/ipa_v3/ipa_i.h
@@ -1604,6 +1604,7 @@
struct mutex ipa_cne_evt_lock;
bool use_ipa_pm;
bool vlan_mode_iface[IPA_VLAN_IF_MAX];
+ bool wdi_over_pcie;
};
struct ipa3_plat_drv_res {
@@ -1638,6 +1639,7 @@
struct ipa_tz_unlock_reg_info *ipa_tz_unlock_reg;
bool use_ipa_pm;
struct ipa_pm_init_params pm_init;
+ bool wdi_over_pcie;
};
/**
@@ -2258,6 +2260,8 @@
*/
int ipa3_get_ep_mapping(enum ipa_client_type client);
+enum gsi_prefetch_mode ipa_get_ep_prefetch_mode(enum ipa_client_type client);
+
bool ipa3_is_ready(void);
void ipa3_proxy_clk_vote(void);
diff --git a/drivers/platform/msm/ipa/ipa_v3/ipa_mhi.c b/drivers/platform/msm/ipa/ipa_v3/ipa_mhi.c
index 82cd8187..dd97038 100644
--- a/drivers/platform/msm/ipa/ipa_v3/ipa_mhi.c
+++ b/drivers/platform/msm/ipa/ipa_v3/ipa_mhi.c
@@ -56,9 +56,9 @@
#define IPA_MHI_FUNC_ENTRY() \
- IPA_MHI_DBG_LOW("ENTRY\n")
+ IPA_MHI_DBG("ENTRY\n")
#define IPA_MHI_FUNC_EXIT() \
- IPA_MHI_DBG_LOW("EXIT\n")
+ IPA_MHI_DBG("EXIT\n")
#define IPA_MHI_MAX_UL_CHANNELS 1
#define IPA_MHI_MAX_DL_CHANNELS 1
@@ -198,6 +198,7 @@
union __packed gsi_channel_scratch ch_scratch;
struct ipa3_ep_context *ep;
const struct ipa_gsi_ep_config *ep_cfg;
+ bool burst_mode_enabled = false;
IPA_MHI_FUNC_ENTRY();
@@ -280,8 +281,21 @@
ch_props.ring_len = params->ch_ctx_host->rlen;
ch_props.ring_base_addr = IPA_MHI_HOST_ADDR_COND(
params->ch_ctx_host->rbase);
- ch_props.use_db_eng = GSI_CHAN_DB_MODE;
+
+ if (params->ch_ctx_host->brstmode == IPA_MHI_BURST_MODE_DEFAULT ||
+ params->ch_ctx_host->brstmode == IPA_MHI_BURST_MODE_ENABLE) {
+ burst_mode_enabled = true;
+ }
+
+ if (ipa3_ctx->ipa_hw_type >= IPA_HW_v4_0 &&
+ !burst_mode_enabled)
+ ch_props.use_db_eng = GSI_CHAN_DIRECT_MODE;
+ else
+ ch_props.use_db_eng = GSI_CHAN_DB_MODE;
+
ch_props.max_prefetch = GSI_ONE_PREFETCH_SEG;
+ ch_props.prefetch_mode =
+ ipa_get_ep_prefetch_mode(client);
ch_props.low_weight = 1;
ch_props.err_cb = params->ch_err_cb;
ch_props.chan_user_data = params->channel;
@@ -307,9 +321,9 @@
ch_scratch.mhi.outstanding_threshold = 0;
}
ch_scratch.mhi.oob_mod_threshold = 4;
- if (params->ch_ctx_host->brstmode == IPA_MHI_BURST_MODE_DEFAULT ||
- params->ch_ctx_host->brstmode == IPA_MHI_BURST_MODE_ENABLE) {
- ch_scratch.mhi.burst_mode_enabled = true;
+
+ if (burst_mode_enabled) {
+ ch_scratch.mhi.burst_mode_enabled = burst_mode_enabled;
ch_scratch.mhi.polling_configuration =
ipa3_mhi_get_ch_poll_cfg(client, params->ch_ctx_host,
(ch_props.ring_len / ch_props.re_size));
@@ -549,6 +563,7 @@
int res;
int ipa_ep_idx;
struct ipa3_ep_context *ep;
+ union __packed gsi_channel_scratch gsi_ch_scratch;
IPA_MHI_FUNC_ENTRY();
@@ -563,11 +578,34 @@
/*
* set polling mode bit to DB mode before
* resuming the channel
+ *
+ * For MHI-->IPA pipes:
+ * when resuming due to transition to M0,
+ * set the polling mode bit to 0.
+ * In other cases, restore it's value form
+ * when you stopped the channel.
+ * Here, after successful resume client move to M0 state.
+ * So, by default setting polling mode bit to 0.
+ *
+ * For IPA-->MHI pipe:
+ * always restore the polling mode bit.
*/
- res = gsi_write_channel_scratch(
- ep->gsi_chan_hdl, ch_scratch);
+
+ res = gsi_read_channel_scratch(
+ ep->gsi_chan_hdl, &gsi_ch_scratch);
if (res) {
- IPA_MHI_ERR("write ch scratch fail %d\n"
+ IPA_MHI_ERR("Read ch scratch fail %d\n"
+ , res);
+ return res;
+ }
+
+ if (IPA_CLIENT_IS_PROD(client))
+ gsi_ch_scratch.mhi.polling_mode = false;
+
+ res = gsi_write_channel_scratch(
+ ep->gsi_chan_hdl, gsi_ch_scratch);
+ if (res) {
+ IPA_MHI_ERR("Write ch scratch fail %d\n"
, res);
return res;
}
diff --git a/drivers/platform/msm/ipa/ipa_v3/ipa_uc_wdi.c b/drivers/platform/msm/ipa/ipa_v3/ipa_uc_wdi.c
index 13d2511..3cbc0c6 100644
--- a/drivers/platform/msm/ipa/ipa_v3/ipa_uc_wdi.c
+++ b/drivers/platform/msm/ipa/ipa_v3/ipa_uc_wdi.c
@@ -756,16 +756,21 @@
return -EINVAL;
}
- if (IPA_CLIENT_IS_CONS(in->sys.client)) {
- if (in->u.dl.comp_ring_base_pa % IPA_WDI_RING_ALIGNMENT ||
- in->u.dl.ce_ring_base_pa % IPA_WDI_RING_ALIGNMENT) {
- IPAERR("alignment failure on TX\n");
- return -EINVAL;
- }
- } else {
- if (in->u.ul.rdy_ring_base_pa % IPA_WDI_RING_ALIGNMENT) {
- IPAERR("alignment failure on RX\n");
- return -EINVAL;
+ if (!in->smmu_enabled) {
+ if (IPA_CLIENT_IS_CONS(in->sys.client)) {
+ if (in->u.dl.comp_ring_base_pa %
+ IPA_WDI_RING_ALIGNMENT ||
+ in->u.dl.ce_ring_base_pa %
+ IPA_WDI_RING_ALIGNMENT) {
+ IPAERR("alignment failure on TX\n");
+ return -EINVAL;
+ }
+ } else {
+ if (in->u.ul.rdy_ring_base_pa %
+ IPA_WDI_RING_ALIGNMENT) {
+ IPAERR("alignment failure on RX\n");
+ return -EINVAL;
+ }
}
}
@@ -795,43 +800,73 @@
cmd.size = sizeof(*tx_2);
else
cmd.size = sizeof(*tx);
- IPADBG("comp_ring_base_pa=0x%pa\n",
- &in->u.dl.comp_ring_base_pa);
- IPADBG("comp_ring_size=%d\n", in->u.dl.comp_ring_size);
- IPADBG("ce_ring_base_pa=0x%pa\n", &in->u.dl.ce_ring_base_pa);
- IPADBG("ce_ring_size=%d\n", in->u.dl.ce_ring_size);
- IPADBG("ce_ring_doorbell_pa=0x%pa\n",
- &in->u.dl.ce_door_bell_pa);
- IPADBG("num_tx_buffers=%d\n", in->u.dl.num_tx_buffers);
+ if (in->smmu_enabled) {
+ IPADBG("comp_ring_size=%d\n",
+ in->u.dl_smmu.comp_ring_size);
+ IPADBG("ce_ring_size=%d\n", in->u.dl_smmu.ce_ring_size);
+ IPADBG("ce_ring_doorbell_pa=0x%pa\n",
+ &in->u.dl_smmu.ce_door_bell_pa);
+ IPADBG("num_tx_buffers=%d\n",
+ in->u.dl_smmu.num_tx_buffers);
+ } else {
+ IPADBG("comp_ring_base_pa=0x%pa\n",
+ &in->u.dl.comp_ring_base_pa);
+ IPADBG("comp_ring_size=%d\n", in->u.dl.comp_ring_size);
+ IPADBG("ce_ring_base_pa=0x%pa\n",
+ &in->u.dl.ce_ring_base_pa);
+ IPADBG("ce_ring_size=%d\n", in->u.dl.ce_ring_size);
+ IPADBG("ce_ring_doorbell_pa=0x%pa\n",
+ &in->u.dl.ce_door_bell_pa);
+ IPADBG("num_tx_buffers=%d\n", in->u.dl.num_tx_buffers);
+ }
} else {
if (ipa3_ctx->ipa_wdi2)
cmd.size = sizeof(*rx_2);
else
cmd.size = sizeof(*rx);
- IPADBG("rx_ring_base_pa=0x%pa\n",
- &in->u.ul.rdy_ring_base_pa);
- IPADBG("rx_ring_size=%d\n",
- in->u.ul.rdy_ring_size);
- IPADBG("rx_ring_rp_pa=0x%pa\n",
- &in->u.ul.rdy_ring_rp_pa);
- IPADBG("rx_comp_ring_base_pa=0x%pa\n",
- &in->u.ul.rdy_comp_ring_base_pa);
- IPADBG("rx_comp_ring_size=%d\n",
- in->u.ul.rdy_comp_ring_size);
- IPADBG("rx_comp_ring_wp_pa=0x%pa\n",
- &in->u.ul.rdy_comp_ring_wp_pa);
- ipa3_ctx->uc_ctx.rdy_ring_base_pa =
- in->u.ul.rdy_ring_base_pa;
- ipa3_ctx->uc_ctx.rdy_ring_rp_pa =
- in->u.ul.rdy_ring_rp_pa;
- ipa3_ctx->uc_ctx.rdy_ring_size =
- in->u.ul.rdy_ring_size;
- ipa3_ctx->uc_ctx.rdy_comp_ring_base_pa =
- in->u.ul.rdy_comp_ring_base_pa;
- ipa3_ctx->uc_ctx.rdy_comp_ring_wp_pa =
- in->u.ul.rdy_comp_ring_wp_pa;
- ipa3_ctx->uc_ctx.rdy_comp_ring_size =
- in->u.ul.rdy_comp_ring_size;
+ if (in->smmu_enabled) {
+ IPADBG("rx_ring_size=%d\n",
+ in->u.ul_smmu.rdy_ring_size);
+ IPADBG("rx_ring_rp_pa=0x%pa\n",
+ &in->u.ul_smmu.rdy_ring_rp_pa);
+ IPADBG("rx_comp_ring_size=%d\n",
+ in->u.ul_smmu.rdy_comp_ring_size);
+ IPADBG("rx_comp_ring_wp_pa=0x%pa\n",
+ &in->u.ul_smmu.rdy_comp_ring_wp_pa);
+ ipa3_ctx->uc_ctx.rdy_ring_rp_pa =
+ in->u.ul_smmu.rdy_ring_rp_pa;
+ ipa3_ctx->uc_ctx.rdy_ring_size =
+ in->u.ul_smmu.rdy_ring_size;
+ ipa3_ctx->uc_ctx.rdy_comp_ring_wp_pa =
+ in->u.ul_smmu.rdy_comp_ring_wp_pa;
+ ipa3_ctx->uc_ctx.rdy_comp_ring_size =
+ in->u.ul_smmu.rdy_comp_ring_size;
+ } else {
+ IPADBG("rx_ring_base_pa=0x%pa\n",
+ &in->u.ul.rdy_ring_base_pa);
+ IPADBG("rx_ring_size=%d\n",
+ in->u.ul.rdy_ring_size);
+ IPADBG("rx_ring_rp_pa=0x%pa\n",
+ &in->u.ul.rdy_ring_rp_pa);
+ IPADBG("rx_comp_ring_base_pa=0x%pa\n",
+ &in->u.ul.rdy_comp_ring_base_pa);
+ IPADBG("rx_comp_ring_size=%d\n",
+ in->u.ul.rdy_comp_ring_size);
+ IPADBG("rx_comp_ring_wp_pa=0x%pa\n",
+ &in->u.ul.rdy_comp_ring_wp_pa);
+ ipa3_ctx->uc_ctx.rdy_ring_base_pa =
+ in->u.ul.rdy_ring_base_pa;
+ ipa3_ctx->uc_ctx.rdy_ring_rp_pa =
+ in->u.ul.rdy_ring_rp_pa;
+ ipa3_ctx->uc_ctx.rdy_ring_size =
+ in->u.ul.rdy_ring_size;
+ ipa3_ctx->uc_ctx.rdy_comp_ring_base_pa =
+ in->u.ul.rdy_comp_ring_base_pa;
+ ipa3_ctx->uc_ctx.rdy_comp_ring_wp_pa =
+ in->u.ul.rdy_comp_ring_wp_pa;
+ ipa3_ctx->uc_ctx.rdy_comp_ring_size =
+ in->u.ul.rdy_comp_ring_size;
+ }
}
cmd.base = dma_alloc_coherent(ipa3_ctx->uc_pdev, cmd.size,
@@ -945,10 +980,11 @@
tx->comp_ring_size = len;
len = in->smmu_enabled ? in->u.dl_smmu.ce_ring_size :
in->u.dl.ce_ring_size;
- IPADBG("TX CE ring smmu_en=%d ring_size=%d %d\n",
+ IPADBG("TX CE ring smmu_en=%d ring_size=%d %d 0x%lx\n",
in->smmu_enabled,
in->u.dl_smmu.ce_ring_size,
- in->u.dl.ce_ring_size);
+ in->u.dl.ce_ring_size,
+ va);
if (ipa_create_uc_smmu_mapping(IPA_WDI_CE_RING_RES,
in->smmu_enabled,
in->u.dl.ce_ring_base_pa,
@@ -975,8 +1011,19 @@
result = -ENOMEM;
goto uc_timeout;
}
- tx->ce_ring_doorbell_pa = va;
- tx->num_tx_buffers = in->u.dl.num_tx_buffers;
+
+ IPADBG("CE doorbell pa: 0x%pa va:0x%lx\n", &pa, va);
+ IPADBG("Is wdi_over_pcie ? (%s)\n",
+ ipa3_ctx->wdi_over_pcie ? "Yes":"No");
+
+ if (ipa3_ctx->wdi_over_pcie)
+ tx->ce_ring_doorbell_pa = pa;
+ else
+ tx->ce_ring_doorbell_pa = va;
+
+ tx->num_tx_buffers = in->smmu_enabled ?
+ in->u.dl_smmu.num_tx_buffers :
+ in->u.dl.num_tx_buffers;
tx->ipa_pipe_number = ipa_ep_idx;
}
out->uc_door_bell_pa = ipa3_ctx->ipa_wrapper_base +
diff --git a/drivers/platform/msm/ipa/ipa_v3/ipa_utils.c b/drivers/platform/msm/ipa/ipa_v3/ipa_utils.c
index 554023e..b7a561e 100644
--- a/drivers/platform/msm/ipa/ipa_v3/ipa_utils.c
+++ b/drivers/platform/msm/ipa/ipa_v3/ipa_utils.c
@@ -1126,86 +1126,86 @@
true,
IPA_DPS_HPS_REP_SEQ_TYPE_2PKT_PROC_PASS_NO_DEC_UCP_DMAP,
QMB_MASTER_SELECT_DDR,
- { 6, 2, 8, 16, IPA_EE_UC } },
+ { 6, 2, 8, 16, IPA_EE_UC, GSI_USE_PREFETCH_BUFS } },
[IPA_4_0][IPA_CLIENT_USB_PROD] = {
true, IPA_v4_0_GROUP_UL_DL,
true,
IPA_DPS_HPS_REP_SEQ_TYPE_2PKT_PROC_PASS_NO_DEC_UCP_DMAP,
QMB_MASTER_SELECT_DDR,
- { 0, 8, 8, 16, IPA_EE_AP } },
+ { 0, 8, 8, 16, IPA_EE_AP, GSI_ESCAPE_BUF_ONLY } },
[IPA_4_0][IPA_CLIENT_APPS_LAN_PROD] = {
true, IPA_v4_0_GROUP_UL_DL,
false,
IPA_DPS_HPS_SEQ_TYPE_2ND_PKT_PROCESS_PASS_NO_DEC_UCP,
QMB_MASTER_SELECT_DDR,
- { 8, 10, 8, 16, IPA_EE_AP } },
+ { 8, 10, 8, 16, IPA_EE_AP, GSI_ESCAPE_BUF_ONLY } },
[IPA_4_0][IPA_CLIENT_APPS_WAN_PROD] = {
true, IPA_v4_0_GROUP_UL_DL,
true,
IPA_DPS_HPS_REP_SEQ_TYPE_2PKT_PROC_PASS_NO_DEC_UCP_DMAP,
QMB_MASTER_SELECT_DDR,
- { 2, 3, 16, 32, IPA_EE_AP } },
+ { 2, 3, 16, 32, IPA_EE_AP, GSI_ESCAPE_BUF_ONLY } },
[IPA_4_0][IPA_CLIENT_APPS_CMD_PROD] = {
true, IPA_v4_0_GROUP_UL_DL,
false,
IPA_DPS_HPS_SEQ_TYPE_DMA_ONLY,
QMB_MASTER_SELECT_DDR,
- { 5, 4, 20, 24, IPA_EE_AP } },
+ { 5, 4, 20, 24, IPA_EE_AP, GSI_USE_PREFETCH_BUFS } },
[IPA_4_0][IPA_CLIENT_ODU_PROD] = {
true, IPA_v4_0_GROUP_UL_DL,
true,
IPA_DPS_HPS_REP_SEQ_TYPE_2PKT_PROC_PASS_NO_DEC_UCP_DMAP,
QMB_MASTER_SELECT_DDR,
- { 1, 0, 8, 16, IPA_EE_AP } },
+ { 1, 0, 8, 16, IPA_EE_AP, GSI_ESCAPE_BUF_ONLY } },
[IPA_4_0][IPA_CLIENT_ETHERNET_PROD] = {
true, IPA_v4_0_GROUP_UL_DL,
true,
IPA_DPS_HPS_REP_SEQ_TYPE_2PKT_PROC_PASS_NO_DEC_UCP_DMAP,
QMB_MASTER_SELECT_DDR,
- { 9, 0, 8, 16, IPA_EE_UC } },
+ { 9, 0, 8, 16, IPA_EE_UC, GSI_USE_PREFETCH_BUFS } },
[IPA_4_0][IPA_CLIENT_Q6_WAN_PROD] = {
true, IPA_v4_0_GROUP_UL_DL,
true,
IPA_DPS_HPS_SEQ_TYPE_2ND_PKT_PROCESS_PASS_NO_DEC_UCP,
QMB_MASTER_SELECT_DDR,
- { 3, 0, 16, 32, IPA_EE_Q6 } },
+ { 3, 0, 16, 32, IPA_EE_Q6, GSI_USE_PREFETCH_BUFS } },
[IPA_4_0][IPA_CLIENT_Q6_CMD_PROD] = {
true, IPA_v4_0_GROUP_UL_DL,
false,
IPA_DPS_HPS_SEQ_TYPE_PKT_PROCESS_NO_DEC_UCP,
QMB_MASTER_SELECT_DDR,
- { 4, 1, 20, 24, IPA_EE_Q6 } },
+ { 4, 1, 20, 24, IPA_EE_Q6, GSI_USE_PREFETCH_BUFS } },
/* Only for test purpose */
[IPA_4_0][IPA_CLIENT_TEST_PROD] = {
true, IPA_v4_0_GROUP_UL_DL,
true,
IPA_DPS_HPS_SEQ_TYPE_2ND_PKT_PROCESS_PASS_NO_DEC_UCP,
QMB_MASTER_SELECT_DDR,
- {0, 8, 8, 16, IPA_EE_AP } },
+ {0, 8, 8, 16, IPA_EE_AP, GSI_ESCAPE_BUF_ONLY } },
[IPA_4_0][IPA_CLIENT_TEST1_PROD] = {
true, IPA_v4_0_GROUP_UL_DL,
true,
IPA_DPS_HPS_SEQ_TYPE_2ND_PKT_PROCESS_PASS_NO_DEC_UCP,
QMB_MASTER_SELECT_DDR,
- {0, 8, 8, 16, IPA_EE_AP } },
+ {0, 8, 8, 16, IPA_EE_AP, GSI_ESCAPE_BUF_ONLY } },
[IPA_4_0][IPA_CLIENT_TEST2_PROD] = {
true, IPA_v4_0_GROUP_UL_DL,
true,
IPA_DPS_HPS_SEQ_TYPE_2ND_PKT_PROCESS_PASS_NO_DEC_UCP,
QMB_MASTER_SELECT_DDR,
- { 1, 0, 8, 16, IPA_EE_AP } },
+ { 1, 0, 8, 16, IPA_EE_AP, GSI_ESCAPE_BUF_ONLY } },
[IPA_4_0][IPA_CLIENT_TEST3_PROD] = {
true, IPA_v4_0_GROUP_UL_DL,
true,
IPA_DPS_HPS_SEQ_TYPE_2ND_PKT_PROCESS_PASS_NO_DEC_UCP,
QMB_MASTER_SELECT_DDR,
- { 7, 9, 8, 16, IPA_EE_AP } },
+ { 7, 9, 8, 16, IPA_EE_AP, GSI_USE_PREFETCH_BUFS } },
[IPA_4_0][IPA_CLIENT_TEST4_PROD] = {
true, IPA_v4_0_GROUP_UL_DL,
true,
IPA_DPS_HPS_SEQ_TYPE_2ND_PKT_PROCESS_PASS_NO_DEC_UCP,
QMB_MASTER_SELECT_DDR,
- {8, 10, 8, 16, IPA_EE_AP } },
+ {8, 10, 8, 16, IPA_EE_AP, GSI_ESCAPE_BUF_ONLY } },
[IPA_4_0][IPA_CLIENT_WLAN1_CONS] = {
@@ -1213,73 +1213,73 @@
false,
IPA_DPS_HPS_SEQ_TYPE_INVALID,
QMB_MASTER_SELECT_DDR,
- { 18, 3, 6, 9, IPA_EE_UC } },
+ { 18, 3, 6, 9, IPA_EE_UC, GSI_USE_PREFETCH_BUFS } },
[IPA_4_0][IPA_CLIENT_WLAN2_CONS] = {
true, IPA_v4_0_GROUP_UL_DL,
false,
IPA_DPS_HPS_SEQ_TYPE_INVALID,
QMB_MASTER_SELECT_DDR,
- { 20, 13, 9, 9, IPA_EE_AP } },
+ { 20, 13, 9, 9, IPA_EE_AP, GSI_USE_PREFETCH_BUFS } },
[IPA_4_0][IPA_CLIENT_WLAN3_CONS] = {
true, IPA_v4_0_GROUP_UL_DL,
false,
IPA_DPS_HPS_SEQ_TYPE_INVALID,
QMB_MASTER_SELECT_DDR,
- { 21, 14, 9, 9, IPA_EE_AP } },
+ { 21, 14, 9, 9, IPA_EE_AP, GSI_USE_PREFETCH_BUFS } },
[IPA_4_0][IPA_CLIENT_USB_CONS] = {
true, IPA_v4_0_GROUP_UL_DL,
false,
IPA_DPS_HPS_SEQ_TYPE_INVALID,
QMB_MASTER_SELECT_DDR,
- { 19, 12, 9, 9, IPA_EE_AP } },
+ { 19, 12, 9, 9, IPA_EE_AP, GSI_ESCAPE_BUF_ONLY } },
[IPA_4_0][IPA_CLIENT_USB_DPL_CONS] = {
true, IPA_v4_0_GROUP_UL_DL,
false,
IPA_DPS_HPS_SEQ_TYPE_INVALID,
QMB_MASTER_SELECT_DDR,
- { 15, 7, 5, 5, IPA_EE_AP } },
+ { 15, 7, 5, 5, IPA_EE_AP, GSI_ESCAPE_BUF_ONLY } },
[IPA_4_0][IPA_CLIENT_APPS_LAN_CONS] = {
true, IPA_v4_0_GROUP_UL_DL,
false,
IPA_DPS_HPS_SEQ_TYPE_INVALID,
QMB_MASTER_SELECT_DDR,
- { 10, 5, 9, 9, IPA_EE_AP } },
+ { 10, 5, 9, 9, IPA_EE_AP, GSI_ESCAPE_BUF_ONLY } },
[IPA_4_0][IPA_CLIENT_APPS_WAN_CONS] = {
true, IPA_v4_0_GROUP_UL_DL,
false,
IPA_DPS_HPS_SEQ_TYPE_INVALID,
QMB_MASTER_SELECT_DDR,
- { 11, 6, 9, 9, IPA_EE_AP } },
+ { 11, 6, 9, 9, IPA_EE_AP, GSI_ESCAPE_BUF_ONLY } },
[IPA_4_0][IPA_CLIENT_ODU_EMB_CONS] = {
true, IPA_v4_0_GROUP_UL_DL,
false,
IPA_DPS_HPS_SEQ_TYPE_INVALID,
QMB_MASTER_SELECT_DDR,
- { 17, 1, 17, 17, IPA_EE_AP } },
+ { 17, 1, 17, 17, IPA_EE_AP, GSI_USE_PREFETCH_BUFS } },
[IPA_4_0][IPA_CLIENT_ETHERNET_CONS] = {
true, IPA_v4_0_GROUP_UL_DL,
true,
IPA_DPS_HPS_SEQ_TYPE_INVALID,
QMB_MASTER_SELECT_DDR,
- { 22, 1, 17, 17, IPA_EE_UC } },
+ { 22, 1, 17, 17, IPA_EE_UC, GSI_USE_PREFETCH_BUFS } },
[IPA_4_0][IPA_CLIENT_Q6_LAN_CONS] = {
true, IPA_v4_0_GROUP_UL_DL,
false,
IPA_DPS_HPS_SEQ_TYPE_INVALID,
QMB_MASTER_SELECT_DDR,
- { 14, 4, 9, 9, IPA_EE_Q6 } },
+ { 14, 4, 9, 9, IPA_EE_Q6, GSI_USE_PREFETCH_BUFS } },
[IPA_4_0][IPA_CLIENT_Q6_WAN_CONS] = {
true, IPA_v4_0_GROUP_UL_DL,
false,
IPA_DPS_HPS_SEQ_TYPE_INVALID,
QMB_MASTER_SELECT_DDR,
- { 13, 3, 9, 9, IPA_EE_Q6 } },
+ { 13, 3, 9, 9, IPA_EE_Q6, GSI_USE_PREFETCH_BUFS } },
[IPA_4_0][IPA_CLIENT_Q6_LTE_WIFI_AGGR_CONS] = {
true, IPA_v4_0_GROUP_UL_DL,
false,
IPA_DPS_HPS_SEQ_TYPE_INVALID,
QMB_MASTER_SELECT_DDR,
- { 16, 5, 9, 9, IPA_EE_Q6 } },
+ { 16, 5, 9, 9, IPA_EE_Q6, GSI_USE_PREFETCH_BUFS } },
/* Only for test purpose */
/* MBIM aggregation test pipes should have the same QMB as USB_CONS */
[IPA_4_0][IPA_CLIENT_TEST_CONS] = {
@@ -1287,38 +1287,38 @@
false,
IPA_DPS_HPS_SEQ_TYPE_INVALID,
QMB_MASTER_SELECT_DDR,
- { 11, 6, 9, 9, IPA_EE_AP } },
+ { 11, 6, 9, 9, IPA_EE_AP, GSI_ESCAPE_BUF_ONLY } },
[IPA_4_0][IPA_CLIENT_TEST1_CONS] = {
true, IPA_v4_0_GROUP_UL_DL,
false,
IPA_DPS_HPS_SEQ_TYPE_INVALID,
QMB_MASTER_SELECT_DDR,
- { 11, 6, 9, 9, IPA_EE_AP } },
+ { 11, 6, 9, 9, IPA_EE_AP, GSI_ESCAPE_BUF_ONLY } },
[IPA_4_0][IPA_CLIENT_TEST2_CONS] = {
true, IPA_v4_0_GROUP_UL_DL,
false,
IPA_DPS_HPS_SEQ_TYPE_INVALID,
QMB_MASTER_SELECT_DDR,
- { 12, 2, 5, 5, IPA_EE_AP } },
+ { 12, 2, 5, 5, IPA_EE_AP, GSI_ESCAPE_BUF_ONLY } },
[IPA_4_0][IPA_CLIENT_TEST3_CONS] = {
true, IPA_v4_0_GROUP_UL_DL,
false,
IPA_DPS_HPS_SEQ_TYPE_INVALID,
QMB_MASTER_SELECT_DDR,
- { 19, 12, 9, 9, IPA_EE_AP } },
+ { 19, 12, 9, 9, IPA_EE_AP, GSI_ESCAPE_BUF_ONLY } },
[IPA_4_0][IPA_CLIENT_TEST4_CONS] = {
true, IPA_v4_0_GROUP_UL_DL,
false,
IPA_DPS_HPS_SEQ_TYPE_INVALID,
QMB_MASTER_SELECT_DDR,
- { 21, 14, 9, 9, IPA_EE_AP } },
+ { 21, 14, 9, 9, IPA_EE_AP, GSI_ESCAPE_BUF_ONLY } },
/* Dummy consumer (pipe 31) is used in L2TP rt rule */
[IPA_4_0][IPA_CLIENT_DUMMY_CONS] = {
true, IPA_v4_0_GROUP_UL_DL,
false,
IPA_DPS_HPS_SEQ_TYPE_INVALID,
QMB_MASTER_SELECT_DDR,
- { 31, 31, 8, 8, IPA_EE_AP } },
+ { 31, 31, 8, 8, IPA_EE_AP, GSI_USE_PREFETCH_BUFS } },
/* IPA_4_0_MHI */
[IPA_4_0_MHI][IPA_CLIENT_APPS_WAN_PROD] = {
@@ -1326,74 +1326,74 @@
true,
IPA_DPS_HPS_SEQ_TYPE_2ND_PKT_PROCESS_PASS_NO_DEC_UCP,
QMB_MASTER_SELECT_DDR,
- { 2, 3, 16, 32, IPA_EE_AP } },
+ { 2, 3, 16, 32, IPA_EE_AP, GSI_ESCAPE_BUF_ONLY } },
[IPA_4_0_MHI][IPA_CLIENT_APPS_CMD_PROD] = {
true, IPA_v4_0_MHI_GROUP_DDR,
false,
IPA_DPS_HPS_SEQ_TYPE_DMA_ONLY,
QMB_MASTER_SELECT_DDR,
- { 5, 4, 20, 24, IPA_EE_AP } },
+ { 5, 4, 20, 24, IPA_EE_AP, GSI_USE_PREFETCH_BUFS } },
[IPA_4_0_MHI][IPA_CLIENT_MHI_PROD] = {
true, IPA_v4_0_MHI_GROUP_PCIE,
true,
IPA_DPS_HPS_SEQ_TYPE_2ND_PKT_PROCESS_PASS_NO_DEC_UCP,
QMB_MASTER_SELECT_PCIE,
- { 1, 0, 8, 16, IPA_EE_AP } },
+ { 1, 0, 8, 16, IPA_EE_AP, GSI_USE_PREFETCH_BUFS } },
[IPA_4_0_MHI][IPA_CLIENT_Q6_WAN_PROD] = {
true, IPA_v4_0_GROUP_UL_DL,
true,
IPA_DPS_HPS_SEQ_TYPE_PKT_PROCESS_NO_DEC_UCP,
QMB_MASTER_SELECT_DDR,
- { 3, 0, 16, 32, IPA_EE_Q6 } },
+ { 3, 0, 16, 32, IPA_EE_Q6, GSI_USE_PREFETCH_BUFS } },
[IPA_4_0_MHI][IPA_CLIENT_Q6_CMD_PROD] = {
true, IPA_v4_0_MHI_GROUP_PCIE,
false,
IPA_DPS_HPS_SEQ_TYPE_PKT_PROCESS_NO_DEC_UCP,
QMB_MASTER_SELECT_DDR,
- { 4, 1, 20, 24, IPA_EE_Q6 } },
+ { 4, 1, 20, 24, IPA_EE_Q6, GSI_USE_PREFETCH_BUFS } },
[IPA_4_0_MHI][IPA_CLIENT_MEMCPY_DMA_SYNC_PROD] = {
true, IPA_v4_0_MHI_GROUP_DMA,
false,
IPA_DPS_HPS_SEQ_TYPE_DMA_ONLY,
QMB_MASTER_SELECT_DDR,
- { 7, 9, 8, 16, IPA_EE_AP } },
+ { 7, 9, 8, 16, IPA_EE_AP, GSI_ESCAPE_BUF_ONLY } },
[IPA_4_0_MHI][IPA_CLIENT_MEMCPY_DMA_ASYNC_PROD] = {
true, IPA_v4_0_MHI_GROUP_DMA,
false,
IPA_DPS_HPS_SEQ_TYPE_DMA_ONLY,
QMB_MASTER_SELECT_DDR,
- { 8, 10, 8, 16, IPA_EE_AP } },
+ { 8, 10, 8, 16, IPA_EE_AP, GSI_ESCAPE_BUF_ONLY } },
/* Only for test purpose */
[IPA_4_0_MHI][IPA_CLIENT_TEST_PROD] = {
true, IPA_v4_0_GROUP_UL_DL,
true,
IPA_DPS_HPS_SEQ_TYPE_2ND_PKT_PROCESS_PASS_NO_DEC_UCP,
QMB_MASTER_SELECT_DDR,
- {0, 8, 8, 16, IPA_EE_AP } },
+ {0, 8, 8, 16, IPA_EE_AP, GSI_ESCAPE_BUF_ONLY } },
[IPA_4_0_MHI][IPA_CLIENT_TEST1_PROD] = {
true, IPA_v4_0_GROUP_UL_DL,
true,
IPA_DPS_HPS_SEQ_TYPE_2ND_PKT_PROCESS_PASS_NO_DEC_UCP,
QMB_MASTER_SELECT_DDR,
- {0, 8, 8, 16, IPA_EE_AP } },
+ {0, 8, 8, 16, IPA_EE_AP, GSI_ESCAPE_BUF_ONLY } },
[IPA_4_0_MHI][IPA_CLIENT_TEST2_PROD] = {
true, IPA_v4_0_GROUP_UL_DL,
true,
IPA_DPS_HPS_SEQ_TYPE_2ND_PKT_PROCESS_PASS_NO_DEC_UCP,
QMB_MASTER_SELECT_DDR,
- { 1, 0, 8, 16, IPA_EE_AP } },
+ { 1, 0, 8, 16, IPA_EE_AP, GSI_USE_PREFETCH_BUFS } },
[IPA_4_0_MHI][IPA_CLIENT_TEST3_PROD] = {
true, IPA_v4_0_GROUP_UL_DL,
true,
IPA_DPS_HPS_SEQ_TYPE_2ND_PKT_PROCESS_PASS_NO_DEC_UCP,
QMB_MASTER_SELECT_DDR,
- {7, 9, 8, 16, IPA_EE_AP } },
+ {7, 9, 8, 16, IPA_EE_AP, GSI_ESCAPE_BUF_ONLY } },
[IPA_4_0_MHI][IPA_CLIENT_TEST4_PROD] = {
true, IPA_v4_0_GROUP_UL_DL,
true,
IPA_DPS_HPS_SEQ_TYPE_2ND_PKT_PROCESS_PASS_NO_DEC_UCP,
QMB_MASTER_SELECT_DDR,
- { 8, 10, 8, 16, IPA_EE_AP } },
+ { 8, 10, 8, 16, IPA_EE_AP, GSI_ESCAPE_BUF_ONLY } },
[IPA_4_0_MHI][IPA_CLIENT_APPS_LAN_CONS] = {
@@ -1401,87 +1401,87 @@
false,
IPA_DPS_HPS_SEQ_TYPE_INVALID,
QMB_MASTER_SELECT_DDR,
- { 10, 5, 9, 9, IPA_EE_AP } },
+ { 10, 5, 9, 9, IPA_EE_AP, GSI_ESCAPE_BUF_ONLY } },
[IPA_4_0_MHI][IPA_CLIENT_APPS_WAN_CONS] = {
true, IPA_v4_0_MHI_GROUP_DDR,
false,
IPA_DPS_HPS_SEQ_TYPE_INVALID,
QMB_MASTER_SELECT_DDR,
- { 11, 6, 9, 9, IPA_EE_AP } },
+ { 11, 6, 9, 9, IPA_EE_AP, GSI_ESCAPE_BUF_ONLY } },
[IPA_4_0_MHI][IPA_CLIENT_MHI_CONS] = {
true, IPA_v4_0_MHI_GROUP_PCIE,
false,
IPA_DPS_HPS_SEQ_TYPE_INVALID,
QMB_MASTER_SELECT_PCIE,
- { 17, 1, 17, 17, IPA_EE_AP } },
+ { 17, 1, 17, 17, IPA_EE_AP, GSI_USE_PREFETCH_BUFS } },
[IPA_4_0_MHI][IPA_CLIENT_Q6_LAN_CONS] = {
true, IPA_v4_0_MHI_GROUP_DDR,
false,
IPA_DPS_HPS_SEQ_TYPE_INVALID,
QMB_MASTER_SELECT_DDR,
- { 14, 4, 9, 9, IPA_EE_Q6 } },
+ { 14, 4, 9, 9, IPA_EE_Q6, GSI_USE_PREFETCH_BUFS } },
[IPA_4_0_MHI][IPA_CLIENT_Q6_WAN_CONS] = {
true, IPA_v4_0_MHI_GROUP_DDR,
false,
IPA_DPS_HPS_SEQ_TYPE_INVALID,
QMB_MASTER_SELECT_DDR,
- { 13, 3, 9, 9, IPA_EE_Q6 } },
+ { 13, 3, 9, 9, IPA_EE_Q6, GSI_USE_PREFETCH_BUFS } },
[IPA_4_0_MHI][IPA_CLIENT_MEMCPY_DMA_SYNC_CONS] = {
true, IPA_v4_0_MHI_GROUP_DMA,
false,
IPA_DPS_HPS_SEQ_TYPE_INVALID,
QMB_MASTER_SELECT_PCIE,
- { 20, 13, 9, 9, IPA_EE_AP } },
+ { 20, 13, 9, 9, IPA_EE_AP, GSI_ESCAPE_BUF_ONLY } },
[IPA_4_0_MHI][IPA_CLIENT_MEMCPY_DMA_ASYNC_CONS] = {
true, IPA_v4_0_MHI_GROUP_DMA,
false,
IPA_DPS_HPS_SEQ_TYPE_INVALID,
QMB_MASTER_SELECT_PCIE,
- { 21, 14, 9, 9, IPA_EE_AP } },
+ { 21, 14, 9, 9, IPA_EE_AP, GSI_ESCAPE_BUF_ONLY } },
[IPA_4_0_MHI][IPA_CLIENT_Q6_LTE_WIFI_AGGR_CONS] = {
true, IPA_v4_0_GROUP_UL_DL,
false,
IPA_DPS_HPS_SEQ_TYPE_INVALID,
QMB_MASTER_SELECT_DDR,
- { 16, 5, 9, 9, IPA_EE_Q6 } },
+ { 16, 5, 9, 9, IPA_EE_Q6, GSI_USE_PREFETCH_BUFS } },
/* Only for test purpose */
[IPA_4_0_MHI][IPA_CLIENT_TEST_CONS] = {
true, IPA_v4_0_GROUP_UL_DL,
false,
IPA_DPS_HPS_SEQ_TYPE_INVALID,
QMB_MASTER_SELECT_PCIE,
- { 11, 6, 9, 9, IPA_EE_AP } },
+ { 11, 6, 9, 9, IPA_EE_AP, GSI_ESCAPE_BUF_ONLY } },
[IPA_4_0_MHI][IPA_CLIENT_TEST1_CONS] = {
true, IPA_v4_0_GROUP_UL_DL,
false,
IPA_DPS_HPS_SEQ_TYPE_INVALID,
QMB_MASTER_SELECT_PCIE,
- { 11, 6, 9, 9, IPA_EE_AP } },
+ { 11, 6, 9, 9, IPA_EE_AP, GSI_ESCAPE_BUF_ONLY } },
[IPA_4_0_MHI][IPA_CLIENT_TEST2_CONS] = {
true, IPA_v4_0_GROUP_UL_DL,
false,
IPA_DPS_HPS_SEQ_TYPE_INVALID,
QMB_MASTER_SELECT_DDR,
- { 12, 2, 5, 5, IPA_EE_AP } },
+ { 12, 2, 5, 5, IPA_EE_AP, GSI_ESCAPE_BUF_ONLY } },
[IPA_4_0_MHI][IPA_CLIENT_TEST3_CONS] = {
true, IPA_v4_0_GROUP_UL_DL,
false,
IPA_DPS_HPS_SEQ_TYPE_INVALID,
QMB_MASTER_SELECT_PCIE,
- { 19, 12, 9, 9, IPA_EE_AP } },
+ { 19, 12, 9, 9, IPA_EE_AP, GSI_ESCAPE_BUF_ONLY } },
[IPA_4_0_MHI][IPA_CLIENT_TEST4_CONS] = {
true, IPA_v4_0_GROUP_UL_DL,
false,
IPA_DPS_HPS_SEQ_TYPE_INVALID,
QMB_MASTER_SELECT_PCIE,
- { 21, 14, 9, 9, IPA_EE_AP } },
+ { 21, 14, 9, 9, IPA_EE_AP, GSI_ESCAPE_BUF_ONLY } },
/* Dummy consumer (pipe 31) is used in L2TP rt rule */
[IPA_4_0_MHI][IPA_CLIENT_DUMMY_CONS] = {
true, IPA_v4_0_GROUP_UL_DL,
false,
IPA_DPS_HPS_SEQ_TYPE_INVALID,
QMB_MASTER_SELECT_DDR,
- { 31, 31, 8, 8, IPA_EE_AP } },
+ { 31, 31, 8, 8, IPA_EE_AP, GSI_USE_PREFETCH_BUFS } },
};
/**
@@ -1972,6 +1972,29 @@
IPADBG("ipa_qmb_select_by_address_cons_en = %d\n",
comp_cfg.ipa_qmb_select_by_address_cons_en);
}
+
+ if (ipa3_ctx->ipa_hw_type >= IPA_HW_v4_0) {
+ ipahal_read_reg_fields(IPA_COMP_CFG, &comp_cfg);
+ IPADBG("Before comp config\n");
+ IPADBG("gsi_multi_inorder_rd_dis = %d\n",
+ comp_cfg.gsi_multi_inorder_rd_dis);
+
+ IPADBG("gsi_multi_inorder_wr_dis = %d\n",
+ comp_cfg.gsi_multi_inorder_wr_dis);
+
+ comp_cfg.gsi_multi_inorder_rd_dis = true;
+ comp_cfg.gsi_multi_inorder_wr_dis = true;
+
+ ipahal_write_reg_fields(IPA_COMP_CFG, &comp_cfg);
+
+ ipahal_read_reg_fields(IPA_COMP_CFG, &comp_cfg);
+ IPADBG("After comp config\n");
+ IPADBG("gsi_multi_inorder_rd_dis = %d\n",
+ comp_cfg.gsi_multi_inorder_rd_dis);
+
+ IPADBG("gsi_multi_inorder_wr_dis = %d\n",
+ comp_cfg.gsi_multi_inorder_wr_dis);
+ }
}
/**
@@ -2133,6 +2156,28 @@
return ipa_ep_idx;
}
+
+/**
+ * ipa_get_ep_prefetch_mode() - provide prefetch_mode endpoint
+ * @client: client type
+ *
+ * Return value: prefetch_mode
+ */
+enum gsi_prefetch_mode ipa_get_ep_prefetch_mode(enum ipa_client_type client)
+{
+ enum gsi_prefetch_mode prefetch_mode;
+
+ if (client >= IPA_CLIENT_MAX || client < 0) {
+ IPAERR_RL("Bad client number: client =%d\n", client);
+ return -IPA_EP_NOT_ALLOCATED;
+ }
+
+ prefetch_mode = ipa3_ep_mapping[ipa3_get_hw_type_index()][client].
+ ipa_gsi_ep_info.prefetch_mode;
+
+ return prefetch_mode;
+}
+
/**
* ipa3_get_gsi_ep_info() - provide gsi ep information
* @client: IPA client value
diff --git a/drivers/platform/msm/ipa/ipa_v3/ipahal/ipahal_i.h b/drivers/platform/msm/ipa/ipa_v3/ipahal/ipahal_i.h
index 26b7f0f..d46f13c 100644
--- a/drivers/platform/msm/ipa/ipa_v3/ipahal/ipahal_i.h
+++ b/drivers/platform/msm/ipa/ipa_v3/ipahal/ipahal_i.h
@@ -55,6 +55,14 @@
" %s:%d " fmt, ## args); \
} while (0)
+#define IPAHAL_DBG_REG_IPC_ONLY(fmt, args...) \
+ do { \
+ IPA_IPC_LOGGING(ipa_get_ipc_logbuf(), \
+ " %s:%d " fmt, ## args); \
+ IPA_IPC_LOGGING(ipa_get_ipc_logbuf_low(), \
+ " %s:%d " fmt, ## args); \
+ } while (0)
+
#define IPAHAL_ERR_RL(fmt, args...) \
do { \
pr_err_ratelimited_ipa(IPAHAL_DRV_NAME " %s:%d " fmt, \
diff --git a/drivers/platform/msm/ipa/ipa_v3/ipahal/ipahal_reg.c b/drivers/platform/msm/ipa/ipa_v3/ipahal/ipahal_reg.c
index cc70ac1..2dbea95 100644
--- a/drivers/platform/msm/ipa/ipa_v3/ipahal/ipahal_reg.c
+++ b/drivers/platform/msm/ipa/ipa_v3/ipahal/ipahal_reg.c
@@ -2237,7 +2237,7 @@
0x00000CC0, 0x70, 10, 23, 1},
};
-int ipahal_print_all_regs(void)
+int ipahal_print_all_regs(bool print_to_dmesg)
{
int i, j;
@@ -2256,9 +2256,16 @@
j = ipahal_reg_objs[ipahal_ctx->hw_type][i].n_start;
- if (j == ipahal_reg_objs[ipahal_ctx->hw_type][i].n_end)
- IPAHAL_DBG_REG("%s=0x%x\n", ipahal_reg_name_str(i),
- ipahal_read_reg_n(i, j));
+ if (j == ipahal_reg_objs[ipahal_ctx->hw_type][i].n_end) {
+ if (print_to_dmesg)
+ IPAHAL_DBG_REG("%s=0x%x\n",
+ ipahal_reg_name_str(i),
+ ipahal_read_reg_n(i, j));
+ else
+ IPAHAL_DBG_REG_IPC_ONLY("%s=0x%x\n",
+ ipahal_reg_name_str(i),
+ ipahal_read_reg_n(i, j));
+ }
for (; j < ipahal_reg_objs[ipahal_ctx->hw_type][i].n_end; j++)
IPAHAL_DBG_REG("%s_%u=0x%x\n", ipahal_reg_name_str(i),
diff --git a/drivers/platform/msm/ipa/ipa_v3/ipahal/ipahal_reg.h b/drivers/platform/msm/ipa/ipa_v3/ipahal/ipahal_reg.h
index ea741ba..fdf4fd1 100644
--- a/drivers/platform/msm/ipa/ipa_v3/ipahal/ipahal_reg.h
+++ b/drivers/platform/msm/ipa/ipa_v3/ipahal/ipahal_reg.h
@@ -524,7 +524,7 @@
};
-int ipahal_print_all_regs(void);
+int ipahal_print_all_regs(bool print_to_dmesg);
/*
* ipahal_reg_name_str() - returns string that represent the register
diff --git a/drivers/platform/msm/mhi_dev/mhi.c b/drivers/platform/msm/mhi_dev/mhi.c
index f06d6f3..3e577cf 100644
--- a/drivers/platform/msm/mhi_dev/mhi.c
+++ b/drivers/platform/msm/mhi_dev/mhi.c
@@ -824,13 +824,13 @@
}
EXPORT_SYMBOL(mhi_dev_send_ee_event);
-static void mhi_dev_trigger_cb(void)
+static void mhi_dev_trigger_cb(enum mhi_client_channel ch_id)
{
struct mhi_dev_ready_cb_info *info;
enum mhi_ctrl_info state_data;
list_for_each_entry(info, &mhi_ctx->client_cb_list, list)
- if (info->cb) {
+ if (info->cb && info->cb_data.channel == ch_id) {
mhi_ctrl_state_info(info->cb_data.channel, &state_data);
info->cb_data.ctrl_info = state_data;
info->cb(&info->cb_data);
@@ -1023,7 +1023,7 @@
mhi_update_state_info(ch_id, MHI_STATE_CONNECTED);
/* Trigger callback to clients */
- mhi_dev_trigger_cb();
+ mhi_dev_trigger_cb(ch_id);
if (ch_id == MHI_CLIENT_MBIM_OUT)
kobject_uevent_env(&mhi_ctx->dev->kobj,
KOBJ_CHANGE, connected);
@@ -1572,6 +1572,12 @@
{
struct mhi_dev *mhi = dev_id;
+ if (!atomic_read(&mhi->mhi_dev_wake)) {
+ pm_stay_awake(mhi->dev);
+ atomic_set(&mhi->mhi_dev_wake, 1);
+ mhi_log(MHI_MSG_VERBOSE, "acquiring mhi wakelock in ISR\n");
+ }
+
disable_irq_nosync(mhi->mhi_irq);
schedule_work(&mhi->chdb_ctrl_work);
mhi_log(MHI_MSG_VERBOSE, "mhi irq triggered\n");
@@ -2403,8 +2409,10 @@
return;
}
- if (mhi_ctx->config_iatu || mhi_ctx->mhi_int)
+ if (mhi_ctx->config_iatu || mhi_ctx->mhi_int) {
+ mhi_ctx->mhi_int_en = true;
enable_irq(mhi_ctx->mhi_irq);
+ }
mhi_update_state_info(MHI_DEV_UEVENT_CTRL, MHI_STATE_CONFIGURED);
}
diff --git a/drivers/platform/msm/mhi_dev/mhi.h b/drivers/platform/msm/mhi_dev/mhi.h
index 2dfa58d..2cc7809 100644
--- a/drivers/platform/msm/mhi_dev/mhi.h
+++ b/drivers/platform/msm/mhi_dev/mhi.h
@@ -605,6 +605,8 @@
/*Register for interrupt */
bool mhi_int;
+ bool mhi_int_en;
+
/* Registered client callback list */
struct list_head client_cb_list;
diff --git a/drivers/platform/msm/mhi_dev/mhi_sm.c b/drivers/platform/msm/mhi_dev/mhi_sm.c
index 1200a36..af05c9e 100644
--- a/drivers/platform/msm/mhi_dev/mhi_sm.c
+++ b/drivers/platform/msm/mhi_dev/mhi_sm.c
@@ -19,6 +19,7 @@
#include <linux/ipa_mhi.h>
#include "mhi_hwio.h"
#include "mhi_sm.h"
+#include <linux/interrupt.h>
#define MHI_SM_DBG(fmt, args...) \
mhi_log(MHI_MSG_DBG, fmt, ##args)
@@ -775,6 +776,7 @@
struct mhi_sm_ep_pcie_event *chg_event = container_of(work,
struct mhi_sm_ep_pcie_event, work);
enum ep_pcie_event pcie_event = chg_event->event;
+ unsigned long flags;
MHI_SM_FUNC_ENTRY();
@@ -846,6 +848,15 @@
mhi_dev_restore_mmio(mhi_sm_ctx->mhi_dev);
+ spin_lock_irqsave(&mhi_sm_ctx->mhi_dev->lock, flags);
+ if ((mhi_sm_ctx->mhi_dev->mhi_int) &&
+ (!mhi_sm_ctx->mhi_dev->mhi_int_en)) {
+ enable_irq(mhi_sm_ctx->mhi_dev->mhi_irq);
+ mhi_sm_ctx->mhi_dev->mhi_int_en = true;
+ MHI_SM_DBG("Enable MHI IRQ during PCIe DEAST");
+ }
+ spin_unlock_irqrestore(&mhi_sm_ctx->mhi_dev->lock, flags);
+
res = ep_pcie_enable_endpoint(mhi_sm_ctx->mhi_dev->phandle,
EP_PCIE_OPT_ENUM);
if (res) {
@@ -1141,6 +1152,7 @@
{
struct mhi_sm_ep_pcie_event *dstate_change_evt;
enum ep_pcie_event event;
+ unsigned long flags;
MHI_SM_FUNC_ENTRY();
@@ -1173,6 +1185,16 @@
break;
case EP_PCIE_EVENT_PM_D3_HOT:
mhi_sm_ctx->stats.d3_hot_event_cnt++;
+
+ spin_lock_irqsave(&mhi_sm_ctx->mhi_dev->lock, flags);
+ if ((mhi_sm_ctx->mhi_dev->mhi_int) &&
+ (mhi_sm_ctx->mhi_dev->mhi_int_en)) {
+ disable_irq(mhi_sm_ctx->mhi_dev->mhi_irq);
+ mhi_sm_ctx->mhi_dev->mhi_int_en = false;
+ MHI_SM_DBG("Disable MHI IRQ during D3 HOT");
+ }
+ spin_unlock_irqrestore(&mhi_sm_ctx->mhi_dev->lock, flags);
+
mhi_dev_backup_mmio(mhi_sm_ctx->mhi_dev);
break;
case EP_PCIE_EVENT_PM_RST_DEAST:
@@ -1180,6 +1202,15 @@
break;
case EP_PCIE_EVENT_PM_D0:
mhi_sm_ctx->stats.d0_event_cnt++;
+
+ spin_lock_irqsave(&mhi_sm_ctx->mhi_dev->lock, flags);
+ if ((mhi_sm_ctx->mhi_dev->mhi_int) &&
+ (!mhi_sm_ctx->mhi_dev->mhi_int_en)) {
+ enable_irq(mhi_sm_ctx->mhi_dev->mhi_irq);
+ mhi_sm_ctx->mhi_dev->mhi_int_en = true;
+ MHI_SM_DBG("Enable MHI IRQ during D0");
+ }
+ spin_unlock_irqrestore(&mhi_sm_ctx->mhi_dev->lock, flags);
break;
case EP_PCIE_EVENT_LINKDOWN:
mhi_sm_ctx->stats.linkdown_event_cnt++;
diff --git a/drivers/platform/msm/usb_bam.c b/drivers/platform/msm/usb_bam.c
index 9374bc8..aafb5c8 100644
--- a/drivers/platform/msm/usb_bam.c
+++ b/drivers/platform/msm/usb_bam.c
@@ -1119,7 +1119,7 @@
&ctx->usb_bam_connections[idx];
unsigned long peer_bam_handle;
- ret = sps_phy2h(pipe_connect->dst_phy_addr, &peer_bam_handle);
+ ret = sps_phy2h(pipe_connect->src_phy_addr, &peer_bam_handle);
if (ret) {
log_event_err("%s: sps_phy2h failed (src BAM) %d\n",
__func__, ret);
diff --git a/drivers/power/supply/power_supply_sysfs.c b/drivers/power/supply/power_supply_sysfs.c
index 3ab93fe..8281c41 100644
--- a/drivers/power/supply/power_supply_sysfs.c
+++ b/drivers/power/supply/power_supply_sysfs.c
@@ -335,6 +335,10 @@
POWER_SUPPLY_ATTR(battery_info),
POWER_SUPPLY_ATTR(battery_info_id),
POWER_SUPPLY_ATTR(enable_jeita_detection),
+ POWER_SUPPLY_ATTR(esr_actual),
+ POWER_SUPPLY_ATTR(esr_nominal),
+ POWER_SUPPLY_ATTR(soh),
+ POWER_SUPPLY_ATTR(qc_opti_disable),
/* Local extensions of type int64_t */
POWER_SUPPLY_ATTR(charge_counter_ext),
/* Properties of type `const char *' */
diff --git a/drivers/power/supply/qcom/fg-alg.c b/drivers/power/supply/qcom/fg-alg.c
index 4003679..f3f2c66 100644
--- a/drivers/power/supply/qcom/fg-alg.c
+++ b/drivers/power/supply/qcom/fg-alg.c
@@ -803,9 +803,31 @@
i, soc_per_step, msoc_this_step, msoc_next_step,
ibatt_this_step, t_predicted_this_step, ttf_slope,
t_predicted_cv, t_predicted = 0, charge_type = 0,
- float_volt_uv = 0;
+ float_volt_uv = 0, valid = 0, charge_status = 0;
s64 delta_ms;
+ rc = ttf->get_ttf_param(ttf->data, TTF_VALID, &valid);
+ if (rc < 0) {
+ pr_err("failed to get ttf_valid rc=%d\n", rc);
+ return rc;
+ }
+
+ if (!valid) {
+ *val = -EINVAL;
+ return 0;
+ }
+
+ rc = ttf->get_ttf_param(ttf->data, TTF_CHG_STATUS, &charge_status);
+ if (rc < 0) {
+ pr_err("failed to get charge-status rc=%d\n", rc);
+ return rc;
+ }
+
+ if (charge_status != POWER_SUPPLY_STATUS_CHARGING) {
+ *val = -EINVAL;
+ return 0;
+ }
+
rc = ttf->get_ttf_param(ttf->data, TTF_MSOC, &msoc);
if (rc < 0) {
pr_err("failed to get msoc rc=%d\n", rc);
@@ -1103,7 +1125,30 @@
*/
int ttf_get_time_to_empty(struct ttf *ttf, int *val)
{
- int rc, ibatt_avg, msoc, act_cap_mah, divisor;
+ int rc, ibatt_avg, msoc, act_cap_mah, divisor, valid = 0,
+ charge_status = 0;
+
+ rc = ttf->get_ttf_param(ttf->data, TTF_VALID, &valid);
+ if (rc < 0) {
+ pr_err("failed to get ttf_valid rc=%d\n", rc);
+ return rc;
+ }
+
+ if (!valid) {
+ *val = -EINVAL;
+ return 0;
+ }
+
+ rc = ttf->get_ttf_param(ttf->data, TTF_CHG_STATUS, &charge_status);
+ if (rc < 0) {
+ pr_err("failed to get charge-status rc=%d\n", rc);
+ return rc;
+ }
+
+ if (charge_status == POWER_SUPPLY_STATUS_CHARGING) {
+ *val = -EINVAL;
+ return 0;
+ }
rc = ttf_circ_buf_median(&ttf->ibatt, &ibatt_avg);
if (rc < 0) {
@@ -1136,6 +1181,10 @@
divisor = ibatt_avg * divisor / 100;
divisor = max(100, divisor);
*val = act_cap_mah * msoc * HOURS_TO_SECONDS / divisor;
+
+ pr_debug("TTF: ibatt_avg=%d msoc=%d act_cap_mah=%d TTE=%d\n",
+ ibatt_avg, msoc, act_cap_mah, *val);
+
return 0;
}
diff --git a/drivers/power/supply/qcom/fg-alg.h b/drivers/power/supply/qcom/fg-alg.h
index 70183ba..22e9c2b 100644
--- a/drivers/power/supply/qcom/fg-alg.h
+++ b/drivers/power/supply/qcom/fg-alg.h
@@ -76,6 +76,7 @@
TTF_VFLOAT,
TTF_CHG_TYPE,
TTF_CHG_STATUS,
+ TTF_VALID,
};
struct ttf_circ_buf {
diff --git a/drivers/power/supply/qcom/qg-battery-profile.c b/drivers/power/supply/qcom/qg-battery-profile.c
index 36edd76..00a4533 100644
--- a/drivers/power/supply/qcom/qg-battery-profile.c
+++ b/drivers/power/supply/qcom/qg-battery-profile.c
@@ -398,10 +398,8 @@
{
u8 table_index = charging ? TABLE_SOC_OCV1 : TABLE_SOC_OCV2;
- if (!the_battery || !the_battery->profile) {
- pr_err("Battery profile not loaded\n");
+ if (!the_battery || !the_battery->profile)
return -ENODEV;
- }
*soc = interpolate_soc(&the_battery->profile[table_index],
batt_temp, UV_TO_DECIUV(ocv_uv));
@@ -416,10 +414,8 @@
u8 table_index = charging ? TABLE_FCC1 : TABLE_FCC2;
u32 fcc_mah;
- if (!the_battery || !the_battery->profile) {
- pr_err("Battery profile not loaded\n");
+ if (!the_battery || !the_battery->profile)
return -ENODEV;
- }
fcc_mah = interpolate_single_row_lut(
&the_battery->profile[table_index],
diff --git a/drivers/power/supply/qcom/qg-core.h b/drivers/power/supply/qcom/qg-core.h
index e834b8e..f21b2a8 100644
--- a/drivers/power/supply/qcom/qg-core.h
+++ b/drivers/power/supply/qcom/qg-core.h
@@ -60,6 +60,7 @@
bool cl_feedback_on;
bool esr_disable;
bool esr_discharge_enable;
+ bool qg_ext_sense;
};
struct qg_esr_data {
@@ -120,6 +121,10 @@
int charge_type;
int chg_iterm_ma;
int next_wakeup_ms;
+ int esr_actual;
+ int esr_nominal;
+ int soh;
+ int soc_reporting_ready;
u32 fifo_done_count;
u32 wa_flags;
u32 seq_no;
@@ -151,11 +156,18 @@
struct ttf *ttf;
};
+struct ocv_all {
+ u32 ocv_uv;
+ u32 ocv_raw;
+ char ocv_type[20];
+};
+
enum ocv_type {
S7_PON_OCV,
S3_GOOD_OCV,
S3_LAST_OCV,
SDAM_PON_OCV,
+ PON_OCV_MAX,
};
enum debug_mask {
diff --git a/drivers/power/supply/qcom/qg-reg.h b/drivers/power/supply/qcom/qg-reg.h
index d586a72..e0f400d 100644
--- a/drivers/power/supply/qcom/qg-reg.h
+++ b/drivers/power/supply/qcom/qg-reg.h
@@ -17,6 +17,7 @@
#define QG_TYPE 0x0D
#define QG_STATUS1_REG 0x08
+#define QG_OK_BIT BIT(7)
#define BATTERY_PRESENT_BIT BIT(0)
#define ESR_MEAS_DONE_BIT BIT(4)
@@ -32,6 +33,7 @@
#define QG_INT_RT_STS_REG 0x10
#define FIFO_UPDATE_DONE_RT_STS_BIT BIT(3)
#define VBAT_LOW_INT_RT_STS_BIT BIT(1)
+#define BATTERY_MISSING_INT_RT_STS_BIT BIT(0)
#define QG_INT_LATCHED_STS_REG 0x18
#define FIFO_UPDATE_DONE_INT_LAT_STS_BIT BIT(3)
@@ -64,6 +66,12 @@
#define QG_S3_ENTRY_IBAT_THRESHOLD_REG 0x5E
#define QG_S3_EXIT_IBAT_THRESHOLD_REG 0x5F
+#define QG_S5_OCV_VALIDATE_MEAS_CTL1_REG 0x60
+#define ALLOW_S5_BIT BIT(7)
+
+#define QG_S7_PON_OCV_MEAS_CTL1_REG 0x64
+#define ADC_CONV_DLY_MASK GENMASK(3, 0)
+
#define QG_ESR_MEAS_TRIG_REG 0x68
#define HW_ESR_MEAS_START_BIT BIT(0)
@@ -105,6 +113,9 @@
#define QG_SDAM_ESR_DISCHARGE_DELTA_OFFSET 0x6E /* 4-byte 0x6E-0x71 */
#define QG_SDAM_ESR_CHARGE_SF_OFFSET 0x72 /* 2-byte 0x72-0x73 */
#define QG_SDAM_ESR_DISCHARGE_SF_OFFSET 0x74 /* 2-byte 0x74-0x75 */
-#define QG_SDAM_PON_OCV_OFFSET 0x7C /* 2-byte 0x7C-0x7D */
+#define QG_SDAM_MAX_OFFSET 0xA4
+
+/* Below offset is used by PBS */
+#define QG_SDAM_PON_OCV_OFFSET 0xBC /* 2-byte 0xBC-0xBD */
#endif
diff --git a/drivers/power/supply/qcom/qg-sdam.c b/drivers/power/supply/qcom/qg-sdam.c
index e7ffcb5..a7cb97e 100644
--- a/drivers/power/supply/qcom/qg-sdam.c
+++ b/drivers/power/supply/qcom/qg-sdam.c
@@ -111,7 +111,7 @@
length = sdam_info[param].length;
rc = regmap_bulk_write(chip->regmap, offset, (u8 *)&data, length);
if (rc < 0)
- pr_err("Failed to write offset=%0x4x param=%d value=%d\n",
+ pr_err("Failed to write offset=%0x4 param=%d value=%d\n",
offset, param, data);
else
pr_debug("QG SDAM write param=%s value=%d\n",
@@ -137,11 +137,12 @@
return -EINVAL;
}
+ *data = 0;
offset = chip->sdam_base + sdam_info[param].offset;
length = sdam_info[param].length;
rc = regmap_raw_read(chip->regmap, offset, (u8 *)data, length);
if (rc < 0)
- pr_err("Failed to read offset=%0x4x param=%d\n",
+ pr_err("Failed to read offset=%0x4 param=%d\n",
offset, param);
else
pr_debug("QG SDAM read param=%s value=%d\n",
@@ -163,11 +164,11 @@
offset = chip->sdam_base + offset;
rc = regmap_bulk_write(chip->regmap, offset, data, (size_t)length);
if (rc < 0) {
- pr_err("Failed to write offset=%0x4x value=%d\n",
+ pr_err("Failed to write offset=%0x4 value=%d\n",
offset, *data);
} else {
for (i = 0; i < length; i++)
- pr_debug("QG SDAM write offset=%0x4x value=%d\n",
+ pr_debug("QG SDAM write offset=%0x4 value=%d\n",
offset++, data[i]);
}
@@ -187,10 +188,10 @@
offset = chip->sdam_base + offset;
rc = regmap_raw_read(chip->regmap, offset, (u8 *)data, (size_t)length);
if (rc < 0) {
- pr_err("Failed to read offset=%0x4x\n", offset);
+ pr_err("Failed to read offset=%0x4\n", offset);
} else {
for (i = 0; i < length; i++)
- pr_debug("QG SDAM read offset=%0x4x value=%d\n",
+ pr_debug("QG SDAM read offset=%0x4 value=%d\n",
offset++, data[i]);
}
diff --git a/drivers/power/supply/qcom/qpnp-qg.c b/drivers/power/supply/qcom/qpnp-qg.c
index a8a7826..2efe746 100644
--- a/drivers/power/supply/qcom/qpnp-qg.c
+++ b/drivers/power/supply/qcom/qpnp-qg.c
@@ -25,10 +25,12 @@
#include <linux/platform_device.h>
#include <linux/power_supply.h>
#include <linux/regmap.h>
+#include <linux/slab.h>
#include <linux/uaccess.h>
#include <linux/pmic-voter.h>
#include <linux/qpnp/qpnp-adc.h>
#include <uapi/linux/qg.h>
+#include <uapi/linux/qg-profile.h>
#include "fg-alg.h"
#include "qg-sdam.h"
#include "qg-core.h"
@@ -451,11 +453,12 @@
#define MIN_FIFO_FULL_TIME_MS 12000
static int process_rt_fifo_data(struct qpnp_qg *chip,
- bool vbat_low, bool update_smb)
+ bool update_vbat_low, bool update_smb)
{
int rc = 0;
ktime_t now = ktime_get();
s64 time_delta;
+ u8 fifo_length;
/*
* Reject the FIFO read event if there are back-to-back requests
@@ -464,10 +467,11 @@
*/
time_delta = ktime_ms_delta(now, chip->last_user_update_time);
- qg_dbg(chip, QG_DEBUG_FIFO, "time_delta=%lld ms vbat_low=%d\n",
- time_delta, vbat_low);
+ qg_dbg(chip, QG_DEBUG_FIFO, "time_delta=%lld ms update_vbat_low=%d update_smb=%d\n",
+ time_delta, update_vbat_low, update_smb);
- if (time_delta > MIN_FIFO_FULL_TIME_MS || vbat_low || update_smb) {
+ if (time_delta > MIN_FIFO_FULL_TIME_MS || update_vbat_low
+ || update_smb) {
rc = qg_master_hold(chip, true);
if (rc < 0) {
pr_err("Failed to hold master, rc=%d\n", rc);
@@ -480,17 +484,18 @@
goto done;
}
- if (vbat_low) {
+ if (update_vbat_low) {
/* change FIFO length */
- rc = qg_update_fifo_length(chip,
- chip->dt.s2_vbat_low_fifo_length);
+ fifo_length = chip->vbat_low ?
+ chip->dt.s2_vbat_low_fifo_length :
+ chip->dt.s2_fifo_length;
+ rc = qg_update_fifo_length(chip, fifo_length);
if (rc < 0)
goto done;
qg_dbg(chip, QG_DEBUG_STATUS,
"FIFO length updated to %d vbat_low=%d\n",
- chip->dt.s2_vbat_low_fifo_length,
- vbat_low);
+ fifo_length, chip->vbat_low);
}
if (update_smb) {
@@ -685,6 +690,7 @@
rc = qg_sdam_read(SDAM_ESR_CHARGE_SF, &data);
if (!rc && data) {
+ data = CAP(QG_ESR_SF_MIN, QG_ESR_SF_MAX, data);
chip->kdata.param[QG_ESR_CHARGE_SF].data = data;
chip->kdata.param[QG_ESR_CHARGE_SF].valid = true;
qg_dbg(chip, QG_DEBUG_ESR,
@@ -695,6 +701,7 @@
rc = qg_sdam_read(SDAM_ESR_DISCHARGE_SF, &data);
if (!rc && data) {
+ data = CAP(QG_ESR_SF_MIN, QG_ESR_SF_MAX, data);
chip->kdata.param[QG_ESR_DISCHARGE_SF].data = data;
chip->kdata.param[QG_ESR_DISCHARGE_SF].valid = true;
qg_dbg(chip, QG_DEBUG_ESR,
@@ -1002,6 +1009,7 @@
qg_dbg(chip, QG_DEBUG_ESR, "ESR_SW=%d during %s\n",
chip->esr_avg, is_charging ? "CHARGE" : "DISCHARGE");
qg_retrieve_esr_params(chip);
+ chip->esr_actual = chip->esr_avg;
}
return 0;
@@ -1052,23 +1060,22 @@
if (chip->udata.param[QG_ESR].valid)
chip->esr_last = chip->udata.param[QG_ESR].data;
+ if (chip->esr_actual != -EINVAL && chip->udata.param[QG_ESR].valid) {
+ chip->esr_nominal = chip->udata.param[QG_ESR].data;
+ if (chip->qg_psy)
+ power_supply_changed(chip->qg_psy);
+ }
+
if (!chip->dt.esr_disable)
qg_store_esr_params(chip);
qg_dbg(chip, QG_DEBUG_STATUS, "udata update: batt_soc=%d cc_soc=%d full_soc=%d qg_esr=%d\n",
- chip->batt_soc, chip->cc_soc, chip->full_soc, chip->esr_last);
+ (chip->batt_soc != INT_MIN) ? chip->batt_soc : -EINVAL,
+ (chip->cc_soc != INT_MIN) ? chip->cc_soc : -EINVAL,
+ chip->full_soc, chip->esr_last);
vote(chip->awake_votable, UDATA_READY_VOTER, false, 0);
}
-static irqreturn_t qg_default_irq_handler(int irq, void *data)
-{
- struct qpnp_qg *chip = data;
-
- qg_dbg(chip, QG_DEBUG_IRQ, "IRQ triggered\n");
-
- return IRQ_HANDLED;
-}
-
#define MAX_FIFO_DELTA_PERCENT 10
static irqreturn_t qg_fifo_update_done_handler(int irq, void *data)
{
@@ -1154,9 +1161,14 @@
pr_err("Failed to read RT status, rc=%d\n", rc);
goto done;
}
+ /* ignore VBAT low if battery is missing */
+ if ((status & BATTERY_MISSING_INT_RT_STS_BIT) ||
+ chip->battery_missing)
+ goto done;
+
chip->vbat_low = !!(status & VBAT_LOW_INT_RT_STS_BIT);
- rc = process_rt_fifo_data(chip, chip->vbat_low, false);
+ rc = process_rt_fifo_data(chip, true, false);
if (rc < 0)
pr_err("Failed to process RT FIFO data, rc=%d\n", rc);
@@ -1170,8 +1182,20 @@
{
struct qpnp_qg *chip = data;
u32 ocv_uv = 0;
+ int rc;
+ u8 status = 0;
qg_dbg(chip, QG_DEBUG_IRQ, "IRQ triggered\n");
+
+ rc = qg_read(chip, chip->qg_base + QG_INT_RT_STS_REG, &status, 1);
+ if (rc < 0)
+ pr_err("Failed to read RT status rc=%d\n", rc);
+
+ /* ignore VBAT empty if battery is missing */
+ if ((status & BATTERY_MISSING_INT_RT_STS_BIT) ||
+ chip->battery_missing)
+ return IRQ_HANDLED;
+
pr_warn("VBATT EMPTY SOC = 0\n");
chip->catch_up_soc = 0;
@@ -1232,7 +1256,6 @@
static struct qg_irq_info qg_irqs[] = {
[QG_BATT_MISSING_IRQ] = {
.name = "qg-batt-missing",
- .handler = qg_default_irq_handler,
},
[QG_VBATT_LOW_IRQ] = {
.name = "qg-vbat-low",
@@ -1256,11 +1279,9 @@
},
[QG_FSM_STAT_CHG_IRQ] = {
.name = "qg-fsm-state-chg",
- .handler = qg_default_irq_handler,
},
[QG_EVENT_IRQ] = {
.name = "qg-event",
- .handler = qg_default_irq_handler,
},
};
@@ -1359,7 +1380,7 @@
return -ENODEV;
if (chip->battery_missing || !chip->profile_loaded)
- return -EPERM;
+ return -ENODEV;
rc = qg_sdam_multibyte_read(QG_SDAM_LEARNED_CAPACITY_OFFSET,
(u8 *)&cc_mah, 2);
@@ -1384,7 +1405,7 @@
return -ENODEV;
if (chip->battery_missing || !learned_cap_uah)
- return -EPERM;
+ return -ENODEV;
cc_mah = div64_s64(learned_cap_uah, 1000);
rc = qg_sdam_multibyte_write(QG_SDAM_LEARNED_CAPACITY_OFFSET,
@@ -1424,7 +1445,7 @@
return -ENODEV;
if (chip->battery_missing || !chip->profile_loaded)
- return -EPERM;
+ return -ENODEV;
if (!buf || length > BUCKET_COUNT)
return -EINVAL;
@@ -1452,7 +1473,7 @@
return -ENODEV;
if (chip->battery_missing || !chip->profile_loaded)
- return -EPERM;
+ return -ENODEV;
if (!buf || length > BUCKET_COUNT * 2 || id < 0 ||
id > BUCKET_COUNT - 1 ||
@@ -1593,10 +1614,10 @@
if (!chip)
return -ENODEV;
- if (chip->battery_missing || !chip->profile_loaded)
- return -EPERM;
-
switch (param) {
+ case TTF_VALID:
+ *val = (!chip->battery_missing && chip->profile_loaded);
+ break;
case TTF_MSOC:
rc = qg_get_battery_capacity(chip, val);
break;
@@ -1657,7 +1678,7 @@
return -ENODEV;
if (chip->battery_missing || !chip->profile_loaded)
- return -EPERM;
+ return -ENODEV;
vote(chip->awake_votable, TTF_AWAKE_VOTER, val, 0);
@@ -1691,6 +1712,17 @@
chip->cl->learned_cap_uah = pval->intval;
mutex_unlock(&chip->cl->lock);
break;
+ case POWER_SUPPLY_PROP_SOH:
+ chip->soh = pval->intval;
+ qg_dbg(chip, QG_DEBUG_STATUS, "SOH update: SOH=%d esr_actual=%d esr_nominal=%d\n",
+ chip->soh, chip->esr_actual, chip->esr_nominal);
+ break;
+ case POWER_SUPPLY_PROP_ESR_ACTUAL:
+ chip->esr_actual = pval->intval;
+ break;
+ case POWER_SUPPLY_PROP_ESR_NOMINAL:
+ chip->esr_nominal = pval->intval;
+ break;
default:
break;
}
@@ -1737,6 +1769,9 @@
case POWER_SUPPLY_PROP_RESISTANCE_NOW:
pval->intval = chip->esr_last;
break;
+ case POWER_SUPPLY_PROP_SOC_REPORTING_READY:
+ pval->intval = chip->soc_reporting_ready;
+ break;
case POWER_SUPPLY_PROP_RESISTANCE_CAPACITIVE:
pval->intval = chip->dt.rbat_conn_mohm;
break;
@@ -1785,6 +1820,17 @@
case POWER_SUPPLY_PROP_TIME_TO_EMPTY_AVG:
rc = ttf_get_time_to_empty(chip->ttf, &pval->intval);
break;
+ case POWER_SUPPLY_PROP_ESR_ACTUAL:
+ pval->intval = (chip->esr_actual == -EINVAL) ? -EINVAL :
+ (chip->esr_actual * 1000);
+ break;
+ case POWER_SUPPLY_PROP_ESR_NOMINAL:
+ pval->intval = (chip->esr_nominal == -EINVAL) ? -EINVAL :
+ (chip->esr_nominal * 1000);
+ break;
+ case POWER_SUPPLY_PROP_SOH:
+ pval->intval = chip->soh;
+ break;
default:
pr_debug("Unsupported property %d\n", psp);
break;
@@ -1798,6 +1844,9 @@
{
switch (psp) {
case POWER_SUPPLY_PROP_CHARGE_FULL:
+ case POWER_SUPPLY_PROP_ESR_ACTUAL:
+ case POWER_SUPPLY_PROP_ESR_NOMINAL:
+ case POWER_SUPPLY_PROP_SOH:
return 1;
default:
break;
@@ -1815,6 +1864,7 @@
POWER_SUPPLY_PROP_RESISTANCE,
POWER_SUPPLY_PROP_RESISTANCE_ID,
POWER_SUPPLY_PROP_RESISTANCE_NOW,
+ POWER_SUPPLY_PROP_SOC_REPORTING_READY,
POWER_SUPPLY_PROP_RESISTANCE_CAPACITIVE,
POWER_SUPPLY_PROP_DEBUG_BATTERY,
POWER_SUPPLY_PROP_BATTERY_TYPE,
@@ -1828,6 +1878,9 @@
POWER_SUPPLY_PROP_CHARGE_FULL_DESIGN,
POWER_SUPPLY_PROP_TIME_TO_FULL_AVG,
POWER_SUPPLY_PROP_TIME_TO_EMPTY_AVG,
+ POWER_SUPPLY_PROP_ESR_ACTUAL,
+ POWER_SUPPLY_PROP_ESR_NOMINAL,
+ POWER_SUPPLY_PROP_SOH,
};
static const struct power_supply_desc qg_psy_desc = {
@@ -1914,6 +1967,7 @@
{
int rc;
bool parallel_enabled = is_parallel_enabled(chip);
+ bool update_smb = false;
if (parallel_enabled == chip->parallel_enabled)
return 0;
@@ -1924,7 +1978,14 @@
mutex_lock(&chip->data_lock);
- rc = process_rt_fifo_data(chip, false, true);
+ /*
+ * Parallel charger uses the same external sense, hence do not
+ * enable SMB sensing if PMI632 is configured for external sense.
+ */
+ if (!chip->dt.qg_ext_sense)
+ update_smb = true;
+
+ rc = process_rt_fifo_data(chip, false, update_smb);
if (rc < 0)
pr_err("Failed to process RT FIFO data, rc=%d\n", rc);
@@ -1949,6 +2010,110 @@
return 0;
}
+static int qg_handle_battery_removal(struct qpnp_qg *chip)
+{
+ int rc, length = QG_SDAM_MAX_OFFSET - QG_SDAM_VALID_OFFSET;
+ u8 *data;
+
+ /* clear SDAM */
+ data = kcalloc(length, sizeof(*data), GFP_KERNEL);
+ if (!data)
+ return -ENOMEM;
+
+ rc = qg_sdam_multibyte_write(QG_SDAM_VALID_OFFSET, data, length);
+ if (rc < 0)
+ pr_err("Failed to clear SDAM rc=%d\n", rc);
+
+ return rc;
+}
+
+#define MAX_QG_OK_RETRIES 20
+static int qg_handle_battery_insertion(struct qpnp_qg *chip)
+{
+ int rc, count = 0;
+ u32 ocv_uv = 0, ocv_raw = 0;
+ u8 reg = 0;
+
+ do {
+ rc = qg_read(chip, chip->qg_base + QG_STATUS1_REG, ®, 1);
+ if (rc < 0) {
+ pr_err("Failed to read STATUS1_REG rc=%d\n", rc);
+ return rc;
+ }
+
+ if (reg & QG_OK_BIT)
+ break;
+
+ msleep(200);
+ count++;
+ } while (count < MAX_QG_OK_RETRIES);
+
+ if (count == MAX_QG_OK_RETRIES) {
+ qg_dbg(chip, QG_DEBUG_STATUS, "QG_OK not set!\n");
+ return 0;
+ }
+
+ /* read S7 PON OCV */
+ rc = qg_read_ocv(chip, &ocv_uv, &ocv_raw, S7_PON_OCV);
+ if (rc < 0) {
+ pr_err("Failed to read PON OCV rc=%d\n", rc);
+ return rc;
+ }
+
+ qg_dbg(chip, QG_DEBUG_STATUS,
+ "S7_OCV on battery insertion = %duV\n", ocv_uv);
+
+ chip->kdata.param[QG_GOOD_OCV_UV].data = ocv_uv;
+ chip->kdata.param[QG_GOOD_OCV_UV].valid = true;
+ /* clear all the userspace data */
+ chip->kdata.param[QG_CLEAR_LEARNT_DATA].data = 1;
+ chip->kdata.param[QG_CLEAR_LEARNT_DATA].valid = true;
+
+ vote(chip->awake_votable, GOOD_OCV_VOTER, true, 0);
+ /* signal the read thread */
+ chip->data_ready = true;
+ wake_up_interruptible(&chip->qg_wait_q);
+
+ return 0;
+}
+
+static int qg_battery_status_update(struct qpnp_qg *chip)
+{
+ int rc;
+ union power_supply_propval prop = {0, };
+
+ if (!is_batt_available(chip))
+ return 0;
+
+ mutex_lock(&chip->data_lock);
+
+ rc = power_supply_get_property(chip->batt_psy,
+ POWER_SUPPLY_PROP_PRESENT, &prop);
+ if (rc < 0) {
+ pr_err("Failed to get battery-present, rc=%d\n", rc);
+ goto done;
+ }
+
+ if (chip->battery_missing && prop.intval) {
+ pr_warn("Battery inserted!\n");
+ rc = qg_handle_battery_insertion(chip);
+ if (rc < 0)
+ pr_err("Failed in battery-insertion rc=%d\n", rc);
+ } else if (!chip->battery_missing && !prop.intval) {
+ pr_warn("Battery removed!\n");
+ rc = qg_handle_battery_removal(chip);
+ if (rc < 0)
+ pr_err("Failed in battery-removal rc=%d\n", rc);
+ }
+
+ chip->battery_missing = !prop.intval;
+
+done:
+ mutex_unlock(&chip->data_lock);
+ return rc;
+}
+
+
static void qg_status_change_work(struct work_struct *work)
{
struct qpnp_qg *chip = container_of(work,
@@ -1961,6 +2126,10 @@
goto out;
}
+ rc = qg_battery_status_update(chip);
+ if (rc < 0)
+ pr_err("Failed to process battery status update rc=%d\n", rc);
+
rc = power_supply_get_property(chip->batt_psy,
POWER_SUPPLY_PROP_CHARGE_TYPE, &prop);
if (rc < 0)
@@ -2357,6 +2526,7 @@
qg_dbg(chip, QG_DEBUG_PROFILE, "Battery Missing!\n");
chip->battery_missing = true;
chip->profile_loaded = false;
+ chip->soc_reporting_ready = true;
} else {
/* battery present */
rc = get_batt_id_ohm(chip, &chip->batt_id_ohm);
@@ -2365,11 +2535,14 @@
chip->profile_loaded = false;
} else {
rc = qg_load_battery_profile(chip);
- if (rc < 0)
+ if (rc < 0) {
pr_err("Failed to load battery-profile rc=%d\n",
rc);
- else
+ chip->profile_loaded = false;
+ chip->soc_reporting_ready = true;
+ } else {
chip->profile_loaded = true;
+ }
}
}
@@ -2380,12 +2553,21 @@
return 0;
}
+
+static struct ocv_all ocv[] = {
+ [S7_PON_OCV] = { 0, 0, "S7_PON_OCV"},
+ [S3_GOOD_OCV] = { 0, 0, "S3_GOOD_OCV"},
+ [S3_LAST_OCV] = { 0, 0, "S3_LAST_OCV"},
+ [SDAM_PON_OCV] = { 0, 0, "SDAM_PON_OCV"},
+};
+
+#define S7_ERROR_MARGIN_UV 20000
static int qg_determine_pon_soc(struct qpnp_qg *chip)
{
- int rc = 0, batt_temp = 0;
+ int rc = 0, batt_temp = 0, i;
bool use_pon_ocv = true;
unsigned long rtc_sec = 0;
- u32 ocv_uv = 0, ocv_raw = 0, soc = 0, shutdown[SDAM_MAX] = {0};
+ u32 ocv_uv = 0, soc = 0, shutdown[SDAM_MAX] = {0};
char ocv_type[20] = "NONE";
if (!chip->profile_loaded) {
@@ -2434,33 +2616,47 @@
goto done;
}
- /*
- * Read S3_LAST_OCV, if S3_LAST_OCV is invalid,
- * read the SDAM_PON_OCV
- * if SDAM is not-set, use S7_PON_OCV.
- */
- strlcpy(ocv_type, "S3_LAST_SOC", 20);
- rc = qg_read_ocv(chip, &ocv_uv, &ocv_raw, S3_LAST_OCV);
- if (rc < 0)
- goto done;
-
- if (ocv_raw == FIFO_V_RESET_VAL) {
- /* S3_LAST_OCV is invalid */
- strlcpy(ocv_type, "SDAM_PON_SOC", 20);
- rc = qg_read_ocv(chip, &ocv_uv, &ocv_raw, SDAM_PON_OCV);
+ /* read all OCVs */
+ for (i = S7_PON_OCV; i < PON_OCV_MAX; i++) {
+ rc = qg_read_ocv(chip, &ocv[i].ocv_uv,
+ &ocv[i].ocv_raw, i);
if (rc < 0)
- goto done;
+ pr_err("Failed to read %s OCV rc=%d\n",
+ ocv[i].ocv_type, rc);
+ else
+ qg_dbg(chip, QG_DEBUG_PON, "%s OCV=%d\n",
+ ocv[i].ocv_type, ocv[i].ocv_uv);
+ }
- if (!ocv_uv) {
- /* SDAM_PON_OCV is not set */
+ if (ocv[S3_LAST_OCV].ocv_raw == FIFO_V_RESET_VAL) {
+ if (!ocv[SDAM_PON_OCV].ocv_uv) {
strlcpy(ocv_type, "S7_PON_SOC", 20);
- rc = qg_read_ocv(chip, &ocv_uv, &ocv_raw,
- S7_PON_OCV);
- if (rc < 0)
- goto done;
+ ocv_uv = ocv[S7_PON_OCV].ocv_uv;
+ } else if (ocv[SDAM_PON_OCV].ocv_uv <=
+ ocv[S7_PON_OCV].ocv_uv) {
+ strlcpy(ocv_type, "S7_PON_SOC", 20);
+ ocv_uv = ocv[S7_PON_OCV].ocv_uv;
+ } else if (!shutdown[SDAM_VALID] &&
+ ((ocv[SDAM_PON_OCV].ocv_uv -
+ ocv[S7_PON_OCV].ocv_uv) >
+ S7_ERROR_MARGIN_UV)) {
+ strlcpy(ocv_type, "S7_PON_SOC", 20);
+ ocv_uv = ocv[S7_PON_OCV].ocv_uv;
+ } else {
+ strlcpy(ocv_type, "SDAM_PON_SOC", 20);
+ ocv_uv = ocv[SDAM_PON_OCV].ocv_uv;
+ }
+ } else {
+ if (ocv[S3_LAST_OCV].ocv_uv >= ocv[S7_PON_OCV].ocv_uv) {
+ strlcpy(ocv_type, "S3_LAST_SOC", 20);
+ ocv_uv = ocv[S3_LAST_OCV].ocv_uv;
+ } else {
+ strlcpy(ocv_type, "S7_PON_SOC", 20);
+ ocv_uv = ocv[S7_PON_OCV].ocv_uv;
}
}
+ ocv_uv = CAP(QG_MIN_OCV_UV, QG_MAX_OCV_UV, ocv_uv);
rc = lookup_soc_ocv(&soc, ocv_uv, batt_temp, false);
if (rc < 0) {
pr_err("Failed to lookup SOC@PON rc=%d\n", rc);
@@ -2493,6 +2689,9 @@
pr_info("using %s @ PON ocv_uv=%duV soc=%d\n",
ocv_type, ocv_uv, chip->msoc);
+ /* SOC reporting is now ready */
+ chip->soc_reporting_ready = 1;
+
return 0;
}
@@ -2515,6 +2714,7 @@
return 0;
}
+#define ADC_CONV_DLY_512MS 0xA
static int qg_hw_init(struct qpnp_qg *chip)
{
int rc, temp;
@@ -2695,6 +2895,22 @@
return rc;
}
+ /* disable S5 */
+ rc = qg_masked_write(chip, chip->qg_base +
+ QG_S5_OCV_VALIDATE_MEAS_CTL1_REG,
+ ALLOW_S5_BIT, 0);
+ if (rc < 0)
+ pr_err("Failed to disable S5 rc=%d\n", rc);
+
+ /* change PON OCV time to 512ms */
+ rc = qg_masked_write(chip, chip->qg_base +
+ QG_S7_PON_OCV_MEAS_CTL1_REG,
+ ADC_CONV_DLY_MASK,
+ ADC_CONV_DLY_512MS);
+ if (rc < 0)
+ pr_err("Failed to reconfigure S7-delay rc=%d\n", rc);
+
+
return 0;
}
@@ -3117,6 +3333,8 @@
else
chip->dt.esr_disable_soc = temp * 100;
+ chip->dt.qg_ext_sense = of_property_read_bool(node, "qcom,qg-ext-sns");
+
/* Capacity learning params*/
if (!chip->dt.cl_disable) {
chip->dt.cl_feedback_on = of_property_read_bool(node,
@@ -3176,9 +3394,9 @@
chip->cl->dt.min_start_soc, chip->cl->dt.max_start_soc,
chip->cl->dt.min_temp, chip->cl->dt.max_temp);
}
- qg_dbg(chip, QG_DEBUG_PON, "DT: vbatt_empty_mv=%dmV vbatt_low_mv=%dmV delta_soc=%d\n",
+ qg_dbg(chip, QG_DEBUG_PON, "DT: vbatt_empty_mv=%dmV vbatt_low_mv=%dmV delta_soc=%d ext-sns=%d\n",
chip->dt.vbatt_empty_mv, chip->dt.vbatt_low_mv,
- chip->dt.delta_soc);
+ chip->dt.delta_soc, chip->dt.qg_ext_sense);
return 0;
}
@@ -3407,6 +3625,9 @@
chip->cc_soc = INT_MIN;
chip->full_soc = QG_SOC_FULL;
chip->chg_iterm_ma = INT_MIN;
+ chip->soh = -EINVAL;
+ chip->esr_actual = -EINVAL;
+ chip->esr_nominal = -EINVAL;
rc = qg_alg_init(chip);
if (rc < 0) {
diff --git a/drivers/power/supply/qcom/qpnp-smb2.c b/drivers/power/supply/qcom/qpnp-smb2.c
index 617ef62..56a09c6 100644
--- a/drivers/power/supply/qcom/qpnp-smb2.c
+++ b/drivers/power/supply/qcom/qpnp-smb2.c
@@ -345,6 +345,7 @@
POWER_SUPPLY_PROP_PRESENT,
POWER_SUPPLY_PROP_ONLINE,
POWER_SUPPLY_PROP_VOLTAGE_MAX,
+ POWER_SUPPLY_PROP_VOLTAGE_MAX_DESIGN,
POWER_SUPPLY_PROP_VOLTAGE_NOW,
POWER_SUPPLY_PROP_PD_CURRENT_MAX,
POWER_SUPPLY_PROP_CURRENT_MAX,
@@ -401,6 +402,9 @@
case POWER_SUPPLY_PROP_VOLTAGE_MAX:
rc = smblib_get_prop_usb_voltage_max(chg, val);
break;
+ case POWER_SUPPLY_PROP_VOLTAGE_MAX_DESIGN:
+ rc = smblib_get_prop_usb_voltage_max_design(chg, val);
+ break;
case POWER_SUPPLY_PROP_VOLTAGE_NOW:
rc = smblib_get_prop_usb_voltage_now(chg, val);
break;
@@ -994,6 +998,8 @@
POWER_SUPPLY_PROP_CHARGE_CONTROL_LIMIT_MAX,
POWER_SUPPLY_PROP_CHARGE_CONTROL_LIMIT,
POWER_SUPPLY_PROP_CHARGE_COUNTER,
+ POWER_SUPPLY_PROP_CHARGE_FULL,
+ POWER_SUPPLY_PROP_CYCLE_COUNT,
};
static int smb2_batt_get_prop(struct power_supply *psy,
@@ -1051,9 +1057,6 @@
case POWER_SUPPLY_PROP_SW_JEITA_ENABLED:
val->intval = chg->sw_jeita_enabled;
break;
- case POWER_SUPPLY_PROP_VOLTAGE_NOW:
- rc = smblib_get_prop_batt_voltage_now(chg, val);
- break;
case POWER_SUPPLY_PROP_VOLTAGE_MAX:
val->intval = get_client_vote(chg->fv_votable,
BATT_PROFILE_VOTER);
@@ -1065,9 +1068,6 @@
val->intval = get_client_vote_locked(chg->fv_votable,
QNOVO_VOTER);
break;
- case POWER_SUPPLY_PROP_CURRENT_NOW:
- rc = smblib_get_prop_batt_current_now(chg, val);
- break;
case POWER_SUPPLY_PROP_CURRENT_QNOVO:
val->intval = get_client_vote_locked(chg->fcc_votable,
QNOVO_VOTER);
@@ -1076,9 +1076,6 @@
val->intval = get_client_vote(chg->fcc_votable,
BATT_PROFILE_VOTER);
break;
- case POWER_SUPPLY_PROP_TEMP:
- rc = smblib_get_prop_batt_temp(chg, val);
- break;
case POWER_SUPPLY_PROP_TECHNOLOGY:
val->intval = POWER_SUPPLY_TECHNOLOGY_LION;
break;
@@ -1106,7 +1103,12 @@
val->intval = 0;
break;
case POWER_SUPPLY_PROP_CHARGE_COUNTER:
- rc = smblib_get_prop_batt_charge_counter(chg, val);
+ case POWER_SUPPLY_PROP_CHARGE_FULL:
+ case POWER_SUPPLY_PROP_CYCLE_COUNT:
+ case POWER_SUPPLY_PROP_VOLTAGE_NOW:
+ case POWER_SUPPLY_PROP_CURRENT_NOW:
+ case POWER_SUPPLY_PROP_TEMP:
+ rc = smblib_get_prop_from_bms(chg, psp, val);
break;
default:
pr_err("batt power supply prop %d not supported\n", psp);
diff --git a/drivers/power/supply/qcom/qpnp-smb5.c b/drivers/power/supply/qcom/qpnp-smb5.c
index e095eb0..9840396 100644
--- a/drivers/power/supply/qcom/qpnp-smb5.c
+++ b/drivers/power/supply/qcom/qpnp-smb5.c
@@ -61,7 +61,7 @@
},
.icl_stat = {
.name = "input current limit status",
- .reg = AICL_ICL_STATUS_REG,
+ .reg = ICL_STATUS_REG,
.min_u = 0,
.max_u = 3000000,
.step_u = 50000,
@@ -206,6 +206,13 @@
USBIN_VOLTAGE,
};
+enum {
+ BAT_THERM = 0,
+ MISC_THERM,
+ CONN_THERM,
+ SMB_THERM,
+};
+
#define PMI632_MAX_ICL_UA 3000000
static int smb5_chg_config_init(struct smb5 *chip)
{
@@ -266,6 +273,53 @@
return rc;
}
+#define PULL_NO_PULL 0
+#define PULL_30K 30
+#define PULL_100K 100
+#define PULL_400K 400
+static int get_valid_pullup(int pull_up)
+{
+ int pull;
+
+ /* pull up can only be 0/30K/100K/400K) */
+ switch (pull_up) {
+ case PULL_NO_PULL:
+ pull = INTERNAL_PULL_NO_PULL;
+ break;
+ case PULL_30K:
+ pull = INTERNAL_PULL_30K_PULL;
+ break;
+ case PULL_100K:
+ pull = INTERNAL_PULL_100K_PULL;
+ break;
+ case PULL_400K:
+ pull = INTERNAL_PULL_400K_PULL;
+ break;
+ default:
+ pull = INTERNAL_PULL_100K_PULL;
+ }
+
+ return pull;
+}
+
+#define INTERNAL_PULL_UP_MASK 0x3
+static int smb5_configure_internal_pull(struct smb_charger *chg, int type,
+ int pull)
+{
+ int rc;
+ int shift = type * 2;
+ u8 mask = INTERNAL_PULL_UP_MASK << shift;
+ u8 val = pull << shift;
+
+ rc = smblib_masked_write(chg, BATIF_ADC_INTERNAL_PULL_UP_REG,
+ mask, val);
+ if (rc < 0)
+ dev_err(chg->dev,
+ "Couldn't configure ADC pull-up reg rc=%d\n", rc);
+
+ return rc;
+}
+
#define MICRO_1P5A 1500000
#define MICRO_1PA 1000000
#define MICRO_P1A 100000
@@ -387,6 +441,16 @@
if (rc < 0)
chg->otg_delay_ms = OTG_DEFAULT_DEGLITCH_TIME_MS;
+ chg->hw_die_temp_mitigation = of_property_read_bool(node,
+ "qcom,hw-die-temp-mitigation");
+
+ chg->hw_connector_mitigation = of_property_read_bool(node,
+ "qcom,hw-connector-mitigation");
+
+ chg->connector_pull_up = -EINVAL;
+ of_property_read_u32(node, "qcom,connector-internal-pull-kohm",
+ &chg->connector_pull_up);
+
return 0;
}
@@ -471,9 +535,11 @@
POWER_SUPPLY_PROP_SDP_CURRENT_MAX,
POWER_SUPPLY_PROP_CONNECTOR_TYPE,
POWER_SUPPLY_PROP_VOLTAGE_MAX,
+ POWER_SUPPLY_PROP_VOLTAGE_MAX_DESIGN,
POWER_SUPPLY_PROP_SCOPE,
POWER_SUPPLY_PROP_VOLTAGE_NOW,
POWER_SUPPLY_PROP_HVDCP_OPTI_ALLOWED,
+ POWER_SUPPLY_PROP_QC_OPTI_DISABLE,
};
static int smb5_usb_get_prop(struct power_supply *psy,
@@ -507,6 +573,9 @@
case POWER_SUPPLY_PROP_VOLTAGE_MAX:
rc = smblib_get_prop_usb_voltage_max(chg, val);
break;
+ case POWER_SUPPLY_PROP_VOLTAGE_MAX_DESIGN:
+ rc = smblib_get_prop_usb_voltage_max_design(chg, val);
+ break;
case POWER_SUPPLY_PROP_PD_CURRENT_MAX:
val->intval = get_client_vote(chg->usb_icl_votable, PD_VOTER);
break;
@@ -602,6 +671,13 @@
case POWER_SUPPLY_PROP_HVDCP_OPTI_ALLOWED:
val->intval = !chg->flash_active;
break;
+ case POWER_SUPPLY_PROP_QC_OPTI_DISABLE:
+ if (chg->hw_die_temp_mitigation)
+ val->intval = POWER_SUPPLY_QC_THERMAL_BALANCE_DISABLE
+ | POWER_SUPPLY_QC_INOV_THERMAL_DISABLE;
+ if (chg->hw_connector_mitigation)
+ val->intval |= POWER_SUPPLY_QC_CTM_DISABLE;
+ break;
default:
pr_err("get prop %d is not supported in usb\n", psp);
rc = -EINVAL;
@@ -1493,6 +1569,14 @@
return rc;
}
+ rc = smblib_masked_write(chg, TYPE_C_MODE_CFG_REG,
+ EN_TRY_SNK_BIT, EN_TRY_SNK_BIT);
+ if (rc < 0) {
+ dev_err(chg->dev,
+ "Couldn't enable try.snk rc=%d\n", rc);
+ return rc;
+ }
+
/* Keep VCONN in h/w controlled mode for PMI632 */
if (chg->smb_version != PMI632_SUBTYPE) {
/* configure VCONN for software control */
@@ -1526,6 +1610,42 @@
return rc;
}
+static int smb5_configure_mitigation(struct smb_charger *chg)
+{
+ int rc;
+ u8 chan = 0;
+
+ if (!chg->hw_die_temp_mitigation && !chg->hw_connector_mitigation)
+ return 0;
+
+ if (chg->hw_die_temp_mitigation) {
+ rc = smblib_write(chg, MISC_THERMREG_SRC_CFG_REG,
+ THERMREG_CONNECTOR_ADC_SRC_EN_BIT
+ | THERMREG_DIE_ADC_SRC_EN_BIT
+ | THERMREG_DIE_CMP_SRC_EN_BIT);
+ if (rc < 0) {
+ dev_err(chg->dev,
+ "Couldn't configure THERM_SRC reg rc=%d\n", rc);
+ return rc;
+ };
+
+ chan = DIE_TEMP_CHANNEL_EN_BIT;
+ }
+
+ if (chg->hw_connector_mitigation)
+ chan |= CONN_THM_CHANNEL_EN_BIT;
+
+ rc = smblib_masked_write(chg, BATIF_ADC_CHANNEL_EN_REG,
+ CONN_THM_CHANNEL_EN_BIT | DIE_TEMP_CHANNEL_EN_BIT,
+ chan);
+ if (rc < 0) {
+ dev_err(chg->dev, "Couldn't enable ADC channelrc=%d\n", rc);
+ return rc;
+ }
+
+ return 0;
+}
+
static int smb5_init_hw(struct smb5 *chip)
{
struct smb_charger *chg = &chip->chg;
@@ -1632,6 +1752,13 @@
return rc;
}
+ /* configure temperature mitigation */
+ rc = smb5_configure_mitigation(chg);
+ if (rc < 0) {
+ dev_err(chg->dev, "Couldn't configure mitigation rc=%d\n", rc);
+ return rc;
+ }
+
/* vote 0mA on usb_icl for non battery platforms */
vote(chg->usb_icl_votable,
DEFAULT_VOTER, chip->dt.no_battery, 0);
@@ -1842,6 +1969,17 @@
return rc;
}
+ if (chg->connector_pull_up != -EINVAL) {
+ rc = smb5_configure_internal_pull(chg, CONN_THERM,
+ get_valid_pullup(chg->connector_pull_up));
+ if (rc < 0) {
+ dev_err(chg->dev,
+ "Couldn't configure CONN_THERM pull-up rc=%d\n",
+ rc);
+ return rc;
+ }
+ }
+
return rc;
}
diff --git a/drivers/power/supply/qcom/qpnp-smbcharger.c b/drivers/power/supply/qcom/qpnp-smbcharger.c
index 3bb4810..40cfd9c 100644
--- a/drivers/power/supply/qcom/qpnp-smbcharger.c
+++ b/drivers/power/supply/qcom/qpnp-smbcharger.c
@@ -1520,6 +1520,47 @@
return chip->parallel.psy;
}
+static int smbchg_request_dpdm(struct smbchg_chip *chip, bool enable)
+{
+ int rc = 0;
+
+ /* fetch the DPDM regulator */
+ if (!chip->dpdm_reg && of_get_property(chip->dev->of_node,
+ "dpdm-supply", NULL)) {
+ chip->dpdm_reg = devm_regulator_get(chip->dev, "dpdm");
+ if (IS_ERR(chip->dpdm_reg)) {
+ rc = PTR_ERR(chip->dpdm_reg);
+ dev_err(chip->dev, "Couldn't get dpdm regulator rc=%d\n",
+ rc);
+ chip->dpdm_reg = NULL;
+ return rc;
+ }
+ }
+
+ if (!chip->dpdm_reg)
+ return -ENODEV;
+
+ if (enable) {
+ if (!regulator_is_enabled(chip->dpdm_reg)) {
+ pr_smb(PR_STATUS, "enabling DPDM regulator\n");
+ rc = regulator_enable(chip->dpdm_reg);
+ if (rc < 0)
+ dev_err(chip->dev, "Couldn't enable dpdm regulator rc=%d\n",
+ rc);
+ }
+ } else {
+ if (regulator_is_enabled(chip->dpdm_reg)) {
+ pr_smb(PR_STATUS, "disabling DPDM regulator\n");
+ rc = regulator_disable(chip->dpdm_reg);
+ if (rc < 0)
+ dev_err(chip->dev, "Couldn't disable dpdm regulator rc=%d\n",
+ rc);
+ }
+ }
+
+ return rc;
+}
+
static void smbchg_usb_update_online_work(struct work_struct *work)
{
struct smbchg_chip *chip = container_of(work,
@@ -4590,8 +4631,11 @@
if (!rc && !(reg & USBIN_UV_BIT) && !(reg & USBIN_SRC_DET_BIT)) {
pr_smb(PR_MISC, "overwriting state = %d with %d\n",
state, POWER_SUPPLY_DP_DM_DPF_DMF);
- if (chip->dpdm_reg && !regulator_is_enabled(chip->dpdm_reg))
- return regulator_enable(chip->dpdm_reg);
+ rc = smbchg_request_dpdm(chip, true);
+ if (rc < 0) {
+ pr_err("Couldn't enable DP/DM for pulsing rc=%d\n", rc);
+ return rc;
+ }
}
pr_smb(PR_MISC, "setting usb psy dp dm = %d\n", state);
pval.intval = state;
@@ -4697,8 +4741,7 @@
smbchg_relax(chip, PM_DETECT_HVDCP);
smbchg_change_usb_supply_type(chip, POWER_SUPPLY_TYPE_UNKNOWN);
extcon_set_cable_state_(chip->extcon, EXTCON_USB, chip->usb_present);
- if (chip->dpdm_reg)
- regulator_disable(chip->dpdm_reg);
+ smbchg_request_dpdm(chip, false);
schedule_work(&chip->usb_set_online_work);
pr_smb(PR_MISC, "setting usb psy health UNKNOWN\n");
@@ -5248,8 +5291,7 @@
{
int rc = 0;
- if (chip->dpdm_reg && !regulator_is_enabled(chip->dpdm_reg))
- rc = regulator_enable(chip->dpdm_reg);
+ rc = smbchg_request_dpdm(chip, true);
if (rc < 0) {
pr_err("Couldn't enable DP/DM for pulsing rc=%d\n", rc);
return rc;
@@ -6481,8 +6523,7 @@
*/
if (!(reg & USBIN_UV_BIT) && !(reg & USBIN_SRC_DET_BIT)) {
pr_smb(PR_MISC, "setting usb dp=f dm=f\n");
- if (chip->dpdm_reg && !regulator_is_enabled(chip->dpdm_reg))
- rc = regulator_enable(chip->dpdm_reg);
+ rc = smbchg_request_dpdm(chip, true);
if (rc < 0) {
pr_err("Couldn't enable DP/DM for pulsing rc=%d\n", rc);
return rc;
@@ -6731,15 +6772,8 @@
chip->dc_present = is_dc_present(chip);
if (chip->usb_present) {
- int rc = 0;
-
pr_smb(PR_MISC, "setting usb dp=f dm=f\n");
- if (chip->dpdm_reg && !regulator_is_enabled(chip->dpdm_reg))
- rc = regulator_enable(chip->dpdm_reg);
- if (rc < 0) {
- pr_err("Couldn't enable DP/DM for pulsing rc=%d\n", rc);
- return rc;
- }
+ smbchg_request_dpdm(chip, true);
handle_usb_insertion(chip);
} else {
handle_usb_removal(chip);
@@ -8372,14 +8406,6 @@
goto votables_cleanup;
}
- if (of_find_property(chip->dev->of_node, "dpdm-supply", NULL)) {
- chip->dpdm_reg = devm_regulator_get(chip->dev, "dpdm");
- if (IS_ERR(chip->dpdm_reg)) {
- rc = PTR_ERR(chip->dpdm_reg);
- goto votables_cleanup;
- }
- }
-
rc = smbchg_hw_init(chip);
if (rc < 0) {
dev_err(&pdev->dev,
diff --git a/drivers/power/supply/qcom/smb-lib.c b/drivers/power/supply/qcom/smb-lib.c
index 86f6638..612c3dd 100644
--- a/drivers/power/supply/qcom/smb-lib.c
+++ b/drivers/power/supply/qcom/smb-lib.c
@@ -1908,7 +1908,8 @@
stat);
if (stat & CHARGER_ERROR_STATUS_BAT_OV_BIT) {
- rc = smblib_get_prop_batt_voltage_now(chg, &pval);
+ rc = smblib_get_prop_from_bms(chg,
+ POWER_SUPPLY_PROP_VOLTAGE_NOW, &pval);
if (!rc) {
/*
* If Vbatt is within 40mV above Vfloat, then don't
@@ -1973,45 +1974,6 @@
return 0;
}
-int smblib_get_prop_batt_voltage_now(struct smb_charger *chg,
- union power_supply_propval *val)
-{
- int rc;
-
- if (!chg->bms_psy)
- return -EINVAL;
-
- rc = power_supply_get_property(chg->bms_psy,
- POWER_SUPPLY_PROP_VOLTAGE_NOW, val);
- return rc;
-}
-
-int smblib_get_prop_batt_current_now(struct smb_charger *chg,
- union power_supply_propval *val)
-{
- int rc;
-
- if (!chg->bms_psy)
- return -EINVAL;
-
- rc = power_supply_get_property(chg->bms_psy,
- POWER_SUPPLY_PROP_CURRENT_NOW, val);
- return rc;
-}
-
-int smblib_get_prop_batt_temp(struct smb_charger *chg,
- union power_supply_propval *val)
-{
- int rc;
-
- if (!chg->bms_psy)
- return -EINVAL;
-
- rc = power_supply_get_property(chg->bms_psy,
- POWER_SUPPLY_PROP_TEMP, val);
- return rc;
-}
-
int smblib_get_prop_batt_charge_done(struct smb_charger *chg,
union power_supply_propval *val)
{
@@ -2047,16 +2009,17 @@
return 0;
}
-int smblib_get_prop_batt_charge_counter(struct smb_charger *chg,
- union power_supply_propval *val)
+int smblib_get_prop_from_bms(struct smb_charger *chg,
+ enum power_supply_property psp,
+ union power_supply_propval *val)
{
int rc;
if (!chg->bms_psy)
return -EINVAL;
- rc = power_supply_get_property(chg->bms_psy,
- POWER_SUPPLY_PROP_CHARGE_COUNTER, val);
+ rc = power_supply_get_property(chg->bms_psy, psp, val);
+
return rc;
}
@@ -2452,6 +2415,28 @@
switch (chg->real_charger_type) {
case POWER_SUPPLY_TYPE_USB_HVDCP:
case POWER_SUPPLY_TYPE_USB_HVDCP_3:
+ if (chg->smb_version == PM660_SUBTYPE)
+ val->intval = MICRO_9V;
+ else
+ val->intval = MICRO_12V;
+ break;
+ case POWER_SUPPLY_TYPE_USB_PD:
+ val->intval = chg->voltage_max_uv;
+ break;
+ default:
+ val->intval = MICRO_5V;
+ break;
+ }
+
+ return 0;
+}
+
+int smblib_get_prop_usb_voltage_max_design(struct smb_charger *chg,
+ union power_supply_propval *val)
+{
+ switch (chg->real_charger_type) {
+ case POWER_SUPPLY_TYPE_USB_HVDCP:
+ case POWER_SUPPLY_TYPE_USB_HVDCP_3:
case POWER_SUPPLY_TYPE_USB_PD:
if (chg->smb_version == PM660_SUBTYPE)
val->intval = MICRO_9V;
diff --git a/drivers/power/supply/qcom/smb-lib.h b/drivers/power/supply/qcom/smb-lib.h
index 097b24a..3b8bc1f 100644
--- a/drivers/power/supply/qcom/smb-lib.h
+++ b/drivers/power/supply/qcom/smb-lib.h
@@ -447,14 +447,6 @@
union power_supply_propval *val);
int smblib_get_prop_input_current_limited(struct smb_charger *chg,
union power_supply_propval *val);
-int smblib_get_prop_batt_voltage_now(struct smb_charger *chg,
- union power_supply_propval *val);
-int smblib_get_prop_batt_current_now(struct smb_charger *chg,
- union power_supply_propval *val);
-int smblib_get_prop_batt_temp(struct smb_charger *chg,
- union power_supply_propval *val);
-int smblib_get_prop_batt_charge_counter(struct smb_charger *chg,
- union power_supply_propval *val);
int smblib_set_prop_input_suspend(struct smb_charger *chg,
const union power_supply_propval *val);
int smblib_set_prop_batt_capacity(struct smb_charger *chg,
@@ -483,6 +475,8 @@
union power_supply_propval *val);
int smblib_get_prop_usb_voltage_max(struct smb_charger *chg,
union power_supply_propval *val);
+int smblib_get_prop_usb_voltage_max_design(struct smb_charger *chg,
+ union power_supply_propval *val);
int smblib_get_prop_usb_voltage_now(struct smb_charger *chg,
union power_supply_propval *val);
int smblib_get_prop_usb_current_now(struct smb_charger *chg,
@@ -544,6 +538,9 @@
int smblib_get_charge_current(struct smb_charger *chg, int *total_current_ua);
int smblib_get_prop_pr_swap_in_progress(struct smb_charger *chg,
union power_supply_propval *val);
+int smblib_get_prop_from_bms(struct smb_charger *chg,
+ enum power_supply_property psp,
+ union power_supply_propval *val);
int smblib_set_prop_pr_swap_in_progress(struct smb_charger *chg,
const union power_supply_propval *val);
int smblib_stat_sw_override_cfg(struct smb_charger *chg, bool override);
diff --git a/drivers/power/supply/qcom/smb1355-charger.c b/drivers/power/supply/qcom/smb1355-charger.c
index 1d99ccb..2671d6b 100644
--- a/drivers/power/supply/qcom/smb1355-charger.c
+++ b/drivers/power/supply/qcom/smb1355-charger.c
@@ -80,8 +80,12 @@
#define BATIF_CFG_SMISC_BATID_REG (BATIF_BASE + 0x73)
#define CFG_SMISC_RBIAS_EXT_CTRL_BIT BIT(2)
-#define SMB2CHGS_BATIF_ENG_SMISC_DIETEMP (BATIF_BASE + 0xC0)
+#define SMB2CHG_BATIF_ENG_SMISC_DIETEMP (BATIF_BASE + 0xC0)
#define TDIE_COMPARATOR_THRESHOLD GENMASK(5, 0)
+#define DIE_LOW_RANGE_BASE_DEGC 34
+#define DIE_LOW_RANGE_DELTA 16
+#define DIE_LOW_RANGE_MAX_DEGC 97
+#define DIE_LOW_RANGE_SHIFT 4
#define BATIF_ENG_SCMISC_SPARE1_REG (BATIF_BASE + 0xC2)
#define EXT_BIAS_PIN_BIT BIT(2)
@@ -91,13 +95,10 @@
#define VALLEY_COMPARATOR_EN_BIT BIT(0)
#define TEMP_COMP_STATUS_REG (MISC_BASE + 0x07)
-#define SKIN_TEMP_RST_HOT_BIT BIT(6)
-#define SKIN_TEMP_UB_HOT_BIT BIT(5)
-#define SKIN_TEMP_LB_HOT_BIT BIT(4)
-#define DIE_TEMP_TSD_HOT_BIT BIT(3)
-#define DIE_TEMP_RST_HOT_BIT BIT(2)
-#define DIE_TEMP_UB_HOT_BIT BIT(1)
-#define DIE_TEMP_LB_HOT_BIT BIT(0)
+#define TEMP_RST_HOT_BIT BIT(2)
+#define TEMP_UB_HOT_BIT BIT(1)
+#define TEMP_LB_HOT_BIT BIT(0)
+#define SKIN_TEMP_SHIFT 4
#define MISC_RT_STS_REG (MISC_BASE + 0x10)
#define HARD_ILIMIT_RT_STS_BIT BIT(5)
@@ -223,6 +224,8 @@
bool disable_ctm;
int pl_mode;
int pl_batfet_mode;
+ bool hw_die_temp_mitigation;
+ u32 die_temp_threshold;
};
struct smb1355 {
@@ -250,6 +253,11 @@
struct votable *irq_disable_votable;
};
+enum {
+ CONNECTOR_TEMP = 0,
+ DIE_TEMP,
+};
+
static bool is_secure(struct smb1355 *chip, int addr)
{
if (addr == CLOCK_REQUEST_REG)
@@ -379,8 +387,7 @@
u8 temp_stat;
for (i = 0; i < BIT(5); i++) {
- rc = smb1355_masked_write(chip,
- SMB2CHGS_BATIF_ENG_SMISC_DIETEMP,
+ rc = smb1355_masked_write(chip, SMB2CHG_BATIF_ENG_SMISC_DIETEMP,
TDIE_COMPARATOR_THRESHOLD, i);
if (rc < 0) {
pr_err("Couldn't set temp comp threshold rc=%d\n", rc);
@@ -399,7 +406,7 @@
continue;
}
- if (!(temp_stat & DIE_TEMP_UB_HOT_BIT)) {
+ if (!(temp_stat & TEMP_UB_HOT_BIT)) {
/* found the temp */
break;
}
@@ -465,6 +472,7 @@
return 0;
}
+#define DEFAULT_DIE_TEMP_LOW_THRESHOLD 90
static int smb1355_parse_dt(struct smb1355 *chip)
{
struct device_node *node = chip->dev->of_node;
@@ -495,6 +503,15 @@
if (of_property_read_bool(node, "qcom,stacked-batfet"))
chip->dt.pl_batfet_mode = POWER_SUPPLY_PL_STACKED_BATFET;
+ chip->dt.hw_die_temp_mitigation = of_property_read_bool(node,
+ "qcom,hw-die-temp-mitigation");
+
+ chip->dt.die_temp_threshold = DEFAULT_DIE_TEMP_LOW_THRESHOLD;
+ of_property_read_u32(node, "qcom,die-temp-threshold-degc",
+ &chip->dt.die_temp_threshold);
+ if (chip->dt.die_temp_threshold > DIE_LOW_RANGE_MAX_DEGC)
+ chip->dt.die_temp_threshold = DIE_LOW_RANGE_MAX_DEGC;
+
return 0;
}
@@ -520,6 +537,7 @@
POWER_SUPPLY_PROP_MIN_ICL,
POWER_SUPPLY_PROP_CURRENT_MAX,
POWER_SUPPLY_PROP_SET_SHIP_MODE,
+ POWER_SUPPLY_PROP_DIE_HEALTH,
};
static int smb1355_get_prop_batt_charge_type(struct smb1355 *chip,
@@ -546,10 +564,13 @@
return rc;
}
-static int smb1355_get_prop_connector_health(struct smb1355 *chip)
+static int smb1355_get_prop_health(struct smb1355 *chip, int type)
{
u8 temp;
- int rc;
+ int rc, shift;
+
+ /* Connector-temp uses skin-temp configuration */
+ shift = (type == CONNECTOR_TEMP) ? SKIN_TEMP_SHIFT : 0;
rc = smb1355_read(chip, TEMP_COMP_STATUS_REG, &temp);
if (rc < 0) {
@@ -557,13 +578,13 @@
return POWER_SUPPLY_HEALTH_UNKNOWN;
}
- if (temp & SKIN_TEMP_RST_HOT_BIT)
+ if (temp & (TEMP_RST_HOT_BIT << shift))
return POWER_SUPPLY_HEALTH_OVERHEAT;
- if (temp & SKIN_TEMP_UB_HOT_BIT)
+ if (temp & (TEMP_UB_HOT_BIT << shift))
return POWER_SUPPLY_HEALTH_HOT;
- if (temp & SKIN_TEMP_LB_HOT_BIT)
+ if (temp & (TEMP_LB_HOT_BIT << shift))
return POWER_SUPPLY_HEALTH_WARM;
return POWER_SUPPLY_HEALTH_COOL;
@@ -614,7 +635,17 @@
val->intval = chip->die_temp_deciDegC;
break;
case POWER_SUPPLY_PROP_CHARGER_TEMP_MAX:
- rc = smb1355_get_prop_charger_temp_max(chip, val);
+ /*
+ * In case of h/w controlled die_temp mitigation,
+ * die_temp/die_temp_max can not be reported as this
+ * requires run time manipulation of DIE_TEMP low
+ * threshold which will interfere with h/w mitigation
+ * scheme.
+ */
+ if (chip->dt.hw_die_temp_mitigation)
+ val->intval = -EINVAL;
+ else
+ rc = smb1355_get_prop_charger_temp_max(chip, val);
break;
case POWER_SUPPLY_PROP_INPUT_SUSPEND:
val->intval = chip->disabled;
@@ -635,10 +666,14 @@
break;
case POWER_SUPPLY_PROP_CONNECTOR_HEALTH:
if (chip->c_health == -EINVAL)
- val->intval = smb1355_get_prop_connector_health(chip);
+ val->intval = smb1355_get_prop_health(chip,
+ CONNECTOR_TEMP);
else
val->intval = chip->c_health;
break;
+ case POWER_SUPPLY_PROP_DIE_HEALTH:
+ val->intval = smb1355_get_prop_health(chip, DIE_TEMP);
+ break;
case POWER_SUPPLY_PROP_PARALLEL_BATFET_MODE:
val->intval = chip->dt.pl_batfet_mode;
break;
@@ -708,13 +743,16 @@
}
chip->die_temp_deciDegC = -EINVAL;
- if (disable) {
- chip->exit_die_temp = true;
- cancel_delayed_work_sync(&chip->die_temp_work);
- } else {
- /* start the work to measure temperature */
- chip->exit_die_temp = false;
- schedule_delayed_work(&chip->die_temp_work, 0);
+ /* Only enable temperature measurement for s/w based mitigation */
+ if (!chip->dt.hw_die_temp_mitigation) {
+ if (disable) {
+ chip->exit_die_temp = true;
+ cancel_delayed_work_sync(&chip->die_temp_work);
+ } else {
+ /* start the work to measure temperature */
+ chip->exit_die_temp = false;
+ schedule_delayed_work(&chip->die_temp_work, 0);
+ }
}
if (chip->irq_disable_votable)
@@ -978,6 +1016,7 @@
static int smb1355_init_hw(struct smb1355 *chip)
{
int rc;
+ u8 val, range;
/* request clock always on */
rc = smb1355_clk_request(chip, true);
@@ -1045,13 +1084,35 @@
return rc;
}
+ /* Configure DIE temp Low threshold */
+ if (chip->dt.hw_die_temp_mitigation) {
+ range = (chip->dt.die_temp_threshold - DIE_LOW_RANGE_BASE_DEGC)
+ / (DIE_LOW_RANGE_DELTA);
+ val = (chip->dt.die_temp_threshold
+ - ((range * DIE_LOW_RANGE_DELTA)
+ + DIE_LOW_RANGE_BASE_DEGC))
+ % DIE_LOW_RANGE_DELTA;
+
+ rc = smb1355_masked_write(chip, SMB2CHG_BATIF_ENG_SMISC_DIETEMP,
+ TDIE_COMPARATOR_THRESHOLD,
+ (range << DIE_LOW_RANGE_SHIFT) | val);
+ if (rc < 0) {
+ pr_err("Couldn't set temp comp threshold rc=%d\n", rc);
+ return rc;
+ }
+ }
+
/*
- * Enable thermal Die temperature comparator source and disable hw
- * mitigation for skin/die
+ * Enable thermal Die temperature comparator source and
+ * enable hardware controlled current adjustment for die temp
+ * if charger is configured in h/w controlled die temp mitigation.
*/
+ val = THERMREG_DIE_CMP_SRC_EN_BIT;
+ if (!chip->dt.hw_die_temp_mitigation)
+ val |= BYP_THERM_CHG_CURR_ADJUST_BIT;
rc = smb1355_masked_write(chip, MISC_THERMREG_SRC_CFG_REG,
THERMREG_DIE_CMP_SRC_EN_BIT | BYP_THERM_CHG_CURR_ADJUST_BIT,
- THERMREG_DIE_CMP_SRC_EN_BIT | BYP_THERM_CHG_CURR_ADJUST_BIT);
+ val);
if (rc < 0) {
pr_err("Couldn't set Skin temperature comparator src rc=%d\n",
rc);
@@ -1062,8 +1123,9 @@
* Disable hysterisis for die temperature. This is so that sw can run
* stepping scheme quickly
*/
+ val = chip->dt.hw_die_temp_mitigation ? DIE_TEMP_COMP_HYST_BIT : 0;
rc = smb1355_masked_write(chip, BATIF_ENG_SCMISC_SPARE1_REG,
- DIE_TEMP_COMP_HYST_BIT, 0);
+ DIE_TEMP_COMP_HYST_BIT, val);
if (rc < 0) {
pr_err("Couldn't disable hyst. for die rc=%d\n", rc);
return rc;
diff --git a/drivers/power/supply/qcom/smb1360-charger-fg.c b/drivers/power/supply/qcom/smb1360-charger-fg.c
index ed9c610..4e98ec7 100644
--- a/drivers/power/supply/qcom/smb1360-charger-fg.c
+++ b/drivers/power/supply/qcom/smb1360-charger-fg.c
@@ -3424,8 +3424,8 @@
chip->otg_vreg.rdesc.owner = THIS_MODULE;
chip->otg_vreg.rdesc.type = REGULATOR_VOLTAGE;
chip->otg_vreg.rdesc.ops = &smb1360_otg_reg_ops;
- chip->otg_vreg.rdesc.of_match = chip->dev->of_node->name;
- chip->otg_vreg.rdesc.name = chip->dev->of_node->name;
+ chip->otg_vreg.rdesc.of_match = "qcom,smb1360-vbus";
+ chip->otg_vreg.rdesc.name = "qcom,smb1360-vbus";
cfg.dev = chip->dev;
cfg.driver_data = chip;
diff --git a/drivers/power/supply/qcom/smb5-lib.c b/drivers/power/supply/qcom/smb5-lib.c
index d79e12b..c70d51e8 100644
--- a/drivers/power/supply/qcom/smb5-lib.c
+++ b/drivers/power/supply/qcom/smb5-lib.c
@@ -1894,6 +1894,28 @@
switch (chg->real_charger_type) {
case POWER_SUPPLY_TYPE_USB_HVDCP:
case POWER_SUPPLY_TYPE_USB_HVDCP_3:
+ if (chg->smb_version == PMI632_SUBTYPE)
+ val->intval = MICRO_9V;
+ else
+ val->intval = MICRO_12V;
+ break;
+ case POWER_SUPPLY_TYPE_USB_PD:
+ val->intval = chg->voltage_max_uv;
+ break;
+ default:
+ val->intval = MICRO_5V;
+ break;
+ }
+
+ return 0;
+}
+
+int smblib_get_prop_usb_voltage_max_design(struct smb_charger *chg,
+ union power_supply_propval *val)
+{
+ switch (chg->real_charger_type) {
+ case POWER_SUPPLY_TYPE_USB_HVDCP:
+ case POWER_SUPPLY_TYPE_USB_HVDCP_3:
case POWER_SUPPLY_TYPE_USB_PD:
if (chg->smb_version == PMI632_SUBTYPE)
val->intval = MICRO_9V;
@@ -2109,7 +2131,7 @@
int rc;
u8 stat;
- rc = smblib_read(chg, TEMP_RANGE_STATUS_REG, &stat);
+ rc = smblib_read(chg, MISC_TEMP_RANGE_STATUS_REG, &stat);
if (rc < 0) {
smblib_err(chg, "Couldn't read TEMP_RANGE_STATUS_REG rc=%d\n",
rc);
@@ -2691,6 +2713,24 @@
struct smb_charger *chg = irq_data->parent_data;
if (chg->mode == PARALLEL_MASTER) {
+ /*
+ * Ignore if change in ICL is due to DIE temp mitigation.
+ * This is to prevent any further ICL split.
+ */
+ if (chg->hw_die_temp_mitigation) {
+ rc = smblib_read(chg, MISC_DIE_TEMP_STATUS_REG, &stat);
+ if (rc < 0) {
+ smblib_err(chg,
+ "Couldn't read DIE_TEMP rc=%d\n", rc);
+ return IRQ_HANDLED;
+ }
+ if (stat & (DIE_TEMP_UB_BIT | DIE_TEMP_LB_BIT)) {
+ smblib_dbg(chg, PR_PARALLEL,
+ "skip ICL change DIE_TEMP %x\n", stat);
+ return IRQ_HANDLED;
+ }
+ }
+
rc = smblib_read(chg, AICL_STATUS_REG, &stat);
if (rc < 0) {
smblib_err(chg, "Couldn't read AICL_STATUS rc=%d\n",
diff --git a/drivers/power/supply/qcom/smb5-lib.h b/drivers/power/supply/qcom/smb5-lib.h
index 7c02468..35e5dd3 100644
--- a/drivers/power/supply/qcom/smb5-lib.h
+++ b/drivers/power/supply/qcom/smb5-lib.h
@@ -360,6 +360,9 @@
int auto_recharge_soc;
bool jeita_configured;
enum sink_src_mode sink_src_mode;
+ bool hw_die_temp_mitigation;
+ bool hw_connector_mitigation;
+ int connector_pull_up;
/* workaround flag */
u32 wa_flags;
@@ -492,6 +495,8 @@
union power_supply_propval *val);
int smblib_get_prop_usb_voltage_max(struct smb_charger *chg,
union power_supply_propval *val);
+int smblib_get_prop_usb_voltage_max_design(struct smb_charger *chg,
+ union power_supply_propval *val);
int smblib_get_prop_typec_cc_orientation(struct smb_charger *chg,
union power_supply_propval *val);
int smblib_get_prop_typec_power_role(struct smb_charger *chg,
diff --git a/drivers/power/supply/qcom/smb5-reg.h b/drivers/power/supply/qcom/smb5-reg.h
index 79a8bd0..a925658 100644
--- a/drivers/power/supply/qcom/smb5-reg.h
+++ b/drivers/power/supply/qcom/smb5-reg.h
@@ -106,7 +106,7 @@
* DCDC Peripheral Registers *
********************************/
#define ICL_MAX_STATUS_REG (DCDC_BASE + 0x06)
-
+#define ICL_STATUS_REG (DCDC_BASE + 0x07)
#define AICL_ICL_STATUS_REG (DCDC_BASE + 0x08)
#define AICL_STATUS_REG (DCDC_BASE + 0x0A)
@@ -146,6 +146,18 @@
#define SHIP_MODE_REG (BATIF_BASE + 0x40)
#define SHIP_MODE_EN_BIT BIT(0)
+#define BATIF_ADC_CHANNEL_EN_REG (BATIF_BASE + 0x82)
+#define CONN_THM_CHANNEL_EN_BIT BIT(4)
+#define DIE_TEMP_CHANNEL_EN_BIT BIT(2)
+
+#define BATIF_ADC_INTERNAL_PULL_UP_REG (BATIF_BASE + 0x86)
+#define INTERNAL_PULL_UP_CONN_THM_MASK GENMASK(5, 4)
+#define CONN_THM_SHIFT 4
+#define INTERNAL_PULL_NO_PULL 0x00
+#define INTERNAL_PULL_30K_PULL 0x01
+#define INTERNAL_PULL_100K_PULL 0x02
+#define INTERNAL_PULL_400K_PULL 0x03
+
/********************************
* USBIN Peripheral Registers *
********************************/
@@ -284,6 +296,7 @@
#define TYPE_C_MODE_CFG_REG (TYPEC_BASE + 0x44)
#define TYPEC_POWER_ROLE_CMD_MASK GENMASK(2, 1)
+#define EN_TRY_SNK_BIT BIT(4)
#define EN_SRC_ONLY_BIT BIT(2)
#define EN_SNK_ONLY_BIT BIT(1)
#define TYPEC_DISABLE_CMD_BIT BIT(0)
@@ -332,7 +345,7 @@
/********************************
* MISC Peripheral Registers *
********************************/
-#define TEMP_RANGE_STATUS_REG (MISC_BASE + 0x06)
+#define MISC_TEMP_RANGE_STATUS_REG (MISC_BASE + 0x06)
#define THERM_REG_ACTIVE_BIT BIT(6)
#define TLIM_BIT BIT(5)
#define TEMP_RANGE_MASK GENMASK(4, 1)
@@ -342,6 +355,12 @@
#define TEMP_BELOW_RANGE_BIT BIT(1)
#define THERMREG_DISABLED_BIT BIT(0)
+#define MISC_DIE_TEMP_STATUS_REG (MISC_BASE + 0x07)
+#define DIE_TEMP_SHDN_BIT BIT(3)
+#define DIE_TEMP_RST_BIT BIT(2)
+#define DIE_TEMP_UB_BIT BIT(1)
+#define DIE_TEMP_LB_BIT BIT(0)
+
#define BARK_BITE_WDOG_PET_REG (MISC_BASE + 0x43)
#define BARK_BITE_WDOG_PET_BIT BIT(0)
@@ -365,6 +384,16 @@
#define BARK_WDOG_TIMEOUT_MASK GENMASK(3, 2)
#define BITE_WDOG_TIMEOUT_MASK GENMASK(1, 0)
+#define MISC_THERMREG_SRC_CFG_REG (MISC_BASE + 0x70)
+#define THERMREG_SW_ICL_ADJUST_BIT BIT(7)
+#define DIE_ADC_SEL_BIT BIT(6)
+#define THERMREG_SMB_ADC_SRC_EN_BIT BIT(5)
+#define THERMREG_CONNECTOR_ADC_SRC_EN_BIT BIT(4)
+#define SKIN_ADC_CFG_BIT BIT(3)
+#define THERMREG_SKIN_ADC_SRC_EN_BIT BIT(2)
+#define THERMREG_DIE_ADC_SRC_EN_BIT BIT(1)
+#define THERMREG_DIE_CMP_SRC_EN_BIT BIT(0)
+
#define MISC_SMB_CFG_REG (MISC_BASE + 0x90)
#define SMB_EN_SEL_BIT BIT(4)
#define CP_EN_POLARITY_CFG_BIT BIT(3)
diff --git a/drivers/regulator/qpnp-lcdb-regulator.c b/drivers/regulator/qpnp-lcdb-regulator.c
index 07a6198..cc01399 100644
--- a/drivers/regulator/qpnp-lcdb-regulator.c
+++ b/drivers/regulator/qpnp-lcdb-regulator.c
@@ -167,6 +167,8 @@
#define PM660_BST_HEADROOM_DEFAULT_MV 200
#define BST_HEADROOM_DEFAULT_MV 150
+#define PMIC5_LCDB_OFF_ON_DELAY_US 20000
+
struct ldo_regulator {
struct regulator_desc rdesc;
struct regulator_dev *rdev;
@@ -1340,22 +1342,27 @@
static int qpnp_lcdb_regulator_register(struct qpnp_lcdb *lcdb, u8 type)
{
- int rc = 0;
+ int rc = 0, off_on_delay = 0;
struct regulator_init_data *init_data;
struct regulator_config cfg = {};
struct regulator_desc *rdesc;
struct regulator_dev *rdev;
struct device_node *node;
+ if (lcdb->pmic_rev_id->pmic_subtype != PM660L_SUBTYPE)
+ off_on_delay = PMIC5_LCDB_OFF_ON_DELAY_US;
+
if (type == LDO) {
node = lcdb->ldo.node;
rdesc = &lcdb->ldo.rdesc;
rdesc->ops = &qpnp_lcdb_ldo_ops;
+ rdesc->off_on_delay = off_on_delay;
rdev = lcdb->ldo.rdev;
} else if (type == NCP) {
node = lcdb->ncp.node;
rdesc = &lcdb->ncp.rdesc;
rdesc->ops = &qpnp_lcdb_ncp_ops;
+ rdesc->off_on_delay = off_on_delay;
rdev = lcdb->ncp.rdev;
} else {
pr_err("Invalid regulator type %d\n", type);
diff --git a/drivers/rtc/hctosys.c b/drivers/rtc/hctosys.c
index e1cfa06..e79f2a1 100644
--- a/drivers/rtc/hctosys.c
+++ b/drivers/rtc/hctosys.c
@@ -49,6 +49,11 @@
tv64.tv_sec = rtc_tm_to_time64(&tm);
+#if BITS_PER_LONG == 32
+ if (tv64.tv_sec > INT_MAX)
+ goto err_read;
+#endif
+
err = do_settimeofday64(&tv64);
dev_info(rtc->dev.parent,
diff --git a/drivers/rtc/rtc-snvs.c b/drivers/rtc/rtc-snvs.c
index a753ef9..3e8fd33 100644
--- a/drivers/rtc/rtc-snvs.c
+++ b/drivers/rtc/rtc-snvs.c
@@ -132,20 +132,23 @@
{
struct snvs_rtc_data *data = dev_get_drvdata(dev);
unsigned long time;
+ int ret;
rtc_tm_to_time(tm, &time);
/* Disable RTC first */
- snvs_rtc_enable(data, false);
+ ret = snvs_rtc_enable(data, false);
+ if (ret)
+ return ret;
/* Write 32-bit time to 47-bit timer, leaving 15 LSBs blank */
regmap_write(data->regmap, data->offset + SNVS_LPSRTCLR, time << CNTR_TO_SECS_SH);
regmap_write(data->regmap, data->offset + SNVS_LPSRTCMR, time >> (32 - CNTR_TO_SECS_SH));
/* Enable RTC again */
- snvs_rtc_enable(data, true);
+ ret = snvs_rtc_enable(data, true);
- return 0;
+ return ret;
}
static int snvs_rtc_read_alarm(struct device *dev, struct rtc_wkalrm *alrm)
@@ -287,7 +290,11 @@
regmap_write(data->regmap, data->offset + SNVS_LPSR, 0xffffffff);
/* Enable RTC */
- snvs_rtc_enable(data, true);
+ ret = snvs_rtc_enable(data, true);
+ if (ret) {
+ dev_err(&pdev->dev, "failed to enable rtc %d\n", ret);
+ goto error_rtc_device_register;
+ }
device_init_wakeup(&pdev->dev, true);
diff --git a/drivers/rtc/rtc-tx4939.c b/drivers/rtc/rtc-tx4939.c
index 560d9a5..a952808 100644
--- a/drivers/rtc/rtc-tx4939.c
+++ b/drivers/rtc/rtc-tx4939.c
@@ -86,7 +86,8 @@
for (i = 2; i < 6; i++)
buf[i] = __raw_readl(&rtcreg->dat);
spin_unlock_irq(&pdata->lock);
- sec = (buf[5] << 24) | (buf[4] << 16) | (buf[3] << 8) | buf[2];
+ sec = ((unsigned long)buf[5] << 24) | (buf[4] << 16) |
+ (buf[3] << 8) | buf[2];
rtc_time_to_tm(sec, tm);
return rtc_valid_tm(tm);
}
@@ -147,7 +148,8 @@
alrm->enabled = (ctl & TX4939_RTCCTL_ALME) ? 1 : 0;
alrm->pending = (ctl & TX4939_RTCCTL_ALMD) ? 1 : 0;
spin_unlock_irq(&pdata->lock);
- sec = (buf[5] << 24) | (buf[4] << 16) | (buf[3] << 8) | buf[2];
+ sec = ((unsigned long)buf[5] << 24) | (buf[4] << 16) |
+ (buf[3] << 8) | buf[2];
rtc_time_to_tm(sec, &alrm->time);
return rtc_valid_tm(&alrm->time);
}
diff --git a/drivers/s390/cio/qdio_setup.c b/drivers/s390/cio/qdio_setup.c
index 48b3866..3528690 100644
--- a/drivers/s390/cio/qdio_setup.c
+++ b/drivers/s390/cio/qdio_setup.c
@@ -140,7 +140,7 @@
int i;
for (i = 0; i < nr_queues; i++) {
- q = kmem_cache_alloc(qdio_q_cache, GFP_KERNEL);
+ q = kmem_cache_zalloc(qdio_q_cache, GFP_KERNEL);
if (!q)
return -ENOMEM;
@@ -456,7 +456,6 @@
{
struct ciw *ciw;
struct qdio_irq *irq_ptr = init_data->cdev->private->qdio_data;
- int rc;
memset(&irq_ptr->qib, 0, sizeof(irq_ptr->qib));
memset(&irq_ptr->siga_flag, 0, sizeof(irq_ptr->siga_flag));
@@ -493,16 +492,14 @@
ciw = ccw_device_get_ciw(init_data->cdev, CIW_TYPE_EQUEUE);
if (!ciw) {
DBF_ERROR("%4x NO EQ", irq_ptr->schid.sch_no);
- rc = -EINVAL;
- goto out_err;
+ return -EINVAL;
}
irq_ptr->equeue = *ciw;
ciw = ccw_device_get_ciw(init_data->cdev, CIW_TYPE_AQUEUE);
if (!ciw) {
DBF_ERROR("%4x NO AQ", irq_ptr->schid.sch_no);
- rc = -EINVAL;
- goto out_err;
+ return -EINVAL;
}
irq_ptr->aqueue = *ciw;
@@ -510,9 +507,6 @@
irq_ptr->orig_handler = init_data->cdev->handler;
init_data->cdev->handler = qdio_int_handler;
return 0;
-out_err:
- qdio_release_memory(irq_ptr);
- return rc;
}
void qdio_print_subchannel_info(struct qdio_irq *irq_ptr,
diff --git a/drivers/s390/scsi/zfcp_dbf.c b/drivers/s390/scsi/zfcp_dbf.c
index 34367d1..4534a7c 100644
--- a/drivers/s390/scsi/zfcp_dbf.c
+++ b/drivers/s390/scsi/zfcp_dbf.c
@@ -3,7 +3,7 @@
*
* Debug traces for zfcp.
*
- * Copyright IBM Corp. 2002, 2017
+ * Copyright IBM Corp. 2002, 2018
*/
#define KMSG_COMPONENT "zfcp"
@@ -287,6 +287,27 @@
spin_unlock_irqrestore(&dbf->rec_lock, flags);
}
+/**
+ * zfcp_dbf_rec_trig_lock - trace event related to triggered recovery with lock
+ * @tag: identifier for event
+ * @adapter: adapter on which the erp_action should run
+ * @port: remote port involved in the erp_action
+ * @sdev: scsi device involved in the erp_action
+ * @want: wanted erp_action
+ * @need: required erp_action
+ *
+ * The adapter->erp_lock must not be held.
+ */
+void zfcp_dbf_rec_trig_lock(char *tag, struct zfcp_adapter *adapter,
+ struct zfcp_port *port, struct scsi_device *sdev,
+ u8 want, u8 need)
+{
+ unsigned long flags;
+
+ read_lock_irqsave(&adapter->erp_lock, flags);
+ zfcp_dbf_rec_trig(tag, adapter, port, sdev, want, need);
+ read_unlock_irqrestore(&adapter->erp_lock, flags);
+}
/**
* zfcp_dbf_rec_run_lvl - trace event related to running recovery
diff --git a/drivers/s390/scsi/zfcp_ext.h b/drivers/s390/scsi/zfcp_ext.h
index 21c8c68..7a7984a 100644
--- a/drivers/s390/scsi/zfcp_ext.h
+++ b/drivers/s390/scsi/zfcp_ext.h
@@ -3,7 +3,7 @@
*
* External function declarations.
*
- * Copyright IBM Corp. 2002, 2016
+ * Copyright IBM Corp. 2002, 2018
*/
#ifndef ZFCP_EXT_H
@@ -34,6 +34,9 @@
extern void zfcp_dbf_adapter_unregister(struct zfcp_adapter *);
extern void zfcp_dbf_rec_trig(char *, struct zfcp_adapter *,
struct zfcp_port *, struct scsi_device *, u8, u8);
+extern void zfcp_dbf_rec_trig_lock(char *tag, struct zfcp_adapter *adapter,
+ struct zfcp_port *port,
+ struct scsi_device *sdev, u8 want, u8 need);
extern void zfcp_dbf_rec_run(char *, struct zfcp_erp_action *);
extern void zfcp_dbf_rec_run_lvl(int level, char *tag,
struct zfcp_erp_action *erp);
diff --git a/drivers/s390/scsi/zfcp_scsi.c b/drivers/s390/scsi/zfcp_scsi.c
index a9b8104..bb99db2 100644
--- a/drivers/s390/scsi/zfcp_scsi.c
+++ b/drivers/s390/scsi/zfcp_scsi.c
@@ -3,7 +3,7 @@
*
* Interface to Linux SCSI midlayer.
*
- * Copyright IBM Corp. 2002, 2017
+ * Copyright IBM Corp. 2002, 2018
*/
#define KMSG_COMPONENT "zfcp"
@@ -616,9 +616,9 @@
ids.port_id = port->d_id;
ids.roles = FC_RPORT_ROLE_FCP_TARGET;
- zfcp_dbf_rec_trig("scpaddy", port->adapter, port, NULL,
- ZFCP_PSEUDO_ERP_ACTION_RPORT_ADD,
- ZFCP_PSEUDO_ERP_ACTION_RPORT_ADD);
+ zfcp_dbf_rec_trig_lock("scpaddy", port->adapter, port, NULL,
+ ZFCP_PSEUDO_ERP_ACTION_RPORT_ADD,
+ ZFCP_PSEUDO_ERP_ACTION_RPORT_ADD);
rport = fc_remote_port_add(port->adapter->scsi_host, 0, &ids);
if (!rport) {
dev_err(&port->adapter->ccw_device->dev,
@@ -640,9 +640,9 @@
struct fc_rport *rport = port->rport;
if (rport) {
- zfcp_dbf_rec_trig("scpdely", port->adapter, port, NULL,
- ZFCP_PSEUDO_ERP_ACTION_RPORT_DEL,
- ZFCP_PSEUDO_ERP_ACTION_RPORT_DEL);
+ zfcp_dbf_rec_trig_lock("scpdely", port->adapter, port, NULL,
+ ZFCP_PSEUDO_ERP_ACTION_RPORT_DEL,
+ ZFCP_PSEUDO_ERP_ACTION_RPORT_DEL);
fc_remote_port_delete(rport);
port->rport = NULL;
}
diff --git a/drivers/scsi/aacraid/commsup.c b/drivers/scsi/aacraid/commsup.c
index e2962f1..fe670b6 100644
--- a/drivers/scsi/aacraid/commsup.c
+++ b/drivers/scsi/aacraid/commsup.c
@@ -1374,9 +1374,10 @@
host = aac->scsi_host_ptr;
scsi_block_requests(host);
aac_adapter_disable_int(aac);
- if (aac->thread->pid != current->pid) {
+ if (aac->thread && aac->thread->pid != current->pid) {
spin_unlock_irq(host->host_lock);
kthread_stop(aac->thread);
+ aac->thread = NULL;
jafo = 1;
}
@@ -1445,6 +1446,7 @@
aac->name);
if (IS_ERR(aac->thread)) {
retval = PTR_ERR(aac->thread);
+ aac->thread = NULL;
goto out;
}
}
diff --git a/drivers/scsi/aacraid/linit.c b/drivers/scsi/aacraid/linit.c
index d5b26fa..ad902a6 100644
--- a/drivers/scsi/aacraid/linit.c
+++ b/drivers/scsi/aacraid/linit.c
@@ -1083,6 +1083,7 @@
up(&fib->event_wait);
}
kthread_stop(aac->thread);
+ aac->thread = NULL;
}
aac_adapter_disable_int(aac);
cpu = cpumask_first(cpu_online_mask);
@@ -1203,8 +1204,10 @@
* Map in the registers from the adapter.
*/
aac->base_size = AAC_MIN_FOOTPRINT_SIZE;
- if ((*aac_drivers[index].init)(aac))
+ if ((*aac_drivers[index].init)(aac)) {
+ error = -ENODEV;
goto out_unmap;
+ }
if (aac->sync_mode) {
if (aac_sync_mode)
diff --git a/drivers/scsi/arm/fas216.c b/drivers/scsi/arm/fas216.c
index 2438879..936e8c7 100644
--- a/drivers/scsi/arm/fas216.c
+++ b/drivers/scsi/arm/fas216.c
@@ -2011,7 +2011,7 @@
* have valid data in the sense buffer that could
* confuse the higher levels.
*/
- memset(SCpnt->sense_buffer, 0, sizeof(SCpnt->sense_buffer));
+ memset(SCpnt->sense_buffer, 0, SCSI_SENSE_BUFFERSIZE);
//printk("scsi%d.%c: sense buffer: ", info->host->host_no, '0' + SCpnt->device->id);
//{ int i; for (i = 0; i < 32; i++) printk("%02x ", SCpnt->sense_buffer[i]); printk("\n"); }
/*
diff --git a/drivers/scsi/bnx2fc/bnx2fc_io.c b/drivers/scsi/bnx2fc/bnx2fc_io.c
index f501095..bd39590 100644
--- a/drivers/scsi/bnx2fc/bnx2fc_io.c
+++ b/drivers/scsi/bnx2fc/bnx2fc_io.c
@@ -1869,6 +1869,7 @@
/* we will not receive ABTS response for this IO */
BNX2FC_IO_DBG(io_req, "Timer context finished processing "
"this scsi cmd\n");
+ return;
}
/* Cancel the timeout_work, as we received IO completion */
diff --git a/drivers/scsi/libsas/sas_scsi_host.c b/drivers/scsi/libsas/sas_scsi_host.c
index 519dac4..9a8c2f9 100644
--- a/drivers/scsi/libsas/sas_scsi_host.c
+++ b/drivers/scsi/libsas/sas_scsi_host.c
@@ -222,6 +222,7 @@
static void sas_eh_finish_cmd(struct scsi_cmnd *cmd)
{
struct sas_ha_struct *sas_ha = SHOST_TO_SAS_HA(cmd->device->host);
+ struct domain_device *dev = cmd_to_domain_dev(cmd);
struct sas_task *task = TO_SAS_TASK(cmd);
/* At this point, we only get called following an actual abort
@@ -230,6 +231,14 @@
*/
sas_end_task(cmd, task);
+ if (dev_is_sata(dev)) {
+ /* defer commands to libata so that libata EH can
+ * handle ata qcs correctly
+ */
+ list_move_tail(&cmd->eh_entry, &sas_ha->eh_ata_q);
+ return;
+ }
+
/* now finish the command and move it on to the error
* handler done list, this also takes it off the
* error handler pending list.
@@ -237,22 +246,6 @@
scsi_eh_finish_cmd(cmd, &sas_ha->eh_done_q);
}
-static void sas_eh_defer_cmd(struct scsi_cmnd *cmd)
-{
- struct domain_device *dev = cmd_to_domain_dev(cmd);
- struct sas_ha_struct *ha = dev->port->ha;
- struct sas_task *task = TO_SAS_TASK(cmd);
-
- if (!dev_is_sata(dev)) {
- sas_eh_finish_cmd(cmd);
- return;
- }
-
- /* report the timeout to libata */
- sas_end_task(cmd, task);
- list_move_tail(&cmd->eh_entry, &ha->eh_ata_q);
-}
-
static void sas_scsi_clear_queue_lu(struct list_head *error_q, struct scsi_cmnd *my_cmd)
{
struct scsi_cmnd *cmd, *n;
@@ -260,7 +253,7 @@
list_for_each_entry_safe(cmd, n, error_q, eh_entry) {
if (cmd->device->sdev_target == my_cmd->device->sdev_target &&
cmd->device->lun == my_cmd->device->lun)
- sas_eh_defer_cmd(cmd);
+ sas_eh_finish_cmd(cmd);
}
}
@@ -622,12 +615,12 @@
case TASK_IS_DONE:
SAS_DPRINTK("%s: task 0x%p is done\n", __func__,
task);
- sas_eh_defer_cmd(cmd);
+ sas_eh_finish_cmd(cmd);
continue;
case TASK_IS_ABORTED:
SAS_DPRINTK("%s: task 0x%p is aborted\n",
__func__, task);
- sas_eh_defer_cmd(cmd);
+ sas_eh_finish_cmd(cmd);
continue;
case TASK_IS_AT_LU:
SAS_DPRINTK("task 0x%p is at LU: lu recover\n", task);
@@ -638,7 +631,7 @@
"recovered\n",
SAS_ADDR(task->dev),
cmd->device->lun);
- sas_eh_defer_cmd(cmd);
+ sas_eh_finish_cmd(cmd);
sas_scsi_clear_queue_lu(work_q, cmd);
goto Again;
}
diff --git a/drivers/scsi/lpfc/lpfc_attr.c b/drivers/scsi/lpfc/lpfc_attr.c
index 4532990..cf15b97 100644
--- a/drivers/scsi/lpfc/lpfc_attr.c
+++ b/drivers/scsi/lpfc/lpfc_attr.c
@@ -635,7 +635,12 @@
LPFC_MBOXQ_t *pmboxq;
int mbxstatus = MBXERR_ERROR;
+ /*
+ * If the link is offline, disabled or BLOCK_MGMT_IO
+ * it doesn't make any sense to allow issue_lip
+ */
if ((vport->fc_flag & FC_OFFLINE_MODE) ||
+ (phba->hba_flag & LINK_DISABLED) ||
(phba->sli.sli_flag & LPFC_BLOCK_MGMT_IO))
return -EPERM;
diff --git a/drivers/scsi/lpfc/lpfc_hbadisc.c b/drivers/scsi/lpfc/lpfc_hbadisc.c
index 7d2ad63..8173645 100644
--- a/drivers/scsi/lpfc/lpfc_hbadisc.c
+++ b/drivers/scsi/lpfc/lpfc_hbadisc.c
@@ -690,8 +690,9 @@
(phba->hba_flag & HBA_SP_QUEUE_EVT)) {
if (pring->flag & LPFC_STOP_IOCB_EVENT) {
pring->flag |= LPFC_DEFERRED_RING_EVENT;
- /* Set the lpfc data pending flag */
- set_bit(LPFC_DATA_READY, &phba->data_flags);
+ /* Preserve legacy behavior. */
+ if (!(phba->hba_flag & HBA_SP_QUEUE_EVT))
+ set_bit(LPFC_DATA_READY, &phba->data_flags);
} else {
if (phba->link_state >= LPFC_LINK_UP) {
pring->flag &= ~LPFC_DEFERRED_RING_EVENT;
diff --git a/drivers/scsi/lpfc/lpfc_sli.c b/drivers/scsi/lpfc/lpfc_sli.c
index 0902ed2..6df06e7 100644
--- a/drivers/scsi/lpfc/lpfc_sli.c
+++ b/drivers/scsi/lpfc/lpfc_sli.c
@@ -116,6 +116,8 @@
/* set consumption flag every once in a while */
if (!((q->host_index + 1) % q->entry_repost))
bf_set(wqe_wqec, &wqe->generic.wqe_com, 1);
+ else
+ bf_set(wqe_wqec, &wqe->generic.wqe_com, 0);
if (q->phba->sli3_options & LPFC_SLI4_PHWQ_ENABLED)
bf_set(wqe_wqid, &wqe->generic.wqe_com, q->queue_id);
lpfc_sli_pcimem_bcopy(wqe, temp_wqe, q->entry_size);
diff --git a/drivers/scsi/mpt3sas/mpt3sas_scsih.c b/drivers/scsi/mpt3sas/mpt3sas_scsih.c
index 44da9d8..caa0045 100644
--- a/drivers/scsi/mpt3sas/mpt3sas_scsih.c
+++ b/drivers/scsi/mpt3sas/mpt3sas_scsih.c
@@ -8853,7 +8853,7 @@
snprintf(ioc->firmware_event_name, sizeof(ioc->firmware_event_name),
"fw_event_%s%d", ioc->driver_name, ioc->id);
ioc->firmware_event_thread = alloc_ordered_workqueue(
- ioc->firmware_event_name, WQ_MEM_RECLAIM);
+ ioc->firmware_event_name, 0);
if (!ioc->firmware_event_thread) {
pr_err(MPT3SAS_FMT "failure at %s:%d/%s()!\n",
ioc->name, __FILE__, __LINE__, __func__);
diff --git a/drivers/scsi/mvsas/mv_94xx.c b/drivers/scsi/mvsas/mv_94xx.c
index 7de5d8d..eb5471b 100644
--- a/drivers/scsi/mvsas/mv_94xx.c
+++ b/drivers/scsi/mvsas/mv_94xx.c
@@ -1080,16 +1080,16 @@
void __iomem *regs = mvi->regs_ex - 0x10200;
int drive = (i/3) & (4-1); /* drive number on host */
- u32 block = mr32(MVS_SGPIO_DCTRL +
+ int driveshift = drive * 8; /* bit offset of drive */
+ u32 block = ioread32be(regs + MVS_SGPIO_DCTRL +
MVS_SGPIO_HOST_OFFSET * mvi->id);
-
/*
* if bit is set then create a mask with the first
* bit of the drive set in the mask ...
*/
- u32 bit = (write_data[i/8] & (1 << (i&(8-1)))) ?
- 1<<(24-drive*8) : 0;
+ u32 bit = get_unaligned_be32(write_data) & (1 << i) ?
+ 1 << driveshift : 0;
/*
* ... and then shift it to the right position based
@@ -1098,26 +1098,27 @@
switch (i%3) {
case 0: /* activity */
block &= ~((0x7 << MVS_SGPIO_DCTRL_ACT_SHIFT)
- << (24-drive*8));
+ << driveshift);
/* hardwire activity bit to SOF */
block |= LED_BLINKA_SOF << (
MVS_SGPIO_DCTRL_ACT_SHIFT +
- (24-drive*8));
+ driveshift);
break;
case 1: /* id */
block &= ~((0x3 << MVS_SGPIO_DCTRL_LOC_SHIFT)
- << (24-drive*8));
+ << driveshift);
block |= bit << MVS_SGPIO_DCTRL_LOC_SHIFT;
break;
case 2: /* fail */
block &= ~((0x7 << MVS_SGPIO_DCTRL_ERR_SHIFT)
- << (24-drive*8));
+ << driveshift);
block |= bit << MVS_SGPIO_DCTRL_ERR_SHIFT;
break;
}
- mw32(MVS_SGPIO_DCTRL + MVS_SGPIO_HOST_OFFSET * mvi->id,
- block);
+ iowrite32be(block,
+ regs + MVS_SGPIO_DCTRL +
+ MVS_SGPIO_HOST_OFFSET * mvi->id);
}
@@ -1132,7 +1133,7 @@
void __iomem *regs = mvi->regs_ex - 0x10200;
mw32(MVS_SGPIO_DCTRL + MVS_SGPIO_HOST_OFFSET * mvi->id,
- be32_to_cpu(((u32 *) write_data)[i]));
+ ((u32 *) write_data)[i]);
}
return reg_count;
}
diff --git a/drivers/scsi/qla2xxx/qla_isr.c b/drivers/scsi/qla2xxx/qla_isr.c
index bddaabb..73c99f2 100644
--- a/drivers/scsi/qla2xxx/qla_isr.c
+++ b/drivers/scsi/qla2xxx/qla_isr.c
@@ -272,7 +272,8 @@
struct device_reg_2xxx __iomem *reg = &ha->iobase->isp;
/* Read all mbox registers? */
- mboxes = (1 << ha->mbx_count) - 1;
+ WARN_ON_ONCE(ha->mbx_count > 32);
+ mboxes = (1ULL << ha->mbx_count) - 1;
if (!ha->mcp)
ql_dbg(ql_dbg_async, vha, 0x5001, "MBX pointer ERROR.\n");
else
@@ -2516,7 +2517,8 @@
struct device_reg_24xx __iomem *reg = &ha->iobase->isp24;
/* Read all mbox registers? */
- mboxes = (1 << ha->mbx_count) - 1;
+ WARN_ON_ONCE(ha->mbx_count > 32);
+ mboxes = (1ULL << ha->mbx_count) - 1;
if (!ha->mcp)
ql_dbg(ql_dbg_async, vha, 0x504e, "MBX pointer ERROR.\n");
else
diff --git a/drivers/scsi/qla4xxx/ql4_def.h b/drivers/scsi/qla4xxx/ql4_def.h
index a7cfc27..ce1d063f 100644
--- a/drivers/scsi/qla4xxx/ql4_def.h
+++ b/drivers/scsi/qla4xxx/ql4_def.h
@@ -168,6 +168,8 @@
#define DEV_DB_NON_PERSISTENT 0
#define DEV_DB_PERSISTENT 1
+#define QL4_ISP_REG_DISCONNECT 0xffffffffU
+
#define COPY_ISID(dst_isid, src_isid) { \
int i, j; \
for (i = 0, j = ISID_SIZE - 1; i < ISID_SIZE;) \
diff --git a/drivers/scsi/qla4xxx/ql4_os.c b/drivers/scsi/qla4xxx/ql4_os.c
index 01c3610..d8c0343 100644
--- a/drivers/scsi/qla4xxx/ql4_os.c
+++ b/drivers/scsi/qla4xxx/ql4_os.c
@@ -262,6 +262,24 @@
static struct scsi_transport_template *qla4xxx_scsi_transport;
+static int qla4xxx_isp_check_reg(struct scsi_qla_host *ha)
+{
+ u32 reg_val = 0;
+ int rval = QLA_SUCCESS;
+
+ if (is_qla8022(ha))
+ reg_val = readl(&ha->qla4_82xx_reg->host_status);
+ else if (is_qla8032(ha) || is_qla8042(ha))
+ reg_val = qla4_8xxx_rd_direct(ha, QLA8XXX_PEG_ALIVE_COUNTER);
+ else
+ reg_val = readw(&ha->reg->ctrl_status);
+
+ if (reg_val == QL4_ISP_REG_DISCONNECT)
+ rval = QLA_ERROR;
+
+ return rval;
+}
+
static int qla4xxx_send_ping(struct Scsi_Host *shost, uint32_t iface_num,
uint32_t iface_type, uint32_t payload_size,
uint32_t pid, struct sockaddr *dst_addr)
@@ -9196,10 +9214,17 @@
struct srb *srb = NULL;
int ret = SUCCESS;
int wait = 0;
+ int rval;
ql4_printk(KERN_INFO, ha, "scsi%ld:%d:%llu: Abort command issued cmd=%p, cdb=0x%x\n",
ha->host_no, id, lun, cmd, cmd->cmnd[0]);
+ rval = qla4xxx_isp_check_reg(ha);
+ if (rval != QLA_SUCCESS) {
+ ql4_printk(KERN_INFO, ha, "PCI/Register disconnect, exiting.\n");
+ return FAILED;
+ }
+
spin_lock_irqsave(&ha->hardware_lock, flags);
srb = (struct srb *) CMD_SP(cmd);
if (!srb) {
@@ -9251,6 +9276,7 @@
struct scsi_qla_host *ha = to_qla_host(cmd->device->host);
struct ddb_entry *ddb_entry = cmd->device->hostdata;
int ret = FAILED, stat;
+ int rval;
if (!ddb_entry)
return ret;
@@ -9270,6 +9296,12 @@
cmd, jiffies, cmd->request->timeout / HZ,
ha->dpc_flags, cmd->result, cmd->allowed));
+ rval = qla4xxx_isp_check_reg(ha);
+ if (rval != QLA_SUCCESS) {
+ ql4_printk(KERN_INFO, ha, "PCI/Register disconnect, exiting.\n");
+ return FAILED;
+ }
+
/* FIXME: wait for hba to go online */
stat = qla4xxx_reset_lun(ha, ddb_entry, cmd->device->lun);
if (stat != QLA_SUCCESS) {
@@ -9313,6 +9345,7 @@
struct scsi_qla_host *ha = to_qla_host(cmd->device->host);
struct ddb_entry *ddb_entry = cmd->device->hostdata;
int stat, ret;
+ int rval;
if (!ddb_entry)
return FAILED;
@@ -9330,6 +9363,12 @@
ha->host_no, cmd, jiffies, cmd->request->timeout / HZ,
ha->dpc_flags, cmd->result, cmd->allowed));
+ rval = qla4xxx_isp_check_reg(ha);
+ if (rval != QLA_SUCCESS) {
+ ql4_printk(KERN_INFO, ha, "PCI/Register disconnect, exiting.\n");
+ return FAILED;
+ }
+
stat = qla4xxx_reset_target(ha, ddb_entry);
if (stat != QLA_SUCCESS) {
starget_printk(KERN_INFO, scsi_target(cmd->device),
@@ -9384,9 +9423,16 @@
{
int return_status = FAILED;
struct scsi_qla_host *ha;
+ int rval;
ha = to_qla_host(cmd->device->host);
+ rval = qla4xxx_isp_check_reg(ha);
+ if (rval != QLA_SUCCESS) {
+ ql4_printk(KERN_INFO, ha, "PCI/Register disconnect, exiting.\n");
+ return FAILED;
+ }
+
if ((is_qla8032(ha) || is_qla8042(ha)) && ql4xdontresethba)
qla4_83xx_set_idc_dontreset(ha);
diff --git a/drivers/scsi/sd.c b/drivers/scsi/sd.c
index b20cd8f..1cb0403 100644
--- a/drivers/scsi/sd.c
+++ b/drivers/scsi/sd.c
@@ -2321,6 +2321,7 @@
int res;
struct scsi_device *sdp = sdkp->device;
struct scsi_mode_data data;
+ int disk_ro = get_disk_ro(sdkp->disk);
set_disk_ro(sdkp->disk, 0);
if (sdp->skip_ms_page_3f) {
@@ -2360,7 +2361,7 @@
"Test WP failed, assume Write Enabled\n");
} else {
sdkp->write_prot = ((data.device_specific & 0x80) != 0);
- set_disk_ro(sdkp->disk, sdkp->write_prot);
+ set_disk_ro(sdkp->disk, sdkp->write_prot || disk_ro);
}
}
diff --git a/drivers/scsi/sg.c b/drivers/scsi/sg.c
index 3d9ad4c..15d5af0 100644
--- a/drivers/scsi/sg.c
+++ b/drivers/scsi/sg.c
@@ -1897,7 +1897,7 @@
num = (rem_sz > scatter_elem_sz_prev) ?
scatter_elem_sz_prev : rem_sz;
- schp->pages[k] = alloc_pages(gfp_mask, order);
+ schp->pages[k] = alloc_pages(gfp_mask | __GFP_ZERO, order);
if (!schp->pages[k])
goto out;
diff --git a/drivers/scsi/storvsc_drv.c b/drivers/scsi/storvsc_drv.c
index 0dd1984..d92b280 100644
--- a/drivers/scsi/storvsc_drv.c
+++ b/drivers/scsi/storvsc_drv.c
@@ -1580,7 +1580,7 @@
.eh_timed_out = storvsc_eh_timed_out,
.slave_alloc = storvsc_device_alloc,
.slave_configure = storvsc_device_configure,
- .cmd_per_lun = 255,
+ .cmd_per_lun = 2048,
.this_id = -1,
.use_clustering = ENABLE_CLUSTERING,
/* Make sure we dont get a sg segment crosses a page boundary */
diff --git a/drivers/scsi/sym53c8xx_2/sym_hipd.c b/drivers/scsi/sym53c8xx_2/sym_hipd.c
index 6b349e3..c6425e3 100644
--- a/drivers/scsi/sym53c8xx_2/sym_hipd.c
+++ b/drivers/scsi/sym53c8xx_2/sym_hipd.c
@@ -536,7 +536,7 @@
* Look for the greatest clock divisor that allows an
* input speed faster than the period.
*/
- while (div-- > 0)
+ while (--div > 0)
if (kpc >= (div_10M[div] << 2)) break;
/*
diff --git a/drivers/scsi/ufs/ufshcd.c b/drivers/scsi/ufs/ufshcd.c
index aeb09f3..c6cfd18 100644
--- a/drivers/scsi/ufs/ufshcd.c
+++ b/drivers/scsi/ufs/ufshcd.c
@@ -5433,7 +5433,7 @@
/* REPORT SUPPORTED OPERATION CODES is not supported */
sdev->no_report_opcodes = 1;
- /* WRITE_SAME command is not supported*/
+ /* WRITE_SAME command is not supported */
sdev->no_write_same = 1;
ufshcd_set_queue_depth(sdev);
@@ -6559,8 +6559,8 @@
u32 mode;
hba = container_of(work, struct ufs_hba, rls_work);
- ufshcd_scsi_block_requests(hba);
pm_runtime_get_sync(hba->dev);
+ ufshcd_scsi_block_requests(hba);
down_write(&hba->lock);
ret = ufshcd_wait_for_doorbell_clr(hba, U64_MAX);
if (ret) {
diff --git a/drivers/soc/qcom/bg_rsb.c b/drivers/soc/qcom/bg_rsb.c
index 02c6deb..ffba372 100644
--- a/drivers/soc/qcom/bg_rsb.c
+++ b/drivers/soc/qcom/bg_rsb.c
@@ -122,6 +122,8 @@
struct device *ldev;
+ struct wakeup_source bgrsb_ws;
+
wait_queue_head_t link_state_wait;
uint32_t calbrtion_intrvl;
@@ -462,6 +464,7 @@
if (!dev->chnl_state)
return -ENODEV;
+ __pm_stay_awake(&dev->bgrsb_ws);
mutex_lock(&dev->glink_mutex);
init_completion(&dev->tx_done);
init_completion(&dev->bg_resp_cmplt);
@@ -507,6 +510,7 @@
err_ret:
mutex_unlock(&dev->glink_mutex);
+ __pm_relax(&dev->bgrsb_ws);
return rc;
}
@@ -904,6 +908,9 @@
if (!dev)
return -ENOMEM;
+ /* Add wake lock for PM suspend */
+ wakeup_source_init(&dev->bgrsb_ws, "BGRSB_wake_lock");
+
dev->bgrsb_current_state = BGRSB_STATE_UNKNOWN;
rc = bgrsb_init(dev);
if (rc)
@@ -964,6 +971,7 @@
destroy_workqueue(dev->bgrsb_event_wq);
destroy_workqueue(dev->bgrsb_wq);
input_free_device(dev->input);
+ wakeup_source_trash(&dev->bgrsb_ws);
return 0;
}
diff --git a/drivers/soc/qcom/big_cluster_min_freq_adjust.c b/drivers/soc/qcom/big_cluster_min_freq_adjust.c
index dbc89e1..979dd81 100644
--- a/drivers/soc/qcom/big_cluster_min_freq_adjust.c
+++ b/drivers/soc/qcom/big_cluster_min_freq_adjust.c
@@ -125,8 +125,13 @@
cancel_delayed_work(&p->min_freq_work);
- if (p->min_freq_state != p->min_freq_request)
- schedule_delayed_work(&p->min_freq_work, delay);
+ if (p->min_freq_state != p->min_freq_request) {
+ if (p->min_freq_request == ADJUST_MIN_FLOOR) {
+ if (p->min_freq_floor > cpufreq_quick_get(cpu))
+ delay = 0;
+ }
+ queue_delayed_work(system_unbound_wq, &p->min_freq_work, delay);
+ }
spin_unlock(&p->lock);
return NOTIFY_OK;
@@ -160,13 +165,12 @@
if (p->big_min_freq_on == true)
return 0;
- INIT_DEFERRABLE_WORK(&p->min_freq_work, cpufreq_min_freq_work);
+ if (!cpumask_weight(&p->cluster_cpumask)) {
+ pr_err("Cluster CPU IDs not set\n");
+ return -EPERM;
+ }
- cpumask_clear(&p->cluster_cpumask);
- cpumask_set_cpu(4, &p->cluster_cpumask);
- cpumask_set_cpu(5, &p->cluster_cpumask);
- cpumask_set_cpu(6, &p->cluster_cpumask);
- cpumask_set_cpu(7, &p->cluster_cpumask);
+ INIT_DEFERRABLE_WORK(&p->min_freq_work, cpufreq_min_freq_work);
if (!big_min_down_delay_ms) {
big_min_down_delay_ms = MIN_DOWN_DELAY_MSEC;
@@ -267,6 +271,48 @@
module_param_cb(min_down_delay_ms, ¶m_ops_big_min_down_delay_ms,
&big_min_down_delay_ms, 0644);
+#define MAX_STR_LEN 16
+static char big_min_freq_cluster[MAX_STR_LEN];
+static struct kparam_string big_min_freq_cluster_kps = {
+ .string = big_min_freq_cluster,
+ .maxlen = MAX_STR_LEN,
+};
+
+static int set_big_min_freq_cluster(const char *buf,
+ const struct kernel_param *kp)
+{
+ struct big_min_freq_adjust_data *p = &big_min_freq_adjust_data;
+ int ret;
+
+ if (p->big_min_freq_on == true) {
+ ret = -EPERM;
+ goto err;
+ }
+
+ ret = param_set_copystring(buf, kp);
+ if (ret)
+ goto err;
+
+ ret = cpulist_parse(big_min_freq_cluster_kps.string,
+ &p->cluster_cpumask);
+ if (ret) {
+ cpumask_clear(&p->cluster_cpumask);
+ goto err;
+ }
+
+ return 0;
+err:
+ pr_err("Unable to set big_min_freq_cluster: %d\n", ret);
+ return ret;
+}
+
+static const struct kernel_param_ops param_ops_big_min_freq_cluster = {
+ .set = set_big_min_freq_cluster,
+ .get = param_get_string,
+};
+module_param_cb(min_freq_cluster, ¶m_ops_big_min_freq_cluster,
+ &big_min_freq_cluster_kps, 0644);
+
static int __init big_min_freq_adjust_init(void)
{
big_min_freq_adjust_data.is_init = true;
diff --git a/drivers/soc/qcom/cmd-db.c b/drivers/soc/qcom/cmd-db.c
index c9dc547..23fde2e 100644
--- a/drivers/soc/qcom/cmd-db.c
+++ b/drivers/soc/qcom/cmd-db.c
@@ -365,6 +365,7 @@
res.start = readl_relaxed(dict);
res.end = res.start + readl_relaxed(dict + 0x4);
res.flags = IORESOURCE_MEM;
+ res.name = NULL;
iounmap(dict);
start_addr = devm_ioremap_resource(&pdev->dev, &res);
diff --git a/drivers/soc/qcom/glink.c b/drivers/soc/qcom/glink.c
index b8deec1..c976f17 100644
--- a/drivers/soc/qcom/glink.c
+++ b/drivers/soc/qcom/glink.c
@@ -1775,6 +1775,18 @@
return tx_pkt;
}
}
+ list_for_each_entry(tx_pkt, &ctx->tx_active, list_node) {
+ if (tx_pkt->riid == riid) {
+ if (tx_pkt->size_remaining) {
+ GLINK_ERR_CH(ctx, "%s: R[%u] TX not complete",
+ __func__, riid);
+ tx_pkt = NULL;
+ }
+ spin_unlock_irqrestore(
+ &ctx->tx_pending_rmt_done_lock_lhc4, flags);
+ return tx_pkt;
+ }
+ }
spin_unlock_irqrestore(&ctx->tx_pending_rmt_done_lock_lhc4, flags);
GLINK_ERR_CH(ctx, "%s: R[%u] Tx packet for intent not found.\n",
@@ -1817,6 +1829,20 @@
return;
}
}
+ list_for_each_entry_safe(local_tx_pkt, tmp_tx_pkt,
+ &ctx->tx_active, list_node) {
+ if (tx_pkt == local_tx_pkt) {
+ list_del_init(&tx_pkt->list_done);
+ GLINK_DBG_CH(ctx,
+ "%s: R[%u] Removed Tx packet for intent\n",
+ __func__,
+ tx_pkt->riid);
+ rwref_put(&tx_pkt->pkt_ref);
+ spin_unlock_irqrestore(
+ &ctx->tx_pending_rmt_done_lock_lhc4, flags);
+ return;
+ }
+ }
spin_unlock_irqrestore(&ctx->tx_pending_rmt_done_lock_lhc4, flags);
GLINK_ERR_CH(ctx, "%s: R[%u] Tx packet for intent not found", __func__,
@@ -5578,12 +5604,6 @@
tx_info = list_first_entry(&ctx->tx_active,
struct glink_core_tx_pkt, list_node);
rwref_get(&tx_info->pkt_ref);
-
- spin_lock(&ctx->tx_pending_rmt_done_lock_lhc4);
- if (list_empty(&tx_info->list_done))
- list_add(&tx_info->list_done,
- &ctx->tx_pending_remote_done);
- spin_unlock(&ctx->tx_pending_rmt_done_lock_lhc4);
spin_unlock_irqrestore(&ctx->tx_lists_lock_lhc3, flags);
if (unlikely(tx_info->tracer_pkt)) {
@@ -5648,9 +5668,16 @@
txd_len += tx_len;
if (!tx_info->size_remaining) {
num_pkts++;
+ spin_lock(&ctx->tx_pending_rmt_done_lock_lhc4);
list_del_init(&tx_info->list_node);
+ if (list_empty(&tx_info->list_done))
+ list_add(&tx_info->list_done,
+ &ctx->tx_pending_remote_done);
+ rwref_put(&tx_info->pkt_ref);
+ spin_unlock(&ctx->tx_pending_rmt_done_lock_lhc4);
+ } else {
+ rwref_put(&tx_info->pkt_ref);
}
- rwref_put(&tx_info->pkt_ref);
}
ctx->txd_len += txd_len;
diff --git a/drivers/soc/qcom/glink_smem_native_xprt.c b/drivers/soc/qcom/glink_smem_native_xprt.c
index ca9953a..5640666 100644
--- a/drivers/soc/qcom/glink_smem_native_xprt.c
+++ b/drivers/soc/qcom/glink_smem_native_xprt.c
@@ -949,6 +949,12 @@
return;
}
+ if (!einfo->rx_fifo) {
+ if (!get_rx_fifo(einfo))
+ return;
+ einfo->xprt_if.glink_core_if_ptr->link_up(&einfo->xprt_if);
+ }
+
if ((atomic_ctx) && ((einfo->tx_resume_needed) ||
(waitqueue_active(&einfo->tx_blocked_queue)))) /* tx waiting ?*/
tx_wakeup_worker(einfo);
@@ -1554,10 +1560,10 @@
struct edge_info *einfo;
einfo = container_of(if_ptr, struct edge_info, xprt_if);
+ einfo->in_ssr = false;
if (!einfo->rx_fifo) {
if (!get_rx_fifo(einfo))
return;
- einfo->in_ssr = false;
einfo->xprt_if.glink_core_if_ptr->link_up(&einfo->xprt_if);
}
}
diff --git a/drivers/soc/qcom/socinfo.c b/drivers/soc/qcom/socinfo.c
index e02bf84..fffef10 100644
--- a/drivers/soc/qcom/socinfo.c
+++ b/drivers/soc/qcom/socinfo.c
@@ -593,12 +593,18 @@
/* QCS605 ID */
[347] = {MSM_CPU_QCS605, "QCS605"},
+ /* SXR1130 ID */
+ [371] = {MSM_CPU_SXR1130, "SXR1130"},
+
/* SDA670 ID */
[337] = {MSM_CPU_SDA670, "SDA670"},
/* SDM710 ID */
[360] = {MSM_CPU_SDM710, "SDM710"},
+ /* SXR1120 ID */
+ [370] = {MSM_CPU_SXR1120, "SXR1120"},
+
/* 8953 ID */
[293] = {MSM_CPU_8953, "MSM8953"},
[304] = {MSM_CPU_8953, "APQ8053"},
@@ -615,6 +621,12 @@
[294] = {MSM_CPU_8937, "MSM8937"},
[295] = {MSM_CPU_8937, "APQ8937"},
+ /* MSM8917 IDs */
+ [303] = {MSM_CPU_8917, "MSM8917"},
+ [307] = {MSM_CPU_8917, "APQ8017"},
+ [308] = {MSM_CPU_8917, "MSM8217"},
+ [309] = {MSM_CPU_8917, "MSM8617"},
+
/* SDM429 and SDM439 ID*/
[353] = {MSM_CPU_SDM439, "SDM439"},
[354] = {MSM_CPU_SDM429, "SDM429"},
@@ -1532,6 +1544,10 @@
dummy_socinfo.id = 336;
strlcpy(dummy_socinfo.build_id, "sdm670 - ",
sizeof(dummy_socinfo.build_id));
+ } else if (early_machine_is_sxr1130()) {
+ dummy_socinfo.id = 371;
+ strlcpy(dummy_socinfo.build_id, "sxr1130 - ",
+ sizeof(dummy_socinfo.build_id));
} else if (early_machine_is_sdm710()) {
dummy_socinfo.id = 360;
strlcpy(dummy_socinfo.build_id, "sdm710 - ",
@@ -1544,6 +1560,10 @@
dummy_socinfo.id = 347;
strlcpy(dummy_socinfo.build_id, "qcs605 - ",
sizeof(dummy_socinfo.build_id));
+ } else if (early_machine_is_sxr1120()) {
+ dummy_socinfo.id = 370;
+ strlcpy(dummy_socinfo.build_id, "sxr1120 - ",
+ sizeof(dummy_socinfo.build_id));
} else if (early_machine_is_mdm9650()) {
dummy_socinfo.id = 286;
strlcpy(dummy_socinfo.build_id, "mdm9650 - ",
@@ -1560,6 +1580,10 @@
dummy_socinfo.id = 294;
strlcpy(dummy_socinfo.build_id, "msm8937 - ",
sizeof(dummy_socinfo.build_id));
+ } else if (early_machine_is_msm8917()) {
+ dummy_socinfo.id = 303;
+ strlcpy(dummy_socinfo.build_id, "msm8917 - ",
+ sizeof(dummy_socinfo.build_id));
} else if (early_machine_is_sdm450()) {
dummy_socinfo.id = 338;
strlcpy(dummy_socinfo.build_id, "sdm450 - ",
diff --git a/drivers/spi/spi-bcm-qspi.c b/drivers/spi/spi-bcm-qspi.c
index 7d629b4..adc3f56 100644
--- a/drivers/spi/spi-bcm-qspi.c
+++ b/drivers/spi/spi-bcm-qspi.c
@@ -514,7 +514,7 @@
static void bcm_qspi_enable_bspi(struct bcm_qspi *qspi)
{
- if (!has_bspi(qspi) || (qspi->bspi_enabled))
+ if (!has_bspi(qspi))
return;
qspi->bspi_enabled = 1;
@@ -529,7 +529,7 @@
static void bcm_qspi_disable_bspi(struct bcm_qspi *qspi)
{
- if (!has_bspi(qspi) || (!qspi->bspi_enabled))
+ if (!has_bspi(qspi))
return;
qspi->bspi_enabled = 0;
@@ -543,16 +543,19 @@
static void bcm_qspi_chip_select(struct bcm_qspi *qspi, int cs)
{
- u32 data = 0;
+ u32 rd = 0;
+ u32 wr = 0;
- if (qspi->curr_cs == cs)
- return;
if (qspi->base[CHIP_SELECT]) {
- data = bcm_qspi_read(qspi, CHIP_SELECT, 0);
- data = (data & ~0xff) | (1 << cs);
- bcm_qspi_write(qspi, CHIP_SELECT, 0, data);
+ rd = bcm_qspi_read(qspi, CHIP_SELECT, 0);
+ wr = (rd & ~0xff) | (1 << cs);
+ if (rd == wr)
+ return;
+ bcm_qspi_write(qspi, CHIP_SELECT, 0, wr);
usleep_range(10, 20);
}
+
+ dev_dbg(&qspi->pdev->dev, "using cs:%d\n", cs);
qspi->curr_cs = cs;
}
@@ -770,8 +773,13 @@
dev_dbg(&qspi->pdev->dev, "WR %04x\n", val);
}
mspi_cdram = MSPI_CDRAM_CONT_BIT;
- mspi_cdram |= (~(1 << spi->chip_select) &
- MSPI_CDRAM_PCS);
+
+ if (has_bspi(qspi))
+ mspi_cdram &= ~1;
+ else
+ mspi_cdram |= (~(1 << spi->chip_select) &
+ MSPI_CDRAM_PCS);
+
mspi_cdram |= ((tp.trans->bits_per_word <= 8) ? 0 :
MSPI_CDRAM_BITSE_BIT);
diff --git a/drivers/spi/spi-geni-qcom.c b/drivers/spi/spi-geni-qcom.c
index c42c49c..1663d3b 100644
--- a/drivers/spi/spi-geni-qcom.c
+++ b/drivers/spi/spi-geni-qcom.c
@@ -89,7 +89,7 @@
#define TIMESTAMP_AFTER BIT(3)
#define POST_CMD_DELAY BIT(4)
-#define SPI_CORE2X_VOTE (10000)
+#define SPI_CORE2X_VOTE (7600)
/* GSI CONFIG0 TRE Params */
/* Flags bit fields */
#define GSI_LOOPBACK_EN (BIT(0))
@@ -752,9 +752,8 @@
u32 max_speed = spi->cur_msg->spi->max_speed_hz;
struct se_geni_rsc *rsc = &mas->spi_rsc;
- /* Adjust the AB/IB based on the max speed of the slave.*/
+ /* Adjust the IB based on the max speed of the slave.*/
rsc->ib = max_speed * DEFAULT_BUS_WIDTH;
- rsc->ab = max_speed * DEFAULT_BUS_WIDTH;
if (mas->shared_se) {
struct se_geni_rsc *rsc;
int ret = 0;
diff --git a/drivers/spi/spi-pxa2xx.h b/drivers/spi/spi-pxa2xx.h
index ce31b81..b8e004d 100644
--- a/drivers/spi/spi-pxa2xx.h
+++ b/drivers/spi/spi-pxa2xx.h
@@ -38,7 +38,7 @@
/* SSP register addresses */
void __iomem *ioaddr;
- u32 ssdr_physical;
+ phys_addr_t ssdr_physical;
/* SSP masks*/
u32 dma_cr1;
diff --git a/drivers/staging/android/ion/ion_system_heap.c b/drivers/staging/android/ion/ion_system_heap.c
index 3ac71ed..3b27252 100644
--- a/drivers/staging/android/ion/ion_system_heap.c
+++ b/drivers/staging/android/ion/ion_system_heap.c
@@ -756,8 +756,10 @@
{
int i;
for (i = 0; i < num_orders; i++)
- if (pools[i])
+ if (pools[i]) {
ion_page_pool_destroy(pools[i]);
+ pools[i] = NULL;
+ }
}
/**
diff --git a/drivers/staging/lustre/lustre/include/obd.h b/drivers/staging/lustre/lustre/include/obd.h
index f6fc4dd..722c33f 100644
--- a/drivers/staging/lustre/lustre/include/obd.h
+++ b/drivers/staging/lustre/lustre/include/obd.h
@@ -253,7 +253,7 @@
struct sptlrpc_flavor cl_flvr_mgc; /* fixed flavor of mgc->mgs */
/* the grant values are protected by loi_list_lock below */
- unsigned long cl_dirty_pages; /* all _dirty_ in pahges */
+ unsigned long cl_dirty_pages; /* all _dirty_ in pages */
unsigned long cl_dirty_max_pages; /* allowed w/o rpc */
unsigned long cl_dirty_transit; /* dirty synchronous */
unsigned long cl_avail_grant; /* bytes of credit for ost */
diff --git a/drivers/staging/lustre/lustre/lmv/lmv_obd.c b/drivers/staging/lustre/lustre/lmv/lmv_obd.c
index cd19ce8..9e63171 100644
--- a/drivers/staging/lustre/lustre/lmv/lmv_obd.c
+++ b/drivers/staging/lustre/lustre/lmv/lmv_obd.c
@@ -2928,7 +2928,7 @@
if (lsm && !lmm) {
int i;
- for (i = 1; i < lsm->lsm_md_stripe_count; i++) {
+ for (i = 0; i < lsm->lsm_md_stripe_count; i++) {
/*
* For migrating inode, the master stripe and master
* object will be the same, so do not need iput, see
diff --git a/drivers/staging/lustre/lustre/osc/osc_cache.c b/drivers/staging/lustre/lustre/osc/osc_cache.c
index 4bbe219..1a8c9f5 100644
--- a/drivers/staging/lustre/lustre/osc/osc_cache.c
+++ b/drivers/staging/lustre/lustre/osc/osc_cache.c
@@ -1542,7 +1542,7 @@
if (rc < 0)
return 0;
- if (cli->cl_dirty_pages <= cli->cl_dirty_max_pages &&
+ if (cli->cl_dirty_pages < cli->cl_dirty_max_pages &&
atomic_long_read(&obd_dirty_pages) + 1 <= obd_max_dirty_pages) {
osc_consume_write_grant(cli, &oap->oap_brw_page);
if (transient) {
diff --git a/drivers/staging/rtl8192u/r8192U_core.c b/drivers/staging/rtl8192u/r8192U_core.c
index 457eeb5..5fe9593 100644
--- a/drivers/staging/rtl8192u/r8192U_core.c
+++ b/drivers/staging/rtl8192u/r8192U_core.c
@@ -1705,6 +1705,8 @@
priv->rx_urb[16] = usb_alloc_urb(0, GFP_KERNEL);
priv->oldaddr = kmalloc(16, GFP_KERNEL);
+ if (!priv->oldaddr)
+ return -ENOMEM;
oldaddr = priv->oldaddr;
align = ((long)oldaddr) & 3;
if (align) {
diff --git a/drivers/thermal/Makefile b/drivers/thermal/Makefile
index 1259654..ae24a68 100644
--- a/drivers/thermal/Makefile
+++ b/drivers/thermal/Makefile
@@ -58,4 +58,4 @@
obj-$(CONFIG_MTK_THERMAL) += mtk_thermal.o
obj-$(CONFIG_GENERIC_ADC_THERMAL) += thermal-generic-adc.o
obj-$(CONFIG_THERMAL_QPNP_ADC_TM) += qpnp-adc-tm.o
-obj-$(CONFIG_THERMAL_TSENS) += msm-tsens.o tsens2xxx.o tsens-dbg.o tsens-mtc.o tsens1xxx.o
+obj-$(CONFIG_THERMAL_TSENS) += msm-tsens.o tsens2xxx.o tsens-dbg.o tsens-mtc.o tsens1xxx.o tsens_calib.o
diff --git a/drivers/thermal/msm-tsens.c b/drivers/thermal/msm-tsens.c
index c137d3d..6241ef6 100644
--- a/drivers/thermal/msm-tsens.c
+++ b/drivers/thermal/msm-tsens.c
@@ -90,6 +90,9 @@
{ .compatible = "qcom,msm8937-tsens",
.data = &data_tsens14xx,
},
+ { .compatible = "qcom,msm8909-tsens",
+ .data = &data_tsens1xxx_8909,
+ },
{}
};
MODULE_DEVICE_TABLE(of, tsens_table);
diff --git a/drivers/thermal/tsens.h b/drivers/thermal/tsens.h
index d35b867..c8e6233 100644
--- a/drivers/thermal/tsens.h
+++ b/drivers/thermal/tsens.h
@@ -23,7 +23,8 @@
#define DEBUG_SIZE 10
#define TSENS_MAX_SENSORS 16
-#define TSENS_1x_MAX_SENSORS 11
+#define TSENS_NUM_SENSORS_8937 11
+#define TSENS_NUM_SENSORS_8909 5
#define TSENS_CONTROLLER_ID(n) (n)
#define TSENS_CTRL_ADDR(n) (n)
#define TSENS_TM_SN_STATUS(n) ((n) + 0xa0)
@@ -32,6 +33,9 @@
#define ONE_PT_CALIB2 0x2
#define TWO_PT_CALIB 0x3
+#define SLOPE_FACTOR 1000
+#define SLOPE_DEFAULT 3200
+
enum tsens_dbg_type {
TSENS_DBG_POLL,
TSENS_DBG_LOG_TEMP_READS,
@@ -143,6 +147,7 @@
struct device *dev;
struct platform_device *pdev;
struct list_head list;
+ bool prev_reading_avail;
struct regmap *map;
struct regmap_field *status_field;
void __iomem *tsens_srot_addr;
@@ -158,7 +163,10 @@
};
extern const struct tsens_data data_tsens2xxx, data_tsens23xx, data_tsens24xx;
-extern const struct tsens_data data_tsens14xx;
+extern const struct tsens_data data_tsens14xx, data_tsens1xxx_8909;
extern struct list_head tsens_device_list;
+extern int calibrate_8937(struct tsens_device *tmdev);
+extern int calibrate_8909(struct tsens_device *tmdev);
+
#endif /* __QCOM_TSENS_H__ */
diff --git a/drivers/thermal/tsens1xxx.c b/drivers/thermal/tsens1xxx.c
index 19e2b5a..d698aed 100644
--- a/drivers/thermal/tsens1xxx.c
+++ b/drivers/thermal/tsens1xxx.c
@@ -33,6 +33,7 @@
#define TSENS_UPPER_THRESHOLD_SHIFT 10
#define TSENS_S0_STATUS_ADDR(n) ((n) + 0x30)
+#define TSENS_S0_TRDY_ADDR(n) ((n) + 0x5c)
#define TSENS_SN_ADDR_OFFSET 0x4
#define TSENS_SN_STATUS_TEMP_MASK 0x3ff
#define TSENS_SN_STATUS_LOWER_STATUS BIT(11)
@@ -55,102 +56,6 @@
#define TSENS_THRESHOLD_MIN_CODE 0x0
#define TSENS_SCALE_MILLIDEG 1000
-/* eeprom layout data for 8937 */
-#define BASE0_MASK 0x000000ff
-#define BASE1_MASK 0xff000000
-#define BASE1_SHIFT 24
-
-#define S0_P1_MASK 0x000001f8
-#define S1_P1_MASK 0x001f8000
-#define S2_P1_MASK_0_4 0xf8000000
-#define S2_P1_MASK_5 0x00000001
-#define S3_P1_MASK 0x00001f80
-#define S4_P1_MASK 0x01f80000
-#define S5_P1_MASK 0x00003f00
-#define S6_P1_MASK 0x03f00000
-#define S7_P1_MASK 0x0000003f
-#define S8_P1_MASK 0x0003f000
-#define S9_P1_MASK 0x0000003f
-#define S10_P1_MASK 0x0003f000
-
-#define S0_P2_MASK 0x00007e00
-#define S1_P2_MASK 0x07e00000
-#define S2_P2_MASK 0x0000007e
-#define S3_P2_MASK 0x0007e000
-#define S4_P2_MASK 0x7e000000
-#define S5_P2_MASK 0x000fc000
-#define S6_P2_MASK 0xfc000000
-#define S7_P2_MASK 0x00000fc0
-#define S8_P2_MASK 0x00fc0000
-#define S9_P2_MASK 0x00000fc0
-#define S10_P2_MASK 0x00fc0000
-
-#define S0_P1_SHIFT 3
-#define S1_P1_SHIFT 15
-#define S2_P1_SHIFT_0_4 27
-#define S2_P1_SHIFT_5 5
-#define S3_P1_SHIFT 7
-#define S4_P1_SHIFT 19
-#define S5_P1_SHIFT 8
-#define S6_P1_SHIFT 20
-#define S8_P1_SHIFT 12
-#define S10_P1_SHIFT 12
-
-#define S0_P2_SHIFT 9
-#define S1_P2_SHIFT 21
-#define S2_P2_SHIFT 1
-#define S3_P2_SHIFT 13
-#define S4_P2_SHIFT 25
-#define S5_P2_SHIFT 14
-#define S6_P2_SHIFT 26
-#define S7_P2_SHIFT 6
-#define S8_P2_SHIFT 18
-#define S9_P2_SHIFT 6
-#define S10_P2_SHIFT 18
-
-#define CAL_SEL_MASK 0x00000007
-
-#define CAL_DEGC_PT1 30
-#define CAL_DEGC_PT2 120
-#define SLOPE_FACTOR 1000
-#define SLOPE_DEFAULT 3200
-
-/*
- * Use this function on devices where slope and offset calculations
- * depend on calibration data read from qfprom. On others the slope
- * and offset values are derived from tz->tzp->slope and tz->tzp->offset
- * resp.
- */
-static void compute_intercept_slope(struct tsens_device *tmdev, u32 *p1,
- u32 *p2, u32 mode)
-{
- int i;
- int num, den;
-
- for (i = 0; i < TSENS_1x_MAX_SENSORS; i++) {
- pr_debug(
- "sensor%d - data_point1:%#x data_point2:%#x\n",
- i, p1[i], p2[i]);
-
- tmdev->sensor[i].slope = SLOPE_DEFAULT;
- if (mode == TWO_PT_CALIB) {
- /*
- * slope (m) = adc_code2 - adc_code1 (y2 - y1)/
- * temp_120_degc - temp_30_degc (x2 - x1)
- */
- num = p2[i] - p1[i];
- num *= SLOPE_FACTOR;
- den = CAL_DEGC_PT2 - CAL_DEGC_PT1;
- tmdev->sensor[i].slope = num / den;
- }
-
- tmdev->sensor[i].offset = (p1[i] * SLOPE_FACTOR) -
- (CAL_DEGC_PT1 *
- tmdev->sensor[i].slope);
- pr_debug("offset:%d\n", tmdev->sensor[i].offset);
- }
-}
-
static int code_to_degc(u32 adc_code, const struct tsens_sensor *sensor)
{
int degc, num, den;
@@ -184,72 +89,6 @@
return code;
}
-static int calibrate_8937(struct tsens_device *tmdev)
-{
- int base0 = 0, base1 = 0, i;
- u32 p1[TSENS_1x_MAX_SENSORS], p2[TSENS_1x_MAX_SENSORS];
- int mode = 0, tmp = 0;
- u32 qfprom_cdata[5] = {0, 0, 0, 0, 0};
-
- qfprom_cdata[0] = readl_relaxed(tmdev->tsens_calib_addr + 0x1D8);
- qfprom_cdata[1] = readl_relaxed(tmdev->tsens_calib_addr + 0x1DC);
- qfprom_cdata[2] = readl_relaxed(tmdev->tsens_calib_addr + 0x210);
- qfprom_cdata[3] = readl_relaxed(tmdev->tsens_calib_addr + 0x214);
- qfprom_cdata[4] = readl_relaxed(tmdev->tsens_calib_addr + 0x230);
-
- mode = (qfprom_cdata[2] & CAL_SEL_MASK);
- pr_debug("calibration mode is %d\n", mode);
-
- switch (mode) {
- case TWO_PT_CALIB:
- base1 = (qfprom_cdata[1] & BASE1_MASK) >> BASE1_SHIFT;
- p2[0] = (qfprom_cdata[2] & S0_P2_MASK) >> S0_P2_SHIFT;
- p2[1] = (qfprom_cdata[2] & S1_P2_MASK) >> S1_P2_SHIFT;
- p2[2] = (qfprom_cdata[3] & S2_P2_MASK) >> S2_P2_SHIFT;
- p2[3] = (qfprom_cdata[3] & S3_P2_MASK) >> S3_P2_SHIFT;
- p2[4] = (qfprom_cdata[3] & S4_P2_MASK) >> S4_P2_SHIFT;
- p2[5] = (qfprom_cdata[0] & S5_P2_MASK) >> S5_P2_SHIFT;
- p2[6] = (qfprom_cdata[0] & S6_P2_MASK) >> S6_P2_SHIFT;
- p2[7] = (qfprom_cdata[1] & S7_P2_MASK) >> S7_P2_SHIFT;
- p2[8] = (qfprom_cdata[1] & S8_P2_MASK) >> S8_P2_SHIFT;
- p2[9] = (qfprom_cdata[4] & S9_P2_MASK) >> S9_P2_SHIFT;
- p2[10] = (qfprom_cdata[4] & S10_P2_MASK) >> S10_P2_SHIFT;
-
- for (i = 0; i < TSENS_1x_MAX_SENSORS; i++)
- p2[i] = ((base1 + p2[i]) << 2);
- /* Fall through */
- case ONE_PT_CALIB2:
- base0 = (qfprom_cdata[0] & BASE0_MASK);
- p1[0] = (qfprom_cdata[2] & S0_P1_MASK) >> S0_P1_SHIFT;
- p1[1] = (qfprom_cdata[2] & S1_P1_MASK) >> S1_P1_SHIFT;
- p1[2] = (qfprom_cdata[2] & S2_P1_MASK_0_4) >> S2_P1_SHIFT_0_4;
- tmp = (qfprom_cdata[3] & S2_P1_MASK_5) << S2_P1_SHIFT_5;
- p1[2] |= tmp;
- p1[3] = (qfprom_cdata[3] & S3_P1_MASK) >> S3_P1_SHIFT;
- p1[4] = (qfprom_cdata[3] & S4_P1_MASK) >> S4_P1_SHIFT;
- p1[5] = (qfprom_cdata[0] & S5_P1_MASK) >> S5_P1_SHIFT;
- p1[6] = (qfprom_cdata[0] & S6_P1_MASK) >> S6_P1_SHIFT;
- p1[7] = (qfprom_cdata[1] & S7_P1_MASK);
- p1[8] = (qfprom_cdata[1] & S8_P1_MASK) >> S8_P1_SHIFT;
- p1[9] = (qfprom_cdata[4] & S9_P1_MASK);
- p1[10] = (qfprom_cdata[4] & S10_P1_MASK) >> S10_P1_SHIFT;
-
- for (i = 0; i < TSENS_1x_MAX_SENSORS; i++)
- p1[i] = (((base0) + p1[i]) << 2);
- break;
- default:
- for (i = 0; i < TSENS_1x_MAX_SENSORS; i++) {
- p1[i] = 500;
- p2[i] = 780;
- }
- break;
- }
-
- compute_intercept_slope(tmdev, p1, p2, mode);
-
- return 0;
-}
-
static int tsens1xxx_get_temp(struct tsens_sensor *sensor, int *temp)
{
struct tsens_device *tmdev = NULL;
@@ -265,8 +104,21 @@
tmdev = sensor->tmdev;
- trdy_addr = TSENS_TRDY_ADDR(tmdev->tsens_tm_addr);
- sensor_addr = TSENS_SN_STATUS_ADDR(tmdev->tsens_tm_addr);
+ if ((tmdev->ctrl_data->ver_major == 1) &&
+ (tmdev->ctrl_data->ver_minor == 1)) {
+ trdy_addr = TSENS_S0_TRDY_ADDR(tmdev->tsens_tm_addr);
+ sensor_addr = TSENS_S0_STATUS_ADDR(tmdev->tsens_tm_addr);
+
+ if (!(tmdev->prev_reading_avail)) {
+ while (!((readl_relaxed(trdy_addr)) & TSENS_TRDY_MASK))
+ usleep_range(TSENS_TRDY_RDY_MIN_TIME,
+ TSENS_TRDY_RDY_MAX_TIME);
+ tmdev->prev_reading_avail = true;
+ }
+ } else {
+ trdy_addr = TSENS_TRDY_ADDR(tmdev->tsens_tm_addr);
+ sensor_addr = TSENS_SN_STATUS_ADDR(tmdev->tsens_tm_addr);
+ }
code = readl_relaxed(sensor_addr +
(sensor->hw_id << TSENS_STATUS_ADDR_OFFSET));
@@ -486,11 +338,17 @@
void __iomem *sensor_status_ctrl_addr;
u32 rc = 0, addr_offset;
- sensor_status_addr = TSENS_SN_STATUS_ADDR(tm->tsens_tm_addr);
+
+ if ((tm->ctrl_data->ver_major == 1) &&
+ (tm->ctrl_data->ver_minor == 1))
+ sensor_status_addr = TSENS_S0_STATUS_ADDR(tm->tsens_tm_addr);
+ else
+ sensor_status_addr = TSENS_SN_STATUS_ADDR(tm->tsens_tm_addr);
+
sensor_status_ctrl_addr =
TSENS_S0_UPPER_LOWER_STATUS_CTRL_ADDR(tm->tsens_tm_addr);
- for (i = 0; i < TSENS_1x_MAX_SENSORS; i++) {
+ for (i = 0; i < tm->ctrl_data->num_sensors; i++) {
bool upper_thr = false, lower_thr = false;
if (IS_ERR(tm->sensor[i].tzd))
@@ -581,7 +439,12 @@
void __iomem *srot_addr;
unsigned int srot_val, sensor_en;
- srot_addr = TSENS_CTRL_ADDR(tmdev->tsens_srot_addr + 0x4);
+ if ((tmdev->ctrl_data->ver_major == 1) &&
+ (tmdev->ctrl_data->ver_minor == 1))
+ srot_addr = TSENS_CTRL_ADDR(tmdev->tsens_srot_addr);
+ else
+ srot_addr = TSENS_CTRL_ADDR(tmdev->tsens_srot_addr + 0x4);
+
srot_val = readl_relaxed(srot_addr);
srot_val = TSENS_CTRL_SENSOR_EN_MASK(srot_val);
@@ -595,7 +458,12 @@
void __iomem *srot_addr;
unsigned int srot_val;
- srot_addr = TSENS_CTRL_ADDR(tmdev->tsens_srot_addr + 0x4);
+ if ((tmdev->ctrl_data->ver_major == 1) &&
+ (tmdev->ctrl_data->ver_minor == 1))
+ srot_addr = TSENS_CTRL_ADDR(tmdev->tsens_srot_addr);
+ else
+ srot_addr = TSENS_CTRL_ADDR(tmdev->tsens_srot_addr + 0x4);
+
srot_val = readl_relaxed(srot_addr);
if (!(srot_val & TSENS_EN)) {
pr_err("TSENS device is not enabled\n");
@@ -665,9 +533,27 @@
};
const struct tsens_data data_tsens14xx = {
+ .num_sensors = TSENS_NUM_SENSORS_8937,
.ops = &ops_tsens1xxx,
.valid_status_check = true,
.mtc = true,
.ver_major = 1,
.ver_minor = 4,
};
+
+static const struct tsens_ops ops_tsens1xxx_8909 = {
+ .hw_init = tsens1xxx_hw_init,
+ .get_temp = tsens1xxx_get_temp,
+ .set_trips = tsens1xxx_set_trip_temp,
+ .interrupts_reg = tsens1xxx_register_interrupts,
+ .sensor_en = tsens1xxx_hw_sensor_en,
+ .calibrate = calibrate_8909,
+ .dbg = tsens2xxx_dbg,
+};
+
+const struct tsens_data data_tsens1xxx_8909 = {
+ .num_sensors = TSENS_NUM_SENSORS_8909,
+ .ops = &ops_tsens1xxx_8909,
+ .ver_major = 1,
+ .ver_minor = 1,
+};
diff --git a/drivers/thermal/tsens_calib.c b/drivers/thermal/tsens_calib.c
new file mode 100644
index 0000000..04dd5c5
--- /dev/null
+++ b/drivers/thermal/tsens_calib.c
@@ -0,0 +1,285 @@
+/* Copyright (c) 2012-2018, The Linux Foundation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ */
+
+#include <linux/platform_device.h>
+#include "tsens.h"
+
+/* eeprom layout data for 8937 */
+#define BASE0_MASK_8937 0x000000ff
+#define BASE1_MASK_8937 0xff000000
+#define BASE1_SHIFT_8937 24
+
+#define S0_P1_MASK_8937 0x000001f8
+#define S1_P1_MASK_8937 0x001f8000
+#define S2_P1_MASK_0_4_8937 0xf8000000
+#define S2_P1_MASK_5_8937 0x00000001
+#define S3_P1_MASK_8937 0x00001f80
+#define S4_P1_MASK_8937 0x01f80000
+#define S5_P1_MASK_8937 0x00003f00
+#define S6_P1_MASK_8937 0x03f00000
+#define S7_P1_MASK_8937 0x0000003f
+#define S8_P1_MASK_8937 0x0003f000
+#define S9_P1_MASK_8937 0x0000003f
+#define S10_P1_MASK_8937 0x0003f000
+
+#define S0_P2_MASK_8937 0x00007e00
+#define S1_P2_MASK_8937 0x07e00000
+#define S2_P2_MASK_8937 0x0000007e
+#define S3_P2_MASK_8937 0x0007e000
+#define S4_P2_MASK_8937 0x7e000000
+#define S5_P2_MASK_8937 0x000fc000
+#define S6_P2_MASK_8937 0xfc000000
+#define S7_P2_MASK_8937 0x00000fc0
+#define S8_P2_MASK_8937 0x00fc0000
+#define S9_P2_MASK_8937 0x00000fc0
+#define S10_P2_MASK_8937 0x00fc0000
+
+#define S0_P1_SHIFT_8937 3
+#define S1_P1_SHIFT_8937 15
+#define S2_P1_SHIFT_0_4_8937 27
+#define S2_P1_SHIFT_5_8937 5
+#define S3_P1_SHIFT_8937 7
+#define S4_P1_SHIFT_8937 19
+#define S5_P1_SHIFT_8937 8
+#define S6_P1_SHIFT_8937 20
+#define S8_P1_SHIFT_8937 12
+#define S10_P1_SHIFT_8937 12
+
+#define S0_P2_SHIFT_8937 9
+#define S1_P2_SHIFT_8937 21
+#define S2_P2_SHIFT_8937 1
+#define S3_P2_SHIFT_8937 13
+#define S4_P2_SHIFT_8937 25
+#define S5_P2_SHIFT_8937 14
+#define S6_P2_SHIFT_8937 26
+#define S7_P2_SHIFT_8937 6
+#define S8_P2_SHIFT_8937 18
+#define S9_P2_SHIFT_8937 6
+#define S10_P2_SHIFT_8937 18
+
+#define CAL_SEL_MASK_8937 0x00000007
+
+/* eeprom layout for 8909 */
+#define TSENS_EEPROM(n) ((n) + 0xa0)
+#define BASE0_MASK_8909 0x000000ff
+#define BASE1_MASK_8909 0x0000ff00
+
+#define S0_P1_MASK_8909 0x0000003f
+#define S1_P1_MASK_8909 0x0003f000
+#define S2_P1_MASK_8909 0x3f000000
+#define S3_P1_MASK_8909 0x000003f0
+#define S4_P1_MASK_8909 0x003f0000
+
+#define S0_P2_MASK_8909 0x00000fc0
+#define S1_P2_MASK_8909 0x00fc0000
+#define S2_P2_MASK_0_1_8909 0xc0000000
+#define S2_P2_MASK_2_5_8909 0x0000000f
+#define S3_P2_MASK_8909 0x0000fc00
+#define S4_P2_MASK_8909 0x0fc00000
+
+#define TSENS_CAL_SEL_8909 0x00070000
+#define CAL_SEL_SHIFT_8909 16
+#define BASE1_SHIFT_8909 8
+
+#define S1_P1_SHIFT_8909 12
+#define S2_P1_SHIFT_8909 24
+#define S3_P1_SHIFT_8909 4
+#define S4_P1_SHIFT_8909 16
+
+#define S0_P2_SHIFT_8909 6
+#define S1_P2_SHIFT_8909 18
+#define S2_P2_SHIFT_0_1_8909 30
+#define S2_P2_SHIFT_2_5_8909 2
+#define S3_P2_SHIFT_8909 10
+#define S4_P2_SHIFT_8909 22
+
+#define CAL_DEGC_PT1 30
+#define CAL_DEGC_PT2 120
+/*
+ * Use this function on devices where slope and offset calculations
+ * depend on calibration data read from qfprom. On others the slope
+ * and offset values are derived from tz->tzp->slope and tz->tzp->offset
+ * resp.
+ */
+static void compute_intercept_slope(struct tsens_device *tmdev, u32 *p1,
+ u32 *p2, u32 mode)
+{
+ int i;
+ int num, den;
+
+ for (i = 0; i < tmdev->ctrl_data->num_sensors; i++) {
+ pr_debug(
+ "sensor%d - data_point1:%#x data_point2:%#x\n",
+ i, p1[i], p2[i]);
+
+ tmdev->sensor[i].slope = SLOPE_DEFAULT;
+ if (mode == TWO_PT_CALIB) {
+ /*
+ * slope (m) = adc_code2 - adc_code1 (y2 - y1)/
+ * temp_120_degc - temp_30_degc (x2 - x1)
+ */
+ num = p2[i] - p1[i];
+ num *= SLOPE_FACTOR;
+ den = CAL_DEGC_PT2 - CAL_DEGC_PT1;
+ tmdev->sensor[i].slope = num / den;
+ }
+
+ tmdev->sensor[i].offset = (p1[i] * SLOPE_FACTOR) -
+ (CAL_DEGC_PT1 *
+ tmdev->sensor[i].slope);
+ pr_debug("offset:%d\n", tmdev->sensor[i].offset);
+ }
+}
+
+int calibrate_8937(struct tsens_device *tmdev)
+{
+ int base0 = 0, base1 = 0, i;
+ u32 p1[TSENS_NUM_SENSORS_8937], p2[TSENS_NUM_SENSORS_8937];
+ int mode = 0, tmp = 0;
+ u32 qfprom_cdata[5] = {0, 0, 0, 0, 0};
+
+ qfprom_cdata[0] = readl_relaxed(tmdev->tsens_calib_addr + 0x1D8);
+ qfprom_cdata[1] = readl_relaxed(tmdev->tsens_calib_addr + 0x1DC);
+ qfprom_cdata[2] = readl_relaxed(tmdev->tsens_calib_addr + 0x210);
+ qfprom_cdata[3] = readl_relaxed(tmdev->tsens_calib_addr + 0x214);
+ qfprom_cdata[4] = readl_relaxed(tmdev->tsens_calib_addr + 0x230);
+
+ mode = (qfprom_cdata[2] & CAL_SEL_MASK_8937);
+ pr_debug("calibration mode is %d\n", mode);
+
+ switch (mode) {
+ case TWO_PT_CALIB:
+ base1 = (qfprom_cdata[1] &
+ BASE1_MASK_8937) >> BASE1_SHIFT_8937;
+ p2[0] = (qfprom_cdata[2] &
+ S0_P2_MASK_8937) >> S0_P2_SHIFT_8937;
+ p2[1] = (qfprom_cdata[2] &
+ S1_P2_MASK_8937) >> S1_P2_SHIFT_8937;
+ p2[2] = (qfprom_cdata[3] &
+ S2_P2_MASK_8937) >> S2_P2_SHIFT_8937;
+ p2[3] = (qfprom_cdata[3] &
+ S3_P2_MASK_8937) >> S3_P2_SHIFT_8937;
+ p2[4] = (qfprom_cdata[3] &
+ S4_P2_MASK_8937) >> S4_P2_SHIFT_8937;
+ p2[5] = (qfprom_cdata[0] &
+ S5_P2_MASK_8937) >> S5_P2_SHIFT_8937;
+ p2[6] = (qfprom_cdata[0] &
+ S6_P2_MASK_8937) >> S6_P2_SHIFT_8937;
+ p2[7] = (qfprom_cdata[1] &
+ S7_P2_MASK_8937) >> S7_P2_SHIFT_8937;
+ p2[8] = (qfprom_cdata[1] &
+ S8_P2_MASK_8937) >> S8_P2_SHIFT_8937;
+ p2[9] = (qfprom_cdata[4] &
+ S9_P2_MASK_8937) >> S9_P2_SHIFT_8937;
+ p2[10] = (qfprom_cdata[4] &
+ S10_P2_MASK_8937) >> S10_P2_SHIFT_8937;
+
+ for (i = 0; i < TSENS_NUM_SENSORS_8937; i++)
+ p2[i] = ((base1 + p2[i]) << 2);
+ /* Fall through */
+ case ONE_PT_CALIB2:
+ base0 = (qfprom_cdata[0] & BASE0_MASK_8937);
+ p1[0] = (qfprom_cdata[2] &
+ S0_P1_MASK_8937) >> S0_P1_SHIFT_8937;
+ p1[1] = (qfprom_cdata[2] &
+ S1_P1_MASK_8937) >> S1_P1_SHIFT_8937;
+ p1[2] = (qfprom_cdata[2] &
+ S2_P1_MASK_0_4_8937) >> S2_P1_SHIFT_0_4_8937;
+ tmp = (qfprom_cdata[3] &
+ S2_P1_MASK_5_8937) << S2_P1_SHIFT_5_8937;
+ p1[2] |= tmp;
+ p1[3] = (qfprom_cdata[3] &
+ S3_P1_MASK_8937) >> S3_P1_SHIFT_8937;
+ p1[4] = (qfprom_cdata[3] &
+ S4_P1_MASK_8937) >> S4_P1_SHIFT_8937;
+ p1[5] = (qfprom_cdata[0] &
+ S5_P1_MASK_8937) >> S5_P1_SHIFT_8937;
+ p1[6] = (qfprom_cdata[0] &
+ S6_P1_MASK_8937) >> S6_P1_SHIFT_8937;
+ p1[7] = (qfprom_cdata[1] & S7_P1_MASK_8937);
+ p1[8] = (qfprom_cdata[1] &
+ S8_P1_MASK_8937) >> S8_P1_SHIFT_8937;
+ p1[9] = (qfprom_cdata[4] & S9_P1_MASK_8937);
+ p1[10] = (qfprom_cdata[4] &
+ S10_P1_MASK_8937) >> S10_P1_SHIFT_8937;
+
+ for (i = 0; i < TSENS_NUM_SENSORS_8937; i++)
+ p1[i] = (((base0) + p1[i]) << 2);
+ break;
+ default:
+ for (i = 0; i < TSENS_NUM_SENSORS_8937; i++) {
+ p1[i] = 500;
+ p2[i] = 780;
+ }
+ break;
+ }
+
+ compute_intercept_slope(tmdev, p1, p2, mode);
+
+ return 0;
+}
+
+int calibrate_8909(struct tsens_device *tmdev)
+{
+ int i, base0 = 0, base1 = 0;
+ u32 p1[TSENS_NUM_SENSORS_8909], p2[TSENS_NUM_SENSORS_8909];
+ int mode = 0, temp = 0;
+ uint32_t calib_data[3] = {0, 0, 0};
+
+ calib_data[0] = readl_relaxed(
+ TSENS_EEPROM(tmdev->tsens_calib_addr));
+ calib_data[1] = readl_relaxed(
+ (TSENS_EEPROM(tmdev->tsens_calib_addr) + 0x4));
+ calib_data[2] = readl_relaxed(
+ (TSENS_EEPROM(tmdev->tsens_calib_addr) + 0x3c));
+ mode = (calib_data[2] & TSENS_CAL_SEL_8909) >> CAL_SEL_SHIFT_8909;
+
+ pr_debug("calib mode is %d\n", mode);
+
+ switch (mode) {
+ case TWO_PT_CALIB:
+ base1 = (calib_data[2] & BASE1_MASK_8909) >> BASE1_SHIFT_8909;
+ p2[0] = (calib_data[0] & S0_P2_MASK_8909) >> S0_P2_SHIFT_8909;
+ p2[1] = (calib_data[0] & S1_P2_MASK_8909) >> S1_P2_SHIFT_8909;
+ p2[2] = (calib_data[0] &
+ S2_P2_MASK_0_1_8909) >> S2_P2_SHIFT_0_1_8909;
+ temp = (calib_data[1] &
+ S2_P2_MASK_2_5_8909) << S2_P2_SHIFT_2_5_8909;
+ p2[2] |= temp;
+ p2[3] = (calib_data[1] & S3_P2_MASK_8909) >> S3_P2_SHIFT_8909;
+ p2[4] = (calib_data[1] & S4_P2_MASK_8909) >> S4_P2_SHIFT_8909;
+
+ for (i = 0; i < TSENS_NUM_SENSORS_8909; i++)
+ p2[i] = ((base1 + p2[i]) << 2);
+ /* Fall through */
+ case ONE_PT_CALIB2:
+ base0 = (calib_data[2] & BASE0_MASK_8909);
+ p1[0] = (calib_data[0] & S0_P1_MASK_8909);
+ p1[1] = (calib_data[0] & S1_P1_MASK_8909) >> S1_P1_SHIFT_8909;
+ p1[2] = (calib_data[0] & S2_P1_MASK_8909) >> S2_P1_SHIFT_8909;
+ p1[3] = (calib_data[1] & S3_P1_MASK_8909) >> S3_P1_SHIFT_8909;
+ p1[4] = (calib_data[1] & S4_P1_MASK_8909) >> S4_P1_SHIFT_8909;
+ for (i = 0; i < TSENS_NUM_SENSORS_8909; i++)
+ p1[i] = (((base0) + p1[i]) << 2);
+ break;
+ default:
+ for (i = 0; i < TSENS_NUM_SENSORS_8909; i++) {
+ p1[i] = 500;
+ p2[i] = 780;
+ }
+ break;
+ }
+
+ compute_intercept_slope(tmdev, p1, p2, mode);
+ return 0;
+}
diff --git a/drivers/tty/serial/8250/8250_port.c b/drivers/tty/serial/8250/8250_port.c
index f6e4373..5d9038a 100644
--- a/drivers/tty/serial/8250/8250_port.c
+++ b/drivers/tty/serial/8250/8250_port.c
@@ -1815,7 +1815,8 @@
status = serial_port_in(port, UART_LSR);
- if (status & (UART_LSR_DR | UART_LSR_BI)) {
+ if (status & (UART_LSR_DR | UART_LSR_BI) &&
+ iir & UART_IIR_RDI) {
if (!up->dma || handle_rx_dma(up, iir))
status = serial8250_rx_chars(up, status);
}
diff --git a/drivers/tty/serial/arc_uart.c b/drivers/tty/serial/arc_uart.c
index 5ac06fc..fec48de 100644
--- a/drivers/tty/serial/arc_uart.c
+++ b/drivers/tty/serial/arc_uart.c
@@ -596,6 +596,11 @@
if (dev_id < 0)
dev_id = 0;
+ if (dev_id >= ARRAY_SIZE(arc_uart_ports)) {
+ dev_err(&pdev->dev, "serial%d out of range\n", dev_id);
+ return -EINVAL;
+ }
+
uart = &arc_uart_ports[dev_id];
port = &uart->port;
diff --git a/drivers/tty/serial/fsl_lpuart.c b/drivers/tty/serial/fsl_lpuart.c
index 76103f2..937f5e1 100644
--- a/drivers/tty/serial/fsl_lpuart.c
+++ b/drivers/tty/serial/fsl_lpuart.c
@@ -1902,6 +1902,10 @@
dev_err(&pdev->dev, "failed to get alias id, errno %d\n", ret);
return ret;
}
+ if (ret >= ARRAY_SIZE(lpuart_ports)) {
+ dev_err(&pdev->dev, "serial%d out of range\n", ret);
+ return -EINVAL;
+ }
sport->port.line = ret;
sport->lpuart32 = of_device_is_compatible(np, "fsl,ls1021a-lpuart");
diff --git a/drivers/tty/serial/imx.c b/drivers/tty/serial/imx.c
index ecadc27..b24edf6 100644
--- a/drivers/tty/serial/imx.c
+++ b/drivers/tty/serial/imx.c
@@ -2080,6 +2080,12 @@
else if (ret < 0)
return ret;
+ if (sport->port.line >= ARRAY_SIZE(imx_ports)) {
+ dev_err(&pdev->dev, "serial%d out of range\n",
+ sport->port.line);
+ return -EINVAL;
+ }
+
res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
base = devm_ioremap_resource(&pdev->dev, res);
if (IS_ERR(base))
diff --git a/drivers/tty/serial/mxs-auart.c b/drivers/tty/serial/mxs-auart.c
index 07390f8..1d9d778 100644
--- a/drivers/tty/serial/mxs-auart.c
+++ b/drivers/tty/serial/mxs-auart.c
@@ -1664,6 +1664,10 @@
s->port.line = pdev->id < 0 ? 0 : pdev->id;
else if (ret < 0)
return ret;
+ if (s->port.line >= ARRAY_SIZE(auart_port)) {
+ dev_err(&pdev->dev, "serial%d out of range\n", s->port.line);
+ return -EINVAL;
+ }
if (of_id) {
pdev->id_entry = of_id->data;
diff --git a/drivers/tty/serial/samsung.c b/drivers/tty/serial/samsung.c
index d65f92b..f2ab6d8a 100644
--- a/drivers/tty/serial/samsung.c
+++ b/drivers/tty/serial/samsung.c
@@ -1813,6 +1813,10 @@
dbg("s3c24xx_serial_probe(%p) %d\n", pdev, index);
+ if (index >= ARRAY_SIZE(s3c24xx_serial_ports)) {
+ dev_err(&pdev->dev, "serial%d out of range\n", index);
+ return -EINVAL;
+ }
ourport = &s3c24xx_serial_ports[index];
ourport->drv_data = s3c24xx_get_driver_data(pdev);
diff --git a/drivers/tty/serial/xilinx_uartps.c b/drivers/tty/serial/xilinx_uartps.c
index dd4c02f..7497f1d 100644
--- a/drivers/tty/serial/xilinx_uartps.c
+++ b/drivers/tty/serial/xilinx_uartps.c
@@ -1106,7 +1106,7 @@
struct uart_port *port;
/* Try the given port id if failed use default method */
- if (cdns_uart_port[id].mapbase != 0) {
+ if (id < CDNS_UART_NR_PORTS && cdns_uart_port[id].mapbase != 0) {
/* Find the next unused port */
for (id = 0; id < CDNS_UART_NR_PORTS; id++)
if (cdns_uart_port[id].mapbase == 0)
diff --git a/drivers/usb/class/cdc-acm.c b/drivers/usb/class/cdc-acm.c
index 34d23cc..fe22ac7 100644
--- a/drivers/usb/class/cdc-acm.c
+++ b/drivers/usb/class/cdc-acm.c
@@ -174,6 +174,7 @@
wb = &acm->wb[wbn];
if (!wb->use) {
wb->use = 1;
+ wb->len = 0;
return wbn;
}
wbn = (wbn + 1) % ACM_NW;
@@ -731,16 +732,18 @@
static void acm_tty_flush_chars(struct tty_struct *tty)
{
struct acm *acm = tty->driver_data;
- struct acm_wb *cur = acm->putbuffer;
+ struct acm_wb *cur;
int err;
unsigned long flags;
+ spin_lock_irqsave(&acm->write_lock, flags);
+
+ cur = acm->putbuffer;
if (!cur) /* nothing to do */
- return;
+ goto out;
acm->putbuffer = NULL;
err = usb_autopm_get_interface_async(acm->control);
- spin_lock_irqsave(&acm->write_lock, flags);
if (err < 0) {
cur->use = 0;
acm->putbuffer = cur;
diff --git a/drivers/usb/dwc2/core.h b/drivers/usb/dwc2/core.h
index 2a21a04..0f45a2f 100644
--- a/drivers/usb/dwc2/core.h
+++ b/drivers/usb/dwc2/core.h
@@ -209,7 +209,7 @@
unsigned char dir_in;
unsigned char index;
unsigned char mc;
- unsigned char interval;
+ u16 interval;
unsigned int halted:1;
unsigned int periodic:1;
diff --git a/drivers/usb/dwc2/gadget.c b/drivers/usb/dwc2/gadget.c
index cfdd5c3..09921ef 100644
--- a/drivers/usb/dwc2/gadget.c
+++ b/drivers/usb/dwc2/gadget.c
@@ -2642,12 +2642,6 @@
dwc2_writel(dwc2_hsotg_ep0_mps(hsotg->eps_out[0]->ep.maxpacket) |
DXEPCTL_USBACTEP, hsotg->regs + DIEPCTL0);
- dwc2_hsotg_enqueue_setup(hsotg);
-
- dev_dbg(hsotg->dev, "EP0: DIEPCTL0=0x%08x, DOEPCTL0=0x%08x\n",
- dwc2_readl(hsotg->regs + DIEPCTL0),
- dwc2_readl(hsotg->regs + DOEPCTL0));
-
/* clear global NAKs */
val = DCTL_CGOUTNAK | DCTL_CGNPINNAK;
if (!is_usb_reset)
@@ -2658,6 +2652,12 @@
mdelay(3);
hsotg->lx_state = DWC2_L0;
+
+ dwc2_hsotg_enqueue_setup(hsotg);
+
+ dev_dbg(hsotg->dev, "EP0: DIEPCTL0=0x%08x, DOEPCTL0=0x%08x\n",
+ dwc2_readl(hsotg->regs + DIEPCTL0),
+ dwc2_readl(hsotg->regs + DOEPCTL0));
}
static void dwc2_hsotg_core_disconnect(struct dwc2_hsotg *hsotg)
diff --git a/drivers/usb/dwc2/hcd.c b/drivers/usb/dwc2/hcd.c
index 919a321..0a0cf15 100644
--- a/drivers/usb/dwc2/hcd.c
+++ b/drivers/usb/dwc2/hcd.c
@@ -2268,10 +2268,22 @@
*/
static void dwc2_core_host_init(struct dwc2_hsotg *hsotg)
{
- u32 hcfg, hfir, otgctl;
+ u32 hcfg, hfir, otgctl, usbcfg;
dev_dbg(hsotg->dev, "%s(%p)\n", __func__, hsotg);
+ /* Set HS/FS Timeout Calibration to 7 (max available value).
+ * The number of PHY clocks that the application programs in
+ * this field is added to the high/full speed interpacket timeout
+ * duration in the core to account for any additional delays
+ * introduced by the PHY. This can be required, because the delay
+ * introduced by the PHY in generating the linestate condition
+ * can vary from one PHY to another.
+ */
+ usbcfg = dwc2_readl(hsotg->regs + GUSBCFG);
+ usbcfg |= GUSBCFG_TOUTCAL(7);
+ dwc2_writel(usbcfg, hsotg->regs + GUSBCFG);
+
/* Restart the Phy Clock */
dwc2_writel(0, hsotg->regs + PCGCTL);
diff --git a/drivers/usb/dwc3/core.c b/drivers/usb/dwc3/core.c
index 248dd9a..93d8e14 100644
--- a/drivers/usb/dwc3/core.c
+++ b/drivers/usb/dwc3/core.c
@@ -910,6 +910,21 @@
}
/*
+ * Workaround for STAR 9001285599 which affects dwc3 core version 3.20a
+ * only. If the PM TIMER ECN is enabled thru GUCTL2[19], then link
+ * compliance test (TD7.21) may fail. If the ECN is not enabled
+ * GUCTL2[19] = 0), the controller will use the old timer value (5us),
+ * which is still fine for Link Compliance test. Hence Do not enable
+ * PM TIMER ECN in V3.20a by setting GUCTL2[19] by default,
+ * instead use GUCTL2[19] = 0.
+ */
+ if (dwc->revision == DWC3_REVISION_320A) {
+ reg = dwc3_readl(dwc->regs, DWC3_GUCTL2);
+ reg &= ~DWC3_GUCTL2_LC_TIMER;
+ dwc3_writel(dwc->regs, DWC3_GUCTL2, reg);
+ }
+
+ /*
* Enable hardware control of sending remote wakeup in HS when
* the device is in the L1 state.
*/
diff --git a/drivers/usb/dwc3/core.h b/drivers/usb/dwc3/core.h
index e5fe7a4..0963aa3 100644
--- a/drivers/usb/dwc3/core.h
+++ b/drivers/usb/dwc3/core.h
@@ -269,6 +269,8 @@
#define DWC3_GUSB3PIPECTL_ELASTIC_BUF_MODE (1 << 0)
/* Global TX Fifo Size Register */
+#define DWC31_GTXFIFOSIZ_TXFRAMNUM BIT(15) /* DWC_usb31 only */
+#define DWC31_GTXFIFOSIZ_TXFDEF(n) ((n) & 0x7fff) /* DWC_usb31 only */
#define DWC3_GTXFIFOSIZ_TXFDEF(n) ((n) & 0xffff)
#define DWC3_GTXFIFOSIZ_TXFSTADDR(n) ((n) & 0xffff0000)
@@ -333,6 +335,7 @@
#define DWC3_GUCTL2_RST_ACTBITLATER (1 << 14)
#define DWC3_GUCTL2_HP_TIMER(n) ((n) << 21)
#define DWC3_GUCTL2_HP_TIMER_MASK DWC3_GUCTL2_HP_TIMER(0x1f)
+#define DWC3_GUCTL2_LC_TIMER (1 << 19)
/* Device Configuration Register */
#define DWC3_DCFG_DEVADDR(addr) ((addr) << 3)
diff --git a/drivers/usb/dwc3/dwc3-omap.c b/drivers/usb/dwc3/dwc3-omap.c
index 35b6351..f221cb4 100644
--- a/drivers/usb/dwc3/dwc3-omap.c
+++ b/drivers/usb/dwc3/dwc3-omap.c
@@ -598,9 +598,25 @@
return 0;
}
+static void dwc3_omap_complete(struct device *dev)
+{
+ struct dwc3_omap *omap = dev_get_drvdata(dev);
+
+ if (extcon_get_state(omap->edev, EXTCON_USB))
+ dwc3_omap_set_mailbox(omap, OMAP_DWC3_VBUS_VALID);
+ else
+ dwc3_omap_set_mailbox(omap, OMAP_DWC3_VBUS_OFF);
+
+ if (extcon_get_state(omap->edev, EXTCON_USB_HOST))
+ dwc3_omap_set_mailbox(omap, OMAP_DWC3_ID_GROUND);
+ else
+ dwc3_omap_set_mailbox(omap, OMAP_DWC3_ID_FLOAT);
+}
+
static const struct dev_pm_ops dwc3_omap_dev_pm_ops = {
SET_SYSTEM_SLEEP_PM_OPS(dwc3_omap_suspend, dwc3_omap_resume)
+ .complete = dwc3_omap_complete,
};
#define DEV_PM_OPS (&dwc3_omap_dev_pm_ops)
diff --git a/drivers/usb/dwc3/ep0.c b/drivers/usb/dwc3/ep0.c
index 902d36e..d9baac6 100644
--- a/drivers/usb/dwc3/ep0.c
+++ b/drivers/usb/dwc3/ep0.c
@@ -43,6 +43,8 @@
static void __dwc3_ep0_do_control_status(struct dwc3 *dwc, struct dwc3_ep *dep);
static void __dwc3_ep0_do_control_data(struct dwc3 *dwc,
struct dwc3_ep *dep, struct dwc3_request *req);
+static int dwc3_ep0_delegate_req(struct dwc3 *dwc,
+ struct usb_ctrlrequest *ctrl);
static const char *dwc3_ep0_state_string(enum dwc3_ep0_state state)
{
@@ -358,12 +360,14 @@
static void dwc3_ep0_status_cmpl(struct usb_ep *ep, struct usb_request *req)
{
}
+
/*
* ch 9.4.5
*/
static int dwc3_ep0_handle_status(struct dwc3 *dwc,
struct usb_ctrlrequest *ctrl)
{
+ int ret;
struct dwc3_ep *dep;
u32 recip;
u32 reg;
@@ -397,7 +401,8 @@
* Function Remote Wake Capable D0
* Function Remote Wakeup D1
*/
- break;
+ ret = dwc3_ep0_delegate_req(dwc, ctrl);
+ return ret;
case USB_RECIP_ENDPOINT:
dep = dwc3_wIndex_to_dep(dwc, ctrl->wIndex);
@@ -524,6 +529,9 @@
if (wIndex & USB_INTRF_FUNC_SUSPEND_RW)
/* XXX enable remote wakeup */
;
+ ret = dwc3_ep0_delegate_req(dwc, ctrl);
+ if (ret)
+ return ret;
break;
default:
return -EINVAL;
diff --git a/drivers/usb/gadget/composite.c b/drivers/usb/gadget/composite.c
index ab2c623..3de95d5 100644
--- a/drivers/usb/gadget/composite.c
+++ b/drivers/usb/gadget/composite.c
@@ -1563,7 +1563,7 @@
return res;
}
-static void fill_ext_compat(struct usb_configuration *c, u8 *buf)
+static int fill_ext_compat(struct usb_configuration *c, u8 *buf)
{
int i, count;
@@ -1590,10 +1590,12 @@
buf += 23;
}
count += 24;
- if (count >= 4096)
- return;
+ if (count + 24 >= USB_COMP_EP0_OS_DESC_BUFSIZ)
+ return count;
}
}
+
+ return count;
}
static int count_ext_prop(struct usb_configuration *c, int interface)
@@ -1638,25 +1640,20 @@
struct usb_os_desc *d;
struct usb_os_desc_ext_prop *ext_prop;
int j, count, n, ret;
- u8 *start = buf;
f = c->interface[interface];
+ count = 10; /* header length */
for (j = 0; j < f->os_desc_n; ++j) {
if (interface != f->os_desc_table[j].if_id)
continue;
d = f->os_desc_table[j].os_desc;
if (d)
list_for_each_entry(ext_prop, &d->ext_prop, entry) {
- /* 4kB minus header length */
- n = buf - start;
- if (n >= 4086)
- return 0;
-
- count = ext_prop->data_len +
+ n = ext_prop->data_len +
ext_prop->name_len + 14;
- if (count > 4086 - n)
- return -EINVAL;
- usb_ext_prop_put_size(buf, count);
+ if (count + n >= USB_COMP_EP0_OS_DESC_BUFSIZ)
+ return count;
+ usb_ext_prop_put_size(buf, n);
usb_ext_prop_put_type(buf, ext_prop->type);
ret = usb_ext_prop_put_name(buf, ext_prop->name,
ext_prop->name_len);
@@ -1682,11 +1679,12 @@
default:
return -EINVAL;
}
- buf += count;
+ buf += n;
+ count += n;
}
}
- return 0;
+ return count;
}
/*
@@ -1980,6 +1978,7 @@
req->complete = composite_setup_complete;
buf = req->buf;
os_desc_cfg = cdev->os_desc_config;
+ w_length = min_t(u16, w_length, USB_COMP_EP0_OS_DESC_BUFSIZ);
memset(buf, 0, w_length);
buf[5] = 0x01;
switch (ctrl->bRequestType & USB_RECIP_MASK) {
@@ -2003,8 +2002,8 @@
count += 16; /* header */
put_unaligned_le32(count, buf);
buf += 16;
- fill_ext_compat(os_desc_cfg, buf);
- value = w_length;
+ value = fill_ext_compat(os_desc_cfg, buf);
+ value = min_t(u16, w_length, value);
}
break;
case USB_RECIP_INTERFACE:
@@ -2033,8 +2032,7 @@
interface, buf);
if (value < 0)
return value;
-
- value = w_length;
+ value = min_t(u16, w_length, value);
}
break;
}
@@ -2336,8 +2334,8 @@
goto end;
}
- /* OS feature descriptor length <= 4kB */
- cdev->os_desc_req->buf = kmalloc(4096, GFP_KERNEL);
+ cdev->os_desc_req->buf = kmalloc(USB_COMP_EP0_OS_DESC_BUFSIZ,
+ GFP_KERNEL);
if (!cdev->os_desc_req->buf) {
ret = -ENOMEM;
usb_ep_free_request(ep0, cdev->os_desc_req);
diff --git a/drivers/usb/gadget/configfs.c b/drivers/usb/gadget/configfs.c
index f779fdc30..14c18f3 100644
--- a/drivers/usb/gadget/configfs.c
+++ b/drivers/usb/gadget/configfs.c
@@ -1257,9 +1257,9 @@
cfg = container_of(c, struct config_usb_cfg, c);
- list_for_each_entry_safe(f, tmp, &c->functions, list) {
+ list_for_each_entry_safe_reverse(f, tmp, &c->functions, list) {
- list_move_tail(&f->list, &cfg->func_list);
+ list_move(&f->list, &cfg->func_list);
if (f->unbind) {
dev_dbg(&gi->cdev.gadget->dev,
"unbind function '%s'/%pK\n",
diff --git a/drivers/usb/gadget/function/f_fs.c b/drivers/usb/gadget/function/f_fs.c
index 9974332..b9c19d4 100644
--- a/drivers/usb/gadget/function/f_fs.c
+++ b/drivers/usb/gadget/function/f_fs.c
@@ -3734,7 +3734,7 @@
ffs_log("exit");
- return 0;
+ return USB_GADGET_DELAYED_STATUS;
}
static bool ffs_func_req_match(struct usb_function *f,
diff --git a/drivers/usb/gadget/function/f_gsi.c b/drivers/usb/gadget/function/f_gsi.c
index 55c8648..7170dc9 100644
--- a/drivers/usb/gadget/function/f_gsi.c
+++ b/drivers/usb/gadget/function/f_gsi.c
@@ -922,6 +922,11 @@
log_event_dbg("%s: ST_CON_IN_PROG_EVT_HOST_READY",
__func__);
} else if (event == EVT_CONNECTED) {
+ if (peek_event(d_port) == EVT_SUSPEND) {
+ log_event_dbg("%s: ST_CON_IN_PROG_EVT_SUSPEND",
+ __func__);
+ break;
+ }
ipa_data_path_enable(d_port);
d_port->sm_state = STATE_CONNECTED;
log_event_dbg("%s: ST_CON_IN_PROG_EVT_CON %d",
@@ -2475,8 +2480,12 @@
bool block_db;
struct f_gsi *gsi = func_to_gsi(f);
- /* Check if function is already suspended in gsi_func_suspend() */
- if (f->func_is_suspended) {
+ /* Check if function is already suspended in gsi_func_suspend()
+ * Or func_suspend would have bailed out earlier if func_remote_wakeup
+ * wasn't enabled.
+ */
+ if (f->func_is_suspended && (gsi->d_port.sm_state == STATE_SUSPENDED ||
+ gsi->d_port.sm_state == STATE_SUSPEND_IN_PROGRESS)) {
log_event_dbg("%s: func already suspended, return\n", __func__);
return;
}
@@ -2541,6 +2550,14 @@
log_event_dbg("%s: completed", __func__);
}
+static int gsi_get_status(struct usb_function *f)
+{
+ unsigned int remote_wakeup_en_status = f->func_wakeup_allowed ? 1 : 0;
+
+ return (remote_wakeup_en_status << FUNC_WAKEUP_ENABLE_SHIFT) |
+ (1 << FUNC_WAKEUP_CAPABLE_SHIFT);
+}
+
static int gsi_func_suspend(struct usb_function *f, u8 options)
{
bool func_wakeup_allowed;
@@ -3308,6 +3325,7 @@
gsi->function.disable = gsi_disable;
gsi->function.free_func = gsi_free_func;
gsi->function.suspend = gsi_suspend;
+ gsi->function.get_status = gsi_get_status;
gsi->function.func_suspend = gsi_func_suspend;
gsi->function.resume = gsi_resume;
diff --git a/drivers/usb/gadget/function/f_mtp.c b/drivers/usb/gadget/function/f_mtp.c
index 3f25946..79ef286 100644
--- a/drivers/usb/gadget/function/f_mtp.c
+++ b/drivers/usb/gadget/function/f_mtp.c
@@ -137,6 +137,9 @@
} perf[MAX_ITERATION];
unsigned int dbg_read_index;
unsigned int dbg_write_index;
+ unsigned int mtp_rx_req_len;
+ unsigned int mtp_tx_req_len;
+ unsigned int mtp_tx_reqs;
struct mutex read_mutex;
};
@@ -531,16 +534,16 @@
retry_tx_alloc:
/* now allocate requests for our endpoints */
- for (i = 0; i < mtp_tx_reqs; i++) {
+ for (i = 0; i < dev->mtp_tx_reqs; i++) {
req = mtp_request_new(dev->ep_in,
- mtp_tx_req_len + extra_buf_alloc);
+ dev->mtp_tx_req_len + extra_buf_alloc);
if (!req) {
- if (mtp_tx_req_len <= MTP_BULK_BUFFER_SIZE)
+ if (dev->mtp_tx_req_len <= MTP_BULK_BUFFER_SIZE)
goto fail;
while ((req = mtp_req_get(dev, &dev->tx_idle)))
mtp_request_free(req, dev->ep_in);
- mtp_tx_req_len = MTP_BULK_BUFFER_SIZE;
- mtp_tx_reqs = MTP_TX_REQ_MAX;
+ dev->mtp_tx_req_len = MTP_BULK_BUFFER_SIZE;
+ dev->mtp_tx_reqs = MTP_TX_REQ_MAX;
goto retry_tx_alloc;
}
req->complete = mtp_complete_in;
@@ -553,18 +556,18 @@
* operational speed. Hence assuming super speed max
* packet size.
*/
- if (mtp_rx_req_len % 1024)
- mtp_rx_req_len = MTP_BULK_BUFFER_SIZE;
+ if (dev->mtp_rx_req_len % 1024)
+ dev->mtp_rx_req_len = MTP_BULK_BUFFER_SIZE;
retry_rx_alloc:
for (i = 0; i < RX_REQ_MAX; i++) {
- req = mtp_request_new(dev->ep_out, mtp_rx_req_len);
+ req = mtp_request_new(dev->ep_out, dev->mtp_rx_req_len);
if (!req) {
- if (mtp_rx_req_len <= MTP_BULK_BUFFER_SIZE)
+ if (dev->mtp_rx_req_len <= MTP_BULK_BUFFER_SIZE)
goto fail;
for (--i; i >= 0; i--)
mtp_request_free(dev->rx_req[i], dev->ep_out);
- mtp_rx_req_len = MTP_BULK_BUFFER_SIZE;
+ dev->mtp_rx_req_len = MTP_BULK_BUFFER_SIZE;
goto retry_rx_alloc;
}
req->complete = mtp_complete_out;
@@ -609,7 +612,7 @@
}
len = ALIGN(count, dev->ep_out->maxpacket);
- if (len > mtp_rx_req_len)
+ if (len > dev->mtp_rx_req_len)
return -EINVAL;
spin_lock_irq(&dev->lock);
@@ -760,8 +763,8 @@
break;
}
- if (count > mtp_tx_req_len)
- xfer = mtp_tx_req_len;
+ if (count > dev->mtp_tx_req_len)
+ xfer = dev->mtp_tx_req_len;
else
xfer = count;
if (xfer && copy_from_user(req->buf, buf, xfer)) {
@@ -857,8 +860,8 @@
break;
}
- if (count > mtp_tx_req_len)
- xfer = mtp_tx_req_len;
+ if (count > dev->mtp_tx_req_len)
+ xfer = dev->mtp_tx_req_len;
else
xfer = count;
@@ -954,7 +957,7 @@
cur_buf = (cur_buf + 1) % RX_REQ_MAX;
/* some h/w expects size to be aligned to ep's MTU */
- read_req->length = mtp_rx_req_len;
+ read_req->length = dev->mtp_rx_req_len;
dev->rx_done = 0;
mutex_unlock(&dev->read_mutex);
@@ -1431,6 +1434,9 @@
mtp_tx_req_len = 16384;
}
+ dev->mtp_rx_req_len = mtp_rx_req_len;
+ dev->mtp_tx_req_len = mtp_tx_req_len;
+ dev->mtp_tx_reqs = mtp_tx_reqs;
/* allocate interface ID(s) */
id = usb_interface_id(c, f);
if (id < 0)
@@ -1596,7 +1602,7 @@
seq_printf(s, "vfs write: bytes:%ld\t\t time:%d\n",
dev->perf[i].vfs_wbytes,
dev->perf[i].vfs_wtime);
- if (dev->perf[i].vfs_wbytes == mtp_rx_req_len) {
+ if (dev->perf[i].vfs_wbytes == dev->mtp_rx_req_len) {
sum += dev->perf[i].vfs_wtime;
if (min > dev->perf[i].vfs_wtime)
min = dev->perf[i].vfs_wtime;
@@ -1618,7 +1624,7 @@
seq_printf(s, "vfs read: bytes:%ld\t\t time:%d\n",
dev->perf[i].vfs_rbytes,
dev->perf[i].vfs_rtime);
- if (dev->perf[i].vfs_rbytes == mtp_tx_req_len) {
+ if (dev->perf[i].vfs_rbytes == dev->mtp_tx_req_len) {
sum += dev->perf[i].vfs_rtime;
if (min > dev->perf[i].vfs_rtime)
min = dev->perf[i].vfs_rtime;
diff --git a/drivers/usb/gadget/function/f_rndis.c b/drivers/usb/gadget/function/f_rndis.c
index a75e5d3..24bc2d4 100644
--- a/drivers/usb/gadget/function/f_rndis.c
+++ b/drivers/usb/gadget/function/f_rndis.c
@@ -386,10 +386,31 @@
struct sk_buff *skb)
{
struct sk_buff *skb2;
+ struct rndis_packet_msg_type *header = NULL;
+ struct f_rndis *rndis = func_to_rndis(&port->func);
if (!skb)
return NULL;
+ if (rndis->port.multi_pkt_xfer) {
+ if (port->header) {
+ header = port->header;
+ header->MessageType = cpu_to_le32(RNDIS_MSG_PACKET);
+ header->MessageLength = cpu_to_le32(skb->len +
+ sizeof(*header));
+ header->DataOffset = cpu_to_le32(36);
+ header->DataLength = cpu_to_le32(skb->len);
+ pr_debug("MessageLength:%d DataLength:%d\n",
+ header->MessageLength,
+ header->DataLength);
+ return skb;
+ }
+
+ dev_kfree_skb(skb);
+ pr_err("RNDIS header is NULL.\n");
+ return NULL;
+ }
+
skb2 = skb_realloc_headroom(skb, sizeof(struct rndis_packet_msg_type));
rndis_add_hdr(skb2);
diff --git a/drivers/usb/gadget/function/f_uac2.c b/drivers/usb/gadget/function/f_uac2.c
index c330814..626e020 100644
--- a/drivers/usb/gadget/function/f_uac2.c
+++ b/drivers/usb/gadget/function/f_uac2.c
@@ -1156,6 +1156,8 @@
dev_err(dev, "%s:%d Error!\n", __func__, __LINE__);
return ret;
}
+ iad_desc.bFirstInterface = ret;
+
std_ac_if_desc.bInterfaceNumber = ret;
iad_desc.bFirstInterface = ret;
agdev->ac_intf = ret;
diff --git a/drivers/usb/gadget/function/u_ether.c b/drivers/usb/gadget/function/u_ether.c
index 9e38809..c75e790 100644
--- a/drivers/usb/gadget/function/u_ether.c
+++ b/drivers/usb/gadget/function/u_ether.c
@@ -246,6 +246,7 @@
}
static void rx_complete(struct usb_ep *ep, struct usb_request *req);
+static void tx_complete(struct usb_ep *ep, struct usb_request *req);
static int
rx_submit(struct eth_dev *dev, struct usb_request *req, gfp_t gfp_flags)
@@ -307,7 +308,6 @@
req->buf = skb->data;
req->length = size;
- req->complete = rx_complete;
req->context = skb;
retval = usb_ep_queue(out, req, gfp_flags);
@@ -410,6 +410,7 @@
{
unsigned i;
struct usb_request *req;
+ bool usb_in;
if (!n)
return -ENOMEM;
@@ -420,10 +421,22 @@
if (i-- == 0)
goto extra;
}
+
+ if (ep->desc->bEndpointAddress & USB_DIR_IN)
+ usb_in = true;
+ else
+ usb_in = false;
+
while (i--) {
req = usb_ep_alloc_request(ep, GFP_ATOMIC);
if (!req)
return list_empty(list) ? -ENOMEM : 0;
+ /* update completion handler */
+ if (usb_in)
+ req->complete = tx_complete;
+ else
+ req->complete = rx_complete;
+
list_add(&req->list, list);
}
return 0;
@@ -575,7 +588,7 @@
static void tx_complete(struct usb_ep *ep, struct usb_request *req)
{
- struct sk_buff *skb = req->context;
+ struct sk_buff *skb;
struct eth_dev *dev = ep->driver_data;
struct net_device *net = dev->net;
struct usb_request *new_req;
@@ -683,6 +696,7 @@
spin_unlock(&dev->req_lock);
}
} else {
+ skb = req->context;
/* Is aggregation already enabled and buffers allocated ? */
if (dev->port_usb->multi_pkt_xfer && dev->tx_req_bufsize) {
req->buf = kzalloc(dev->tx_req_bufsize
@@ -725,7 +739,7 @@
list_for_each(act, &dev->tx_reqs) {
req = container_of(act, struct usb_request, list);
if (!req->buf)
- req->buf = kmalloc(dev->tx_req_bufsize
+ req->buf = kzalloc(dev->tx_req_bufsize
+ dev->gadget->extra_buf_alloc, GFP_ATOMIC);
if (!req->buf)
@@ -804,29 +818,6 @@
}
dev->tx_pkts_rcvd++;
- /*
- * no buffer copies needed, unless the network stack did it
- * or the hardware can't use skb buffers.
- * or there's not enough space for extra headers we need
- */
- spin_lock_irqsave(&dev->lock, flags);
- if (dev->wrap && dev->port_usb)
- skb = dev->wrap(dev->port_usb, skb);
- spin_unlock_irqrestore(&dev->lock, flags);
-
- if (!skb) {
- if (dev->port_usb && dev->port_usb->supports_multi_frame) {
- /*
- * Multi frame CDC protocols may store the frame for
- * later which is not a dropped frame.
- */
- } else {
- dev->net->stats.tx_dropped++;
- }
-
- /* no error code for dropped packets */
- return NETDEV_TX_OK;
- }
/* Allocate memory for tx_reqs to support multi packet transfer */
spin_lock_irqsave(&dev->req_lock, flags);
@@ -861,13 +852,45 @@
dev->tx_throttle++;
netif_stop_queue(net);
}
-
- dev->tx_skb_hold_count++;
spin_unlock_irqrestore(&dev->req_lock, flags);
+ /* no buffer copies needed, unless the network stack did it
+ * or the hardware can't use skb buffers.
+ * or there's not enough space for extra headers we need
+ */
+ spin_lock_irqsave(&dev->lock, flags);
+ if (dev->wrap) {
+ if (dev->port_usb)
+ skb = dev->wrap(dev->port_usb, skb);
+ if (!skb) {
+ spin_unlock_irqrestore(&dev->lock, flags);
+ /* Multi frame CDC protocols may store the frame for
+ * later which is not a dropped frame.
+ */
+ if (dev->port_usb &&
+ dev->port_usb->supports_multi_frame)
+ goto multiframe;
+ goto drop;
+ }
+ }
+
+ dev->tx_skb_hold_count++;
+ spin_unlock_irqrestore(&dev->lock, flags);
+
if (multi_pkt_xfer) {
+ pr_debug("req->length:%d header_len:%u\n"
+ "skb->len:%d skb->data_len:%d\n",
+ req->length, dev->header_len,
+ skb->len, skb->data_len);
+ /* Add RNDIS Header */
+ memcpy(req->buf + req->length, dev->port_usb->header,
+ dev->header_len);
+ /* Increment req length by header size */
+ req->length += dev->header_len;
+ /* Copy received IP data from SKB */
memcpy(req->buf + req->length, skb->data, skb->len);
- req->length = req->length + skb->len;
+ /* Increment req length by skb data length */
+ req->length += skb->len;
length = req->length;
dev_kfree_skb_any(skb);
@@ -927,8 +950,6 @@
req->context = skb;
}
- req->complete = tx_complete;
-
/* NCM requires no zlp if transfer is dwNtbInMaxSize */
if (is_fixed && length == fixed_in_len &&
(length % in->maxpacket) == 0)
@@ -977,11 +998,13 @@
dev_kfree_skb_any(skb);
else
req->length = 0;
+drop:
dev->net->stats.tx_dropped++;
+multiframe:
spin_lock_irqsave(&dev->req_lock, flags);
if (list_empty(&dev->tx_reqs))
netif_start_queue(net);
- list_add(&req->list, &dev->tx_reqs);
+ list_add_tail(&req->list, &dev->tx_reqs);
spin_unlock_irqrestore(&dev->req_lock, flags);
}
success:
@@ -1443,6 +1466,8 @@
else
INFO(dev, "MAC %pM\n", dev->dev_mac);
+ uether_debugfs_init(dev);
+
return status;
}
EXPORT_SYMBOL_GPL(gether_register_netdev);
@@ -1594,6 +1619,11 @@
if (!dev)
return ERR_PTR(-EINVAL);
+ /* size of rndis_packet_msg_type is 44 */
+ link->header = kzalloc(44, GFP_ATOMIC);
+ if (!link->header)
+ return ERR_PTR(-ENOMEM);
+
if (link->in_ep) {
link->in_ep->driver_data = dev;
result = usb_ep_enable(link->in_ep);
@@ -1657,8 +1687,12 @@
}
fail0:
/* caller is responsible for cleanup on error */
- if (result < 0)
+ if (result < 0) {
+ kfree(link->header);
+
return ERR_PTR(result);
+ }
+
return dev->net;
}
EXPORT_SYMBOL_GPL(gether_connect);
@@ -1711,6 +1745,9 @@
spin_lock(&dev->req_lock);
}
spin_unlock(&dev->req_lock);
+ /* Free rndis header buffer memory */
+ kfree(link->header);
+ link->header = NULL;
link->in_ep->desc = NULL;
}
diff --git a/drivers/usb/gadget/function/u_ether.h b/drivers/usb/gadget/function/u_ether.h
index 3ff09d1..a10503a 100644
--- a/drivers/usb/gadget/function/u_ether.h
+++ b/drivers/usb/gadget/function/u_ether.h
@@ -87,6 +87,7 @@
/* called on network open/close */
void (*open)(struct gether *);
void (*close)(struct gether *);
+ struct rndis_packet_msg_type *header;
};
#define DEFAULT_FILTER (USB_CDC_PACKET_TYPE_BROADCAST \
diff --git a/drivers/usb/gadget/udc/fsl_udc_core.c b/drivers/usb/gadget/udc/fsl_udc_core.c
index aac0ce8..8991a40 100644
--- a/drivers/usb/gadget/udc/fsl_udc_core.c
+++ b/drivers/usb/gadget/udc/fsl_udc_core.c
@@ -1310,7 +1310,7 @@
{
struct fsl_ep *ep = get_ep_by_pipe(udc, pipe);
- if (ep->name)
+ if (ep->ep.name)
nuke(ep, -ESHUTDOWN);
}
@@ -1698,7 +1698,7 @@
curr_ep = get_ep_by_pipe(udc, i);
/* If the ep is configured */
- if (curr_ep->name == NULL) {
+ if (!curr_ep->ep.name) {
WARNING("Invalid EP?");
continue;
}
diff --git a/drivers/usb/gadget/udc/goku_udc.h b/drivers/usb/gadget/udc/goku_udc.h
index 86d2ada..64eb0f2 100644
--- a/drivers/usb/gadget/udc/goku_udc.h
+++ b/drivers/usb/gadget/udc/goku_udc.h
@@ -28,7 +28,7 @@
# define INT_EP1DATASET 0x00040
# define INT_EP2DATASET 0x00080
# define INT_EP3DATASET 0x00100
-#define INT_EPnNAK(n) (0x00100 < (n)) /* 0 < n < 4 */
+#define INT_EPnNAK(n) (0x00100 << (n)) /* 0 < n < 4 */
# define INT_EP1NAK 0x00200
# define INT_EP2NAK 0x00400
# define INT_EP3NAK 0x00800
diff --git a/drivers/usb/host/ohci-hcd.c b/drivers/usb/host/ohci-hcd.c
index 2c39571..216ddee 100644
--- a/drivers/usb/host/ohci-hcd.c
+++ b/drivers/usb/host/ohci-hcd.c
@@ -446,7 +446,8 @@
struct usb_hcd *hcd = ohci_to_hcd(ohci);
/* Accept arbitrarily long scatter-gather lists */
- hcd->self.sg_tablesize = ~0;
+ if (!(hcd->driver->flags & HCD_LOCAL_MEM))
+ hcd->self.sg_tablesize = ~0;
if (distrust_firmware)
ohci->flags |= OHCI_QUIRK_HUB_POWER;
diff --git a/drivers/usb/host/xhci-mem.c b/drivers/usb/host/xhci-mem.c
index 588e053..040feda 100644
--- a/drivers/usb/host/xhci-mem.c
+++ b/drivers/usb/host/xhci-mem.c
@@ -975,6 +975,8 @@
if (dev->out_ctx)
xhci_free_container_ctx(xhci, dev->out_ctx);
+ if (dev->udev && dev->udev->slot_id)
+ dev->udev->slot_id = 0;
kfree(xhci->devs[slot_id]);
xhci->devs[slot_id] = NULL;
}
diff --git a/drivers/usb/pd/policy_engine.c b/drivers/usb/pd/policy_engine.c
index d21823b..6685f05 100644
--- a/drivers/usb/pd/policy_engine.c
+++ b/drivers/usb/pd/policy_engine.c
@@ -753,6 +753,7 @@
{
int i;
union power_supply_propval val;
+ bool pps_found = false;
u32 first_pdo = pd->received_pdos[0];
if (PD_SRC_PDO_TYPE(first_pdo) != PD_SRC_PDO_TYPE_FIXED) {
@@ -768,10 +769,8 @@
power_supply_set_property(pd->usb_psy,
POWER_SUPPLY_PROP_PD_USB_SUSPEND_SUPPORTED, &val);
- if (pd->spec_rev == USBPD_REV_30 && !rev3_sink_only) {
- bool pps_found = false;
-
- /* downgrade to 2.0 if no PPS */
+ /* Check for PPS APDOs */
+ if (pd->spec_rev == USBPD_REV_30) {
for (i = 1; i < PD_MAX_DATA_OBJ; i++) {
if ((PD_SRC_PDO_TYPE(pd->received_pdos[i]) ==
PD_SRC_PDO_TYPE_AUGMENTED) &&
@@ -780,10 +779,18 @@
break;
}
}
- if (!pps_found)
+
+ /* downgrade to 2.0 if no PPS */
+ if (!pps_found && !rev3_sink_only)
pd->spec_rev = USBPD_REV_20;
}
+ val.intval = pps_found ?
+ POWER_SUPPLY_PD_PPS_ACTIVE :
+ POWER_SUPPLY_PD_ACTIVE;
+ power_supply_set_property(pd->usb_psy,
+ POWER_SUPPLY_PROP_PD_ACTIVE, &val);
+
/* Select the first PDO (vSafe5V) immediately. */
pd_select_pdo(pd, 1, 0, 0);
@@ -2140,7 +2147,7 @@
usbpd_dbg(&pd->dev, "Src CapsCounter exceeded, disabling PD\n");
usbpd_set_state(pd, PE_SRC_DISABLED);
- val.intval = 0;
+ val.intval = POWER_SUPPLY_PD_INACTIVE;
power_supply_set_property(pd->usb_psy,
POWER_SUPPLY_PROP_PD_ACTIVE,
&val);
@@ -2160,7 +2167,7 @@
pd->current_state = PE_SRC_SEND_CAPABILITIES_WAIT;
kick_sm(pd, SENDER_RESPONSE_TIME);
- val.intval = 1;
+ val.intval = POWER_SUPPLY_PD_ACTIVE;
power_supply_set_property(pd->usb_psy,
POWER_SUPPLY_PROP_PD_ACTIVE, &val);
break;
@@ -2352,10 +2359,6 @@
pd->src_cap_id++;
usbpd_set_state(pd, PE_SNK_EVALUATE_CAPABILITY);
-
- val.intval = 1;
- power_supply_set_property(pd->usb_psy,
- POWER_SUPPLY_PROP_PD_ACTIVE, &val);
} else if (pd->hard_reset_count < 3) {
usbpd_set_state(pd, PE_SNK_HARD_RESET);
} else {
@@ -2366,7 +2369,7 @@
POWER_SUPPLY_PROP_PD_IN_HARD_RESET,
&val);
- val.intval = 0;
+ val.intval = POWER_SUPPLY_PD_INACTIVE;
power_supply_set_property(pd->usb_psy,
POWER_SUPPLY_PROP_PD_ACTIVE, &val);
}
@@ -3577,7 +3580,7 @@
{
struct usbpd *pd = dev_get_drvdata(dev);
int pos = PD_RDO_OBJ_POS(pd->rdo);
- int type = PD_SRC_PDO_TYPE(pd->received_pdos[pos]);
+ int type = PD_SRC_PDO_TYPE(pd->received_pdos[pos - 1]);
int len;
len = scnprintf(buf, PAGE_SIZE, "Request Data Object\n"
diff --git a/drivers/usb/phy/phy-msm-qusb-v2.c b/drivers/usb/phy/phy-msm-qusb-v2.c
index 33a7f6a..6dfca9c 100644
--- a/drivers/usb/phy/phy-msm-qusb-v2.c
+++ b/drivers/usb/phy/phy-msm-qusb-v2.c
@@ -71,7 +71,6 @@
#define SQ_CTRL1_CHIRP_DISABLE 0x20
#define SQ_CTRL2_CHIRP_DISABLE 0x80
-#define PORT_TUNE1_OVERRIDE_VAL 0xc5
#define DEBUG_CTRL1_OVERRIDE_VAL 0x09
/* PERIPH_SS_PHY_REFGEN_NORTH_BG_CTRL register bits */
@@ -154,6 +153,7 @@
struct hrtimer timer;
int soc_min_rev;
bool host_chirp_erratum;
+ bool override_bias_ctrl2;
};
#ifdef CONFIG_NVMEM
@@ -473,6 +473,7 @@
static void qusb_phy_host_init(struct usb_phy *phy)
{
u8 reg;
+ int p_index;
struct qusb_phy *qphy = container_of(phy, struct qusb_phy, phy);
dev_dbg(phy->dev, "%s\n", __func__);
@@ -480,17 +481,43 @@
qusb_phy_write_seq(qphy->base, qphy->qusb_phy_host_init_seq,
qphy->host_init_seq_len, 0);
- /* If soc revision is mentioned and host_chirp_erratum flag is set
- * then override TUNE1 and DEBUG_CTRL1
- */
- if (qphy->soc_min_rev && qphy->host_chirp_erratum) {
- writel_relaxed(PORT_TUNE1_OVERRIDE_VAL,
- qphy->base + qphy->phy_reg[PORT_TUNE1]);
- writel_relaxed(DEBUG_CTRL1_OVERRIDE_VAL,
- qphy->base + qphy->phy_reg[DEBUG_CTRL1]);
+ if (qphy->efuse_reg) {
+ if (!qphy->tune_val)
+ qusb_phy_get_tune1_param(qphy);
+ } else {
+ /* For non fused chips we need to write the TUNE1 param as
+ * specified in DT otherwise we will end up writing 0 to
+ * to TUNE1
+ */
+ qphy->tune_val = readb_relaxed(qphy->base +
+ qphy->phy_reg[PORT_TUNE1]);
}
- if (qphy->refgen_north_bg_reg)
+ /* If soc revision is mentioned and host_chirp_erratum flag is set
+ * then override TUNE1 and DEBUG_CTRL1 while honouring efuse values
+ */
+ if (qphy->soc_min_rev && qphy->host_chirp_erratum) {
+ writel_relaxed(qphy->tune_val | BIT(7),
+ qphy->base + qphy->phy_reg[PORT_TUNE1]);
+ pr_debug("%s(): Programming TUNE1 parameter as:%x\n",
+ __func__, readb_relaxed(qphy->base +
+ qphy->phy_reg[PORT_TUNE1]));
+ writel_relaxed(DEBUG_CTRL1_OVERRIDE_VAL,
+ qphy->base + qphy->phy_reg[DEBUG_CTRL1]);
+ } else {
+ writel_relaxed(qphy->tune_val,
+ qphy->base + qphy->phy_reg[PORT_TUNE1]);
+ }
+
+ /* if debugfs based tunex params are set, use that value. */
+ for (p_index = 0; p_index < 5; p_index++) {
+ if (qphy->tune[p_index])
+ writel_relaxed(qphy->tune[p_index],
+ qphy->base + qphy->phy_reg[PORT_TUNE1] +
+ (4 * p_index));
+ }
+
+ if (qphy->refgen_north_bg_reg && qphy->override_bias_ctrl2)
if (readl_relaxed(qphy->refgen_north_bg_reg) & BANDGAP_BYPASS)
writel_relaxed(BIAS_CTRL_2_OVERRIDE_VAL,
qphy->base + qphy->phy_reg[BIAS_CTRL_2]);
@@ -585,7 +612,7 @@
(4 * p_index));
}
- if (qphy->refgen_north_bg_reg)
+ if (qphy->refgen_north_bg_reg && qphy->override_bias_ctrl2)
if (readl_relaxed(qphy->refgen_north_bg_reg) & BANDGAP_BYPASS)
writel_relaxed(BIAS_CTRL_2_OVERRIDE_VAL,
qphy->base + qphy->phy_reg[BIAS_CTRL_2]);
@@ -1209,6 +1236,9 @@
qphy->host_chirp_erratum = of_property_read_bool(dev->of_node,
"qcom,host-chirp-erratum");
+ qphy->override_bias_ctrl2 = of_property_read_bool(dev->of_node,
+ "qcom,override-bias-ctrl2");
+
ret = of_property_read_u32_array(dev->of_node, "qcom,vdd-voltage-level",
(u32 *) qphy->vdd_levels,
ARRAY_SIZE(qphy->vdd_levels));
diff --git a/drivers/usb/phy/phy-msm-usb.c b/drivers/usb/phy/phy-msm-usb.c
index a6326d5..b8f4907 100644
--- a/drivers/usb/phy/phy-msm-usb.c
+++ b/drivers/usb/phy/phy-msm-usb.c
@@ -1835,8 +1835,11 @@
union power_supply_propval pval = {0};
if (!psy) {
- dev_err(motg->phy.dev, "no usb power supply registered\n");
- return -ENODEV;
+ psy = power_supply_get_by_name("usb");
+ if (!psy) {
+ dev_err(motg->phy.dev, "Could not get usb power_supply\n");
+ return -ENODEV;
+ }
}
power_supply_get_property(psy, POWER_SUPPLY_PROP_REAL_TYPE, &pval);
@@ -1868,11 +1871,6 @@
else
charger_type = POWER_SUPPLY_TYPE_UNKNOWN;
- if (!psy) {
- dev_err(motg->phy.dev, "no usb power supply registered\n");
- return -ENODEV;
- }
-
pr_debug("Trying to set usb power supply type %d\n", charger_type);
propval.intval = charger_type;
@@ -1897,6 +1895,10 @@
dev_dbg(motg->phy.dev, "Requested curr from USB = %u\n", mA);
+ psy_type = get_psy_type(motg);
+ if (psy_type == -ENODEV)
+ return;
+
if (msm_otg_notify_chg_type(motg))
dev_dbg(motg->phy.dev, "Failed notifying %d charger type to PMIC\n",
motg->chg_type);
@@ -4473,12 +4475,8 @@
}
psy = power_supply_get_by_name("usb");
- if (!psy) {
- dev_dbg(&pdev->dev, "Could not get usb power_supply\n");
- ret = -EPROBE_DEFER;
- goto otg_remove_devices;
- }
-
+ if (!psy)
+ dev_warn(&pdev->dev, "Could not get usb power_supply\n");
ret = msm_otg_extcon_register(motg);
if (ret)
@@ -4533,7 +4531,6 @@
put_psy:
if (psy)
power_supply_put(psy);
-otg_remove_devices:
if (pdev->dev.of_node)
msm_otg_setup_devices(pdev, motg->pdata->mode, false);
remove_cdev:
diff --git a/drivers/usb/serial/cp210x.c b/drivers/usb/serial/cp210x.c
index d985318..90d7c6e 100644
--- a/drivers/usb/serial/cp210x.c
+++ b/drivers/usb/serial/cp210x.c
@@ -745,7 +745,7 @@
unsigned int cflag;
struct cp210x_flow_ctl flow_ctl;
u32 baud;
- u16 bits;
+ u16 bits = 0;
u32 ctl_hs;
cp210x_read_u32_reg(port, CP210X_GET_BAUDRATE, &baud);
diff --git a/drivers/usb/usbip/stub.h b/drivers/usb/usbip/stub.h
index 910f027..84c0599 100644
--- a/drivers/usb/usbip/stub.h
+++ b/drivers/usb/usbip/stub.h
@@ -87,6 +87,7 @@
struct stub_device *sdev;
struct usb_device *udev;
char shutdown_busid;
+ spinlock_t busid_lock;
};
/* stub_priv is allocated from stub_priv_cache */
@@ -97,6 +98,7 @@
/* stub_main.c */
struct bus_id_priv *get_busid_priv(const char *busid);
+void put_busid_priv(struct bus_id_priv *bid);
int del_match_busid(char *busid);
void stub_device_cleanup_urbs(struct stub_device *sdev);
diff --git a/drivers/usb/usbip/stub_dev.c b/drivers/usb/usbip/stub_dev.c
index 3550224..8e629b6 100644
--- a/drivers/usb/usbip/stub_dev.c
+++ b/drivers/usb/usbip/stub_dev.c
@@ -314,9 +314,9 @@
struct stub_device *sdev = NULL;
const char *udev_busid = dev_name(&udev->dev);
struct bus_id_priv *busid_priv;
- int rc;
+ int rc = 0;
- dev_dbg(&udev->dev, "Enter\n");
+ dev_dbg(&udev->dev, "Enter probe\n");
/* check we should claim or not by busid_table */
busid_priv = get_busid_priv(udev_busid);
@@ -331,13 +331,15 @@
* other matched drivers by the driver core.
* See driver_probe_device() in driver/base/dd.c
*/
- return -ENODEV;
+ rc = -ENODEV;
+ goto call_put_busid_priv;
}
if (udev->descriptor.bDeviceClass == USB_CLASS_HUB) {
dev_dbg(&udev->dev, "%s is a usb hub device... skip!\n",
udev_busid);
- return -ENODEV;
+ rc = -ENODEV;
+ goto call_put_busid_priv;
}
if (!strcmp(udev->bus->bus_name, "vhci_hcd")) {
@@ -345,13 +347,16 @@
"%s is attached on vhci_hcd... skip!\n",
udev_busid);
- return -ENODEV;
+ rc = -ENODEV;
+ goto call_put_busid_priv;
}
/* ok, this is my device */
sdev = stub_device_alloc(udev);
- if (!sdev)
- return -ENOMEM;
+ if (!sdev) {
+ rc = -ENOMEM;
+ goto call_put_busid_priv;
+ }
dev_info(&udev->dev,
"usbip-host: register new device (bus %u dev %u)\n",
@@ -383,7 +388,9 @@
}
busid_priv->status = STUB_BUSID_ALLOC;
- return 0;
+ rc = 0;
+ goto call_put_busid_priv;
+
err_files:
usb_hub_release_port(udev->parent, udev->portnum,
(struct usb_dev_state *) udev);
@@ -393,6 +400,9 @@
busid_priv->sdev = NULL;
stub_device_free(sdev);
+
+call_put_busid_priv:
+ put_busid_priv(busid_priv);
return rc;
}
@@ -418,7 +428,7 @@
struct bus_id_priv *busid_priv;
int rc;
- dev_dbg(&udev->dev, "Enter\n");
+ dev_dbg(&udev->dev, "Enter disconnect\n");
busid_priv = get_busid_priv(udev_busid);
if (!busid_priv) {
@@ -431,7 +441,7 @@
/* get stub_device */
if (!sdev) {
dev_err(&udev->dev, "could not get device");
- return;
+ goto call_put_busid_priv;
}
dev_set_drvdata(&udev->dev, NULL);
@@ -446,12 +456,12 @@
(struct usb_dev_state *) udev);
if (rc) {
dev_dbg(&udev->dev, "unable to release port\n");
- return;
+ goto call_put_busid_priv;
}
/* If usb reset is called from event handler */
if (usbip_in_eh(current))
- return;
+ goto call_put_busid_priv;
/* shutdown the current connection */
shutdown_busid(busid_priv);
@@ -462,12 +472,11 @@
busid_priv->sdev = NULL;
stub_device_free(sdev);
- if (busid_priv->status == STUB_BUSID_ALLOC) {
+ if (busid_priv->status == STUB_BUSID_ALLOC)
busid_priv->status = STUB_BUSID_ADDED;
- } else {
- busid_priv->status = STUB_BUSID_OTHER;
- del_match_busid((char *)udev_busid);
- }
+
+call_put_busid_priv:
+ put_busid_priv(busid_priv);
}
#ifdef CONFIG_PM
diff --git a/drivers/usb/usbip/stub_main.c b/drivers/usb/usbip/stub_main.c
index f761e02..fa90496 100644
--- a/drivers/usb/usbip/stub_main.c
+++ b/drivers/usb/usbip/stub_main.c
@@ -28,6 +28,7 @@
#define DRIVER_DESC "USB/IP Host Driver"
struct kmem_cache *stub_priv_cache;
+
/*
* busid_tables defines matching busids that usbip can grab. A user can change
* dynamically what device is locally used and what device is exported to a
@@ -39,6 +40,8 @@
static void init_busid_table(void)
{
+ int i;
+
/*
* This also sets the bus_table[i].status to
* STUB_BUSID_OTHER, which is 0.
@@ -46,6 +49,9 @@
memset(busid_table, 0, sizeof(busid_table));
spin_lock_init(&busid_table_lock);
+
+ for (i = 0; i < MAX_BUSID; i++)
+ spin_lock_init(&busid_table[i].busid_lock);
}
/*
@@ -57,15 +63,20 @@
int i;
int idx = -1;
- for (i = 0; i < MAX_BUSID; i++)
+ for (i = 0; i < MAX_BUSID; i++) {
+ spin_lock(&busid_table[i].busid_lock);
if (busid_table[i].name[0])
if (!strncmp(busid_table[i].name, busid, BUSID_SIZE)) {
idx = i;
+ spin_unlock(&busid_table[i].busid_lock);
break;
}
+ spin_unlock(&busid_table[i].busid_lock);
+ }
return idx;
}
+/* Returns holding busid_lock. Should call put_busid_priv() to unlock */
struct bus_id_priv *get_busid_priv(const char *busid)
{
int idx;
@@ -73,13 +84,22 @@
spin_lock(&busid_table_lock);
idx = get_busid_idx(busid);
- if (idx >= 0)
+ if (idx >= 0) {
bid = &(busid_table[idx]);
+ /* get busid_lock before returning */
+ spin_lock(&bid->busid_lock);
+ }
spin_unlock(&busid_table_lock);
return bid;
}
+void put_busid_priv(struct bus_id_priv *bid)
+{
+ if (bid)
+ spin_unlock(&bid->busid_lock);
+}
+
static int add_match_busid(char *busid)
{
int i;
@@ -92,15 +112,19 @@
goto out;
}
- for (i = 0; i < MAX_BUSID; i++)
+ for (i = 0; i < MAX_BUSID; i++) {
+ spin_lock(&busid_table[i].busid_lock);
if (!busid_table[i].name[0]) {
strlcpy(busid_table[i].name, busid, BUSID_SIZE);
if ((busid_table[i].status != STUB_BUSID_ALLOC) &&
(busid_table[i].status != STUB_BUSID_REMOV))
busid_table[i].status = STUB_BUSID_ADDED;
ret = 0;
+ spin_unlock(&busid_table[i].busid_lock);
break;
}
+ spin_unlock(&busid_table[i].busid_lock);
+ }
out:
spin_unlock(&busid_table_lock);
@@ -121,6 +145,8 @@
/* found */
ret = 0;
+ spin_lock(&busid_table[idx].busid_lock);
+
if (busid_table[idx].status == STUB_BUSID_OTHER)
memset(busid_table[idx].name, 0, BUSID_SIZE);
@@ -128,6 +154,7 @@
(busid_table[idx].status != STUB_BUSID_ADDED))
busid_table[idx].status = STUB_BUSID_REMOV;
+ spin_unlock(&busid_table[idx].busid_lock);
out:
spin_unlock(&busid_table_lock);
@@ -140,9 +167,12 @@
char *out = buf;
spin_lock(&busid_table_lock);
- for (i = 0; i < MAX_BUSID; i++)
+ for (i = 0; i < MAX_BUSID; i++) {
+ spin_lock(&busid_table[i].busid_lock);
if (busid_table[i].name[0])
out += sprintf(out, "%s ", busid_table[i].name);
+ spin_unlock(&busid_table[i].busid_lock);
+ }
spin_unlock(&busid_table_lock);
out += sprintf(out, "\n");
@@ -184,6 +214,51 @@
static DRIVER_ATTR(match_busid, S_IRUSR | S_IWUSR, show_match_busid,
store_match_busid);
+static int do_rebind(char *busid, struct bus_id_priv *busid_priv)
+{
+ int ret;
+
+ /* device_attach() callers should hold parent lock for USB */
+ if (busid_priv->udev->dev.parent)
+ device_lock(busid_priv->udev->dev.parent);
+ ret = device_attach(&busid_priv->udev->dev);
+ if (busid_priv->udev->dev.parent)
+ device_unlock(busid_priv->udev->dev.parent);
+ if (ret < 0) {
+ dev_err(&busid_priv->udev->dev, "rebind failed\n");
+ return ret;
+ }
+ return 0;
+}
+
+static void stub_device_rebind(void)
+{
+#if IS_MODULE(CONFIG_USBIP_HOST)
+ struct bus_id_priv *busid_priv;
+ int i;
+
+ /* update status to STUB_BUSID_OTHER so probe ignores the device */
+ spin_lock(&busid_table_lock);
+ for (i = 0; i < MAX_BUSID; i++) {
+ if (busid_table[i].name[0] &&
+ busid_table[i].shutdown_busid) {
+ busid_priv = &(busid_table[i]);
+ busid_priv->status = STUB_BUSID_OTHER;
+ }
+ }
+ spin_unlock(&busid_table_lock);
+
+ /* now run rebind - no need to hold locks. driver files are removed */
+ for (i = 0; i < MAX_BUSID; i++) {
+ if (busid_table[i].name[0] &&
+ busid_table[i].shutdown_busid) {
+ busid_priv = &(busid_table[i]);
+ do_rebind(busid_table[i].name, busid_priv);
+ }
+ }
+#endif
+}
+
static ssize_t rebind_store(struct device_driver *dev, const char *buf,
size_t count)
{
@@ -201,16 +276,17 @@
if (!bid)
return -ENODEV;
- /* device_attach() callers should hold parent lock for USB */
- if (bid->udev->dev.parent)
- device_lock(bid->udev->dev.parent);
- ret = device_attach(&bid->udev->dev);
- if (bid->udev->dev.parent)
- device_unlock(bid->udev->dev.parent);
- if (ret < 0) {
- dev_err(&bid->udev->dev, "rebind failed\n");
+ /* mark the device for deletion so probe ignores it during rescan */
+ bid->status = STUB_BUSID_OTHER;
+ /* release the busid lock */
+ put_busid_priv(bid);
+
+ ret = do_rebind((char *) buf, bid);
+ if (ret < 0)
return ret;
- }
+
+ /* delete device from busid_table */
+ del_match_busid((char *) buf);
return count;
}
@@ -333,6 +409,9 @@
*/
usb_deregister_device_driver(&stub_driver);
+ /* initiate scan to attach devices */
+ stub_device_rebind();
+
kmem_cache_destroy(stub_priv_cache);
}
diff --git a/drivers/video/fbdev/msm/Kconfig b/drivers/video/fbdev/msm/Kconfig
index e8f902b..a5e0662 100644
--- a/drivers/video/fbdev/msm/Kconfig
+++ b/drivers/video/fbdev/msm/Kconfig
@@ -82,6 +82,16 @@
MHL (Mobile High-Definition Link) technology
uses USB connector to output HDMI content
+config FB_MSM_MDSS_SPI_PANEL
+ depends on FB_MSM_MDSS
+ bool "Support SPI panel feature"
+ default n
+ ---help---
+ The MDSS SPI Panel provides support for transmittimg SPI signals of
+ MDSS frame buffer data to connected panel. Limited by SPI rate, the
+ current max fps only reach to 27 fps, and limited by MDP hardware
+ architecture only supply on MDP3
+
config FB_MSM_MDSS_MHL3
depends on FB_MSM_MDSS_HDMI_PANEL
bool "MHL3 SII8620 Support"
diff --git a/drivers/video/fbdev/msm/Makefile b/drivers/video/fbdev/msm/Makefile
index 81d4953..26a940c 100644
--- a/drivers/video/fbdev/msm/Makefile
+++ b/drivers/video/fbdev/msm/Makefile
@@ -46,6 +46,11 @@
obj-$(CONFIG_FB_MSM_MDSS) += mdss-dsi.o
obj-$(CONFIG_FB_MSM_MDSS) += mdss_panel.o
+ifeq ($(CONFIG_SPI_QUP), y)
+obj-$(CONFIG_FB_MSM_MDSS_SPI_PANEL) += mdss_spi_client.o
+obj-$(CONFIG_FB_MSM_MDSS_SPI_PANEL) += mdss_spi_panel.o
+endif
+
ifneq ($(CONFIG_FB_MSM_MDSS_MDP3), y)
obj-$(CONFIG_FB_MSM_MDSS) += mdss_hdmi_util.o
obj-$(CONFIG_FB_MSM_MDSS) += mdss_hdmi_edid.o
diff --git a/drivers/video/fbdev/msm/dsi_status_6g.c b/drivers/video/fbdev/msm/dsi_status_6g.c
index 88bf0aa..8a32902 100644
--- a/drivers/video/fbdev/msm/dsi_status_6g.c
+++ b/drivers/video/fbdev/msm/dsi_status_6g.c
@@ -18,6 +18,7 @@
#include "mdss_dsi.h"
#include "mdss_mdp.h"
+#include "mdss_debug.h"
/*
* mdss_check_te_status() - Check the status of panel for TE based ESD.
@@ -155,6 +156,7 @@
ctl->ops.wait_pingpong(ctl, NULL);
pr_debug("%s: DSI ctrl wait for ping pong done\n", __func__);
+ MDSS_XLOG(mipi->mode);
mdss_mdp_clk_ctrl(MDP_BLOCK_POWER_ON);
ret = ctrl_pdata->check_status(ctrl_pdata);
diff --git a/drivers/video/fbdev/msm/dsi_status_v2.c b/drivers/video/fbdev/msm/dsi_status_v2.c
index 35b0984..87720cf 100644
--- a/drivers/video/fbdev/msm/dsi_status_v2.c
+++ b/drivers/video/fbdev/msm/dsi_status_v2.c
@@ -18,6 +18,7 @@
#include "mdss_dsi.h"
#include "mdp3_ctrl.h"
+#include "mdss_spi_panel.h"
/*
* mdp3_check_te_status() - Check the status of panel for TE based ESD.
@@ -165,3 +166,79 @@
mdss_fb_report_panel_dead(pdsi_status->mfd);
}
+#if defined(CONFIG_FB_MSM_MDSS_SPI_PANEL)
+void mdp3_check_spi_panel_status(struct work_struct *work, uint32_t interval)
+{
+ struct dsi_status_data *pdsi_status = NULL;
+ struct mdss_panel_data *pdata = NULL;
+ struct spi_panel_data *ctrl_pdata = NULL;
+ struct mdp3_session_data *mdp3_session = NULL;
+ int ret = 0;
+
+ pdsi_status = container_of(to_delayed_work(work),
+ struct dsi_status_data, check_status);
+
+ if (!pdsi_status || !(pdsi_status->mfd)) {
+ pr_err("%s: mfd not available\n", __func__);
+ return;
+ }
+
+ pdata = dev_get_platdata(&pdsi_status->mfd->pdev->dev);
+ if (!pdata) {
+ pr_err("%s: panel data not available\n", __func__);
+ return;
+ }
+
+ ctrl_pdata = container_of(pdata, struct spi_panel_data, panel_data);
+ if (!ctrl_pdata || !ctrl_pdata->check_status) {
+ pr_err("%s: Dsi ctrl or status_check callback not available\n",
+ __func__);
+ return;
+ }
+
+ mdp3_session = pdsi_status->mfd->mdp.private1;
+ if (!mdp3_session) {
+ pr_err("%s: Display is off\n", __func__);
+ return;
+ }
+
+ if (mdp3_session->in_splash_screen) {
+ schedule_delayed_work(&pdsi_status->check_status,
+ msecs_to_jiffies(interval));
+ pr_debug("%s: cont splash is on\n", __func__);
+ return;
+ }
+
+ mutex_lock(&mdp3_session->lock);
+ if (!mdp3_session->status) {
+ pr_debug("%s: display off already\n", __func__);
+ mutex_unlock(&mdp3_session->lock);
+ return;
+ }
+
+ if (!ret)
+ ret = ctrl_pdata->check_status(ctrl_pdata);
+ else
+ pr_err("%s:wait_for_dma_done error\n", __func__);
+ mutex_unlock(&mdp3_session->lock);
+
+ if (mdss_fb_is_power_on_interactive(pdsi_status->mfd)) {
+ if (ret > 0) {
+ schedule_delayed_work(&pdsi_status->check_status,
+ msecs_to_jiffies(interval));
+ } else {
+ char *envp[2] = {"PANEL_ALIVE=0", NULL};
+
+ pdata->panel_info.panel_dead = true;
+ ret = kobject_uevent_env(
+ &pdsi_status->mfd->fbi->dev->kobj, KOBJ_CHANGE, envp);
+ pr_err("%s:panel has gone bad, sending uevent - %s\n",
+ __func__, envp[0]);
+ }
+ }
+}
+#else
+void mdp3_check_spi_panel_status(struct work_struct *work, uint32_t interval)
+{
+}
+#endif
diff --git a/drivers/video/fbdev/msm/mdp3.c b/drivers/video/fbdev/msm/mdp3.c
index c9db88e..5e9e49c 100644
--- a/drivers/video/fbdev/msm/mdp3.c
+++ b/drivers/video/fbdev/msm/mdp3.c
@@ -56,6 +56,7 @@
#include "mdss_debug.h"
#include "mdss_smmu.h"
#include "mdss.h"
+#include "mdss_spi_panel.h"
#ifndef EXPORT_COMPAT
#define EXPORT_COMPAT(x)
@@ -109,6 +110,7 @@
static struct mdss_panel_intf pan_types[] = {
{"dsi", MDSS_PANEL_INTF_DSI},
+ {"spi", MDSS_PANEL_INTF_SPI},
};
static char mdss_mdp3_panel[MDSS_MAX_PANEL_LEN];
@@ -127,6 +129,13 @@
},
};
+#ifndef CONFIG_FB_MSM_MDSS_SPI_PANEL
+void mdss_spi_panel_bl_ctrl_update(struct mdss_panel_data *pdata, u32 bl_level)
+{
+
+}
+#endif
+
static irqreturn_t mdp3_irq_handler(int irq, void *ptr)
{
int i = 0;
@@ -1350,7 +1359,11 @@
client == MDP3_CLIENT_DMA_P)
mdss_smmu_unmap_dma_buf(data->tab_clone,
dom, dir, data->srcp_dma_buf);
- else
+ else if (client == MDP3_CLIENT_SPI) {
+ ion_unmap_kernel(iclient, data->srcp_ihdl);
+ ion_free(iclient, data->srcp_ihdl);
+ data->srcp_ihdl = NULL;
+ } else
mdss_smmu_unmap_dma_buf(data->srcp_table,
dom, dir, data->srcp_dma_buf);
data->mapped = false;
@@ -1416,7 +1429,15 @@
data->srcp_dma_buf = NULL;
return ret;
}
-
+ if (client == MDP3_CLIENT_SPI) {
+ data->srcp_ihdl = ion_import_dma_buf(iclient,
+ data->srcp_dma_buf);
+ if (IS_ERR_OR_NULL(data->srcp_ihdl)) {
+ pr_err("error on ion_import_fd\n");
+ data->srcp_ihdl = NULL;
+ return -EIO;
+ }
+ }
data->srcp_attachment =
mdss_smmu_dma_buf_attach(data->srcp_dma_buf,
&mdp3_res->pdev->dev, dom);
@@ -1449,6 +1470,25 @@
data->tab_clone, dom,
&data->addr, &data->len,
DMA_BIDIRECTIONAL);
+ } else if (client == MDP3_CLIENT_SPI) {
+ void *vaddr;
+
+ if (ion_handle_get_size(iclient,
+ data->srcp_ihdl,
+ (size_t *)&data->len) < 0) {
+ pr_err("get size failed\n");
+ return -EINVAL;
+ }
+ vaddr = ion_map_kernel(iclient,
+ data->srcp_ihdl);
+ if (IS_ERR_OR_NULL(vaddr)) {
+ pr_err("Mapping failed\n");
+ mdp3_put_img(data, client);
+ return -EINVAL;
+ }
+ data->addr = (dma_addr_t) vaddr;
+ data->len -= img->offset;
+ return 0;
} else {
ret = mdss_smmu_map_dma_buf(data->srcp_dma_buf,
data->srcp_table, dom, &data->addr,
@@ -1741,6 +1781,8 @@
if (pdata->panel_info.type == MIPI_VIDEO_PANEL) {
status = MDP3_REG_READ(MDP3_REG_DSI_VIDEO_EN);
rc = status & 0x1;
+ } else if (pdata->panel_info.type == SPI_PANEL) {
+ rc = is_spi_panel_continuous_splash_on(pdata);
} else {
status = MDP3_REG_READ(MDP3_REG_DMA_P_CONFIG);
status &= 0x180000;
@@ -1777,7 +1819,11 @@
mdp3_clk_set_rate(MDP3_CLK_MDP_SRC, mdp_clk_rate,
MDP3_CLIENT_DMA_P);
- rc = mdp3_bus_scale_set_quota(MDP3_CLIENT_DMA_P, ab, ib);
+ /*DMA not used on SPI interface, remove DMA bus voting*/
+ if (panel_info->type == SPI_PANEL)
+ rc = mdp3_bus_scale_set_quota(MDP3_CLIENT_DMA_P, 0, 0);
+ else
+ rc = mdp3_bus_scale_set_quota(MDP3_CLIENT_DMA_P, ab, ib);
bus_handle->restore_ab[MDP3_CLIENT_DMA_P] = ab;
bus_handle->restore_ib[MDP3_CLIENT_DMA_P] = ib;
@@ -1795,6 +1841,8 @@
if (panel_info->type == MIPI_VIDEO_PANEL)
mdp3_res->intf[MDP3_DMA_OUTPUT_SEL_DSI_VIDEO].active = 1;
+ else if (panel_info->type == SPI_PANEL)
+ mdp3_res->intf[MDP3_DMA_OUTPUT_SEL_SPI_CMD].active = 1;
else
mdp3_res->intf[MDP3_DMA_OUTPUT_SEL_DSI_CMD].active = 1;
@@ -2485,6 +2533,9 @@
mdp3_res->mdss_util->mdp_probe_done = true;
pr_debug("%s: END\n", __func__);
+ if (mdp3_res->pan_cfg.pan_intf == MDSS_PANEL_INTF_SPI)
+ mdp3_interface.check_dsi_status = mdp3_check_spi_panel_status;
+
probe_done:
if (IS_ERR_VALUE(rc))
kfree(mdp3_res->mdp3_hw.irq_info);
diff --git a/drivers/video/fbdev/msm/mdp3.h b/drivers/video/fbdev/msm/mdp3.h
index 7132dee..6b56052 100644
--- a/drivers/video/fbdev/msm/mdp3.h
+++ b/drivers/video/fbdev/msm/mdp3.h
@@ -84,6 +84,7 @@
MDP3_CLIENT_DSI = 1,
MDP3_CLIENT_PPP,
MDP3_CLIENT_IOMMU,
+ MDP3_CLIENT_SPI,
MDP3_CLIENT_MAX,
};
@@ -208,6 +209,8 @@
bool solid_fill_vote_en;
struct list_head reg_bus_clist;
struct mutex reg_bus_lock;
+ int bklt_level;
+ int bklt_update;
bool twm_en;
u32 max_bw;
@@ -267,6 +270,7 @@
void mdp3_enable_regulator(int enable);
void mdp3_check_dsi_ctrl_status(struct work_struct *work,
uint32_t interval);
+void mdp3_check_spi_panel_status(struct work_struct *work, uint32_t interval);
int mdp3_dynamic_clock_gating_ctrl(int enable);
int mdp3_footswitch_ctrl(int enable);
int mdp3_qos_remapper_setup(struct mdss_panel_data *panel);
@@ -279,6 +283,8 @@
void mdp3_clear_irq(u32 interrupt_mask);
int mdp3_enable_panic_ctrl(void);
+void mdss_spi_panel_bl_ctrl_update(struct mdss_panel_data *pdata, u32 bl_level);
+
int mdp3_layer_pre_commit(struct msm_fb_data_type *mfd,
struct file *file, struct mdp_layer_commit_v1 *commit);
int mdp3_layer_atomic_validate(struct msm_fb_data_type *mfd,
diff --git a/drivers/video/fbdev/msm/mdp3_ctrl.c b/drivers/video/fbdev/msm/mdp3_ctrl.c
index 50b232a..c976c0e 100644
--- a/drivers/video/fbdev/msm/mdp3_ctrl.c
+++ b/drivers/video/fbdev/msm/mdp3_ctrl.c
@@ -23,11 +23,13 @@
#include <linux/dma-buf.h>
#include <linux/pm_runtime.h>
#include <linux/iommu.h>
+#include <linux/msm_ion.h>
#include "mdp3_ctrl.h"
#include "mdp3.h"
#include "mdp3_ppp.h"
#include "mdss_smmu.h"
+#include "mdss_spi_panel.h"
#include "mdss_sync.h"
#define VSYNC_EXPIRE_TICK 4
@@ -72,7 +74,7 @@
bufq->pop_idx = 0;
}
-void mdp3_bufq_deinit(struct mdp3_buffer_queue *bufq)
+void mdp3_bufq_deinit(struct mdp3_buffer_queue *bufq, int client)
{
int count = bufq->count;
@@ -83,7 +85,7 @@
struct mdp3_img_data *data = &bufq->img_data[bufq->pop_idx];
bufq->pop_idx = (bufq->pop_idx + 1) % MDP3_MAX_BUF_QUEUE;
- mdp3_put_img(data, MDP3_CLIENT_DMA_P);
+ mdp3_put_img(data, client);
}
bufq->count = 0;
bufq->push_idx = 0;
@@ -122,6 +124,18 @@
return bufq->count;
}
+int mdp3_get_ion_client(struct msm_fb_data_type *mfd)
+{
+ int intf_type;
+
+ intf_type = mdp3_ctrl_get_intf_type(mfd);
+
+ if (intf_type == MDP3_DMA_OUTPUT_SEL_SPI_CMD)
+ return MDP3_CLIENT_SPI;
+ else
+ return MDP3_CLIENT_DMA_P;
+}
+
void mdp3_ctrl_notifier_register(struct mdp3_session_data *ses,
struct notifier_block *notifier)
{
@@ -308,8 +322,11 @@
struct mdp3_notification vsync_client;
struct mdp3_notification *arg = NULL;
bool mod_vsync_timer = false;
+ int intf_type;
pr_debug("mdp3_ctrl_vsync_enable =%d\n", enable);
+
+ intf_type = mdp3_ctrl_get_intf_type(mfd);
mdp3_session = (struct mdp3_session_data *)mfd->mdp.private1;
if (!mdp3_session || !mdp3_session->panel || !mdp3_session->dma ||
!mdp3_session->intf)
@@ -347,18 +364,25 @@
}
}
- mdp3_clk_enable(1, 0);
- mdp3_session->dma->vsync_enable(mdp3_session->dma, arg);
- mdp3_clk_enable(0, 0);
+ if (intf_type == MDP3_DMA_OUTPUT_SEL_SPI_CMD) {
+ mdp3_spi_vsync_enable(mdp3_session->panel, arg);
+ } else {
+ mdp3_clk_enable(1, 0);
+ mdp3_session->dma->vsync_enable(mdp3_session->dma, arg);
+ mdp3_clk_enable(0, 0);
+ }
/*
* Need to fake vsync whenever dsi interface is not
* active or when dsi clocks are currently off
*/
- if (mod_vsync_timer) {
+ if (mod_vsync_timer && (intf_type != MDP3_DMA_OUTPUT_SEL_SPI_CMD)) {
mod_timer(&mdp3_session->vsync_timer,
jiffies + msecs_to_jiffies(mdp3_session->vsync_period));
- } else if (!enable) {
+ } else if (enable && !mdp3_session->clk_on) {
+ mdp3_ctrl_reset_countdown(mdp3_session, mfd);
+ mdp3_ctrl_clk_enable(mfd, 1);
+ } else if (!enable && (intf_type != MDP3_DMA_OUTPUT_SEL_SPI_CMD)) {
del_timer(&mdp3_session->vsync_timer);
}
@@ -597,14 +621,32 @@
static int mdp3_ctrl_res_req_bus(struct msm_fb_data_type *mfd, int status)
{
int rc = 0;
+ u32 vtotal = 0;
+ int frame_rate = DEFAULT_FRAME_RATE;
if (status) {
+ struct mdss_panel_info *panel_info = mfd->panel_info;
u64 ab = 0;
u64 ib = 0;
+ frame_rate = mdss_panel_get_framerate(mfd->panel_info,
+ FPS_RESOLUTION_HZ);
mdp3_calc_dma_res(mfd->panel_info, NULL, &ab, &ib,
ppp_bpp(mfd->fb_imgType));
- rc = mdp3_bus_scale_set_quota(MDP3_CLIENT_DMA_P, ab, ib);
+ vtotal = panel_info->yres + panel_info->lcdc.v_back_porch +
+ panel_info->lcdc.v_front_porch +
+ panel_info->lcdc.v_pulse_width;
+ ab = panel_info->xres * vtotal * ppp_bpp(mfd->fb_imgType);
+ ab *= frame_rate;
+ ib = ab;
+
+ /*DMA not used on SPI interface, remove DMA bus voting*/
+ if (mdp3_ctrl_get_intf_type(mfd) ==
+ MDP3_DMA_OUTPUT_SEL_SPI_CMD)
+ rc = mdp3_bus_scale_set_quota(MDP3_CLIENT_DMA_P, 0, 0);
+ else
+ rc = mdp3_bus_scale_set_quota(MDP3_CLIENT_DMA_P,
+ ab, ib);
} else {
rc = mdp3_bus_scale_set_quota(MDP3_CLIENT_DMA_P, 0, 0);
}
@@ -653,6 +695,9 @@
case LCDC_PANEL:
type = MDP3_DMA_OUTPUT_SEL_LCDC;
break;
+ case SPI_PANEL:
+ type = MDP3_DMA_OUTPUT_SEL_SPI_CMD;
+ break;
default:
type = MDP3_DMA_OUTPUT_SEL_MAX;
}
@@ -717,7 +762,8 @@
cfg.type = mdp3_ctrl_get_intf_type(mfd);
if (cfg.type == MDP3_DMA_OUTPUT_SEL_DSI_VIDEO ||
- cfg.type == MDP3_DMA_OUTPUT_SEL_LCDC) {
+ cfg.type == MDP3_DMA_OUTPUT_SEL_LCDC ||
+ cfg.type == MDP3_DMA_OUTPUT_SEL_SPI_CMD) {
video->hsync_period = hsync_period;
video->hsync_pulse_width = h_pulse_width;
video->vsync_period = vsync_period;
@@ -765,7 +811,7 @@
struct fb_var_screeninfo *var;
struct mdp3_dma_output_config outputConfig;
struct mdp3_dma_source sourceConfig;
- int frame_rate = mfd->panel_info->mipi.frame_rate;
+ int frame_rate = DEFAULT_FRAME_RATE;
int vbp, vfp, vspw;
int vtotal, vporch;
struct mdp3_notification dma_done_callback;
@@ -774,6 +820,7 @@
mdp3_session = (struct mdp3_session_data *)mfd->mdp.private1;
+ frame_rate = mdss_panel_get_framerate(panel_info, FPS_RESOLUTION_HZ);
vbp = panel_info->lcdc.v_back_porch;
vfp = panel_info->lcdc.v_front_porch;
vspw = panel_info->lcdc.v_pulse_width;
@@ -814,7 +861,7 @@
sourceConfig.stride = fix->line_length;
}
- te.frame_rate = panel_info->mipi.frame_rate;
+ te.frame_rate = frame_rate;
te.hw_vsync_mode = panel_info->mipi.hw_vsync_mode;
te.tear_check_en = panel_info->te.tear_check_en;
te.sync_cfg_height = panel_info->te.sync_cfg_height;
@@ -1003,6 +1050,7 @@
static int mdp3_ctrl_off(struct msm_fb_data_type *mfd)
{
int rc = 0;
+ int client = 0;
bool intf_stopped = true;
struct mdp3_session_data *mdp3_session;
struct mdss_panel_data *panel;
@@ -1156,10 +1204,11 @@
pr_err("%s: pm_runtime_put failed (rc %d)\n",
__func__, rc);
}
- mdp3_bufq_deinit(&mdp3_session->bufq_out);
+ client = mdp3_get_ion_client(mfd);
+ mdp3_bufq_deinit(&mdp3_session->bufq_out, client);
if (mdp3_session->overlay.id != MSMFB_NEW_REQUEST) {
mdp3_session->overlay.id = MSMFB_NEW_REQUEST;
- mdp3_bufq_deinit(&mdp3_session->bufq_in);
+ mdp3_bufq_deinit(&mdp3_session->bufq_in, client);
}
}
@@ -1189,6 +1238,10 @@
mdp3_ctrl_clk_enable(mdp3_session->mfd, 0);
}
off_error:
+ if (mdp3_session->overlay.id != MSMFB_NEW_REQUEST) {
+ mdp3_session->overlay.id = MSMFB_NEW_REQUEST;
+ mdp3_bufq_deinit(&mdp3_session->bufq_in, client);
+ }
MDSS_XLOG(XLOG_FUNC_EXIT, __LINE__);
mutex_unlock(&mdp3_session->lock);
/* Release the last reference to the runtime device */
@@ -1336,14 +1389,16 @@
struct fb_info *fbi = mfd->fbi;
struct fb_fix_screeninfo *fix;
int format;
+ int client;
fix = &fbi->fix;
format = mdp3_ctrl_get_source_format(mfd->fb_imgType);
mutex_lock(&mdp3_session->lock);
+ client = mdp3_get_ion_client(mfd);
if (mdp3_session->overlay.id == ndx && ndx == 1) {
mdp3_session->overlay.id = MSMFB_NEW_REQUEST;
- mdp3_bufq_deinit(&mdp3_session->bufq_in);
+ mdp3_bufq_deinit(&mdp3_session->bufq_in, client);
} else {
rc = -EINVAL;
}
@@ -1362,18 +1417,20 @@
struct msmfb_data *img = &req->data;
struct mdp3_img_data data;
struct mdp3_dma *dma = mdp3_session->dma;
+ int client;
+ client = mdp3_get_ion_client(mfd);
memset(&data, 0, sizeof(struct mdp3_img_data));
- if (mfd->panel.type == MIPI_CMD_PANEL)
+ if (mfd->panel.type == MIPI_CMD_PANEL || client == MDP3_CLIENT_SPI)
is_panel_type_cmd = true;
if (is_panel_type_cmd) {
- rc = mdp3_iommu_enable(MDP3_CLIENT_DMA_P);
+ rc = mdp3_iommu_enable(client);
if (rc) {
pr_err("fail to enable iommu\n");
return rc;
}
}
- rc = mdp3_get_img(img, &data, MDP3_CLIENT_DMA_P);
+ rc = mdp3_get_img(img, &data, client);
if (rc) {
pr_err("fail to get overlay buffer\n");
goto err;
@@ -1383,14 +1440,14 @@
pr_err("buf size(0x%lx) is smaller than dma config(0x%x)\n",
data.len, (dma->source_config.stride *
dma->source_config.height));
- mdp3_put_img(&data, MDP3_CLIENT_DMA_P);
+ mdp3_put_img(&data, client);
rc = -EINVAL;
goto err;
}
rc = mdp3_bufq_push(&mdp3_session->bufq_in, &data);
if (rc) {
pr_err("fail to queue the overlay buffer, buffer drop\n");
- mdp3_put_img(&data, MDP3_CLIENT_DMA_P);
+ mdp3_put_img(&data, client);
goto err;
}
rc = 0;
@@ -1449,8 +1506,11 @@
struct mdp3_img_data *data;
struct mdss_panel_info *panel_info;
int rc = 0;
+ int client;
static bool splash_done;
struct mdss_panel_data *panel;
+ int frame_rate = DEFAULT_FRAME_RATE;
+ int stride;
if (!mfd || !mfd->mdp.private1)
return -EINVAL;
@@ -1460,6 +1520,9 @@
if (!mdp3_session || !mdp3_session->dma)
return -EINVAL;
+ frame_rate = mdss_panel_get_framerate(panel_info, FPS_RESOLUTION_HZ);
+ client = mdp3_get_ion_client(mfd);
+
if (mdp3_bufq_count(&mdp3_session->bufq_in) == 0) {
pr_debug("no buffer in queue yet\n");
return -EPERM;
@@ -1510,7 +1573,17 @@
if (data) {
mdp3_ctrl_reset_countdown(mdp3_session, mfd);
mdp3_ctrl_clk_enable(mfd, 1);
- if (mdp3_session->dma->update_src_cfg &&
+ stride = mdp3_session->dma->source_config.stride;
+ if (mdp3_ctrl_get_intf_type(mfd) ==
+ MDP3_DMA_OUTPUT_SEL_SPI_CMD){
+ mdp3_session->intf->active = false;
+ msm_ion_do_cache_op(mdp3_res->ion_client,
+ data->srcp_ihdl, (void *)(int)data->addr,
+ data->len, ION_IOC_INV_CACHES);
+ rc = mdss_spi_panel_kickoff(mdp3_session->panel,
+ (void *)(int)data->addr, (int)data->len,
+ stride);
+ } else if (mdp3_session->dma->update_src_cfg &&
panel_info->partial_update_enabled) {
panel->panel_info.roi.x = mdp3_session->dma->roi.x;
panel->panel_info.roi.y = mdp3_session->dma->roi.y;
@@ -1530,7 +1603,9 @@
MDP_NOTIFY_FRAME_TIMEOUT);
} else {
if (mdp3_ctrl_get_intf_type(mfd) ==
- MDP3_DMA_OUTPUT_SEL_DSI_VIDEO) {
+ MDP3_DMA_OUTPUT_SEL_DSI_VIDEO ||
+ mdp3_ctrl_get_intf_type(mfd) ==
+ MDP3_DMA_OUTPUT_SEL_SPI_CMD) {
mdp3_ctrl_notify(mdp3_session,
MDP_NOTIFY_FRAME_DONE);
}
@@ -1545,16 +1620,16 @@
mdp3_release_splash_memory(mfd);
data = mdp3_bufq_pop(&mdp3_session->bufq_out);
if (data)
- mdp3_put_img(data, MDP3_CLIENT_DMA_P);
+ mdp3_put_img(data, client);
}
if (mdp3_session->first_commit) {
/*wait to ensure frame is sent to panel*/
if (panel_info->mipi.post_init_delay)
- msleep(((1000 / panel_info->mipi.frame_rate) + 1) *
+ msleep(((1000 / frame_rate) + 1) *
panel_info->mipi.post_init_delay);
else
- msleep(1000 / panel_info->mipi.frame_rate);
+ msleep((1000 / frame_rate) + 1);
mdp3_session->first_commit = false;
if (panel)
rc |= panel->event_handler(panel,
@@ -1569,6 +1644,12 @@
mdp3_session->esd_recovery = false;
}
+ /*Update backlight only if its changed*/
+ if (mdp3_res->bklt_level && mdp3_res->bklt_update) {
+ mdss_spi_panel_bl_ctrl_update(panel, mdp3_res->bklt_level);
+ mdp3_res->bklt_update = false;
+ }
+
/* start vsync tick countdown for cmd mode if vsync isn't enabled */
if (mfd->panel.type == MIPI_CMD_PANEL && !mdp3_session->vsync_enabled)
mdp3_ctrl_vsync_enable(mdp3_session->mfd, 0);
@@ -1695,17 +1776,18 @@
}
panel = mdp3_session->panel;
- if (mdp3_session->first_commit) {
- /*wait to ensure frame is sent to panel*/
- if (panel_info->mipi.post_init_delay)
- msleep(((1000 / panel_info->mipi.frame_rate) + 1) *
- panel_info->mipi.post_init_delay);
- else
- msleep(1000 / panel_info->mipi.frame_rate);
- mdp3_session->first_commit = false;
- if (panel)
- panel->event_handler(panel, MDSS_EVENT_POST_PANEL_ON,
- NULL);
+ if (mdp3_ctrl_get_intf_type(mfd) != MDP3_DMA_OUTPUT_SEL_SPI_CMD) {
+ if (mdp3_session->first_commit) {
+ if (panel_info->mipi.init_delay)
+ msleep(((1000 / panel_info->mipi.frame_rate)
+ + 1) * panel_info->mipi.post_init_delay);
+ else
+ msleep(1000 / panel_info->mipi.frame_rate);
+ mdp3_session->first_commit = false;
+ if (panel)
+ panel->event_handler(panel,
+ MDSS_EVENT_POST_PANEL_ON, NULL);
+ }
}
mdp3_session->vsync_before_commit = 0;
@@ -1716,6 +1798,11 @@
mdp3_session->esd_recovery = false;
}
+ /*Update backlight only if its changed*/
+ if (mdp3_res->bklt_level && mdp3_res->bklt_update) {
+ mdss_spi_panel_bl_ctrl_update(panel, mdp3_res->bklt_level);
+ mdp3_res->bklt_update = false;
+ }
pan_error:
mutex_unlock(&mdp3_session->lock);
@@ -1756,7 +1843,8 @@
switch (metadata->op) {
case metadata_op_frame_rate:
metadata->data.panel_frame_rate =
- mfd->panel_info->mipi.frame_rate;
+ mdss_panel_get_framerate(mfd->panel_info,
+ FPS_RESOLUTION_HZ);
break;
case metadata_op_get_caps:
metadata->data.caps.mdp_rev = 305;
@@ -2893,6 +2981,7 @@
struct msm_mdp_interface *mdp3_interface = &mfd->mdp;
struct mdp3_session_data *mdp3_session = NULL;
u32 intf_type = MDP3_DMA_OUTPUT_SEL_DSI_VIDEO;
+ int frame_rate = DEFAULT_FRAME_RATE;
int rc;
int splash_mismatch = 0;
struct sched_param sched = { .sched_priority = 16 };
@@ -2902,6 +2991,8 @@
if (rc)
splash_mismatch = 1;
+ frame_rate = mdss_panel_get_framerate(mfd->panel_info,
+ FPS_RESOLUTION_HZ);
mdp3_interface->on_fnc = mdp3_ctrl_on;
mdp3_interface->off_fnc = mdp3_ctrl_off;
mdp3_interface->do_histogram = NULL;
@@ -2980,10 +3071,11 @@
init_timer(&mdp3_session->vsync_timer);
mdp3_session->vsync_timer.function = mdp3_vsync_timer_func;
mdp3_session->vsync_timer.data = (u32)mdp3_session;
- mdp3_session->vsync_period = 1000 / mfd->panel_info->mipi.frame_rate;
+ mdp3_session->vsync_period = 1000 / frame_rate;
mfd->mdp.private1 = mdp3_session;
init_completion(&mdp3_session->dma_completion);
- if (intf_type != MDP3_DMA_OUTPUT_SEL_DSI_VIDEO)
+ if (intf_type != MDP3_DMA_OUTPUT_SEL_DSI_VIDEO ||
+ intf_type != MDP3_DMA_OUTPUT_SEL_SPI_CMD)
mdp3_session->wait_for_dma_done = mdp3_wait_for_dma_done;
rc = sysfs_create_group(&dev->kobj, &vsync_fs_attr_group);
diff --git a/drivers/video/fbdev/msm/mdp3_ctrl.h b/drivers/video/fbdev/msm/mdp3_ctrl.h
index b7b667b..5193af1 100644
--- a/drivers/video/fbdev/msm/mdp3_ctrl.h
+++ b/drivers/video/fbdev/msm/mdp3_ctrl.h
@@ -84,12 +84,13 @@
struct work_struct retire_work;
};
-void mdp3_bufq_deinit(struct mdp3_buffer_queue *bufq);
+void mdp3_bufq_deinit(struct mdp3_buffer_queue *bufq, int client);
int mdp3_ctrl_init(struct msm_fb_data_type *mfd);
int mdp3_bufq_push(struct mdp3_buffer_queue *bufq,
struct mdp3_img_data *data);
int mdp3_ctrl_get_source_format(u32 imgType);
int mdp3_ctrl_get_pack_pattern(u32 imgType);
int mdp3_ctrl_reset(struct msm_fb_data_type *mfd);
+int mdp3_get_ion_client(struct msm_fb_data_type *mfd);
#endif /* MDP3_CTRL_H */
diff --git a/drivers/video/fbdev/msm/mdp3_dma.c b/drivers/video/fbdev/msm/mdp3_dma.c
index 71fcbf9..b223c87 100644
--- a/drivers/video/fbdev/msm/mdp3_dma.c
+++ b/drivers/video/fbdev/msm/mdp3_dma.c
@@ -114,7 +114,8 @@
}
if (dma->output_config.out_sel == MDP3_DMA_OUTPUT_SEL_DSI_VIDEO ||
- dma->output_config.out_sel == MDP3_DMA_OUTPUT_SEL_LCDC) {
+ dma->output_config.out_sel == MDP3_DMA_OUTPUT_SEL_LCDC ||
+ dma->output_config.out_sel == MDP3_DMA_OUTPUT_SEL_SPI_CMD) {
if (type & MDP3_DMA_CALLBACK_TYPE_VSYNC)
mdp3_irq_enable(MDP3_INTR_LCDC_START_OF_FRAME);
} else if (dma->output_config.out_sel == MDP3_DMA_OUTPUT_SEL_DSI_CMD) {
@@ -150,7 +151,8 @@
}
if (dma->output_config.out_sel == MDP3_DMA_OUTPUT_SEL_DSI_VIDEO ||
- dma->output_config.out_sel == MDP3_DMA_OUTPUT_SEL_LCDC) {
+ dma->output_config.out_sel == MDP3_DMA_OUTPUT_SEL_LCDC ||
+ dma->output_config.out_sel == MDP3_DMA_OUTPUT_SEL_SPI_CMD) {
if (type & MDP3_DMA_CALLBACK_TYPE_VSYNC)
mdp3_irq_disable(MDP3_INTR_LCDC_START_OF_FRAME);
} else if (dma->output_config.out_sel == MDP3_DMA_OUTPUT_SEL_DSI_CMD) {
@@ -1268,6 +1270,22 @@
return 0;
}
+static int spi_cmd_config(struct mdp3_intf *intf, struct mdp3_intf_cfg *cfg)
+{
+ return 0;
+}
+
+static int spi_cmd_start(struct mdp3_intf *intf)
+{
+ intf->active = true;
+ return 0;
+}
+
+static int spi_cmd_stop(struct mdp3_intf *intf)
+{
+ intf->active = false;
+ return 0;
+}
int mdp3_intf_init(struct mdp3_intf *intf)
{
switch (intf->cfg.type) {
@@ -1286,6 +1304,11 @@
intf->start = dsi_cmd_start;
intf->stop = dsi_cmd_stop;
break;
+ case MDP3_DMA_OUTPUT_SEL_SPI_CMD:
+ intf->config = spi_cmd_config;
+ intf->start = spi_cmd_start;
+ intf->stop = spi_cmd_stop;
+ break;
default:
return -EINVAL;
diff --git a/drivers/video/fbdev/msm/mdp3_dma.h b/drivers/video/fbdev/msm/mdp3_dma.h
index 24caedb9..ec327b6 100644
--- a/drivers/video/fbdev/msm/mdp3_dma.h
+++ b/drivers/video/fbdev/msm/mdp3_dma.h
@@ -47,6 +47,7 @@
MDP3_DMA_OUTPUT_SEL_DSI_CMD,
MDP3_DMA_OUTPUT_SEL_LCDC,
MDP3_DMA_OUTPUT_SEL_DSI_VIDEO,
+ MDP3_DMA_OUTPUT_SEL_SPI_CMD,
MDP3_DMA_OUTPUT_SEL_MAX
};
diff --git a/drivers/video/fbdev/msm/mdp3_layer.c b/drivers/video/fbdev/msm/mdp3_layer.c
index 0078466..98b5c19 100644
--- a/drivers/video/fbdev/msm/mdp3_layer.c
+++ b/drivers/video/fbdev/msm/mdp3_layer.c
@@ -197,6 +197,7 @@
struct msmfb_data img;
bool is_panel_type_cmd = false;
struct mdp3_img_data data;
+ int intf_type;
int rc = 0;
layer = &input_layer[0];
@@ -208,23 +209,24 @@
goto err;
}
+ intf_type = mdp3_get_ion_client(mfd);
memset(&img, 0, sizeof(img));
img.memory_id = buffer->planes[0].fd;
img.offset = buffer->planes[0].offset;
memset(&data, 0, sizeof(struct mdp3_img_data));
- if (mfd->panel.type == MIPI_CMD_PANEL)
+ if (mfd->panel.type == MIPI_CMD_PANEL || intf_type == MDP3_CLIENT_SPI)
is_panel_type_cmd = true;
if (is_panel_type_cmd) {
- rc = mdp3_iommu_enable(MDP3_CLIENT_DMA_P);
+ rc = mdp3_iommu_enable(intf_type);
if (rc) {
pr_err("fail to enable iommu\n");
return rc;
}
}
- rc = mdp3_get_img(&img, &data, MDP3_CLIENT_DMA_P);
+ rc = mdp3_get_img(&img, &data, intf_type);
if (rc) {
pr_err("fail to get overlay buffer\n");
goto err;
@@ -260,7 +262,7 @@
struct mdp3_session_data *mdp3_session;
struct mdp3_dma *dma;
int layer_count = commit->input_layer_cnt;
- int stride, format;
+ int stride, format, client;
/* Handle NULL commit */
if (!layer_count) {
@@ -273,7 +275,8 @@
mutex_lock(&mdp3_session->lock);
- mdp3_bufq_deinit(&mdp3_session->bufq_in);
+ client = mdp3_get_ion_client(mfd);
+ mdp3_bufq_deinit(&mdp3_session->bufq_in, client);
layer_list = commit->input_layers;
layer = &layer_list[0];
diff --git a/drivers/video/fbdev/msm/mdp3_ppp.c b/drivers/video/fbdev/msm/mdp3_ppp.c
index 3391059..5459510 100644
--- a/drivers/video/fbdev/msm/mdp3_ppp.c
+++ b/drivers/video/fbdev/msm/mdp3_ppp.c
@@ -542,6 +542,7 @@
{
struct mdss_panel_info *panel_info = mfd->panel_info;
int i, lcount = 0;
+ int frame_rate = DEFAULT_FRAME_RATE;
struct mdp_blit_req *req;
struct bpp_info bpp;
u64 old_solid_fill_pixel = 0;
@@ -556,6 +557,7 @@
ATRACE_BEGIN(__func__);
lcount = lreq->count;
+ frame_rate = mdss_panel_get_framerate(panel_info, FPS_RESOLUTION_HZ);
if (lcount == 0) {
pr_err("Blit with request count 0, continue to recover!!!\n");
ATRACE_END(__func__);
@@ -583,11 +585,11 @@
is_blit_optimization_possible(lreq, i);
req = &(lreq->req_list[i]);
- if (req->fps > 0 && req->fps <= panel_info->mipi.frame_rate) {
+ if (req->fps > 0 && req->fps <= frame_rate) {
if (fps == 0)
fps = req->fps;
else
- fps = panel_info->mipi.frame_rate;
+ fps = frame_rate;
}
mdp3_get_bpp_info(req->src.format, &bpp);
@@ -645,7 +647,7 @@
}
if (fps == 0)
- fps = panel_info->mipi.frame_rate;
+ fps = frame_rate;
if (lreq->req_list[0].flags & MDP_SOLID_FILL) {
honest_ppp_ab = ppp_res.solid_fill_byte * 4;
diff --git a/drivers/video/fbdev/msm/mdp3_ppp_data.c b/drivers/video/fbdev/msm/mdp3_ppp_data.c
index ac88d9b..dd2cce0 100644
--- a/drivers/video/fbdev/msm/mdp3_ppp_data.c
+++ b/drivers/video/fbdev/msm/mdp3_ppp_data.c
@@ -89,8 +89,8 @@
};
const uint32_t swapped_pack_patt_lut[MDP_IMGTYPE_LIMIT] = {
- [MDP_RGB_565] = PPP_GET_PACK_PATTERN(0, CLR_B, CLR_G, CLR_R, 8),
- [MDP_BGR_565] = PPP_GET_PACK_PATTERN(0, CLR_R, CLR_G, CLR_B, 8),
+ [MDP_RGB_565] = PPP_GET_PACK_PATTERN(0, CLR_R, CLR_G, CLR_B, 8),
+ [MDP_BGR_565] = PPP_GET_PACK_PATTERN(0, CLR_B, CLR_G, CLR_R, 8),
[MDP_RGB_888] = PPP_GET_PACK_PATTERN(0, CLR_B, CLR_G, CLR_R, 8),
[MDP_BGR_888] = PPP_GET_PACK_PATTERN(0, CLR_R, CLR_G, CLR_B, 8),
[MDP_BGRA_8888] = PPP_GET_PACK_PATTERN(CLR_ALPHA, CLR_R,
diff --git a/drivers/video/fbdev/msm/mdss.h b/drivers/video/fbdev/msm/mdss.h
index e6d55b5..6fa7906 100644
--- a/drivers/video/fbdev/msm/mdss.h
+++ b/drivers/video/fbdev/msm/mdss.h
@@ -163,6 +163,7 @@
MDSS_QUIRK_NEED_SECURE_MAP,
MDSS_QUIRK_SRC_SPLIT_ALWAYS,
MDSS_QUIRK_HDR_SUPPORT_ENABLED,
+ MDSS_QUIRK_MDP_CLK_SET_RATE,
MDSS_QUIRK_MAX,
};
@@ -289,6 +290,7 @@
u32 max_mdp_clk_rate;
struct mdss_util_intf *mdss_util;
struct mdss_panel_data *pdata;
+ unsigned long mdp_clk_rate;
struct platform_device *pdev;
struct mdss_io_data mdss_io;
@@ -414,6 +416,7 @@
u32 enable_gate;
u32 enable_bw_release;
u32 enable_rotator_bw_release;
+ u32 enable_cdp;
u32 serialize_wait4pp;
u32 wait4autorefresh;
u32 lines_before_active;
@@ -466,6 +469,7 @@
u32 nmax_concurrent_ad_hw;
struct workqueue_struct *ad_calc_wq;
u32 ad_debugen;
+ bool mem_retain;
struct mdss_intr hist_intr;
@@ -522,6 +526,7 @@
u32 splash_intf_sel;
u32 splash_split_disp;
+ struct mult_factor bus_throughput_factor;
};
extern struct mdss_data_type *mdss_res;
diff --git a/drivers/video/fbdev/msm/mdss_compat_utils.c b/drivers/video/fbdev/msm/mdss_compat_utils.c
index 9a9f5e4..a81f149 100644
--- a/drivers/video/fbdev/msm/mdss_compat_utils.c
+++ b/drivers/video/fbdev/msm/mdss_compat_utils.c
@@ -129,6 +129,7 @@
commit32->commit_v1.input_layer_cnt;
commit->commit_v1.left_roi = commit32->commit_v1.left_roi;
commit->commit_v1.right_roi = commit32->commit_v1.right_roi;
+ commit->commit_v1.bl_level = commit32->commit_v1.bl_level;
memcpy(&commit->commit_v1.reserved, &commit32->commit_v1.reserved,
count);
}
diff --git a/drivers/video/fbdev/msm/mdss_compat_utils.h b/drivers/video/fbdev/msm/mdss_compat_utils.h
index ebae393..819106b 100644
--- a/drivers/video/fbdev/msm/mdss_compat_utils.h
+++ b/drivers/video/fbdev/msm/mdss_compat_utils.h
@@ -539,6 +539,7 @@
compat_caddr_t dest_scaler;
uint32_t dest_scaler_cnt;
compat_caddr_t frc_info;
+ uint32_t bl_level; /* BL level to be updated in commit */
uint32_t reserved[MDP_LAYER_COMMIT_V1_PAD];
};
diff --git a/drivers/video/fbdev/msm/mdss_debug.c b/drivers/video/fbdev/msm/mdss_debug.c
index 7d07040..86f3bce 100644
--- a/drivers/video/fbdev/msm/mdss_debug.c
+++ b/drivers/video/fbdev/msm/mdss_debug.c
@@ -1109,7 +1109,7 @@
struct mdss_data_type *mdata = file->private_data;
struct mdss_max_bw_settings *temp_settings;
int len = 0, i;
- char buf[256];
+ char buf[256] = {'\0'};
if (!mdata)
return -ENODEV;
diff --git a/drivers/video/fbdev/msm/mdss_debug_xlog.c b/drivers/video/fbdev/msm/mdss_debug_xlog.c
index 7bf4f11..ed00fc5 100644
--- a/drivers/video/fbdev/msm/mdss_debug_xlog.c
+++ b/drivers/video/fbdev/msm/mdss_debug_xlog.c
@@ -93,6 +93,48 @@
(flag == MDSS_XLOG_ALL && mdss_dbg_xlog.xlog_enable);
}
+static void __halt_vbif_xin(void)
+{
+ struct mdss_data_type *mdata = mdss_mdp_get_mdata();
+
+ pr_err("Halting VBIF-XIN\n");
+ MDSS_VBIF_WRITE(mdata, MMSS_VBIF_XIN_HALT_CTRL0, 0xFFFFFFFF, false);
+}
+
+static void __halt_vbif_axi(void)
+{
+ struct mdss_data_type *mdata = mdss_mdp_get_mdata();
+
+ pr_err("Halting VBIF-AXI\n");
+ MDSS_VBIF_WRITE(mdata, MMSS_VBIF_AXI_HALT_CTRL0, 0xFFFFFFFF, false);
+}
+
+static void __dump_vbif_state(void)
+{
+ struct mdss_data_type *mdata = mdss_mdp_get_mdata();
+ unsigned int reg_vbif_src_err, reg_vbif_err_info,
+ reg_vbif_xin_halt_ctrl0, reg_vbif_xin_halt_ctrl1,
+ reg_vbif_axi_halt_ctrl0, reg_vbif_axi_halt_ctrl1;
+
+ reg_vbif_src_err = MDSS_VBIF_READ(mdata,
+ MMSS_VBIF_SRC_ERR, false);
+ reg_vbif_err_info = MDSS_VBIF_READ(mdata,
+ MMSS_VBIF_ERR_INFO, false);
+ reg_vbif_xin_halt_ctrl0 = MDSS_VBIF_READ(mdata,
+ MMSS_VBIF_XIN_HALT_CTRL0, false);
+ reg_vbif_xin_halt_ctrl1 = MDSS_VBIF_READ(mdata,
+ MMSS_VBIF_XIN_HALT_CTRL1, false);
+ reg_vbif_axi_halt_ctrl0 = MDSS_VBIF_READ(mdata,
+ MMSS_VBIF_AXI_HALT_CTRL0, false);
+ reg_vbif_axi_halt_ctrl1 = MDSS_VBIF_READ(mdata,
+ MMSS_VBIF_AXI_HALT_CTRL1, false);
+ pr_err("VBIF SRC_ERR=%x, ERR_INFO=%x\n",
+ reg_vbif_src_err, reg_vbif_err_info);
+ pr_err("VBIF XIN_HALT_CTRL0=%x, XIN_HALT_CTRL1=%x, AXI_HALT_CTRL0=%x, AXI_HALT_CTRL1=%x\n"
+ , reg_vbif_xin_halt_ctrl0, reg_vbif_xin_halt_ctrl1,
+ reg_vbif_axi_halt_ctrl0, reg_vbif_axi_halt_ctrl1);
+}
+
void mdss_xlog(const char *name, int line, int flag, ...)
{
unsigned long flags;
@@ -604,8 +646,17 @@
mdss_dump_dsi_debug_bus(mdss_dbg_xlog.enable_dsi_dbgbus_dump,
&mdss_dbg_xlog.dsi_dbgbus_dump);
- if (dead && mdss_dbg_xlog.panic_on_err)
+ if (dead && mdss_dbg_xlog.panic_on_err) {
+ mdss_mdp_clk_ctrl(MDP_BLOCK_POWER_ON);
+ __dump_vbif_state();
+ __halt_vbif_xin();
+ usleep_range(10000, 10010);
+ __halt_vbif_axi();
+ usleep_range(10000, 10010);
+ __dump_vbif_state();
+ mdss_mdp_clk_ctrl(MDP_BLOCK_POWER_OFF);
panic(name);
+ }
}
static void xlog_debug_work(struct work_struct *work)
diff --git a/drivers/video/fbdev/msm/mdss_dsi.c b/drivers/video/fbdev/msm/mdss_dsi.c
index 816eed0..b4e4bdd 100644
--- a/drivers/video/fbdev/msm/mdss_dsi.c
+++ b/drivers/video/fbdev/msm/mdss_dsi.c
@@ -383,6 +383,14 @@
ret = 0;
}
+ if (gpio_is_valid(ctrl_pdata->vdd_ext_gpio)) {
+ ret = gpio_direction_output(
+ ctrl_pdata->vdd_ext_gpio, 0);
+ if (ret)
+ pr_err("%s: unable to set dir for vdd gpio\n",
+ __func__);
+ }
+
if (mdss_dsi_pinctrl_set_state(ctrl_pdata, false))
pr_debug("reset disable: pinctrl not enabled\n");
@@ -410,6 +418,15 @@
ctrl_pdata = container_of(pdata, struct mdss_dsi_ctrl_pdata,
panel_data);
+ if (gpio_is_valid(ctrl_pdata->vdd_ext_gpio)) {
+ ret = gpio_direction_output(
+ ctrl_pdata->vdd_ext_gpio, 1);
+ usleep_range(3000, 4000); /* h/w recommended delay */
+ if (ret)
+ pr_err("%s: unable to set dir for vdd gpio\n",
+ __func__);
+ }
+
ret = msm_mdss_enable_vreg(
ctrl_pdata->panel_power_data.vreg_config,
ctrl_pdata->panel_power_data.num_vreg, 1);
@@ -3263,6 +3280,7 @@
struct mdss_util_intf *util;
static int te_irq_registered;
struct mdss_panel_data *pdata;
+ struct mdss_panel_cfg *pan_cfg = NULL;
if (!pdev || !pdev->dev.of_node) {
pr_err("%s: pdev not found for DSI controller\n", __func__);
@@ -3295,6 +3313,14 @@
return -ENODEV;
}
+ pan_cfg = util->panel_intf_type(MDSS_PANEL_INTF_SPI);
+ if (IS_ERR(pan_cfg)) {
+ return PTR_ERR(pan_cfg);
+ } else if (pan_cfg) {
+ pr_debug("%s: SPI is primary\n", __func__);
+ return -ENODEV;
+ }
+
ctrl_pdata->mdss_util = util;
atomic_set(&ctrl_pdata->te_irq_ready, 0);
@@ -4183,6 +4209,11 @@
of_property_read_bool(ctrl_pdev->dev.of_node,
"qcom,platform-bklight-en-gpio-invert");
+ ctrl_pdata->vdd_ext_gpio = of_get_named_gpio(ctrl_pdev->dev.of_node,
+ "qcom,ext-vdd-gpio", 0);
+ if (!gpio_is_valid(ctrl_pdata->vdd_ext_gpio))
+ pr_info("%s: ext vdd gpio not specified\n", __func__);
+
ctrl_pdata->rst_gpio = of_get_named_gpio(ctrl_pdev->dev.of_node,
"qcom,platform-reset-gpio", 0);
if (!gpio_is_valid(ctrl_pdata->rst_gpio))
diff --git a/drivers/video/fbdev/msm/mdss_dsi.h b/drivers/video/fbdev/msm/mdss_dsi.h
index 2ff2951..5d2d677 100644
--- a/drivers/video/fbdev/msm/mdss_dsi.h
+++ b/drivers/video/fbdev/msm/mdss_dsi.h
@@ -435,6 +435,7 @@
int rst_gpio;
int disp_en_gpio;
int bklt_en_gpio;
+ int vdd_ext_gpio;
int mode_gpio;
int intf_mux_gpio;
bool bklt_en_gpio_invert;
diff --git a/drivers/video/fbdev/msm/mdss_dsi_host.c b/drivers/video/fbdev/msm/mdss_dsi_host.c
index e221c1c..751a463 100644
--- a/drivers/video/fbdev/msm/mdss_dsi_host.c
+++ b/drivers/video/fbdev/msm/mdss_dsi_host.c
@@ -2277,7 +2277,7 @@
u32 *lp, *temp, data;
int i, j = 0, off, cnt;
bool ack_error = false;
- char reg[16];
+ char reg[16] = {0x0};
int repeated_bytes = 0;
struct mdss_dsi_ctrl_pdata *mctrl = mdss_dsi_get_other_ctrl(ctrl);
diff --git a/drivers/video/fbdev/msm/mdss_dsi_panel.c b/drivers/video/fbdev/msm/mdss_dsi_panel.c
index 85ed42e..cde2bc3 100644
--- a/drivers/video/fbdev/msm/mdss_dsi_panel.c
+++ b/drivers/video/fbdev/msm/mdss_dsi_panel.c
@@ -326,6 +326,15 @@
goto bklt_en_gpio_err;
}
}
+ if (gpio_is_valid(ctrl_pdata->vdd_ext_gpio)) {
+ rc = gpio_request(ctrl_pdata->vdd_ext_gpio,
+ "vdd_enable");
+ if (rc) {
+ pr_err("request vdd enable gpio failed, rc=%d\n",
+ rc);
+ goto vdd_en_gpio_err;
+ }
+ }
if (gpio_is_valid(ctrl_pdata->mode_gpio)) {
rc = gpio_request(ctrl_pdata->mode_gpio, "panel_mode");
if (rc) {
@@ -337,6 +346,9 @@
return rc;
mode_gpio_err:
+ if (gpio_is_valid(ctrl_pdata->vdd_ext_gpio))
+ gpio_free(ctrl_pdata->vdd_ext_gpio);
+vdd_en_gpio_err:
if (gpio_is_valid(ctrl_pdata->bklt_en_gpio))
gpio_free(ctrl_pdata->bklt_en_gpio);
bklt_en_gpio_err:
@@ -1052,6 +1064,48 @@
return 0;
}
+static void mdss_dsi_parse_mdp_kickoff_threshold(struct device_node *np,
+ struct mdss_panel_info *pinfo)
+{
+ int len, rc;
+ const u32 *src;
+ u32 tmp;
+ u32 max_delay_us;
+
+ pinfo->mdp_koff_thshold = false;
+ src = of_get_property(np, "qcom,mdss-mdp-kickoff-threshold", &len);
+ if (!src || (len == 0))
+ return;
+
+ rc = of_property_read_u32(np, "qcom,mdss-mdp-kickoff-delay", &tmp);
+ if (!rc)
+ pinfo->mdp_koff_delay = tmp;
+ else
+ return;
+
+ if (pinfo->mipi.frame_rate == 0) {
+ pr_err("cannot enable guard window, unexpected panel fps\n");
+ return;
+ }
+
+ pinfo->mdp_koff_thshold_low = be32_to_cpu(src[0]);
+ pinfo->mdp_koff_thshold_high = be32_to_cpu(src[1]);
+ max_delay_us = 1000000 / pinfo->mipi.frame_rate;
+
+ /* enable the feature if threshold is valid */
+ if ((pinfo->mdp_koff_thshold_low < pinfo->mdp_koff_thshold_high) &&
+ ((pinfo->mdp_koff_delay > 0) ||
+ (pinfo->mdp_koff_delay < max_delay_us)))
+ pinfo->mdp_koff_thshold = true;
+
+ pr_debug("panel kickoff thshold:[%d, %d] delay:%d (max:%d) enable:%d\n",
+ pinfo->mdp_koff_thshold_low,
+ pinfo->mdp_koff_thshold_high,
+ pinfo->mdp_koff_delay,
+ max_delay_us,
+ pinfo->mdp_koff_thshold);
+}
+
static void mdss_dsi_parse_trigger(struct device_node *np, char *trigger,
char *trigger_key)
{
@@ -2833,6 +2887,8 @@
rc = of_property_read_u32(np, "qcom,mdss-mdp-transfer-time-us", &tmp);
pinfo->mdp_transfer_time_us = (!rc ? tmp : DEFAULT_MDP_TRANSFER_TIME);
+ mdss_dsi_parse_mdp_kickoff_threshold(np, pinfo);
+
pinfo->mipi.lp11_init = of_property_read_bool(np,
"qcom,mdss-dsi-lp11-init");
rc = of_property_read_u32(np, "qcom,mdss-dsi-init-delay-us", &tmp);
diff --git a/drivers/video/fbdev/msm/mdss_dsi_status.c b/drivers/video/fbdev/msm/mdss_dsi_status.c
index c5af962..326768d 100644
--- a/drivers/video/fbdev/msm/mdss_dsi_status.c
+++ b/drivers/video/fbdev/msm/mdss_dsi_status.c
@@ -146,15 +146,18 @@
return NOTIFY_DONE;
mfd = evdata->info->par;
- ctrl_pdata = container_of(dev_get_platdata(&mfd->pdev->dev),
+ if (mfd->panel_info->type == SPI_PANEL) {
+ pinfo = mfd->panel_info;
+ } else {
+ ctrl_pdata = container_of(dev_get_platdata(&mfd->pdev->dev),
struct mdss_dsi_ctrl_pdata, panel_data);
- if (!ctrl_pdata) {
- pr_err("%s: DSI ctrl not available\n", __func__);
- return NOTIFY_BAD;
+ if (!ctrl_pdata) {
+ pr_err("%s: DSI ctrl not available\n", __func__);
+ return NOTIFY_BAD;
+ }
+
+ pinfo = &ctrl_pdata->panel_data.panel_info;
}
-
- pinfo = &ctrl_pdata->panel_data.panel_info;
-
if ((!(pinfo->esd_check_enabled) &&
dsi_status_disable) ||
(dsi_status_disable == DSI_STATUS_CHECK_DISABLE)) {
diff --git a/drivers/video/fbdev/msm/mdss_fb.c b/drivers/video/fbdev/msm/mdss_fb.c
index 72f651e..72adb17 100644
--- a/drivers/video/fbdev/msm/mdss_fb.c
+++ b/drivers/video/fbdev/msm/mdss_fb.c
@@ -243,9 +243,11 @@
}
} else if (notify == NOTIFY_UPDATE_STOP) {
mutex_lock(&mfd->update.lock);
- if (mfd->update.init_done)
+ if (mfd->update.init_done) {
+ mutex_unlock(&mfd->update.lock);
+ mutex_lock(&mfd->no_update.lock);
reinit_completion(&mfd->no_update.comp);
- else {
+ } else {
mutex_unlock(&mfd->update.lock);
pr_err("notify update stop called without init\n");
return -EINVAL;
@@ -306,10 +308,23 @@
}
}
+static enum led_brightness mdss_fb_get_bl_brightness(
+ struct led_classdev *led_cdev)
+{
+ struct msm_fb_data_type *mfd = dev_get_drvdata(led_cdev->dev->parent);
+ u64 value;
+
+ MDSS_BL_TO_BRIGHT(value, mfd->bl_level, mfd->panel_info->bl_max,
+ mfd->panel_info->brightness_max);
+
+ return value;
+}
+
static struct led_classdev backlight_led = {
.name = "lcd-backlight",
.brightness = MDSS_MAX_BL_BRIGHTNESS / 2,
.brightness_set = mdss_fb_set_bl_brightness,
+ .brightness_get = mdss_fb_get_bl_brightness,
.max_brightness = MDSS_MAX_BL_BRIGHTNESS,
};
@@ -345,6 +360,9 @@
case EDP_PANEL:
ret = snprintf(buf, PAGE_SIZE, "edp panel\n");
break;
+ case SPI_PANEL:
+ ret = snprintf(buf, PAGE_SIZE, "spi panel\n");
+ break;
default:
ret = snprintf(buf, PAGE_SIZE, "unknown panel\n");
break;
@@ -592,7 +610,8 @@
"white_chromaticity_x=%d\nwhite_chromaticity_y=%d\n"
"red_chromaticity_x=%d\nred_chromaticity_y=%d\n"
"green_chromaticity_x=%d\ngreen_chromaticity_y=%d\n"
- "blue_chromaticity_x=%d\nblue_chromaticity_y=%d\n",
+ "blue_chromaticity_x=%d\nblue_chromaticity_y=%d\n"
+ "panel_orientation=%d\n",
pinfo->partial_update_enabled,
pinfo->roi_alignment.xstart_pix_align,
pinfo->roi_alignment.width_pix_align,
@@ -615,7 +634,8 @@
pinfo->hdr_properties.display_primaries[4],
pinfo->hdr_properties.display_primaries[5],
pinfo->hdr_properties.display_primaries[6],
- pinfo->hdr_properties.display_primaries[7]);
+ pinfo->hdr_properties.display_primaries[7],
+ pinfo->panel_orientation);
return ret;
}
@@ -885,6 +905,12 @@
return ret;
}
+static ssize_t mdss_fb_idle_pc_notify(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ return scnprintf(buf, PAGE_SIZE, "idle power collapsed\n");
+}
+
static DEVICE_ATTR(msm_fb_type, 0444, mdss_fb_get_type, NULL);
static DEVICE_ATTR(msm_fb_split, 0644, mdss_fb_show_split,
mdss_fb_store_split);
@@ -905,6 +931,8 @@
mdss_fb_get_fps_info, NULL);
static DEVICE_ATTR(msm_fb_persist_mode, 0644,
mdss_fb_get_persist_mode, mdss_fb_change_persist_mode);
+static DEVICE_ATTR(idle_power_collapse, 0444, mdss_fb_idle_pc_notify, NULL);
+
static struct attribute *mdss_fb_attrs[] = {
&dev_attr_msm_fb_type.attr,
&dev_attr_msm_fb_split.attr,
@@ -918,6 +946,7 @@
&dev_attr_msm_fb_dfps_mode.attr,
&dev_attr_measured_fps.attr,
&dev_attr_msm_fb_persist_mode.attr,
+ &dev_attr_idle_power_collapse.attr,
NULL,
};
@@ -1214,6 +1243,7 @@
struct mdss_panel_data *pdata;
struct fb_info *fbi;
int rc;
+ const char *data;
if (fbi_list_index >= MAX_FBI_LIST)
return -ENOMEM;
@@ -1259,9 +1289,25 @@
mfd->fb_imgType = MDP_RGBA_8888;
mfd->calib_mode_bl = 0;
mfd->unset_bl_level = U32_MAX;
+ mfd->bl_extn_level = -1;
mfd->pdev = pdev;
+ if (mfd->panel.type == SPI_PANEL)
+ mfd->fb_imgType = MDP_RGB_565;
+ if (mfd->panel.type == MIPI_VIDEO_PANEL || mfd->panel.type ==
+ MIPI_CMD_PANEL || mfd->panel.type == SPI_PANEL){
+ rc = of_property_read_string(pdev->dev.of_node,
+ "qcom,mdss-fb-format", &data);
+ if (!rc) {
+ if (!strcmp(data, "rgb888"))
+ mfd->fb_imgType = MDP_RGB_888;
+ else if (!strcmp(data, "rgb565"))
+ mfd->fb_imgType = MDP_RGB_565;
+ else
+ mfd->fb_imgType = MDP_RGBA_8888;
+ }
+ }
mfd->split_fb_left = mfd->split_fb_right = 0;
mdss_fb_set_split_mode(mfd, pdata);
@@ -1374,6 +1420,7 @@
mfd->mdp_sync_pt_data.threshold = 1;
mfd->mdp_sync_pt_data.retire_threshold = 0;
break;
+ case SPI_PANEL:
case MIPI_CMD_PANEL:
mfd->mdp_sync_pt_data.threshold = 1;
mfd->mdp_sync_pt_data.retire_threshold = 1;
@@ -2086,6 +2133,7 @@
}
ret = mdss_fb_blank_sub(blank_mode, info, mfd->op_enable);
+ MDSS_XLOG(blank_mode);
end:
mutex_unlock(&mfd->mdss_sysfs_lock);
@@ -2843,7 +2891,9 @@
* enabling ahead of unblank. for some special cases like
* adb shell stop/start.
*/
+ mutex_lock(&mfd->bl_lock);
mdss_fb_set_backlight(mfd, 0);
+ mutex_unlock(&mfd->bl_lock);
ret = mdss_fb_blank_sub(FB_BLANK_POWERDOWN, info,
mfd->op_enable);
@@ -3440,6 +3490,15 @@
mfd->msm_fb_backup.atomic_commit = true;
mfd->msm_fb_backup.disp_commit.l_roi = commit_v1->left_roi;
mfd->msm_fb_backup.disp_commit.r_roi = commit_v1->right_roi;
+ mfd->msm_fb_backup.disp_commit.flags = commit_v1->flags;
+ if (commit_v1->flags & MDP_COMMIT_UPDATE_BRIGHTNESS) {
+ MDSS_BRIGHT_TO_BL(mfd->bl_extn_level, commit_v1->bl_level,
+ mfd->panel_info->bl_max,
+ mfd->panel_info->brightness_max);
+ if (!mfd->bl_extn_level && commit_v1->bl_level)
+ mfd->bl_extn_level = 1;
+ } else
+ mfd->bl_extn_level = -1;
mutex_lock(&mfd->mdp_sync_pt_data.sync_mutex);
atomic_inc(&mfd->mdp_sync_pt_data.commit_cnt);
@@ -4529,6 +4588,9 @@
* In case of an ESD attack, since we early return from the
* commits, we need to signal the outstanding fences.
*/
+ mutex_lock(&mfd->mdp_sync_pt_data.sync_mutex);
+ atomic_inc(&mfd->mdp_sync_pt_data.commit_cnt);
+ mutex_unlock(&mfd->mdp_sync_pt_data.sync_mutex);
mdss_fb_release_fences(mfd);
if ((mfd->panel.type == MIPI_CMD_PANEL) &&
mfd->mdp.signal_retire_fence && mdp5_data)
@@ -5148,3 +5210,18 @@
mfd->fps_info.frame_count = 0;
}
}
+
+void mdss_fb_idle_pc(struct msm_fb_data_type *mfd)
+{
+ struct mdss_overlay_private *mdp5_data;
+
+ if (!mfd || mdss_fb_is_power_off(mfd))
+ return;
+
+ mdp5_data = mfd_to_mdp5_data(mfd);
+
+ if ((mfd->panel_info->type == MIPI_CMD_PANEL) && mdp5_data) {
+ pr_debug("Notify fb%d idle power collapsed\n", mfd->index);
+ sysfs_notify(&mfd->fbi->dev->kobj, NULL, "idle_power_collapse");
+ }
+}
diff --git a/drivers/video/fbdev/msm/mdss_fb.h b/drivers/video/fbdev/msm/mdss_fb.h
index 5f2baef..3515e37 100644
--- a/drivers/video/fbdev/msm/mdss_fb.h
+++ b/drivers/video/fbdev/msm/mdss_fb.h
@@ -245,6 +245,10 @@
out = (2 * (v) * (bl_max) + max_bright);\
do_div(out, 2 * max_bright);\
} while (0)
+#define MDSS_BL_TO_BRIGHT(out, v, bl_max, max_bright) do {\
+ out = ((v) * (max_bright));\
+ do_div(out, bl_max);\
+ } while (0)
struct mdss_fb_file_info {
struct file *file;
@@ -309,6 +313,7 @@
u32 calib_mode_bl;
u32 ad_bl_level;
u64 bl_level;
+ u64 bl_extn_level;
u32 bl_scale;
u32 bl_min_lvl;
u32 unset_bl_level;
@@ -473,4 +478,5 @@
void mdss_panelinfo_to_fb_var(struct mdss_panel_info *pinfo,
struct fb_var_screeninfo *var);
void mdss_fb_calc_fps(struct msm_fb_data_type *mfd);
+void mdss_fb_idle_pc(struct msm_fb_data_type *mfd);
#endif /* MDSS_FB_H */
diff --git a/drivers/video/fbdev/msm/mdss_hdmi_hdcp2p2.c b/drivers/video/fbdev/msm/mdss_hdmi_hdcp2p2.c
index 8dce151..98f4c658 100644
--- a/drivers/video/fbdev/msm/mdss_hdmi_hdcp2p2.c
+++ b/drivers/video/fbdev/msm/mdss_hdmi_hdcp2p2.c
@@ -666,7 +666,7 @@
static void hdmi_hdcp2p2_recv_msg(struct hdmi_hdcp2p2_ctrl *ctrl)
{
- int rc = 0, timeout_hsync;
+ int timeout_hsync = 0, rc = 0;
char *recvd_msg_buf = NULL;
struct hdmi_tx_hdcp2p2_ddc_data *ddc_data;
struct hdmi_tx_ddc_ctrl *ddc_ctrl;
@@ -1077,7 +1077,7 @@
static bool hdmi_hdcp2p2_supported(struct hdmi_hdcp2p2_ctrl *ctrl)
{
- u8 hdcp2version;
+ u8 hdcp2version = 0;
int rc = hdmi_hdcp2p2_read_version(ctrl, &hdcp2version);
diff --git a/drivers/video/fbdev/msm/mdss_hdmi_tx.c b/drivers/video/fbdev/msm/mdss_hdmi_tx.c
index 4f2bb09..42e2181 100644
--- a/drivers/video/fbdev/msm/mdss_hdmi_tx.c
+++ b/drivers/video/fbdev/msm/mdss_hdmi_tx.c
@@ -70,8 +70,10 @@
#define HDMI_TX_3_MAX_PCLK_RATE 297000
#define HDMI_TX_4_MAX_PCLK_RATE 600000
-#define hdmi_tx_get_fd(x) (x ? hdmi_ctrl->feature_data[ffs(x) - 1] : 0)
-#define hdmi_tx_set_fd(x, y) {if (x) hdmi_ctrl->feature_data[ffs(x) - 1] = y; }
+#define hdmi_tx_get_fd(x) ((x && (ffs(x) > 0)) ? \
+ hdmi_ctrl->feature_data[ffs(x) - 1] : 0)
+#define hdmi_tx_set_fd(x, y) {if (x && (ffs(x) > 0)) \
+ hdmi_ctrl->feature_data[ffs(x) - 1] = y; }
#define MAX_EDID_READ_RETRY 5
diff --git a/drivers/video/fbdev/msm/mdss_mdp.c b/drivers/video/fbdev/msm/mdss_mdp.c
index a6d43a6..24f7521 100644
--- a/drivers/video/fbdev/msm/mdss_mdp.c
+++ b/drivers/video/fbdev/msm/mdss_mdp.c
@@ -811,7 +811,7 @@
int mdss_mdp_irq_enable(u32 intr_type, u32 intf_num)
{
- int irq_idx;
+ int irq_idx = 0;
unsigned long irq_flags;
int ret = 0;
struct mdss_data_type *mdata = mdss_mdp_get_mdata();
@@ -830,7 +830,7 @@
spin_lock_irqsave(&mdp_lock, irq_flags);
if (mdata->mdp_irq_mask[irq.reg_idx] & irq.irq_mask) {
pr_warn("MDSS MDP IRQ-0x%x is already set, mask=%x\n",
- irq.irq_mask, mdata->mdp_irq_mask[irq.reg_idx]);
+ irq.irq_mask, mdata->mdp_irq_mask[irq.reg_idx]);
ret = -EBUSY;
} else {
pr_debug("MDP IRQ mask old=%x new=%x\n",
@@ -1129,12 +1129,31 @@
{
int ret = -ENODEV;
struct clk *clk = mdss_mdp_get_clk(clk_idx);
+ struct mdss_data_type *mdata = mdss_res;
if (clk) {
pr_debug("clk=%d en=%d\n", clk_idx, enable);
if (enable) {
if (clk_idx == MDSS_CLK_MDP_VSYNC)
clk_set_rate(clk, 19200000);
+ if (mdss_has_quirk(mdata, MDSS_QUIRK_MDP_CLK_SET_RATE)
+ && (clk_idx == MDSS_CLK_MDP_CORE)) {
+
+ if (WARN_ON(!mdata->mdp_clk_rate)) {
+ /*
+ * rate should have been set in probe
+ * or during clk scaling; but if this
+ * is not the case, set max clk rate.
+ */
+ pr_warn("set max mdp clk rate:%u\n",
+ mdata->max_mdp_clk_rate);
+ mdss_mdp_set_clk_rate(
+ mdata->max_mdp_clk_rate, true);
+ } else {
+ clk_set_rate(clk, mdata->mdp_clk_rate);
+ }
+ }
+
ret = clk_prepare_enable(clk);
} else {
clk_disable_unprepare(clk);
@@ -1163,7 +1182,7 @@
return ret;
}
-void mdss_mdp_set_clk_rate(unsigned long rate)
+void mdss_mdp_set_clk_rate(unsigned long rate, bool locked)
{
struct mdss_data_type *mdata = mdss_res;
unsigned long clk_rate;
@@ -1173,7 +1192,9 @@
min_clk_rate = max(rate, mdata->perf_tune.min_mdp_clk);
if (clk) {
- mutex_lock(&mdp_clk_lock);
+
+ if (!locked)
+ mutex_lock(&mdp_clk_lock);
if (min_clk_rate < mdata->max_mdp_clk_rate)
clk_rate = clk_round_rate(clk, min_clk_rate);
else
@@ -1181,13 +1202,15 @@
if (IS_ERR_VALUE(clk_rate)) {
pr_err("unable to round rate err=%ld\n", clk_rate);
} else if (clk_rate != clk_get_rate(clk)) {
- if (IS_ERR_VALUE((unsigned long)
- clk_set_rate(clk, clk_rate)))
+ mdata->mdp_clk_rate = clk_rate;
+ if (IS_ERR_VALUE(
+ (unsigned long)clk_set_rate(clk, clk_rate)))
pr_err("clk_set_rate failed\n");
else
pr_debug("mdp clk rate=%lu\n", clk_rate);
}
- mutex_unlock(&mdp_clk_lock);
+ if (!locked)
+ mutex_unlock(&mdp_clk_lock);
} else {
pr_err("mdp src clk not setup properly\n");
}
@@ -1285,6 +1308,68 @@
}
}
+/*
+ * __mdss_mdp_clk_control - Overall MDSS clock control for power on/off
+ */
+static void __mdss_mdp_clk_control(struct mdss_data_type *mdata, bool enable)
+{
+ int rc = 0;
+ unsigned long flags;
+
+ if (enable) {
+ pm_runtime_get_sync(&mdata->pdev->dev);
+
+ mdss_update_reg_bus_vote(mdata->reg_bus_clt,
+ VOTE_INDEX_LOW);
+
+ rc = mdss_iommu_ctrl(1);
+ if (IS_ERR_VALUE((unsigned long)rc))
+ pr_err("IOMMU attach failed\n");
+
+ /* Active+Sleep */
+ msm_bus_scale_client_update_context(mdata->bus_hdl,
+ false, mdata->curr_bw_uc_idx);
+
+ spin_lock_irqsave(&mdp_lock, flags);
+ mdata->clk_ena = enable;
+ spin_unlock_irqrestore(&mdp_lock, flags);
+
+ mdss_mdp_clk_update(MDSS_CLK_MNOC_AHB, 1);
+ mdss_mdp_clk_update(MDSS_CLK_AHB, 1);
+ mdss_mdp_clk_update(MDSS_CLK_AXI, 1);
+ mdss_mdp_clk_update(MDSS_CLK_MDP_CORE, 1);
+ mdss_mdp_clk_update(MDSS_CLK_MDP_LUT, 1);
+ if (mdata->vsync_ena)
+ mdss_mdp_clk_update(MDSS_CLK_MDP_VSYNC, 1);
+ } else {
+ spin_lock_irqsave(&mdp_lock, flags);
+ mdata->clk_ena = enable;
+ spin_unlock_irqrestore(&mdp_lock, flags);
+
+ if (mdata->vsync_ena)
+ mdss_mdp_clk_update(MDSS_CLK_MDP_VSYNC, 0);
+
+ mdss_mdp_clk_update(MDSS_CLK_MDP_LUT, 0);
+ mdss_mdp_clk_update(MDSS_CLK_MDP_CORE, 0);
+ mdss_mdp_clk_update(MDSS_CLK_AXI, 0);
+ mdss_mdp_clk_update(MDSS_CLK_AHB, 0);
+ mdss_mdp_clk_update(MDSS_CLK_MNOC_AHB, 0);
+
+ /* release iommu control */
+ mdss_iommu_ctrl(0);
+
+ /* Active-Only */
+ msm_bus_scale_client_update_context(mdata->bus_hdl,
+ true, mdata->ao_bw_uc_idx);
+
+ mdss_update_reg_bus_vote(mdata->reg_bus_clt,
+ VOTE_INDEX_DISABLE);
+
+ pm_runtime_mark_last_busy(&mdata->pdev->dev);
+ pm_runtime_put_autosuspend(&mdata->pdev->dev);
+ }
+}
+
int __mdss_mdp_vbif_halt(struct mdss_data_type *mdata, bool is_nrt)
{
int rc = 0;
@@ -1382,10 +1467,17 @@
return mdata->iommu_ref_cnt;
}
-static void mdss_mdp_memory_retention_enter(void)
+#define MEM_RETAIN_ON 1
+#define MEM_RETAIN_OFF 0
+#define PERIPH_RETAIN_ON 1
+#define PERIPH_RETAIN_OFF 0
+
+static void mdss_mdp_memory_retention_ctrl(bool mem_ctrl, bool periph_ctrl)
{
struct clk *mdss_mdp_clk = NULL;
struct clk *mdp_vote_clk = mdss_mdp_get_clk(MDSS_CLK_MDP_CORE);
+ struct mdss_data_type *mdata = mdss_mdp_get_mdata();
+ struct clk *mdss_mdp_lut_clk = NULL;
if (mdp_vote_clk) {
mdss_mdp_clk = clk_get_parent(mdp_vote_clk);
@@ -1395,21 +1487,40 @@
clk_set_flags(mdss_mdp_clk, CLKFLAG_NORETAIN_PERIPH);
}
}
-}
-static void mdss_mdp_memory_retention_exit(void)
-{
- struct clk *mdss_mdp_clk = NULL;
- struct clk *mdp_vote_clk = mdss_mdp_get_clk(MDSS_CLK_MDP_CORE);
-
- if (mdp_vote_clk) {
- mdss_mdp_clk = clk_get_parent(mdp_vote_clk);
- if (mdss_mdp_clk) {
+ __mdss_mdp_reg_access_clk_enable(mdata, true);
+ if (mdss_mdp_clk) {
+ if (mem_ctrl)
clk_set_flags(mdss_mdp_clk, CLKFLAG_RETAIN_MEM);
+ else
+ clk_set_flags(mdss_mdp_clk, CLKFLAG_NORETAIN_MEM);
+
+ if (periph_ctrl) {
clk_set_flags(mdss_mdp_clk, CLKFLAG_RETAIN_PERIPH);
clk_set_flags(mdss_mdp_clk, CLKFLAG_PERIPH_OFF_CLEAR);
+ } else {
+ clk_set_flags(mdss_mdp_clk, CLKFLAG_PERIPH_OFF_SET);
+ clk_set_flags(mdss_mdp_clk, CLKFLAG_NORETAIN_PERIPH);
}
}
+
+ if (mdss_mdp_lut_clk) {
+ if (mem_ctrl)
+ clk_set_flags(mdss_mdp_lut_clk, CLKFLAG_RETAIN_MEM);
+ else
+ clk_set_flags(mdss_mdp_lut_clk, CLKFLAG_NORETAIN_MEM);
+
+ if (periph_ctrl) {
+ clk_set_flags(mdss_mdp_lut_clk, CLKFLAG_RETAIN_PERIPH);
+ clk_set_flags(mdss_mdp_lut_clk,
+ CLKFLAG_PERIPH_OFF_CLEAR);
+ } else {
+ clk_set_flags(mdss_mdp_lut_clk, CLKFLAG_PERIPH_OFF_SET);
+ clk_set_flags(mdss_mdp_lut_clk,
+ CLKFLAG_NORETAIN_PERIPH);
+ }
+ }
+ __mdss_mdp_reg_access_clk_enable(mdata, false);
}
/**
@@ -1440,17 +1551,21 @@
mdss_hw_init(mdata);
mdss_iommu_ctrl(0);
- /**
- * sleep 10 microseconds to make sure AD auto-reinitialization
- * is done
- */
- udelay(10);
- mdss_mdp_memory_retention_exit();
-
mdss_mdp_ctl_restore(true);
mdata->idle_pc = false;
end:
+ if (mdata->mem_retain) {
+ /**
+ * sleep 10 microseconds to make sure AD auto-reinitialization
+ * is done
+ */
+ udelay(10);
+ mdss_mdp_memory_retention_ctrl(MEM_RETAIN_ON,
+ PERIPH_RETAIN_ON);
+ mdata->mem_retain = false;
+ }
+
mutex_unlock(&mdp_fs_idle_pc_lock);
return rc;
}
@@ -1543,9 +1658,7 @@
{
struct mdss_data_type *mdata = mdss_mdp_get_mdata();
static int mdp_clk_cnt;
- unsigned long flags;
int changed = 0;
- int rc = 0;
mutex_lock(&mdp_clk_lock);
if (enable) {
@@ -1569,49 +1682,8 @@
__builtin_return_address(0), current->group_leader->comm,
mdata->bus_ref_cnt, changed, enable);
- if (changed) {
- if (enable) {
- pm_runtime_get_sync(&mdata->pdev->dev);
-
- mdss_update_reg_bus_vote(mdata->reg_bus_clt,
- VOTE_INDEX_LOW);
-
- rc = mdss_iommu_ctrl(1);
- if (IS_ERR_VALUE((unsigned long)rc))
- pr_err("IOMMU attach failed\n");
-
- /* Active+Sleep */
- msm_bus_scale_client_update_context(mdata->bus_hdl,
- false, mdata->curr_bw_uc_idx);
- }
-
- spin_lock_irqsave(&mdp_lock, flags);
- mdata->clk_ena = enable;
- spin_unlock_irqrestore(&mdp_lock, flags);
-
- mdss_mdp_clk_update(MDSS_CLK_MNOC_AHB, enable);
- mdss_mdp_clk_update(MDSS_CLK_AHB, enable);
- mdss_mdp_clk_update(MDSS_CLK_AXI, enable);
- mdss_mdp_clk_update(MDSS_CLK_MDP_CORE, enable);
- mdss_mdp_clk_update(MDSS_CLK_MDP_LUT, enable);
- if (mdata->vsync_ena)
- mdss_mdp_clk_update(MDSS_CLK_MDP_VSYNC, enable);
-
- if (!enable) {
- /* release iommu control */
- mdss_iommu_ctrl(0);
-
- /* Active-Only */
- msm_bus_scale_client_update_context(mdata->bus_hdl,
- true, mdata->ao_bw_uc_idx);
-
- mdss_update_reg_bus_vote(mdata->reg_bus_clt,
- VOTE_INDEX_DISABLE);
-
- pm_runtime_mark_last_busy(&mdata->pdev->dev);
- pm_runtime_put_autosuspend(&mdata->pdev->dev);
- }
- }
+ if (changed)
+ __mdss_mdp_clk_control(mdata, enable);
if (enable && changed)
mdss_mdp_idle_pc_restore();
@@ -1757,7 +1829,7 @@
mdss_mdp_irq_clk_register(mdata, "mnoc_clk", MDSS_CLK_MNOC_AHB);
/* Setting the default clock rate to the max supported.*/
- mdss_mdp_set_clk_rate(mdata->max_mdp_clk_rate);
+ mdss_mdp_set_clk_rate(mdata->max_mdp_clk_rate, false);
pr_debug("mdp clk rate=%ld\n",
mdss_mdp_get_clk_rate(MDSS_CLK_MDP_CORE, false));
@@ -1867,7 +1939,8 @@
mdata->pixel_ram_size = 50 * 1024;
set_bit(MDSS_QOS_PER_PIPE_IB, mdata->mdss_qos_map);
set_bit(MDSS_QOS_OVERHEAD_FACTOR, mdata->mdss_qos_map);
- set_bit(MDSS_QOS_CDP, mdata->mdss_qos_map);
+ set_bit(MDSS_QOS_CDP, mdata->mdss_qos_map); /* cdp supported */
+ mdata->enable_cdp = true; /* enable cdp */
set_bit(MDSS_QOS_OTLIM, mdata->mdss_qos_map);
set_bit(MDSS_QOS_PER_PIPE_LUT, mdata->mdss_qos_map);
set_bit(MDSS_QOS_SIMPLIFIED_PREFILL, mdata->mdss_qos_map);
@@ -1961,7 +2034,8 @@
set_bit(MDSS_QOS_PER_PIPE_IB, mdata->mdss_qos_map);
set_bit(MDSS_QOS_TS_PREFILL, mdata->mdss_qos_map);
set_bit(MDSS_QOS_OVERHEAD_FACTOR, mdata->mdss_qos_map);
- set_bit(MDSS_QOS_CDP, mdata->mdss_qos_map);
+ set_bit(MDSS_QOS_CDP, mdata->mdss_qos_map); /* cdp supported */
+ mdata->enable_cdp = false; /* disable cdp */
set_bit(MDSS_QOS_OTLIM, mdata->mdss_qos_map);
set_bit(MDSS_QOS_PER_PIPE_LUT, mdata->mdss_qos_map);
set_bit(MDSS_QOS_SIMPLIFIED_PREFILL, mdata->mdss_qos_map);
@@ -1978,6 +2052,7 @@
mdss_set_quirk(mdata, MDSS_QUIRK_DSC_RIGHT_ONLY_PU);
mdss_set_quirk(mdata, MDSS_QUIRK_DSC_2SLICE_PU_THRPUT);
mdss_set_quirk(mdata, MDSS_QUIRK_SRC_SPLIT_ALWAYS);
+ mdss_set_quirk(mdata, MDSS_QUIRK_MDP_CLK_SET_RATE);
mdata->has_wb_ubwc = true;
set_bit(MDSS_CAPS_10_BIT_SUPPORTED, mdata->mdss_caps_map);
break;
@@ -2340,6 +2415,8 @@
size_t len = PAGE_SIZE;
int num_bytes = BITS_TO_BYTES(MDP_IMGTYPE_LIMIT1);
+ if (!pipe)
+ return;
#define SPRINT(fmt, ...) \
(*cnt += scnprintf(buf + *cnt, len - *cnt, fmt, ##__VA_ARGS__))
@@ -2824,11 +2901,9 @@
MDSS_MDP_REG_SPLIT_DISPLAY_EN);
mdata->splash_intf_sel = intf_sel;
mdata->splash_split_disp = split_display;
-
if (intf_sel != 0) {
for (i = 0; i < 4; i++)
- if ((intf_sel >> i*8) & 0x000000FF)
- num_of_display_on++;
+ num_of_display_on += ((intf_sel >> i*8) & 0x000000FF);
/*
* For split display enabled - DSI0, DSI1 interfaces are
@@ -3918,6 +3993,7 @@
static void mdss_mdp_parse_vbif_qos(struct platform_device *pdev)
{
struct mdss_data_type *mdata = platform_get_drvdata(pdev);
+ u32 npriority_lvl_nrt;
int rc;
mdata->npriority_lvl = mdss_mdp_parse_dt_prop_len(pdev,
@@ -3941,8 +4017,20 @@
return;
}
- mdata->npriority_lvl = mdss_mdp_parse_dt_prop_len(pdev,
+ npriority_lvl_nrt = mdss_mdp_parse_dt_prop_len(pdev,
"qcom,mdss-vbif-qos-nrt-setting");
+
+ if (!npriority_lvl_nrt) {
+ pr_debug("no vbif nrt priorities found rt:%d\n",
+ mdata->npriority_lvl);
+ return;
+ } else if (npriority_lvl_nrt != mdata->npriority_lvl) {
+ /* driver expects same number for both nrt and rt */
+ pr_err("invalid nrt settings nrt(%d) != rt(%d)\n",
+ npriority_lvl_nrt, mdata->npriority_lvl);
+ return;
+ }
+
if (mdata->npriority_lvl == MDSS_VBIF_QOS_REMAP_ENTRIES) {
mdata->vbif_nrt_qos = kcalloc(mdata->npriority_lvl,
sizeof(u32), GFP_KERNEL);
@@ -3958,7 +4046,7 @@
}
} else {
mdata->npriority_lvl = 0;
- pr_debug("Invalid or no vbif qos nrt seting\n");
+ pr_debug("Invalid or no vbif qos nrt setting\n");
}
}
@@ -4183,6 +4271,15 @@
mdss_mdp_parse_dt_fudge_factors(pdev, "qcom,mdss-clk-factor",
&mdata->clk_factor);
+ /*
+ * Bus throughput factor will be used during high downscale cases.
+ * The recommended default factor is 1.1.
+ */
+ mdata->bus_throughput_factor.numer = 11;
+ mdata->bus_throughput_factor.denom = 10;
+ mdss_mdp_parse_dt_fudge_factors(pdev, "qcom,mdss-bus-througput-factor",
+ &mdata->bus_throughput_factor);
+
rc = of_property_read_u32(pdev->dev.of_node,
"qcom,max-bandwidth-low-kbps", &mdata->max_bw_low);
if (rc)
@@ -4821,6 +4918,22 @@
}
/**
+ * mdss_mdp_notify_idle_pc() - Notify fb driver of idle power collapse
+ * @mdata: MDP private data
+ *
+ * This function is called if there are active overlays.
+ */
+static void mdss_mdp_notify_idle_pc(struct mdss_data_type *mdata)
+{
+ int i;
+
+ for (i = 0; i < mdata->nctl; i++)
+ if ((mdata->ctl_off[i].ref_cnt) &&
+ !mdss_mdp_ctl_is_power_off(&mdata->ctl_off[i]))
+ mdss_fb_idle_pc(mdata->ctl_off[i].mfd);
+}
+
+/**
* mdss_mdp_footswitch_ctrl() - Disable/enable MDSS GDSC and CX/Batfet rails
* @mdata: MDP private data
* @on: 1 to turn on footswitch, 0 to turn off footswitch
@@ -4870,14 +4983,21 @@
* Turning off GDSC while overlays are still
* active.
*/
+
+ mdss_mdp_memory_retention_ctrl(MEM_RETAIN_ON,
+ PERIPH_RETAIN_OFF);
mdata->idle_pc = true;
+ mdss_mdp_notify_idle_pc(mdata);
pr_debug("idle pc. active overlays=%d\n",
active_cnt);
- mdss_mdp_memory_retention_enter();
} else {
mdss_mdp_cx_ctrl(mdata, false);
mdss_mdp_batfet_ctrl(mdata, false);
+ mdss_mdp_memory_retention_ctrl(
+ MEM_RETAIN_OFF,
+ PERIPH_RETAIN_OFF);
}
+ mdata->mem_retain = true;
if (mdata->en_svs_high)
mdss_mdp_config_cx_voltage(mdata, false);
regulator_disable(mdata->fs);
diff --git a/drivers/video/fbdev/msm/mdss_mdp.h b/drivers/video/fbdev/msm/mdss_mdp.h
index 9497318..78ee489 100644
--- a/drivers/video/fbdev/msm/mdss_mdp.h
+++ b/drivers/video/fbdev/msm/mdss_mdp.h
@@ -350,6 +350,9 @@
/* to update lineptr, [1..yres] - enable, 0 - disable */
int (*update_lineptr)(struct mdss_mdp_ctl *ctl, bool enable);
+
+ /* to wait for vsync */
+ int (*wait_for_vsync_fnc)(struct mdss_mdp_ctl *ctl);
};
/* FRC info used for Deterministic Frame Rate Control */
@@ -648,6 +651,7 @@
/* vsync handler for FRC */
struct mdss_mdp_vsync_handler frc_vsync_handler;
+ bool need_vsync_on;
};
struct mdss_mdp_mixer {
@@ -664,6 +668,8 @@
bool valid_roi;
bool roi_changed;
struct mdss_rect roi;
+ bool dsc_enabled;
+ bool dsc_merge_enabled;
u8 cursor_enabled;
u16 cursor_hotx;
@@ -738,6 +744,7 @@
struct dma_buf *srcp_dma_buf;
struct dma_buf_attachment *srcp_attachment;
struct sg_table *srcp_table;
+ struct ion_handle *ihandle;
};
enum mdss_mdp_data_state {
@@ -1026,6 +1033,8 @@
struct kthread_worker worker;
struct kthread_work vsync_work;
struct task_struct *thread;
+
+ bool cache_null_commit; /* Cache if preceding commit was NULL */
};
struct mdss_mdp_set_ot_params {
@@ -1620,7 +1629,7 @@
void mdss_mdp_footswitch_ctrl_splash(int on);
void mdss_mdp_batfet_ctrl(struct mdss_data_type *mdata, int enable);
-void mdss_mdp_set_clk_rate(unsigned long min_clk_rate);
+void mdss_mdp_set_clk_rate(unsigned long min_clk_rate, bool locked);
unsigned long mdss_mdp_get_clk_rate(u32 clk_idx, bool locked);
int mdss_mdp_vsync_clk_enable(int enable, bool locked);
void mdss_mdp_clk_ctrl(int enable);
@@ -1730,7 +1739,7 @@
void mdss_mdp_ctl_notifier_unregister(struct mdss_mdp_ctl *ctl,
struct notifier_block *notifier);
u32 mdss_mdp_ctl_perf_get_transaction_status(struct mdss_mdp_ctl *ctl);
-u32 apply_comp_ratio_factor(u32 quota, struct mdss_mdp_format_params *fmt,
+u64 apply_comp_ratio_factor(u64 quota, struct mdss_mdp_format_params *fmt,
struct mult_factor *factor);
int mdss_mdp_scan_pipes(void);
diff --git a/drivers/video/fbdev/msm/mdss_mdp_cdm.c b/drivers/video/fbdev/msm/mdss_mdp_cdm.c
index ab680f5..3d1be10 100644
--- a/drivers/video/fbdev/msm/mdss_mdp_cdm.c
+++ b/drivers/video/fbdev/msm/mdss_mdp_cdm.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2014-2016, 2018, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2014-2018, The Linux Foundation. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 and
@@ -378,6 +378,17 @@
return -EINVAL;
}
+ mdss_mdp_clk_ctrl(MDP_BLOCK_POWER_ON);
+ mutex_lock(&cdm->lock);
+ /* Disable HDMI packer */
+ writel_relaxed(0x0, cdm->base + MDSS_MDP_REG_CDM_HDMI_PACK_OP_MODE);
+
+ /* Put CDM in bypass */
+ writel_relaxed(0x0, cdm->mdata->mdp_base + MDSS_MDP_MDP_OUT_CTL_0);
+
+ mutex_unlock(&cdm->lock);
+ mdss_mdp_clk_ctrl(MDP_BLOCK_POWER_OFF);
+
kref_put(&cdm->kref, mdss_mdp_cdm_free);
return rc;
diff --git a/drivers/video/fbdev/msm/mdss_mdp_ctl.c b/drivers/video/fbdev/msm/mdss_mdp_ctl.c
index 9de02d9..4cfb48d 100644
--- a/drivers/video/fbdev/msm/mdss_mdp_ctl.c
+++ b/drivers/video/fbdev/msm/mdss_mdp_ctl.c
@@ -31,6 +31,7 @@
#define MDSS_MDP_QSEED3_VER_DOWNSCALE_LIM 2
#define NUM_MIXERCFG_REGS 3
#define MDSS_MDP_WB_OUTPUT_BPP 3
+#define MIN_BUS_THROUGHPUT_SCALE_FACTOR 35
struct mdss_mdp_mixer_cfg {
u32 config_masks[NUM_MIXERCFG_REGS];
bool border_enabled;
@@ -608,11 +609,21 @@
}
static inline bool __is_vert_downscaling(u32 src_h,
- struct mdss_rect dst){
-
+ struct mdss_rect dst)
+{
return (src_h > dst.h);
}
+static inline bool __is_bus_throughput_factor_required(u32 src_h,
+ struct mdss_rect dst)
+{
+ u64 scale_factor = src_h * 10;
+
+ do_div(scale_factor, dst.h);
+ return (__is_vert_downscaling(src_h, dst) &&
+ (scale_factor >= MIN_BUS_THROUGHPUT_SCALE_FACTOR));
+}
+
static u32 get_pipe_mdp_clk_rate(struct mdss_mdp_pipe *pipe,
struct mdss_rect src, struct mdss_rect dst,
u32 fps, u32 v_total, u32 flags)
@@ -659,6 +670,15 @@
}
}
+ /*
+ * If the downscale factor is >= 3.5 for a 32 BPP surface,
+ * it is recommended to add a 10% bus throughput factor to
+ * the clock rate.
+ */
+ if ((pipe->src_fmt->bpp == 4) &&
+ __is_bus_throughput_factor_required(src_h, dst))
+ rate = apply_fudge_factor(rate, &mdata->bus_throughput_factor);
+
if (flags & PERF_CALC_PIPE_APPLY_CLK_FUDGE)
rate = mdss_mdp_clk_fudge_factor(mixer, rate);
@@ -816,7 +836,7 @@
return factor->numer && factor->denom;
}
-u32 apply_comp_ratio_factor(u32 quota,
+u64 apply_comp_ratio_factor(u64 quota,
struct mdss_mdp_format_params *fmt,
struct mult_factor *factor)
{
@@ -907,7 +927,7 @@
static u32 __get_min_prefill_line_time_us(struct mdss_mdp_ctl *ctl)
{
- u32 vbp_min = 0;
+ u32 vbp_min = UINT_MAX;
int i;
struct mdss_data_type *mdata;
@@ -929,6 +949,9 @@
}
}
+ if (vbp_min == UINT_MAX)
+ vbp_min = 0;
+
return vbp_min;
}
@@ -2055,12 +2078,11 @@
return bw_sum_of_intfs;
}
-static void mdss_mdp_ctl_update_client_vote(struct mdss_data_type *mdata,
+/* apply any adjustments to the ib quota */
+static inline u64 __calc_bus_ib_quota(struct mdss_data_type *mdata,
struct mdss_mdp_perf_params *perf, bool nrt_client, u64 bw_vote)
{
- u64 bus_ab_quota, bus_ib_quota;
-
- bus_ab_quota = max(bw_vote, mdata->perf_tune.min_bus_vote);
+ u64 bus_ib_quota;
if (test_bit(MDSS_QOS_PER_PIPE_IB, mdata->mdss_qos_map)) {
if (!nrt_client)
@@ -2087,6 +2109,18 @@
bus_ib_quota = apply_fudge_factor(bus_ib_quota,
&mdata->per_pipe_ib_factor);
+ return bus_ib_quota;
+}
+
+static void mdss_mdp_ctl_update_client_vote(struct mdss_data_type *mdata,
+ struct mdss_mdp_perf_params *perf, bool nrt_client, u64 bw_vote)
+{
+ u64 bus_ab_quota, bus_ib_quota;
+
+ bus_ab_quota = max(bw_vote, mdata->perf_tune.min_bus_vote);
+ bus_ib_quota = __calc_bus_ib_quota(mdata, perf, nrt_client, bw_vote);
+
+
bus_ab_quota = apply_fudge_factor(bus_ab_quota, &mdss_res->ab_factor);
ATRACE_INT("bus_quota", bus_ib_quota);
@@ -2252,6 +2286,48 @@
return false;
}
+static bool __mdss_mdp_compare_bw(
+ struct mdss_mdp_ctl *ctl,
+ struct mdss_mdp_perf_params *new_perf,
+ struct mdss_mdp_perf_params *old_perf,
+ bool params_changed,
+ bool stop_req)
+{
+ struct mdss_data_type *mdata = ctl->mdata;
+ bool is_nrt = mdss_mdp_is_nrt_ctl_path(ctl);
+ u64 new_ib =
+ __calc_bus_ib_quota(mdata, new_perf, is_nrt, new_perf->bw_ctl);
+ u64 old_ib =
+ __calc_bus_ib_quota(mdata, old_perf, is_nrt, old_perf->bw_ctl);
+ u64 new_ab = new_perf->bw_ctl;
+ u64 old_ab = old_perf->bw_ctl;
+ bool update_bw = false;
+
+ /*
+ * three cases for bus bandwidth update.
+ * 1. new bandwidth vote (ab or ib) or writeback output vote
+ * are higher than current vote for update request.
+ * 2. new bandwidth vote or writeback output vote are
+ * lower than current vote at end of commit or stop.
+ * 3. end of writeback/rotator session - last chance to
+ * non-realtime remove vote.
+ */
+ if ((params_changed &&
+ (((new_ib > old_ib) || (new_ab > old_ab)) ||
+ (new_perf->bw_writeback > old_perf->bw_writeback))) ||
+ (!params_changed &&
+ (((new_ib < old_ib) || (new_ab < old_ab)) ||
+ (new_perf->bw_writeback < old_perf->bw_writeback))) ||
+ (stop_req && is_nrt))
+ update_bw = true;
+
+ trace_mdp_compare_bw(new_perf->bw_ctl, new_ib, new_perf->bw_writeback,
+ old_perf->bw_ctl, old_ib, old_perf->bw_writeback,
+ params_changed, update_bw);
+
+ return update_bw;
+}
+
static void mdss_mdp_ctl_perf_update(struct mdss_mdp_ctl *ctl,
int params_changed, bool stop_req)
{
@@ -2287,20 +2363,8 @@
else if (is_bw_released || params_changed)
mdss_mdp_perf_calc_ctl(ctl, new);
- /*
- * three cases for bus bandwidth update.
- * 1. new bandwidth vote or writeback output vote
- * are higher than current vote for update request.
- * 2. new bandwidth vote or writeback output vote are
- * lower than current vote at end of commit or stop.
- * 3. end of writeback/rotator session - last chance to
- * non-realtime remove vote.
- */
- if ((params_changed && ((new->bw_ctl > old->bw_ctl) ||
- (new->bw_writeback > old->bw_writeback))) ||
- (!params_changed && ((new->bw_ctl < old->bw_ctl) ||
- (new->bw_writeback < old->bw_writeback))) ||
- (stop_req && mdss_mdp_is_nrt_ctl_path(ctl))) {
+ if (__mdss_mdp_compare_bw(ctl, new, old, params_changed,
+ stop_req)) {
pr_debug("c=%d p=%d new_bw=%llu,old_bw=%llu\n",
ctl->num, params_changed, new->bw_ctl,
@@ -2355,7 +2419,7 @@
*/
if (update_clk) {
ATRACE_INT("mdp_clk", clk_rate);
- mdss_mdp_set_clk_rate(clk_rate);
+ mdss_mdp_set_clk_rate(clk_rate, false);
pr_debug("update clk rate = %d HZ\n", clk_rate);
}
@@ -2454,6 +2518,7 @@
u32 nmixers_wb;
u32 i;
u32 nmixers;
+ u32 nmixers_active;
struct mdss_mdp_mixer *mixer_pool = NULL;
if (!ctl || !ctl->mdata)
@@ -2467,10 +2532,21 @@
case MDSS_MDP_MIXER_TYPE_INTF:
mixer_pool = ctl->mdata->mixer_intf;
nmixers = nmixers_intf;
+ nmixers_active = nmixers;
+
+ for (i = 0; i < nmixers; i++) {
+ mixer = mixer_pool + i;
+ if (mixer->ref_cnt)
+ nmixers_active--;
+ }
+ mixer = NULL;
/*
* try to reserve first layer mixer for write back if
- * assertive display needs to be supported through wfd
+ * assertive display needs to be supported through wfd.
+ * For external displays(pluggable) and writeback avoid
+ * allocating mixers LM0 and LM1 which are allocated
+ * to primary display first.
*/
if (ctl->mdata->has_wb_ad && ctl->intf_num &&
((ctl->panel_data->panel_info.type != MIPI_CMD_PANEL) ||
@@ -2482,6 +2558,10 @@
&& (ctl->mdata->ndspp < nmixers)) {
mixer_pool += ctl->mdata->ndspp;
nmixers -= ctl->mdata->ndspp;
+ } else if ((ctl->panel_data->panel_info.is_pluggable) &&
+ nmixers_active) {
+ mixer_pool += ctl->mdata->ndspp;
+ nmixers -= ctl->mdata->ndspp;
}
break;
@@ -2695,10 +2775,7 @@
if (!clk_period)
return -EINVAL;
- time_of_line = (pinfo->lcdc.h_back_porch +
- pinfo->lcdc.h_front_porch +
- pinfo->lcdc.h_pulse_width +
- pinfo->xres) * clk_period;
+ time_of_line = mdss_panel_get_htotal(pinfo, true) * clk_period;
time_of_line /= 1000; /* in nano second */
if (!time_of_line)
@@ -2706,10 +2783,7 @@
current_line = ctl->ops.read_line_cnt_fnc(ctl);
- total_line = pinfo->lcdc.v_back_porch +
- pinfo->lcdc.v_front_porch +
- pinfo->lcdc.v_pulse_width +
- pinfo->yres;
+ total_line = mdss_panel_get_vtotal(pinfo);
if (current_line >= total_line)
time_to_vsync = time_of_line * total_line;
@@ -2835,6 +2909,7 @@
{
mdss_mdp_pingpong_write(mixer->pingpong_base,
MDSS_MDP_REG_PP_DSC_MODE, 1);
+ mixer->dsc_enabled = true;
}
static inline void __dsc_disable(struct mdss_mdp_mixer *mixer)
@@ -2854,6 +2929,13 @@
return;
}
writel_relaxed(0, offset + MDSS_MDP_REG_DSC_COMMON_MODE);
+ mixer->dsc_enabled = false;
+ mixer->dsc_merge_enabled = false;
+}
+
+static bool __is_dsc_merge_enabled(u32 common_mode)
+{
+ return common_mode & BIT(1);
}
static void __dsc_config(struct mdss_mdp_mixer *mixer,
@@ -2866,6 +2948,7 @@
u32 initial_lines = dsc->initial_lines;
bool is_cmd_mode = !(mode & BIT(2));
+ mixer->dsc_merge_enabled = __is_dsc_merge_enabled(mode);
data = mdss_mdp_pingpong_read(mixer->pingpong_base,
MDSS_MDP_REG_PP_DCE_DATA_OUT_SWAP);
data |= BIT(18); /* endian flip */
@@ -3020,11 +3103,6 @@
}
}
-static bool __is_dsc_merge_enabled(u32 common_mode)
-{
- return common_mode & BIT(1);
-}
-
static bool __dsc_is_3d_mux_enabled(struct mdss_mdp_ctl *ctl,
struct mdss_panel_info *pinfo)
{
@@ -3366,8 +3444,19 @@
struct mdss_mdp_ctl *sctl;
struct mdss_panel_info *spinfo;
- if (!is_dsc_compression(pinfo))
+ /*
+ * Check for dynamic resolution switch from DSC On to DSC Off
+ * and disable DSC
+ */
+ if ((ctl->pending_mode_switch == SWITCH_RESOLUTION) &&
+ ctl->is_master &&
+ (!is_dsc_compression(pinfo))) {
+ if (ctl->mixer_left && ctl->mixer_left->dsc_enabled)
+ __dsc_disable(ctl->mixer_left);
+ if (ctl->mixer_right && ctl->mixer_right->dsc_enabled)
+ __dsc_disable(ctl->mixer_right);
return;
+ }
if (!ctl->is_master) {
pr_debug("skip slave ctl because master will program for both\n");
@@ -3653,6 +3742,30 @@
ctl->mixer_right->width = ctl->width / 2;
ctl->mixer_right->height = ctl->height;
}
+
+ /*
+ * If we are transitioning from DSC On + DSC Merge to DSC Off
+ * the 3D mux needs to be enabled
+ */
+ if (!is_dsc_compression(&pdata->panel_info) &&
+ ctl->mixer_left &&
+ ctl->mixer_left->dsc_enabled &&
+ ctl->mixer_left->dsc_merge_enabled) {
+ ctl->opmode |= MDSS_MDP_CTL_OP_PACK_3D_ENABLE |
+ MDSS_MDP_CTL_OP_PACK_3D_H_ROW_INT;
+ }
+
+ /*
+ * If we are transitioning from DSC Off to DSC On + DSC Merge
+ * the 3D mux needs to be disabled
+ */
+ if (is_dsc_compression(&pdata->panel_info) &&
+ ctl->mixer_left &&
+ !ctl->mixer_left->dsc_enabled &&
+ pdata->panel_info.dsc_enc_total != 1) {
+ ctl->opmode &= ~(MDSS_MDP_CTL_OP_PACK_3D_ENABLE |
+ MDSS_MDP_CTL_OP_PACK_3D_H_ROW_INT);
+ }
} else {
/*
* Handles MDP_SPLIT_MODE_NONE, MDP_DUAL_LM_DUAL_DISPLAY and
@@ -3667,7 +3780,6 @@
ctl->border_x_off = pdata->panel_info.lcdc.border_left;
ctl->border_y_off = pdata->panel_info.lcdc.border_top;
-
return ret;
}
@@ -5577,10 +5689,10 @@
sctl->flush_bits = 0;
sctl_flush_bits = 0;
} else {
- sctl_flush_bits = sctl->flush_bits;
+ sctl_flush_bits |= sctl->flush_bits;
}
}
- ctl_flush_bits = ctl->flush_bits;
+ ctl_flush_bits |= ctl->flush_bits;
mutex_unlock(&ctl->flush_lock);
}
/*
@@ -5670,6 +5782,10 @@
mdss_mdp_bwcpanic_ctrl(mdata, true);
ATRACE_BEGIN("flush_kickoff");
+
+ MDSS_XLOG(ctl->intf_num, ctl_flush_bits, sctl_flush_bits,
+ mdss_mdp_ctl_read(ctl, MDSS_MDP_REG_CTL_FLUSH), split_lm_valid);
+
mdss_mdp_ctl_write(ctl, MDSS_MDP_REG_CTL_FLUSH, ctl_flush_bits);
if (sctl && sctl_flush_bits) {
mdss_mdp_ctl_write(sctl, MDSS_MDP_REG_CTL_FLUSH,
@@ -5703,6 +5819,18 @@
if (ret)
pr_warn("ctl %d error displaying frame\n", ctl->num);
+ /* update backlight in commit */
+ if (ctl->intf_type == MDSS_INTF_DSI && !ctl->is_video_mode &&
+ ctl->mfd && ctl->mfd->bl_extn_level > 0) {
+ if (!IS_CALIB_MODE_BL(ctl->mfd) && (!ctl->mfd->ext_bl_ctrl ||
+ !ctl->mfd->bl_level)) {
+ mutex_lock(&ctl->mfd->bl_lock);
+ mdss_fb_set_backlight(ctl->mfd,
+ ctl->mfd->bl_extn_level);
+ mutex_unlock(&ctl->mfd->bl_lock);
+ }
+ }
+
ctl->play_cnt++;
ATRACE_END("flush_kickoff");
diff --git a/drivers/video/fbdev/msm/mdss_mdp_debug.c b/drivers/video/fbdev/msm/mdss_mdp_debug.c
index 9332f49..bd4ee23 100644
--- a/drivers/video/fbdev/msm/mdss_mdp_debug.c
+++ b/drivers/video/fbdev/msm/mdss_mdp_debug.c
@@ -1066,12 +1066,14 @@
seq_puts(s, "\n");
}
-static void __dump_pipe(struct seq_file *s, struct mdss_mdp_pipe *pipe)
+static void __dump_pipe(struct seq_file *s, struct mdss_mdp_pipe *pipe,
+ struct msm_fb_data_type *mfd)
{
struct mdss_mdp_data *buf;
int format;
int smps[4];
int i;
+ struct mdss_overlay_private *mdp5_data = mfd_to_mdp5_data(mfd);
seq_printf(s, "\nSSPP #%d type=%s ndx=%x flags=0x%08x play_cnt=%u xin_id=%d\n",
pipe->num, mdss_mdp_pipetype2str(pipe->type),
@@ -1126,11 +1128,14 @@
seq_puts(s, "Data:\n");
+ mutex_lock(&mdp5_data->list_lock);
list_for_each_entry(buf, &pipe->buf_queue, pipe_list)
__print_buf(s, buf, false);
+ mutex_unlock(&mdp5_data->list_lock);
}
-static void __dump_mixer(struct seq_file *s, struct mdss_mdp_mixer *mixer)
+static void __dump_mixer(struct seq_file *s, struct mdss_mdp_mixer *mixer,
+ struct msm_fb_data_type *mfd)
{
struct mdss_mdp_pipe *pipe;
int i, cnt = 0;
@@ -1147,7 +1152,7 @@
for (i = 0; i < ARRAY_SIZE(mixer->stage_pipe); i++) {
pipe = mixer->stage_pipe[i];
if (pipe) {
- __dump_pipe(s, pipe);
+ __dump_pipe(s, pipe, mfd);
cnt++;
}
}
@@ -1224,8 +1229,8 @@
seq_printf(s, "Play Count=%u Underrun Count=%u\n",
ctl->play_cnt, ctl->underrun_cnt);
- __dump_mixer(s, ctl->mixer_left);
- __dump_mixer(s, ctl->mixer_right);
+ __dump_mixer(s, ctl->mixer_left, ctl->mfd);
+ __dump_mixer(s, ctl->mixer_right, ctl->mfd);
}
static int __dump_mdp(struct seq_file *s, struct mdss_data_type *mdata)
@@ -1419,7 +1424,7 @@
seq_printf(s, "vsync: %08u \tunderrun: %08u\n",
ctl->vsync_cnt, ctl->underrun_cnt);
if (ctl->mfd) {
- seq_printf(s, "user_bl: %08llu \tmod_bl: %08u\n",
+ seq_printf(s, "user_bl: %llu \tmod_bl: %08u\n",
ctl->mfd->bl_level, ctl->mfd->bl_level_scaled);
}
} else {
diff --git a/drivers/video/fbdev/msm/mdss_mdp_hwio.h b/drivers/video/fbdev/msm/mdss_mdp_hwio.h
index 54ceb19..5bff904 100644
--- a/drivers/video/fbdev/msm/mdss_mdp_hwio.h
+++ b/drivers/video/fbdev/msm/mdss_mdp_hwio.h
@@ -820,6 +820,8 @@
#define MMSS_VBIF_WR_LIM_CONF 0x0C0
#define MMSS_VBIF_OUT_RD_LIM_CONF0 0x0D0
+#define MMSS_VBIF_SRC_ERR 0x194
+#define MMSS_VBIF_ERR_INFO 0x1A0
#define MMSS_VBIF_XIN_HALT_CTRL0 0x200
#define MMSS_VBIF_XIN_HALT_CTRL1 0x204
#define MMSS_VBIF_AXI_HALT_CTRL0 0x208
diff --git a/drivers/video/fbdev/msm/mdss_mdp_intf_cmd.c b/drivers/video/fbdev/msm/mdss_mdp_intf_cmd.c
index c002ba4..947a3fe 100644
--- a/drivers/video/fbdev/msm/mdss_mdp_intf_cmd.c
+++ b/drivers/video/fbdev/msm/mdss_mdp_intf_cmd.c
@@ -52,8 +52,10 @@
u32 current_pp_num;
/*
* aux_pp_num will be set only when topology is using split-lm.
- * aux_pp_num will be used only when MDSS_QUIRK_DSC_RIGHT_ONLY_PU
- * quirk is set and on following partial updates.
+ * aux_pp_num will be used
+ * if right-only update on DUAL_LM_SINGLE_DISPLAY with 3D Mux
+ * or if MDSS_QUIRK_DSC_RIGHT_ONLY_PU quirk is set
+ * and on following partial updates.
*
* right-only update on DUAL_LM_SINGLE_DISPLAY with DSC_MERGE
* right-only update on DUAL_LM_DUAL_DISPLAY with DSC
@@ -76,6 +78,7 @@
struct mutex clk_mtx;
spinlock_t clk_lock;
spinlock_t koff_lock;
+ spinlock_t ctlstart_lock;
struct work_struct gate_clk_work;
struct delayed_work delayed_off_clk_work;
struct work_struct pp_done_work;
@@ -119,14 +122,32 @@
static bool __mdss_mdp_cmd_is_aux_pp_needed(struct mdss_data_type *mdata,
struct mdss_mdp_ctl *mctl)
{
- return (mdata && mctl && mctl->is_master &&
- mdss_has_quirk(mdata, MDSS_QUIRK_DSC_RIGHT_ONLY_PU) &&
- is_dsc_compression(&mctl->panel_data->panel_info) &&
- ((mctl->mfd->split_mode == MDP_DUAL_LM_DUAL_DISPLAY) ||
- ((mctl->mfd->split_mode == MDP_DUAL_LM_SINGLE_DISPLAY) &&
- (mctl->panel_data->panel_info.dsc_enc_total == 1))) &&
- !mctl->mixer_left->valid_roi &&
- mctl->mixer_right->valid_roi);
+ bool mux3d, merge, quirk, rightonly;
+
+ if (!mdata || !mctl || !mctl->is_master)
+ return false;
+
+ /*
+ * aux_pp_num will be used:
+ * if right-only update on DUAL_LM_SINGLE_DISPLAY with 3D Mux
+ * or if MDSS_QUIRK_DSC_RIGHT_ONLY_PU quirk is set
+ * and on following partial updates.
+ *
+ * right-only update on DUAL_LM_SINGLE_DISPLAY with DSC_MERGE
+ * right-only update on DUAL_LM_DUAL_DISPLAY with DSC
+ */
+ mux3d = ((mctl->mfd->split_mode == MDP_DUAL_LM_SINGLE_DISPLAY) &&
+ (mctl->opmode & MDSS_MDP_CTL_OP_PACK_3D_ENABLE));
+ merge = ((mctl->mfd->split_mode == MDP_DUAL_LM_SINGLE_DISPLAY) &&
+ (mctl->panel_data->panel_info.dsc_enc_total == 1));
+ quirk = (mdss_has_quirk(mdata, MDSS_QUIRK_DSC_RIGHT_ONLY_PU) &&
+ is_dsc_compression(&mctl->panel_data->panel_info) &&
+ ((mctl->mfd->split_mode == MDP_DUAL_LM_DUAL_DISPLAY) ||
+ merge));
+ rightonly = !mctl->mixer_left->valid_roi &&
+ mctl->mixer_right->valid_roi;
+
+ return ((mux3d || quirk) && rightonly);
}
static bool __mdss_mdp_cmd_is_panel_power_off(struct mdss_mdp_cmd_ctx *ctx)
@@ -147,15 +168,11 @@
u32 init;
u32 height;
- mdss_mdp_clk_ctrl(MDP_BLOCK_POWER_ON);
-
mixer = mdss_mdp_mixer_get(ctl, MDSS_MDP_MIXER_MUX_LEFT);
if (!mixer) {
mixer = mdss_mdp_mixer_get(ctl, MDSS_MDP_MIXER_MUX_RIGHT);
- if (!mixer) {
- mdss_mdp_clk_ctrl(MDP_BLOCK_POWER_OFF);
+ if (!mixer)
goto exit;
- }
}
init = mdss_mdp_pingpong_read(mixer->pingpong_base,
@@ -163,10 +180,8 @@
height = mdss_mdp_pingpong_read(mixer->pingpong_base,
MDSS_MDP_REG_PP_SYNC_CONFIG_HEIGHT) & 0xffff;
- if (height < init) {
- mdss_mdp_clk_ctrl(MDP_BLOCK_POWER_OFF);
+ if (height < init)
goto exit;
- }
cnt = mdss_mdp_pingpong_read(mixer->pingpong_base,
MDSS_MDP_REG_PP_INT_COUNT_VAL) & 0xffff;
@@ -176,13 +191,21 @@
else
cnt -= init;
- mdss_mdp_clk_ctrl(MDP_BLOCK_POWER_OFF);
-
pr_debug("cnt=%d init=%d height=%d\n", cnt, init, height);
exit:
return cnt;
}
+static inline u32 mdss_mdp_cmd_line_count_wrapper(struct mdss_mdp_ctl *ctl)
+{
+ u32 ret;
+
+ mdss_mdp_clk_ctrl(MDP_BLOCK_POWER_ON);
+ ret = mdss_mdp_cmd_line_count(ctl);
+ mdss_mdp_clk_ctrl(MDP_BLOCK_POWER_OFF);
+ return ret;
+}
+
static int mdss_mdp_tearcheck_enable(struct mdss_mdp_ctl *ctl, bool enable)
{
struct mdss_data_type *mdata = mdss_mdp_get_mdata();
@@ -335,6 +358,138 @@
return 0;
}
+/**
+ * mdss_mdp_cmd_autorefresh_pp_done() - pp done irq callback for autorefresh
+ * @arg: void pointer to the controller context.
+ *
+ * This function is the pp_done interrupt callback while disabling
+ * autorefresh. This function does not modify the kickoff count (koff_cnt).
+ */
+static void mdss_mdp_cmd_autorefresh_pp_done(void *arg)
+{
+ struct mdss_mdp_ctl *ctl = arg;
+ struct mdss_mdp_cmd_ctx *ctx = ctl->intf_ctx[MASTER_CTX];
+
+ if (!ctx) {
+ pr_err("%s: invalid ctx\n", __func__);
+ return;
+ }
+
+ mdss_mdp_irq_disable_nosync(MDSS_MDP_IRQ_TYPE_PING_PONG_COMP,
+ ctx->current_pp_num);
+ mdss_mdp_set_intr_callback_nosync(MDSS_MDP_IRQ_TYPE_PING_PONG_COMP,
+ ctx->current_pp_num, NULL, NULL);
+
+ MDSS_XLOG(ctl->num, atomic_read(&ctx->koff_cnt), ctx->current_pp_num);
+ complete_all(&ctx->autorefresh_ppdone);
+
+ pr_debug("%s: ctl_num=%d intf_num=%d ctx=%d cnt=%d\n", __func__,
+ ctl->num, ctl->intf_num, ctx->current_pp_num,
+ atomic_read(&ctx->koff_cnt));
+}
+
+static void mdss_mdp_cmd_wait4_autorefresh_pp(struct mdss_mdp_ctl *ctl)
+{
+ int rc;
+ u32 val, line_out, intr_type = MDSS_MDP_IRQ_TYPE_PING_PONG_COMP;
+ char __iomem *pp_base = ctl->mixer_left->pingpong_base;
+ struct mdss_mdp_cmd_ctx *ctx = ctl->intf_ctx[MASTER_CTX];
+
+ line_out = mdss_mdp_pingpong_read(pp_base, MDSS_MDP_REG_PP_LINE_COUNT);
+
+ MDSS_XLOG(ctl->num, line_out, ctl->mixer_left->roi.h);
+ pr_debug("ctl:%d line_out:%d\n", ctl->num, line_out);
+
+ if (!ctx) {
+ pr_err("%s: invalid ctx\n", __func__);
+ return;
+ }
+
+ if (line_out < ctl->mixer_left->roi.h) {
+ reinit_completion(&ctx->autorefresh_ppdone);
+
+ /* enable ping pong done */
+ mdss_mdp_set_intr_callback(intr_type, ctx->current_pp_num,
+ mdss_mdp_cmd_autorefresh_pp_done, ctl);
+ mdss_mdp_irq_enable(intr_type, ctx->current_pp_num);
+
+ /* wait for ping pong done */
+ rc = wait_for_completion_timeout(&ctx->autorefresh_ppdone,
+ KOFF_TIMEOUT);
+ if (rc <= 0) {
+ val = mdss_mdp_pingpong_read(pp_base,
+ MDSS_MDP_REG_PP_LINE_COUNT);
+ if (val == ctl->mixer_left->roi.h) {
+ mdss_mdp_irq_clear(ctl->mdata,
+ MDSS_MDP_IRQ_TYPE_PING_PONG_COMP,
+ ctx->current_pp_num);
+ mdss_mdp_irq_disable_nosync(intr_type,
+ ctx->current_pp_num);
+ mdss_mdp_set_intr_callback(intr_type,
+ ctx->current_pp_num, NULL, NULL);
+ } else {
+ pr_err("timedout waiting for ctl%d autorefresh pp done\n",
+ ctl->num);
+ MDSS_XLOG(0xbad3);
+ MDSS_XLOG_TOUT_HANDLER("mdp",
+ "vbif", "dbg_bus", "vbif_dbg_bus",
+ "panic");
+ }
+ }
+ }
+}
+
+static bool __disable_rd_ptr_from_te(char __iomem *pingpong_base)
+{
+ u32 cfg;
+ bool disabled;
+
+ cfg = mdss_mdp_pingpong_read(pingpong_base,
+ MDSS_MDP_REG_PP_SYNC_CONFIG_VSYNC);
+
+ disabled = BIT(20) & cfg;
+ cfg &= ~BIT(20);
+ mdss_mdp_pingpong_write(pingpong_base,
+ MDSS_MDP_REG_PP_SYNC_CONFIG_VSYNC, cfg);
+
+ return disabled;
+}
+
+static inline void __enable_rd_ptr_from_te(char __iomem *pingpong_base)
+{
+ u32 cfg;
+
+ cfg = mdss_mdp_pingpong_read(pingpong_base,
+ MDSS_MDP_REG_PP_SYNC_CONFIG_VSYNC);
+ cfg |= BIT(20);
+ mdss_mdp_pingpong_write(pingpong_base,
+ MDSS_MDP_REG_PP_SYNC_CONFIG_VSYNC, cfg);
+}
+
+/*
+ * __disable_autorefresh - disables autorefresh feature in the hw.
+ *
+ * To disable autorefresh, driver needs to make sure no transactions are
+ * on-going; for ensuring this, driver must:
+ *
+ * 1. Disable listening to the external TE (this gives extra time before
+ * trigger next transaction).
+ * 2. Wait for any on-going transaction (wait for ping pong done interrupt).
+ * 3. Disable auto-refresh.
+ * 4. Re-enable listening to the external panel TE.
+ *
+ * So it is responsability of the caller of this function to only call to
+ * disable autorefresh if no hw transaction is on-going (wait for ping pong)
+ * and if the listening for the external TE is disabled in the tear
+ * check logic (this to prevent any race conditions with the hw), as mentioned
+ * in the above steps.
+ */
+static inline void __disable_autorefresh(char __iomem *pingpong_base)
+{
+ mdss_mdp_pingpong_write(pingpong_base,
+ MDSS_MDP_REG_PP_AUTOREFRESH_CONFIG, 0x0);
+}
+
static int mdss_mdp_cmd_tearcheck_setup(struct mdss_mdp_cmd_ctx *ctx,
bool locked)
{
@@ -342,7 +497,7 @@
struct mdss_mdp_mixer *mixer = NULL, *mixer_right = NULL;
struct mdss_mdp_ctl *ctl = ctx->ctl;
struct mdss_data_type *mdata = mdss_mdp_get_mdata();
- u32 offset = 0;
+ bool rd_ptr_disabled = false;
mixer = mdss_mdp_mixer_get(ctl, MDSS_MDP_MIXER_MUX_LEFT);
if (mixer) {
@@ -352,21 +507,35 @@
*/
if (mdss_mdp_pingpong_read(mixer->pingpong_base,
MDSS_MDP_REG_PP_AUTOREFRESH_CONFIG) & BIT(31)) {
- offset = MDSS_MDP_REG_PP_AUTOREFRESH_CONFIG;
+
+ /* 1. disable rd pointer from the external te */
+ rd_ptr_disabled =
+ __disable_rd_ptr_from_te(mixer->pingpong_base);
+
+ /* 2. wait for previous transfer to finish */
+ mdss_mdp_cmd_wait4_autorefresh_pp(ctl);
+
+ /* 3. disable autorefresh */
if (is_pingpong_split(ctl->mfd))
- writel_relaxed(0x0,
- (mdata->slave_pingpong_base + offset));
+ __disable_autorefresh(
+ mdata->slave_pingpong_base);
+
if (is_split_lm(ctl->mfd)) {
- mixer_right =
- mdss_mdp_mixer_get(ctl,
- MDSS_MDP_MIXER_MUX_RIGHT);
+ mixer_right = mdss_mdp_mixer_get(ctl,
+ MDSS_MDP_MIXER_MUX_RIGHT);
+
if (mixer_right)
- writel_relaxed(0x0,
- (mixer_right->pingpong_base + offset));
+ __disable_autorefresh(
+ mixer_right->pingpong_base);
}
- mdss_mdp_pingpong_write(mixer->pingpong_base,
- MDSS_MDP_REG_PP_AUTOREFRESH_CONFIG, 0x0);
+
+ __disable_autorefresh(mixer->pingpong_base);
pr_debug("%s: disabling auto refresh\n", __func__);
+
+ /* 4. re-enable rd pointer from te (if was enabled) */
+ if (rd_ptr_disabled)
+ __enable_rd_ptr_from_te(mixer->pingpong_base);
+
}
rc = mdss_mdp_cmd_tearcheck_cfg(mixer, ctx, locked);
if (rc)
@@ -527,6 +696,8 @@
pr_err("%s cannot find master ctl\n",
__func__);
WARN_ON(1);
+ rc = -EINVAL;
+ goto exit;
}
/*
* We have both controllers but sctl has the Master,
@@ -999,6 +1170,7 @@
vsync_time = ktime_get();
ctl->vsync_cnt++;
MDSS_XLOG(ctl->num, atomic_read(&ctx->koff_cnt));
+ trace_mdp_cmd_readptr_done(ctl->num, atomic_read(&ctx->koff_cnt));
complete_all(&ctx->rdptr_done);
/* If caller is waiting for the read pointer, notify. */
@@ -1424,36 +1596,6 @@
return 0;
}
-/**
- * mdss_mdp_cmd_autorefresh_pp_done() - pp done irq callback for autorefresh
- * @arg: void pointer to the controller context.
- *
- * This function is the pp_done interrupt callback while disabling
- * autorefresh. This function does not modify the kickoff count (koff_cnt).
- */
-static void mdss_mdp_cmd_autorefresh_pp_done(void *arg)
-{
- struct mdss_mdp_ctl *ctl = arg;
- struct mdss_mdp_cmd_ctx *ctx = ctl->intf_ctx[MASTER_CTX];
-
- if (!ctx) {
- pr_err("%s: invalid ctx\n", __func__);
- return;
- }
-
- mdss_mdp_irq_disable_nosync(MDSS_MDP_IRQ_TYPE_PING_PONG_COMP,
- ctx->current_pp_num);
- mdss_mdp_set_intr_callback_nosync(MDSS_MDP_IRQ_TYPE_PING_PONG_COMP,
- ctx->current_pp_num, NULL, NULL);
-
- MDSS_XLOG(ctl->num, atomic_read(&ctx->koff_cnt), ctx->current_pp_num);
- complete_all(&ctx->autorefresh_ppdone);
-
- pr_debug("%s: ctl_num=%d intf_num=%d ctx=%d cnt=%d\n", __func__,
- ctl->num, ctl->intf_num, ctx->current_pp_num,
- atomic_read(&ctx->koff_cnt));
-}
-
static void pingpong_done_work(struct work_struct *work)
{
u32 status;
@@ -1856,22 +1998,34 @@
bool handoff)
{
struct mdss_panel_data *pdata;
- struct mdss_mdp_ctl *sctl = mdss_mdp_get_split_ctl(ctl);
+ struct mdss_mdp_ctl *sctl = NULL;
+ struct mdss_mdp_cmd_ctx *sctx = NULL;
struct dsi_panel_clk_ctrl clk_ctrl;
int ret = 0;
+ /* Get both controllers in the correct order for dual displays */
+ mdss_mdp_get_split_display_ctls(&ctl, &sctl);
+
+ if (sctl)
+ sctx = (struct mdss_mdp_cmd_ctx *) sctl->intf_ctx[MASTER_CTX];
+
+ /* In pingpong split we have single controller, dual context */
+ if (is_pingpong_split(ctl->mfd))
+ sctx = (struct mdss_mdp_cmd_ctx *) ctl->intf_ctx[SLAVE_CTX];
+
pdata = ctl->panel_data;
clk_ctrl.state = MDSS_DSI_CLK_OFF;
clk_ctrl.client = DSI_CLK_REQ_MDP_CLIENT;
- if (sctl) {
+
+ if (sctx) { /* then slave */
u32 flags = CTL_INTF_EVENT_FLAG_SKIP_BROADCAST;
- if (is_pingpong_split(sctl->mfd))
+ if (sctx->pingpong_split_slave)
flags |= CTL_INTF_EVENT_FLAG_SLAVE_INTF;
- mdss_mdp_ctl_intf_event(sctl, MDSS_EVENT_PANEL_CLK_CTRL,
- (void *)&clk_ctrl, flags);
+ mdss_mdp_ctl_intf_event(sctx->ctl, MDSS_EVENT_PANEL_CLK_CTRL,
+ (void *)&clk_ctrl, flags);
}
mdss_mdp_ctl_intf_event(ctl, MDSS_EVENT_PANEL_CLK_CTRL,
@@ -2068,11 +2222,27 @@
return;
pinfo = &ctl->panel_data->panel_info;
- if (pinfo->compression_mode != COMPRESSION_DSC)
- return;
+ if (pinfo->compression_mode != COMPRESSION_DSC) {
+ /*
+ * Check for a dynamic resolution switch from DSC On to
+ * DSC Off and call mdss_mdp_ctl_dsc_setup to disable DSC
+ */
+ if (ctl->pending_mode_switch == SWITCH_RESOLUTION) {
+ if (ctl->mixer_left && ctl->mixer_left->dsc_enabled)
+ changed = true;
+ if (is_split_lm(ctl->mfd) &&
+ ctl->mixer_right &&
+ ctl->mixer_right->dsc_enabled)
+ changed = true;
+ } else {
+ return;
+ }
+ }
- changed = ctl->mixer_left->roi_changed;
- if (is_split_lm(ctl->mfd))
+ if (ctl->mixer_left)
+ changed |= ctl->mixer_left->roi_changed;
+ if (is_split_lm(ctl->mfd) &&
+ ctl->mixer_right)
changed |= ctl->mixer_right->roi_changed;
if (changed)
@@ -2312,7 +2482,6 @@
struct mdss_mdp_cmd_ctx *ctx = mctl->intf_ctx[MASTER_CTX];
char __iomem *pp_base;
u32 autorefresh_state;
- u32 cfg;
if (!mctl->is_master)
return;
@@ -2332,11 +2501,8 @@
* instruct MDP to ignore the panel TE so the next auto-refresh
* is delayed until flush bits are set.
*/
- cfg = mdss_mdp_pingpong_read(pp_base,
- MDSS_MDP_REG_PP_SYNC_CONFIG_VSYNC);
- cfg &= ~BIT(20);
- mdss_mdp_pingpong_write(pp_base,
- MDSS_MDP_REG_PP_SYNC_CONFIG_VSYNC, cfg);
+ __disable_rd_ptr_from_te(pp_base);
+
ctx->ignore_external_te = true;
}
@@ -2348,7 +2514,6 @@
{
struct mdss_mdp_cmd_ctx *ctx = mctl->intf_ctx[MASTER_CTX];
char __iomem *pp_base;
- u32 cfg;
if (!mctl->is_master)
return;
@@ -2367,60 +2532,12 @@
pp_base = mctl->mixer_left->pingpong_base;
/* enable MDP to listen to the TE */
- cfg = mdss_mdp_pingpong_read(pp_base,
- MDSS_MDP_REG_PP_SYNC_CONFIG_VSYNC);
- cfg |= BIT(20);
- mdss_mdp_pingpong_write(pp_base,
- MDSS_MDP_REG_PP_SYNC_CONFIG_VSYNC, cfg);
+ __enable_rd_ptr_from_te(pp_base);
+
ctx->ignore_external_te = false;
}
}
-static void mdss_mdp_cmd_wait4_autorefresh_pp(struct mdss_mdp_ctl *ctl)
-{
- int rc;
- u32 val, line_out, intr_type = MDSS_MDP_IRQ_TYPE_PING_PONG_COMP;
- char __iomem *pp_base = ctl->mixer_left->pingpong_base;
- struct mdss_mdp_cmd_ctx *ctx = ctl->intf_ctx[MASTER_CTX];
-
- line_out = mdss_mdp_pingpong_read(pp_base, MDSS_MDP_REG_PP_LINE_COUNT);
-
- MDSS_XLOG(ctl->num, line_out, ctl->mixer_left->roi.h);
-
- if ((line_out < ctl->mixer_left->roi.h) && line_out) {
- reinit_completion(&ctx->autorefresh_ppdone);
-
- /* enable ping pong done */
- mdss_mdp_set_intr_callback(intr_type, ctx->current_pp_num,
- mdss_mdp_cmd_autorefresh_pp_done, ctl);
- mdss_mdp_irq_enable(intr_type, ctx->current_pp_num);
-
- /* wait for ping pong done */
- rc = wait_for_completion_timeout(&ctx->autorefresh_ppdone,
- KOFF_TIMEOUT);
- if (rc <= 0) {
- val = mdss_mdp_pingpong_read(pp_base,
- MDSS_MDP_REG_PP_LINE_COUNT);
- if (val == ctl->mixer_left->roi.h) {
- mdss_mdp_irq_clear(ctl->mdata,
- MDSS_MDP_IRQ_TYPE_PING_PONG_COMP,
- ctx->current_pp_num);
- mdss_mdp_irq_disable_nosync(intr_type,
- ctx->current_pp_num);
- mdss_mdp_set_intr_callback(intr_type,
- ctx->current_pp_num, NULL, NULL);
- } else {
- pr_err("timedout waiting for ctl%d autorefresh pp done\n",
- ctl->num);
- MDSS_XLOG(0xbad3);
- MDSS_XLOG_TOUT_HANDLER("mdp",
- "vbif", "dbg_bus", "vbif_dbg_bus",
- "panic");
- }
- }
- }
-}
-
static void mdss_mdp_cmd_autorefresh_done(void *arg)
{
struct mdss_mdp_ctl *ctl = arg;
@@ -2494,10 +2611,11 @@
struct mdss_mdp_cmd_ctx *ctx = ctl->intf_ctx[MASTER_CTX];
unsigned long flags;
unsigned long autorefresh_timeout;
+ u32 timeout_us = 20000;
line_out = mdss_mdp_pingpong_read(pp_base, MDSS_MDP_REG_PP_LINE_COUNT);
- MDSS_XLOG(ctl->num, line_out, ctl->mixer_left->roi.h);
+ MDSS_XLOG(ctl->num, line_out, ctl->mixer_left->roi.h, 0x111);
reinit_completion(&ctx->autorefresh_done);
@@ -2556,6 +2674,26 @@
"dsi1_ctrl", "dsi1_phy", "vbif", "vbif_nrt",
"dbg_bus", "vbif_dbg_bus", "panic");
}
+
+ /* once autorefresh is done, wait for write pointer */
+ line_out = mdss_mdp_pingpong_read(pp_base, MDSS_MDP_REG_PP_LINE_COUNT);
+ MDSS_XLOG(ctl->num, line_out, 0x222);
+
+ /* wait until the first line is out to make sure transfer is on-going */
+ rc = readl_poll_timeout(pp_base +
+ MDSS_MDP_REG_PP_LINE_COUNT, val,
+ (val & 0xffff) >= 1, 10, timeout_us);
+
+ if (rc) {
+ pr_err("timed out waiting for line out ctl:%d val:0x%x\n",
+ ctl->num, val);
+ MDSS_XLOG(0xbad5, val);
+ MDSS_XLOG_TOUT_HANDLER("mdp", "dsi0_ctrl", "dsi0_phy",
+ "dsi1_ctrl", "dsi1_phy", "vbif", "vbif_nrt",
+ "dbg_bus", "vbif_dbg_bus", "panic");
+ }
+
+ MDSS_XLOG(val, 0x333);
}
/* caller needs to hold autorefresh_lock before calling this function */
@@ -2623,11 +2761,10 @@
mdss_mdp_cmd_wait4_autorefresh_pp(sctl);
/* disable autorefresh */
- mdss_mdp_pingpong_write(pp_base, MDSS_MDP_REG_PP_AUTOREFRESH_CONFIG, 0);
+ __disable_autorefresh(pp_base);
if (is_pingpong_split(ctl->mfd))
- mdss_mdp_pingpong_write(mdata->slave_pingpong_base,
- MDSS_MDP_REG_PP_AUTOREFRESH_CONFIG, 0);
+ __disable_autorefresh(mdata->slave_pingpong_base);
ctx->autorefresh_state = MDP_AUTOREFRESH_OFF;
ctx->autorefresh_frame_cnt = 0;
@@ -2643,12 +2780,42 @@
return 0;
}
+static bool wait_for_read_ptr_if_late(struct mdss_mdp_ctl *ctl,
+ struct mdss_mdp_ctl *sctl, struct mdss_panel_info *pinfo)
+{
+ u32 line_count;
+ u32 sline_count = 0;
+ bool ret = true;
+ u32 low_threshold = pinfo->mdp_koff_thshold_low;
+ u32 high_threshold = pinfo->mdp_koff_thshold_high;
+
+ /* read the line count */
+ line_count = mdss_mdp_cmd_line_count(ctl);
+ if (sctl)
+ sline_count = mdss_mdp_cmd_line_count(sctl);
+
+ /* if line count is between the range, return to trigger transfer */
+ if (((line_count > low_threshold) && (line_count < high_threshold)) &&
+ (!sctl || ((sline_count > low_threshold) &&
+ (sline_count < high_threshold))))
+ ret = false;
+
+ pr_debug("threshold:[%d, %d]\n", low_threshold, high_threshold);
+ pr_debug("line:%d sline:%d ret:%d\n", line_count, sline_count, ret);
+ MDSS_XLOG(line_count, sline_count, ret);
+
+ return ret;
+}
static void __mdss_mdp_kickoff(struct mdss_mdp_ctl *ctl,
- struct mdss_mdp_cmd_ctx *ctx)
+ struct mdss_mdp_ctl *sctl, struct mdss_mdp_cmd_ctx *ctx)
{
struct mdss_data_type *mdata = mdss_mdp_get_mdata();
bool is_pp_split = is_pingpong_split(ctl->mfd);
+ struct mdss_panel_info *pinfo = NULL;
+
+ if (ctl->panel_data)
+ pinfo = &ctl->panel_data->panel_info;
MDSS_XLOG(ctx->autorefresh_state);
@@ -2673,12 +2840,71 @@
ctx->autorefresh_state = MDP_AUTOREFRESH_ON;
} else {
+
+ /*
+ * Some panels can require that mdp is within some range
+ * of the scanlines in order to trigger the tansfer.
+ * If that is the case, make sure the panel scanline
+ * is within the limit to start.
+ * Acquire an spinlock for this operation to raise the
+ * priority of this thread and make sure the context
+ * is maintained, so we can have the less time possible
+ * between the check of the scanline and the kickoff.
+ */
+ if (pinfo && pinfo->mdp_koff_thshold) {
+ spin_lock(&ctx->ctlstart_lock);
+ if (wait_for_read_ptr_if_late(ctl, sctl, pinfo)) {
+ spin_unlock(&ctx->ctlstart_lock);
+ usleep_range(pinfo->mdp_koff_delay,
+ pinfo->mdp_koff_delay + 10);
+ spin_lock(&ctx->ctlstart_lock);
+ }
+ }
+
/* SW Kickoff */
mdss_mdp_ctl_write(ctl, MDSS_MDP_REG_CTL_START, 1);
MDSS_XLOG(0x11, ctx->autorefresh_state);
+
+ if (pinfo && pinfo->mdp_koff_thshold)
+ spin_unlock(&ctx->ctlstart_lock);
}
}
+static int mdss_mdp_cmd_wait4_vsync(struct mdss_mdp_ctl *ctl)
+{
+ int rc = 0;
+ struct mdss_mdp_cmd_ctx *ctx = ctl->intf_ctx[MASTER_CTX];
+
+ if (!ctx) {
+ pr_err("invalid context to wait for vsync\n");
+ return -ENODEV;
+ }
+
+ atomic_inc(&ctx->rdptr_cnt);
+
+ /* enable clks and rd_ptr interrupt */
+ mdss_mdp_setup_vsync(ctx, true);
+
+ /* wait for read pointer */
+ MDSS_XLOG(atomic_read(&ctx->rdptr_cnt));
+ pr_debug("%s: wait for vsync cnt:%d\n",
+ __func__, atomic_read(&ctx->rdptr_cnt));
+
+ rc = mdss_mdp_cmd_wait4readptr(ctx);
+
+ /* wait for 1ms to make sure we are out from trigger window */
+ usleep_range(1000, 1010);
+
+ /* disable rd_ptr interrupt */
+ mdss_mdp_setup_vsync(ctx, false);
+
+ MDSS_XLOG(ctl->num);
+ pr_debug("%s: out from wait for rd_ptr ctl:%d\n", __func__, ctl->num);
+
+ return rc;
+}
+
+
/*
* There are 3 partial update possibilities
* left only ==> enable left pingpong_done
@@ -2807,7 +3033,7 @@
}
/* Kickoff */
- __mdss_mdp_kickoff(ctl, ctx);
+ __mdss_mdp_kickoff(ctl, sctl, ctx);
mdss_mdp_cmd_post_programming(ctl);
@@ -3044,8 +3270,18 @@
* mode.
*/
send_panel_events = true;
- if (mdss_panel_is_power_on_ulp(panel_power_state))
+ if (mdss_panel_is_power_on_ulp(panel_power_state)) {
turn_off_clocks = true;
+ } else if (atomic_read(&ctx->koff_cnt)) {
+ /*
+ * Transition from interactive to low power
+ * Wait for kickoffs to finish
+ */
+ MDSS_XLOG(ctl->num, atomic_read(&ctx->koff_cnt));
+ mdss_mdp_cmd_wait4pingpong(ctl, NULL);
+ if (sctl)
+ mdss_mdp_cmd_wait4pingpong(sctl, NULL);
+ }
} else {
/* Transitions between low power and ultra low power */
if (mdss_panel_is_power_on_ulp(panel_power_state)) {
@@ -3074,6 +3310,8 @@
(void *)&ctx->intf_mdp_callback,
CTL_INTF_EVENT_FLAG_DEFAULT);
+ mdss_mdp_tearcheck_enable(ctl, true);
+
ctx->intf_stopped = 0;
if (sctx)
sctx->intf_stopped = 0;
@@ -3139,6 +3377,7 @@
ctl->ops.add_vsync_handler = NULL;
ctl->ops.remove_vsync_handler = NULL;
ctl->ops.reconfigure = NULL;
+ ctl->ops.wait_for_vsync_fnc = NULL;
end:
if (!IS_ERR_VALUE((unsigned long)ret)) {
@@ -3241,6 +3480,7 @@
init_completion(&ctx->autorefresh_done);
spin_lock_init(&ctx->clk_lock);
spin_lock_init(&ctx->koff_lock);
+ spin_lock_init(&ctx->ctlstart_lock);
mutex_init(&ctx->clk_mtx);
mutex_init(&ctx->mdp_rdptr_lock);
mutex_init(&ctx->mdp_wrptr_lock);
@@ -3497,12 +3737,24 @@
}
ctl->switch_with_handoff = false;
}
+ /*
+ * keep track of vsync, so it can be enabled as part
+ * of the post switch sequence
+ */
+ if (ctl->vsync_handler.enabled)
+ ctl->need_vsync_on = true;
mdss_mdp_ctl_stop(ctl, MDSS_PANEL_POWER_OFF);
mdss_mdp_ctl_intf_event(ctl,
MDSS_EVENT_DSI_DYNAMIC_SWITCH,
(void *) mode, CTL_INTF_EVENT_FLAG_DEFAULT);
} else {
+ if (ctl->need_vsync_on &&
+ ctl->ops.add_vsync_handler) {
+ ctl->ops.add_vsync_handler(ctl,
+ &ctl->vsync_handler);
+ ctl->need_vsync_on = false;
+ }
mdss_mdp_clk_ctrl(MDP_BLOCK_POWER_OFF);
}
}
@@ -3529,12 +3781,13 @@
ctl->ops.wait_pingpong = mdss_mdp_cmd_wait4pingpong;
ctl->ops.add_vsync_handler = mdss_mdp_cmd_add_vsync_handler;
ctl->ops.remove_vsync_handler = mdss_mdp_cmd_remove_vsync_handler;
- ctl->ops.read_line_cnt_fnc = mdss_mdp_cmd_line_count;
+ ctl->ops.read_line_cnt_fnc = mdss_mdp_cmd_line_count_wrapper;
ctl->ops.restore_fnc = mdss_mdp_cmd_restore;
ctl->ops.early_wake_up_fnc = mdss_mdp_cmd_early_wake_up;
ctl->ops.reconfigure = mdss_mdp_cmd_reconfigure;
ctl->ops.pre_programming = mdss_mdp_cmd_pre_programming;
ctl->ops.update_lineptr = mdss_mdp_cmd_update_lineptr;
+ ctl->ops.wait_for_vsync_fnc = mdss_mdp_cmd_wait4_vsync;
pr_debug("%s:-\n", __func__);
return 0;
diff --git a/drivers/video/fbdev/msm/mdss_mdp_intf_video.c b/drivers/video/fbdev/msm/mdss_mdp_intf_video.c
index 591fa38..dba3b0d 100644
--- a/drivers/video/fbdev/msm/mdss_mdp_intf_video.c
+++ b/drivers/video/fbdev/msm/mdss_mdp_intf_video.c
@@ -544,8 +544,10 @@
ctl_flush |= (BIT(31) >>
(sctx->intf_num - MDSS_MDP_INTF0));
}
+ MDSS_XLOG(ctl->intf_num, sctx?sctx->intf_num:0xf00, ctl_flush,
+ mdss_mdp_ctl_read(ctl, MDSS_MDP_REG_CTL_FLUSH));
mdss_mdp_ctl_write(ctl, MDSS_MDP_REG_CTL_FLUSH, ctl_flush);
- MDSS_XLOG(ctl->intf_num, sctx?sctx->intf_num:0xf00, ctl_flush);
+
}
static inline void video_vsync_irq_enable(struct mdss_mdp_ctl *ctl, bool clear)
@@ -929,6 +931,13 @@
{
int intfs_num, ret = 0;
+ if (ctl->cdm) {
+ if (!mdss_mdp_cdm_destroy(ctl->cdm))
+ mdss_mdp_ctl_write(ctl,
+ MDSS_MDP_REG_CTL_FLUSH, BIT(26));
+ ctl->cdm = NULL;
+ }
+
intfs_num = ctl->intf_num - MDSS_MDP_INTF0;
ret = mdss_mdp_video_intfs_stop(ctl, ctl->panel_data, intfs_num);
if (IS_ERR_VALUE((unsigned long)ret)) {
@@ -941,10 +950,6 @@
mdss_mdp_ctl_reset(ctl, false);
ctl->intf_ctx[MASTER_CTX] = NULL;
- if (ctl->cdm) {
- mdss_mdp_cdm_destroy(ctl->cdm);
- ctl->cdm = NULL;
- }
return 0;
}
@@ -1556,13 +1561,43 @@
return 0;
}
+static int mdss_mdp_video_splash_handoff(struct mdss_mdp_ctl *ctl)
+{
+ int i, ret = 0;
+ u32 data, flush;
+
+ ret = mdss_mdp_ctl_intf_event(ctl, MDSS_EVENT_CONT_SPLASH_BEGIN,
+ NULL, CTL_INTF_EVENT_FLAG_DEFAULT);
+
+ if (ret) {
+ pr_err("%s:ctl%d failed to handle 'CONT_SPLASH_BEGIN' event\n"
+ , __func__, ctl->num);
+ return ret;
+ }
+
+ /* clear up mixer0 and mixer1 */
+ flush = 0;
+ for (i = 0; i < 2; i++) {
+ data = mdss_mdp_ctl_read(ctl,
+ MDSS_MDP_REG_CTL_LAYER(i));
+ if (data) {
+ mdss_mdp_ctl_write(ctl,
+ MDSS_MDP_REG_CTL_LAYER(i),
+ MDSS_MDP_LM_BORDER_COLOR);
+ flush |= (0x40 << i);
+ }
+ }
+ mdss_mdp_ctl_write(ctl, MDSS_MDP_REG_CTL_FLUSH, flush);
+
+ return ret;
+}
+
int mdss_mdp_video_reconfigure_splash_done(struct mdss_mdp_ctl *ctl,
bool handoff)
{
struct mdss_panel_data *pdata;
- int i, ret = 0, off;
- u32 data, flush;
- struct mdss_mdp_video_ctx *ctx;
+ int ret = 0, off;
+ struct mdss_mdp_video_ctx *ctx, *sctx = NULL;
struct mdss_mdp_ctl *sctl;
if (!ctl) {
@@ -1586,41 +1621,43 @@
pdata->panel_info.cont_splash_enabled = 0;
sctl = mdss_mdp_get_split_ctl(ctl);
- if (sctl)
+ if (sctl) {
sctl->panel_data->panel_info.cont_splash_enabled = 0;
- else if (ctl->panel_data->next && is_pingpong_split(ctl->mfd))
+ sctx = (struct mdss_mdp_video_ctx *) sctl->intf_ctx[MASTER_CTX];
+ } else if (ctl->panel_data->next && is_pingpong_split(ctl->mfd)) {
ctl->panel_data->next->panel_info.cont_splash_enabled = 0;
+ sctx = (struct mdss_mdp_video_ctx *) ctl->intf_ctx[SLAVE_CTX];
+ }
if (!handoff) {
- ret = mdss_mdp_ctl_intf_event(ctl, MDSS_EVENT_CONT_SPLASH_BEGIN,
- NULL, CTL_INTF_EVENT_FLAG_DEFAULT);
- if (ret) {
- pr_err("%s: Failed to handle 'CONT_SPLASH_BEGIN' event\n"
- , __func__);
- return ret;
- }
+ ret = mdss_mdp_video_splash_handoff(ctl);
- /* clear up mixer0 and mixer1 */
- flush = 0;
- for (i = 0; i < 2; i++) {
- data = mdss_mdp_ctl_read(ctl,
- MDSS_MDP_REG_CTL_LAYER(i));
- if (data) {
- mdss_mdp_ctl_write(ctl,
- MDSS_MDP_REG_CTL_LAYER(i),
- MDSS_MDP_LM_BORDER_COLOR);
- flush |= (0x40 << i);
- }
- }
- mdss_mdp_ctl_write(ctl, MDSS_MDP_REG_CTL_FLUSH, flush);
+ if (!ret && sctl)
+ ret = mdss_mdp_video_splash_handoff(sctl);
+
+ if (ret)
+ return ret;
mdp_video_write(ctx, MDSS_MDP_REG_INTF_TIMING_ENGINE_EN, 0);
+
+ if (sctx)
+ mdp_video_write(sctx,
+ MDSS_MDP_REG_INTF_TIMING_ENGINE_EN, 0);
+
+ mdss_mdp_video_timegen_flush(ctl, sctx);
+
/* wait for 1 VSYNC for the pipe to be unstaged */
msleep(20);
ret = mdss_mdp_ctl_intf_event(ctl,
MDSS_EVENT_CONT_SPLASH_FINISH, NULL,
CTL_INTF_EVENT_FLAG_DEFAULT);
+
+ if (!ret && sctl)
+ ret = mdss_mdp_ctl_intf_event(sctl,
+ MDSS_EVENT_CONT_SPLASH_FINISH, NULL,
+ CTL_INTF_EVENT_FLAG_DEFAULT);
+
}
return ret;
@@ -1673,7 +1710,7 @@
static void mdss_mdp_fetch_start_config(struct mdss_mdp_video_ctx *ctx,
struct mdss_mdp_ctl *ctl)
{
- int fetch_start, fetch_enable, v_total, h_total;
+ int fetch_start = 0, fetch_enable, v_total, h_total;
struct mdss_data_type *mdata;
struct mdss_panel_info *pinfo = &ctl->panel_data->panel_info;
@@ -1682,6 +1719,15 @@
pinfo->prg_fet = mdss_mdp_get_prefetch_lines(pinfo);
if (!pinfo->prg_fet) {
pr_debug("programmable fetch is not needed/supported\n");
+
+ fetch_enable = mdp_video_read(ctx, MDSS_MDP_REG_INTF_CONFIG);
+ fetch_enable &= ~BIT(31);
+
+ mdp_video_write(ctx, MDSS_MDP_REG_INTF_CONFIG, fetch_enable);
+ mdp_video_write(ctx, MDSS_MDP_REG_INTF_PROG_FETCH_START,
+ fetch_start);
+
+ MDSS_XLOG(ctx->intf_num, fetch_enable, fetch_start);
return;
}
@@ -2186,6 +2232,7 @@
ctl->ops.config_fps_fnc = mdss_mdp_video_config_fps;
ctl->ops.early_wake_up_fnc = mdss_mdp_video_early_wake_up;
ctl->ops.update_lineptr = mdss_mdp_video_lineptr_ctrl;
+ ctl->ops.wait_for_vsync_fnc = NULL;
return 0;
}
diff --git a/drivers/video/fbdev/msm/mdss_mdp_intf_writeback.c b/drivers/video/fbdev/msm/mdss_mdp_intf_writeback.c
index 46f25dd..3d63890 100644
--- a/drivers/video/fbdev/msm/mdss_mdp_intf_writeback.c
+++ b/drivers/video/fbdev/msm/mdss_mdp_intf_writeback.c
@@ -518,7 +518,9 @@
}
if (ctl->cdm) {
- mdss_mdp_cdm_destroy(ctl->cdm);
+ if (!mdss_mdp_cdm_destroy(ctl->cdm))
+ mdss_mdp_ctl_write(ctl,
+ MDSS_MDP_REG_CTL_FLUSH, BIT(26));
ctl->cdm = NULL;
}
return 0;
diff --git a/drivers/video/fbdev/msm/mdss_mdp_layer.c b/drivers/video/fbdev/msm/mdss_mdp_layer.c
index d898e7e..a7692f0 100644
--- a/drivers/video/fbdev/msm/mdss_mdp_layer.c
+++ b/drivers/video/fbdev/msm/mdss_mdp_layer.c
@@ -103,14 +103,15 @@
struct mdss_data_type *mdata = mdss_mdp_get_mdata();
if ((layer->z_order != HW_CURSOR_STAGE(mdata))
+ || layer->flags & MDP_LAYER_FLIP_LR
|| layer->src_rect.w > mdata->max_cursor_size
|| layer->src_rect.h > mdata->max_cursor_size
|| layer->src_rect.w != layer->dst_rect.w
|| layer->src_rect.h != layer->dst_rect.h
|| !mdata->ncursor_pipes) {
- pr_err("Incorrect cursor configs for pipe:%d, cursor_pipes:%d, z_order:%d\n",
+ pr_err("Incorrect cursor configs for pipe:0x%x, ncursor_pipes:%d, z_order:%d, flags:0x%x\n",
layer->pipe_ndx, mdata->ncursor_pipes,
- layer->z_order);
+ layer->z_order, layer->flags);
pr_err("src:{%d,%d,%d,%d}, dst:{%d,%d,%d,%d}\n",
layer->src_rect.x, layer->src_rect.y,
layer->src_rect.w, layer->src_rect.h,
@@ -344,12 +345,18 @@
*/
if (pipe->csc_coeff_set != layer->color_space) {
src_fmt = mdss_mdp_get_format_params(layer->buffer.format);
- if (pipe->src_fmt->is_yuv && src_fmt && src_fmt->is_yuv) {
- status = -EPERM;
- pr_err("csc change is not permitted on used pipe\n");
+ if (!src_fmt) {
+ pr_err("Invalid layer format %d\n",
+ layer->buffer.format);
+ status = -EINVAL;
+ } else {
+ if (pipe->src_fmt->is_yuv && src_fmt &&
+ src_fmt->is_yuv) {
+ status = -EPERM;
+ pr_err("csc change is not permitted on used pipe\n");
+ }
}
}
-
return status;
}
@@ -484,9 +491,6 @@
pipe->comp_ratio = layer->buffer.comp_ratio;
- if (mfd->panel_orientation)
- layer->flags ^= mfd->panel_orientation;
-
pipe->mixer_left = mixer;
pipe->mfd = mfd;
pipe->play_cnt = 0;
@@ -561,6 +565,15 @@
goto end;
}
+ /* scaling is not allowed for solid_fill layers */
+ if ((pipe->flags & MDP_SOLID_FILL) &&
+ ((pipe->src.w != pipe->dst.w) ||
+ (pipe->src.h != pipe->dst.h))) {
+ pr_err("solid fill pipe:%d cannot have scaling\n", pipe->num);
+ ret = -EINVAL;
+ goto end;
+ }
+
/*
* unstage the pipe if it's current z_order does not match with new
* z_order because client may only call the validate.
@@ -625,13 +638,6 @@
pipe->multirect.mode = vinfo->multirect.mode;
pipe->mixer_stage = layer->z_order;
- if (mfd->panel_orientation & MDP_FLIP_LR)
- pipe->dst.x = pipe->mixer_left->width - pipe->dst.x -
- pipe->dst.w;
- if (mfd->panel_orientation & MDP_FLIP_UD)
- pipe->dst.y = pipe->mixer_left->height - pipe->dst.y -
- pipe->dst.h;
-
memcpy(&pipe->layer, layer, sizeof(struct mdp_input_layer));
mdss_mdp_overlay_set_chroma_sample(pipe);
@@ -1175,6 +1181,11 @@
pr_debug("pipe count:: secure display:%d non-secure:%d\n",
sd_pipes, nonsd_pipes);
+ if (mdss_get_sd_client_cnt() && !mdp5_data->sd_enabled) {
+ pr_err("Secure session already enabled for other client\n");
+ return -EINVAL;
+ }
+
mdp5_data->sd_transition_state = SD_TRANSITION_NONE;
if (!__is_sd_state_valid(sd_pipes, nonsd_pipes, panel_type,
mdp5_data->sd_enabled)) {
@@ -1188,7 +1199,14 @@
} else if (mdp5_data->sd_enabled && !sd_pipes) {
mdp5_data->sd_transition_state =
SD_TRANSITION_SECURE_TO_NON_SECURE;
+ } else if (mdp5_data->ctl->is_video_mode &&
+ ((sd_pipes && !mdp5_data->sd_enabled) ||
+ (!sd_pipes && mdp5_data->sd_enabled)) &&
+ !mdp5_data->cache_null_commit) {
+ pr_err("NULL commit missing before display secure session entry/exit\n");
+ ret = -EINVAL;
}
+
return ret;
}
diff --git a/drivers/video/fbdev/msm/mdss_mdp_overlay.c b/drivers/video/fbdev/msm/mdss_mdp_overlay.c
index 672b634..af6e4ce 100644
--- a/drivers/video/fbdev/msm/mdss_mdp_overlay.c
+++ b/drivers/video/fbdev/msm/mdss_mdp_overlay.c
@@ -2904,6 +2904,7 @@
if (ctl->ops.wait_pingpong && mdp5_data->mdata->serialize_wait4pp)
mdss_mdp_display_wait4pingpong(ctl, true);
+ mdp5_data->cache_null_commit = list_empty(&mdp5_data->pipes_used);
sd_transition_state = mdp5_data->sd_transition_state;
if (sd_transition_state != SD_TRANSITION_NONE) {
ret = __config_secure_display(mdp5_data);
@@ -2936,6 +2937,7 @@
ATRACE_BEGIN("sspp_programming");
ret = __overlay_queue_pipes(mfd);
ATRACE_END("sspp_programming");
+
mutex_unlock(&mdp5_data->list_lock);
mdp5_data->kickoff_released = false;
@@ -3864,7 +3866,8 @@
struct mdss_overlay_private *mdp5_data = mfd_to_mdp5_data(mfd);
struct dynamic_fps_data data = {0};
- if (!mdp5_data->ctl || !mdss_mdp_ctl_is_power_on(mdp5_data->ctl)) {
+ if (!mdp5_data->ctl || !mdss_mdp_ctl_is_power_on(mdp5_data->ctl) ||
+ mdss_panel_is_power_off(mfd->panel_power_state)) {
pr_debug("panel is off\n");
return count;
}
@@ -6649,10 +6652,6 @@
mfd->panel_orientation = mfd->panel_info->panel_orientation;
- if ((mfd->panel_info->panel_orientation & MDP_FLIP_LR) &&
- (mfd->split_mode == MDP_DUAL_LM_DUAL_DISPLAY))
- mdp5_data->mixer_swap = true;
-
rc = sysfs_create_group(&dev->kobj, &mdp_overlay_sysfs_group);
if (rc) {
pr_err("vsync sysfs group creation failed, ret=%d\n", rc);
diff --git a/drivers/video/fbdev/msm/mdss_mdp_pipe.c b/drivers/video/fbdev/msm/mdss_mdp_pipe.c
index 3a8df20..4231af4 100644
--- a/drivers/video/fbdev/msm/mdss_mdp_pipe.c
+++ b/drivers/video/fbdev/msm/mdss_mdp_pipe.c
@@ -934,17 +934,18 @@
data = readl_relaxed(mdata->mdp_base +
MDSS_MDP_REG_SMP_ALLOC_W0 + off);
client_id = (data >> s) & 0xFF;
- if (test_bit(i, mdata->mmb_alloc_map)) {
- /*
- * Certain pipes may have a dedicated set of
- * SMP MMBs statically allocated to them. In
- * such cases, we do not need to do anything
- * here.
- */
- pr_debug("smp mmb %d already assigned to pipe %d (client_id %d)\n"
- , i, pipe ? pipe->num : -1, client_id);
- continue;
- }
+ if (i < ARRAY_SIZE(mdata->mmb_alloc_map))
+ if (test_bit(i, mdata->mmb_alloc_map)) {
+ /*
+ * Certain pipes may have a dedicated set of
+ * SMP MMBs statically allocated to them. In
+ * such cases, we do not need to do anything
+ * here.
+ */
+ pr_debug("smp mmb %d already assigned to pipe %d (client_id %d)\n"
+ , i, pipe ? pipe->num : -1, client_id);
+ continue;
+ }
if (client_id) {
if (client_id != prev_id) {
@@ -1011,8 +1012,10 @@
u32 mask, reg_val, reg_val_lvl, i, vbif_qos;
u32 reg_high;
bool is_nrt_vbif = mdss_mdp_is_nrt_vbif_client(mdata, pipe);
+ u32 *vbif_qos_ptr = is_realtime ? mdata->vbif_rt_qos :
+ mdata->vbif_nrt_qos;
- if (mdata->npriority_lvl == 0)
+ if ((mdata->npriority_lvl == 0) || !vbif_qos_ptr)
return;
if (test_bit(MDSS_QOS_REMAPPER, mdata->mdss_qos_map)) {
@@ -1028,8 +1031,7 @@
is_nrt_vbif);
mask = 0x3 << (pipe->xin_id * 4);
- vbif_qos = is_realtime ?
- mdata->vbif_rt_qos[i] : mdata->vbif_nrt_qos[i];
+ vbif_qos = vbif_qos_ptr[i];
reg_val &= ~(mask);
reg_val |= vbif_qos << (pipe->xin_id * 4);
@@ -1053,8 +1055,7 @@
mask = 0x3 << (pipe->xin_id * 2);
reg_val &= ~(mask);
- vbif_qos = is_realtime ?
- mdata->vbif_rt_qos[i] : mdata->vbif_nrt_qos[i];
+ vbif_qos = vbif_qos_ptr[i];
reg_val |= vbif_qos << (pipe->xin_id * 2);
MDSS_VBIF_WRITE(mdata, MDSS_VBIF_QOS_REMAP_BASE + i*4,
reg_val, is_nrt_vbif);
@@ -2072,8 +2073,9 @@
u32 cdp_settings = 0x0;
bool is_rotator = (pipe->mixer_left && pipe->mixer_left->rotator_mode);
- /* Disable CDP for rotator pipe in v1 */
- if (is_rotator && mdss_has_quirk(mdata, MDSS_QUIRK_ROTCDP))
+ /* Disable CDP for rotator pipe or if not requested for the target */
+ if (!mdata->enable_cdp || (is_rotator &&
+ mdss_has_quirk(mdata, MDSS_QUIRK_ROTCDP)))
goto exit;
cdp_settings = MDSS_MDP_CDP_ENABLE;
@@ -2290,6 +2292,9 @@
mdss_mdp_pipe_write(pipe, MDSS_MDP_REG_SSPP_SRC3_ADDR, addr[2]);
}
+ MDSS_XLOG(pipe->num, pipe->multirect.num, pipe->mixer_left->num,
+ pipe->play_cnt, addr[0], addr[1], addr[2], addr[3]);
+
return 0;
}
@@ -2311,7 +2316,7 @@
/* support ARGB color format only */
unpack = (C3_ALPHA << 24) | (C2_R_Cr << 16) |
- (C1_B_Cb << 8) | (C0_G_Y << 0);
+ (C0_G_Y << 8) | (C1_B_Cb << 0);
if (pipe->scaler.enable)
opmode |= (1 << 31);
@@ -2677,9 +2682,6 @@
goto update_nobuf;
}
- MDSS_XLOG(pipe->num, pipe->multirect.num, pipe->mixer_left->num,
- pipe->play_cnt, 0x222);
-
if (params_changed) {
pipe->params_changed = 0;
diff --git a/drivers/video/fbdev/msm/mdss_mdp_pp.c b/drivers/video/fbdev/msm/mdss_mdp_pp.c
index 13afa46..8f4d437 100644
--- a/drivers/video/fbdev/msm/mdss_mdp_pp.c
+++ b/drivers/video/fbdev/msm/mdss_mdp_pp.c
@@ -2445,7 +2445,7 @@
}
if (flags & PP_FLAGS_DIRTY_DITHER) {
- if (!pp_ops[DITHER].pp_set_config) {
+ if (!pp_ops[DITHER].pp_set_config && addr) {
pp_dither_config(addr, pp_sts,
&mdss_pp_res->dither_disp_cfg[disp_num]);
} else {
@@ -5156,7 +5156,7 @@
u32 block)
{
int ret = 0;
- u32 sum;
+ int sum = 0;
char __iomem *v_base = NULL;
unsigned long flag;
struct mdss_data_type *mdata = mdss_mdp_get_mdata();
@@ -5186,7 +5186,8 @@
else if (block == SSPP_VIG)
v_base = ctl_base +
MDSS_MDP_REG_VIG_HIST_CTL_BASE;
- sum = pp_hist_read(v_base, hist_info);
+ if (v_base)
+ sum = pp_hist_read(v_base, hist_info);
}
writel_relaxed(0, hist_info->base);
mdss_mdp_clk_ctrl(MDP_BLOCK_POWER_OFF);
diff --git a/drivers/video/fbdev/msm/mdss_mdp_trace.h b/drivers/video/fbdev/msm/mdss_mdp_trace.h
index c100e9c..35a126b 100644
--- a/drivers/video/fbdev/msm/mdss_mdp_trace.h
+++ b/drivers/video/fbdev/msm/mdss_mdp_trace.h
@@ -295,6 +295,42 @@
__entry->ib_quota)
);
+TRACE_EVENT(mdp_compare_bw,
+ TP_PROTO(unsigned long long new_ab, unsigned long long new_ib,
+ unsigned long long new_wb,
+ unsigned long long old_ab, unsigned long long old_ib,
+ unsigned long long old_wb,
+ u32 params_changed, bool update_bw),
+ TP_ARGS(new_ab, new_ib, new_wb,
+ old_ab, old_ib, old_wb,
+ params_changed, update_bw),
+ TP_STRUCT__entry(
+ __field(u64, new_ab)
+ __field(u64, new_ib)
+ __field(u64, new_wb)
+ __field(u64, old_ab)
+ __field(u64, old_ib)
+ __field(u64, old_wb)
+ __field(u32, params_changed)
+ __field(bool, update_bw)
+ ),
+ TP_fast_assign(
+ __entry->new_ab = new_ab;
+ __entry->new_ib = new_ib;
+ __entry->new_wb = new_wb;
+ __entry->old_ab = old_ab;
+ __entry->old_ib = old_ib;
+ __entry->old_wb = old_wb;
+ __entry->params_changed = params_changed;
+ __entry->update_bw = update_bw;
+ ),
+ TP_printk("[ab,ib,wb]new[%llu,%llu,%llu]old[%llu,%llu,%llu]chgd:%d %d",
+ __entry->new_ab, __entry->new_ib, __entry->new_wb,
+ __entry->old_ab, __entry->old_ib,
+ __entry->old_wb, __entry->params_changed,
+ __entry->update_bw)
+);
+
TRACE_EVENT(mdp_misr_crc,
TP_PROTO(u32 block_id, u32 vsync_cnt, u32 crc),
TP_ARGS(block_id, vsync_cnt, crc),
@@ -332,6 +368,22 @@
__entry->koff_cnt)
);
+TRACE_EVENT(mdp_cmd_readptr_done,
+ TP_PROTO(u32 ctl_num, int koff_cnt),
+ TP_ARGS(ctl_num, koff_cnt),
+ TP_STRUCT__entry(
+ __field(u32, ctl_num)
+ __field(int, koff_cnt)
+ ),
+ TP_fast_assign(
+ __entry->ctl_num = ctl_num;
+ __entry->koff_cnt = koff_cnt;
+ ),
+ TP_printk("ctl num:%d kickoff:%d",
+ __entry->ctl_num,
+ __entry->koff_cnt)
+);
+
TRACE_EVENT(mdp_cmd_release_bw,
TP_PROTO(u32 ctl_num),
TP_ARGS(ctl_num),
diff --git a/drivers/video/fbdev/msm/mdss_mdp_util.c b/drivers/video/fbdev/msm/mdss_mdp_util.c
index c030109..dd73d2c 100644
--- a/drivers/video/fbdev/msm/mdss_mdp_util.c
+++ b/drivers/video/fbdev/msm/mdss_mdp_util.c
@@ -969,7 +969,9 @@
* be filled due to map call which will be unmapped above.
*
*/
- pr_debug("skip memory unmapping for secure display content\n");
+ if (data->ihandle)
+ ion_free(iclient, data->ihandle);
+ pr_debug("free memory handle for secure display/camera content\n");
} else {
return -ENOMEM;
}
@@ -1048,19 +1050,18 @@
ret = 0;
goto done;
} else {
- struct ion_handle *ihandle = NULL;
struct sg_table *sg_ptr = NULL;
+ data->ihandle = ion_import_dma_buf_fd(iclient,
+ img->memory_id);
+ if (IS_ERR_OR_NULL(data->ihandle)) {
+ ret = -EINVAL;
+ pr_err("ion import buffer failed\n");
+ data->ihandle = NULL;
+ goto done;
+ }
do {
- ihandle = ion_import_dma_buf_fd(iclient,
- img->memory_id);
- if (IS_ERR_OR_NULL(ihandle)) {
- ret = -EINVAL;
- pr_err("ion import buffer failed\n");
- break;
- }
-
- sg_ptr = ion_sg_table(iclient, ihandle);
+ sg_ptr = ion_sg_table(iclient, data->ihandle);
if (sg_ptr == NULL) {
pr_err("ion sg table get failed\n");
ret = -EINVAL;
@@ -1086,8 +1087,6 @@
ret = 0;
} while (0);
- if (!IS_ERR_OR_NULL(ihandle))
- ion_free(iclient, ihandle);
return ret;
}
}
diff --git a/drivers/video/fbdev/msm/mdss_panel.h b/drivers/video/fbdev/msm/mdss_panel.h
index aa90d5f..c66d5ab 100644
--- a/drivers/video/fbdev/msm/mdss_panel.h
+++ b/drivers/video/fbdev/msm/mdss_panel.h
@@ -60,6 +60,7 @@
#define WRITEBACK_PANEL 10 /* Wifi display */
#define LVDS_PANEL 11 /* LVDS */
#define EDP_PANEL 12 /* LVDS */
+#define SPI_PANEL 13
#define DSC_PPS_LEN 128
@@ -108,6 +109,7 @@
MDSS_PANEL_INTF_DSI,
MDSS_PANEL_INTF_EDP,
MDSS_PANEL_INTF_HDMI,
+ MDSS_PANEL_INTF_SPI,
};
enum {
@@ -118,6 +120,12 @@
};
enum {
+ MDSS_PANEL_BLANK_BLANK = 0,
+ MDSS_PANEL_BLANK_UNBLANK,
+ MDSS_PANEL_BLANK_LOW_POWER,
+};
+
+enum {
MDSS_PANEL_LOW_PERSIST_MODE_OFF = 0,
MDSS_PANEL_LOW_PERSIST_MODE_ON,
};
@@ -430,6 +438,10 @@
char frame_rate; /* fps */
};
+struct spi_panel_info {
+ char frame_rate;
+};
+
/**
* struct dynamic_fps_data - defines dynamic fps related data
* @hfp: horizontal front porch
@@ -660,6 +672,10 @@
u32 saved_fporch;
/* current fps, once is programmed in hw */
int current_fps;
+ u32 mdp_koff_thshold_low;
+ u32 mdp_koff_thshold_high;
+ bool mdp_koff_thshold;
+ u32 mdp_koff_delay;
int panel_max_fps;
int panel_max_vtotal;
@@ -677,6 +693,7 @@
u32 partial_update_roi_merge;
struct ion_handle *splash_ihdl;
int panel_power_state;
+ int blank_state;
int compression_mode;
uint32_t panel_dead;
@@ -736,6 +753,7 @@
struct lcd_panel_info lcdc;
struct fbc_panel_info fbc;
struct mipi_panel_info mipi;
+ struct spi_panel_info spi;
struct lvds_panel_info lvds;
struct edp_panel_info edp;
@@ -875,6 +893,9 @@
frame_rate = panel_info->lcdc.frame_rate;
break;
}
+ case SPI_PANEL:
+ frame_rate = panel_info->spi.frame_rate;
+ break;
default:
pixel_total = (panel_info->lcdc.h_back_porch +
panel_info->lcdc.h_front_porch +
diff --git a/drivers/video/fbdev/msm/mdss_smmu.c b/drivers/video/fbdev/msm/mdss_smmu.c
index c02823b..c213f70 100644
--- a/drivers/video/fbdev/msm/mdss_smmu.c
+++ b/drivers/video/fbdev/msm/mdss_smmu.c
@@ -495,24 +495,30 @@
(struct mdss_smmu_client *)user_data;
u32 fsynr1, mid, i;
- if (!mdss_smmu || !mdss_smmu->mmu_base)
+ if (!mdss_smmu)
goto end;
- fsynr1 = readl_relaxed(mdss_smmu->mmu_base + SMMU_CBN_FSYNR1);
- mid = fsynr1 & 0xff;
- pr_err("mdss_smmu: iova:0x%lx flags:0x%x fsynr1: 0x%x mid: 0x%x\n",
- iova, flags, fsynr1, mid);
+ if (mdss_smmu->mmu_base) {
+ fsynr1 = readl_relaxed(mdss_smmu->mmu_base + SMMU_CBN_FSYNR1);
+ mid = fsynr1 & 0xff;
+ pr_err("mdss_smmu: iova:0x%lx flags:0x%x fsynr1: 0x%x mid: 0x%x\n",
+ iova, flags, fsynr1, mid);
- /* get domain id information */
- for (i = 0; i < MDSS_IOMMU_MAX_DOMAIN; i++) {
- if (mdss_smmu == mdss_smmu_get_cb(i))
- break;
+ /* get domain id information */
+ for (i = 0; i < MDSS_IOMMU_MAX_DOMAIN; i++) {
+ if (mdss_smmu == mdss_smmu_get_cb(i))
+ break;
+ }
+
+ if (i == MDSS_IOMMU_MAX_DOMAIN)
+ goto end;
+
+ mdss_mdp_debug_mid(mid);
+ } else {
+ pr_err("mdss_smmu: iova:0x%lx flags:0x%x\n",
+ iova, flags);
+ MDSS_XLOG_TOUT_HANDLER("mdp");
}
-
- if (i == MDSS_IOMMU_MAX_DOMAIN)
- goto end;
-
- mdss_mdp_debug_mid(mid);
end:
return -ENODEV;
}
@@ -861,14 +867,13 @@
mdss_smmu->dev = dev;
+ iommu_set_fault_handler(mdss_smmu->mmu_mapping->domain,
+ mdss_smmu_fault_handler, mdss_smmu);
address = of_get_address_by_name(pdev->dev.of_node, "mmu_cb", 0, 0);
if (address) {
size = address + 1;
mdss_smmu->mmu_base = ioremap(be32_to_cpu(*address),
be32_to_cpu(*size));
- if (mdss_smmu->mmu_base)
- iommu_set_fault_handler(mdss_smmu->mmu_mapping->domain,
- mdss_smmu_fault_handler, mdss_smmu);
} else {
pr_debug("unable to map context bank base\n");
}
diff --git a/drivers/video/fbdev/msm/mdss_spi_client.c b/drivers/video/fbdev/msm/mdss_spi_client.c
new file mode 100644
index 0000000..541e382
--- /dev/null
+++ b/drivers/video/fbdev/msm/mdss_spi_client.c
@@ -0,0 +1,198 @@
+/* Copyright (c) 2017-2018, The Linux Foundation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ */
+
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/spi/spi.h>
+#include <linux/of_gpio.h>
+#include <linux/gpio.h>
+#include <linux/qpnp/pin.h>
+#include <linux/delay.h>
+
+#include "mdss_spi_client.h"
+
+#define MAX_READ_SPEED_HZ 9600000
+#define SPI_PANEL_COMMAND_LEN 1
+static struct spi_device *mdss_spi_client;
+
+int mdss_spi_read_data(u8 reg_addr, u8 *data, u8 len)
+{
+ int rc = 0;
+ u32 max_speed_hz;
+ u8 memory_write_reg = 0x2c;
+ u8 empty_pack[] = {0x29, 0x29, 0x29};
+ struct spi_transfer t[4] = {
+ [0] = {
+ .tx_buf = ®_addr,
+ .len = 1,
+ },
+ [1] = {
+ .rx_buf = data,
+ .len = len,
+ },
+ [2] = {
+ .tx_buf = &empty_pack,
+ .len = 3,
+ },
+ [3] = {
+ .tx_buf = &memory_write_reg,
+ .len = 1,
+ }
+ };
+ struct spi_message m;
+
+ if (!mdss_spi_client) {
+ pr_err("%s: spi client not available\n", __func__);
+ return -EINVAL;
+ }
+
+ mdss_spi_client->bits_per_word = 8;
+ max_speed_hz = mdss_spi_client->max_speed_hz;
+ mdss_spi_client->max_speed_hz = MAX_READ_SPEED_HZ;
+
+ spi_message_init(&m);
+ spi_message_add_tail(&t[0], &m);
+ spi_message_add_tail(&t[1], &m);
+ rc = spi_sync(mdss_spi_client, &m);
+
+ spi_message_init(&m);
+ spi_message_add_tail(&t[2], &m);
+ rc = spi_sync(mdss_spi_client, &m);
+ spi_message_init(&m);
+ spi_message_add_tail(&t[3], &m);
+ rc = spi_sync(mdss_spi_client, &m);
+ mdss_spi_client->max_speed_hz = max_speed_hz;
+
+ return rc;
+}
+
+int mdss_spi_tx_command(const void *buf)
+{
+ int rc = 0;
+ struct spi_transfer t = {
+ .tx_buf = buf,
+ .len = SPI_PANEL_COMMAND_LEN,
+ };
+ struct spi_message m;
+
+ if (!mdss_spi_client) {
+ pr_err("%s: spi client not available\n", __func__);
+ return -EINVAL;
+ }
+
+ mdss_spi_client->bits_per_word = 8;
+
+ spi_message_init(&m);
+ spi_message_add_tail(&t, &m);
+ rc = spi_sync(mdss_spi_client, &m);
+
+ return rc;
+}
+
+int mdss_spi_tx_parameter(const void *buf, size_t len)
+{
+ int rc = 0;
+ struct spi_transfer t = {
+ .tx_buf = buf,
+ .len = len,
+ };
+ struct spi_message m;
+
+ if (!mdss_spi_client) {
+ pr_err("%s: spi client not available\n", __func__);
+ return -EINVAL;
+ }
+
+ mdss_spi_client->bits_per_word = 8;
+
+ spi_message_init(&m);
+ spi_message_add_tail(&t, &m);
+ rc = spi_sync(mdss_spi_client, &m);
+
+ return rc;
+}
+
+int mdss_spi_tx_pixel(const void *buf, size_t len)
+{
+ int rc = 0;
+ struct spi_transfer t = {
+ .tx_buf = buf,
+ .len = len,
+ };
+ struct spi_message m;
+
+ if (!mdss_spi_client) {
+ pr_err("%s: spi client not available\n", __func__);
+ return -EINVAL;
+ }
+
+ mdss_spi_client->bits_per_word = 16;
+ spi_message_init(&m);
+ spi_message_add_tail(&t, &m);
+ rc = spi_sync(mdss_spi_client, &m);
+
+ return rc;
+}
+
+static int mdss_spi_client_probe(struct spi_device *spidev)
+{
+ int irq;
+ int cs;
+ int cpha, cpol, cs_high;
+ u32 max_speed;
+ struct device_node *np;
+
+ irq = spidev->irq;
+ cs = spidev->chip_select;
+ cpha = (spidev->mode & SPI_CPHA) ? 1:0;
+ cpol = (spidev->mode & SPI_CPOL) ? 1:0;
+ cs_high = (spidev->mode & SPI_CS_HIGH) ? 1:0;
+ max_speed = spidev->max_speed_hz;
+ np = spidev->dev.of_node;
+ pr_debug("cs[%x] CPHA[%x] CPOL[%x] CS_HIGH[%x] Max_speed[%d]\n",
+ cs, cpha, cpol, cs_high, max_speed);
+ mdss_spi_client = spidev;
+
+ return 0;
+}
+
+
+static const struct of_device_id mdss_spi_dt_match[] = {
+ { .compatible = "qcom,mdss-spi-client" },
+ {},
+};
+
+static struct spi_driver mdss_spi_client_driver = {
+ .probe = mdss_spi_client_probe,
+ .driver = {
+ .name = "mdss-spi-client",
+ .owner = THIS_MODULE,
+ .of_match_table = mdss_spi_dt_match,
+ },
+};
+
+static int __init mdss_spi_init(void)
+{
+ int ret;
+
+ ret = spi_register_driver(&mdss_spi_client_driver);
+
+ return 0;
+}
+module_init(mdss_spi_init);
+
+static void __exit mdss_spi_exit(void)
+{
+ spi_unregister_driver(&mdss_spi_client_driver);
+}
+module_exit(mdss_spi_exit);
+
diff --git a/drivers/video/fbdev/msm/mdss_spi_client.h b/drivers/video/fbdev/msm/mdss_spi_client.h
new file mode 100644
index 0000000..2d15625
--- /dev/null
+++ b/drivers/video/fbdev/msm/mdss_spi_client.h
@@ -0,0 +1,20 @@
+/* Copyright (c) 2017-2018, The Linux Foundation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ */
+
+#ifndef __MDSS_SPI_CLINET_H__
+#define __MDSS_SPI_CLINET_H__
+
+int mdss_spi_tx_command(const void *buf);
+int mdss_spi_tx_parameter(const void *buf, size_t len);
+int mdss_spi_tx_pixel(const void *buf, size_t len);
+int mdss_spi_read_data(u8 reg_addr, u8 *data, u8 len);
+#endif /* End of __MDSS_SPI_CLINET_H__ */
diff --git a/drivers/video/fbdev/msm/mdss_spi_panel.c b/drivers/video/fbdev/msm/mdss_spi_panel.c
new file mode 100644
index 0000000..86a1c1c
--- /dev/null
+++ b/drivers/video/fbdev/msm/mdss_spi_panel.c
@@ -0,0 +1,1713 @@
+/* Copyright (c) 2017-2018, The Linux Foundation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ */
+
+#include <linux/module.h>
+#include <linux/of_gpio.h>
+#include <linux/gpio.h>
+#include <linux/qpnp/pin.h>
+#include <linux/delay.h>
+#include <linux/interrupt.h>
+#include <linux/leds.h>
+#include <linux/qpnp/pwm.h>
+#include <linux/of_device.h>
+
+#include "mdss.h"
+#include "mdss_panel.h"
+#include "mdss_spi_panel.h"
+#include "mdss_spi_client.h"
+#include "mdp3.h"
+
+DEFINE_LED_TRIGGER(bl_led_trigger);
+static int mdss_spi_panel_reset(struct mdss_panel_data *pdata, int enable)
+{
+ struct spi_panel_data *ctrl_pdata = NULL;
+ struct mdss_panel_info *pinfo = NULL;
+ int i, rc = 0;
+
+ if (pdata == NULL) {
+ pr_err("%s: Invalid input data\n", __func__);
+ return -EINVAL;
+ }
+
+ ctrl_pdata = container_of(pdata, struct spi_panel_data,
+ panel_data);
+
+ if (!gpio_is_valid(ctrl_pdata->rst_gpio)) {
+ pr_debug("%s:%d, reset line not configured\n",
+ __func__, __LINE__);
+ return rc;
+ }
+
+ if (!gpio_is_valid(ctrl_pdata->disp_dc_gpio)) {
+ pr_debug("%s:%d, dc line not configured\n",
+ __func__, __LINE__);
+ return rc;
+ }
+
+ pr_debug("%s: enable = %d\n", __func__, enable);
+ pinfo = &(ctrl_pdata->panel_data.panel_info);
+
+ if (enable) {
+ rc = gpio_request(ctrl_pdata->rst_gpio, "disp_rst_n");
+ if (rc) {
+ pr_err("display reset gpio request failed\n");
+ return rc;
+ }
+
+ rc = gpio_request(ctrl_pdata->disp_dc_gpio, "disp_dc");
+ if (rc) {
+ pr_err("display dc gpio request failed\n");
+ return rc;
+ }
+
+ if (!pinfo->cont_splash_enabled) {
+ for (i = 0; i < pdata->panel_info.rst_seq_len; ++i) {
+ gpio_direction_output((ctrl_pdata->rst_gpio),
+ pdata->panel_info.rst_seq[i]);
+ if (pdata->panel_info.rst_seq[++i])
+ usleep_range(pinfo->rst_seq[i] * 1000,
+ pinfo->rst_seq[i] * 1000);
+ }
+ }
+
+ if (ctrl_pdata->ctrl_state & CTRL_STATE_PANEL_INIT) {
+ pr_debug("%s: Panel Not properly turned OFF\n",
+ __func__);
+ ctrl_pdata->ctrl_state &= ~CTRL_STATE_PANEL_INIT;
+ pr_err("%s: Reset panel done\n", __func__);
+ }
+ } else {
+ gpio_direction_output((ctrl_pdata->rst_gpio), 0);
+ gpio_free(ctrl_pdata->rst_gpio);
+
+ gpio_direction_output(ctrl_pdata->disp_dc_gpio, 0);
+ gpio_free(ctrl_pdata->disp_dc_gpio);
+ }
+ return rc;
+}
+
+
+static int mdss_spi_panel_pinctrl_set_state(
+ struct spi_panel_data *ctrl_pdata,
+ bool active)
+{
+ struct pinctrl_state *pin_state;
+ int rc = -EFAULT;
+
+ if (IS_ERR_OR_NULL(ctrl_pdata->pin_res.pinctrl))
+ return PTR_ERR(ctrl_pdata->pin_res.pinctrl);
+
+ pin_state = active ? ctrl_pdata->pin_res.gpio_state_active
+ : ctrl_pdata->pin_res.gpio_state_suspend;
+ if (!IS_ERR_OR_NULL(pin_state)) {
+ rc = pinctrl_select_state(ctrl_pdata->pin_res.pinctrl,
+ pin_state);
+ if (rc)
+ pr_err("%s: can not set %s pins\n", __func__,
+ active ? MDSS_PINCTRL_STATE_DEFAULT
+ : MDSS_PINCTRL_STATE_SLEEP);
+ } else {
+ pr_err("%s: invalid '%s' pinstate\n", __func__,
+ active ? MDSS_PINCTRL_STATE_DEFAULT
+ : MDSS_PINCTRL_STATE_SLEEP);
+ }
+ return rc;
+}
+
+
+static int mdss_spi_panel_pinctrl_init(struct platform_device *pdev)
+{
+ struct spi_panel_data *ctrl_pdata;
+
+ ctrl_pdata = platform_get_drvdata(pdev);
+ ctrl_pdata->pin_res.pinctrl = devm_pinctrl_get(&pdev->dev);
+ if (IS_ERR_OR_NULL(ctrl_pdata->pin_res.pinctrl)) {
+ pr_err("%s: failed to get pinctrl\n", __func__);
+ return PTR_ERR(ctrl_pdata->pin_res.pinctrl);
+ }
+
+ ctrl_pdata->pin_res.gpio_state_active
+ = pinctrl_lookup_state(ctrl_pdata->pin_res.pinctrl,
+ MDSS_PINCTRL_STATE_DEFAULT);
+ if (IS_ERR_OR_NULL(ctrl_pdata->pin_res.gpio_state_active))
+ pr_warn("%s: can not get default pinstate\n", __func__);
+
+ ctrl_pdata->pin_res.gpio_state_suspend
+ = pinctrl_lookup_state(ctrl_pdata->pin_res.pinctrl,
+ MDSS_PINCTRL_STATE_SLEEP);
+ if (IS_ERR_OR_NULL(ctrl_pdata->pin_res.gpio_state_suspend))
+ pr_warn("%s: can not get sleep pinstate\n", __func__);
+
+ return 0;
+}
+
+
+static int mdss_spi_panel_power_on(struct mdss_panel_data *pdata)
+{
+ int ret = 0;
+ struct spi_panel_data *ctrl_pdata = NULL;
+
+ if (pdata == NULL) {
+ pr_err("%s: Invalid input data\n", __func__);
+ return -EINVAL;
+ }
+
+ ctrl_pdata = container_of(pdata, struct spi_panel_data,
+ panel_data);
+ ret = msm_mdss_enable_vreg(
+ ctrl_pdata->panel_power_data.vreg_config,
+ ctrl_pdata->panel_power_data.num_vreg, 1);
+ if (ret) {
+ pr_err("%s: failed to enable vregs for %s\n",
+ __func__, "PANEL_PM");
+ }
+
+ /*
+ * If continuous splash screen feature is enabled, then we need to
+ * request all the GPIOs that have already been configured in the
+ * bootloader. This needs to be done irresepective of whether
+ * the lp11_init flag is set or not.
+ */
+ if (pdata->panel_info.cont_splash_enabled) {
+ if (mdss_spi_panel_pinctrl_set_state(ctrl_pdata, true))
+ pr_debug("reset enable: pinctrl not enabled\n");
+
+ ret = mdss_spi_panel_reset(pdata, 1);
+ if (ret)
+ pr_err("%s: Panel reset failed. rc=%d\n",
+ __func__, ret);
+ }
+
+ return ret;
+}
+
+
+static int mdss_spi_panel_power_off(struct mdss_panel_data *pdata)
+{
+ int ret = 0;
+ struct spi_panel_data *ctrl_pdata = NULL;
+
+ if (pdata == NULL) {
+ pr_err("%s: Invalid input data\n", __func__);
+ ret = -EINVAL;
+ goto end;
+ }
+ ctrl_pdata = container_of(pdata, struct spi_panel_data,
+ panel_data);
+
+ ret = mdss_spi_panel_reset(pdata, 0);
+ if (ret) {
+ pr_warn("%s: Panel reset failed. rc=%d\n", __func__, ret);
+ ret = 0;
+ }
+
+ if (mdss_spi_panel_pinctrl_set_state(ctrl_pdata, false))
+ pr_warn("reset disable: pinctrl not enabled\n");
+
+ ret = msm_mdss_enable_vreg(
+ ctrl_pdata->panel_power_data.vreg_config,
+ ctrl_pdata->panel_power_data.num_vreg, 0);
+ if (ret)
+ pr_err("%s: failed to disable vregs for %s\n",
+ __func__, "PANEL_PM");
+
+end:
+ return ret;
+}
+
+
+static int mdss_spi_panel_power_ctrl(struct mdss_panel_data *pdata,
+ int power_state)
+{
+ int ret;
+ struct mdss_panel_info *pinfo;
+
+ if (pdata == NULL) {
+ pr_err("%s: Invalid input data\n", __func__);
+ return -EINVAL;
+ }
+
+ pinfo = &pdata->panel_info;
+ pr_debug("%s: cur_power_state=%d req_power_state=%d\n", __func__,
+ pinfo->panel_power_state, power_state);
+
+ if (pinfo->panel_power_state == power_state) {
+ pr_debug("%s: no change needed\n", __func__);
+ return 0;
+ }
+
+ switch (power_state) {
+ case MDSS_PANEL_POWER_OFF:
+ ret = mdss_spi_panel_power_off(pdata);
+ break;
+ case MDSS_PANEL_POWER_ON:
+ ret = mdss_spi_panel_power_on(pdata);
+ break;
+ default:
+ pr_err("%s: unknown panel power state requested (%d)\n",
+ __func__, power_state);
+ ret = -EINVAL;
+ }
+
+ if (!ret)
+ pinfo->panel_power_state = power_state;
+
+ return ret;
+}
+
+static int mdss_spi_panel_unblank(struct mdss_panel_data *pdata)
+{
+ int ret = 0;
+ struct spi_panel_data *ctrl_pdata = NULL;
+
+ if (pdata == NULL) {
+ pr_err("%s: Invalid input data\n", __func__);
+ return -EINVAL;
+ }
+
+ ctrl_pdata = container_of(pdata, struct spi_panel_data,
+ panel_data);
+
+ if (!(ctrl_pdata->ctrl_state & CTRL_STATE_PANEL_INIT)) {
+ ret = ctrl_pdata->on(pdata);
+ if (ret) {
+ pr_err("%s: unable to initialize the panel\n",
+ __func__);
+ return ret;
+ }
+ ctrl_pdata->ctrl_state |= CTRL_STATE_PANEL_INIT;
+ }
+
+ return ret;
+}
+
+static int mdss_spi_panel_blank(struct mdss_panel_data *pdata, int power_state)
+{
+ int ret = 0;
+ struct spi_panel_data *ctrl_pdata = NULL;
+
+ if (pdata == NULL) {
+ pr_err("%s: Invalid input data\n", __func__);
+ return -EINVAL;
+ }
+
+ ctrl_pdata = container_of(pdata, struct spi_panel_data,
+ panel_data);
+
+ if (ctrl_pdata->ctrl_state & CTRL_STATE_PANEL_INIT) {
+ ret = ctrl_pdata->off(pdata);
+ if (ret) {
+ pr_err("%s: Panel OFF failed\n", __func__);
+ return ret;
+ }
+ ctrl_pdata->ctrl_state &= ~CTRL_STATE_PANEL_INIT;
+ }
+
+ return ret;
+}
+
+
+static int mdss_spi_panel_event_handler(struct mdss_panel_data *pdata,
+ int event, void *arg)
+{
+ int rc = 0;
+ struct spi_panel_data *ctrl_pdata = NULL;
+ int power_state;
+
+ if (pdata == NULL) {
+ pr_err("%s: Invalid input data\n", __func__);
+ return -EINVAL;
+ }
+ ctrl_pdata = container_of(pdata, struct spi_panel_data,
+ panel_data);
+
+ switch (event) {
+ case MDSS_EVENT_LINK_READY:
+ rc = mdss_spi_panel_power_ctrl(pdata, MDSS_PANEL_POWER_ON);
+ if (rc) {
+ pr_err("%s:Panel power on failed. rc=%d\n",
+ __func__, rc);
+ return rc;
+ }
+ mdss_spi_panel_pinctrl_set_state(ctrl_pdata, true);
+ mdss_spi_panel_reset(pdata, 1);
+ break;
+ case MDSS_EVENT_UNBLANK:
+ rc = mdss_spi_panel_unblank(pdata);
+ break;
+ case MDSS_EVENT_PANEL_ON:
+ ctrl_pdata->ctrl_state |= CTRL_STATE_MDP_ACTIVE;
+ break;
+ case MDSS_EVENT_BLANK:
+ power_state = (int) (unsigned long) arg;
+ break;
+ case MDSS_EVENT_PANEL_OFF:
+ power_state = (int) (unsigned long) arg;
+ ctrl_pdata->ctrl_state &= ~CTRL_STATE_MDP_ACTIVE;
+ rc = mdss_spi_panel_blank(pdata, power_state);
+ rc = mdss_spi_panel_power_ctrl(pdata, power_state);
+ break;
+ default:
+ pr_debug("%s: unhandled event=%d\n", __func__, event);
+ break;
+ }
+ pr_debug("%s-:event=%d, rc=%d\n", __func__, event, rc);
+ return rc;
+}
+
+int is_spi_panel_continuous_splash_on(struct mdss_panel_data *pdata)
+{
+ int i = 0, voltage = 0;
+ struct mdss_vreg *vreg;
+ int num_vreg;
+ struct spi_panel_data *ctrl_pdata = NULL;
+
+ ctrl_pdata = container_of(pdata, struct spi_panel_data,
+ panel_data);
+ vreg = ctrl_pdata->panel_power_data.vreg_config;
+ num_vreg = ctrl_pdata->panel_power_data.num_vreg;
+
+ for (i = 0; i < num_vreg; i++) {
+ if (regulator_is_enabled(vreg[i].vreg) <= 0)
+ return false;
+ voltage = regulator_get_voltage(vreg[i].vreg);
+ if (!(voltage >= vreg[i].min_voltage &&
+ voltage <= vreg[i].max_voltage))
+ return false;
+ }
+
+ return true;
+}
+
+static void enable_spi_panel_te_irq(struct spi_panel_data *ctrl_pdata,
+ bool enable)
+{
+ static bool is_enabled = true;
+
+ if (is_enabled == enable)
+ return;
+
+ if (!gpio_is_valid(ctrl_pdata->disp_te_gpio)) {
+ pr_err("%s:%d,SPI panel TE GPIO not configured\n",
+ __func__, __LINE__);
+ return;
+ }
+
+ if (enable)
+ enable_irq(gpio_to_irq(ctrl_pdata->disp_te_gpio));
+ else
+ disable_irq(gpio_to_irq(ctrl_pdata->disp_te_gpio));
+
+ is_enabled = enable;
+}
+
+int mdss_spi_panel_kickoff(struct mdss_panel_data *pdata,
+ char *buf, int len, int dma_stride)
+{
+ struct spi_panel_data *ctrl_pdata = NULL;
+ char *tx_buf;
+ int rc = 0;
+ int panel_yres;
+ int panel_xres;
+ int padding_length = 0;
+ int actual_stride = 0;
+ int byte_per_pixel = 0;
+ int scan_count = 0;
+
+ if (pdata == NULL) {
+ pr_err("%s: Invalid input data\n", __func__);
+ return -EINVAL;
+ }
+
+ ctrl_pdata = container_of(pdata, struct spi_panel_data,
+ panel_data);
+
+ tx_buf = ctrl_pdata->tx_buf;
+ panel_xres = ctrl_pdata->panel_data.panel_info.xres;
+ panel_yres = ctrl_pdata->panel_data.panel_info.yres;
+
+ byte_per_pixel = ctrl_pdata->panel_data.panel_info.bpp / 8;
+ actual_stride = panel_xres * byte_per_pixel;
+ padding_length = dma_stride - actual_stride;
+
+ /* remove the padding and copy to continuous buffer */
+ while (scan_count < panel_yres) {
+ memcpy((tx_buf + scan_count * actual_stride),
+ (buf + scan_count * (actual_stride + padding_length)),
+ actual_stride);
+ scan_count++;
+ }
+
+ enable_spi_panel_te_irq(ctrl_pdata, true);
+
+ mutex_lock(&ctrl_pdata->spi_tx_mutex);
+ reinit_completion(&ctrl_pdata->spi_panel_te);
+
+ rc = wait_for_completion_timeout(&ctrl_pdata->spi_panel_te,
+ msecs_to_jiffies(SPI_PANEL_TE_TIMEOUT));
+
+ if (rc == 0)
+ pr_err("wait panel TE time out\n");
+
+ rc = mdss_spi_tx_pixel(tx_buf, ctrl_pdata->byte_pre_frame);
+ mutex_unlock(&ctrl_pdata->spi_tx_mutex);
+
+ return rc;
+}
+
+static int mdss_spi_read_panel_data(struct mdss_panel_data *pdata,
+ u8 reg_addr, u8 *data, u8 len)
+{
+ int rc = 0;
+ struct spi_panel_data *ctrl_pdata = NULL;
+
+ ctrl_pdata = container_of(pdata, struct spi_panel_data,
+ panel_data);
+
+ mutex_lock(&ctrl_pdata->spi_tx_mutex);
+ gpio_direction_output(ctrl_pdata->disp_dc_gpio, 0);
+ rc = mdss_spi_read_data(reg_addr, data, len);
+ gpio_direction_output(ctrl_pdata->disp_dc_gpio, 1);
+ mutex_unlock(&ctrl_pdata->spi_tx_mutex);
+
+ return rc;
+}
+
+static int mdss_spi_panel_on(struct mdss_panel_data *pdata)
+{
+ struct spi_panel_data *ctrl = NULL;
+ struct mdss_panel_info *pinfo;
+ int i;
+
+ if (pdata == NULL) {
+ pr_err("%s: Invalid input data\n", __func__);
+ return -EINVAL;
+ }
+ pinfo = &pdata->panel_info;
+ ctrl = container_of(pdata, struct spi_panel_data,
+ panel_data);
+
+ for (i = 0; i < ctrl->on_cmds.cmd_cnt; i++) {
+ /* pull down dc gpio indicate this is command */
+ gpio_direction_output(ctrl->disp_dc_gpio, 0);
+ mdss_spi_tx_command(ctrl->on_cmds.cmds[i].command);
+ gpio_direction_output((ctrl->disp_dc_gpio), 1);
+
+ if (ctrl->on_cmds.cmds[i].dchdr.dlen > 1) {
+ mdss_spi_tx_parameter(ctrl->on_cmds.cmds[i].parameter,
+ ctrl->on_cmds.cmds[i].dchdr.dlen-1);
+ }
+ if (ctrl->on_cmds.cmds[i].dchdr.wait != 0)
+ msleep(ctrl->on_cmds.cmds[i].dchdr.wait);
+ }
+
+ pinfo->blank_state = MDSS_PANEL_BLANK_UNBLANK;
+
+ pr_debug("%s:-\n", __func__);
+
+ return 0;
+}
+
+
+static int mdss_spi_panel_off(struct mdss_panel_data *pdata)
+{
+ struct spi_panel_data *ctrl = NULL;
+ struct mdss_panel_info *pinfo;
+ int i;
+
+ if (pdata == NULL) {
+ pr_err("%s: Invalid input data\n", __func__);
+ return -EINVAL;
+ }
+
+ pinfo = &pdata->panel_info;
+ ctrl = container_of(pdata, struct spi_panel_data,
+ panel_data);
+
+ for (i = 0; i < ctrl->off_cmds.cmd_cnt; i++) {
+ /* pull down dc gpio indicate this is command */
+ gpio_direction_output(ctrl->disp_dc_gpio, 0);
+ mdss_spi_tx_command(ctrl->off_cmds.cmds[i].command);
+ gpio_direction_output((ctrl->disp_dc_gpio), 1);
+
+ if (ctrl->off_cmds.cmds[i].dchdr.dlen > 1) {
+ mdss_spi_tx_parameter(ctrl->off_cmds.cmds[i].parameter,
+ ctrl->off_cmds.cmds[i].dchdr.dlen-1);
+ }
+
+ if (ctrl->off_cmds.cmds[i].dchdr.wait != 0)
+ msleep(ctrl->off_cmds.cmds[i].dchdr.wait);
+ }
+
+ pinfo->blank_state = MDSS_PANEL_BLANK_BLANK;
+
+ pr_debug("%s:-\n", __func__);
+ return 0;
+}
+
+static void mdss_spi_put_dt_vreg_data(struct device *dev,
+ struct mdss_module_power *module_power)
+{
+ if (!module_power) {
+ pr_err("%s: invalid input\n", __func__);
+ return;
+ }
+
+ if (module_power->vreg_config) {
+ devm_kfree(dev, module_power->vreg_config);
+ module_power->vreg_config = NULL;
+ }
+ module_power->num_vreg = 0;
+}
+
+
+static int mdss_spi_get_panel_vreg_data(struct device *dev,
+ struct mdss_module_power *mp)
+{
+ int i = 0, rc = 0;
+ u32 tmp = 0;
+ struct device_node *of_node = NULL, *supply_node = NULL;
+ struct device_node *supply_root_node = NULL;
+
+ if (!dev || !mp) {
+ pr_err("%s: invalid input\n", __func__);
+ rc = -EINVAL;
+ return rc;
+ }
+
+ of_node = dev->of_node;
+
+ mp->num_vreg = 0;
+
+ supply_root_node = of_get_child_by_name(of_node,
+ "qcom,panel-supply-entries");
+
+ for_each_available_child_of_node(supply_root_node, supply_node) {
+ mp->num_vreg++;
+ }
+ if (mp->num_vreg == 0) {
+ pr_debug("%s: no vreg\n", __func__);
+ goto novreg;
+ } else {
+ pr_debug("%s: vreg found. count=%d\n", __func__, mp->num_vreg);
+ }
+
+ mp->vreg_config = kcalloc(mp->num_vreg, sizeof(struct mdss_vreg),
+ GFP_KERNEL);
+
+ if (mp->vreg_config != NULL) {
+ for_each_available_child_of_node(supply_root_node,
+ supply_node) {
+ const char *st = NULL;
+ /* vreg-name */
+ rc = of_property_read_string(supply_node,
+ "qcom,supply-name", &st);
+ if (rc) {
+ pr_err("%s: error reading name. rc=%d\n",
+ __func__, rc);
+ goto error;
+ }
+ snprintf(mp->vreg_config[i].vreg_name,
+ ARRAY_SIZE((mp->vreg_config[i].vreg_name)),
+ "%s", st);
+ /* vreg-min-voltage */
+ rc = of_property_read_u32(supply_node,
+ "qcom,supply-min-voltage", &tmp);
+ if (rc) {
+ pr_err("%s: error reading min volt. rc=%d\n",
+ __func__, rc);
+ goto error;
+ }
+ mp->vreg_config[i].min_voltage = tmp;
+
+ /* vreg-max-voltage */
+ rc = of_property_read_u32(supply_node,
+ "qcom,supply-max-voltage", &tmp);
+ if (rc) {
+ pr_err("%s: error reading max volt. rc=%d\n",
+ __func__, rc);
+ goto error;
+ }
+ mp->vreg_config[i].max_voltage = tmp;
+
+ /* enable-load */
+ rc = of_property_read_u32(supply_node,
+ "qcom,supply-enable-load", &tmp);
+ if (rc) {
+ pr_err("%s: error read enable load. rc=%d\n",
+ __func__, rc);
+ goto error;
+ }
+ mp->vreg_config[i].load[DSS_REG_MODE_ENABLE] = tmp;
+
+ /* disable-load */
+ rc = of_property_read_u32(supply_node,
+ "qcom,supply-disable-load", &tmp);
+ if (rc) {
+ pr_err("%s: error read disable load. rc=%d\n",
+ __func__, rc);
+ goto error;
+ }
+ mp->vreg_config[i].load[DSS_REG_MODE_DISABLE] = tmp;
+
+ /* pre-sleep */
+ rc = of_property_read_u32(supply_node,
+ "qcom,supply-pre-on-sleep", &tmp);
+ if (rc) {
+ pr_debug("%s: error read pre on value\n",
+ __func__);
+ rc = 0;
+ } else {
+ mp->vreg_config[i].pre_on_sleep = tmp;
+ }
+
+ rc = of_property_read_u32(supply_node,
+ "qcom,supply-pre-off-sleep", &tmp);
+ if (rc) {
+ pr_debug("%s: error read pre off value\n",
+ __func__);
+ rc = 0;
+ } else {
+ mp->vreg_config[i].pre_off_sleep = tmp;
+ }
+
+ /* post-sleep */
+ rc = of_property_read_u32(supply_node,
+ "qcom,supply-post-on-sleep", &tmp);
+ if (rc) {
+ pr_debug("%s: error read post on value\n",
+ __func__);
+ rc = 0;
+ } else {
+ mp->vreg_config[i].post_on_sleep = tmp;
+ }
+
+ rc = of_property_read_u32(supply_node,
+ "qcom,supply-post-off-sleep", &tmp);
+ if (rc) {
+ pr_debug("%s: error read post off value\n",
+ __func__);
+ rc = 0;
+ } else {
+ mp->vreg_config[i].post_off_sleep = tmp;
+ }
+
+ ++i;
+ }
+ }
+ return rc;
+error:
+ kfree(mp->vreg_config);
+ mp->vreg_config = NULL;
+
+novreg:
+ mp->num_vreg = 0;
+
+ return rc;
+
+}
+
+static int mdss_spi_panel_parse_cmds(struct device_node *np,
+ struct spi_panel_cmds *pcmds, char *cmd_key)
+{
+ const char *data;
+ int blen = 0, len;
+ char *buf, *bp;
+ struct spi_ctrl_hdr *dchdr;
+ int i, cnt;
+
+ data = of_get_property(np, cmd_key, &blen);
+ if (!data) {
+ pr_err("%s: failed, key=%s\n", __func__, cmd_key);
+ return -ENOMEM;
+ }
+
+ buf = kcalloc(blen, sizeof(char), GFP_KERNEL);
+ if (!buf)
+ return -ENOMEM;
+
+ memcpy(buf, data, blen);
+
+ /* scan dcs commands */
+ bp = buf;
+ len = blen;
+ cnt = 0;
+ while (len >= sizeof(*dchdr)) {
+ dchdr = (struct spi_ctrl_hdr *)bp;
+ if (dchdr->dlen > len) {
+ pr_err("%s: dtsi parse error, len=%d",
+ __func__, dchdr->dlen);
+ goto exit_free;
+ }
+ bp += sizeof(*dchdr);
+ len -= sizeof(*dchdr);
+ bp += dchdr->dlen;
+ len -= dchdr->dlen;
+ cnt++;
+ }
+
+ if (len != 0) {
+ pr_err("%s: dcs_cmd=%x len=%d error",
+ __func__, buf[0], len);
+ goto exit_free;
+ }
+
+ pcmds->cmds = kcalloc(cnt, sizeof(struct spi_cmd_desc),
+ GFP_KERNEL);
+ if (!pcmds->cmds)
+ goto exit_free;
+
+ pcmds->cmd_cnt = cnt;
+ pcmds->buf = buf;
+ pcmds->blen = blen;
+
+ bp = buf;
+ len = blen;
+ for (i = 0; i < cnt; i++) {
+ dchdr = (struct spi_ctrl_hdr *)bp;
+ len -= sizeof(*dchdr);
+ bp += sizeof(*dchdr);
+ pcmds->cmds[i].dchdr = *dchdr;
+ pcmds->cmds[i].command = bp;
+ pcmds->cmds[i].parameter = bp + sizeof(char);
+ bp += dchdr->dlen;
+ len -= dchdr->dlen;
+ }
+
+ pr_debug("%s: dcs_cmd=%x, len=%d, cmd_cnt=%d\n", __func__,
+ pcmds->buf[0], pcmds->blen, pcmds->cmd_cnt);
+
+ return 0;
+
+exit_free:
+ kfree(buf);
+ return -ENOMEM;
+}
+static int mdss_spi_panel_parse_reset_seq(struct device_node *np,
+ u32 rst_seq[MDSS_SPI_RST_SEQ_LEN], u32 *rst_len,
+ const char *name)
+{
+ int num = 0, i;
+ int rc;
+ struct property *data;
+ u32 tmp[MDSS_SPI_RST_SEQ_LEN];
+
+ *rst_len = 0;
+ data = of_find_property(np, name, &num);
+ num /= sizeof(u32);
+ if (!data || !num || num > MDSS_SPI_RST_SEQ_LEN || num % 2) {
+ pr_err("%s:%d, error reading %s, length found = %d\n",
+ __func__, __LINE__, name, num);
+ } else {
+ rc = of_property_read_u32_array(np, name, tmp, num);
+ if (rc)
+ pr_err("%s:%d, error reading %s, rc = %d\n",
+ __func__, __LINE__, name, rc);
+ else {
+ for (i = 0; i < num; ++i)
+ rst_seq[i] = tmp[i];
+ *rst_len = num;
+ }
+ }
+ return 0;
+}
+
+static bool mdss_send_panel_cmd_for_esd(struct spi_panel_data *ctrl_pdata)
+{
+
+ if (ctrl_pdata == NULL) {
+ pr_err("%s: Invalid input data\n", __func__);
+ return false;
+ }
+
+ mutex_lock(&ctrl_pdata->spi_tx_mutex);
+ mdss_spi_panel_on(&ctrl_pdata->panel_data);
+ mutex_unlock(&ctrl_pdata->spi_tx_mutex);
+
+ return true;
+}
+
+static bool mdss_spi_reg_status_check(struct spi_panel_data *ctrl_pdata)
+{
+ int ret = 0;
+ int i = 0;
+
+ if (ctrl_pdata == NULL) {
+ pr_err("%s: Invalid input data\n", __func__);
+ return false;
+ }
+
+ pr_debug("%s: Checking Register status\n", __func__);
+
+ ret = mdss_spi_read_panel_data(&ctrl_pdata->panel_data,
+ ctrl_pdata->panel_status_reg,
+ ctrl_pdata->act_status_value,
+ ctrl_pdata->status_cmds_rlen);
+ if (ret < 0) {
+ pr_err("%s: Read status register returned error\n", __func__);
+ } else {
+ for (i = 0; i < ctrl_pdata->status_cmds_rlen; i++) {
+ pr_debug("act_value[%d] = %x, exp_value[%d] = %x\n",
+ i, ctrl_pdata->act_status_value[i],
+ i, ctrl_pdata->exp_status_value[i]);
+ if (ctrl_pdata->act_status_value[i] !=
+ ctrl_pdata->exp_status_value[i])
+ return false;
+ }
+ }
+
+ return true;
+}
+
+static void mdss_spi_parse_esd_params(struct device_node *np,
+ struct spi_panel_data *ctrl)
+{
+ u32 tmp;
+ int rc;
+ struct property *data;
+ const char *string;
+ struct mdss_panel_info *pinfo = &ctrl->panel_data.panel_info;
+
+ pinfo->esd_check_enabled = of_property_read_bool(np,
+ "qcom,esd-check-enabled");
+
+ if (!pinfo->esd_check_enabled)
+ return;
+
+ ctrl->status_mode = SPI_ESD_MAX;
+
+ rc = of_property_read_string(np,
+ "qcom,mdss-spi-panel-status-check-mode", &string);
+ if (!rc) {
+ if (!strcmp(string, "reg_read")) {
+ ctrl->status_mode = SPI_ESD_REG;
+ ctrl->check_status =
+ mdss_spi_reg_status_check;
+ } else if (!strcmp(string, "send_init_command")) {
+ ctrl->status_mode = SPI_SEND_PANEL_COMMAND;
+ ctrl->check_status =
+ mdss_send_panel_cmd_for_esd;
+ return;
+ } else {
+ pr_err("No valid panel-status-check-mode string\n");
+ pinfo->esd_check_enabled = false;
+ return;
+ }
+ }
+
+ rc = of_property_read_u8(np, "qcom,mdss-spi-panel-status-reg",
+ &ctrl->panel_status_reg);
+ if (rc) {
+ pr_warn("%s:%d, Read status reg failed, disable ESD check\n",
+ __func__, __LINE__);
+ pinfo->esd_check_enabled = false;
+ return;
+ }
+
+ rc = of_property_read_u32(np, "qcom,mdss-spi-panel-status-read-length",
+ &tmp);
+ if (rc) {
+ pr_warn("%s:%d, Read reg length failed, disable ESD check\n",
+ __func__, __LINE__);
+ pinfo->esd_check_enabled = false;
+ return;
+ }
+
+ ctrl->status_cmds_rlen = (!rc ? tmp : 1);
+
+ ctrl->exp_status_value = kzalloc(sizeof(u8) *
+ (ctrl->status_cmds_rlen + 1), GFP_KERNEL);
+ ctrl->act_status_value = kzalloc(sizeof(u8) *
+ (ctrl->status_cmds_rlen + 1), GFP_KERNEL);
+
+ if (!ctrl->exp_status_value || !ctrl->act_status_value) {
+ pr_err("%s: Error allocating memory for status buffer\n",
+ __func__);
+ pinfo->esd_check_enabled = false;
+ return;
+ }
+
+ data = of_find_property(np, "qcom,mdss-spi-panel-status-value", &tmp);
+ tmp /= sizeof(u8);
+ if (!data || (tmp != ctrl->status_cmds_rlen)) {
+ pr_err("%s: Panel status values not found\n", __func__);
+ pinfo->esd_check_enabled = false;
+ memset(ctrl->exp_status_value, 0, ctrl->status_cmds_rlen);
+ } else {
+ rc = of_property_read_u8_array(np,
+ "qcom,mdss-spi-panel-status-value",
+ ctrl->exp_status_value, tmp);
+ if (rc) {
+ pr_err("%s: Error reading panel status values\n",
+ __func__);
+ pinfo->esd_check_enabled = false;
+ memset(ctrl->exp_status_value, 0,
+ ctrl->status_cmds_rlen);
+ }
+ }
+}
+
+static int mdss_spi_panel_parse_dt(struct device_node *np,
+ struct spi_panel_data *ctrl_pdata)
+{
+ u32 tmp;
+ int rc;
+ const char *data;
+ struct mdss_panel_info *pinfo = &(ctrl_pdata->panel_data.panel_info);
+
+ pinfo->cont_splash_enabled = of_property_read_bool(np,
+ "qcom,cont-splash-enabled");
+
+ rc = of_property_read_u32(np, "qcom,mdss-spi-panel-width", &tmp);
+ if (rc) {
+ pr_err("%s: panel width not specified\n", __func__);
+ return -EINVAL;
+ }
+ pinfo->xres = (!rc ? tmp : 240);
+
+ rc = of_property_read_u32(np, "qcom,mdss-spi-panel-height", &tmp);
+ if (rc) {
+ pr_err("%s:panel height not specified\n", __func__);
+ return -EINVAL;
+ }
+ pinfo->yres = (!rc ? tmp : 320);
+
+ rc = of_property_read_u32(np,
+ "qcom,mdss-pan-physical-width-dimension", &tmp);
+ pinfo->physical_width = (!rc ? tmp : 0);
+ rc = of_property_read_u32(np,
+ "qcom,mdss-pan-physical-height-dimension", &tmp);
+ pinfo->physical_height = (!rc ? tmp : 0);
+ rc = of_property_read_u32(np, "qcom,mdss-spi-panel-framerate", &tmp);
+ pinfo->spi.frame_rate = (!rc ? tmp : 30);
+ rc = of_property_read_u32(np, "qcom,mdss-spi-h-front-porch", &tmp);
+ pinfo->lcdc.h_front_porch = (!rc ? tmp : 6);
+ rc = of_property_read_u32(np, "qcom,mdss-spi-h-back-porch", &tmp);
+ pinfo->lcdc.h_back_porch = (!rc ? tmp : 6);
+ rc = of_property_read_u32(np, "qcom,mdss-spi-h-pulse-width", &tmp);
+ pinfo->lcdc.h_pulse_width = (!rc ? tmp : 2);
+ rc = of_property_read_u32(np, "qcom,mdss-spi-h-sync-skew", &tmp);
+ pinfo->lcdc.hsync_skew = (!rc ? tmp : 0);
+ rc = of_property_read_u32(np, "qcom,mdss-spi-v-back-porch", &tmp);
+ pinfo->lcdc.v_back_porch = (!rc ? tmp : 6);
+ rc = of_property_read_u32(np, "qcom,mdss-spi-v-front-porch", &tmp);
+ pinfo->lcdc.v_front_porch = (!rc ? tmp : 6);
+ rc = of_property_read_u32(np, "qcom,mdss-spi-v-pulse-width", &tmp);
+ pinfo->lcdc.v_pulse_width = (!rc ? tmp : 2);
+
+
+ rc = of_property_read_u32(np, "qcom,mdss-spi-bpp", &tmp);
+ if (rc) {
+ pr_err("%s: bpp not specified\n", __func__);
+ return -EINVAL;
+ }
+ pinfo->bpp = (!rc ? tmp : 16);
+
+ pinfo->pdest = DISPLAY_1;
+
+ ctrl_pdata->bklt_ctrl = SPI_UNKNOWN_CTRL;
+ data = of_get_property(np, "qcom,mdss-spi-bl-pmic-control-type", NULL);
+ if (data) {
+ if (!strcmp(data, "bl_ctrl_wled")) {
+ led_trigger_register_simple("bkl-trigger",
+ &bl_led_trigger);
+ pr_debug("%s: SUCCESS-> WLED TRIGGER register\n",
+ __func__);
+ ctrl_pdata->bklt_ctrl = SPI_BL_WLED;
+ } else if (!strcmp(data, "bl_gpio_pulse")) {
+ led_trigger_register_simple("gpio-bklt-trigger",
+ &bl_led_trigger);
+ pr_debug("%s: SUCCESS-> GPIO PULSE TRIGGER register\n",
+ __func__);
+ ctrl_pdata->bklt_ctrl = SPI_BL_WLED;
+ } else if (!strcmp(data, "bl_ctrl_pwm")) {
+ ctrl_pdata->bklt_ctrl = SPI_BL_PWM;
+ ctrl_pdata->pwm_pmi = of_property_read_bool(np,
+ "qcom,mdss-spi-bl-pwm-pmi");
+ rc = of_property_read_u32(np,
+ "qcom,mdss-spi-bl-pmic-pwm-frequency", &tmp);
+ if (rc) {
+ pr_err("%s: Error, panel pwm_period\n",
+ __func__);
+ return -EINVAL;
+ }
+ ctrl_pdata->pwm_period = tmp;
+ if (ctrl_pdata->pwm_pmi) {
+ ctrl_pdata->pwm_bl = of_pwm_get(np, NULL);
+ if (IS_ERR(ctrl_pdata->pwm_bl)) {
+ pr_err("%s: Error, pwm device\n",
+ __func__);
+ ctrl_pdata->pwm_bl = NULL;
+ return -EINVAL;
+ }
+ } else {
+ rc = of_property_read_u32(np,
+ "qcom,mdss-spi-bl-pmic-bank-select",
+ &tmp);
+ if (rc) {
+ pr_err("%s: Error, lpg channel\n",
+ __func__);
+ return -EINVAL;
+ }
+ ctrl_pdata->pwm_lpg_chan = tmp;
+ tmp = of_get_named_gpio(np,
+ "qcom,mdss-spi-pwm-gpio", 0);
+ ctrl_pdata->pwm_pmic_gpio = tmp;
+ pr_debug("%s: Configured PWM bklt ctrl\n",
+ __func__);
+ }
+ }
+ }
+ rc = of_property_read_u32(np, "qcom,mdss-brightness-max-level", &tmp);
+ pinfo->brightness_max = (!rc ? tmp : MDSS_MAX_BL_BRIGHTNESS);
+ rc = of_property_read_u32(np, "qcom,mdss-spi-bl-min-level", &tmp);
+ pinfo->bl_min = (!rc ? tmp : 0);
+ rc = of_property_read_u32(np, "qcom,mdss-spi-bl-max-level", &tmp);
+ pinfo->bl_max = (!rc ? tmp : 255);
+ ctrl_pdata->bklt_max = pinfo->bl_max;
+
+
+ mdss_spi_panel_parse_reset_seq(np, pinfo->rst_seq,
+ &(pinfo->rst_seq_len),
+ "qcom,mdss-spi-reset-sequence");
+
+ mdss_spi_panel_parse_cmds(np, &ctrl_pdata->on_cmds,
+ "qcom,mdss-spi-on-command");
+
+ mdss_spi_panel_parse_cmds(np, &ctrl_pdata->off_cmds,
+ "qcom,mdss-spi-off-command");
+
+ mdss_spi_parse_esd_params(np, ctrl_pdata);
+
+
+ return 0;
+}
+
+static void mdss_spi_panel_pwm_cfg(struct spi_panel_data *ctrl)
+{
+ if (ctrl->pwm_pmi)
+ return;
+
+ ctrl->pwm_bl = pwm_request(ctrl->pwm_lpg_chan, "lcd-bklt");
+ if (ctrl->pwm_bl == NULL || IS_ERR(ctrl->pwm_bl)) {
+ pr_err("%s: Error: lpg_chan=%d pwm request failed",
+ __func__, ctrl->pwm_lpg_chan);
+ }
+ ctrl->pwm_enabled = 0;
+}
+
+static void mdss_spi_panel_bklt_pwm(struct spi_panel_data *ctrl, int level)
+{
+ int ret;
+ u32 duty;
+ u32 period_ns;
+
+ if (ctrl->pwm_bl == NULL) {
+ pr_err("%s: no PWM\n", __func__);
+ return;
+ }
+
+ if (level == 0) {
+ if (ctrl->pwm_enabled) {
+ ret = pwm_config_us(ctrl->pwm_bl, level,
+ ctrl->pwm_period);
+ if (ret)
+ pr_err("%s: pwm_config_us() failed err=%d.\n",
+ __func__, ret);
+ pwm_disable(ctrl->pwm_bl);
+ }
+ ctrl->pwm_enabled = 0;
+ return;
+ }
+
+ duty = level * ctrl->pwm_period;
+ duty /= ctrl->bklt_max;
+
+ pr_debug("%s: bklt_ctrl=%d pwm_period=%d pwm_gpio=%d pwm_lpg_chan=%d\n",
+ __func__, ctrl->bklt_ctrl, ctrl->pwm_period,
+ ctrl->pwm_pmic_gpio, ctrl->pwm_lpg_chan);
+
+ if (ctrl->pwm_period >= USEC_PER_SEC) {
+ ret = pwm_config_us(ctrl->pwm_bl, duty, ctrl->pwm_period);
+ if (ret) {
+ pr_err("%s: pwm_config_us() failed err=%d\n",
+ __func__, ret);
+ return;
+ }
+ } else {
+ period_ns = ctrl->pwm_period * NSEC_PER_USEC;
+ ret = pwm_config(ctrl->pwm_bl,
+ level * period_ns / ctrl->bklt_max,
+ period_ns);
+ if (ret) {
+ pr_err("%s: pwm_config() failed err=%d\n",
+ __func__, ret);
+ return;
+ }
+ }
+
+ if (!ctrl->pwm_enabled) {
+ ret = pwm_enable(ctrl->pwm_bl);
+ if (ret)
+ pr_err("%s: pwm_enable() failed err=%d\n", __func__,
+ ret);
+ ctrl->pwm_enabled = 1;
+ }
+}
+
+static void mdss_spi_panel_bl_ctrl(struct mdss_panel_data *pdata,
+ u32 bl_level)
+{
+ if (bl_level) {
+ mdp3_res->bklt_level = bl_level;
+ mdp3_res->bklt_update = true;
+ } else {
+ mdss_spi_panel_bl_ctrl_update(pdata, bl_level);
+ }
+}
+
+#if defined(CONFIG_FB_MSM_MDSS_SPI_PANEL) && defined(CONFIG_SPI_QUP)
+void mdss_spi_panel_bl_ctrl_update(struct mdss_panel_data *pdata,
+ u32 bl_level)
+{
+ struct spi_panel_data *ctrl_pdata = NULL;
+
+ if (pdata == NULL) {
+ pr_err("%s: Invalid input data\n", __func__);
+ return;
+ }
+
+ ctrl_pdata = container_of(pdata, struct spi_panel_data,
+ panel_data);
+
+ if ((bl_level < pdata->panel_info.bl_min) && (bl_level != 0))
+ bl_level = pdata->panel_info.bl_min;
+
+ switch (ctrl_pdata->bklt_ctrl) {
+ case SPI_BL_WLED:
+ led_trigger_event(bl_led_trigger, bl_level);
+ break;
+ case SPI_BL_PWM:
+ mdss_spi_panel_bklt_pwm(ctrl_pdata, bl_level);
+ break;
+ default:
+ pr_err("%s: Unknown bl_ctrl configuration %d\n",
+ __func__, ctrl_pdata->bklt_ctrl);
+ break;
+ }
+}
+#endif
+
+static int mdss_spi_panel_init(struct device_node *node,
+ struct spi_panel_data *ctrl_pdata,
+ bool cmd_cfg_cont_splash)
+{
+ int rc = 0;
+ static const char *panel_name;
+ struct mdss_panel_info *pinfo;
+
+ if (!node || !ctrl_pdata) {
+ pr_err("%s: Invalid arguments\n", __func__);
+ return -ENODEV;
+ }
+
+ pinfo = &ctrl_pdata->panel_data.panel_info;
+
+ pr_debug("%s:%d\n", __func__, __LINE__);
+ pinfo->panel_name[0] = '\0';
+ panel_name = of_get_property(node, "qcom,mdss-spi-panel-name", NULL);
+ if (!panel_name) {
+ pr_info("%s:%d, Panel name not specified\n",
+ __func__, __LINE__);
+ } else {
+ pr_debug("%s: Panel Name = %s\n", __func__, panel_name);
+ strlcpy(&pinfo->panel_name[0], panel_name, MDSS_MAX_PANEL_LEN);
+ }
+ rc = mdss_spi_panel_parse_dt(node, ctrl_pdata);
+ if (rc) {
+ pr_err("%s:%d panel dt parse failed\n", __func__, __LINE__);
+ return rc;
+ }
+
+ ctrl_pdata->byte_pre_frame = pinfo->xres * pinfo->yres * pinfo->bpp/8;
+
+ ctrl_pdata->tx_buf = kmalloc(ctrl_pdata->byte_pre_frame, GFP_KERNEL);
+
+ if (!cmd_cfg_cont_splash)
+ pinfo->cont_splash_enabled = false;
+
+ pr_info("%s: Continuous splash %s\n", __func__,
+ pinfo->cont_splash_enabled ? "enabled" : "disabled");
+
+ pinfo->dynamic_switch_pending = false;
+ pinfo->is_lpm_mode = false;
+ pinfo->esd_rdy = false;
+
+ ctrl_pdata->on = mdss_spi_panel_on;
+ ctrl_pdata->off = mdss_spi_panel_off;
+ ctrl_pdata->panel_data.set_backlight = mdss_spi_panel_bl_ctrl;
+
+ return 0;
+}
+
+static int mdss_spi_get_panel_cfg(char *panel_cfg,
+ struct spi_panel_data *ctrl_pdata)
+{
+ int rc;
+ struct mdss_panel_cfg *pan_cfg = NULL;
+
+ if (!ctrl_pdata)
+ return MDSS_PANEL_INTF_INVALID;
+
+ pan_cfg = ctrl_pdata->mdss_util->panel_intf_type(MDSS_PANEL_INTF_SPI);
+ if (IS_ERR(pan_cfg)) {
+ return PTR_ERR(pan_cfg);
+ } else if (!pan_cfg) {
+ panel_cfg[0] = 0;
+ return 0;
+ }
+
+ pr_debug("%s:%d: cfg:[%s]\n", __func__, __LINE__,
+ pan_cfg->arg_cfg);
+ ctrl_pdata->panel_data.panel_info.is_prim_panel = true;
+ rc = strlcpy(panel_cfg, pan_cfg->arg_cfg,
+ sizeof(pan_cfg->arg_cfg));
+ return rc;
+}
+
+static int mdss_spi_panel_regulator_init(struct platform_device *pdev)
+{
+ int rc = 0;
+
+ struct spi_panel_data *ctrl_pdata = NULL;
+
+ if (!pdev) {
+ pr_err("%s: invalid input\n", __func__);
+ return -EINVAL;
+ }
+
+ ctrl_pdata = platform_get_drvdata(pdev);
+ if (!ctrl_pdata) {
+ pr_err("%s: invalid driver data\n", __func__);
+ return -EINVAL;
+ }
+
+ rc = msm_mdss_config_vreg(&pdev->dev,
+ ctrl_pdata->panel_power_data.vreg_config,
+ ctrl_pdata->panel_power_data.num_vreg, 1);
+ if (rc)
+ pr_err("%s: failed to init vregs for %s\n",
+ __func__, "PANEL_PM");
+
+ return rc;
+
+}
+
+static irqreturn_t spi_panel_te_handler(int irq, void *data)
+{
+ struct spi_panel_data *ctrl_pdata = (struct spi_panel_data *)data;
+ static int count = 2;
+
+ if (!ctrl_pdata) {
+ pr_err("%s: SPI display not available\n", __func__);
+ return IRQ_HANDLED;
+ }
+ complete(&ctrl_pdata->spi_panel_te);
+
+ if (ctrl_pdata->vsync_client.handler && !(--count)) {
+ ctrl_pdata->vsync_client.handler(ctrl_pdata->vsync_client.arg);
+ count = 2;
+ }
+
+ return IRQ_HANDLED;
+}
+
+void mdp3_spi_vsync_enable(struct mdss_panel_data *pdata,
+ struct mdp3_notification *vsync_client)
+{
+ int updated = 0;
+ struct spi_panel_data *ctrl_pdata = NULL;
+
+ if (pdata == NULL) {
+ pr_err("%s: Invalid input data\n", __func__);
+ return;
+ }
+
+ ctrl_pdata = container_of(pdata, struct spi_panel_data,
+ panel_data);
+
+ if (vsync_client) {
+ if (ctrl_pdata->vsync_client.handler != vsync_client->handler) {
+ ctrl_pdata->vsync_client = *vsync_client;
+ updated = 1;
+ }
+ } else {
+ if (ctrl_pdata->vsync_client.handler) {
+ ctrl_pdata->vsync_client.handler = NULL;
+ ctrl_pdata->vsync_client.arg = NULL;
+ updated = 1;
+ }
+ }
+
+ if (updated) {
+ if (vsync_client && vsync_client->handler)
+ enable_spi_panel_te_irq(ctrl_pdata, true);
+ else
+ enable_spi_panel_te_irq(ctrl_pdata, false);
+ }
+}
+
+static struct device_node *mdss_spi_pref_prim_panel(
+ struct platform_device *pdev)
+{
+ struct device_node *spi_pan_node = NULL;
+
+ pr_debug("%s:%d: Select primary panel from dt\n",
+ __func__, __LINE__);
+ spi_pan_node = of_parse_phandle(pdev->dev.of_node,
+ "qcom,spi-pref-prim-pan", 0);
+ if (!spi_pan_node)
+ pr_err("%s:can't find panel phandle\n", __func__);
+
+ return spi_pan_node;
+}
+
+static int spi_panel_device_register(struct device_node *pan_node,
+ struct spi_panel_data *ctrl_pdata)
+{
+ int rc;
+ struct mdss_panel_info *pinfo = &(ctrl_pdata->panel_data.panel_info);
+ struct device_node *spi_ctrl_np = NULL;
+ struct platform_device *ctrl_pdev = NULL;
+
+ pinfo->type = SPI_PANEL;
+
+ spi_ctrl_np = of_parse_phandle(pan_node,
+ "qcom,mdss-spi-panel-controller", 0);
+ if (!spi_ctrl_np) {
+ pr_err("%s: SPI controller node not initialized\n", __func__);
+ return -EPROBE_DEFER;
+ }
+
+ ctrl_pdev = of_find_device_by_node(spi_ctrl_np);
+ if (!ctrl_pdev) {
+ of_node_put(spi_ctrl_np);
+ pr_err("%s: SPI controller node not find\n", __func__);
+ return -EPROBE_DEFER;
+ }
+
+ rc = mdss_spi_panel_regulator_init(ctrl_pdev);
+ if (rc) {
+ pr_err("%s: failed to init regulator, rc=%d\n",
+ __func__, rc);
+ return rc;
+ }
+
+ pinfo->panel_max_fps = mdss_panel_get_framerate(pinfo,
+ FPS_RESOLUTION_HZ);
+ pinfo->panel_max_vtotal = mdss_panel_get_vtotal(pinfo);
+
+ ctrl_pdata->disp_te_gpio = of_get_named_gpio(ctrl_pdev->dev.of_node,
+ "qcom,platform-te-gpio", 0);
+ if (!gpio_is_valid(ctrl_pdata->disp_te_gpio))
+ pr_err("%s:%d, TE gpio not specified\n",
+ __func__, __LINE__);
+
+ ctrl_pdata->disp_dc_gpio = of_get_named_gpio(ctrl_pdev->dev.of_node,
+ "qcom,platform-spi-dc-gpio", 0);
+ if (!gpio_is_valid(ctrl_pdata->disp_dc_gpio))
+ pr_err("%s:%d, SPI DC gpio not specified\n",
+ __func__, __LINE__);
+
+ ctrl_pdata->rst_gpio = of_get_named_gpio(ctrl_pdev->dev.of_node,
+ "qcom,platform-reset-gpio", 0);
+ if (!gpio_is_valid(ctrl_pdata->rst_gpio))
+ pr_err("%s:%d, reset gpio not specified\n",
+ __func__, __LINE__);
+
+ ctrl_pdata->panel_data.event_handler = mdss_spi_panel_event_handler;
+
+ if (ctrl_pdata->bklt_ctrl == SPI_BL_PWM)
+ mdss_spi_panel_pwm_cfg(ctrl_pdata);
+
+ ctrl_pdata->ctrl_state = CTRL_STATE_UNKNOWN;
+
+ if (pinfo->cont_splash_enabled) {
+ rc = mdss_spi_panel_power_ctrl(&(ctrl_pdata->panel_data),
+ MDSS_PANEL_POWER_ON);
+ if (rc) {
+ pr_err("%s: Panel power on failed\n", __func__);
+ return rc;
+ }
+ if (ctrl_pdata->bklt_ctrl == SPI_BL_PWM)
+ ctrl_pdata->pwm_enabled = 1;
+ pinfo->blank_state = MDSS_PANEL_BLANK_UNBLANK;
+ ctrl_pdata->ctrl_state |=
+ (CTRL_STATE_PANEL_INIT | CTRL_STATE_MDP_ACTIVE);
+ } else {
+ pinfo->panel_power_state = MDSS_PANEL_POWER_OFF;
+ }
+
+ rc = mdss_register_panel(ctrl_pdev, &(ctrl_pdata->panel_data));
+ if (rc) {
+ pr_err("%s: unable to register SPI panel\n", __func__);
+ return rc;
+ }
+
+ pr_debug("%s: Panel data initialized\n", __func__);
+ return 0;
+}
+
+
+/**
+ * mdss_spi_find_panel_of_node(): find device node of spi panel
+ * @pdev: platform_device of the spi ctrl node
+ * @panel_cfg: string containing intf specific config data
+ *
+ * Function finds the panel device node using the interface
+ * specific configuration data. This configuration data is
+ * could be derived from the result of bootloader's GCDB
+ * panel detection mechanism. If such config data doesn't
+ * exist then this panel returns the default panel configured
+ * in the device tree.
+ *
+ * returns pointer to panel node on success, NULL on error.
+ */
+static struct device_node *mdss_spi_find_panel_of_node(
+ struct platform_device *pdev, char *panel_cfg)
+{
+ int len, i;
+ int ctrl_id = pdev->id - 1;
+ char panel_name[MDSS_MAX_PANEL_LEN] = "";
+ char ctrl_id_stream[3] = "0:";
+ char *stream = NULL, *pan = NULL;
+ struct device_node *spi_pan_node = NULL, *mdss_node = NULL;
+
+ len = strlen(panel_cfg);
+ if (!len) {
+ /* no panel cfg chg, parse dt */
+ pr_err("%s:%d: no cmd line cfg present\n",
+ __func__, __LINE__);
+ goto end;
+ } else {
+ if (ctrl_id == 1)
+ strlcpy(ctrl_id_stream, "1:", 3);
+
+ stream = strnstr(panel_cfg, ctrl_id_stream, len);
+ if (!stream) {
+ pr_err("controller config is not present\n");
+ goto end;
+ }
+ stream += 2;
+
+ pan = strnchr(stream, strlen(stream), ':');
+ if (!pan) {
+ strlcpy(panel_name, stream, MDSS_MAX_PANEL_LEN);
+ } else {
+ for (i = 0; (stream + i) < pan; i++)
+ panel_name[i] = *(stream + i);
+ panel_name[i] = 0;
+ }
+
+ pr_debug("%s:%d:%s:%s\n", __func__, __LINE__,
+ panel_cfg, panel_name);
+
+ mdss_node = of_parse_phandle(pdev->dev.of_node,
+ "qcom,mdss-mdp", 0);
+ if (!mdss_node) {
+ pr_err("%s: %d: mdss_node null\n",
+ __func__, __LINE__);
+ return NULL;
+ }
+
+ spi_pan_node = of_find_node_by_name(mdss_node,
+ panel_name);
+ if (!spi_pan_node) {
+ pr_err("%s: invalid pan node, selecting prim panel\n",
+ __func__);
+ goto end;
+ }
+ return spi_pan_node;
+ }
+end:
+ if (strcmp(panel_name, NONE_PANEL))
+ spi_pan_node = mdss_spi_pref_prim_panel(pdev);
+ of_node_put(mdss_node);
+ return spi_pan_node;
+}
+
+
+static int mdss_spi_panel_probe(struct platform_device *pdev)
+{
+ int rc = 0;
+ struct spi_panel_data *ctrl_pdata;
+ struct mdss_panel_cfg *pan_cfg = NULL;
+ struct device_node *spi_pan_node = NULL;
+ bool cmd_cfg_cont_splash = true;
+ char panel_cfg[MDSS_MAX_PANEL_LEN];
+ struct mdss_util_intf *util;
+ const char *ctrl_name;
+
+ util = mdss_get_util_intf();
+ if (util == NULL) {
+ pr_err("Failed to get mdss utility functions\n");
+ return -ENODEV;
+ }
+
+ if (!util->mdp_probe_done) {
+ pr_err("%s: MDP not probed yet\n", __func__);
+ return -EPROBE_DEFER;
+ }
+
+ if (!pdev->dev.of_node) {
+ pr_err("SPI driver only supports device tree probe\n");
+ return -ENOTSUPP;
+ }
+
+ pan_cfg = util->panel_intf_type(MDSS_PANEL_INTF_DSI);
+ if (IS_ERR(pan_cfg)) {
+ pr_err("%s: return MDSS_PANEL_INTF_DSI\n", __func__);
+ return PTR_ERR(pan_cfg);
+ } else if (pan_cfg) {
+ pr_err("%s: DSI is primary\n", __func__);
+ return -ENODEV;
+ }
+
+ ctrl_pdata = platform_get_drvdata(pdev);
+ if (!ctrl_pdata) {
+ ctrl_pdata = devm_kzalloc(&pdev->dev,
+ sizeof(struct spi_panel_data),
+ GFP_KERNEL);
+ if (!ctrl_pdata) {
+ pr_err("%s: FAILED: cannot alloc spi panel\n",
+ __func__);
+ rc = -ENOMEM;
+ goto error_no_mem;
+ }
+ platform_set_drvdata(pdev, ctrl_pdata);
+ }
+
+ ctrl_pdata->mdss_util = util;
+
+ ctrl_name = of_get_property(pdev->dev.of_node, "label", NULL);
+ if (!ctrl_name)
+ pr_info("%s:%d, Ctrl name not specified\n",
+ __func__, __LINE__);
+ else
+ pr_debug("%s: Ctrl name = %s\n",
+ __func__, ctrl_name);
+
+
+ rc = of_platform_populate(pdev->dev.of_node,
+ NULL, NULL, &pdev->dev);
+ if (rc) {
+ dev_err(&pdev->dev,
+ "%s: failed to add child nodes, rc=%d\n",
+ __func__, rc);
+ goto error_no_mem;
+ }
+
+ rc = mdss_spi_panel_pinctrl_init(pdev);
+ if (rc)
+ pr_warn("%s: failed to get pin resources\n", __func__);
+
+ rc = mdss_spi_get_panel_vreg_data(&pdev->dev,
+ &ctrl_pdata->panel_power_data);
+ if (rc) {
+ dev_err(&pdev->dev,
+ "%s: failed to get panel vreg data, rc=%d\n",
+ __func__, rc);
+ goto error_vreg;
+ }
+
+ /* SPI panels can be different between controllers */
+ rc = mdss_spi_get_panel_cfg(panel_cfg, ctrl_pdata);
+ if (!rc)
+ /* spi panel cfg not present */
+ pr_warn("%s:%d:spi specific cfg not present\n",
+ __func__, __LINE__);
+
+ /* find panel device node */
+ spi_pan_node = mdss_spi_find_panel_of_node(pdev, panel_cfg);
+ if (!spi_pan_node) {
+ pr_err("%s: can't find panel node %s\n", __func__, panel_cfg);
+ goto error_pan_node;
+ }
+
+ cmd_cfg_cont_splash = true;
+
+ rc = mdss_spi_panel_init(spi_pan_node, ctrl_pdata, cmd_cfg_cont_splash);
+ if (rc) {
+ pr_err("%s: spi panel init failed\n", __func__);
+ goto error_pan_node;
+ }
+
+ rc = spi_panel_device_register(spi_pan_node, ctrl_pdata);
+ if (rc) {
+ pr_err("%s: spi panel dev reg failed\n", __func__);
+ goto error_pan_node;
+ }
+
+ ctrl_pdata->panel_data.event_handler = mdss_spi_panel_event_handler;
+
+
+ init_completion(&ctrl_pdata->spi_panel_te);
+ mutex_init(&ctrl_pdata->spi_tx_mutex);
+
+ rc = devm_request_irq(&pdev->dev,
+ gpio_to_irq(ctrl_pdata->disp_te_gpio),
+ spi_panel_te_handler, IRQF_TRIGGER_RISING,
+ "TE_GPIO", ctrl_pdata);
+ if (rc) {
+ pr_err("TE request_irq failed.\n");
+ return rc;
+ }
+
+ pr_debug("%s: spi panel initialized\n", __func__);
+ return 0;
+
+error_pan_node:
+ of_node_put(spi_pan_node);
+error_vreg:
+ mdss_spi_put_dt_vreg_data(&pdev->dev,
+ &ctrl_pdata->panel_power_data);
+error_no_mem:
+ devm_kfree(&pdev->dev, ctrl_pdata);
+ return rc;
+}
+
+
+static const struct of_device_id mdss_spi_panel_match[] = {
+ { .compatible = "qcom,mdss-spi-display" },
+ {},
+};
+
+static struct platform_driver this_driver = {
+ .probe = mdss_spi_panel_probe,
+ .driver = {
+ .name = "spi_panel",
+ .owner = THIS_MODULE,
+ .of_match_table = mdss_spi_panel_match,
+ },
+};
+
+static int __init mdss_spi_display_init(void)
+{
+ int ret;
+
+ ret = platform_driver_register(&this_driver);
+ return 0;
+}
+module_init(mdss_spi_display_init);
+
+MODULE_DEVICE_TABLE(of, mdss_spi_panel_match);
+MODULE_LICENSE("GPL v2");
diff --git a/drivers/video/fbdev/msm/mdss_spi_panel.h b/drivers/video/fbdev/msm/mdss_spi_panel.h
new file mode 100644
index 0000000..80b7ea8
--- /dev/null
+++ b/drivers/video/fbdev/msm/mdss_spi_panel.h
@@ -0,0 +1,148 @@
+/* Copyright (c) 2017-2018, The Linux Foundation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ */
+
+#ifndef __MDSS_SPI_PANEL_H__
+#define __MDSS_SPI_PANEL_H__
+
+#if defined(CONFIG_FB_MSM_MDSS_SPI_PANEL) && defined(CONFIG_SPI_QUP)
+#include <linux/list.h>
+#include <linux/mdss_io_util.h>
+#include <linux/irqreturn.h>
+#include <linux/pinctrl/consumer.h>
+#include <linux/gpio.h>
+
+#include "mdss_panel.h"
+#include "mdp3_dma.h"
+
+#define MDSS_MAX_BL_BRIGHTNESS 255
+
+#define MDSS_SPI_RST_SEQ_LEN 10
+
+#define NONE_PANEL "none"
+
+#define CTRL_STATE_UNKNOWN 0x00
+#define CTRL_STATE_PANEL_INIT BIT(0)
+#define CTRL_STATE_MDP_ACTIVE BIT(1)
+
+#define MDSS_PINCTRL_STATE_DEFAULT "mdss_default"
+#define MDSS_PINCTRL_STATE_SLEEP "mdss_sleep"
+#define SPI_PANEL_TE_TIMEOUT 400
+
+enum spi_panel_data_type {
+ panel_cmd,
+ panel_parameter,
+ panel_pixel,
+ UNKNOWN_FORMAT,
+};
+
+enum spi_panel_bl_ctrl {
+ SPI_BL_PWM,
+ SPI_BL_WLED,
+ SPI_BL_DCS_CMD,
+ SPI_UNKNOWN_CTRL,
+};
+
+struct spi_pinctrl_res {
+ struct pinctrl *pinctrl;
+ struct pinctrl_state *gpio_state_active;
+ struct pinctrl_state *gpio_state_suspend;
+};
+#define SPI_PANEL_DST_FORMAT_RGB565 0
+
+struct spi_ctrl_hdr {
+ char wait; /* ms */
+ char dlen; /* 8 bits */
+};
+
+struct spi_cmd_desc {
+ struct spi_ctrl_hdr dchdr;
+ char *command;
+ char *parameter;
+};
+
+struct spi_panel_cmds {
+ char *buf;
+ int blen;
+ struct spi_cmd_desc *cmds;
+ int cmd_cnt;
+};
+
+enum spi_panel_status_mode {
+ SPI_ESD_REG,
+ SPI_SEND_PANEL_COMMAND,
+ SPI_ESD_MAX,
+};
+
+
+struct spi_panel_data {
+ struct mdss_panel_data panel_data;
+ struct mdss_util_intf *mdss_util;
+ struct spi_pinctrl_res pin_res;
+ struct mdss_module_power panel_power_data;
+ struct completion spi_panel_te;
+ struct mdp3_notification vsync_client;
+ unsigned int vsync_status;
+ int byte_pre_frame;
+ char *tx_buf;
+ u8 ctrl_state;
+ int disp_te_gpio;
+ int rst_gpio;
+ int disp_dc_gpio; /* command or data */
+ struct spi_panel_cmds on_cmds;
+ struct spi_panel_cmds off_cmds;
+ bool (*check_status)(struct spi_panel_data *pdata);
+ int (*on)(struct mdss_panel_data *pdata);
+ int (*off)(struct mdss_panel_data *pdata);
+ struct mutex spi_tx_mutex;
+ struct pwm_device *pwm_bl;
+ int bklt_ctrl; /* backlight ctrl */
+ bool pwm_pmi;
+ int pwm_period;
+ int pwm_pmic_gpio;
+ int pwm_lpg_chan;
+ int pwm_enabled;
+ int bklt_max;
+ int status_mode;
+ u32 status_cmds_rlen;
+ u8 panel_status_reg;
+ u8 *exp_status_value;
+ u8 *act_status_value;
+ unsigned char *return_buf;
+};
+
+int mdss_spi_panel_kickoff(struct mdss_panel_data *pdata,
+ char *buf, int len, int stride);
+int is_spi_panel_continuous_splash_on(struct mdss_panel_data *pdata);
+void mdp3_spi_vsync_enable(struct mdss_panel_data *pdata,
+ struct mdp3_notification *vsync_client);
+void mdp3_check_spi_panel_status(struct work_struct *work,
+ uint32_t interval);
+
+#else
+static inline int mdss_spi_panel_kickoff(struct mdss_panel_data *pdata,
+ char *buf, int len, int stride){
+ return 0;
+}
+static inline int is_spi_panel_continuous_splash_on(
+ struct mdss_panel_data *pdata)
+{
+ return 0;
+}
+static inline int mdp3_spi_vsync_enable(struct mdss_panel_data *pdata,
+ struct mdp3_notification *vsync_client){
+ return 0;
+}
+
+#endif/* End of CONFIG_FB_MSM_MDSS_SPI_PANEL && ONFIG_SPI_QUP */
+
+#endif /* End of __MDSS_SPI_PANEL_H__ */
diff --git a/drivers/video/fbdev/msm/mdss_util.c b/drivers/video/fbdev/msm/mdss_util.c
index 30fcf28..a5fb8b6 100644
--- a/drivers/video/fbdev/msm/mdss_util.c
+++ b/drivers/video/fbdev/msm/mdss_util.c
@@ -23,6 +23,7 @@
{
unsigned long irq_flags;
u32 ndx_bit;
+ bool err = false;
if (!hw || hw->hw_ndx >= MDSS_MAX_HW_BLK)
return -EINVAL;
@@ -33,10 +34,12 @@
if (!mdss_irq_handlers[hw->hw_ndx])
mdss_irq_handlers[hw->hw_ndx] = hw;
else
- pr_err("panel %d's irq at %pK is already registered\n",
- hw->hw_ndx, hw->irq_handler);
+ err = true;
spin_unlock_irqrestore(&mdss_lock, irq_flags);
+ if (err)
+ pr_err("panel %d's irq at %pK is already registered\n",
+ hw->hw_ndx, hw->irq_handler);
return 0;
}
@@ -76,6 +79,7 @@
{
unsigned long irq_flags;
u32 ndx_bit;
+ bool err = false;
if (hw->hw_ndx >= MDSS_MAX_HW_BLK)
return;
@@ -87,7 +91,7 @@
spin_lock_irqsave(&mdss_lock, irq_flags);
if (!(hw->irq_info->irq_mask & ndx_bit)) {
- pr_warn("MDSS HW ndx=%d is NOT set\n", hw->hw_ndx);
+ err = true;
} else {
hw->irq_info->irq_mask &= ~ndx_bit;
if (hw->irq_info->irq_mask == 0) {
@@ -96,12 +100,16 @@
}
}
spin_unlock_irqrestore(&mdss_lock, irq_flags);
+
+ if (err)
+ pr_warn("MDSS HW ndx=%d is NOT set\n", hw->hw_ndx);
}
/* called from interrupt context */
void mdss_disable_irq_nosync(struct mdss_hw *hw)
{
u32 ndx_bit;
+ bool err = false;
if (hw->hw_ndx >= MDSS_MAX_HW_BLK)
return;
@@ -113,7 +121,7 @@
spin_lock(&mdss_lock);
if (!(hw->irq_info->irq_mask & ndx_bit)) {
- pr_warn("MDSS HW ndx=%d is NOT set\n", hw->hw_ndx);
+ err = true;
} else {
hw->irq_info->irq_mask &= ~ndx_bit;
if (hw->irq_info->irq_mask == 0) {
@@ -122,6 +130,9 @@
}
}
spin_unlock(&mdss_lock);
+
+ if (err)
+ pr_warn("MDSS HW ndx=%d is NOT set\n", hw->hw_ndx);
}
int mdss_irq_dispatch(u32 hw_ndx, int irq, void *ptr)
@@ -176,6 +187,7 @@
{
unsigned long irq_flags;
u32 ndx_bit;
+ bool err = false;
if (hw->hw_ndx >= MDSS_MAX_HW_BLK)
return;
@@ -188,7 +200,7 @@
spin_lock_irqsave(&mdss_lock, irq_flags);
if (!(hw->irq_info->irq_wake_mask & ndx_bit)) {
- pr_warn("MDSS HW ndx=%d is NOT set\n", hw->hw_ndx);
+ err = true;
} else {
hw->irq_info->irq_wake_mask &= ~ndx_bit;
if (hw->irq_info->irq_wake_ena) {
@@ -197,6 +209,9 @@
}
}
spin_unlock_irqrestore(&mdss_lock, irq_flags);
+
+ if (err)
+ pr_warn("MDSS HW ndx=%d is NOT set\n", hw->hw_ndx);
}
static bool check_display(char *param_string)
diff --git a/fs/btrfs/ctree.c b/fs/btrfs/ctree.c
index f6ba165..409b123 100644
--- a/fs/btrfs/ctree.c
+++ b/fs/btrfs/ctree.c
@@ -2486,10 +2486,8 @@
if (p->reada != READA_NONE)
reada_for_search(root, p, level, slot, key->objectid);
- btrfs_release_path(p);
-
ret = -EAGAIN;
- tmp = read_tree_block(root, blocknr, 0);
+ tmp = read_tree_block(root, blocknr, gen);
if (!IS_ERR(tmp)) {
/*
* If the read above didn't mark this buffer up to date,
@@ -2503,6 +2501,8 @@
} else {
ret = PTR_ERR(tmp);
}
+
+ btrfs_release_path(p);
return ret;
}
diff --git a/fs/btrfs/tree-log.c b/fs/btrfs/tree-log.c
index 5240173..c65350e 100644
--- a/fs/btrfs/tree-log.c
+++ b/fs/btrfs/tree-log.c
@@ -4614,6 +4614,7 @@
struct extent_map_tree *em_tree = &BTRFS_I(inode)->extent_tree;
u64 logged_isize = 0;
bool need_log_inode_item = true;
+ bool xattrs_logged = false;
path = btrfs_alloc_path();
if (!path)
@@ -4918,6 +4919,7 @@
err = btrfs_log_all_xattrs(trans, root, inode, path, dst_path);
if (err)
goto out_unlock;
+ xattrs_logged = true;
if (max_key.type >= BTRFS_EXTENT_DATA_KEY && !fast_search) {
btrfs_release_path(path);
btrfs_release_path(dst_path);
@@ -4930,6 +4932,11 @@
btrfs_release_path(dst_path);
if (need_log_inode_item) {
err = log_inode_item(trans, log, dst_path, inode);
+ if (!err && !xattrs_logged) {
+ err = btrfs_log_all_xattrs(trans, root, inode, path,
+ dst_path);
+ btrfs_release_path(path);
+ }
if (err)
goto out_unlock;
}
diff --git a/fs/btrfs/volumes.c b/fs/btrfs/volumes.c
index 39b917b7..d95eddc 100644
--- a/fs/btrfs/volumes.c
+++ b/fs/btrfs/volumes.c
@@ -3966,6 +3966,15 @@
return 0;
}
+ /*
+ * A ro->rw remount sequence should continue with the paused balance
+ * regardless of who pauses it, system or the user as of now, so set
+ * the resume flag.
+ */
+ spin_lock(&fs_info->balance_lock);
+ fs_info->balance_ctl->flags |= BTRFS_BALANCE_RESUME;
+ spin_unlock(&fs_info->balance_lock);
+
tsk = kthread_run(balance_kthread, fs_info, "btrfs-balance");
return PTR_ERR_OR_ZERO(tsk);
}
diff --git a/fs/debugfs/file.c b/fs/debugfs/file.c
index 354e2ab..0536072 100644
--- a/fs/debugfs/file.c
+++ b/fs/debugfs/file.c
@@ -22,7 +22,6 @@
#include <linux/slab.h>
#include <linux/atomic.h>
#include <linux/device.h>
-#include <linux/srcu.h>
#include <asm/poll.h>
#include "internal.h"
@@ -48,66 +47,108 @@
.llseek = noop_llseek,
};
+#define F_DENTRY(filp) ((filp)->f_path.dentry)
+
+const struct file_operations *debugfs_real_fops(const struct file *filp)
+{
+ struct debugfs_fsdata *fsd = F_DENTRY(filp)->d_fsdata;
+
+ if ((unsigned long)fsd & DEBUGFS_FSDATA_IS_REAL_FOPS_BIT) {
+ /*
+ * Urgh, we've been called w/o a protecting
+ * debugfs_file_get().
+ */
+ WARN_ON(1);
+ return NULL;
+ }
+
+ return fsd->real_fops;
+}
+EXPORT_SYMBOL_GPL(debugfs_real_fops);
+
/**
- * debugfs_use_file_start - mark the beginning of file data access
+ * debugfs_file_get - mark the beginning of file data access
* @dentry: the dentry object whose data is being accessed.
- * @srcu_idx: a pointer to some memory to store a SRCU index in.
*
- * Up to a matching call to debugfs_use_file_finish(), any
- * successive call into the file removing functions debugfs_remove()
- * and debugfs_remove_recursive() will block. Since associated private
+ * Up to a matching call to debugfs_file_put(), any successive call
+ * into the file removing functions debugfs_remove() and
+ * debugfs_remove_recursive() will block. Since associated private
* file data may only get freed after a successful return of any of
* the removal functions, you may safely access it after a successful
- * call to debugfs_use_file_start() without worrying about
- * lifetime issues.
+ * call to debugfs_file_get() without worrying about lifetime issues.
*
* If -%EIO is returned, the file has already been removed and thus,
* it is not safe to access any of its data. If, on the other hand,
* it is allowed to access the file data, zero is returned.
- *
- * Regardless of the return code, any call to
- * debugfs_use_file_start() must be followed by a matching call
- * to debugfs_use_file_finish().
*/
-int debugfs_use_file_start(const struct dentry *dentry, int *srcu_idx)
- __acquires(&debugfs_srcu)
+int debugfs_file_get(struct dentry *dentry)
{
- *srcu_idx = srcu_read_lock(&debugfs_srcu);
- barrier();
+ struct debugfs_fsdata *fsd;
+ void *d_fsd;
+
+ d_fsd = READ_ONCE(dentry->d_fsdata);
+ if (!((unsigned long)d_fsd & DEBUGFS_FSDATA_IS_REAL_FOPS_BIT)) {
+ fsd = d_fsd;
+ } else {
+ fsd = kmalloc(sizeof(*fsd), GFP_KERNEL);
+ if (!fsd)
+ return -ENOMEM;
+
+ fsd->real_fops = (void *)((unsigned long)d_fsd &
+ ~DEBUGFS_FSDATA_IS_REAL_FOPS_BIT);
+ refcount_set(&fsd->active_users, 1);
+ init_completion(&fsd->active_users_drained);
+ if (cmpxchg(&dentry->d_fsdata, d_fsd, fsd) != d_fsd) {
+ kfree(fsd);
+ fsd = READ_ONCE(dentry->d_fsdata);
+ }
+ }
+
+ /*
+ * In case of a successful cmpxchg() above, this check is
+ * strictly necessary and must follow it, see the comment in
+ * __debugfs_remove_file().
+ * OTOH, if the cmpxchg() hasn't been executed or wasn't
+ * successful, this serves the purpose of not starving
+ * removers.
+ */
if (d_unlinked(dentry))
return -EIO;
+
+ if (!refcount_inc_not_zero(&fsd->active_users))
+ return -EIO;
+
return 0;
}
-EXPORT_SYMBOL_GPL(debugfs_use_file_start);
+EXPORT_SYMBOL_GPL(debugfs_file_get);
/**
- * debugfs_use_file_finish - mark the end of file data access
- * @srcu_idx: the SRCU index "created" by a former call to
- * debugfs_use_file_start().
+ * debugfs_file_put - mark the end of file data access
+ * @dentry: the dentry object formerly passed to
+ * debugfs_file_get().
*
* Allow any ongoing concurrent call into debugfs_remove() or
* debugfs_remove_recursive() blocked by a former call to
- * debugfs_use_file_start() to proceed and return to its caller.
+ * debugfs_file_get() to proceed and return to its caller.
*/
-void debugfs_use_file_finish(int srcu_idx) __releases(&debugfs_srcu)
+void debugfs_file_put(struct dentry *dentry)
{
- srcu_read_unlock(&debugfs_srcu, srcu_idx);
-}
-EXPORT_SYMBOL_GPL(debugfs_use_file_finish);
+ struct debugfs_fsdata *fsd = READ_ONCE(dentry->d_fsdata);
-#define F_DENTRY(filp) ((filp)->f_path.dentry)
+ if (refcount_dec_and_test(&fsd->active_users))
+ complete(&fsd->active_users_drained);
+}
+EXPORT_SYMBOL_GPL(debugfs_file_put);
static int open_proxy_open(struct inode *inode, struct file *filp)
{
- const struct dentry *dentry = F_DENTRY(filp);
+ struct dentry *dentry = F_DENTRY(filp);
const struct file_operations *real_fops = NULL;
- int srcu_idx, r;
+ int r;
- r = debugfs_use_file_start(dentry, &srcu_idx);
- if (r) {
- r = -ENOENT;
- goto out;
- }
+ r = debugfs_file_get(dentry);
+ if (r)
+ return r == -EIO ? -ENOENT : r;
real_fops = debugfs_real_fops(filp);
real_fops = fops_get(real_fops);
@@ -124,7 +165,7 @@
r = real_fops->open(inode, filp);
out:
- debugfs_use_file_finish(srcu_idx);
+ debugfs_file_put(dentry);
return r;
}
@@ -138,16 +179,16 @@
#define FULL_PROXY_FUNC(name, ret_type, filp, proto, args) \
static ret_type full_proxy_ ## name(proto) \
{ \
- const struct dentry *dentry = F_DENTRY(filp); \
- const struct file_operations *real_fops = \
- debugfs_real_fops(filp); \
- int srcu_idx; \
+ struct dentry *dentry = F_DENTRY(filp); \
+ const struct file_operations *real_fops; \
ret_type r; \
\
- r = debugfs_use_file_start(dentry, &srcu_idx); \
- if (likely(!r)) \
- r = real_fops->name(args); \
- debugfs_use_file_finish(srcu_idx); \
+ r = debugfs_file_get(dentry); \
+ if (unlikely(r)) \
+ return r; \
+ real_fops = debugfs_real_fops(filp); \
+ r = real_fops->name(args); \
+ debugfs_file_put(dentry); \
return r; \
}
@@ -172,18 +213,16 @@
static unsigned int full_proxy_poll(struct file *filp,
struct poll_table_struct *wait)
{
- const struct dentry *dentry = F_DENTRY(filp);
- const struct file_operations *real_fops = debugfs_real_fops(filp);
- int srcu_idx;
+ struct dentry *dentry = F_DENTRY(filp);
unsigned int r = 0;
+ const struct file_operations *real_fops;
- if (debugfs_use_file_start(dentry, &srcu_idx)) {
- debugfs_use_file_finish(srcu_idx);
+ if (debugfs_file_get(dentry))
return POLLHUP;
- }
+ real_fops = debugfs_real_fops(filp);
r = real_fops->poll(filp, wait);
- debugfs_use_file_finish(srcu_idx);
+ debugfs_file_put(dentry);
return r;
}
@@ -227,16 +266,14 @@
static int full_proxy_open(struct inode *inode, struct file *filp)
{
- const struct dentry *dentry = F_DENTRY(filp);
+ struct dentry *dentry = F_DENTRY(filp);
const struct file_operations *real_fops = NULL;
struct file_operations *proxy_fops = NULL;
- int srcu_idx, r;
+ int r;
- r = debugfs_use_file_start(dentry, &srcu_idx);
- if (r) {
- r = -ENOENT;
- goto out;
- }
+ r = debugfs_file_get(dentry);
+ if (r)
+ return r == -EIO ? -ENOENT : r;
real_fops = debugfs_real_fops(filp);
real_fops = fops_get(real_fops);
@@ -274,7 +311,7 @@
kfree(proxy_fops);
fops_put(real_fops);
out:
- debugfs_use_file_finish(srcu_idx);
+ debugfs_file_put(dentry);
return r;
}
@@ -285,13 +322,14 @@
ssize_t debugfs_attr_read(struct file *file, char __user *buf,
size_t len, loff_t *ppos)
{
+ struct dentry *dentry = F_DENTRY(file);
ssize_t ret;
- int srcu_idx;
- ret = debugfs_use_file_start(F_DENTRY(file), &srcu_idx);
- if (likely(!ret))
- ret = simple_attr_read(file, buf, len, ppos);
- debugfs_use_file_finish(srcu_idx);
+ ret = debugfs_file_get(dentry);
+ if (unlikely(ret))
+ return ret;
+ ret = simple_attr_read(file, buf, len, ppos);
+ debugfs_file_put(dentry);
return ret;
}
EXPORT_SYMBOL_GPL(debugfs_attr_read);
@@ -299,13 +337,14 @@
ssize_t debugfs_attr_write(struct file *file, const char __user *buf,
size_t len, loff_t *ppos)
{
+ struct dentry *dentry = F_DENTRY(file);
ssize_t ret;
- int srcu_idx;
- ret = debugfs_use_file_start(F_DENTRY(file), &srcu_idx);
- if (likely(!ret))
- ret = simple_attr_write(file, buf, len, ppos);
- debugfs_use_file_finish(srcu_idx);
+ ret = debugfs_file_get(dentry);
+ if (unlikely(ret))
+ return ret;
+ ret = simple_attr_write(file, buf, len, ppos);
+ debugfs_file_put(dentry);
return ret;
}
EXPORT_SYMBOL_GPL(debugfs_attr_write);
@@ -739,14 +778,14 @@
{
char buf[3];
bool val;
- int r, srcu_idx;
+ int r;
+ struct dentry *dentry = F_DENTRY(file);
- r = debugfs_use_file_start(F_DENTRY(file), &srcu_idx);
- if (likely(!r))
- val = *(bool *)file->private_data;
- debugfs_use_file_finish(srcu_idx);
- if (r)
+ r = debugfs_file_get(dentry);
+ if (unlikely(r))
return r;
+ val = *(bool *)file->private_data;
+ debugfs_file_put(dentry);
if (val)
buf[0] = 'Y';
@@ -764,8 +803,9 @@
char buf[32];
size_t buf_size;
bool bv;
- int r, srcu_idx;
+ int r;
bool *val = file->private_data;
+ struct dentry *dentry = F_DENTRY(file);
buf_size = min(count, (sizeof(buf)-1));
if (copy_from_user(buf, user_buf, buf_size))
@@ -773,12 +813,11 @@
buf[buf_size] = '\0';
if (strtobool(buf, &bv) == 0) {
- r = debugfs_use_file_start(F_DENTRY(file), &srcu_idx);
- if (likely(!r))
- *val = bv;
- debugfs_use_file_finish(srcu_idx);
- if (r)
+ r = debugfs_file_get(dentry);
+ if (unlikely(r))
return r;
+ *val = bv;
+ debugfs_file_put(dentry);
}
return count;
@@ -840,14 +879,15 @@
size_t count, loff_t *ppos)
{
struct debugfs_blob_wrapper *blob = file->private_data;
+ struct dentry *dentry = F_DENTRY(file);
ssize_t r;
- int srcu_idx;
- r = debugfs_use_file_start(F_DENTRY(file), &srcu_idx);
- if (likely(!r))
- r = simple_read_from_buffer(user_buf, count, ppos, blob->data,
- blob->size);
- debugfs_use_file_finish(srcu_idx);
+ r = debugfs_file_get(dentry);
+ if (unlikely(r))
+ return r;
+ r = simple_read_from_buffer(user_buf, count, ppos, blob->data,
+ blob->size);
+ debugfs_file_put(dentry);
return r;
}
diff --git a/fs/debugfs/inode.c b/fs/debugfs/inode.c
index 3d7de9f..f7f672d 100644
--- a/fs/debugfs/inode.c
+++ b/fs/debugfs/inode.c
@@ -27,14 +27,11 @@
#include <linux/parser.h>
#include <linux/magic.h>
#include <linux/slab.h>
-#include <linux/srcu.h>
#include "internal.h"
#define DEBUGFS_DEFAULT_MODE 0700
-DEFINE_SRCU(debugfs_srcu);
-
static struct vfsmount *debugfs_mount;
static int debugfs_mount_count;
static bool debugfs_registered;
@@ -185,6 +182,14 @@
.evict_inode = debugfs_evict_inode,
};
+static void debugfs_release_dentry(struct dentry *dentry)
+{
+ void *fsd = dentry->d_fsdata;
+
+ if (!((unsigned long)fsd & DEBUGFS_FSDATA_IS_REAL_FOPS_BIT))
+ kfree(dentry->d_fsdata);
+}
+
static struct vfsmount *debugfs_automount(struct path *path)
{
debugfs_automount_t f;
@@ -194,6 +199,7 @@
static const struct dentry_operations debugfs_dops = {
.d_delete = always_delete_dentry,
+ .d_release = debugfs_release_dentry,
.d_automount = debugfs_automount,
};
@@ -324,7 +330,8 @@
inode->i_private = data;
inode->i_fop = proxy_fops;
- dentry->d_fsdata = (void *)real_fops;
+ dentry->d_fsdata = (void *)((unsigned long)real_fops |
+ DEBUGFS_FSDATA_IS_REAL_FOPS_BIT);
d_instantiate(dentry, inode);
fsnotify_create(d_inode(dentry->d_parent), dentry);
@@ -581,18 +588,43 @@
}
EXPORT_SYMBOL_GPL(debugfs_create_symlink);
+static void __debugfs_remove_file(struct dentry *dentry, struct dentry *parent)
+{
+ struct debugfs_fsdata *fsd;
+
+ simple_unlink(d_inode(parent), dentry);
+ d_delete(dentry);
+
+ /*
+ * Paired with the closing smp_mb() implied by a successful
+ * cmpxchg() in debugfs_file_get(): either
+ * debugfs_file_get() must see a dead dentry or we must see a
+ * debugfs_fsdata instance at ->d_fsdata here (or both).
+ */
+ smp_mb();
+ fsd = READ_ONCE(dentry->d_fsdata);
+ if ((unsigned long)fsd & DEBUGFS_FSDATA_IS_REAL_FOPS_BIT)
+ return;
+ if (!refcount_dec_and_test(&fsd->active_users))
+ wait_for_completion(&fsd->active_users_drained);
+}
+
static int __debugfs_remove(struct dentry *dentry, struct dentry *parent)
{
int ret = 0;
if (simple_positive(dentry)) {
dget(dentry);
- if (d_is_dir(dentry))
- ret = simple_rmdir(d_inode(parent), dentry);
- else
- simple_unlink(d_inode(parent), dentry);
- if (!ret)
- d_delete(dentry);
+ if (!d_is_reg(dentry)) {
+ if (d_is_dir(dentry))
+ ret = simple_rmdir(d_inode(parent), dentry);
+ else
+ simple_unlink(d_inode(parent), dentry);
+ if (!ret)
+ d_delete(dentry);
+ } else {
+ __debugfs_remove_file(dentry, parent);
+ }
dput(dentry);
}
return ret;
@@ -626,8 +658,6 @@
inode_unlock(d_inode(parent));
if (!ret)
simple_release_fs(&debugfs_mount, &debugfs_mount_count);
-
- synchronize_srcu(&debugfs_srcu);
}
EXPORT_SYMBOL_GPL(debugfs_remove);
@@ -701,8 +731,6 @@
if (!__debugfs_remove(child, parent))
simple_release_fs(&debugfs_mount, &debugfs_mount_count);
inode_unlock(d_inode(parent));
-
- synchronize_srcu(&debugfs_srcu);
}
EXPORT_SYMBOL_GPL(debugfs_remove_recursive);
diff --git a/fs/debugfs/internal.h b/fs/debugfs/internal.h
index b3e8443..49ba8dd 100644
--- a/fs/debugfs/internal.h
+++ b/fs/debugfs/internal.h
@@ -12,6 +12,8 @@
#ifndef _DEBUGFS_INTERNAL_H_
#define _DEBUGFS_INTERNAL_H_
+#include <linux/refcount.h>
+
struct file_operations;
/* declared over in file.c */
@@ -19,4 +21,18 @@
extern const struct file_operations debugfs_open_proxy_file_operations;
extern const struct file_operations debugfs_full_proxy_file_operations;
+struct debugfs_fsdata {
+ const struct file_operations *real_fops;
+ refcount_t active_users;
+ struct completion active_users_drained;
+};
+
+/*
+ * A dentry's ->d_fsdata either points to the real fops or to a
+ * dynamically allocated debugfs_fsdata instance.
+ * In order to distinguish between these two cases, a real fops
+ * pointer gets its lowest bit set.
+ */
+#define DEBUGFS_FSDATA_IS_REAL_FOPS_BIT BIT(0)
+
#endif /* _DEBUGFS_INTERNAL_H_ */
diff --git a/fs/ext2/inode.c b/fs/ext2/inode.c
index 41b8b44..85449a6 100644
--- a/fs/ext2/inode.c
+++ b/fs/ext2/inode.c
@@ -1258,21 +1258,11 @@
static void ext2_truncate_blocks(struct inode *inode, loff_t offset)
{
- /*
- * XXX: it seems like a bug here that we don't allow
- * IS_APPEND inode to have blocks-past-i_size trimmed off.
- * review and fix this.
- *
- * Also would be nice to be able to handle IO errors and such,
- * but that's probably too much to ask.
- */
if (!(S_ISREG(inode->i_mode) || S_ISDIR(inode->i_mode) ||
S_ISLNK(inode->i_mode)))
return;
if (ext2_inode_is_fast_symlink(inode))
return;
- if (IS_APPEND(inode) || IS_IMMUTABLE(inode))
- return;
dax_sem_down_write(EXT2_I(inode));
__ext2_truncate_blocks(inode, offset);
diff --git a/fs/hfsplus/super.c b/fs/hfsplus/super.c
index 11854dd..b9563cd 100644
--- a/fs/hfsplus/super.c
+++ b/fs/hfsplus/super.c
@@ -588,6 +588,7 @@
return 0;
out_put_hidden_dir:
+ cancel_delayed_work_sync(&sbi->sync_work);
iput(sbi->hidden_dir);
out_put_root:
dput(sb->s_root);
diff --git a/fs/proc/array.c b/fs/proc/array.c
index 794b52a..94f83e7 100644
--- a/fs/proc/array.c
+++ b/fs/proc/array.c
@@ -80,6 +80,7 @@
#include <linux/delayacct.h>
#include <linux/seq_file.h>
#include <linux/pid_namespace.h>
+#include <linux/prctl.h>
#include <linux/ptrace.h>
#include <linux/tracehook.h>
#include <linux/string_helpers.h>
@@ -345,8 +346,32 @@
{
#ifdef CONFIG_SECCOMP
seq_put_decimal_ull(m, "Seccomp:\t", p->seccomp.mode);
- seq_putc(m, '\n');
#endif
+ seq_printf(m, "\nSpeculation_Store_Bypass:\t");
+ switch (arch_prctl_spec_ctrl_get(p, PR_SPEC_STORE_BYPASS)) {
+ case -EINVAL:
+ seq_printf(m, "unknown");
+ break;
+ case PR_SPEC_NOT_AFFECTED:
+ seq_printf(m, "not vulnerable");
+ break;
+ case PR_SPEC_PRCTL | PR_SPEC_FORCE_DISABLE:
+ seq_printf(m, "thread force mitigated");
+ break;
+ case PR_SPEC_PRCTL | PR_SPEC_DISABLE:
+ seq_printf(m, "thread mitigated");
+ break;
+ case PR_SPEC_PRCTL | PR_SPEC_ENABLE:
+ seq_printf(m, "thread vulnerable");
+ break;
+ case PR_SPEC_DISABLE:
+ seq_printf(m, "globally mitigated");
+ break;
+ default:
+ seq_printf(m, "vulnerable");
+ break;
+ }
+ seq_putc(m, '\n');
}
static inline void task_context_switch_counts(struct seq_file *m,
diff --git a/fs/proc/uid.c b/fs/proc/uid.c
index 3fd7b9f..b2bb085 100644
--- a/fs/proc/uid.c
+++ b/fs/proc/uid.c
@@ -174,7 +174,7 @@
return 0;
for (u = uid_base_stuff + (ctx->pos - 2);
- u <= uid_base_stuff + nents - 1; u++) {
+ u < uid_base_stuff + nents; u++) {
if (!proc_fill_cache(file, ctx, u->name, u->len,
proc_uident_instantiate, NULL, u))
break;
diff --git a/include/asm-generic/atomic-long.h b/include/asm-generic/atomic-long.h
index 288cc9e..f2d97b7 100644
--- a/include/asm-generic/atomic-long.h
+++ b/include/asm-generic/atomic-long.h
@@ -243,4 +243,7 @@
#define atomic_long_inc_not_zero(l) \
ATOMIC_LONG_PFX(_inc_not_zero)((ATOMIC_LONG_PFX(_t) *)(l))
+#define atomic_long_cond_read_acquire(v, c) \
+ ATOMIC_LONG_PFX(_cond_read_acquire)((ATOMIC_LONG_PFX(_t) *)(v), (c))
+
#endif /* _ASM_GENERIC_ATOMIC_LONG_H */
diff --git a/include/asm-generic/qrwlock.h b/include/asm-generic/qrwlock.h
index 7d026bf..814d5b64 100644
--- a/include/asm-generic/qrwlock.h
+++ b/include/asm-generic/qrwlock.h
@@ -49,7 +49,7 @@
/*
* External function declarations
*/
-extern void queued_read_lock_slowpath(struct qrwlock *lock, u32 cnts);
+extern void queued_read_lock_slowpath(struct qrwlock *lock);
extern void queued_write_lock_slowpath(struct qrwlock *lock);
/**
@@ -118,7 +118,7 @@
return;
/* The slowpath will decrement the reader count, if necessary. */
- queued_read_lock_slowpath(lock, cnts);
+ queued_read_lock_slowpath(lock);
}
/**
@@ -147,22 +147,12 @@
}
/**
- * __qrwlock_write_byte - retrieve the write byte address of a queue rwlock
- * @lock : Pointer to queue rwlock structure
- * Return: the write byte address of a queue rwlock
- */
-static inline u8 *__qrwlock_write_byte(struct qrwlock *lock)
-{
- return (u8 *)lock + 3 * IS_BUILTIN(CONFIG_CPU_BIG_ENDIAN);
-}
-
-/**
* queued_write_unlock - release write lock of a queue rwlock
* @lock : Pointer to queue rwlock structure
*/
static inline void queued_write_unlock(struct qrwlock *lock)
{
- smp_store_release(__qrwlock_write_byte(lock), 0);
+ smp_store_release(&lock->wmode, 0);
}
/*
diff --git a/include/asm-generic/qrwlock_types.h b/include/asm-generic/qrwlock_types.h
index 0abc6b6..507f2dc 100644
--- a/include/asm-generic/qrwlock_types.h
+++ b/include/asm-generic/qrwlock_types.h
@@ -9,12 +9,23 @@
*/
typedef struct qrwlock {
- atomic_t cnts;
+ union {
+ atomic_t cnts;
+ struct {
+#ifdef __LITTLE_ENDIAN
+ u8 wmode; /* Writer mode */
+ u8 rcnts[3]; /* Reader counts */
+#else
+ u8 rcnts[3]; /* Reader counts */
+ u8 wmode; /* Writer mode */
+#endif
+ };
+ };
arch_spinlock_t wait_lock;
} arch_rwlock_t;
#define __ARCH_RW_LOCK_UNLOCKED { \
- .cnts = ATOMIC_INIT(0), \
+ { .cnts = ATOMIC_INIT(0), }, \
.wait_lock = __ARCH_SPIN_LOCK_UNLOCKED, \
}
diff --git a/include/linux/atomic.h b/include/linux/atomic.h
index e71835b..bc7dba0 100644
--- a/include/linux/atomic.h
+++ b/include/linux/atomic.h
@@ -627,6 +627,8 @@
}
#endif
+#define atomic_cond_read_acquire(v, c) smp_cond_load_acquire(&(v)->counter, (c))
+
#ifdef CONFIG_GENERIC_ATOMIC64
#include <asm-generic/atomic64.h>
#endif
@@ -1023,6 +1025,8 @@
}
#endif
+#define atomic64_cond_read_acquire(v, c) smp_cond_load_acquire(&(v)->counter, (c))
+
#include <asm-generic/atomic-long.h>
#endif /* _LINUX_ATOMIC_H */
diff --git a/include/linux/cpu.h b/include/linux/cpu.h
index 1f7e4ec..912d945 100644
--- a/include/linux/cpu.h
+++ b/include/linux/cpu.h
@@ -50,6 +50,8 @@
struct device_attribute *attr, char *buf);
extern ssize_t cpu_show_spectre_v2(struct device *dev,
struct device_attribute *attr, char *buf);
+extern ssize_t cpu_show_spec_store_bypass(struct device *dev,
+ struct device_attribute *attr, char *buf);
extern __printf(4, 5)
struct device *cpu_device_create(struct device *parent, void *drvdata,
diff --git a/include/linux/cpufreq.h b/include/linux/cpufreq.h
index 45d5522..0fbce32 100644
--- a/include/linux/cpufreq.h
+++ b/include/linux/cpufreq.h
@@ -424,6 +424,7 @@
#define CPUFREQ_START (2)
#define CPUFREQ_CREATE_POLICY (3)
#define CPUFREQ_REMOVE_POLICY (4)
+#define CPUFREQ_STOP (5)
/* Govinfo Notifiers */
#define CPUFREQ_LOAD_CHANGE (0)
diff --git a/include/linux/debugfs.h b/include/linux/debugfs.h
index b20a094..2e75ae2 100644
--- a/include/linux/debugfs.h
+++ b/include/linux/debugfs.h
@@ -23,7 +23,6 @@
struct device;
struct file_operations;
-struct srcu_struct;
struct debugfs_blob_wrapper {
void *data;
@@ -43,25 +42,6 @@
extern struct dentry *arch_debugfs_dir;
-extern struct srcu_struct debugfs_srcu;
-
-/**
- * debugfs_real_fops - getter for the real file operation
- * @filp: a pointer to a struct file
- *
- * Must only be called under the protection established by
- * debugfs_use_file_start().
- */
-static inline const struct file_operations *debugfs_real_fops(struct file *filp)
- __must_hold(&debugfs_srcu)
-{
- /*
- * Neither the pointer to the struct file_operations, nor its
- * contents ever change -- srcu_dereference() is not needed here.
- */
- return filp->f_path.dentry->d_fsdata;
-}
-
#define DEFINE_DEBUGFS_ATTRIBUTE(__fops, __get, __set, __fmt) \
static int __fops ## _open(struct inode *inode, struct file *file) \
{ \
@@ -105,10 +85,10 @@
void debugfs_remove(struct dentry *dentry);
void debugfs_remove_recursive(struct dentry *dentry);
-int debugfs_use_file_start(const struct dentry *dentry, int *srcu_idx)
- __acquires(&debugfs_srcu);
+const struct file_operations *debugfs_real_fops(const struct file *filp);
-void debugfs_use_file_finish(int srcu_idx) __releases(&debugfs_srcu);
+int debugfs_file_get(struct dentry *dentry);
+void debugfs_file_put(struct dentry *dentry);
ssize_t debugfs_attr_read(struct file *file, char __user *buf,
size_t len, loff_t *ppos);
@@ -223,15 +203,12 @@
static inline void debugfs_remove_recursive(struct dentry *dentry)
{ }
-static inline int debugfs_use_file_start(const struct dentry *dentry,
- int *srcu_idx)
- __acquires(&debugfs_srcu)
+static inline int debugfs_file_get(struct dentry *dentry)
{
return 0;
}
-static inline void debugfs_use_file_finish(int srcu_idx)
- __releases(&debugfs_srcu)
+static inline void debugfs_file_put(struct dentry *dentry)
{ }
static inline ssize_t debugfs_attr_read(struct file *file, char __user *buf,
diff --git a/include/linux/efi.h b/include/linux/efi.h
index 5e204a5..2877ccb 100644
--- a/include/linux/efi.h
+++ b/include/linux/efi.h
@@ -380,8 +380,8 @@
u32 attributes;
u32 get_bar_attributes;
u32 set_bar_attributes;
- uint64_t romsize;
- void *romimage;
+ u64 romsize;
+ u32 romimage;
} efi_pci_io_protocol_32;
typedef struct {
@@ -400,8 +400,8 @@
u64 attributes;
u64 get_bar_attributes;
u64 set_bar_attributes;
- uint64_t romsize;
- void *romimage;
+ u64 romsize;
+ u64 romimage;
} efi_pci_io_protocol_64;
typedef struct {
diff --git a/include/linux/ipa.h b/include/linux/ipa.h
index 1a1c68e..2c31666 100644
--- a/include/linux/ipa.h
+++ b/include/linux/ipa.h
@@ -1156,6 +1156,7 @@
* @ipa_if_tlv: number of IPA_IF TLV
* @ipa_if_aos: number of IPA_IF AOS
* @ee: Execution environment
+ * @prefetch_mode: Prefetch mode to be used
*/
struct ipa_gsi_ep_config {
int ipa_ep_num;
@@ -1163,6 +1164,7 @@
int ipa_if_tlv;
int ipa_if_aos;
int ee;
+ enum gsi_prefetch_mode prefetch_mode;
};
/**
diff --git a/include/linux/leds.h b/include/linux/leds.h
index 66a1f4e..b27315c 100644
--- a/include/linux/leds.h
+++ b/include/linux/leds.h
@@ -35,6 +35,7 @@
const char *name;
enum led_brightness brightness;
enum led_brightness max_brightness;
+ enum led_brightness usr_brightness_req;
int flags;
/* Lower 16 bits reflect status */
diff --git a/include/linux/mmc/host.h b/include/linux/mmc/host.h
index 9a20d3c..149b718 100644
--- a/include/linux/mmc/host.h
+++ b/include/linux/mmc/host.h
@@ -694,6 +694,7 @@
#define mmc_bus_manual_resume(host) ((host)->bus_resume_flags & \
MMC_BUSRESUME_MANUAL_RESUME)
+#ifdef CONFIG_MMC_BLOCK_DEFERRED_RESUME
static inline void mmc_set_bus_resume_policy(struct mmc_host *host, int manual)
{
if (manual)
@@ -701,6 +702,11 @@
else
host->bus_resume_flags &= ~MMC_BUSRESUME_MANUAL_RESUME;
}
+#else
+static inline void mmc_set_bus_resume_policy(struct mmc_host *host, int manual)
+{
+}
+#endif
extern int mmc_resume_bus(struct mmc_host *host);
diff --git a/include/linux/msm_gsi.h b/include/linux/msm_gsi.h
index 3b1e0e7..79e7daa 100644
--- a/include/linux/msm_gsi.h
+++ b/include/linux/msm_gsi.h
@@ -854,6 +854,18 @@
union __packed gsi_channel_scratch val);
/**
+ * gsi_read_channel_scratch - Peripheral should call this function to
+ * read the scratch area of the channel context
+ *
+ * @chan_hdl: Client handle previously obtained from
+ * gsi_alloc_channel
+ *
+ * @Return gsi_status
+ */
+int gsi_read_channel_scratch(unsigned long chan_hdl,
+ union __packed gsi_channel_scratch *ch_scratch);
+
+/**
* gsi_start_channel - Peripheral should call this function to
* start a channel i.e put into running state
*
@@ -1111,6 +1123,7 @@
* gsi_alloc_channel (for as many channels as needed; channels can have
* no event ring, an exclusive event ring or a shared event ring)
* gsi_write_channel_scratch
+ * gsi_read_channel_scratch
* gsi_start_channel
* gsi_queue_xfer/gsi_start_xfer
* gsi_config_channel_mode/gsi_poll_channel (if clients wants to poll on
@@ -1195,6 +1208,12 @@
return -GSI_STATUS_UNSUPPORTED_OP;
}
+static inline int gsi_read_channel_scratch(unsigned long chan_hdl,
+ union __packed gsi_channel_scratch *ch_scratch)
+{
+ return -GSI_STATUS_UNSUPPORTED_OP;
+}
+
static inline int gsi_start_channel(unsigned long chan_hdl)
{
return -GSI_STATUS_UNSUPPORTED_OP;
diff --git a/include/linux/nospec.h b/include/linux/nospec.h
index e791ebc..0c5ef54 100644
--- a/include/linux/nospec.h
+++ b/include/linux/nospec.h
@@ -7,6 +7,8 @@
#define _LINUX_NOSPEC_H
#include <asm/barrier.h>
+struct task_struct;
+
/**
* array_index_mask_nospec() - generate a ~0 mask when index < size, 0 otherwise
* @index: array element index
@@ -55,4 +57,12 @@
\
(typeof(_i)) (_i & _mask); \
})
+
+/* Speculation control prctl */
+int arch_prctl_spec_ctrl_get(struct task_struct *task, unsigned long which);
+int arch_prctl_spec_ctrl_set(struct task_struct *task, unsigned long which,
+ unsigned long ctrl);
+/* Speculation control for seccomp enforced mitigation */
+void arch_seccomp_spec_mitigate(struct task_struct *task);
+
#endif /* _LINUX_NOSPEC_H */
diff --git a/include/linux/power_supply.h b/include/linux/power_supply.h
index 78c2a9f..9412480 100644
--- a/include/linux/power_supply.h
+++ b/include/linux/power_supply.h
@@ -125,6 +125,18 @@
POWER_SUPPLY_PL_NON_STACKED_BATFET,
};
+enum {
+ POWER_SUPPLY_PD_INACTIVE = 0,
+ POWER_SUPPLY_PD_ACTIVE,
+ POWER_SUPPLY_PD_PPS_ACTIVE,
+};
+
+enum {
+ POWER_SUPPLY_QC_CTM_DISABLE = BIT(0),
+ POWER_SUPPLY_QC_THERMAL_BALANCE_DISABLE = BIT(1),
+ POWER_SUPPLY_QC_INOV_THERMAL_DISABLE = BIT(2),
+};
+
enum power_supply_property {
/* Properties of type `int' */
POWER_SUPPLY_PROP_STATUS = 0,
@@ -286,6 +298,10 @@
POWER_SUPPLY_PROP_BATTERY_INFO,
POWER_SUPPLY_PROP_BATTERY_INFO_ID,
POWER_SUPPLY_PROP_ENABLE_JEITA_DETECTION,
+ POWER_SUPPLY_PROP_ESR_ACTUAL,
+ POWER_SUPPLY_PROP_ESR_NOMINAL,
+ POWER_SUPPLY_PROP_SOH,
+ POWER_SUPPLY_PROP_QC_OPTI_DISABLE,
/* Local extensions of type int64_t */
POWER_SUPPLY_PROP_CHARGE_COUNTER_EXT,
/* Properties of type `const char *' */
diff --git a/include/linux/sched.h b/include/linux/sched.h
index 0748b7b..6b03b08 100644
--- a/include/linux/sched.h
+++ b/include/linux/sched.h
@@ -2629,6 +2629,8 @@
#define PFA_SPREAD_PAGE 1 /* Spread page cache over cpuset */
#define PFA_SPREAD_SLAB 2 /* Spread some slab caches over cpuset */
#define PFA_LMK_WAITING 3 /* Lowmemorykiller is waiting */
+#define PFA_SPEC_SSB_DISABLE 4 /* Speculative Store Bypass disabled */
+#define PFA_SPEC_SSB_FORCE_DISABLE 5 /* Speculative Store Bypass force disabled*/
#define TASK_PFA_TEST(name, func) \
@@ -2655,6 +2657,13 @@
TASK_PFA_TEST(LMK_WAITING, lmk_waiting)
TASK_PFA_SET(LMK_WAITING, lmk_waiting)
+TASK_PFA_TEST(SPEC_SSB_DISABLE, spec_ssb_disable)
+TASK_PFA_SET(SPEC_SSB_DISABLE, spec_ssb_disable)
+TASK_PFA_CLEAR(SPEC_SSB_DISABLE, spec_ssb_disable)
+
+TASK_PFA_TEST(SPEC_SSB_FORCE_DISABLE, spec_ssb_force_disable)
+TASK_PFA_SET(SPEC_SSB_FORCE_DISABLE, spec_ssb_force_disable)
+
/*
* task->jobctl flags
*/
diff --git a/include/linux/seccomp.h b/include/linux/seccomp.h
index ecc296c..50c460a 100644
--- a/include/linux/seccomp.h
+++ b/include/linux/seccomp.h
@@ -3,7 +3,8 @@
#include <uapi/linux/seccomp.h>
-#define SECCOMP_FILTER_FLAG_MASK (SECCOMP_FILTER_FLAG_TSYNC)
+#define SECCOMP_FILTER_FLAG_MASK (SECCOMP_FILTER_FLAG_TSYNC | \
+ SECCOMP_FILTER_FLAG_SPEC_ALLOW)
#ifdef CONFIG_SECCOMP
diff --git a/include/linux/signal.h b/include/linux/signal.h
index b63f63e..5308304 100644
--- a/include/linux/signal.h
+++ b/include/linux/signal.h
@@ -97,6 +97,23 @@
}
}
+static inline int sigequalsets(const sigset_t *set1, const sigset_t *set2)
+{
+ switch (_NSIG_WORDS) {
+ case 4:
+ return (set1->sig[3] == set2->sig[3]) &&
+ (set1->sig[2] == set2->sig[2]) &&
+ (set1->sig[1] == set2->sig[1]) &&
+ (set1->sig[0] == set2->sig[0]);
+ case 2:
+ return (set1->sig[1] == set2->sig[1]) &&
+ (set1->sig[0] == set2->sig[0]);
+ case 1:
+ return set1->sig[0] == set2->sig[0];
+ }
+ return 0;
+}
+
#define sigmask(sig) (1UL << ((sig) - 1))
#ifndef __HAVE_ARCH_SIG_SETOPS
diff --git a/include/linux/usb/composite.h b/include/linux/usb/composite.h
index 7f4367b..87e97bb 100644
--- a/include/linux/usb/composite.h
+++ b/include/linux/usb/composite.h
@@ -45,6 +45,9 @@
#define FUNC_SUSPEND_OPT_SUSP_MASK BIT(0)
#define FUNC_SUSPEND_OPT_RW_EN_MASK BIT(1)
+#define FUNC_WAKEUP_CAPABLE_SHIFT 0
+#define FUNC_WAKEUP_ENABLE_SHIFT 1
+
/*
* USB function drivers should return USB_GADGET_DELAYED_STATUS if they
* wish to delay the data/status stages of the control transfer till they
@@ -57,6 +60,9 @@
/* big enough to hold our biggest descriptor */
#define USB_COMP_EP0_BUFSIZ 4096
+/* OS feature descriptor length <= 4kB */
+#define USB_COMP_EP0_OS_DESC_BUFSIZ 4096
+
#define USB_MS_TO_HS_INTERVAL(x) (ilog2((x * 1000 / 125)) + 1)
struct usb_configuration;
diff --git a/include/media/msm_cam_sensor.h b/include/media/msm_cam_sensor.h
index 2c8b651..54cd27b 100644
--- a/include/media/msm_cam_sensor.h
+++ b/include/media/msm_cam_sensor.h
@@ -26,6 +26,21 @@
uint16_t size_down;
};
+struct msm_camera_i2c_reg_setting32 {
+ compat_uptr_t reg_setting;
+ uint16_t size;
+ enum msm_camera_i2c_reg_addr_type addr_type;
+ enum msm_camera_i2c_data_type data_type;
+ uint16_t delay;
+};
+
+struct msm_sensor_id_info_t32 {
+ unsigned short sensor_id_reg_addr;
+ unsigned short sensor_id;
+ unsigned short sensor_id_mask;
+ struct msm_camera_i2c_reg_setting32 setting;
+};
+
struct msm_camera_sensor_slave_info32 {
char sensor_name[32];
char eeprom_name[32];
@@ -36,7 +51,7 @@
uint16_t slave_addr;
enum i2c_freq_mode_t i2c_freq_mode;
enum msm_camera_i2c_reg_addr_type addr_type;
- struct msm_sensor_id_info_t sensor_id_info;
+ struct msm_sensor_id_info_t32 sensor_id_info;
struct msm_sensor_power_setting_array32 power_setting_array;
uint8_t is_init_params_valid;
struct msm_sensor_init_params sensor_init_params;
@@ -128,14 +143,6 @@
uint16_t delay;
};
-struct msm_camera_i2c_reg_setting32 {
- compat_uptr_t reg_setting;
- uint16_t size;
- enum msm_camera_i2c_reg_addr_type addr_type;
- enum msm_camera_i2c_data_type data_type;
- uint16_t delay;
-};
-
struct msm_camera_i2c_array_write_config32 {
struct msm_camera_i2c_reg_setting32 conf_array;
uint16_t slave_addr;
diff --git a/include/soc/qcom/camera2.h b/include/soc/qcom/camera2.h
index c529aff..5139d22 100644
--- a/include/soc/qcom/camera2.h
+++ b/include/soc/qcom/camera2.h
@@ -47,6 +47,7 @@
uint16_t sensor_id_reg_addr;
uint16_t sensor_id;
uint16_t sensor_id_mask;
+ struct msm_camera_i2c_reg_setting *setting;
};
struct msm_cam_clk_info {
diff --git a/include/soc/qcom/qseecomi.h b/include/soc/qcom/qseecomi.h
index a7d4190..d249168 100644
--- a/include/soc/qcom/qseecomi.h
+++ b/include/soc/qcom/qseecomi.h
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2013-2017, The Linux Foundation. All rights reserved.
+ * Copyright (c) 2013-2018, The Linux Foundation. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 and
@@ -19,6 +19,7 @@
#define QSEECOM_KEY_ID_SIZE 32
#define QSEOS_RESULT_FAIL_SEND_CMD_NO_THREAD -19 /*0xFFFFFFED*/
+#define QSEOS_RESULT_FAIL_APP_ALREADY_LOADED -38 /*0xFFFFFFDA*/
#define QSEOS_RESULT_FAIL_UNSUPPORTED_CE_PIPE -63
#define QSEOS_RESULT_FAIL_KS_OP -64
#define QSEOS_RESULT_FAIL_KEY_ID_EXISTS -65
diff --git a/include/soc/qcom/socinfo.h b/include/soc/qcom/socinfo.h
index 5f496a8..d4ebb7d 100644
--- a/include/soc/qcom/socinfo.h
+++ b/include/soc/qcom/socinfo.h
@@ -102,16 +102,22 @@
of_flat_dt_is_compatible(of_get_flat_dt_root(), "qcom,sdm845")
#define early_machine_is_sdm670() \
of_flat_dt_is_compatible(of_get_flat_dt_root(), "qcom,sdm670")
+#define early_machine_is_sxr1130() \
+ of_flat_dt_is_compatible(of_get_flat_dt_root(), "qcom,sxr1130")
#define early_machine_is_qcs605() \
of_flat_dt_is_compatible(of_get_flat_dt_root(), "qcom,qcs605")
#define early_machine_is_sda670() \
of_flat_dt_is_compatible(of_get_flat_dt_root(), "qcom,sda670")
#define early_machine_is_sdm710() \
of_flat_dt_is_compatible(of_get_flat_dt_root(), "qcom,sdm670")
+#define early_machine_is_sxr1120() \
+ of_flat_dt_is_compatible(of_get_flat_dt_root(), "qcom,sxr1120")
#define early_machine_is_msm8953() \
of_flat_dt_is_compatible(of_get_flat_dt_root(), "qcom,msm8953")
#define early_machine_is_msm8937() \
of_flat_dt_is_compatible(of_get_flat_dt_root(), "qcom,msm8937")
+#define early_machine_is_msm8917() \
+ of_flat_dt_is_compatible(of_get_flat_dt_root(), "qcom,msm8917")
#define early_machine_is_mdm9607() \
of_flat_dt_is_compatible(of_get_flat_dt_root(), "qcom,mdm9607")
#define early_machine_is_sdm450() \
@@ -169,11 +175,14 @@
#define early_machine_is_sdxpoorwills() 0
#define early_machine_is_sdm845() 0
#define early_machine_is_sdm670() 0
+#define early_machine_is_sxr1130() 0
#define early_machine_is_qcs605() 0
#define early_machine_is_sda670() 0
#define early_machine_is_sdm710() 0
+#define early_machine_is_sxr1120() 0
#define early_machine_is_msm8953() 0
#define early_machine_is_msm8937() 0
+#define early_machine_is_msm8917() 0
#define early_machine_is_sdm450() 0
#define early_machine_is_sdm632() 0
#define early_machine_is_sdm439() 0
@@ -243,14 +252,17 @@
SDX_CPU_SDXPOORWILLS,
MSM_CPU_SDM845,
MSM_CPU_SDM670,
+ MSM_CPU_SXR1130,
MSM_CPU_QCS605,
MSM_CPU_SDA670,
MSM_CPU_SDM710,
+ MSM_CPU_SXR1120,
MSM_CPU_8953,
MSM_CPU_SDM450,
MSM_CPU_SDM632,
MSM_CPU_SDA632,
MSM_CPU_8937,
+ MSM_CPU_8917,
MSM_CPU_9607,
MSM_CPU_SDM439,
MSM_CPU_SDM429,
diff --git a/include/trace/events/xen.h b/include/trace/events/xen.h
index bce990f..d6be935 100644
--- a/include/trace/events/xen.h
+++ b/include/trace/events/xen.h
@@ -377,22 +377,6 @@
DEFINE_XEN_MMU_PGD_EVENT(xen_mmu_pgd_pin);
DEFINE_XEN_MMU_PGD_EVENT(xen_mmu_pgd_unpin);
-TRACE_EVENT(xen_mmu_flush_tlb_all,
- TP_PROTO(int x),
- TP_ARGS(x),
- TP_STRUCT__entry(__array(char, x, 0)),
- TP_fast_assign((void)x),
- TP_printk("%s", "")
- );
-
-TRACE_EVENT(xen_mmu_flush_tlb,
- TP_PROTO(int x),
- TP_ARGS(x),
- TP_STRUCT__entry(__array(char, x, 0)),
- TP_fast_assign((void)x),
- TP_printk("%s", "")
- );
-
TRACE_EVENT(xen_mmu_flush_tlb_single,
TP_PROTO(unsigned long addr),
TP_ARGS(addr),
diff --git a/include/uapi/linux/msm_mdp_ext.h b/include/uapi/linux/msm_mdp_ext.h
index 1a2a7e2c..6e4a6d7 100644
--- a/include/uapi/linux/msm_mdp_ext.h
+++ b/include/uapi/linux/msm_mdp_ext.h
@@ -34,9 +34,9 @@
* To allow proper structure padding for 64bit/32bit target
*/
#ifdef __LP64
-#define MDP_LAYER_COMMIT_V1_PAD 2
+#define MDP_LAYER_COMMIT_V1_PAD 1
#else
-#define MDP_LAYER_COMMIT_V1_PAD 3
+#define MDP_LAYER_COMMIT_V1_PAD 2
#endif
/*
@@ -147,6 +147,9 @@
*/
#define MDP_COMMIT_AVR_ONE_SHOT_MODE 0x10
+/* Flag to update brightness when commit */
+#define MDP_COMMIT_UPDATE_BRIGHTNESS 0x40
+
/* Flag to enable concurrent writeback for the frame */
#define MDP_COMMIT_CWB_EN 0x800
@@ -485,6 +488,9 @@
/* FRC info per device which contains frame count and timestamp */
struct mdp_frc_info __user *frc_info;
+ /* Backlight level that would update when display commit */
+ uint32_t bl_level;
+
/* 32-bits reserved value for future usage. */
uint32_t reserved[MDP_LAYER_COMMIT_V1_PAD];
};
diff --git a/include/uapi/linux/nl80211.h b/include/uapi/linux/nl80211.h
index 9399a35..20a01ca 100644
--- a/include/uapi/linux/nl80211.h
+++ b/include/uapi/linux/nl80211.h
@@ -2603,6 +2603,8 @@
#define NL80211_ATTR_KEYS NL80211_ATTR_KEYS
#define NL80211_ATTR_FEATURE_FLAGS NL80211_ATTR_FEATURE_FLAGS
+#define NL80211_WIPHY_NAME_MAXLEN 128
+
#define NL80211_MAX_SUPP_RATES 32
#define NL80211_MAX_SUPP_HT_RATES 77
#define NL80211_MAX_SUPP_REG_RULES 64
diff --git a/include/uapi/linux/prctl.h b/include/uapi/linux/prctl.h
index c1af9b3..f0320a0 100644
--- a/include/uapi/linux/prctl.h
+++ b/include/uapi/linux/prctl.h
@@ -203,6 +203,18 @@
*/
#define PR_SET_TIMERSLACK_PID 127
+/* Per task speculation control */
+#define PR_GET_SPECULATION_CTRL 52
+#define PR_SET_SPECULATION_CTRL 53
+/* Speculation control variants */
+# define PR_SPEC_STORE_BYPASS 0
+/* Return and control values for PR_SET/GET_SPECULATION_CTRL */
+# define PR_SPEC_NOT_AFFECTED 0
+# define PR_SPEC_PRCTL (1UL << 0)
+# define PR_SPEC_ENABLE (1UL << 1)
+# define PR_SPEC_DISABLE (1UL << 2)
+# define PR_SPEC_FORCE_DISABLE (1UL << 3)
+
#define PR_SET_VMA 0x53564d41
# define PR_SET_VMA_ANON_NAME 0
diff --git a/include/uapi/linux/qg-profile.h b/include/uapi/linux/qg-profile.h
index bffddbb..0230b32 100644
--- a/include/uapi/linux/qg-profile.h
+++ b/include/uapi/linux/qg-profile.h
@@ -55,6 +55,8 @@
#define QG_MAX_FCC_MAH 16000
#define QG_MIN_SLOPE 1
#define QG_MAX_SLOPE 50000
+#define QG_ESR_SF_MIN 5000
+#define QG_ESR_SF_MAX 20000
/* IOCTLs to query battery profile data */
#define BPIOCXSOC _IOWR('B', 0x01, struct battery_params) /* SOC */
diff --git a/include/uapi/linux/qg.h b/include/uapi/linux/qg.h
index 2194e1f..40882a7 100644
--- a/include/uapi/linux/qg.h
+++ b/include/uapi/linux/qg.h
@@ -19,7 +19,7 @@
QG_ESR_CHARGE_SF,
QG_ESR_DISCHARGE_SF,
QG_FULL_SOC,
- QG_RESERVED_8,
+ QG_CLEAR_LEARNT_DATA,
QG_RESERVED_9,
QG_RESERVED_10,
QG_MAX,
@@ -32,6 +32,7 @@
#define QG_ESR_CHARGE_SF QG_ESR_CHARGE_SF
#define QG_ESR_DISCHARGE_SF QG_ESR_DISCHARGE_SF
#define QG_FULL_SOC QG_FULL_SOC
+#define QG_CLEAR_LEARNT_DATA QG_CLEAR_LEARNT_DATA
struct fifo_data {
unsigned int v;
diff --git a/include/uapi/linux/seccomp.h b/include/uapi/linux/seccomp.h
index 0f238a4..e4acb61 100644
--- a/include/uapi/linux/seccomp.h
+++ b/include/uapi/linux/seccomp.h
@@ -15,7 +15,9 @@
#define SECCOMP_SET_MODE_FILTER 1
/* Valid flags for SECCOMP_SET_MODE_FILTER */
-#define SECCOMP_FILTER_FLAG_TSYNC 1
+#define SECCOMP_FILTER_FLAG_TSYNC (1UL << 0)
+/* In v4.14+ SECCOMP_FILTER_FLAG_LOG is (1UL << 1) */
+#define SECCOMP_FILTER_FLAG_SPEC_ALLOW (1UL << 2)
/*
* All BPF programs must return a 32-bit value.
diff --git a/include/uapi/media/msm_camsensor_sdk.h b/include/uapi/media/msm_camsensor_sdk.h
index 6d25967..63abd156 100644
--- a/include/uapi/media/msm_camsensor_sdk.h
+++ b/include/uapi/media/msm_camsensor_sdk.h
@@ -50,6 +50,8 @@
#define MSM_SENSOR_BYPASS_VIDEO_NODE 1
+#define SENSOR_PROBE_WRITE
+
enum msm_sensor_camera_id_t {
CAMERA_0,
CAMERA_1,
@@ -292,10 +294,19 @@
unsigned int sensor_mount_angle;
};
+struct msm_camera_i2c_reg_setting {
+ struct msm_camera_i2c_reg_array *reg_setting;
+ unsigned short size;
+ enum msm_camera_i2c_reg_addr_type addr_type;
+ enum msm_camera_i2c_data_type data_type;
+ unsigned short delay;
+};
+
struct msm_sensor_id_info_t {
unsigned short sensor_id_reg_addr;
unsigned short sensor_id;
unsigned short sensor_id_mask;
+ struct msm_camera_i2c_reg_setting setting;
};
struct msm_camera_sensor_slave_info {
@@ -322,14 +333,6 @@
unsigned int delay;
};
-struct msm_camera_i2c_reg_setting {
- struct msm_camera_i2c_reg_array *reg_setting;
- unsigned short size;
- enum msm_camera_i2c_reg_addr_type addr_type;
- enum msm_camera_i2c_data_type data_type;
- unsigned short delay;
-};
-
struct msm_camera_csid_vc_cfg {
unsigned char cid;
unsigned char dt;
diff --git a/kernel/auditsc.c b/kernel/auditsc.c
index 2cd5256..93648f6 100644
--- a/kernel/auditsc.c
+++ b/kernel/auditsc.c
@@ -2252,10 +2252,11 @@
audit_sig_uid = uid;
security_task_getsecid(tsk, &audit_sig_sid);
}
- if (!audit_signals || audit_dummy_context())
- return 0;
}
+ if (!audit_signals || audit_dummy_context())
+ return 0;
+
/* optimize the common case by putting first signal recipient directly
* in audit_context */
if (!ctx->target_pid) {
diff --git a/kernel/exit.c b/kernel/exit.c
index 2c18194..ee8c601 100644
--- a/kernel/exit.c
+++ b/kernel/exit.c
@@ -717,6 +717,7 @@
static DEFINE_SPINLOCK(low_water_lock);
static int lowest_to_date = THREAD_SIZE;
unsigned long free;
+ int islower = false;
free = stack_not_used(current);
@@ -725,11 +726,15 @@
spin_lock(&low_water_lock);
if (free < lowest_to_date) {
- pr_info("%s (%d) used greatest stack depth: %lu bytes left\n",
- current->comm, task_pid_nr(current), free);
lowest_to_date = free;
+ islower = true;
}
spin_unlock(&low_water_lock);
+
+ if (islower) {
+ pr_info("%s (%d) used greatest stack depth: %lu bytes left\n",
+ current->comm, task_pid_nr(current), free);
+ }
}
#else
static inline void check_stack_usage(void) {}
diff --git a/kernel/locking/qrwlock.c b/kernel/locking/qrwlock.c
index 19248dd..d4eec10 100644
--- a/kernel/locking/qrwlock.c
+++ b/kernel/locking/qrwlock.c
@@ -22,49 +22,11 @@
#include <linux/hardirq.h>
#include <asm/qrwlock.h>
-/*
- * This internal data structure is used for optimizing access to some of
- * the subfields within the atomic_t cnts.
- */
-struct __qrwlock {
- union {
- atomic_t cnts;
- struct {
-#ifdef __LITTLE_ENDIAN
- u8 wmode; /* Writer mode */
- u8 rcnts[3]; /* Reader counts */
-#else
- u8 rcnts[3]; /* Reader counts */
- u8 wmode; /* Writer mode */
-#endif
- };
- };
- arch_spinlock_t lock;
-};
-
-/**
- * rspin_until_writer_unlock - inc reader count & spin until writer is gone
- * @lock : Pointer to queue rwlock structure
- * @writer: Current queue rwlock writer status byte
- *
- * In interrupt context or at the head of the queue, the reader will just
- * increment the reader count & wait until the writer releases the lock.
- */
-static __always_inline void
-rspin_until_writer_unlock(struct qrwlock *lock, u32 cnts)
-{
- while ((cnts & _QW_WMASK) == _QW_LOCKED) {
- cpu_relax_lowlatency();
- cnts = atomic_read_acquire(&lock->cnts);
- }
-}
-
/**
* queued_read_lock_slowpath - acquire read lock of a queue rwlock
* @lock: Pointer to queue rwlock structure
- * @cnts: Current qrwlock lock value
*/
-void queued_read_lock_slowpath(struct qrwlock *lock, u32 cnts)
+void queued_read_lock_slowpath(struct qrwlock *lock)
{
/*
* Readers come here when they cannot get the lock without waiting
@@ -72,13 +34,12 @@
if (unlikely(in_interrupt())) {
/*
* Readers in interrupt context will get the lock immediately
- * if the writer is just waiting (not holding the lock yet).
- * The rspin_until_writer_unlock() function returns immediately
- * in this case. Otherwise, they will spin (with ACQUIRE
- * semantics) until the lock is available without waiting in
- * the queue.
+ * if the writer is just waiting (not holding the lock yet),
+ * so spin with ACQUIRE semantics until the lock is available
+ * without waiting in the queue.
*/
- rspin_until_writer_unlock(lock, cnts);
+ atomic_cond_read_acquire(&lock->cnts, (VAL & _QW_WMASK)
+ != _QW_LOCKED);
return;
}
atomic_sub(_QR_BIAS, &lock->cnts);
@@ -87,14 +48,14 @@
* Put the reader into the wait queue
*/
arch_spin_lock(&lock->wait_lock);
+ atomic_add(_QR_BIAS, &lock->cnts);
/*
* The ACQUIRE semantics of the following spinning code ensure
* that accesses can't leak upwards out of our subsequent critical
* section in the case that the lock is currently held for write.
*/
- cnts = atomic_fetch_add_acquire(_QR_BIAS, &lock->cnts);
- rspin_until_writer_unlock(lock, cnts);
+ atomic_cond_read_acquire(&lock->cnts, (VAL & _QW_WMASK) != _QW_LOCKED);
/*
* Signal the next one in queue to become queue head
@@ -109,8 +70,6 @@
*/
void queued_write_lock_slowpath(struct qrwlock *lock)
{
- u32 cnts;
-
/* Put the writer into the wait queue */
arch_spin_lock(&lock->wait_lock);
@@ -124,25 +83,18 @@
* or wait for a previous writer to go away.
*/
for (;;) {
- struct __qrwlock *l = (struct __qrwlock *)lock;
-
- if (!READ_ONCE(l->wmode) &&
- (cmpxchg_relaxed(&l->wmode, 0, _QW_WAITING) == 0))
+ if (!READ_ONCE(lock->wmode) &&
+ (cmpxchg_relaxed(&lock->wmode, 0, _QW_WAITING) == 0))
break;
cpu_relax_lowlatency();
}
/* When no more readers, set the locked flag */
- for (;;) {
- cnts = atomic_read(&lock->cnts);
- if ((cnts == _QW_WAITING) &&
- (atomic_cmpxchg_acquire(&lock->cnts, _QW_WAITING,
- _QW_LOCKED) == _QW_WAITING))
- break;
-
- cpu_relax_lowlatency();
- }
+ do {
+ atomic_cond_read_acquire(&lock->cnts, VAL == _QW_WAITING);
+ } while (atomic_cmpxchg_relaxed(&lock->cnts, _QW_WAITING,
+ _QW_LOCKED) != _QW_WAITING);
unlock:
arch_spin_unlock(&lock->wait_lock);
}
diff --git a/kernel/power/qos.c b/kernel/power/qos.c
index 0469d80..d6a0b0f 100644
--- a/kernel/power/qos.c
+++ b/kernel/power/qos.c
@@ -478,8 +478,6 @@
val = c->default_value;
for_each_cpu(cpu, mask) {
- if (cpu_isolated(cpu))
- continue;
switch (c->type) {
case PM_QOS_MIN:
diff --git a/kernel/sched/fair.c b/kernel/sched/fair.c
index 5ad731a..3e629bb 100644
--- a/kernel/sched/fair.c
+++ b/kernel/sched/fair.c
@@ -6929,6 +6929,7 @@
int target_cpu = -1;
int cpu, i;
unsigned int active_cpus_count = 0;
+ int isolated_candidate = -1;
*backup_cpu = -1;
@@ -6974,13 +6975,16 @@
unsigned long wake_util, new_util, min_capped_util;
cpumask_clear_cpu(i, &search_cpus);
+
+ if (!cpu_online(i) || cpu_isolated(i))
+ continue;
+
+ isolated_candidate = i;
+
if (avoid_prev_cpu && i == task_cpu(p))
continue;
- if (!cpu_online(i) || cpu_isolated(i) || is_reserved(i))
- continue;
-
- if (walt_cpu_high_irqload(i))
+ if (walt_cpu_high_irqload(i) || is_reserved(i))
continue;
trace_sched_cpu_util(i);
@@ -7266,6 +7270,12 @@
? best_active_cpu
: best_idle_cpu;
+ if (target_cpu == -1 && cpu_isolated(task_cpu(p)) &&
+ isolated_candidate != -1) {
+ target_cpu = isolated_candidate;
+ fbt_env->avoid_prev_cpu = true;
+ }
+
trace_sched_find_best_target(p, prefer_idle, min_util, cpu,
best_idle_cpu, best_active_cpu,
target_cpu);
diff --git a/kernel/seccomp.c b/kernel/seccomp.c
index af182a6..3975856 100644
--- a/kernel/seccomp.c
+++ b/kernel/seccomp.c
@@ -16,6 +16,8 @@
#include <linux/atomic.h>
#include <linux/audit.h>
#include <linux/compat.h>
+#include <linux/nospec.h>
+#include <linux/prctl.h>
#include <linux/sched.h>
#include <linux/seccomp.h>
#include <linux/slab.h>
@@ -214,8 +216,11 @@
return true;
}
+void __weak arch_seccomp_spec_mitigate(struct task_struct *task) { }
+
static inline void seccomp_assign_mode(struct task_struct *task,
- unsigned long seccomp_mode)
+ unsigned long seccomp_mode,
+ unsigned long flags)
{
assert_spin_locked(&task->sighand->siglock);
@@ -225,6 +230,9 @@
* filter) is set.
*/
smp_mb__before_atomic();
+ /* Assume default seccomp processes want spec flaw mitigation. */
+ if ((flags & SECCOMP_FILTER_FLAG_SPEC_ALLOW) == 0)
+ arch_seccomp_spec_mitigate(task);
set_tsk_thread_flag(task, TIF_SECCOMP);
}
@@ -292,7 +300,7 @@
* without dropping the locks.
*
*/
-static inline void seccomp_sync_threads(void)
+static inline void seccomp_sync_threads(unsigned long flags)
{
struct task_struct *thread, *caller;
@@ -333,7 +341,8 @@
* allow one thread to transition the other.
*/
if (thread->seccomp.mode == SECCOMP_MODE_DISABLED)
- seccomp_assign_mode(thread, SECCOMP_MODE_FILTER);
+ seccomp_assign_mode(thread, SECCOMP_MODE_FILTER,
+ flags);
}
}
@@ -452,7 +461,7 @@
/* Now that the new filter is in place, synchronize to all threads. */
if (flags & SECCOMP_FILTER_FLAG_TSYNC)
- seccomp_sync_threads();
+ seccomp_sync_threads(flags);
return 0;
}
@@ -712,7 +721,7 @@
#ifdef TIF_NOTSC
disable_TSC();
#endif
- seccomp_assign_mode(current, seccomp_mode);
+ seccomp_assign_mode(current, seccomp_mode, 0);
ret = 0;
out:
@@ -770,7 +779,7 @@
/* Do not free the successfully attached filter. */
prepared = NULL;
- seccomp_assign_mode(current, seccomp_mode);
+ seccomp_assign_mode(current, seccomp_mode, flags);
out:
spin_unlock_irq(¤t->sighand->siglock);
if (flags & SECCOMP_FILTER_FLAG_TSYNC)
diff --git a/kernel/signal.c b/kernel/signal.c
index 7ebe236..17428fe 100644
--- a/kernel/signal.c
+++ b/kernel/signal.c
@@ -2495,6 +2495,13 @@
{
struct task_struct *tsk = current;
+ /*
+ * In case the signal mask hasn't changed, there is nothing we need
+ * to do. The current->blocked shouldn't be modified by other task.
+ */
+ if (sigequalsets(&tsk->blocked, newset))
+ return;
+
spin_lock_irq(&tsk->sighand->siglock);
__set_task_blocked(tsk, newset);
spin_unlock_irq(&tsk->sighand->siglock);
diff --git a/kernel/sys.c b/kernel/sys.c
index 4ccf5f0..1b59b6e 100644
--- a/kernel/sys.c
+++ b/kernel/sys.c
@@ -55,6 +55,8 @@
#include <linux/uidgid.h>
#include <linux/cred.h>
+#include <linux/nospec.h>
+
#include <linux/kmsg_dump.h>
/* Move somewhere else to avoid recompiling? */
#include <generated/utsrelease.h>
@@ -2221,6 +2223,17 @@
}
#endif
+int __weak arch_prctl_spec_ctrl_get(struct task_struct *t, unsigned long which)
+{
+ return -EINVAL;
+}
+
+int __weak arch_prctl_spec_ctrl_set(struct task_struct *t, unsigned long which,
+ unsigned long ctrl)
+{
+ return -EINVAL;
+}
+
SYSCALL_DEFINE5(prctl, int, option, unsigned long, arg2, unsigned long, arg3,
unsigned long, arg4, unsigned long, arg5)
{
@@ -2440,6 +2453,16 @@
case PR_GET_FP_MODE:
error = GET_FP_MODE(me);
break;
+ case PR_GET_SPECULATION_CTRL:
+ if (arg3 || arg4 || arg5)
+ return -EINVAL;
+ error = arch_prctl_spec_ctrl_get(me, arg2);
+ break;
+ case PR_SET_SPECULATION_CTRL:
+ if (arg4 || arg5)
+ return -EINVAL;
+ error = arch_prctl_spec_ctrl_set(me, arg2, arg3);
+ break;
case PR_SET_VMA:
error = prctl_set_vma(arg2, arg3, arg4, arg5);
break;
diff --git a/kernel/sysctl.c b/kernel/sysctl.c
index f41c0e9..09a1611 100644
--- a/kernel/sysctl.c
+++ b/kernel/sysctl.c
@@ -398,22 +398,6 @@
.mode = 0644,
.proc_handler = proc_dointvec,
},
-#ifdef CONFIG_SCHED_WALT
- {
- .procname = "sched_use_walt_cpu_util",
- .data = &sysctl_sched_use_walt_cpu_util,
- .maxlen = sizeof(unsigned int),
- .mode = 0644,
- .proc_handler = proc_dointvec,
- },
- {
- .procname = "sched_use_walt_task_util",
- .data = &sysctl_sched_use_walt_task_util,
- .maxlen = sizeof(unsigned int),
- .mode = 0644,
- .proc_handler = proc_dointvec,
- },
-#endif
{
.procname = "sched_cstate_aware",
.data = &sysctl_sched_cstate_aware,
diff --git a/kernel/time/tick-broadcast.c b/kernel/time/tick-broadcast.c
index d2a20e8..22d7454 100644
--- a/kernel/time/tick-broadcast.c
+++ b/kernel/time/tick-broadcast.c
@@ -610,6 +610,14 @@
now = ktime_get();
/* Find all expired events */
for_each_cpu(cpu, tick_broadcast_oneshot_mask) {
+ /*
+ * Required for !SMP because for_each_cpu() reports
+ * unconditionally CPU0 as set on UP kernels.
+ */
+ if (!IS_ENABLED(CONFIG_SMP) &&
+ cpumask_empty(tick_broadcast_oneshot_mask))
+ break;
+
td = &per_cpu(tick_cpu_device, cpu);
if (td->evtdev->next_event.tv64 <= now.tv64) {
cpumask_set_cpu(cpu, tmpmask);
diff --git a/kernel/trace/ipc_logging_debug.c b/kernel/trace/ipc_logging_debug.c
index 7a4c630..3a13ef3 100644
--- a/kernel/trace/ipc_logging_debug.c
+++ b/kernel/trace/ipc_logging_debug.c
@@ -78,17 +78,16 @@
struct dentry *d = file->f_path.dentry;
char *buffer;
int bsize;
- int srcu_idx;
int r;
- r = debugfs_use_file_start(d, &srcu_idx);
+ r = debugfs_file_get(d);
if (!r) {
ilctxt = file->private_data;
r = kref_get_unless_zero(&ilctxt->refcount) ? 0 : -EIO;
- }
- debugfs_use_file_finish(srcu_idx);
- if (r)
+ } else {
return r;
+ }
+ debugfs_file_put(d);
buffer = kmalloc(count, GFP_KERNEL);
if (!buffer) {
@@ -119,18 +118,17 @@
struct ipc_log_context *ilctxt;
struct dentry *d = file->f_path.dentry;
int bsize = 1;
- int srcu_idx;
int r;
char local_buf[3];
- r = debugfs_use_file_start(d, &srcu_idx);
+ r = debugfs_file_get(d);
if (!r) {
ilctxt = file->private_data;
r = kref_get_unless_zero(&ilctxt->refcount) ? 0 : -EIO;
- }
- debugfs_use_file_finish(srcu_idx);
- if (r)
+ } else {
return r;
+ }
+ debugfs_file_put(d);
if (copy_from_user(local_buf, buff, bsize)) {
count = -EFAULT;
@@ -172,17 +170,16 @@
struct ipc_log_context *ilctxt;
struct dentry *d = file->f_path.dentry;
int bsize = 2;
- int srcu_idx;
int r;
- r = debugfs_use_file_start(d, &srcu_idx);
+ r = debugfs_file_get(d);
if (!r) {
ilctxt = file->private_data;
r = kref_get_unless_zero(&ilctxt->refcount) ? 0 : -EIO;
- }
- debugfs_use_file_finish(srcu_idx);
- if (r)
+ } else {
return r;
+ }
+ debugfs_file_put(d);
bsize = simple_read_from_buffer(buff, count, ppos,
ilctxt->disabled?"1\n":"0\n", bsize);
diff --git a/lib/Kconfig.debug b/lib/Kconfig.debug
index 37641d1..640818c 100644
--- a/lib/Kconfig.debug
+++ b/lib/Kconfig.debug
@@ -269,7 +269,6 @@
config DEBUG_FS
bool "Debug Filesystem"
- select SRCU
help
debugfs is a virtual file system that kernel developers use to put
debugging files into. Enable this option to be able to read and
diff --git a/mm/Kconfig b/mm/Kconfig
index 3363a70..051f7bc 100644
--- a/mm/Kconfig
+++ b/mm/Kconfig
@@ -675,6 +675,7 @@
depends on ARCH_SUPPORTS_DEFERRED_STRUCT_PAGE_INIT
depends on NO_BOOTMEM && MEMORY_HOTPLUG
depends on !FLATMEM
+ depends on !NEED_PER_CPU_KM
help
Ordinarily all struct pages are initialised during early boot in a
single thread. On very large machines this can take a considerable
diff --git a/net/bluetooth/hidp/core.c b/net/bluetooth/hidp/core.c
index 1fc0764..1811f8e 100644
--- a/net/bluetooth/hidp/core.c
+++ b/net/bluetooth/hidp/core.c
@@ -431,8 +431,8 @@
del_timer(&session->timer);
}
-static void hidp_process_report(struct hidp_session *session,
- int type, const u8 *data, int len, int intr)
+static void hidp_process_report(struct hidp_session *session, int type,
+ const u8 *data, unsigned int len, int intr)
{
if (len > HID_MAX_BUFFER_SIZE)
len = HID_MAX_BUFFER_SIZE;
diff --git a/net/core/sock.c b/net/core/sock.c
index 1d88335..0e82197 100644
--- a/net/core/sock.c
+++ b/net/core/sock.c
@@ -1465,7 +1465,7 @@
static void __sk_free(struct sock *sk)
{
- if (unlikely(sock_diag_has_destroy_listeners(sk) && sk->sk_net_refcnt))
+ if (unlikely(sk->sk_net_refcnt && sock_diag_has_destroy_listeners(sk)))
sock_diag_broadcast_destroy(sk);
else
sk_destruct(sk);
diff --git a/net/ipc_router/Kconfig b/net/ipc_router/Kconfig
index 30cd45a..9121667 100644
--- a/net/ipc_router/Kconfig
+++ b/net/ipc_router/Kconfig
@@ -23,3 +23,13 @@
once configured with the security rules will ensure that the
sender of the message to a service belongs to the relevant
Linux group as configured by the security script.
+
+config IPC_ROUTER_NODE_ID
+ depends on IPC_ROUTER
+ int "IPC router local NODE ID"
+ default 1
+ help
+ This option allows to configure the IPC Router NODE ID dynamically.
+ The NODE defined here is used as the local NODE ID by IPC Router
+ core and publish the same NODE ID to other NODES present in the
+ network.
diff --git a/net/ipc_router/ipc_router_core.c b/net/ipc_router/ipc_router_core.c
index 3403108..1a6b539 100644
--- a/net/ipc_router/ipc_router_core.c
+++ b/net/ipc_router/ipc_router_core.c
@@ -137,6 +137,7 @@
struct msm_ipc_router_xprt *xprt;
u32 remote_node_id;
u32 initialized;
+ u32 hello_sent;
struct list_head pkt_list;
struct wakeup_source ws;
struct mutex rx_lock_lhb2; /* lock for xprt rx operations */
@@ -2494,12 +2495,36 @@
}
}
+static int send_hello_msg(struct msm_ipc_router_xprt_info *xprt_info)
+{
+ int rc = 0;
+ union rr_control_msg ctl;
+
+ if (!xprt_info->hello_sent) {
+ xprt_info->hello_sent = 1;
+ /* Send a HELLO message */
+ memset(&ctl, 0, sizeof(ctl));
+ ctl.hello.cmd = IPC_ROUTER_CTRL_CMD_HELLO;
+ ctl.hello.checksum = IPC_ROUTER_HELLO_MAGIC;
+ ctl.hello.versions = (uint32_t)IPC_ROUTER_VER_BITMASK;
+ ctl.hello.checksum = ipc_router_calc_checksum(&ctl);
+ rc = ipc_router_send_ctl_msg(xprt_info, &ctl,
+ IPC_ROUTER_DUMMY_DEST_NODE);
+ if (rc < 0) {
+ xprt_info->hello_sent = 0;
+ IPC_RTR_ERR("%s: Error sending HELLO message\n",
+ __func__);
+ return rc;
+ }
+ }
+ return rc;
+}
+
static int process_hello_msg(struct msm_ipc_router_xprt_info *xprt_info,
union rr_control_msg *msg,
struct rr_header_v1 *hdr)
{
int i, rc = 0;
- union rr_control_msg ctl;
struct msm_ipc_routing_table_entry *rt_entry;
if (!hdr)
@@ -2514,19 +2539,10 @@
kref_put(&rt_entry->ref, ipc_router_release_rtentry);
do_version_negotiation(xprt_info, msg);
- /* Send a reply HELLO message */
- memset(&ctl, 0, sizeof(ctl));
- ctl.hello.cmd = IPC_ROUTER_CTRL_CMD_HELLO;
- ctl.hello.checksum = IPC_ROUTER_HELLO_MAGIC;
- ctl.hello.versions = (u32)IPC_ROUTER_VER_BITMASK;
- ctl.hello.checksum = ipc_router_calc_checksum(&ctl);
- rc = ipc_router_send_ctl_msg(xprt_info, &ctl,
- IPC_ROUTER_DUMMY_DEST_NODE);
- if (rc < 0) {
- IPC_RTR_ERR("%s: Error sending reply HELLO message\n",
- __func__);
+ rc = send_hello_msg(xprt_info);
+ if (rc < 0)
return rc;
- }
+
xprt_info->initialized = 1;
/* Send list of servers from the local node and from nodes
@@ -4068,6 +4084,7 @@
xprt_info->xprt = xprt;
xprt_info->initialized = 0;
+ xprt_info->hello_sent = 0;
xprt_info->remote_node_id = -1;
INIT_LIST_HEAD(&xprt_info->pkt_list);
mutex_init(&xprt_info->rx_lock_lhb2);
@@ -4109,6 +4126,7 @@
up_write(&routing_table_lock_lha3);
xprt->priv = xprt_info;
+ send_hello_msg(xprt_info);
return 0;
}
diff --git a/net/ipc_router/ipc_router_private.h b/net/ipc_router/ipc_router_private.h
index 3ec9818..6e0c4be 100644
--- a/net/ipc_router/ipc_router_private.h
+++ b/net/ipc_router/ipc_router_private.h
@@ -1,4 +1,4 @@
-/* Copyright (c) 2011-2016, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2011-2016, 2018, The Linux Foundation. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 and
@@ -37,7 +37,7 @@
#define IPC_ROUTER_ADDRESS 0x0000FFFF
-#define IPC_ROUTER_NID_LOCAL 1
+#define IPC_ROUTER_NID_LOCAL CONFIG_IPC_ROUTER_NODE_ID
#define MAX_IPC_PKT_SIZE 66000
#define IPC_ROUTER_LOW_RX_QUOTA 5
diff --git a/net/ipv4/ip_output.c b/net/ipv4/ip_output.c
index e60f9fa..d0bd98f 100644
--- a/net/ipv4/ip_output.c
+++ b/net/ipv4/ip_output.c
@@ -1098,7 +1098,8 @@
if (copy > length)
copy = length;
- if (!(rt->dst.dev->features&NETIF_F_SG)) {
+ if (!(rt->dst.dev->features&NETIF_F_SG) &&
+ skb_tailroom(skb) >= copy) {
unsigned int off;
off = skb->len;
diff --git a/net/ipv4/tcp_output.c b/net/ipv4/tcp_output.c
index 16a473a..70c7212 100644
--- a/net/ipv4/tcp_output.c
+++ b/net/ipv4/tcp_output.c
@@ -2691,8 +2691,10 @@
return -EBUSY;
if (before(TCP_SKB_CB(skb)->seq, tp->snd_una)) {
- if (before(TCP_SKB_CB(skb)->end_seq, tp->snd_una))
- BUG();
+ if (unlikely(before(TCP_SKB_CB(skb)->end_seq, tp->snd_una))) {
+ WARN_ON_ONCE(1);
+ return -EINVAL;
+ }
if (tcp_trim_head(sk, skb, tp->snd_una - TCP_SKB_CB(skb)->seq))
return -ENOMEM;
}
@@ -3236,6 +3238,7 @@
sock_reset_flag(sk, SOCK_DONE);
tp->snd_wnd = 0;
tcp_init_wl(tp, 0);
+ tcp_write_queue_purge(sk);
tp->snd_una = tp->write_seq;
tp->snd_sml = tp->write_seq;
tp->snd_up = tp->write_seq;
diff --git a/net/ipv6/ip6_output.c b/net/ipv6/ip6_output.c
index de0188e..0b5a75b 100644
--- a/net/ipv6/ip6_output.c
+++ b/net/ipv6/ip6_output.c
@@ -1553,7 +1553,8 @@
if (copy > length)
copy = length;
- if (!(rt->dst.dev->features&NETIF_F_SG)) {
+ if (!(rt->dst.dev->features&NETIF_F_SG) &&
+ skb_tailroom(skb) >= copy) {
unsigned int off;
off = skb->len;
diff --git a/net/netfilter/nf_tables_api.c b/net/netfilter/nf_tables_api.c
index fa3ef25..762f31f 100644
--- a/net/netfilter/nf_tables_api.c
+++ b/net/netfilter/nf_tables_api.c
@@ -2200,41 +2200,46 @@
}
if (nlh->nlmsg_flags & NLM_F_REPLACE) {
- if (nft_is_active_next(net, old_rule)) {
- trans = nft_trans_rule_add(&ctx, NFT_MSG_DELRULE,
- old_rule);
- if (trans == NULL) {
- err = -ENOMEM;
- goto err2;
- }
- nft_deactivate_next(net, old_rule);
- chain->use--;
- list_add_tail_rcu(&rule->list, &old_rule->list);
- } else {
+ if (!nft_is_active_next(net, old_rule)) {
err = -ENOENT;
goto err2;
}
- } else if (nlh->nlmsg_flags & NLM_F_APPEND)
- if (old_rule)
- list_add_rcu(&rule->list, &old_rule->list);
- else
- list_add_tail_rcu(&rule->list, &chain->rules);
- else {
- if (old_rule)
- list_add_tail_rcu(&rule->list, &old_rule->list);
- else
- list_add_rcu(&rule->list, &chain->rules);
- }
+ trans = nft_trans_rule_add(&ctx, NFT_MSG_DELRULE,
+ old_rule);
+ if (trans == NULL) {
+ err = -ENOMEM;
+ goto err2;
+ }
+ nft_deactivate_next(net, old_rule);
+ chain->use--;
- if (nft_trans_rule_add(&ctx, NFT_MSG_NEWRULE, rule) == NULL) {
- err = -ENOMEM;
- goto err3;
+ if (nft_trans_rule_add(&ctx, NFT_MSG_NEWRULE, rule) == NULL) {
+ err = -ENOMEM;
+ goto err2;
+ }
+
+ list_add_tail_rcu(&rule->list, &old_rule->list);
+ } else {
+ if (nft_trans_rule_add(&ctx, NFT_MSG_NEWRULE, rule) == NULL) {
+ err = -ENOMEM;
+ goto err2;
+ }
+
+ if (nlh->nlmsg_flags & NLM_F_APPEND) {
+ if (old_rule)
+ list_add_rcu(&rule->list, &old_rule->list);
+ else
+ list_add_tail_rcu(&rule->list, &chain->rules);
+ } else {
+ if (old_rule)
+ list_add_tail_rcu(&rule->list, &old_rule->list);
+ else
+ list_add_rcu(&rule->list, &chain->rules);
+ }
}
chain->use++;
return 0;
-err3:
- list_del_rcu(&rule->list);
err2:
nf_tables_rule_destroy(&ctx, rule);
err1:
diff --git a/net/packet/af_packet.c b/net/packet/af_packet.c
index 8f78d14..430a7c7 100644
--- a/net/packet/af_packet.c
+++ b/net/packet/af_packet.c
@@ -2910,13 +2910,15 @@
if (skb == NULL)
goto out_unlock;
- skb_set_network_header(skb, reserve);
+ skb_reset_network_header(skb);
err = -EINVAL;
if (sock->type == SOCK_DGRAM) {
offset = dev_hard_header(skb, dev, ntohs(proto), addr, NULL, len);
if (unlikely(offset < 0))
goto out_free;
+ } else if (reserve) {
+ skb_push(skb, reserve);
}
/* Returns -EFAULT on error */
diff --git a/net/wireless/core.c b/net/wireless/core.c
index 3181b07..c88874f 100644
--- a/net/wireless/core.c
+++ b/net/wireless/core.c
@@ -95,6 +95,9 @@
ASSERT_RTNL();
+ if (strlen(newname) > NL80211_WIPHY_NAME_MAXLEN)
+ return -EINVAL;
+
/* prohibit calling the thing phy%d when %d is not its number */
sscanf(newname, PHY_NAME "%d%n", &wiphy_idx, &taken);
if (taken == strlen(newname) && wiphy_idx != rdev->wiphy_idx) {
diff --git a/net/wireless/db.txt b/net/wireless/db.txt
index 30cc249..f900f5c 100644
--- a/net/wireless/db.txt
+++ b/net/wireless/db.txt
@@ -37,10 +37,10 @@
country AL: DFS-ETSI
(2402 - 2482 @ 40), (20)
- (5150 - 5250 @ 80), (23), AUTO-BW
- (5250 - 5350 @ 80), (23), DFS, AUTO-BW
- (5470 - 5710 @ 160), (30), DFS
- (5725 - 5875 @ 80), (14)
+ (5170 - 5250 @ 80), (23), AUTO-BW
+ (5250 - 5330 @ 80), (23), DFS, AUTO-BW
+ (5490 - 5730 @ 160), (30), DFS
+ (5735 - 5875 @ 80), (14)
country AM: DFS-ETSI
(2402 - 2482 @ 40), (20)
@@ -51,8 +51,8 @@
(2402 - 2482 @ 40), (20)
(5170 - 5250 @ 80), (23), AUTO-BW
(5250 - 5330 @ 80), (23), DFS, AUTO-BW
- (5490 - 5710 @ 160), (30), DFS
- (5725 - 5875 @ 80), (14)
+ (5490 - 5730 @ 160), (30), DFS
+ (5735 - 5875 @ 80), (14)
country AR:
(2402 - 2482 @ 40), (36)
@@ -75,8 +75,8 @@
(2402 - 2482 @ 40), (20)
(5170 - 5250 @ 80), (23), AUTO-BW
(5250 - 5330 @ 80), (23), DFS, AUTO-BW
- (5490 - 5710 @ 160), (30), DFS
- (5725 - 5875 @ 80), (14)
+ (5490 - 5730 @ 160), (30), DFS
+ (5735 - 5875 @ 80), (14)
# 60 gHz band channels 1-4, ref: Etsi En 302 567
(57000 - 66000 @ 2160), (40)
@@ -105,8 +105,8 @@
(2402 - 2482 @ 40), (20)
(5170 - 5250 @ 80), (23), AUTO-BW
(5250 - 5330 @ 80), (23), DFS, AUTO-BW
- (5490 - 5710 @ 160), (30), DFS
- (5725 - 5875 @ 80), (14)
+ (5490 - 5730 @ 160), (30), DFS
+ (5735 - 5875 @ 80), (14)
country BB: DFS-FCC
(2402 - 2482 @ 40), (20)
@@ -122,8 +122,8 @@
(2402 - 2482 @ 40), (20)
(5170 - 5250 @ 80), (23), AUTO-BW
(5250 - 5330 @ 80), (23), DFS, AUTO-BW
- (5490 - 5710 @ 160), (30), DFS
- (5725 - 5875 @ 80), (14)
+ (5490 - 5730 @ 160), (30), DFS
+ (5735 - 5875 @ 80), (14)
# 60 gHz band channels 1-4, ref: Etsi En 302 567
(57000 - 66000 @ 2160), (40)
@@ -138,8 +138,8 @@
(2402 - 2482 @ 40), (20)
(5170 - 5250 @ 80), (23), AUTO-BW
(5250 - 5330 @ 80), (23), DFS, AUTO-BW
- (5490 - 5710 @ 160), (30), DFS
- (5725 - 5875 @ 80), (14)
+ (5490 - 5730 @ 160), (30), DFS
+ (5735 - 5875 @ 80), (14)
# 60 gHz band channels 1-4, ref: Etsi En 302 567
(57000 - 66000 @ 2160), (40)
@@ -228,8 +228,8 @@
(2402 - 2482 @ 40), (20)
(5170 - 5250 @ 80), (23), AUTO-BW
(5250 - 5330 @ 80), (23), DFS, AUTO-BW
- (5490 - 5710 @ 160), (30), DFS
- (5725 - 5875 @ 80), (14)
+ (5490 - 5730 @ 160), (30), DFS
+ (5735 - 5875 @ 80), (14)
# 60 gHz band channels 1-4, ref: Etsi En 302 567
(57000 - 66000 @ 2160), (40)
@@ -282,8 +282,8 @@
(2402 - 2482 @ 40), (20)
(5170 - 5250 @ 80), (23), AUTO-BW
(5250 - 5330 @ 80), (23), DFS, AUTO-BW
- (5490 - 5710 @ 160), (30), DFS
- (5725 - 5875 @ 80), (14)
+ (5490 - 5730 @ 160), (30), DFS
+ (5735 - 5875 @ 80), (14)
# 60 gHz band channels 1-4, ref: Etsi En 302 567
(57000 - 66000 @ 2160), (40)
@@ -293,8 +293,8 @@
(2402 - 2482 @ 40), (20)
(5170 - 5250 @ 80), (23), AUTO-BW
(5250 - 5330 @ 80), (23), DFS, AUTO-BW
- (5490 - 5710 @ 160), (30), DFS
- (5725 - 5875 @ 80), (14)
+ (5490 - 5730 @ 160), (30), DFS
+ (5735 - 5875 @ 80), (14)
# 60 gHz band channels 1-4, ref: Etsi En 302 567
(57000 - 66000 @ 2160), (40)
@@ -308,8 +308,8 @@
(2402 - 2482 @ 40), (20)
(5170 - 5250 @ 80), (23), AUTO-BW
(5250 - 5330 @ 80), (23), DFS, AUTO-BW
- (5490 - 5710 @ 160), (30), DFS
- (5725 - 5875 @ 80), (14)
+ (5490 - 5730 @ 160), (30), DFS
+ (5735 - 5875 @ 80), (14)
# 60 gHz band channels 1-4, ref: Etsi En 302 567
(57000 - 66000 @ 2160), (40)
@@ -317,8 +317,8 @@
(2402 - 2482 @ 40), (20)
(5170 - 5250 @ 80), (23), AUTO-BW
(5250 - 5330 @ 80), (23), DFS, AUTO-BW
- (5490 - 5710 @ 160), (30), DFS
- (5725 - 5875 @ 80), (14)
+ (5490 - 5730 @ 160), (30), DFS
+ (5735 - 5875 @ 80), (14)
# 60 gHz band channels 1-4, ref: Etsi En 302 567
(57000 - 66000 @ 2160), (40)
@@ -353,8 +353,8 @@
(2402 - 2482 @ 40), (20)
(5170 - 5250 @ 80), (23), AUTO-BW
(5250 - 5330 @ 80), (23), DFS, AUTO-BW
- (5490 - 5710 @ 160), (30), DFS
- (5725 - 5875 @ 80), (14)
+ (5490 - 5730 @ 160), (30), DFS
+ (5735 - 5875 @ 80), (14)
# 60 gHz band channels 1-4, ref: Etsi En 302 567
(57000 - 66000 @ 2160), (40)
@@ -367,8 +367,8 @@
(2402 - 2482 @ 40), (20)
(5170 - 5250 @ 80), (23), AUTO-BW
(5250 - 5330 @ 80), (23), DFS, AUTO-BW
- (5490 - 5710 @ 160), (30), DFS
- (5725 - 5875 @ 80), (14)
+ (5490 - 5730 @ 160), (30), DFS
+ (5735 - 5875 @ 80), (14)
# 60 gHz band channels 1-4, ref: Etsi En 302 567
(57000 - 66000 @ 2160), (40)
@@ -382,8 +382,8 @@
(2402 - 2482 @ 40), (20)
(5170 - 5250 @ 80), (23), AUTO-BW
(5250 - 5330 @ 80), (23), DFS, AUTO-BW
- (5490 - 5710 @ 160), (30), DFS
- (5725 - 5875 @ 80), (14)
+ (5490 - 5730 @ 160), (30), DFS
+ (5735 - 5875 @ 80), (14)
# 60 gHz band channels 1-4, ref: Etsi En 302 567
(57000 - 66000 @ 2160), (40)
@@ -398,8 +398,8 @@
(2402 - 2482 @ 40), (20)
(5170 - 5250 @ 80), (23), AUTO-BW
(5250 - 5330 @ 80), (23), DFS, AUTO-BW
- (5490 - 5710 @ 160), (30), DFS
- (5725 - 5875 @ 80), (14)
+ (5490 - 5730 @ 160), (30), DFS
+ (5735 - 5875 @ 80), (14)
# 60 gHz band channels 1-4, ref: Etsi En 302 567
(57000 - 66000 @ 2160), (40)
@@ -407,8 +407,8 @@
(2402 - 2482 @ 40), (20)
(5170 - 5250 @ 80), (23), AUTO-BW
(5250 - 5330 @ 80), (23), DFS, AUTO-BW
- (5490 - 5710 @ 160), (30), DFS
- (5725 - 5875 @ 80), (14)
+ (5490 - 5730 @ 160), (30), DFS
+ (5735 - 5875 @ 80), (14)
# 60 gHz band channels 1-4, ref: Etsi En 302 567
(57000 - 66000 @ 2160), (40)
@@ -428,8 +428,8 @@
(2402 - 2482 @ 40), (20)
(5170 - 5250 @ 80), (23), AUTO-BW
(5250 - 5330 @ 80), (23), DFS, AUTO-BW
- (5490 - 5710 @ 160), (30), DFS
- (5725 - 5875 @ 80), (14)
+ (5490 - 5730 @ 160), (30), DFS
+ (5735 - 5875 @ 80), (14)
country GH: DFS-FCC
(2402 - 2482 @ 40), (20)
@@ -460,8 +460,8 @@
(2402 - 2482 @ 40), (20)
(5170 - 5250 @ 80), (23), AUTO-BW
(5250 - 5330 @ 80), (23), DFS, AUTO-BW
- (5490 - 5710 @ 160), (30), DFS
- (5725 - 5875 @ 80), (14)
+ (5490 - 5730 @ 160), (30), DFS
+ (5735 - 5875 @ 80), (14)
# 60 gHz band channels 1-4, ref: Etsi En 302 567
(57000 - 66000 @ 2160), (40)
@@ -505,8 +505,8 @@
(2402 - 2482 @ 40), (20)
(5170 - 5250 @ 80), (23), AUTO-BW
(5250 - 5330 @ 80), (23), DFS, AUTO-BW
- (5490 - 5710 @ 160), (30), DFS
- (5725 - 5875 @ 80), (14)
+ (5490 - 5730 @ 160), (30), DFS
+ (5735 - 5875 @ 80), (14)
# 60 gHz band channels 1-4, ref: Etsi En 302 567
(57000 - 66000 @ 2160), (40)
@@ -521,8 +521,8 @@
(2402 - 2482 @ 40), (20)
(5170 - 5250 @ 80), (23), AUTO-BW
(5250 - 5330 @ 80), (23), DFS, AUTO-BW
- (5490 - 5710 @ 160), (30), DFS
- (5725 - 5875 @ 80), (14)
+ (5490 - 5730 @ 160), (30), DFS
+ (5735 - 5875 @ 80), (14)
# 60 gHz band channels 1-4, ref: Etsi En 302 567
(57000 - 66000 @ 2160), (40)
@@ -535,8 +535,8 @@
(2402 - 2482 @ 40), (20)
(5170 - 5250 @ 80), (23), AUTO-BW
(5250 - 5330 @ 80), (23), DFS, AUTO-BW
- (5490 - 5710 @ 160), (30), DFS
- (5725 - 5875 @ 80), (14)
+ (5490 - 5730 @ 160), (30), DFS
+ (5735 - 5875 @ 80), (14)
# 60 gHz band channels 1-4, ref: Etsi En 302 567
(57000 - 66000 @ 2160), (40)
@@ -562,8 +562,8 @@
(2402 - 2482 @ 40), (20)
(5170 - 5250 @ 80), (23), AUTO-BW
(5250 - 5330 @ 80), (23), DFS, AUTO-BW
- (5490 - 5710 @ 160), (30), DFS
- (5725 - 5875 @ 80), (14)
+ (5490 - 5730 @ 160), (30), DFS
+ (5735 - 5875 @ 80), (14)
# 60 gHz band channels 1-4, ref: Etsi En 302 567
(57000 - 66000 @ 2160), (40)
@@ -571,8 +571,8 @@
(2402 - 2482 @ 40), (20)
(5170 - 5250 @ 80), (23), AUTO-BW
(5250 - 5330 @ 80), (23), DFS, AUTO-BW
- (5490 - 5710 @ 160), (30), DFS
- (5725 - 5875 @ 80), (14)
+ (5490 - 5730 @ 160), (30), DFS
+ (5735 - 5875 @ 80), (14)
# 60 gHz band channels 1-4, ref: Etsi En 302 567
(57000 - 66000 @ 2160), (40)
@@ -662,8 +662,8 @@
(2402 - 2482 @ 40), (20)
(5170 - 5250 @ 80), (23), AUTO-BW
(5250 - 5330 @ 80), (23), DFS, AUTO-BW
- (5490 - 5710 @ 160), (30), DFS
- (5725 - 5875 @ 80), (14)
+ (5490 - 5730 @ 160), (30), DFS
+ (5735 - 5875 @ 80), (14)
# 60 gHz band channels 1-4, ref: Etsi En 302 567
(57000 - 66000 @ 2160), (40)
@@ -684,8 +684,8 @@
(2402 - 2482 @ 40), (20)
(5170 - 5250 @ 80), (23), AUTO-BW
(5250 - 5330 @ 80), (23), DFS, AUTO-BW
- (5490 - 5710 @ 160), (30), DFS
- (5725 - 5875 @ 80), (14)
+ (5490 - 5730 @ 160), (30), DFS
+ (5735 - 5875 @ 80), (14)
# 60 gHz band channels 1-4, ref: Etsi En 302 567
(57000 - 66000 @ 2160), (40)
@@ -693,8 +693,8 @@
(2402 - 2482 @ 40), (20)
(5170 - 5250 @ 80), (23), AUTO-BW
(5250 - 5330 @ 80), (23), DFS, AUTO-BW
- (5490 - 5710 @ 160), (30), DFS
- (5725 - 5875 @ 80), (14)
+ (5490 - 5730 @ 160), (30), DFS
+ (5735 - 5875 @ 80), (14)
# 60 gHz band channels 1-4, ref: Etsi En 302 567
(57000 - 66000 @ 2160), (40)
@@ -702,8 +702,8 @@
(2402 - 2482 @ 40), (20)
(5170 - 5250 @ 80), (23), AUTO-BW
(5250 - 5330 @ 80), (23), DFS, AUTO-BW
- (5490 - 5710 @ 160), (30), DFS
- (5725 - 5875 @ 80), (14)
+ (5490 - 5730 @ 160), (30), DFS
+ (5735 - 5875 @ 80), (14)
# 60 gHz band channels 1-4, ref: Etsi En 302 567
(57000 - 66000 @ 2160), (40)
@@ -718,22 +718,22 @@
(2402 - 2482 @ 40), (20)
(5170 - 5250 @ 80), (23), AUTO-BW
(5250 - 5330 @ 80), (23), DFS, AUTO-BW
- (5490 - 5710 @ 160), (30), DFS
- (5725 - 5875 @ 80), (14)
+ (5490 - 5730 @ 160), (30), DFS
+ (5735 - 5875 @ 80), (14)
country MD: DFS-ETSI
(2402 - 2482 @ 40), (20)
(5170 - 5250 @ 80), (23), AUTO-BW
(5250 - 5330 @ 80), (23), DFS, AUTO-BW
- (5490 - 5710 @ 160), (30), DFS
- (5725 - 5875 @ 80), (14)
+ (5490 - 5730 @ 160), (30), DFS
+ (5735 - 5875 @ 80), (14)
country ME: DFS-ETSI
(2402 - 2482 @ 40), (20)
(5170 - 5250 @ 80), (23), AUTO-BW
(5250 - 5330 @ 80), (23), DFS, AUTO-BW
- (5490 - 5710 @ 160), (30), DFS
- (5725 - 5875 @ 80), (14)
+ (5490 - 5730 @ 160), (30), DFS
+ (5735 - 5875 @ 80), (14)
country MF: DFS-ETSI
(2402 - 2482 @ 40), (20)
@@ -752,8 +752,8 @@
(2402 - 2482 @ 40), (20)
(5170 - 5250 @ 80), (23), AUTO-BW
(5250 - 5330 @ 80), (23), DFS, AUTO-BW
- (5490 - 5710 @ 160), (30), DFS
- (5725 - 5875 @ 80), (14)
+ (5490 - 5730 @ 160), (30), DFS
+ (5735 - 5875 @ 80), (14)
country MN: DFS-FCC
(2402 - 2482 @ 40), (20)
@@ -780,8 +780,8 @@
(2402 - 2482 @ 40), (20)
(5170 - 5250 @ 80), (23), AUTO-BW
(5250 - 5330 @ 80), (23), DFS, AUTO-BW
- (5490 - 5710 @ 160), (30), DFS
- (5725 - 5875 @ 80), (14)
+ (5490 - 5730 @ 160), (30), DFS
+ (5735 - 5875 @ 80), (14)
country MR: DFS-ETSI
(2402 - 2482 @ 40), (20)
@@ -793,17 +793,17 @@
(2402 - 2482 @ 40), (20)
(5170 - 5250 @ 80), (23), AUTO-BW
(5250 - 5330 @ 80), (23), DFS, AUTO-BW
- (5490 - 5710 @ 160), (30), DFS
- (5725 - 5875 @ 80), (14)
+ (5490 - 5730 @ 160), (30), DFS
+ (5735 - 5875 @ 80), (14)
# 60 gHz band channels 1-4, ref: Etsi En 302 567
(57000 - 66000 @ 2160), (40)
-country MU: DFS-FCC
+country MU: DFS-ETSI
(2402 - 2482 @ 40), (20)
- (5170 - 5250 @ 80), (24), AUTO-BW
- (5250 - 5330 @ 80), (24), DFS, AUTO-BW
- (5490 - 5730 @ 160), (24), DFS
- (5735 - 5835 @ 80), (30)
+ (5170 - 5250 @ 80), (23), AUTO-BW
+ (5250 - 5330 @ 80), (23), DFS, AUTO-BW
+ (5490 - 5730 @ 160), (30), DFS
+ (5735 - 5875 @ 80), (14)
country MV: DFS-ETSI
(2402 - 2482 @ 40), (20)
@@ -860,8 +860,8 @@
(2402 - 2482 @ 40), (20)
(5170 - 5250 @ 80), (23), AUTO-BW
(5250 - 5330 @ 80), (23), DFS, AUTO-BW
- (5490 - 5710 @ 160), (30), DFS
- (5725 - 5875 @ 80), (14)
+ (5490 - 5730 @ 160), (30), DFS
+ (5735 - 5875 @ 80), (14)
# 60 gHz band channels 1-4, ref: Etsi En 302 567
(57000 - 66000 @ 2160), (40)
@@ -869,8 +869,8 @@
(2402 - 2482 @ 40), (20)
(5170 - 5250 @ 80), (23), AUTO-BW
(5250 - 5330 @ 80), (23), DFS, AUTO-BW
- (5490 - 5710 @ 160), (30), DFS
- (5725 - 5875 @ 80), (14)
+ (5490 - 5730 @ 160), (30), DFS
+ (5735 - 5875 @ 80), (14)
# 60 gHz band channels 1-4, ref: Etsi En 302 567
(57000 - 66000 @ 2160), (40)
@@ -911,8 +911,8 @@
(2402 - 2482 @ 40), (20)
(5170 - 5250 @ 80), (23), AUTO-BW
(5250 - 5330 @ 80), (23), DFS, AUTO-BW
- (5490 - 5710 @ 160), (30), DFS
- (5725 - 5875 @ 80), (14)
+ (5490 - 5730 @ 160), (30), DFS
+ (5735 - 5875 @ 80), (14)
country PG: DFS-FCC
(2402 - 2482 @ 40), (20)
@@ -938,8 +938,8 @@
(2402 - 2482 @ 40), (20)
(5170 - 5250 @ 80), (23), AUTO-BW
(5250 - 5330 @ 80), (23), DFS, AUTO-BW
- (5490 - 5710 @ 160), (30), DFS
- (5725 - 5875 @ 80), (14)
+ (5490 - 5730 @ 160), (30), DFS
+ (5735 - 5875 @ 80), (14)
# 60 gHz band channels 1-4, ref: Etsi En 302 567
(57000 - 66000 @ 2160), (40)
@@ -947,8 +947,8 @@
(2402 - 2482 @ 40), (20)
(5170 - 5250 @ 80), (23), AUTO-BW
(5250 - 5330 @ 80), (23), DFS, AUTO-BW
- (5490 - 5710 @ 160), (30), DFS
- (5725 - 5875 @ 80), (14)
+ (5490 - 5730 @ 160), (30), DFS
+ (5735 - 5875 @ 80), (14)
country PR: DFS-FCC
(2402 - 2472 @ 40), (30)
@@ -968,8 +968,8 @@
(2402 - 2482 @ 40), (20)
(5170 - 5250 @ 80), (23), AUTO-BW
(5250 - 5330 @ 80), (23), DFS, AUTO-BW
- (5490 - 5710 @ 160), (30), DFS
- (5725 - 5875 @ 80), (14)
+ (5490 - 5730 @ 160), (30), DFS
+ (5735 - 5875 @ 80), (14)
# 60 gHz band channels 1-4, ref: Etsi En 302 567
(57000 - 66000 @ 2160), (40)
@@ -1006,8 +1006,8 @@
(2402 - 2482 @ 40), (20)
(5170 - 5250 @ 80), (23), AUTO-BW
(5250 - 5330 @ 80), (23), DFS, AUTO-BW
- (5490 - 5710 @ 160), (30), DFS
- (5725 - 5875 @ 80), (14)
+ (5490 - 5730 @ 160), (30), DFS
+ (5735 - 5875 @ 80), (14)
# 60 gHz band channels 1-4, ref: Etsi En 302 567
(57000 - 66000 @ 2160), (40)
@@ -1017,8 +1017,8 @@
(2402 - 2482 @ 40), (20)
(5170 - 5250 @ 80), (23), AUTO-BW
(5250 - 5330 @ 80), (23), DFS, AUTO-BW
- (5490 - 5710 @ 160), (30), DFS
- (5725 - 5875 @ 80), (14)
+ (5490 - 5730 @ 160), (30), DFS
+ (5735 - 5875 @ 80), (14)
# 60 gHz band channels 1-4, ref: Etsi En 302 567
(57000 - 66000 @ 2160), (40)
@@ -1047,8 +1047,8 @@
(2402 - 2482 @ 40), (20)
(5170 - 5250 @ 80), (23), AUTO-BW
(5250 - 5330 @ 80), (23), DFS, AUTO-BW
- (5490 - 5710 @ 160), (30), DFS
- (5725 - 5875 @ 80), (14)
+ (5490 - 5730 @ 160), (30), DFS
+ (5735 - 5875 @ 80), (14)
# 60 gHz band channels 1-4, ref: Etsi En 302 567
(57000 - 66000 @ 2160), (40)
@@ -1065,8 +1065,8 @@
(2402 - 2482 @ 40), (20)
(5170 - 5250 @ 80), (23), AUTO-BW
(5250 - 5330 @ 80), (23), DFS, AUTO-BW
- (5490 - 5710 @ 160), (30), DFS
- (5725 - 5875 @ 80), (14)
+ (5490 - 5730 @ 160), (30), DFS
+ (5735 - 5875 @ 80), (14)
# 60 gHz band channels 1-4, ref: Etsi En 302 567
(57000 - 66000 @ 2160), (40)
@@ -1074,8 +1074,8 @@
(2402 - 2482 @ 40), (20)
(5170 - 5250 @ 80), (23), AUTO-BW
(5250 - 5330 @ 80), (23), DFS, AUTO-BW
- (5490 - 5710 @ 160), (30), DFS
- (5725 - 5875 @ 80), (14)
+ (5490 - 5730 @ 160), (30), DFS
+ (5735 - 5875 @ 80), (14)
# 60 gHz band channels 1-4, ref: Etsi En 302 567
(57000 - 66000 @ 2160), (40)
@@ -1134,8 +1134,8 @@
(2402 - 2482 @ 40), (20)
(5170 - 5250 @ 80), (23), AUTO-BW
(5250 - 5330 @ 80), (23), DFS, AUTO-BW
- (5490 - 5710 @ 160), (30), DFS
- (5725 - 5875 @ 80), (14)
+ (5490 - 5730 @ 160), (30), DFS
+ (5735 - 5875 @ 80), (14)
country TT:
(2402 - 2482 @ 40), (20)
@@ -1209,8 +1209,8 @@
(2402 - 2482 @ 40), (20)
(5170 - 5250 @ 80), (23), AUTO-BW
(5250 - 5330 @ 80), (23), DFS, AUTO-BW
- (5490 - 5710 @ 160), (30), DFS
- (5725 - 5875 @ 80), (14)
+ (5490 - 5730 @ 160), (30), DFS
+ (5735 - 5875 @ 80), (14)
country VE: DFS-FCC
(2402 - 2482 @ 40), (20)
diff --git a/scripts/build-all.py b/scripts/build-all.py
index bd468cd..4a60ebc 100755
--- a/scripts/build-all.py
+++ b/scripts/build-all.py
@@ -59,12 +59,8 @@
def check_kernel():
"""Ensure that PWD is a kernel directory"""
- have_defconfig = any([
- os.path.isfile('arch/arm64/configs/msm_defconfig'),
- os.path.isfile('arch/arm64/configs/sdm845_defconfig')])
-
- if not all([os.path.isfile('MAINTAINERS'), have_defconfig]):
- fail("This doesn't seem to be an MSM kernel dir")
+ if not os.path.isfile('MAINTAINERS'):
+ fail("This doesn't seem to be a kernel dir")
def check_build():
"""Ensure that the build directory is present."""
diff --git a/scripts/checkpatch.pl b/scripts/checkpatch.pl
index cdfa754..0534378 100755
--- a/scripts/checkpatch.pl
+++ b/scripts/checkpatch.pl
@@ -3012,6 +3012,10 @@
} elsif ($line =~ /^\+.*\bEFI_GUID\s*\(/) {
$msg_type = "";
+ # Long copyright statements are another special case
+ } elsif ($rawline =~ /^\+.\*.*copyright.*\(c\).*$/i) {
+ $msg_type = "";
+
# Otherwise set the alternate message types
# a comment starts before $max_line_length
diff --git a/sound/core/control_compat.c b/sound/core/control_compat.c
index 1fa7076..84ee29c 100644
--- a/sound/core/control_compat.c
+++ b/sound/core/control_compat.c
@@ -400,8 +400,7 @@
if (copy_from_user(&data->id, &data32->id, sizeof(data->id)) ||
copy_from_user(&data->type, &data32->type, 3 * sizeof(u32)))
goto error;
- if (get_user(data->owner, &data32->owner) ||
- get_user(data->type, &data32->type))
+ if (get_user(data->owner, &data32->owner))
goto error;
switch (data->type) {
case SNDRV_CTL_ELEM_TYPE_BOOLEAN:
diff --git a/sound/pci/hda/hda_intel.c b/sound/pci/hda/hda_intel.c
index 7d3f88d..4e91120 100644
--- a/sound/pci/hda/hda_intel.c
+++ b/sound/pci/hda/hda_intel.c
@@ -2061,6 +2061,8 @@
SND_PCI_QUIRK(0x1849, 0x0c0c, "Asrock B85M-ITX", 0),
/* https://bugzilla.redhat.com/show_bug.cgi?id=1525104 */
SND_PCI_QUIRK(0x1043, 0x8733, "Asus Prime X370-Pro", 0),
+ /* https://bugzilla.redhat.com/show_bug.cgi?id=1572975 */
+ SND_PCI_QUIRK(0x17aa, 0x36a7, "Lenovo C50 All in one", 0),
/* https://bugzilla.kernel.org/show_bug.cgi?id=198611 */
SND_PCI_QUIRK(0x17aa, 0x2227, "Lenovo X1 Carbon 3rd Gen", 0),
{}
diff --git a/sound/soc/au1x/ac97c.c b/sound/soc/au1x/ac97c.c
index 29a97d5..66d6c52 100644
--- a/sound/soc/au1x/ac97c.c
+++ b/sound/soc/au1x/ac97c.c
@@ -91,8 +91,8 @@
do {
mutex_lock(&ctx->lock);
- tmo = 5;
- while ((RD(ctx, AC97_STATUS) & STAT_CP) && tmo--)
+ tmo = 6;
+ while ((RD(ctx, AC97_STATUS) & STAT_CP) && --tmo)
udelay(21); /* wait an ac97 frame time */
if (!tmo) {
pr_debug("ac97rd timeout #1\n");
@@ -105,7 +105,7 @@
* poll, Forrest, poll...
*/
tmo = 0x10000;
- while ((RD(ctx, AC97_STATUS) & STAT_CP) && tmo--)
+ while ((RD(ctx, AC97_STATUS) & STAT_CP) && --tmo)
asm volatile ("nop");
data = RD(ctx, AC97_CMDRESP);
diff --git a/sound/soc/samsung/i2s.c b/sound/soc/samsung/i2s.c
index 85324e6..2d14e37 100644
--- a/sound/soc/samsung/i2s.c
+++ b/sound/soc/samsung/i2s.c
@@ -642,8 +642,12 @@
tmp |= mod_slave;
break;
case SND_SOC_DAIFMT_CBS_CFS:
- /* Set default source clock in Master mode */
- if (i2s->rclk_srcrate == 0)
+ /*
+ * Set default source clock in Master mode, only when the
+ * CLK_I2S_RCLK_SRC clock is not exposed so we ensure any
+ * clock configuration assigned in DT is not overwritten.
+ */
+ if (i2s->rclk_srcrate == 0 && i2s->clk_data.clks == NULL)
i2s_set_sysclk(dai, SAMSUNG_I2S_RCLKSRC_0,
0, SND_SOC_CLOCK_IN);
break;
@@ -858,6 +862,11 @@
return 0;
if (!(i2s->quirks & QUIRK_NO_MUXPSR)) {
+ struct clk *rclksrc = i2s->clk_table[CLK_I2S_RCLK_SRC];
+
+ if (i2s->rclk_srcrate == 0 && rclksrc && !IS_ERR(rclksrc))
+ i2s->rclk_srcrate = clk_get_rate(rclksrc);
+
psr = i2s->rclk_srcrate / i2s->frmclk / rfs;
writel(((psr - 1) << 8) | PSR_PSREN, i2s->addr + I2SPSR);
dev_dbg(&i2s->pdev->dev,
diff --git a/sound/soc/soc-core.c b/sound/soc/soc-core.c
index b761761..2840a14 100644
--- a/sound/soc/soc-core.c
+++ b/sound/soc/soc-core.c
@@ -1073,7 +1073,8 @@
}
if (!rtd->platform) {
dev_err(card->dev, "ASoC: platform %s not registered\n",
- dai_link->platform_name);
+ ((platform_name) ? platform_name :
+ dai_link->platform_of_node->full_name));
goto _err_defer;
}
diff --git a/sound/soc/soc-topology.c b/sound/soc/soc-topology.c
index 8a758c9..d6b48c7 100644
--- a/sound/soc/soc-topology.c
+++ b/sound/soc/soc-topology.c
@@ -1180,6 +1180,9 @@
kfree(sm);
continue;
}
+
+ /* create any TLV data */
+ soc_tplg_create_tlv(tplg, &kc[i], &mc->hdr);
}
return kc;
diff --git a/sound/usb/mixer.c b/sound/usb/mixer.c
index ce11cc9..1c5d099 100644
--- a/sound/usb/mixer.c
+++ b/sound/usb/mixer.c
@@ -975,6 +975,14 @@
}
break;
+ case USB_ID(0x0d8c, 0x0103):
+ if (!strcmp(kctl->id.name, "PCM Playback Volume")) {
+ usb_audio_info(chip,
+ "set volume quirk for CM102-A+/102S+\n");
+ cval->min = -256;
+ }
+ break;
+
case USB_ID(0x0471, 0x0101):
case USB_ID(0x0471, 0x0104):
case USB_ID(0x0471, 0x0105):
diff --git a/sound/usb/quirks.c b/sound/usb/quirks.c
index 45655b9..da9fc08 100644
--- a/sound/usb/quirks.c
+++ b/sound/usb/quirks.c
@@ -1153,24 +1153,27 @@
return false;
}
-/* Marantz/Denon USB DACs need a vendor cmd to switch
+/* ITF-USB DSD based DACs need a vendor cmd to switch
* between PCM and native DSD mode
+ * (2 altsets version)
*/
-static bool is_marantz_denon_dac(unsigned int id)
+static bool is_itf_usb_dsd_2alts_dac(unsigned int id)
{
switch (id) {
case USB_ID(0x154e, 0x1003): /* Denon DA-300USB */
case USB_ID(0x154e, 0x3005): /* Marantz HD-DAC1 */
case USB_ID(0x154e, 0x3006): /* Marantz SA-14S1 */
+ case USB_ID(0x1852, 0x5065): /* Luxman DA-06 */
return true;
}
return false;
}
-/* TEAC UD-501/UD-503/NT-503 USB DACs need a vendor cmd to switch
- * between PCM/DOP and native DSD mode
+/* ITF-USB DSD based DACs need a vendor cmd to switch
+ * between PCM and native DSD mode
+ * (3 altsets version)
*/
-static bool is_teac_dsd_dac(unsigned int id)
+static bool is_itf_usb_dsd_3alts_dac(unsigned int id)
{
switch (id) {
case USB_ID(0x0644, 0x8043): /* TEAC UD-501/UD-503/NT-503 */
@@ -1187,7 +1190,7 @@
struct usb_device *dev = subs->dev;
int err;
- if (is_marantz_denon_dac(subs->stream->chip->usb_id)) {
+ if (is_itf_usb_dsd_2alts_dac(subs->stream->chip->usb_id)) {
/* First switch to alt set 0, otherwise the mode switch cmd
* will not be accepted by the DAC
*/
@@ -1208,7 +1211,7 @@
break;
}
mdelay(20);
- } else if (is_teac_dsd_dac(subs->stream->chip->usb_id)) {
+ } else if (is_itf_usb_dsd_3alts_dac(subs->stream->chip->usb_id)) {
/* Vendor mode switch cmd is required. */
switch (fmt->altsetting) {
case 3: /* DSD mode (DSD_U32) requested */
@@ -1304,10 +1307,10 @@
(requesttype & USB_TYPE_MASK) == USB_TYPE_CLASS)
mdelay(20);
- /* Marantz/Denon devices with USB DAC functionality need a delay
+ /* ITF-USB DSD based DACs functionality need a delay
* after each class compliant request
*/
- if (is_marantz_denon_dac(chip->usb_id)
+ if (is_itf_usb_dsd_2alts_dac(chip->usb_id)
&& (requesttype & USB_TYPE_MASK) == USB_TYPE_CLASS)
mdelay(20);
@@ -1371,14 +1374,14 @@
break;
}
- /* Denon/Marantz devices with USB DAC functionality */
- if (is_marantz_denon_dac(chip->usb_id)) {
+ /* ITF-USB DSD based DACs (2 altsets version) */
+ if (is_itf_usb_dsd_2alts_dac(chip->usb_id)) {
if (fp->altsetting == 2)
return SNDRV_PCM_FMTBIT_DSD_U32_BE;
}
- /* TEAC devices with USB DAC functionality */
- if (is_teac_dsd_dac(chip->usb_id)) {
+ /* ITF-USB DSD based DACs (3 altsets version) */
+ if (is_itf_usb_dsd_3alts_dac(chip->usb_id)) {
if (fp->altsetting == 3)
return SNDRV_PCM_FMTBIT_DSD_U32_BE;
}
diff --git a/tools/testing/selftests/seccomp/seccomp_bpf.c b/tools/testing/selftests/seccomp/seccomp_bpf.c
index f689981..d5be7b5 100644
--- a/tools/testing/selftests/seccomp/seccomp_bpf.c
+++ b/tools/testing/selftests/seccomp/seccomp_bpf.c
@@ -1692,7 +1692,11 @@
#endif
#ifndef SECCOMP_FILTER_FLAG_TSYNC
-#define SECCOMP_FILTER_FLAG_TSYNC 1
+#define SECCOMP_FILTER_FLAG_TSYNC (1UL << 0)
+#endif
+
+#ifndef SECCOMP_FILTER_FLAG_SPEC_ALLOW
+#define SECCOMP_FILTER_FLAG_SPEC_ALLOW (1UL << 2)
#endif
#ifndef seccomp
@@ -1791,6 +1795,78 @@
}
}
+/*
+ * Test detection of known and unknown filter flags. Userspace needs to be able
+ * to check if a filter flag is supported by the current kernel and a good way
+ * of doing that is by attempting to enter filter mode, with the flag bit in
+ * question set, and a NULL pointer for the _args_ parameter. EFAULT indicates
+ * that the flag is valid and EINVAL indicates that the flag is invalid.
+ */
+TEST(detect_seccomp_filter_flags)
+{
+ unsigned int flags[] = { SECCOMP_FILTER_FLAG_TSYNC,
+ SECCOMP_FILTER_FLAG_SPEC_ALLOW };
+ unsigned int flag, all_flags;
+ int i;
+ long ret;
+
+ /* Test detection of known-good filter flags */
+ for (i = 0, all_flags = 0; i < ARRAY_SIZE(flags); i++) {
+ int bits = 0;
+
+ flag = flags[i];
+ /* Make sure the flag is a single bit! */
+ while (flag) {
+ if (flag & 0x1)
+ bits ++;
+ flag >>= 1;
+ }
+ ASSERT_EQ(1, bits);
+ flag = flags[i];
+
+ ret = seccomp(SECCOMP_SET_MODE_FILTER, flag, NULL);
+ ASSERT_NE(ENOSYS, errno) {
+ TH_LOG("Kernel does not support seccomp syscall!");
+ }
+ EXPECT_EQ(-1, ret);
+ EXPECT_EQ(EFAULT, errno) {
+ TH_LOG("Failed to detect that a known-good filter flag (0x%X) is supported!",
+ flag);
+ }
+
+ all_flags |= flag;
+ }
+
+ /* Test detection of all known-good filter flags */
+ ret = seccomp(SECCOMP_SET_MODE_FILTER, all_flags, NULL);
+ EXPECT_EQ(-1, ret);
+ EXPECT_EQ(EFAULT, errno) {
+ TH_LOG("Failed to detect that all known-good filter flags (0x%X) are supported!",
+ all_flags);
+ }
+
+ /* Test detection of an unknown filter flag */
+ flag = -1;
+ ret = seccomp(SECCOMP_SET_MODE_FILTER, flag, NULL);
+ EXPECT_EQ(-1, ret);
+ EXPECT_EQ(EINVAL, errno) {
+ TH_LOG("Failed to detect that an unknown filter flag (0x%X) is unsupported!",
+ flag);
+ }
+
+ /*
+ * Test detection of an unknown filter flag that may simply need to be
+ * added to this test
+ */
+ flag = flags[ARRAY_SIZE(flags) - 1] << 1;
+ ret = seccomp(SECCOMP_SET_MODE_FILTER, flag, NULL);
+ EXPECT_EQ(-1, ret);
+ EXPECT_EQ(EINVAL, errno) {
+ TH_LOG("Failed to detect that an unknown filter flag (0x%X) is unsupported! Does a new flag need to be added to this test?",
+ flag);
+ }
+}
+
TEST(TSYNC_first)
{
struct sock_filter filter[] = {
diff --git a/virt/kvm/arm/vgic/vgic-its.c b/virt/kvm/arm/vgic/vgic-its.c
index 31f5625..1ebbf23 100644
--- a/virt/kvm/arm/vgic/vgic-its.c
+++ b/virt/kvm/arm/vgic/vgic-its.c
@@ -208,8 +208,8 @@
u8 prop;
int ret;
- ret = kvm_read_guest(kvm, propbase + irq->intid - GIC_LPI_OFFSET,
- &prop, 1);
+ ret = kvm_read_guest_lock(kvm, propbase + irq->intid - GIC_LPI_OFFSET,
+ &prop, 1);
if (ret)
return ret;
@@ -339,8 +339,9 @@
* this very same byte in the last iteration. Reuse that.
*/
if (byte_offset != last_byte_offset) {
- ret = kvm_read_guest(vcpu->kvm, pendbase + byte_offset,
- &pendmask, 1);
+ ret = kvm_read_guest_lock(vcpu->kvm,
+ pendbase + byte_offset,
+ &pendmask, 1);
if (ret) {
kfree(intids);
return ret;
@@ -628,7 +629,7 @@
return false;
/* Each 1st level entry is represented by a 64-bit value. */
- if (kvm_read_guest(its->dev->kvm,
+ if (kvm_read_guest_lock(its->dev->kvm,
BASER_ADDRESS(baser) + index * sizeof(indirect_ptr),
&indirect_ptr, sizeof(indirect_ptr)))
return false;
@@ -1152,8 +1153,8 @@
cbaser = CBASER_ADDRESS(its->cbaser);
while (its->cwriter != its->creadr) {
- int ret = kvm_read_guest(kvm, cbaser + its->creadr,
- cmd_buf, ITS_CMD_SIZE);
+ int ret = kvm_read_guest_lock(kvm, cbaser + its->creadr,
+ cmd_buf, ITS_CMD_SIZE);
/*
* If kvm_read_guest() fails, this could be due to the guest
* programming a bogus value in CBASER or something else going