aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--Documentation/RCU/stallwarn.txt5
-rw-r--r--Documentation/devicetree/bindings/i2c/i2c-msm-v2.txt4
-rw-r--r--Makefile6
-rwxr-xr-x[-rw-r--r--]arch/arm/boot/dts/qcom/msm8996-camera-sensor-mtp.dtsi26
-rw-r--r--arch/arm/boot/dts/qcom/msm8996-pinctrl.dtsi13
-rw-r--r--arch/arm/boot/dts/qcom/msm8996.dtsi9
-rw-r--r--arch/arm64/boot/dts/htc/dsi-panel-s1m1-ea8064tg.dtsi2
-rw-r--r--arch/arm64/boot/dts/htc/dsi-panel-s1m1-s6e3ha3.dtsi2
-rwxr-xr-xarch/arm64/boot/dts/htc/msm8996-camera-sensor-m1s1.dtsi8
-rw-r--r--arch/arm64/boot/dts/htc/msm8996-htc_marlin.dtsi8
-rw-r--r--arch/arm64/boot/dts/htc/msm8996-htc_sailfish.dtsi8
-rw-r--r--arch/arm64/boot/dts/htc/msm8996-touch-m1.dtsi18
-rwxr-xr-xarch/arm64/boot/dts/htc/msm8996-touch-s1.dtsi18
-rw-r--r--arch/arm64/configs/marlin_defconfig8
-rw-r--r--arch/arm64/include/asm/pmu.h2
-rw-r--r--arch/arm64/kernel/perf_event.c43
-rw-r--r--build.config5
-rw-r--r--build.config.kasan27
-rw-r--r--drivers/base/Kconfig5
-rw-r--r--drivers/base/firmware_class.c8
-rw-r--r--drivers/base/power/main.c3
-rw-r--r--drivers/char/diag/diag_dci.c2
-rw-r--r--drivers/char/diag/diag_masks.c9
-rw-r--r--drivers/char/diag/diag_usb.c6
-rw-r--r--drivers/char/diag/diagchar.h3
-rw-r--r--drivers/char/diag/diagchar_core.c35
-rw-r--r--drivers/char/diag/diagfwd.c17
-rw-r--r--drivers/i2c/busses/i2c-msm-v2.c111
-rw-r--r--drivers/input/touchscreen/synaptics_dsx_htc_2.6/synaptics_dsx_core.c95
-rw-r--r--drivers/media/platform/msm/camera_v2/isp/msm_isp.h2
-rw-r--r--drivers/media/platform/msm/camera_v2/isp/msm_isp32.c5
-rw-r--r--drivers/media/platform/msm/camera_v2/isp/msm_isp40.c5
-rw-r--r--drivers/media/platform/msm/camera_v2/isp/msm_isp44.c5
-rw-r--r--drivers/media/platform/msm/camera_v2/isp/msm_isp46.c5
-rw-r--r--drivers/media/platform/msm/camera_v2/isp/msm_isp47.c7
-rw-r--r--drivers/media/platform/msm/camera_v2/isp/msm_isp47.h2
-rw-r--r--drivers/media/platform/msm/camera_v2/isp/msm_isp_axi_util.c2
-rw-r--r--drivers/media/platform/msm/camera_v2/isp/msm_isp_util.c25
-rw-r--r--drivers/media/platform/msm/camera_v2/isp/msm_isp_util.h2
-rw-r--r--drivers/media/platform/msm/camera_v2/ispif/msm_ispif.c12
-rw-r--r--drivers/platform/msm/sps/sps_bam.c29
-rw-r--r--drivers/power/htc_battery.c22
-rw-r--r--drivers/power/qpnp-fg.c101
-rw-r--r--drivers/power/qpnp-smbcharger.c18
-rw-r--r--drivers/soc/qcom/pil-q6v5-mss.c8
-rw-r--r--drivers/soc/qcom/subsys-pil-tz.c6
-rw-r--r--drivers/soc/qcom/subsystem_restart.c12
-rw-r--r--drivers/staging/qcacld-2.0/CORE/HDD/inc/wlan_hdd_cfg.h6
-rw-r--r--drivers/staging/qcacld-2.0/CORE/HDD/src/wlan_hdd_cfg80211.c6
-rw-r--r--drivers/staging/qcacld-2.0/CORE/HDD/src/wlan_hdd_softap_tx_rx.c44
-rw-r--r--drivers/staging/qcacld-2.0/CORE/HDD/src/wlan_hdd_tx_rx.c44
-rw-r--r--drivers/staging/qcacld-2.0/CORE/MAC/inc/qwlan_version.h2
-rw-r--r--drivers/staging/qcacld-2.0/CORE/MAC/src/pe/lim/limFT.c10
-rw-r--r--drivers/staging/qcacld-2.0/CORE/MAC/src/pe/lim/limLinkMonitoringAlgo.c10
-rw-r--r--drivers/staging/qcacld-2.0/CORE/MAC/src/pe/lim/limUtils.c25
-rw-r--r--drivers/staging/qcacld-2.0/CORE/SAP/src/sapFsm.c2
-rw-r--r--drivers/staging/qcacld-2.0/CORE/SERVICES/COMMON/adf/adf_nbuf.c43
-rw-r--r--drivers/staging/qcacld-2.0/CORE/SERVICES/COMMON/adf/adf_nbuf.h7
-rw-r--r--drivers/staging/qcacld-2.0/CORE/SERVICES/WMA/wma.c491
-rw-r--r--drivers/staging/qcacld-2.0/CORE/SERVICES/WMA/wma.h8
-rw-r--r--drivers/staging/qcacld-2.0/CORE/SERVICES/WMI/wmi_unified_priv.h4
-rw-r--r--drivers/staging/qcacld-2.0/CORE/VOSS/inc/vos_packet.h4
-rw-r--r--drivers/staging/qcacld-2.0/CORE/VOSS/src/vos_api.c4
-rw-r--r--drivers/staging/qcacld-2.0/CORE/VOSS/src/vos_packet.c61
-rw-r--r--drivers/usb/dwc3/dwc3-msm.c53
-rw-r--r--drivers/video/msm/mdss/mdss_rotator.c34
-rw-r--r--drivers/video/msm/mdss/mdss_rotator_internal.h6
-rw-r--r--fs/eventpoll.c6
-rw-r--r--fs/pstore/platform.c36
-rw-r--r--fs/pstore/pmsg.c35
-rw-r--r--fs/pstore/ram.c19
-rw-r--r--fs/pstore/ram_core.c47
-rw-r--r--include/linux/inet_diag.h2
-rw-r--r--include/linux/interrupt.h7
-rw-r--r--include/linux/power/htc_battery.h2
-rw-r--r--include/linux/power_supply.h1
-rw-r--r--include/linux/pstore.h11
-rw-r--r--include/linux/pstore_ram.h7
-rw-r--r--include/linux/trace_clock.h1
-rw-r--r--include/net/udp.h1
-rw-r--r--include/soc/qcom/subsystem_restart.h3
-rw-r--r--include/uapi/linux/inet_diag.h15
-rw-r--r--include/uapi/media/msmb_ispif.h2
-rw-r--r--kernel/rcu/tree.c32
-rw-r--r--kernel/rcu/tree.h2
-rw-r--r--kernel/sched/cpupri.c35
-rw-r--r--kernel/sched/fair.c3
-rw-r--r--kernel/sched/rt.c48
-rw-r--r--kernel/sched/sched.h5
-rw-r--r--kernel/softirq.c9
-rw-r--r--kernel/trace/trace.c1
-rw-r--r--kernel/trace/trace_clock.c14
-rw-r--r--net/ipv4/inet_diag.c112
-rw-r--r--net/ipv4/udp.c15
-rw-r--r--net/ipv4/udp_diag.c89
-rw-r--r--net/ipv6/icmp.c2
-rw-r--r--net/ipv6/ping.c38
-rw-r--r--net/ipv6/udp.c1
-rwxr-xr-xscripts/gcc-wrapper.py102
-rwxr-xr-xsound/soc/codecs/wcd9335.c4
-rw-r--r--sound/soc/msm/msm-cpe-lsm.c43
-rw-r--r--sound/soc/msm/qdsp6v2/msm-pcm-q6-noirq.c26
-rw-r--r--sound/soc/msm/qdsp6v2/msm-pcm-q6-v2.c7
-rwxr-xr-xsound/soc/msm/qdsp6v2/msm-pcm-routing-v2.c13
-rw-r--r--verity_rdev_keys.der.x509bin0 -> 959 bytes
105 files changed, 1683 insertions, 751 deletions
diff --git a/Documentation/RCU/stallwarn.txt b/Documentation/RCU/stallwarn.txt
index ef5a2fd4ff70..607270338b93 100644
--- a/Documentation/RCU/stallwarn.txt
+++ b/Documentation/RCU/stallwarn.txt
@@ -193,6 +193,11 @@ o For !CONFIG_PREEMPT kernels, a CPU looping anywhere in the
behavior, you might need to replace some of the cond_resched()
calls with calls to cond_resched_rcu_qs().
+o Anything that prevents RCU's grace-period kthreads from running.
+ This can result in the "All QSes seen" console-log message.
+ This message will include information on when the kthread last
+ ran and how often it should be expected to run.
+
o A CPU-bound real-time task in a CONFIG_PREEMPT kernel, which might
happen to preempt a low-priority task in the middle of an RCU
read-side critical section. This is especially damaging if
diff --git a/Documentation/devicetree/bindings/i2c/i2c-msm-v2.txt b/Documentation/devicetree/bindings/i2c/i2c-msm-v2.txt
index fa3abb215773..77ff94245276 100644
--- a/Documentation/devicetree/bindings/i2c/i2c-msm-v2.txt
+++ b/Documentation/devicetree/bindings/i2c/i2c-msm-v2.txt
@@ -32,6 +32,10 @@ Optional property:
register. When missing, default to the value given in driver.
- qcom,fs-clk-div: fs divider value to configure clk-ctl register. When
missing, default to the value given in driver.
+ - qcom,i2c-clk : clock GPIO in case SW bit-banging is needed (if HW recovery
+ mechanism fails, SW will bit-bang clock line upto 9 times and sniff
+ data until slave releases the data line)
+ - qcom,i2c-dat : data-line GPIO in case SW bit-banging is needed
Example:
aliases {
diff --git a/Makefile b/Makefile
index 51ab2fee33ff..cedf40687ece 100644
--- a/Makefile
+++ b/Makefile
@@ -354,7 +354,7 @@ include $(srctree)/scripts/Kbuild.include
# Make variables (CC, etc...)
AS = $(CROSS_COMPILE)as
LD = $(CROSS_COMPILE)ld
-REAL_CC = $(CROSS_COMPILE)gcc
+CC = $(CROSS_COMPILE)gcc
CPP = $(CC) -E
AR = $(CROSS_COMPILE)ar
NM = $(CROSS_COMPILE)nm
@@ -369,10 +369,6 @@ PERL = perl
PYTHON = python
CHECK = sparse
-# Use the wrapper for the compiler. This wrapper scans for new
-# warnings and causes the build to stop upon encountering them.
-CC = $(srctree)/scripts/gcc-wrapper.py $(REAL_CC)
-
CHECKFLAGS := -D__linux__ -Dlinux -D__STDC__ -Dunix -D__unix__ \
-Wbitwise -Wno-return-void $(CF)
CFLAGS_MODULE =
diff --git a/arch/arm/boot/dts/qcom/msm8996-camera-sensor-mtp.dtsi b/arch/arm/boot/dts/qcom/msm8996-camera-sensor-mtp.dtsi
index 63600b6abd68..20ba9d3a31b0 100644..100755
--- a/arch/arm/boot/dts/qcom/msm8996-camera-sensor-mtp.dtsi
+++ b/arch/arm/boot/dts/qcom/msm8996-camera-sensor-mtp.dtsi
@@ -22,29 +22,6 @@
};
&cci {
- actuator0: qcom,actuator@0 {
- cell-index = <0>;
- reg = <0x0>;
- compatible = "qcom,actuator";
- qcom,cci-master = <0>;
- cam_vaf-supply = <&pm8994_l23>;
- qcom,cam-vreg-name = "cam_vaf";
- qcom,cam-vreg-min-voltage = <2800000>;
- qcom,cam-vreg-max-voltage = <2800000>;
- qcom,cam-vreg-op-mode = <100000>;
- };
-
- actuator1: qcom,actuator@1 {
- cell-index = <1>;
- reg = <0x1>;
- compatible = "qcom,actuator";
- qcom,cci-master = <1>;
- cam_vaf-supply = <&pm8994_l23>;
- qcom,cam-vreg-name = "cam_vaf";
- qcom,cam-vreg-min-voltage = <2800000>;
- qcom,cam-vreg-max-voltage = <2800000>;
- qcom,cam-vreg-op-mode = <100000>;
- };
ois0: qcom,ois@0 {
cell-index = <0>;
@@ -134,7 +111,6 @@
qcom,csid-sd-index = <0>;
qcom,mount-angle = <90>;
qcom,led-flash-src = <&led_flash0>;
- qcom,actuator-src = <&actuator0>;
qcom,ois-src = <&ois0>;
qcom,eeprom-src = <&eeprom0>;
cam_vdig-supply = <&pm8994_s3>;
@@ -178,7 +154,6 @@
qcom,csid-sd-index = <1>;
qcom,mount-angle = <90>;
qcom,eeprom-src = <&eeprom1>;
- qcom,actuator-src = <&actuator1>;
cam_vdig-supply = <&pm8994_s3>;
cam_vio-supply = <&pm8994_lvs1>;
cam_vana-supply = <&pm8994_l17>;
@@ -221,7 +196,6 @@
qcom,csid-sd-index = <2>;
qcom,mount-angle = <90>;
qcom,eeprom-src = <&eeprom1>;
- qcom,actuator-src = <&actuator1>;
cam_vdig-supply = <&pm8994_l27>;
cam_vio-supply = <&pm8994_lvs1>;
cam_vana-supply = <&pm8994_l29>;
diff --git a/arch/arm/boot/dts/qcom/msm8996-pinctrl.dtsi b/arch/arm/boot/dts/qcom/msm8996-pinctrl.dtsi
index ff128acb376a..e1949eb31439 100644
--- a/arch/arm/boot/dts/qcom/msm8996-pinctrl.dtsi
+++ b/arch/arm/boot/dts/qcom/msm8996-pinctrl.dtsi
@@ -713,6 +713,19 @@
bias-pull-down;
};
};
+
+ i2c_12_bitbang: i2c_12_bitbang {
+ mux {
+ pins = "gpio87", "gpio88";
+ function = "gpio";
+ };
+
+ config {
+ pins = "gpio87", "gpio88";
+ drive-strength = <8>;
+ bias-disable;
+ };
+ };
};
i2c_6 {
diff --git a/arch/arm/boot/dts/qcom/msm8996.dtsi b/arch/arm/boot/dts/qcom/msm8996.dtsi
index 76cdcfd5b0c3..41cc93940878 100644
--- a/arch/arm/boot/dts/qcom/msm8996.dtsi
+++ b/arch/arm/boot/dts/qcom/msm8996.dtsi
@@ -20,10 +20,6 @@
qcom,pmic-id = <0x20009 0x2000A 0x0 0x0>;
interrupt-parent = <&intc>;
- chosen {
- bootargs = "sched_enable_hmp=1 sched_enable_power_aware=1";
- };
-
aliases {
sdhc1 = &sdhc_1; /* SDC1 eMMC slot */
sdhc2 = &sdhc_2; /* SDC2 SD card slot */
@@ -459,12 +455,15 @@
qcom,master-id = <84>;
qcom,clk-freq-out = <400000>;
qcom,clk-freq-in = <19200000>;
+ qcom,i2c-clk = <&tlmm 88 0>;
+ qcom,i2c-dat = <&tlmm 87 0>;
clock-names = "iface_clk", "core_clk";
clocks = <&clock_gcc clk_gcc_blsp2_ahb_clk>,
<&clock_gcc clk_gcc_blsp2_qup6_i2c_apps_clk>;
- pinctrl-names = "i2c_active", "i2c_sleep";
+ pinctrl-names = "i2c_active", "i2c_sleep", "i2c_bitbang";
pinctrl-0 = <&i2c_12_active>;
pinctrl-1 = <&i2c_12_sleep>;
+ pinctrl-2 = <&i2c_12_bitbang>;
};
diff --git a/arch/arm64/boot/dts/htc/dsi-panel-s1m1-ea8064tg.dtsi b/arch/arm64/boot/dts/htc/dsi-panel-s1m1-ea8064tg.dtsi
index c13798318455..abe53af9871a 100644
--- a/arch/arm64/boot/dts/htc/dsi-panel-s1m1-ea8064tg.dtsi
+++ b/arch/arm64/boot/dts/htc/dsi-panel-s1m1-ea8064tg.dtsi
@@ -110,7 +110,6 @@
29 01 00 00 00 00 02 B0 01
29 01 00 00 00 00 03 B2 05 48
29 01 00 00 00 00 02 F7 03
- 29 01 00 00 00 00 02 51 60
29 01 00 00 00 00 03 F0 A5 A5
];
qcom,mdss-dsi-lp-mode-off = [
@@ -130,7 +129,6 @@
29 01 00 00 00 00 02 B0 01
29 01 00 00 00 00 03 B2 00 10
29 01 00 00 00 00 02 F7 03
- 29 01 00 00 00 00 02 51 00
29 01 00 00 00 00 03 F0 A5 A5
];
qcom,mdss-dsi-lp-off-offset = <16 1 0>;
diff --git a/arch/arm64/boot/dts/htc/dsi-panel-s1m1-s6e3ha3.dtsi b/arch/arm64/boot/dts/htc/dsi-panel-s1m1-s6e3ha3.dtsi
index 88386d7d5fd0..27ad9146a066 100644
--- a/arch/arm64/boot/dts/htc/dsi-panel-s1m1-s6e3ha3.dtsi
+++ b/arch/arm64/boot/dts/htc/dsi-panel-s1m1-s6e3ha3.dtsi
@@ -117,7 +117,6 @@
29 01 00 00 00 00 02 B0 06
29 01 00 00 00 00 03 F2 0C 04
29 01 00 00 00 00 02 F7 03
- 20 01 00 00 00 00 02 51 5A
29 01 00 00 00 00 03 F0 A5 A5
];
qcom,mdss-dsi-lp-mode-off = [
@@ -137,7 +136,6 @@
29 01 00 00 00 00 02 B0 06
29 01 00 00 00 00 03 F2 0A 06
29 01 00 00 00 00 02 F7 03
- 29 01 00 00 00 00 02 51 00
29 01 00 00 00 00 03 F0 A5 A5
];
qcom,mdss-dsi-lp-off-offset = <16 1 0>;
diff --git a/arch/arm64/boot/dts/htc/msm8996-camera-sensor-m1s1.dtsi b/arch/arm64/boot/dts/htc/msm8996-camera-sensor-m1s1.dtsi
index 0060e2ec45bc..cae8d6291831 100755
--- a/arch/arm64/boot/dts/htc/msm8996-camera-sensor-m1s1.dtsi
+++ b/arch/arm64/boot/dts/htc/msm8996-camera-sensor-m1s1.dtsi
@@ -295,8 +295,8 @@ qcom,camera@0 {
qcom,cam-vreg-op-mode = <0 0>;//uA
qcom,gpio-no-mux = <0>;
pinctrl-names = "cam_default", "cam_suspend";
- pinctrl-0 = <&cam_sensor_mclk0_active &cam_sensor_rear_active &cci0_active>;
- pinctrl-1 = <&cam_sensor_mclk0_suspend &cam_sensor_rear_suspend &cci0_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 93 0>,
<&tlmm 49 0>;
@@ -337,8 +337,8 @@ qcom,camera@1 {
qcom,cam-vreg-op-mode = <0 0 0>;//uA
qcom,gpio-no-mux = <0>;
pinctrl-names = "cam_default", "cam_suspend";
- pinctrl-0 = <&cam_sensor_mclk1_active &cam_sensor_rear2_active &cci1_active>;
- pinctrl-1 = <&cam_sensor_mclk1_suspend &cam_sensor_rear2_suspend &cci0_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 23 0>,
<&pm8994_gpios 14 0>;
diff --git a/arch/arm64/boot/dts/htc/msm8996-htc_marlin.dtsi b/arch/arm64/boot/dts/htc/msm8996-htc_marlin.dtsi
index 2d7842a7bdcc..32a9ccdbef1e 100644
--- a/arch/arm64/boot/dts/htc/msm8996-htc_marlin.dtsi
+++ b/arch/arm64/boot/dts/htc/msm8996-htc_marlin.dtsi
@@ -120,10 +120,11 @@
};
&qusb_phy0 {
- qcom,qusb-phy-init-seq = <0xE8 0x80
- 0x51 0x84
- 0x81 0x88
+ qcom,qusb-phy-init-seq = <0xA8 0x80
+ 0x63 0x84
+ 0x83 0x88
0xC0 0x8C
+ 0x03 0x90
0x30 0x08
0x79 0x0C
0x21 0x10
@@ -240,6 +241,7 @@
qcom,ext-sense-type = <1>;
qcom,cold-hot-jeita-hysteresis = <20 30>;
qcom,fg-cutoff-voltage-mv = <3250>;
+ qcom,irq-volt-empty-mv = <3050>;
/delete-property/ qcom,capacity-learning-feedback;
};
diff --git a/arch/arm64/boot/dts/htc/msm8996-htc_sailfish.dtsi b/arch/arm64/boot/dts/htc/msm8996-htc_sailfish.dtsi
index 242a050f65b1..310dc7b7a6bd 100644
--- a/arch/arm64/boot/dts/htc/msm8996-htc_sailfish.dtsi
+++ b/arch/arm64/boot/dts/htc/msm8996-htc_sailfish.dtsi
@@ -15,10 +15,11 @@
#include "msm8996-touch-s1.dtsi"
&qusb_phy0 {
- qcom,qusb-phy-init-seq = <0xE8 0x80
- 0x23 0x84
- 0x81 0x88
+ qcom,qusb-phy-init-seq = <0xA8 0x80
+ 0x63 0x84
+ 0x83 0x88
0xC0 0x8C
+ 0x03 0x90
0x30 0x08
0x79 0x0C
0x21 0x10
@@ -56,6 +57,7 @@
qcom,ext-sense-type = <1>;
qcom,cold-hot-jeita-hysteresis = <20 30>;
qcom,fg-cutoff-voltage-mv = <3250>;
+ qcom,irq-volt-empty-mv = <3050>;
/delete-property/ qcom,capacity-learning-feedback;
};
diff --git a/arch/arm64/boot/dts/htc/msm8996-touch-m1.dtsi b/arch/arm64/boot/dts/htc/msm8996-touch-m1.dtsi
index ee41b2591556..3f70175b5d79 100644
--- a/arch/arm64/boot/dts/htc/msm8996-touch-m1.dtsi
+++ b/arch/arm64/boot/dts/htc/msm8996-touch-m1.dtsi
@@ -85,6 +85,19 @@
bias-disable;
};
};
+
+ i2c_3_bitbang: i2c_3_bitbang {
+ mux {
+ pins = "gpio47", "gpio48";
+ function = "gpio";
+ };
+
+ config {
+ pins = "gpio47", "gpio48";
+ drive-strength = <8>;
+ bias-disable;
+ };
+ };
};
};
@@ -129,12 +142,15 @@
qcom,master-id = <86>;
qcom,clk-freq-out = <400000>;
qcom,clk-freq-in = <19200000>;
+ qcom,i2c-clk = <&tlmm 48 0>;
+ qcom,i2c-dat = <&tlmm 47 0>;
clock-names = "iface_clk", "core_clk";
clocks = <&clock_gcc clk_gcc_blsp1_ahb_clk>,
<&clock_gcc clk_gcc_blsp1_qup3_i2c_apps_clk>;
- pinctrl-names = "i2c_active", "i2c_sleep";
+ pinctrl-names = "i2c_active", "i2c_sleep", "i2c_bitbang";
pinctrl-0 = <&i2c_3_active>;
pinctrl-1 = <&i2c_3_sleep>;
+ pinctrl-2 = <&i2c_3_bitbang>;
};
};
diff --git a/arch/arm64/boot/dts/htc/msm8996-touch-s1.dtsi b/arch/arm64/boot/dts/htc/msm8996-touch-s1.dtsi
index bfa6126f181f..ede762608774 100755
--- a/arch/arm64/boot/dts/htc/msm8996-touch-s1.dtsi
+++ b/arch/arm64/boot/dts/htc/msm8996-touch-s1.dtsi
@@ -85,6 +85,19 @@
bias-disable;
};
};
+
+ i2c_3_bitbang: i2c_3_bitbang {
+ mux {
+ pins = "gpio47", "gpio48";
+ function = "gpio";
+ };
+
+ config {
+ pins = "gpio47", "gpio48";
+ drive-strength = <8>;
+ bias-disable;
+ };
+ };
};
};
@@ -129,12 +142,15 @@
qcom,master-id = <86>;
qcom,clk-freq-out = <400000>;
qcom,clk-freq-in = <19200000>;
+ qcom,i2c-clk = <&tlmm 48 0>;
+ qcom,i2c-dat = <&tlmm 47 0>;
clock-names = "iface_clk", "core_clk";
clocks = <&clock_gcc clk_gcc_blsp1_ahb_clk>,
<&clock_gcc clk_gcc_blsp1_qup3_i2c_apps_clk>;
- pinctrl-names = "i2c_active", "i2c_sleep";
+ pinctrl-names = "i2c_active", "i2c_sleep", "i2c_bitbang";
pinctrl-0 = <&i2c_3_active>;
pinctrl-1 = <&i2c_3_sleep>;
+ pinctrl-2 = <&i2c_3_bitbang>;
};
};
diff --git a/arch/arm64/configs/marlin_defconfig b/arch/arm64/configs/marlin_defconfig
index a87144fcc012..ca6fa3ae5aa3 100644
--- a/arch/arm64/configs/marlin_defconfig
+++ b/arch/arm64/configs/marlin_defconfig
@@ -514,7 +514,7 @@ CONFIG_MSM_DDR_HEALTH=y
CONFIG_MSM_WATCHDOG_V2=y
CONFIG_MSM_FORCE_WDOG_BITE_ON_PANIC=y
CONFIG_MSM_CACHE_M4M_ERP64=y
-CONFIG_MSM_CACHE_M4M_ERP64_PANIC_ON_CE=y
+# CONFIG_MSM_CACHE_M4M_ERP64_PANIC_ON_CE is not set
CONFIG_MSM_CACHE_M4M_ERP64_PANIC_ON_UE=y
CONFIG_MSM_RPM_SMD=y
CONFIG_MSM_RPM_LOG=y
@@ -577,10 +577,6 @@ CONFIG_HTC_NC_GPIO_PIN_SETTING=y
CONFIG_HTC_DEBUG_BOOTLOADER_LOG=y
CONFIG_MSM_TZ_LOG=y
CONFIG_MOBICORE_DRIVER=y
-CONFIG_EXT2_FS=y
-CONFIG_EXT2_FS_XATTR=y
-CONFIG_EXT3_FS=y
-# CONFIG_EXT3_DEFAULTS_TO_ORDERED is not set
CONFIG_EXT4_FS=y
CONFIG_EXT4_FS_SECURITY=y
CONFIG_EXT4_FS_ENCRYPTION=y
@@ -590,12 +586,12 @@ CONFIG_VFAT_FS=y
CONFIG_TMPFS=y
CONFIG_TMPFS_POSIX_ACL=y
CONFIG_ECRYPT_FS=y
-CONFIG_ECRYPT_FS_MESSAGING=y
CONFIG_SDCARD_FS=y
CONFIG_PSTORE=y
CONFIG_PSTORE_CONSOLE=y
CONFIG_PSTORE_PMSG=y
CONFIG_PSTORE_RAM=y
+# CONFIG_NETWORK_FILESYSTEMS is not set
CONFIG_NLS_CODEPAGE_437=y
CONFIG_NLS_ASCII=y
CONFIG_NLS_ISO8859_1=y
diff --git a/arch/arm64/include/asm/pmu.h b/arch/arm64/include/asm/pmu.h
index 48c59086aed2..53d992a6c6f1 100644
--- a/arch/arm64/include/asm/pmu.h
+++ b/arch/arm64/include/asm/pmu.h
@@ -43,6 +43,8 @@ struct pmu_hw_events {
struct arm_pmu {
struct pmu pmu;
+ bool percpu_irq_requested;
+ int percpu_irq;
cpumask_t active_irqs;
const char *name;
irqreturn_t (*handle_irq)(int irq_num, void *dev);
diff --git a/arch/arm64/kernel/perf_event.c b/arch/arm64/kernel/perf_event.c
index 386ca2617bbf..a07d1f40eaf4 100644
--- a/arch/arm64/kernel/perf_event.c
+++ b/arch/arm64/kernel/perf_event.c
@@ -393,7 +393,9 @@ armpmu_disable_percpu_irq(void *data)
static void
armpmu_release_hardware(struct arm_pmu *armpmu)
{
+ get_online_cpus();
armpmu->free_irq(armpmu);
+ put_online_cpus();
}
static void
@@ -414,12 +416,12 @@ armpmu_reserve_hardware(struct arm_pmu *armpmu)
return -ENODEV;
}
+ get_online_cpus();
err = armpmu->request_irq(armpmu, armpmu->handle_irq);
- if (err) {
+ if (err)
armpmu_release_hardware(armpmu);
- return err;
- }
- return 0;
+ put_online_cpus();
+ return err;
}
static void
@@ -1042,6 +1044,8 @@ static int armv8pmu_request_irq(struct arm_pmu *cpu_pmu, irq_handler_t handler)
}
on_each_cpu(armpmu_enable_percpu_irq, &irq, 1);
+ cpu_pmu->percpu_irq_requested = true;
+ cpu_pmu->percpu_irq = irq;
} else {
for (i = 0; i < irqs; ++i) {
err = 0;
@@ -1093,6 +1097,7 @@ static void armv8pmu_free_irq(struct arm_pmu *cpu_pmu)
if (irq_is_percpu(irq)) {
on_each_cpu(armpmu_disable_percpu_irq, &irq, 1);
free_percpu_irq(irq, &cpu_hw_events);
+ cpu_pmu->percpu_irq_requested = false;
} else {
for (i = 0; i < irqs; ++i) {
if (!cpumask_test_and_clear_cpu(i,
@@ -1334,16 +1339,28 @@ static int __cpuinit cpu_pmu_notify(struct notifier_block *b,
{
int cpu = (unsigned long)hcpu;
struct arm_pmu *pmu = container_of(b, struct arm_pmu, hotplug_nb);
- if ((action & ~CPU_TASKS_FROZEN) != CPU_STARTING)
- return NOTIFY_DONE;
- if (!cpumask_test_cpu(cpu, cpu_online_mask))
- return NOTIFY_DONE;
- if (pmu->reset)
- cpu_pmu->reset(pmu);
- else
- return NOTIFY_DONE;
- return NOTIFY_OK;
+ switch (action & ~CPU_TASKS_FROZEN) {
+ case CPU_DOWN_PREPARE:
+ if (pmu->percpu_irq_requested) {
+ int irq = pmu->percpu_irq;
+ smp_call_function_single(cpu,
+ armpmu_disable_percpu_irq, &irq, 1);
+ }
+ break;
+
+ case CPU_STARTING:
+ case CPU_DOWN_FAILED:
+ if (pmu->reset)
+ pmu->reset(pmu);
+ if (pmu->percpu_irq_requested) {
+ int irq = pmu->percpu_irq;
+ smp_call_function_single(cpu,
+ armpmu_enable_percpu_irq, &irq, 1);
+ }
+ break;
+ }
+ return NOTIFY_DONE;
}
#ifdef CONFIG_CPU_PM
diff --git a/build.config b/build.config
index 230bfd14cafd..fa53eb4c343f 100644
--- a/build.config
+++ b/build.config
@@ -1,12 +1,13 @@
ARCH=arm64
-BRANCH=android-msm-marlin-3.18-ndr-factoryrom
+BRANCH=android-msm-marlin-3.18
CROSS_COMPILE=aarch64-linux-android-
DEFCONFIG=marlin_defconfig
-EXTRA_CMDS=''
+EXTRA_CMDS='python build/buildinfo/buildinfo.py'
KERNEL_DIR=private/msm-google
LINUX_GCC_CROSS_COMPILE_PREBUILTS_BIN=prebuilts/gcc/linux-x86/aarch64/aarch64-linux-android-4.9/bin
FILES="
arch/arm64/boot/Image.gz-dtb
vmlinux
System.map
+compile.json
"
diff --git a/build.config.kasan b/build.config.kasan
new file mode 100644
index 000000000000..8f0141aa0446
--- /dev/null
+++ b/build.config.kasan
@@ -0,0 +1,27 @@
+function update_kasan_config() {
+ ${KERNEL_DIR}/scripts/config --file ${OUT_DIR}/.config \
+ -e CONFIG_KASAN \
+ -e CONFIG_KASAN_INLINE \
+ -e CONFIG_TEST_KASAN \
+ -e CONFIG_KCOV \
+ -e CONFIG_SLUB \
+ -e CONFIG_SLUB_DEBUG \
+ -e CONFIG_SLUB_DEBUG_ON \
+ -d CONFIG_SLUB_DEBUG_PANIC_ON \
+ -d CONFIG_KASAN_OUTLINE
+ (cd ${OUT_DIR} && \
+ make O=${OUT_DIR} $archsubarch CROSS_COMPILE=${CROSS_COMPILE} olddefconfig)
+}
+
+ARCH=arm64
+BRANCH=android-msm-marlin-3.18
+CROSS_COMPILE=aarch64-linux-android-
+DEFCONFIG=marlin_defconfig
+KERNEL_DIR=private/msm-google
+POST_DEFCONFIG_CMDS="update_kasan_config"
+LINUX_GCC_CROSS_COMPILE_PREBUILTS_BIN=prebuilts-master/gcc/linux-x86/aarch64/aarch64-linux-android-4.9/bin
+FILES="
+arch/arm64/boot/Image.gz-dtb
+vmlinux
+System.map
+"
diff --git a/drivers/base/Kconfig b/drivers/base/Kconfig
index c7d273ba567a..1d6d1f6f7cd0 100644
--- a/drivers/base/Kconfig
+++ b/drivers/base/Kconfig
@@ -165,6 +165,11 @@ config FW_LOADER_USER_HELPER_FALLBACK
If you are unsure about this, say N here.
+config FW_CACHE
+ bool "Enable firmware caching during suspend"
+ depends on PM_SLEEP
+ default n
+
config WANT_DEV_COREDUMP
bool
help
diff --git a/drivers/base/firmware_class.c b/drivers/base/firmware_class.c
index 033b3101cbfe..b87fa5d419ae 100644
--- a/drivers/base/firmware_class.c
+++ b/drivers/base/firmware_class.c
@@ -1119,7 +1119,7 @@ static int fw_load_from_user_helper(struct firmware *firmware,
return _request_firmware_load(fw_priv, desc->opt_flags, timeout);
}
-#ifdef CONFIG_PM_SLEEP
+#ifdef CONFIG_FW_CACHE
/* kill pending requests without uevent to avoid blocking suspend */
static void kill_requests_without_uevent(void)
{
@@ -1597,7 +1597,7 @@ request_firmware_nowait_into_buf(
}
EXPORT_SYMBOL_GPL(request_firmware_nowait_into_buf);
-#ifdef CONFIG_PM_SLEEP
+#ifdef CONFIG_FW_CACHE
static ASYNC_DOMAIN_EXCLUSIVE(fw_cache_domain);
/**
@@ -1937,7 +1937,7 @@ static void __init fw_cache_init(void)
INIT_LIST_HEAD(&fw_cache.head);
fw_cache.state = FW_LOADER_NO_CACHE;
-#ifdef CONFIG_PM_SLEEP
+#ifdef CONFIG_FW_CACHE
spin_lock_init(&fw_cache.name_lock);
INIT_LIST_HEAD(&fw_cache.fw_names);
@@ -1964,7 +1964,7 @@ static int __init firmware_class_init(void)
static void __exit firmware_class_exit(void)
{
-#ifdef CONFIG_PM_SLEEP
+#ifdef CONFIG_FW_CACHE
unregister_syscore_ops(&fw_syscore_ops);
unregister_pm_notifier(&fw_cache.pm_notify);
#endif
diff --git a/drivers/base/power/main.c b/drivers/base/power/main.c
index ef5d2797fceb..230ab8d0ce67 100644
--- a/drivers/base/power/main.c
+++ b/drivers/base/power/main.c
@@ -30,7 +30,6 @@
#include <linux/suspend.h>
#include <trace/events/power.h>
#include <linux/cpufreq.h>
-#include <linux/cpuidle.h>
#include <linux/timer.h>
#include <linux/wakeup_reason.h>
@@ -606,7 +605,6 @@ void dpm_resume_noirq(pm_message_t state)
async_synchronize_full();
dpm_show_time(starttime, state, "noirq");
resume_device_irqs();
- cpuidle_resume();
trace_suspend_resume(TPS("dpm_resume_noirq"), state.event, false);
}
@@ -1142,7 +1140,6 @@ int dpm_suspend_noirq(pm_message_t state)
int error = 0;
trace_suspend_resume(TPS("dpm_suspend_noirq"), state.event, true);
- cpuidle_pause();
suspend_device_irqs();
mutex_lock(&dpm_list_mtx);
pm_transition = state;
diff --git a/drivers/char/diag/diag_dci.c b/drivers/char/diag/diag_dci.c
index 62b0cf2e966f..13a3afa5409c 100644
--- a/drivers/char/diag/diag_dci.c
+++ b/drivers/char/diag/diag_dci.c
@@ -3000,7 +3000,7 @@ int diag_dci_write_proc(uint8_t peripheral, int pkt_type, char *buf, int len)
DIAG_LOG(DIAG_DEBUG_DCI,
"buf: 0x%pK, p: %d, len: %d, f_mask: %d\n",
buf, peripheral, len,
- driver->feature[peripheral].rcvd_feature_mask);
+ driver->feature[PERIPHERAL_MODEM].rcvd_feature_mask);
return -EINVAL;
}
diff --git a/drivers/char/diag/diag_masks.c b/drivers/char/diag/diag_masks.c
index 9f694a052cb8..f6709faa2d77 100644
--- a/drivers/char/diag/diag_masks.c
+++ b/drivers/char/diag/diag_masks.c
@@ -1779,6 +1779,15 @@ int diag_copy_to_user_msg_mask(char __user *buf, size_t count,
if (!mask_info)
return -EIO;
+ mutex_lock(&driver->diag_maskclear_mutex);
+ if (driver->mask_clear) {
+ DIAG_LOG(DIAG_DEBUG_PERIPHERALS,
+ "diag:%s: count = %zu\n", __func__, count);
+ mutex_unlock(&driver->diag_maskclear_mutex);
+ return -EIO;
+ }
+ mutex_unlock(&driver->diag_maskclear_mutex);
+
mutex_lock(&mask_info->lock);
mask = (struct diag_msg_mask_t *)(mask_info->ptr);
for (i = 0; i < driver->msg_mask_tbl_count; i++, mask++) {
diff --git a/drivers/char/diag/diag_usb.c b/drivers/char/diag/diag_usb.c
index eb715cc8501c..ca54b24ec604 100644
--- a/drivers/char/diag/diag_usb.c
+++ b/drivers/char/diag/diag_usb.c
@@ -215,6 +215,12 @@ static void usb_connect_work_fn(struct work_struct *work)
*/
static void usb_disconnect(struct diag_usb_info *ch)
{
+ if (!ch)
+ return;
+
+ if (!atomic_read(&ch->connected) && driver->usb_connected)
+ diag_clear_masks(NULL);
+
if (ch && ch->ops && ch->ops->close)
ch->ops->close(ch->ctxt, DIAG_USB_MODE);
}
diff --git a/drivers/char/diag/diagchar.h b/drivers/char/diag/diagchar.h
index fb86f6e246b1..43331190c582 100644
--- a/drivers/char/diag/diagchar.h
+++ b/drivers/char/diag/diagchar.h
@@ -463,6 +463,8 @@ struct diagchar_dev {
struct class *diagchar_class;
struct device *diag_dev;
int ref_count;
+ int mask_clear;
+ struct mutex diag_maskclear_mutex;
struct mutex diagchar_mutex;
struct mutex diag_file_mutex;
wait_queue_head_t wait_q;
@@ -622,6 +624,7 @@ void diag_cmd_remove_reg(struct diag_cmd_reg_entry_t *entry, uint8_t proc);
void diag_cmd_remove_reg_by_pid(int pid);
void diag_cmd_remove_reg_by_proc(int proc);
int diag_cmd_chk_polling(struct diag_cmd_reg_entry_t *entry);
+void diag_clear_masks(struct diag_md_session_t *info);
void diag_record_stats(int type, int flag);
diff --git a/drivers/char/diag/diagchar_core.c b/drivers/char/diag/diagchar_core.c
index ee11ba0a5dcc..10a38dcd812b 100644
--- a/drivers/char/diag/diagchar_core.c
+++ b/drivers/char/diag/diagchar_core.c
@@ -387,6 +387,27 @@ static uint32_t diag_translate_kernel_to_user_mask(uint32_t peripheral_mask)
return ret;
}
+void diag_clear_masks(struct diag_md_session_t *info)
+{
+ int ret;
+ char cmd_disable_log_mask[] = { 0x73, 0, 0, 0, 0, 0, 0, 0};
+ char cmd_disable_msg_mask[] = { 0x7D, 0x05, 0, 0, 0, 0, 0, 0};
+ char cmd_disable_event_mask[] = { 0x60, 0};
+
+ DIAG_LOG(DIAG_DEBUG_PERIPHERALS,
+ "diag: %s: masks clear request upon %s\n", __func__,
+ ((info) ? "ODL exit" : "USB Disconnection"));
+
+ ret = diag_process_apps_masks(cmd_disable_log_mask,
+ sizeof(cmd_disable_log_mask), info);
+ ret = diag_process_apps_masks(cmd_disable_msg_mask,
+ sizeof(cmd_disable_msg_mask), info);
+ ret = diag_process_apps_masks(cmd_disable_event_mask,
+ sizeof(cmd_disable_event_mask), info);
+ DIAG_LOG(DIAG_DEBUG_PERIPHERALS,
+ "diag:%s: masks cleared successfully\n", __func__);
+}
+
static void diag_close_logging_process(const int pid)
{
int i;
@@ -398,6 +419,12 @@ static void diag_close_logging_process(const int pid)
if (!session_info)
return;
+ diag_clear_masks(session_info);
+
+ mutex_lock(&driver->diag_maskclear_mutex);
+ driver->mask_clear = 1;
+ mutex_unlock(&driver->diag_maskclear_mutex);
+
session_peripheral_mask = session_info->peripheral_mask;
diag_md_session_close(session_info);
for (i = 0; i < NUM_MD_SESSIONS; i++)
@@ -473,9 +500,14 @@ static int diag_remove_client_entry(struct file *file)
}
static int diagchar_close(struct inode *inode, struct file *file)
{
+ int ret;
DIAG_LOG(DIAG_DEBUG_USERSPACE, "diag: process exit %s\n",
current->comm);
- return diag_remove_client_entry(file);
+ ret = diag_remove_client_entry(file);
+ mutex_lock(&driver->diag_maskclear_mutex);
+ driver->mask_clear = 0;
+ mutex_unlock(&driver->diag_maskclear_mutex);
+ return ret;
}
void diag_record_stats(int type, int flag)
@@ -3354,6 +3386,7 @@ static int __init diagchar_init(void)
non_hdlc_data.len = 0;
mutex_init(&driver->hdlc_disable_mutex);
mutex_init(&driver->diagchar_mutex);
+ mutex_init(&driver->diag_maskclear_mutex);
mutex_init(&driver->diag_file_mutex);
mutex_init(&driver->delayed_rsp_mutex);
mutex_init(&apps_data_mutex);
diff --git a/drivers/char/diag/diagfwd.c b/drivers/char/diag/diagfwd.c
index 7ead0f1c8a30..65bbe7cdd834 100644
--- a/drivers/char/diag/diagfwd.c
+++ b/drivers/char/diag/diagfwd.c
@@ -1225,8 +1225,6 @@ static int diagfwd_mux_open(int id, int mode)
static int diagfwd_mux_close(int id, int mode)
{
- uint8_t i;
-
switch (mode) {
case DIAG_USB_MODE:
driver->usb_connected = 0;
@@ -1241,15 +1239,16 @@ static int diagfwd_mux_close(int id, int mode)
driver->md_session_mode == DIAG_MD_NONE) ||
(driver->md_session_mode == DIAG_MD_PERIPHERAL)) {
/*
- * In this case the channel must not be closed. This case
- * indicates that the USB is removed but there is a client
- * running in background with Memory Device mode
+ * This case indicates that the USB is removed
+ * but there is a client running in background
+ * with Memory Device mode.
*/
} else {
- for (i = 0; i < NUM_PERIPHERALS; i++) {
- diagfwd_close(i, TYPE_DATA);
- diagfwd_close(i, TYPE_CMD);
- }
+ /*
+ * With clearing of masks on ODL exit and
+ * USB disconnection, closing of the channel is
+ * not needed.This enables read and drop of stale packets.
+ */
/* Re enable HDLC encoding */
pr_debug("diag: In %s, re-enabling HDLC encoding\n",
__func__);
diff --git a/drivers/i2c/busses/i2c-msm-v2.c b/drivers/i2c/busses/i2c-msm-v2.c
index f7586ecb0f9a..aa4c887ff5fc 100644
--- a/drivers/i2c/busses/i2c-msm-v2.c
+++ b/drivers/i2c/busses/i2c-msm-v2.c
@@ -32,6 +32,8 @@
#include <linux/dma-mapping.h>
#include <linux/i2c.h>
#include <linux/of.h>
+#include <linux/gpio.h>
+#include <linux/of_gpio.h>
#include <linux/msm-sps.h>
#include <linux/msm-bus.h>
#include <linux/msm-bus-board.h>
@@ -50,6 +52,10 @@ static int i2c_msm_xfer_wait_for_completion(struct i2c_msm_ctrl *ctrl,
static int i2c_msm_pm_resume(struct device *dev);
static void i2c_msm_pm_suspend(struct device *dev);
static void i2c_msm_clk_path_init(struct i2c_msm_ctrl *ctrl);
+static struct pinctrl_state *
+i2c_msm_rsrcs_gpio_get_state(struct i2c_msm_ctrl *ctrl, const char *name);
+static void i2c_msm_pm_pinctrl_state(struct i2c_msm_ctrl *ctrl,
+ bool runtime_active);
/* string table for enum i2c_msm_xfer_mode_id */
const char * const i2c_msm_mode_str_tbl[] = {
@@ -1902,74 +1908,81 @@ static void i2c_msm_qup_init(struct i2c_msm_ctrl *ctrl)
"error on verifying HW support (I2C_MAST_GEN=0)\n");
}
-/*
- * qup_i2c_try_recover_bus_busy: issue QUP bus clear command
- */
-static int qup_i2c_try_recover_bus_busy(struct i2c_msm_ctrl *ctrl)
+
+static void qup_i2c_recover_bit_bang(struct i2c_msm_ctrl *ctrl)
{
- int ret;
- ulong min_sleep_usec;
+ int i, ret;
+ int gpio_clk;
+ int gpio_dat;
+ bool gpio_clk_status = false;
+ uint32_t status = readl_relaxed(ctrl->rsrcs.base + QUP_I2C_STATUS);
+ struct pinctrl_state *bitbang;
- /* call i2c_msm_qup_init() to set core in idle state */
- i2c_msm_qup_init(ctrl);
+ disable_irq(ctrl->rsrcs.irq);
+ gpio_clk = of_get_named_gpio(ctrl->adapter.dev.of_node, "qcom,i2c-clk",
+ 0);
+ gpio_dat = of_get_named_gpio(ctrl->adapter.dev.of_node, "qcom,i2c-dat",
+ 0);
- /* must be in run state for bus clear */
- ret = i2c_msm_qup_state_set(ctrl, QUP_STATE_RUN);
- if (ret < 0) {
- dev_err(ctrl->dev, "error: bus clear fail to set run state\n");
- return ret;
+ if (gpio_clk < 0 || gpio_dat < 0) {
+ dev_warn(ctrl->dev, "SW bigbang err: i2c gpios not known\n");
+ goto recovery_exit;
}
- /*
- * call i2c_msm_qup_xfer_init_run_state() to set clock dividers.
- * the dividers are necessary for bus clear.
- */
- i2c_msm_qup_xfer_init_run_state(ctrl);
-
- writel_relaxed(0x1, ctrl->rsrcs.base + QUP_I2C_MASTER_BUS_CLR);
-
- /*
- * wait for recovery (9 clock pulse cycles) to complete.
- * min_time = 9 clock *10 (1000% margin)
- * max_time = 10* min_time
- */
- min_sleep_usec =
- max_t(ulong, (9 * 10 * USEC_PER_SEC) / ctrl->rsrcs.clk_freq_out, 100);
+ bitbang = i2c_msm_rsrcs_gpio_get_state(ctrl, "i2c_bitbang");
+ if (bitbang)
+ ret = pinctrl_select_state(ctrl->rsrcs.pinctrl, bitbang);
+ if (!bitbang || ret) {
+ dev_err(ctrl->dev, "GPIO pins have no bitbang setting\n");
+ goto recovery_exit;
+ }
- usleep_range(min_sleep_usec, min_sleep_usec * 10);
- return ret;
-}
+ for (i = 0; i < 9; i++) {
+ if (gpio_get_value(gpio_dat) && gpio_clk_status)
+ break;
+ gpio_direction_output(gpio_clk, 0);
+ udelay(5);
+ gpio_direction_output(gpio_dat, 0);
+ udelay(5);
+ gpio_direction_input(gpio_clk);
+ udelay(5);
+ if (!gpio_get_value(gpio_clk))
+ udelay(20);
+ if (!gpio_get_value(gpio_clk))
+ usleep_range(10000, 10001);
+ gpio_clk_status = gpio_get_value(gpio_clk);
+ gpio_direction_input(gpio_dat);
+ udelay(5);
+ }
-static int qup_i2c_recover_bus_busy(struct i2c_msm_ctrl *ctrl)
-{
- u32 bus_clr, bus_active, status;
- int retry = 0;
- dev_info(ctrl->dev, "Executing bus recovery procedure (9 clk pulse)\n");
+ i2c_msm_pm_pinctrl_state(ctrl, true);
+ udelay(10);
- do {
- qup_i2c_try_recover_bus_busy(ctrl);
- bus_clr = readl_relaxed(ctrl->rsrcs.base +
- QUP_I2C_MASTER_BUS_CLR);
- status = readl_relaxed(ctrl->rsrcs.base + QUP_I2C_STATUS);
- bus_active = status & I2C_STATUS_BUS_ACTIVE;
- if (++retry >= I2C_QUP_MAX_BUS_RECOVERY_RETRY)
- break;
- } while (bus_clr || bus_active);
+ status = readl_relaxed(ctrl->rsrcs.base + QUP_I2C_STATUS);
+ if (!(status & I2C_STATUS_BUS_ACTIVE)) {
+ dev_info(ctrl->dev, "Bus busy cleared after %d clock cycles, "
+ "status %x\n",
+ i, status);
+ goto recovery_exit;
+ }
- dev_info(ctrl->dev, "Bus recovery %s after %d retries\n",
- (bus_clr || bus_active) ? "fail" : "success", retry);
- return 0;
+ dev_warn(ctrl->dev, "Bus still busy, status %x\n", status);
+recovery_exit:
+ enable_irq(ctrl->rsrcs.irq);
}
static int i2c_msm_qup_post_xfer(struct i2c_msm_ctrl *ctrl, int err)
{
+ if (ctrl->xfer.err == I2C_MSM_ERR_ARB_LOST)
+ qup_i2c_recover_bit_bang(ctrl);
+
/* poll until bus is released */
if (i2c_msm_qup_poll_bus_active_unset(ctrl)) {
if ((ctrl->xfer.err == I2C_MSM_ERR_ARB_LOST) ||
(ctrl->xfer.err == I2C_MSM_ERR_BUS_ERR) ||
(ctrl->xfer.err == I2C_MSM_ERR_TIMEOUT)) {
if (i2c_msm_qup_slv_holds_bus(ctrl))
- qup_i2c_recover_bus_busy(ctrl);
+ qup_i2c_recover_bit_bang(ctrl);
/* do not generalize error to EIO if its already set */
if (!err)
diff --git a/drivers/input/touchscreen/synaptics_dsx_htc_2.6/synaptics_dsx_core.c b/drivers/input/touchscreen/synaptics_dsx_htc_2.6/synaptics_dsx_core.c
index 0cf705bba644..90b6fc37284b 100644
--- a/drivers/input/touchscreen/synaptics_dsx_htc_2.6/synaptics_dsx_core.c
+++ b/drivers/input/touchscreen/synaptics_dsx_htc_2.6/synaptics_dsx_core.c
@@ -65,6 +65,7 @@
#define REPORT_2D_PRESSURE
#define TEMP_FORCE_WA
/* #define USE_DATA_SERVER */
+#define USE_I2C_SWITCH
#define F12_DATA_15_WORKAROUND
@@ -2856,6 +2857,35 @@ exit:
return retval;
}
+static int synaptics_rmi4_f12_configure_lpwg(
+ struct synaptics_rmi4_data *rmi4_data,
+ const struct synaptics_rmi4_fn *fhandler)
+{
+ int retval;
+ struct synaptics_rmi4_f12_ctrl_27 ctrl_27 = {
+ .double_tap_enable = 1,
+ .lpwg_report_rate = 20,
+ .false_activation_threshold = 3,
+ .maximum_active_duration = 12,
+ .timer_1_duration = 15,
+ .maximum_active_duration_timeout = 10,
+ };
+ const struct synaptics_rmi4_f12_extra_data *extra_data =
+ (const struct synaptics_rmi4_f12_extra_data *)fhandler->extra;
+
+ retval = synaptics_rmi4_reg_write(rmi4_data,
+ fhandler->full_addr.ctrl_base +
+ extra_data->ctrl27_offset,
+ ctrl_27.data,
+ sizeof(ctrl_27.data));
+ if (retval < 0)
+ dev_err(rmi4_data->pdev->dev.parent,
+ "%s: Failed to change lpwg settings\n",
+ __func__);
+
+ return retval;
+}
+
static int synaptics_rmi4_f12_init(struct synaptics_rmi4_data *rmi4_data,
struct synaptics_rmi4_fn *fhandler,
struct synaptics_rmi4_fn_desc *fd,
@@ -3326,6 +3356,10 @@ static int synaptics_rmi4_f12_init(struct synaptics_rmi4_data *rmi4_data,
printk("[TP]%s:Wakeup Gesture range (%d,%d) -> (%d,%d)\n", __func__,
double_tap[0], double_tap[1], double_tap[2], double_tap[3]);
+
+ retval = synaptics_rmi4_f12_configure_lpwg(rmi4_data, fhandler);
+ if (retval < 0)
+ return retval;
}
synaptics_rmi4_set_intr_mask(fhandler, fd, intr_count);
@@ -4950,6 +4984,7 @@ static int synaptics_rmi4_reinit_device(struct synaptics_rmi4_data *rmi4_data)
list_for_each_entry(fhandler, &rmi->support_fn_list, link) {
if (fhandler->fn_number == SYNAPTICS_RMI4_F12) {
synaptics_rmi4_f12_set_enables(rmi4_data, 0);
+ synaptics_rmi4_f12_configure_lpwg(rmi4_data, fhandler);
break;
}
}
@@ -5673,7 +5708,6 @@ static void synaptics_rmi4_f12_wg(struct synaptics_rmi4_data *rmi4_data,
{
int retval;
unsigned char reporting_control[3];
- struct synaptics_rmi4_f12_ctrl_27 ctrl_27;
struct synaptics_rmi4_f12_extra_data *extra_data;
struct synaptics_rmi4_fn *fhandler;
struct synaptics_rmi4_device_info *rmi;
@@ -5699,47 +5733,10 @@ static void synaptics_rmi4_f12_wg(struct synaptics_rmi4_data *rmi4_data,
return;
}
- retval = synaptics_rmi4_reg_read(rmi4_data,
- fhandler->full_addr.ctrl_base +
- extra_data->ctrl27_offset,
- ctrl_27.data,
- sizeof(ctrl_27.data));
- if (retval < 0) {
- dev_err(rmi4_data->pdev->dev.parent,
- "%s: Failed to change lpwg settings\n",
- __func__);
- return;
- }
-
- if (enable) {
+ if (enable)
reporting_control[2] = F12_WAKEUP_GESTURE_MODE;
- ctrl_27.double_tap_enable = 1;
- ctrl_27.lpwg_report_rate = 20;
- ctrl_27.false_activation_threshold = 3;
- ctrl_27.maximum_active_duration = 12;
- ctrl_27.timer_1_duration = 15;
- ctrl_27.maximum_active_duration_timeout = 10;
- } else {
+ else
reporting_control[2] = F12_CONTINUOUS_MODE;
- ctrl_27.double_tap_enable = 0;
- ctrl_27.lpwg_report_rate = 20;
- ctrl_27.false_activation_threshold = 3;
- ctrl_27.maximum_active_duration = 12;
- ctrl_27.timer_1_duration = 15;
- ctrl_27.maximum_active_duration_timeout = 10;
- }
-
- retval = synaptics_rmi4_reg_write(rmi4_data,
- fhandler->full_addr.ctrl_base +
- extra_data->ctrl27_offset,
- ctrl_27.data,
- sizeof(ctrl_27.data));
- if (retval < 0) {
- dev_err(rmi4_data->pdev->dev.parent,
- "%s: Failed to change lpwg settings\n",
- __func__);
- return;
- }
retval = synaptics_rmi4_reg_write(rmi4_data,
fhandler->full_addr.ctrl_base +
@@ -5909,6 +5906,13 @@ exit:
}
mutex_unlock(&exp_data.mutex);
+#ifdef USE_I2C_SWITCH
+ gpio_set_value(rmi4_data->hw_if->board_data->switch_gpio, 1);
+ dev_dbg(rmi4_data->pdev->dev.parent,
+ "%s: Switch I2C mux to sensor hub\n",
+ __func__);
+#endif // USE_I2C_SWITCH
+
rmi4_data->suspend = true;
return 0;
@@ -5925,6 +5929,13 @@ static int synaptics_rmi4_resume(struct device *dev)
if (rmi4_data->stay_awake)
return 0;
+#ifdef USE_I2C_SWITCH
+ gpio_set_value(rmi4_data->hw_if->board_data->switch_gpio, 0);
+ dev_dbg(rmi4_data->pdev->dev.parent,
+ "%s: Switch I2C mux to AP\n",
+ __func__);
+#endif // USE_I2C_SWITCH
+
synaptics_rmi4_free_fingers(rmi4_data);
if (rmi4_data->enable_wakeup_gesture) {
@@ -5937,6 +5948,10 @@ static int synaptics_rmi4_resume(struct device *dev)
rmi4_data->current_page = MASK_8BIT;
synaptics_rmi4_sleep_enable(rmi4_data, false);
+#ifdef USE_I2C_SWITCH
+ synaptics_rmi4_wakeup_gesture(rmi4_data, false);
+ synaptics_rmi4_force_cal(rmi4_data);
+#endif
synaptics_rmi4_irq_enable(rmi4_data, true, false);
exit:
diff --git a/drivers/media/platform/msm/camera_v2/isp/msm_isp.h b/drivers/media/platform/msm/camera_v2/isp/msm_isp.h
index f525c71f5da2..99e19fe93f54 100644
--- a/drivers/media/platform/msm/camera_v2/isp/msm_isp.h
+++ b/drivers/media/platform/msm/camera_v2/isp/msm_isp.h
@@ -234,7 +234,7 @@ struct msm_vfe_core_ops {
struct msm_vfe_rdi_cfg *rdi_cfg,
enum msm_vfe_input_src input_src);
void (*get_error_mask)(uint32_t *error_mask0, uint32_t *error_mask1);
- void (*process_error_status)(struct vfe_device *vfe_dev);
+ int (*process_error_status)(struct vfe_device *vfe_dev);
void (*get_overflow_mask)(uint32_t *overflow_mask);
void (*get_irq_mask)(struct vfe_device *vfe_dev,
uint32_t *irq0_mask, uint32_t *irq1_mask);
diff --git a/drivers/media/platform/msm/camera_v2/isp/msm_isp32.c b/drivers/media/platform/msm/camera_v2/isp/msm_isp32.c
index 062ff3bea7e6..69f9f7f3a974 100644
--- a/drivers/media/platform/msm/camera_v2/isp/msm_isp32.c
+++ b/drivers/media/platform/msm/camera_v2/isp/msm_isp32.c
@@ -484,8 +484,9 @@ static void msm_vfe32_get_overflow_mask(uint32_t *overflow_mask)
*overflow_mask = 0x0;
}
-static void msm_vfe32_process_error_status(struct vfe_device *vfe_dev)
+static int msm_vfe32_process_error_status(struct vfe_device *vfe_dev)
{
+ int ret = 0;
uint32_t error_status1 = vfe_dev->error_info.error_mask1;
if (error_status1 & BIT(0))
@@ -565,6 +566,8 @@ static void msm_vfe32_process_error_status(struct vfe_device *vfe_dev)
}
if (error_status1 & BIT(22))
pr_err("%s: axi error\n", __func__);
+
+ return ret;
}
static void msm_vfe32_read_irq_status(struct vfe_device *vfe_dev,
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 5b419ecfcbfd..5dc7b8ee498c 100644
--- a/drivers/media/platform/msm/camera_v2/isp/msm_isp40.c
+++ b/drivers/media/platform/msm/camera_v2/isp/msm_isp40.c
@@ -466,8 +466,9 @@ static void msm_vfe40_process_violation_status(
pr_err("%s: realign buf cr violation\n", __func__);
}
-static void msm_vfe40_process_error_status(struct vfe_device *vfe_dev)
+static int msm_vfe40_process_error_status(struct vfe_device *vfe_dev)
{
+ int ret = 0;
uint32_t error_status1 = vfe_dev->error_info.error_mask1;
if (error_status1 & (1 << 0)) {
pr_err_ratelimited("%s: vfe %d camif error status: 0x%x\n",
@@ -562,6 +563,8 @@ static void msm_vfe40_process_error_status(struct vfe_device *vfe_dev)
/* Update ab/ib values for any overflow that may have occured*/
if ((error_status1 >> 9) & 0x7FFF)
msm_isp_update_last_overflow_ab_ib(vfe_dev);
+
+ return ret;
}
static void msm_vfe40_read_irq_status(struct vfe_device *vfe_dev,
diff --git a/drivers/media/platform/msm/camera_v2/isp/msm_isp44.c b/drivers/media/platform/msm/camera_v2/isp/msm_isp44.c
index b1e515c81801..90564ac215e6 100644
--- a/drivers/media/platform/msm/camera_v2/isp/msm_isp44.c
+++ b/drivers/media/platform/msm/camera_v2/isp/msm_isp44.c
@@ -310,8 +310,9 @@ static void msm_vfe44_process_violation_status(
pr_err("%s: bpc violation\n", __func__);
}
-static void msm_vfe44_process_error_status(struct vfe_device *vfe_dev)
+static int msm_vfe44_process_error_status(struct vfe_device *vfe_dev)
{
+ int ret = 0;
uint32_t error_status1 = vfe_dev->error_info.error_mask1;
if (error_status1 & (1 << 0)) {
pr_err("%s: camif error status: 0x%x\n",
@@ -397,6 +398,8 @@ static void msm_vfe44_process_error_status(struct vfe_device *vfe_dev)
vfe_dev->stats->bfscale_overflow++;
pr_err("%s: status bf scale bus overflow\n", __func__);
}
+
+ return ret;
}
static void msm_vfe44_read_irq_status(struct vfe_device *vfe_dev,
diff --git a/drivers/media/platform/msm/camera_v2/isp/msm_isp46.c b/drivers/media/platform/msm/camera_v2/isp/msm_isp46.c
index 32ffd5906627..bab4e1923973 100644
--- a/drivers/media/platform/msm/camera_v2/isp/msm_isp46.c
+++ b/drivers/media/platform/msm/camera_v2/isp/msm_isp46.c
@@ -281,8 +281,9 @@ static void msm_vfe46_process_violation_status(
violation_status);
}
-static void msm_vfe46_process_error_status(struct vfe_device *vfe_dev)
+static int msm_vfe46_process_error_status(struct vfe_device *vfe_dev)
{
+ int ret = 0;
uint32_t error_status1 = vfe_dev->error_info.error_mask1;
if (error_status1 & (1 << 0)) {
@@ -337,6 +338,8 @@ static void msm_vfe46_process_error_status(struct vfe_device *vfe_dev)
pr_err("%s: status skin bhist bus overflow\n", __func__);
if (error_status1 & (1 << 24))
pr_err("%s: status bf scale bus overflow\n", __func__);
+
+ return ret;
}
static void msm_vfe46_read_irq_status(struct vfe_device *vfe_dev,
diff --git a/drivers/media/platform/msm/camera_v2/isp/msm_isp47.c b/drivers/media/platform/msm/camera_v2/isp/msm_isp47.c
index 06effe701203..0e5565516e14 100644
--- a/drivers/media/platform/msm/camera_v2/isp/msm_isp47.c
+++ b/drivers/media/platform/msm/camera_v2/isp/msm_isp47.c
@@ -444,8 +444,9 @@ void msm_vfe47_process_violation_status(
violation_status);
}
-void msm_vfe47_process_error_status(struct vfe_device *vfe_dev)
+int msm_vfe47_process_error_status(struct vfe_device *vfe_dev)
{
+ int ret = 0;
uint32_t error_status1 = vfe_dev->error_info.error_mask1;
if (error_status1 & (1 << 0)) {
@@ -471,6 +472,8 @@ void msm_vfe47_process_error_status(struct vfe_device *vfe_dev)
pr_err("%s: realign buf cr overflow\n", __func__);
if (error_status1 & (1 << 7)) {
msm_vfe47_process_violation_status(vfe_dev);
+ /* force overflow recovery for violation */
+ ret = -1;
}
if (error_status1 & (1 << 9))
pr_err("%s: image master 0 bus overflow\n", __func__);
@@ -506,6 +509,8 @@ void msm_vfe47_process_error_status(struct vfe_device *vfe_dev)
pr_err("%s: status aec bg bus overflow\n", __func__);
if (error_status1 & (1 << 25))
pr_err("%s: status dsp error\n", __func__);
+
+ return ret;
}
void msm_vfe47_read_irq_status(struct vfe_device *vfe_dev,
diff --git a/drivers/media/platform/msm/camera_v2/isp/msm_isp47.h b/drivers/media/platform/msm/camera_v2/isp/msm_isp47.h
index f75d64f3ff69..ae134e6deba1 100644
--- a/drivers/media/platform/msm/camera_v2/isp/msm_isp47.h
+++ b/drivers/media/platform/msm/camera_v2/isp/msm_isp47.h
@@ -158,7 +158,7 @@ void msm_vfe47_process_input_irq(struct vfe_device *vfe_dev,
struct msm_isp_timestamp *ts);
void msm_vfe47_process_violation_status(
struct vfe_device *vfe_dev);
-void msm_vfe47_process_error_status(struct vfe_device *vfe_dev);
+int msm_vfe47_process_error_status(struct vfe_device *vfe_dev);
void msm_vfe47_clear_status_reg(struct vfe_device *vfe_dev);
int msm_vfe47_get_platform_data(struct vfe_device *vfe_dev);
int msm_vfe47_enable_regulators(struct vfe_device *vfe_dev, int enable);
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 3c7a82858bbf..5e0b685aec80 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
@@ -3046,7 +3046,7 @@ static int msm_isp_request_frame(struct vfe_device *vfe_dev,
*/
if (((vfe_dev->axi_data.src_info[VFE_PIX_0].active) && ((frame_id <=
vfe_dev->axi_data.src_info[VFE_PIX_0].frame_id) ||
- (frame_id <= vfe_dev->axi_data.src_info[VFE_PIX_0].eof_id))) ||
+ (frame_id <= (vfe_dev->axi_data.src_info[VFE_PIX_0].eof_id + 1)))) ||
((!vfe_dev->axi_data.src_info[VFE_PIX_0].active) && (frame_id <=
vfe_dev->axi_data.src_info[frame_src].frame_id)) ||
stream_info->undelivered_request_cnt >= MAX_BUFFERS_IN_HW) {
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 d2b3629202b2..64c44421607b 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
@@ -184,7 +184,9 @@ uint32_t msm_isp_get_framedrop_period(
void msm_isp_get_timestamp(struct msm_isp_timestamp *time_stamp, struct vfe_device *vfe_dev)
{
struct timespec ts;
- do_gettimeofday(&(time_stamp->event_time));
+ ktime_get_ts(&ts);
+ time_stamp->event_time.tv_sec = ts.tv_sec;
+ time_stamp->event_time.tv_usec = ts.tv_nsec/1000;
if (vfe_dev->vt_enable) {
msm_isp_get_avtimer_ts(time_stamp);
time_stamp->buf_time.tv_sec = time_stamp->vt_time.tv_sec;
@@ -1647,19 +1649,21 @@ static int msm_isp_process_iommu_page_fault(struct vfe_device *vfe_dev)
return rc;
}
-void msm_isp_process_error_info(struct vfe_device *vfe_dev)
+int msm_isp_process_error_info(struct vfe_device *vfe_dev)
{
+ int ret = 0;
struct msm_vfe_error_info *error_info = &vfe_dev->error_info;
if (error_info->error_count == 1 ||
!(error_info->info_dump_frame_count % 100)) {
- vfe_dev->hw_info->vfe_ops.core_ops.
+ ret = vfe_dev->hw_info->vfe_ops.core_ops.
process_error_status(vfe_dev);
error_info->error_mask0 = 0;
error_info->error_mask1 = 0;
error_info->camif_status = 0;
error_info->violation_status = 0;
}
+ return ret;
}
static inline void msm_isp_update_error_info(struct vfe_device *vfe_dev,
@@ -1672,7 +1676,8 @@ static inline void msm_isp_update_error_info(struct vfe_device *vfe_dev,
static void msm_isp_process_overflow_irq(
struct vfe_device *vfe_dev,
- uint32_t *irq_status0, uint32_t *irq_status1)
+ uint32_t *irq_status0, uint32_t *irq_status1,
+ uint32_t force_overflow)
{
uint32_t overflow_mask;
@@ -1695,7 +1700,8 @@ static void msm_isp_process_overflow_irq(
/*Check if any overflow bit is set*/
vfe_dev->hw_info->vfe_ops.core_ops.
get_overflow_mask(&overflow_mask);
- overflow_mask &= *irq_status1;
+ if (!force_overflow)
+ overflow_mask &= *irq_status1;
if (overflow_mask) {
struct msm_isp_event_data error_event;
@@ -1812,7 +1818,7 @@ irqreturn_t msm_isp_process_irq(int irq_num, void *data)
irq_status0);
}
msm_isp_process_overflow_irq(vfe_dev,
- &irq_status0, &irq_status1);
+ &irq_status0, &irq_status1, 0);
vfe_dev->hw_info->vfe_ops.core_ops.
get_error_mask(&error_mask0, &error_mask1);
@@ -1881,7 +1887,12 @@ void msm_isp_do_tasklet(unsigned long data)
__func__);
continue;
}
- msm_isp_process_error_info(vfe_dev);
+ if (msm_isp_process_error_info(vfe_dev) == -1) {
+ /* force overflow recovery */
+ msm_isp_process_overflow_irq(vfe_dev,
+ &irq_status0, &irq_status1 ,1);
+ break;
+ }
irq_ops->process_stats_irq(vfe_dev,
irq_status0, irq_status1,
pingpong_status, &ts);
diff --git a/drivers/media/platform/msm/camera_v2/isp/msm_isp_util.h b/drivers/media/platform/msm/camera_v2/isp/msm_isp_util.h
index a8a7ea05f68e..1cc24a97ca1f 100644
--- a/drivers/media/platform/msm/camera_v2/isp/msm_isp_util.h
+++ b/drivers/media/platform/msm/camera_v2/isp/msm_isp_util.h
@@ -62,7 +62,7 @@ irqreturn_t msm_isp_process_irq(int irq_num, void *data);
int msm_isp_set_src_state(struct vfe_device *vfe_dev, void *arg);
void msm_isp_do_tasklet(unsigned long data);
void msm_isp_update_error_frame_count(struct vfe_device *vfe_dev);
-void msm_isp_process_error_info(struct vfe_device *vfe_dev);
+int msm_isp_process_error_info(struct vfe_device *vfe_dev);
int msm_isp_open_node(struct v4l2_subdev *sd, struct v4l2_subdev_fh *fh);
int msm_isp_close_node(struct v4l2_subdev *sd, struct v4l2_subdev_fh *fh);
long msm_isp_ioctl(struct v4l2_subdev *sd, unsigned int cmd, void *arg);
diff --git a/drivers/media/platform/msm/camera_v2/ispif/msm_ispif.c b/drivers/media/platform/msm/camera_v2/ispif/msm_ispif.c
index d0e308e23050..26a76cf4fc64 100644
--- a/drivers/media/platform/msm/camera_v2/ispif/msm_ispif.c
+++ b/drivers/media/platform/msm/camera_v2/ispif/msm_ispif.c
@@ -880,7 +880,7 @@ static int msm_ispif_start_frame_boundary(struct ispif_device *ispif,
return rc;
}
-static int msm_ispif_restart_frame_boundary(struct ispif_device *ispif,
+static int msm_ispif_reconfig(struct ispif_device *ispif,
struct msm_ispif_param_data *params)
{
int rc = 0;
@@ -890,13 +890,11 @@ static int msm_ispif_restart_frame_boundary(struct ispif_device *ispif,
rc = msm_ispif_reset(ispif);
if (!rc)
rc = msm_ispif_config(ispif, params);
- if (!rc)
- rc = msm_ispif_start_frame_boundary(ispif, params);
if (!rc)
- pr_info("ISPIF restart Successful\n");
+ pr_info("ISPIF reconfig Successful\n");
else
- pr_info("ISPIF restart Failed\n");
+ pr_info("ISPIF reconfig Failed\n");
return rc;
}
@@ -1264,8 +1262,8 @@ static long msm_ispif_cmd(struct v4l2_subdev *sd, void *arg)
rc = msm_ispif_start_frame_boundary(ispif, &pcdata->params);
msm_ispif_io_dump_reg(ispif);
break;
- case ISPIF_RESTART_FRAME_BOUNDARY:
- rc = msm_ispif_restart_frame_boundary(ispif, &pcdata->params);
+ case ISPIF_RECONFIG:
+ rc = msm_ispif_reconfig(ispif, &pcdata->params);
msm_ispif_io_dump_reg(ispif);
break;
diff --git a/drivers/platform/msm/sps/sps_bam.c b/drivers/platform/msm/sps/sps_bam.c
index f34242f29e2b..351a416a0f92 100644
--- a/drivers/platform/msm/sps/sps_bam.c
+++ b/drivers/platform/msm/sps/sps_bam.c
@@ -170,19 +170,19 @@ polling:
}
/* Process active pipe sources */
- pipe = list_first_entry(&dev->pipes_q, struct sps_pipe, list);
-
- list_for_each_entry(pipe, &dev->pipes_q, list) {
- /* Check this pipe's bit in the source mask */
- if (BAM_PIPE_IS_ASSIGNED(pipe)
+ if (!list_empty(&dev->pipes_q)) {
+ list_for_each_entry(pipe, &dev->pipes_q, list) {
+ /* Check this pipe's bit in the source mask */
+ if (BAM_PIPE_IS_ASSIGNED(pipe)
&& (!pipe->disconnecting)
&& (source & pipe->pipe_index_mask)) {
- /* This pipe has an interrupt pending */
- pipe_handler(dev, pipe);
- source &= ~pipe->pipe_index_mask;
+ /* This pipe has an interrupt pending */
+ pipe_handler(dev, pipe);
+ source &= ~pipe->pipe_index_mask;
+ }
+ if (source == 0)
+ break;
}
- if (source == 0)
- break;
}
/* Process any inactive pipe sources */
@@ -812,6 +812,7 @@ int sps_bam_pipe_connect(struct sps_pipe *bam_pipe,
void *desc_buf = NULL;
u32 pipe_index;
int result;
+ unsigned long flags;
/* Clear the client pipe state and hw init struct */
pipe_clear(bam_pipe);
@@ -1048,8 +1049,10 @@ int sps_bam_pipe_connect(struct sps_pipe *bam_pipe,
/* Indicate initialization is complete */
dev->pipes[pipe_index] = bam_pipe;
+ spin_lock_irqsave(&dev->isr_lock, flags);
dev->pipe_active_mask |= 1UL << pipe_index;
list_add_tail(&bam_pipe->list, &dev->pipes_q);
+ spin_unlock_irqrestore(&dev->isr_lock, flags);
SPS_DBG2(dev,
"sps:BAM %pa; pipe %d; pipe_index_mask:0x%x; pipe_active_mask:0x%x.\n",
@@ -1083,6 +1086,7 @@ int sps_bam_pipe_disconnect(struct sps_bam *dev, u32 pipe_index)
{
struct sps_pipe *pipe;
int result;
+ unsigned long flags;
if (pipe_index >= dev->props.num_pipes) {
SPS_ERR(dev, "sps:Invalid BAM %pa pipe: %d\n", BAM_ID(dev),
@@ -1094,8 +1098,10 @@ int sps_bam_pipe_disconnect(struct sps_bam *dev, u32 pipe_index)
pipe = dev->pipes[pipe_index];
if (BAM_PIPE_IS_ASSIGNED(pipe)) {
if ((dev->pipe_active_mask & (1UL << pipe_index))) {
+ spin_lock_irqsave(&dev->isr_lock, flags);
list_del(&pipe->list);
dev->pipe_active_mask &= ~(1UL << pipe_index);
+ spin_unlock_irqrestore(&dev->isr_lock, flags);
}
dev->pipe_remote_mask &= ~(1UL << pipe_index);
if (pipe->connect.options & SPS_O_NO_DISABLE)
@@ -2346,6 +2352,7 @@ int sps_bam_get_free_count(struct sps_bam *dev, u32 pipe_index,
int sps_bam_set_satellite(struct sps_bam *dev, u32 pipe_index)
{
struct sps_pipe *pipe = dev->pipes[pipe_index];
+ unsigned long flags;
/*
* Switch to satellite control is only supported on processor
@@ -2387,8 +2394,10 @@ int sps_bam_set_satellite(struct sps_bam *dev, u32 pipe_index)
}
/* Indicate satellite control */
+ spin_lock_irqsave(&dev->isr_lock, flags);
list_del(&pipe->list);
dev->pipe_active_mask &= ~(1UL << pipe_index);
+ spin_unlock_irqrestore(&dev->isr_lock, flags);
dev->pipe_remote_mask |= pipe->pipe_index_mask;
pipe->state |= BAM_STATE_REMOTE;
diff --git a/drivers/power/htc_battery.c b/drivers/power/htc_battery.c
index 75937b780196..4cbb9b852e1f 100644
--- a/drivers/power/htc_battery.c
+++ b/drivers/power/htc_battery.c
@@ -81,6 +81,7 @@ static bool g_htc_battery_probe_done = false;
static bool g_is_fcc_limited = false;
static bool g_is_unknown_charger = false;
static bool g_rerun_apsd_done = false;
+static bool g_critical_shutdown = false;
/* fake soc when set this flag */
bool g_test_power_monitor = false;
@@ -1409,9 +1410,16 @@ static void batt_worker(struct work_struct *work)
batt_level_adjust(time_since_last_update_ms);
g_is_rep_level_ready = true;
- /* STEP 7: force level=0 to trigger userspace shutdown
- FIXME: need discussing with HW which condition needs force shutdown
- */
+ /* STEP 7: force level=0 to trigger userspace shutdown */
+ if ((g_critical_shutdown || (htc_batt_info.force_shutdown_batt_vol &&
+ (htc_batt_info.rep.batt_vol <= htc_batt_info.force_shutdown_batt_vol))) &&
+ htc_batt_info.rep.batt_temp > 0) {
+ BATT_LOG("critical shutdown criteria: %dmV (set level=0 to force shutdown)",
+ htc_batt_info.force_shutdown_batt_vol);
+ htc_batt_info.rep.level = 0;
+ gs_update_PSY = true;
+ wake_lock(&htc_batt_info.batt_shutdown_lock);
+ }
/* STEP 8: Update limited charge
Dou to some returned device is cause by limit charge,
@@ -2169,6 +2177,12 @@ void htc_battery_info_update(enum power_supply_property prop, int intval)
htc_batt_schedule_batt_info_update();
}
break;
+ case POWER_SUPPLY_PROP_CRITICAL_SHUTDOWN:
+ if (g_latest_chg_src == POWER_SUPPLY_TYPE_UNKNOWN) {
+ g_critical_shutdown = true;
+ htc_batt_schedule_batt_info_update();
+ }
+ break;
default:
break;
}
@@ -3062,6 +3076,7 @@ static int __init htc_battery_init(void)
wake_lock_init(&htc_batt_timer.battery_lock, WAKE_LOCK_SUSPEND, "htc_battery");
wake_lock_init(&htc_batt_info.charger_exist_lock, WAKE_LOCK_SUSPEND,"charger_exist_lock");
+ wake_lock_init(&htc_batt_info.batt_shutdown_lock, WAKE_LOCK_SUSPEND, "batt_shutdown");
/* init battery parameters. */
htc_batt_info.rep.batt_vol = 4000;
@@ -3082,6 +3097,7 @@ static int __init htc_battery_init(void)
htc_batt_info.smooth_chg_full_delay_min = 3;
htc_batt_info.decreased_batt_level_check = 1;
htc_batt_info.critical_low_voltage_mv = 3200;
+ htc_batt_info.force_shutdown_batt_vol = 3050;
htc_batt_info.batt_full_voltage_mv = 4350;
htc_batt_info.batt_full_current_ma = 300;
htc_batt_info.batt_eoc_current_ma = 50;
diff --git a/drivers/power/qpnp-fg.c b/drivers/power/qpnp-fg.c
index 308dffa6c1b8..a7842de7b20b 100644
--- a/drivers/power/qpnp-fg.c
+++ b/drivers/power/qpnp-fg.c
@@ -332,6 +332,7 @@ static int fg_reset_on_lockup;
#ifdef CONFIG_HTC_BATT
/* Enable batterydebug log*/
bool g_fg_flag_enable_batt_debug_log = false;
+int g_empty_soc_irq_count = 0;
#endif
static int fg_sense_type = -EINVAL;
@@ -636,6 +637,8 @@ struct fg_chip {
struct fg_wakeup_source sanity_wakeup_source;
u8 last_beat_count;
#ifdef CONFIG_HTC_BATT
+ struct delayed_work clear_empty_soc_irq_counter;
+ struct delayed_work rearm_empty_soc_irq_work;
int batt_full_charge_criteria_ma;
int batt_fcc_ma;
int batt_capacity_mah;
@@ -4904,6 +4907,9 @@ static irqreturn_t fg_jeita_soft_hot_irq_handler(int irq, void *_chip)
bool batt_warm;
union power_supply_propval val = {0, };
+ if (!is_charger_available(chip))
+ return IRQ_HANDLED;
+
rc = fg_read(chip, &regval, INT_RT_STS(chip->batt_base), 1);
if (rc) {
pr_err("spmi read failed: addr=%03X, rc=%d\n",
@@ -4947,6 +4953,9 @@ static irqreturn_t fg_jeita_soft_cold_irq_handler(int irq, void *_chip)
bool batt_cool;
union power_supply_propval val = {0, };
+ if (!is_charger_available(chip))
+ return IRQ_HANDLED;
+
rc = fg_read(chip, &regval, INT_RT_STS(chip->batt_base), 1);
if (rc) {
pr_err("spmi read failed: addr=%03X, rc=%d\n",
@@ -5194,6 +5203,70 @@ static irqreturn_t fg_soc_irq_handler(int irq, void *_chip)
return IRQ_HANDLED;
}
+#ifdef CONFIG_HTC_BATT
+#define CLEAR_EMPTY_SOC_IRQ_COUNTER_MS 30000
+#define REARM_EMPTY_SOC_IRQ_MS 1000
+#define FG_ALG_SYSCTL_1 0x4B0
+#define ALERT_CFG_OFFSET 3
+#define IRQ_USE_VOLTAGE_HYST_BIT BIT(0)
+#define EMPTY_FROM_VOLTAGE_BIT BIT(1)
+#define EMPTY_FROM_SOC_BIT BIT(2)
+#define EMPTY_SOC_IRQ_MASK (IRQ_USE_VOLTAGE_HYST_BIT | \
+ EMPTY_FROM_SOC_BIT | \
+ EMPTY_FROM_VOLTAGE_BIT)
+
+static void clear_empty_soc_irq_counter(struct work_struct *work)
+{
+ pr_info("clear empty_soc irq counter\n");
+ g_empty_soc_irq_count = 0;
+}
+
+static void rearm_empty_soc_irq_work(struct work_struct *work)
+{
+ int rc;
+ if (!the_chip) {
+ pr_err("[Battery_FDA] Called before init\n");
+ return;
+ }
+
+ /*
+ * Clear bits 0-2 in 0x4B3 and set them again to make empty_soc irq
+ * trigger again.
+ */
+ rc = fg_mem_masked_write(the_chip, FG_ALG_SYSCTL_1, EMPTY_SOC_IRQ_MASK,
+ 0, ALERT_CFG_OFFSET);
+ if (rc) {
+ pr_err("failed to write to 0x4B3 rc=%d\n", rc);
+ return;
+ }
+
+ /* Wait for a FG cycle before enabling empty soc irq configuration */
+ msleep(FG_CYCLE_MS);
+
+ rc = fg_mem_masked_write(the_chip, FG_ALG_SYSCTL_1, EMPTY_SOC_IRQ_MASK,
+ EMPTY_SOC_IRQ_MASK, ALERT_CFG_OFFSET);
+ if (rc) {
+ pr_err("failed to write to 0x4B3 rc=%d\n", rc);
+ return;
+ }
+}
+
+#define CRITICAL_SHUTDOWN_COUNT 3
+static void rearm_empty_soc_irq(void)
+{
+ if (!the_chip) {
+ pr_err("[Battery_FDA] Called before init\n");
+ return;
+ }
+
+ if (delayed_work_pending(&the_chip->rearm_empty_soc_irq_work))
+ cancel_delayed_work_sync(&the_chip->rearm_empty_soc_irq_work);
+ if (g_empty_soc_irq_count < CRITICAL_SHUTDOWN_COUNT)
+ schedule_delayed_work(&the_chip->rearm_empty_soc_irq_work,
+ REARM_EMPTY_SOC_IRQ_MS);
+}
+#endif /* CONFIG_HTC_BATT */
+
static irqreturn_t fg_empty_soc_irq_handler(int irq, void *_chip)
{
struct fg_chip *chip = _chip;
@@ -5207,8 +5280,10 @@ static irqreturn_t fg_empty_soc_irq_handler(int irq, void *_chip)
goto done;
}
+#ifndef CONFIG_HTC_BATT
if (fg_debug_mask & FG_IRQS)
pr_info("triggered 0x%x\n", soc_rt_sts);
+#endif
if (fg_is_batt_empty(chip)) {
fg_stay_awake(&chip->empty_check_wakeup_source);
schedule_delayed_work(&chip->check_empty_work,
@@ -5217,6 +5292,26 @@ static irqreturn_t fg_empty_soc_irq_handler(int irq, void *_chip)
chip->soc_empty = false;
}
+#ifdef CONFIG_HTC_BATT
+ /* Clear critical shutdown count after 30secs */
+ if (!delayed_work_pending(&chip->clear_empty_soc_irq_counter))
+ schedule_delayed_work(&chip->clear_empty_soc_irq_counter,
+ CLEAR_EMPTY_SOC_IRQ_COUNTER_MS);
+
+ if (g_empty_soc_irq_count < CRITICAL_SHUTDOWN_COUNT
+ && fg_is_batt_empty(chip))
+ g_empty_soc_irq_count++;
+
+ pr_info("triggered=0x%x, vbatt=%dmV, irq_count:%d, is_batt_empty=%d\n",
+ soc_rt_sts, get_sram_prop_now(chip, FG_DATA_VOLTAGE) / 1000,
+ g_empty_soc_irq_count, fg_is_batt_empty(chip));
+ if (g_empty_soc_irq_count >= CRITICAL_SHUTDOWN_COUNT)
+ htc_battery_info_update(POWER_SUPPLY_PROP_CRITICAL_SHUTDOWN,
+ get_sram_prop_now(chip, FG_DATA_VOLTAGE) / 1000);
+
+ rearm_empty_soc_irq();
+#endif /* CONFIG_HTC_BATT */
+
done:
return IRQ_HANDLED;
}
@@ -6703,7 +6798,9 @@ static int update_irq_volt_empty(struct fg_chip *chip)
data = (u8)VOLT_UV_TO_VOLTCMP8(volt_mv * 1000);
+#ifndef CONFIG_HTC_BATT
if (fg_debug_mask & FG_STATUS)
+#endif /* CONFIG_HTC_BATT */
pr_info("voltage = %d, converted_raw = %04x\n", volt_mv, data);
return fg_mem_write(chip, &data,
settings[FG_MEM_IRQ_VOLT_EMPTY].address, 1,
@@ -8612,6 +8709,10 @@ static int fg_probe(struct spmi_device *spmi)
mutex_init(&chip->rslow_comp.lock);
mutex_init(&chip->sysfs_restart_lock);
mutex_init(&chip->ima_recovery_lock);
+#ifdef CONFIG_HTC_BATT
+ INIT_DELAYED_WORK(&chip->clear_empty_soc_irq_counter, clear_empty_soc_irq_counter);
+ INIT_DELAYED_WORK(&chip->rearm_empty_soc_irq_work, rearm_empty_soc_irq_work);
+#endif /* CONFIG_HTC_BATT */
INIT_DELAYED_WORK(&chip->update_jeita_setting, update_jeita_setting);
INIT_DELAYED_WORK(&chip->update_sram_data, update_sram_data_work);
INIT_DELAYED_WORK(&chip->update_temp_work, update_temp_data);
diff --git a/drivers/power/qpnp-smbcharger.c b/drivers/power/qpnp-smbcharger.c
index df37a4603a8c..702977bea3db 100644
--- a/drivers/power/qpnp-smbcharger.c
+++ b/drivers/power/qpnp-smbcharger.c
@@ -306,6 +306,7 @@ struct smbchg_chip {
#define HARD_TEMP_MASK SMB_MASK(6, 5)
#define SOFT_TEMP_MASK SMB_MASK(3, 0)
#define SKIP_HARD_LIMIT_CHECK_LEVEL 70
+#define SKIP_HARD_LIMIT_CHECK_VBAT_MV 3900
static struct smbchg_chip *the_chip;
static bool g_is_batt_full_eoc_stop = false;
static void handle_usb_insertion(struct smbchg_chip *chip);
@@ -7640,32 +7641,27 @@ void check_charger_ability(int aicl_level)
{
union power_supply_propval prop = {0,};
int rc, usb_supply_type;
- u8 reg;
- int level;
+ int level = 0, vbat_mv = 0;
if (!the_chip) {
pr_err("called before init\n");
return;
}
+ vbat_mv = get_prop_batt_voltage_now(the_chip)/1000;
level = get_prop_batt_capacity(the_chip);
rc = the_chip->usb_psy->get_property(the_chip->usb_psy,
POWER_SUPPLY_PROP_TYPE, &prop);
usb_supply_type = prop.intval;
- pr_smb(PR_STATUS, "CHG_TYPE is %d, AICL is %d, level is %d\n",
- usb_supply_type, aicl_level, level);
+ pr_smb(PR_STATUS, "CHG_TYPE = %d, AICL = %d, level = %d, vbat_mv = %d, hard_limit = %d\n",
+ usb_supply_type, aicl_level, level, vbat_mv, is_smbchg_hard_limit(the_chip));
if (usb_supply_type != POWER_SUPPLY_TYPE_USB_DCP &&
usb_supply_type != POWER_SUPPLY_TYPE_USB_TYPE_C)
return;
- //checking for hard limit behavior
- rc = smbchg_read(the_chip, &reg,
- the_chip->chgr_base + FV_STS, 1);
- if (rc)
- pr_err("Failed to read FV state rc=%d\n", rc);
- pr_smb(PR_STATUS, "FV status = %02x, Hard Limit = %d\n", reg, ((reg & FV_AICL_STS_BIT)!=0));
- if (((reg & FV_AICL_STS_BIT) == 0) && (level > SKIP_HARD_LIMIT_CHECK_LEVEL)) {
+ if ((!is_smbchg_hard_limit(the_chip)) &&
+ ((level > SKIP_HARD_LIMIT_CHECK_LEVEL) || (vbat_mv > SKIP_HARD_LIMIT_CHECK_VBAT_MV))) {
if (aicl_level > USB_MA_2000) {
rc = vote(the_chip->usb_icl_votable, PSY_ICL_VOTER,
true, USB_MA_2000);
diff --git a/drivers/soc/qcom/pil-q6v5-mss.c b/drivers/soc/qcom/pil-q6v5-mss.c
index 8e1a4c714771..9cef023dd919 100644
--- a/drivers/soc/qcom/pil-q6v5-mss.c
+++ b/drivers/soc/qcom/pil-q6v5-mss.c
@@ -39,16 +39,16 @@
#define MAX_VDD_MSS_UV 1150000
#define PROXY_TIMEOUT_MS 10000
-#define MAX_SSR_REASON_LEN 81U
#define STOP_ACK_TIMEOUT_MS 1000
#define subsys_to_drv(d) container_of(d, struct modem_data, subsys_desc)
-static void log_modem_sfr(void)
+static void log_modem_sfr(struct modem_data *drv)
{
u32 size;
- char *smem_reason, reason[MAX_SSR_REASON_LEN];
+ char *smem_reason, *reason;
+ reason = drv->subsys_desc.last_crash_reason;
smem_reason = smem_get_entry_no_rlock(SMEM_SSR_REASON_MSS0, &size, 0,
SMEM_ANY_HOST_FLAG);
if (!smem_reason || !size) {
@@ -69,7 +69,7 @@ static void log_modem_sfr(void)
static void restart_modem(struct modem_data *drv)
{
- log_modem_sfr();
+ log_modem_sfr(drv);
drv->ignore_errors = true;
subsystem_restart_dev(drv->subsys);
}
diff --git a/drivers/soc/qcom/subsys-pil-tz.c b/drivers/soc/qcom/subsys-pil-tz.c
index f98cfbc8d947..d1d6608ddb2a 100644
--- a/drivers/soc/qcom/subsys-pil-tz.c
+++ b/drivers/soc/qcom/subsys-pil-tz.c
@@ -36,7 +36,6 @@
#define XO_FREQ 19200000
#define PROXY_TIMEOUT_MS 10000
-#define MAX_SSR_REASON_LEN 81U
#define STOP_ACK_TIMEOUT_MS 1000
#define CRASH_STOP_ACK_TO_MS 200
@@ -776,15 +775,16 @@ static struct pil_reset_ops pil_ops_trusted = {
.proxy_unvote = pil_remove_proxy_vote,
};
-static void log_failure_reason(const struct pil_tz_data *d)
+static void log_failure_reason(struct pil_tz_data *d)
{
u32 size;
- char *smem_reason, reason[MAX_SSR_REASON_LEN];
+ char *smem_reason, *reason;
const char *name = d->subsys_desc.name;
if (d->smem_id == -1)
return;
+ reason = d->subsys_desc.last_crash_reason;
smem_reason = smem_get_entry_no_rlock(d->smem_id, &size, 0,
SMEM_ANY_HOST_FLAG);
if (!smem_reason || !size) {
diff --git a/drivers/soc/qcom/subsystem_restart.c b/drivers/soc/qcom/subsystem_restart.c
index 016e7b89be87..20b417555e19 100644
--- a/drivers/soc/qcom/subsystem_restart.c
+++ b/drivers/soc/qcom/subsystem_restart.c
@@ -184,6 +184,8 @@ struct subsys_device {
struct list_head list;
};
+static int is_ramdump_enabled(struct subsys_device *dev);
+
static struct subsys_device *to_subsys(struct device *d)
{
return container_of(d, struct subsys_device, dev);
@@ -223,6 +225,15 @@ static ssize_t crash_count_show(struct device *dev,
return snprintf(buf, PAGE_SIZE, "%d\n", to_subsys(dev)->crash_count);
}
+static ssize_t crash_reason_show(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ if(is_ramdump_enabled(to_subsys(dev)))
+ return snprintf(buf, PAGE_SIZE, "%s\n", to_subsys(dev)->desc->last_crash_reason);
+
+ return snprintf(buf, PAGE_SIZE, "\n");
+}
+
static ssize_t
restart_level_show(struct device *dev, struct device_attribute *attr, char *buf)
{
@@ -347,6 +358,7 @@ static struct device_attribute subsys_attrs[] = {
__ATTR_RO(name),
__ATTR_RO(state),
__ATTR_RO(crash_count),
+ __ATTR_RO(crash_reason),
__ATTR(restart_level, 0644, restart_level_show, restart_level_store),
__ATTR(firmware_name, 0644, firmware_name_show, firmware_name_store),
__ATTR(system_debug, 0644, system_debug_show, system_debug_store),
diff --git a/drivers/staging/qcacld-2.0/CORE/HDD/inc/wlan_hdd_cfg.h b/drivers/staging/qcacld-2.0/CORE/HDD/inc/wlan_hdd_cfg.h
index 1a925415b84d..4df26571e0e1 100644
--- a/drivers/staging/qcacld-2.0/CORE/HDD/inc/wlan_hdd_cfg.h
+++ b/drivers/staging/qcacld-2.0/CORE/HDD/inc/wlan_hdd_cfg.h
@@ -2659,12 +2659,16 @@ This feature requires the dependent cfg.ini "gRoamPrefer5GHz" set to 1 */
* 0x1 - Enable mgmt pkt logs (no probe req/rsp).
* 0x2 - Enable EAPOL pkt logs.
* 0x4 - Enable DHCP pkt logs.
+ * 0x8 - Enable mgmt. action pkt logs.
+ * 0x10 - Enable ARP packet logs.
+ * 0x20 - Enable ICMPv6 NS packet logs.
+ * 0x40 - Enable ICMPv6 NA packet logs.
* 0x0 - Disable all the above connection related logs.
*/
#define CFG_ENABLE_DEBUG_CONNECT_ISSUE "gEnableDebugLog"
#define CFG_ENABLE_DEBUG_CONNECT_ISSUE_MIN (0)
#define CFG_ENABLE_DEBUG_CONNECT_ISSUE_MAX (0xFF)
-#define CFG_ENABLE_DEBUG_CONNECT_ISSUE_DEFAULT (6)
+#define CFG_ENABLE_DEBUG_CONNECT_ISSUE_DEFAULT (0x40 | 0x20 | 0x10 | 0x04 | 0x02)
/*
* RX packet handling options
diff --git a/drivers/staging/qcacld-2.0/CORE/HDD/src/wlan_hdd_cfg80211.c b/drivers/staging/qcacld-2.0/CORE/HDD/src/wlan_hdd_cfg80211.c
index 0387b0dc11d5..e45b70456011 100644
--- a/drivers/staging/qcacld-2.0/CORE/HDD/src/wlan_hdd_cfg80211.c
+++ b/drivers/staging/qcacld-2.0/CORE/HDD/src/wlan_hdd_cfg80211.c
@@ -18861,6 +18861,10 @@ static int __wlan_hdd_cfg80211_disconnect( struct wiphy *wiphy,
reasonCode = pHddCtx->cfg_ini->gEnableDeauthToDisassocMap ?
eCSR_DISCONNECT_REASON_STA_HAS_LEFT :
eCSR_DISCONNECT_REASON_DEAUTH;
+ vos_flush_logs(WLAN_LOG_TYPE_NON_FATAL,
+ WLAN_LOG_INDICATOR_FRAMEWORK,
+ WLAN_LOG_REASON_CODE_FRAMEWORK,
+ DUMP_PACKET_TRACE);
break;
case WLAN_REASON_DISASSOC_STA_HAS_LEFT:
reasonCode = eCSR_DISCONNECT_REASON_STA_HAS_LEFT;
@@ -23169,7 +23173,7 @@ int __wlan_hdd_cfg80211_resume_wlan(struct wiphy *wiphy)
* results in app's is in suspended state and not able to
* process the connect request to AP
*/
- hdd_prevent_suspend_timeout(2000,
+ hdd_prevent_suspend_timeout(1000,
WIFI_POWER_EVENT_WAKELOCK_RESUME_WLAN);
cfg80211_sched_scan_results(pHddCtx->wiphy);
}
diff --git a/drivers/staging/qcacld-2.0/CORE/HDD/src/wlan_hdd_softap_tx_rx.c b/drivers/staging/qcacld-2.0/CORE/HDD/src/wlan_hdd_softap_tx_rx.c
index 45d9f20be0dd..e927073e3318 100644
--- a/drivers/staging/qcacld-2.0/CORE/HDD/src/wlan_hdd_softap_tx_rx.c
+++ b/drivers/staging/qcacld-2.0/CORE/HDD/src/wlan_hdd_softap_tx_rx.c
@@ -365,13 +365,24 @@ int __hdd_softap_hard_start_xmit(struct sk_buff *skb, struct net_device *dev)
/* Proto Trace enabled */
proto_type = vos_pkt_get_proto_type(skb,
hddCtxt->cfg_ini->gEnableDebugLog, 0);
- if (VOS_PKT_TRAC_TYPE_EAPOL & proto_type)
- {
+ switch (proto_type) {
+ case VOS_PKT_TRAC_TYPE_EAPOL:
vos_pkt_trace_buf_update("HA:T:EPL");
- }
- else if (VOS_PKT_TRAC_TYPE_DHCP & proto_type)
- {
+ break;
+ case VOS_PKT_TRAC_TYPE_DHCP:
hdd_dhcp_pkt_trace_buf_update(skb, TX_PATH, AP);
+ break;
+ case VOS_PKT_TRAC_TYPE_ARP:
+ vos_pkt_trace_buf_update("HA:T:ARP");
+ break;
+ case VOS_PKT_TRAC_TYPE_NS:
+ vos_pkt_trace_buf_update("HA:T:NS");
+ break;
+ case VOS_PKT_TRAC_TYPE_NA:
+ vos_pkt_trace_buf_update("HA:T:NA");
+ break;
+ default:
+ break;
}
}
#endif /* QCA_PKT_PROTO_TRACE */
@@ -842,10 +853,25 @@ VOS_STATUS hdd_softap_rx_packet_cbk(v_VOID_t *vosContext,
(pHddCtx->cfg_ini->gEnableDebugLog & VOS_PKT_TRAC_TYPE_DHCP)) {
proto_type = vos_pkt_get_proto_type(skb,
pHddCtx->cfg_ini->gEnableDebugLog, 0);
- if (VOS_PKT_TRAC_TYPE_EAPOL & proto_type)
- vos_pkt_trace_buf_update("HA:R:EPL");
- else if (VOS_PKT_TRAC_TYPE_DHCP & proto_type)
- hdd_dhcp_pkt_trace_buf_update(skb, RX_PATH, AP);
+ switch (proto_type) {
+ case VOS_PKT_TRAC_TYPE_EAPOL:
+ vos_pkt_trace_buf_update("HA:R:EPL");
+ break;
+ case VOS_PKT_TRAC_TYPE_DHCP:
+ hdd_dhcp_pkt_trace_buf_update(skb, RX_PATH, AP);
+ break;
+ case VOS_PKT_TRAC_TYPE_ARP:
+ vos_pkt_trace_buf_update("HA:R:ARP");
+ break;
+ case VOS_PKT_TRAC_TYPE_NS:
+ vos_pkt_trace_buf_update("HA:R:NS");
+ break;
+ case VOS_PKT_TRAC_TYPE_NA:
+ vos_pkt_trace_buf_update("HA:R:NA");
+ break;
+ default:
+ break;
+ }
}
#endif /* QCA_PKT_PROTO_TRACE */
diff --git a/drivers/staging/qcacld-2.0/CORE/HDD/src/wlan_hdd_tx_rx.c b/drivers/staging/qcacld-2.0/CORE/HDD/src/wlan_hdd_tx_rx.c
index 382bb8f6a460..507170a10072 100644
--- a/drivers/staging/qcacld-2.0/CORE/HDD/src/wlan_hdd_tx_rx.c
+++ b/drivers/staging/qcacld-2.0/CORE/HDD/src/wlan_hdd_tx_rx.c
@@ -611,13 +611,24 @@ int __hdd_hard_start_xmit(struct sk_buff *skb, struct net_device *dev)
{
proto_type = vos_pkt_get_proto_type(skb,
hddCtxt->cfg_ini->gEnableDebugLog, 0);
- if (VOS_PKT_TRAC_TYPE_EAPOL & proto_type)
- {
+ switch (proto_type) {
+ case VOS_PKT_TRAC_TYPE_EAPOL:
vos_pkt_trace_buf_update("ST:T:EPL");
- }
- else if (VOS_PKT_TRAC_TYPE_DHCP & proto_type)
- {
+ break;
+ case VOS_PKT_TRAC_TYPE_DHCP:
hdd_dhcp_pkt_trace_buf_update(skb, TX_PATH, STA);
+ break;
+ case VOS_PKT_TRAC_TYPE_ARP:
+ vos_pkt_trace_buf_update("ST:T:ARP");
+ break;
+ case VOS_PKT_TRAC_TYPE_NS:
+ vos_pkt_trace_buf_update("ST:T:NS");
+ break;
+ case VOS_PKT_TRAC_TYPE_NA:
+ vos_pkt_trace_buf_update("ST:T:NA");
+ break;
+ default:
+ break;
}
}
#endif /* QCA_PKT_PROTO_TRACE */
@@ -1214,10 +1225,25 @@ VOS_STATUS hdd_rx_packet_cbk(v_VOID_t *vosContext,
(pHddCtx->cfg_ini->gEnableDebugLog & VOS_PKT_TRAC_TYPE_DHCP)) {
proto_type = vos_pkt_get_proto_type(skb,
pHddCtx->cfg_ini->gEnableDebugLog, 0);
- if (VOS_PKT_TRAC_TYPE_EAPOL & proto_type)
- vos_pkt_trace_buf_update("ST:R:EPL");
- else if (VOS_PKT_TRAC_TYPE_DHCP & proto_type)
- hdd_dhcp_pkt_trace_buf_update(skb, RX_PATH, STA);
+ switch (proto_type) {
+ case VOS_PKT_TRAC_TYPE_EAPOL:
+ vos_pkt_trace_buf_update("ST:R:EPL");
+ break;
+ case VOS_PKT_TRAC_TYPE_DHCP:
+ hdd_dhcp_pkt_trace_buf_update(skb, RX_PATH, STA);
+ break;
+ case VOS_PKT_TRAC_TYPE_ARP:
+ vos_pkt_trace_buf_update("ST:R:ARP");
+ break;
+ case VOS_PKT_TRAC_TYPE_NS:
+ vos_pkt_trace_buf_update("ST:R:NS");
+ break;
+ case VOS_PKT_TRAC_TYPE_NA:
+ vos_pkt_trace_buf_update("ST:R:NA");
+ break;
+ default:
+ break;
+ }
}
#endif /* QCA_PKT_PROTO_TRACE */
diff --git a/drivers/staging/qcacld-2.0/CORE/MAC/inc/qwlan_version.h b/drivers/staging/qcacld-2.0/CORE/MAC/inc/qwlan_version.h
index c59d6765883c..8011c2828f8c 100644
--- a/drivers/staging/qcacld-2.0/CORE/MAC/inc/qwlan_version.h
+++ b/drivers/staging/qcacld-2.0/CORE/MAC/inc/qwlan_version.h
@@ -44,7 +44,7 @@ BRIEF DESCRIPTION:
#define QWLAN_VERSION_EXTRA ""
#define QWLAN_VERSION_BUILD 26
-#define QWLAN_VERSIONSTR "4.4.25.026"
+#define QWLAN_VERSIONSTR "4.4.25.027"
#define AR6320_REV1_VERSION 0x5000000
diff --git a/drivers/staging/qcacld-2.0/CORE/MAC/src/pe/lim/limFT.c b/drivers/staging/qcacld-2.0/CORE/MAC/src/pe/lim/limFT.c
index 550e36ce48bb..e69d6b5ee7b2 100644
--- a/drivers/staging/qcacld-2.0/CORE/MAC/src/pe/lim/limFT.c
+++ b/drivers/staging/qcacld-2.0/CORE/MAC/src/pe/lim/limFT.c
@@ -991,14 +991,14 @@ void limFillFTSession(tpAniSirGlobal pMac,
#ifdef WLAN_FEATURE_11W
pftSessionEntry->limRmfEnabled = psessionEntry->limRmfEnabled;
- if (psessionEntry->limRmfEnabled) {
- psessionEntry->pmfComebackTimerInfo.pMac = pMac;
- psessionEntry->pmfComebackTimerInfo.sessionID =
+ if (pftSessionEntry->limRmfEnabled) {
+ pftSessionEntry->pmfComebackTimerInfo.pMac = pMac;
+ pftSessionEntry->pmfComebackTimerInfo.sessionID =
psessionEntry->smeSessionId;
- vosStatus = vos_timer_init(&psessionEntry->pmfComebackTimer,
+ vosStatus = vos_timer_init(&pftSessionEntry->pmfComebackTimer,
VOS_TIMER_TYPE_SW,
limPmfComebackTimerCallback,
- (void *)&psessionEntry->pmfComebackTimerInfo);
+ (void *)&pftSessionEntry->pmfComebackTimerInfo);
if (VOS_STATUS_SUCCESS != vosStatus) {
limLog(pMac, LOGP,
FL("cannot init pmf comeback timer."));
diff --git a/drivers/staging/qcacld-2.0/CORE/MAC/src/pe/lim/limLinkMonitoringAlgo.c b/drivers/staging/qcacld-2.0/CORE/MAC/src/pe/lim/limLinkMonitoringAlgo.c
index 2c1581767ce9..b9811a31fb17 100644
--- a/drivers/staging/qcacld-2.0/CORE/MAC/src/pe/lim/limLinkMonitoringAlgo.c
+++ b/drivers/staging/qcacld-2.0/CORE/MAC/src/pe/lim/limLinkMonitoringAlgo.c
@@ -462,11 +462,19 @@ void limHandleHeartBeatFailure(tpAniSirGlobal pMac,tpPESession psessionEntry)
{
if (!pMac->sys.gSysEnableLinkMonitorMode)
return;
+ /* Ignore HB if channel switch is in progress */
+ if (psessionEntry->gLimSpecMgmt.dot11hChanSwState ==
+ eLIM_11H_CHANSW_RUNNING) {
+ limLog(pMac, LOGE,
+ FL("Ignore Heartbeat failure as Channel switch is in progress"));
+ pMac->pmm.inMissedBeaconScenario = false;
+ return;
+ }
/**
* Beacon frame not received within heartbeat timeout.
*/
- PELOGW(limLog(pMac, LOGW, FL("Heartbeat Failure"));)
+ limLog(pMac, LOGW, FL("Heartbeat Failure"));
pMac->lim.gLimHBfailureCntInLinkEstState++;
/**
diff --git a/drivers/staging/qcacld-2.0/CORE/MAC/src/pe/lim/limUtils.c b/drivers/staging/qcacld-2.0/CORE/MAC/src/pe/lim/limUtils.c
index 7a40b74cee40..c907ef43c337 100644
--- a/drivers/staging/qcacld-2.0/CORE/MAC/src/pe/lim/limUtils.c
+++ b/drivers/staging/qcacld-2.0/CORE/MAC/src/pe/lim/limUtils.c
@@ -2092,9 +2092,10 @@ void limProcessChannelSwitchTimeout(tpAniSirGlobal pMac)
tANI_U8 channel; // This is received and stored from channelSwitch Action frame
tANI_U8 isSessionPowerActive = false;
- if((psessionEntry = peFindSessionBySessionId(pMac, pMac->lim.limTimers.gLimChannelSwitchTimer.sessionId))== NULL)
- {
- limLog(pMac, LOGP,FL("Session Does not exist for given sessionID"));
+ psessionEntry = peFindSessionBySessionId(pMac,
+ pMac->lim.limTimers.gLimChannelSwitchTimer.sessionId);
+ if (!psessionEntry) {
+ limLog(pMac, LOGW, FL("Session Does not exist for given sessionID"));
return;
}
@@ -2104,6 +2105,13 @@ void limProcessChannelSwitchTimeout(tpAniSirGlobal pMac)
GET_LIM_SYSTEM_ROLE(psessionEntry));)
return;
}
+ if (psessionEntry->gLimSpecMgmt.dot11hChanSwState !=
+ eLIM_11H_CHANSW_RUNNING) {
+ limLog(pMac, LOGW,
+ FL("Channel switch timer should not have been running in state %d"),
+ psessionEntry->gLimSpecMgmt.dot11hChanSwState);
+ return;
+ }
if(pMac->psOffloadEnabled)
{
@@ -2113,7 +2121,6 @@ void limProcessChannelSwitchTimeout(tpAniSirGlobal pMac)
{
isSessionPowerActive = limIsSystemInActiveState(pMac);
}
-
channel = psessionEntry->gLimChannelSwitch.primaryChannel;
/*
@@ -2173,13 +2180,19 @@ void limProcessChannelSwitchTimeout(tpAniSirGlobal pMac)
return;
}
- /* If the channel-list that AP is asking us to switch is invalid,
+ /*
+ * If the channel-list that AP is asking us to switch is invalid,
* then we cannot switch the channel. Just disassociate from AP.
* We will find a better AP !!!
*/
- limTearDownLinkWithAp(pMac,
+ if ((psessionEntry->limMlmState == eLIM_MLM_LINK_ESTABLISHED_STATE) &&
+ (psessionEntry->limSmeState != eLIM_SME_WT_DISASSOC_STATE)&&
+ (psessionEntry->limSmeState != eLIM_SME_WT_DEAUTH_STATE)) {
+ limLog(pMac, LOGE, FL("Invalid channel!! Disconnect.."));
+ limTearDownLinkWithAp(pMac,
pMac->lim.limTimers.gLimChannelSwitchTimer.sessionId,
eSIR_MAC_UNSPEC_FAILURE_REASON);
+ }
return;
}
limCovertChannelScanType(pMac, psessionEntry->currentOperChannel, false);
diff --git a/drivers/staging/qcacld-2.0/CORE/SAP/src/sapFsm.c b/drivers/staging/qcacld-2.0/CORE/SAP/src/sapFsm.c
index 715a0c9faabc..0bbe20657493 100644
--- a/drivers/staging/qcacld-2.0/CORE/SAP/src/sapFsm.c
+++ b/drivers/staging/qcacld-2.0/CORE/SAP/src/sapFsm.c
@@ -1946,7 +1946,7 @@ v_BOOL_t
sapDfsIsChannelInNolList(ptSapContext sapContext, v_U8_t channelNumber,
ePhyChanBondState chanBondState)
{
- int i, j;
+ int i = 0, j;
v_U64_t timeElapsedSinceLastRadar,timeWhenRadarFound,currentTime = 0;
v_U64_t max_jiffies;
tHalHandle hHal = VOS_GET_HAL_CB(sapContext->pvosGCtx);
diff --git a/drivers/staging/qcacld-2.0/CORE/SERVICES/COMMON/adf/adf_nbuf.c b/drivers/staging/qcacld-2.0/CORE/SERVICES/COMMON/adf/adf_nbuf.c
index 53212933a92a..dc0ef3185da2 100644
--- a/drivers/staging/qcacld-2.0/CORE/SERVICES/COMMON/adf/adf_nbuf.c
+++ b/drivers/staging/qcacld-2.0/CORE/SERVICES/COMMON/adf/adf_nbuf.c
@@ -747,6 +747,12 @@ __adf_nbuf_data_get_icmpv6_subtype(uint8_t *data)
case ICMPV6_RESPONSE:
proto_subtype = ADF_PROTO_ICMPV6_RES;
break;
+ case ICMPV6_NS:
+ proto_subtype = ADF_PROTO_ICMPV6_NS;
+ break;
+ case ICMPV6_NA:
+ proto_subtype = ADF_PROTO_ICMPV6_NA;
+ break;
default:
break;
}
@@ -1146,22 +1152,33 @@ __adf_nbuf_trace_update(struct sk_buff *buf, char *event_string)
NBUF_PKT_TRAC_MAX_STRING);
adf_os_mem_copy(string_buf,
event_string, adf_os_str_len(event_string));
- if (NBUF_PKT_TRAC_TYPE_EAPOL &
- adf_nbuf_trace_get_proto_type(buf)) {
+ switch (adf_nbuf_trace_get_proto_type(buf)) {
+ case NBUF_PKT_TRAC_TYPE_EAPOL:
adf_os_mem_copy(string_buf + adf_os_str_len(event_string),
- "EPL",
- NBUF_PKT_TRAC_PROTO_STRING);
- }
- else if (NBUF_PKT_TRAC_TYPE_DHCP &
- adf_nbuf_trace_get_proto_type(buf)) {
+ "EPL", NBUF_PKT_TRAC_PROTO_STRING);
+ break;
+ case NBUF_PKT_TRAC_TYPE_DHCP:
+ adf_os_mem_copy(string_buf + adf_os_str_len(event_string),
+ "DHC", NBUF_PKT_TRAC_PROTO_STRING);
+ break;
+ case NBUF_PKT_TRAC_TYPE_MGMT_ACTION:
+ adf_os_mem_copy(string_buf + adf_os_str_len(event_string),
+ "MACT", NBUF_PKT_TRAC_PROTO_STRING);
+ break;
+ case NBUF_PKT_TRAC_TYPE_ARP:
+ adf_os_mem_copy(string_buf + adf_os_str_len(event_string),
+ "ARP", NBUF_PKT_TRAC_PROTO_STRING);
+ break;
+ case NBUF_PKT_TRAC_TYPE_NS:
adf_os_mem_copy(string_buf + adf_os_str_len(event_string),
- "DHC",
- NBUF_PKT_TRAC_PROTO_STRING);
- } else if (NBUF_PKT_TRAC_TYPE_MGMT_ACTION &
- adf_nbuf_trace_get_proto_type(buf)) {
+ "NS", NBUF_PKT_TRAC_PROTO_STRING);
+ break;
+ case NBUF_PKT_TRAC_TYPE_NA:
adf_os_mem_copy(string_buf + adf_os_str_len(event_string),
- "MACT",
- NBUF_PKT_TRAC_PROTO_STRING);
+ "NA", NBUF_PKT_TRAC_PROTO_STRING);
+ break;
+ default:
+ break;
}
trace_update_cb(string_buf);
diff --git a/drivers/staging/qcacld-2.0/CORE/SERVICES/COMMON/adf/adf_nbuf.h b/drivers/staging/qcacld-2.0/CORE/SERVICES/COMMON/adf/adf_nbuf.h
index 904b299a0261..db809020f0a6 100644
--- a/drivers/staging/qcacld-2.0/CORE/SERVICES/COMMON/adf/adf_nbuf.h
+++ b/drivers/staging/qcacld-2.0/CORE/SERVICES/COMMON/adf/adf_nbuf.h
@@ -53,6 +53,8 @@
#define NBUF_PKT_TRAC_TYPE_DHCP 0x04
#define NBUF_PKT_TRAC_TYPE_MGMT_ACTION 0x08
#define NBUF_PKT_TRAC_TYPE_ARP 0x10
+#define NBUF_PKT_TRAC_TYPE_NS 0x20
+#define NBUF_PKT_TRAC_TYPE_NA 0x40
#define NBUF_PKT_TRAC_MAX_STRING 12
#define NBUF_PKT_TRAC_PROTO_STRING 4
#define ADF_NBUF_PKT_ERROR 1
@@ -174,7 +176,8 @@ struct mon_rx_status {
#define ICMPV6_SUBTYPE_OFFSET 54
#define ICMPV6_REQUEST 0x80
#define ICMPV6_RESPONSE 0x81
-
+#define ICMPV6_NS 0x87
+#define ICMPV6_NA 0x88
#define ADF_NBUF_IPA_CHECK_MASK 0x80000000
enum adf_proto_type {
@@ -205,6 +208,8 @@ enum adf_proto_subtype {
ADF_PROTO_ICMP_RES,
ADF_PROTO_ICMPV6_REQ,
ADF_PROTO_ICMPV6_RES,
+ ADF_PROTO_ICMPV6_NS,
+ ADF_PROTO_ICMPV6_NA,
ADF_PROTO_IPV4_UDP,
ADF_PROTO_IPV4_TCP,
ADF_PROTO_IPV6_UDP,
diff --git a/drivers/staging/qcacld-2.0/CORE/SERVICES/WMA/wma.c b/drivers/staging/qcacld-2.0/CORE/SERVICES/WMA/wma.c
index 55eb2c43e756..6369f17e08d3 100644
--- a/drivers/staging/qcacld-2.0/CORE/SERVICES/WMA/wma.c
+++ b/drivers/staging/qcacld-2.0/CORE/SERVICES/WMA/wma.c
@@ -2241,6 +2241,12 @@ static int wma_vdev_stop_ind(tp_wma_handle wma, u_int8_t *buf)
goto free_req_msg;
}
+ /* Clear arp and ns offload cache */
+ vos_mem_zero(&iface->ns_offload_req,
+ sizeof(iface->ns_offload_req));
+ vos_mem_zero(&iface->arp_offload_req,
+ sizeof(iface->arp_offload_req));
+
#ifdef QCA_IBSS_SUPPORT
if ( wma_is_vdev_in_ibss_mode(wma, resp_event->vdev_id))
wma_delete_all_ibss_peers(wma, resp_event->vdev_id);
@@ -21136,7 +21142,7 @@ static void wma_wow_parse_data_pkt_buffer(uint8_t *data,
WMA_LOGD("wow_buf_pkt_len: %u", buf_len);
if (buf_len >= ADF_NBUF_TRAC_IPV4_OFFSET)
- WMA_LOGE("Src_mac: " MAC_ADDRESS_STR " Dst_mac: " MAC_ADDRESS_STR,
+ WMA_LOGE("SA: " MAC_ADDRESS_STR " DA: " MAC_ADDRESS_STR,
MAC_ADDR_ARRAY(data + ADF_NBUF_SRC_MAC_OFFSET),
MAC_ADDR_ARRAY(data));
else
@@ -21148,7 +21154,7 @@ static void wma_wow_parse_data_pkt_buffer(uint8_t *data,
case ADF_PROTO_EAPOL_M2:
case ADF_PROTO_EAPOL_M3:
case ADF_PROTO_EAPOL_M4:
- WMA_LOGE("WOW Wakeup: %s rcvd",
+ WMA_LOGE("WOW %s rcvd",
wma_pkt_proto_subtype_to_string(proto_subtype));
if (buf_len >= WMA_EAPOL_INFO_GET_MIN_LEN) {
pkt_len = (uint16_t)(*(uint16_t *)(data +
@@ -21169,7 +21175,7 @@ static void wma_wow_parse_data_pkt_buffer(uint8_t *data,
case ADF_PROTO_DHCP_RELEASE:
case ADF_PROTO_DHCP_INFORM:
case ADF_PROTO_DHCP_DECLINE:
- WMA_LOGE("WOW Wakeup: %s rcvd",
+ WMA_LOGE("WOW %s rcvd",
wma_pkt_proto_subtype_to_string(proto_subtype));
if (buf_len >= WMA_DHCP_INFO_GET_MIN_LEN) {
pkt_len = (uint16_t)(*(uint16_t *)(data +
@@ -21184,13 +21190,13 @@ static void wma_wow_parse_data_pkt_buffer(uint8_t *data,
case ADF_PROTO_ARP_REQ:
case ADF_PROTO_ARP_RES:
- WMA_LOGE("WOW Wakeup: %s rcvd",
+ WMA_LOGE("WOW %s rcvd",
wma_pkt_proto_subtype_to_string(proto_subtype));
break;
case ADF_PROTO_ICMP_REQ:
case ADF_PROTO_ICMP_RES:
- WMA_LOGE("WOW Wakeup: %s rcvd",
+ WMA_LOGE("WOW %s rcvd",
wma_pkt_proto_subtype_to_string(proto_subtype));
if (buf_len >= WMA_IPV4_PKT_INFO_GET_MIN_LEN) {
pkt_len = (uint16_t)(*(uint16_t *)(data +
@@ -21205,14 +21211,14 @@ static void wma_wow_parse_data_pkt_buffer(uint8_t *data,
case ADF_PROTO_ICMPV6_REQ:
case ADF_PROTO_ICMPV6_RES:
- WMA_LOGE("WOW Wakeup: %s rcvd",
+ WMA_LOGE("WOW %s rcvd",
wma_pkt_proto_subtype_to_string(proto_subtype));
if (buf_len >= WMA_IPV6_PKT_INFO_GET_MIN_LEN) {
pkt_len = (uint16_t)(*(uint16_t *)(data +
IPV6_PKT_LEN_OFFSET));
seq_num = (uint16_t)(*(uint16_t *)(data +
ICMPV6_SEQ_NUM_OFFSET));
- WMA_LOGE("Pkt_len: %u, Seq_num: %u",
+ WMA_LOGE("len: %u, SN: %u",
adf_os_cpu_to_be16(pkt_len),
adf_os_cpu_to_be16(seq_num));
}
@@ -21220,7 +21226,7 @@ static void wma_wow_parse_data_pkt_buffer(uint8_t *data,
case ADF_PROTO_IPV4_UDP:
case ADF_PROTO_IPV4_TCP:
- WMA_LOGE("WOW Wakeup: %s rcvd",
+ WMA_LOGE("WOW %s rcvd",
wma_pkt_proto_subtype_to_string(proto_subtype));
if (buf_len >= WMA_IPV4_PKT_INFO_GET_MIN_LEN) {
pkt_len = (uint16_t)(*(uint16_t *)(data +
@@ -21229,15 +21235,14 @@ static void wma_wow_parse_data_pkt_buffer(uint8_t *data,
IPV4_SRC_PORT_OFFSET));
dst_port = (uint16_t)(*(uint16_t *)(data +
IPV4_DST_PORT_OFFSET));
- WMA_LOGE("Pkt_len: %u",
- adf_os_cpu_to_be16(pkt_len));
- WMA_LOGE("src_port: %u, dst_port: %u",
+ WMA_LOGE("len: %u sport: %u dport: %u",
+ adf_os_cpu_to_be16(pkt_len),
adf_os_cpu_to_be16(src_port),
adf_os_cpu_to_be16(dst_port));
if (proto_subtype == ADF_PROTO_IPV4_TCP) {
tcp_seq_num = (uint32_t)(*(uint32_t *)(data +
IPV4_TCP_SEQ_NUM_OFFSET));
- WMA_LOGE("TCP_seq_num: %u",
+ WMA_LOGD("TCP SN: %u",
adf_os_cpu_to_be32(tcp_seq_num));
}
}
@@ -21245,7 +21250,7 @@ static void wma_wow_parse_data_pkt_buffer(uint8_t *data,
case ADF_PROTO_IPV6_UDP:
case ADF_PROTO_IPV6_TCP:
- WMA_LOGE("WOW Wakeup: %s rcvd",
+ WMA_LOGE("WOW %s rcvd",
wma_pkt_proto_subtype_to_string(proto_subtype));
if (buf_len >= WMA_IPV6_PKT_INFO_GET_MIN_LEN) {
pkt_len = (uint16_t)(*(uint16_t *)(data +
@@ -21254,15 +21259,14 @@ static void wma_wow_parse_data_pkt_buffer(uint8_t *data,
IPV6_SRC_PORT_OFFSET));
dst_port = (uint16_t)(*(uint16_t *)(data +
IPV6_DST_PORT_OFFSET));
- WMA_LOGE("Pkt_len: %u",
- adf_os_cpu_to_be16(pkt_len));
- WMA_LOGE("src_port: %u, dst_port: %u",
+ WMA_LOGE("len: %u sport: %u dport: %u",
+ adf_os_cpu_to_be16(pkt_len),
adf_os_cpu_to_be16(src_port),
adf_os_cpu_to_be16(dst_port));
if (proto_subtype == ADF_PROTO_IPV6_TCP) {
tcp_seq_num = (uint32_t)(*(uint32_t *)(data +
IPV6_TCP_SEQ_NUM_OFFSET));
- WMA_LOGE("TCP_seq_num: %u",
+ WMA_LOGD("TCP SN: %u",
adf_os_cpu_to_be32(tcp_seq_num));
}
}
@@ -21270,8 +21274,7 @@ static void wma_wow_parse_data_pkt_buffer(uint8_t *data,
default:
end:
- WMA_LOGE("wow_buf_pkt_len: %u", buf_len);
- WMA_LOGE("Unknown Packet or Insufficient packet buffer");
+ WMA_LOGE("Unknown Packet or Insufficient packet buffer (len=%u)", buf_len);
break;
}
}
@@ -21407,12 +21410,10 @@ static int wma_wow_wakeup_host_event(void *handle, u_int8_t *event,
wake_info = param_buf->fixed_param;
- if ((wake_info->wake_reason != WOW_REASON_UNSPECIFIED) ||
- (wake_info->wake_reason == WOW_REASON_UNSPECIFIED &&
- !wmi_get_runtime_pm_inprogress(wma->wmi_handle)))
- WMA_LOGA("WOW wakeup host event received (reason: %s(%d)) for vdev %d",
- wma_wow_wake_reason_str(wake_info->wake_reason, wma),
+ if (!wmi_get_runtime_pm_inprogress(wma->wmi_handle))
+ WMA_LOGA("WOW (%d) %s vdev:%d",
wake_info->wake_reason,
+ wma_wow_wake_reason_str(wake_info->wake_reason, wma),
wake_info->vdev_id);
vos_event_set(&wma->wma_resume_event);
@@ -24604,8 +24605,12 @@ static VOS_STATUS wma_process_mcbc_set_filter_req(tp_wma_handle wma_handle,
uint8_t vdev_id = 0;
int i;
- if(mcbc_param->ulMulticastAddrCnt <= 0) {
- WMA_LOGW("Number of multicast addresses is 0");
+ if (mcbc_param->ulMulticastAddrCnt <= 0 ||
+ mcbc_param->ulMulticastAddrCnt >
+ CFG_TGT_MAX_MULTICAST_FILTER_ENTRIES) {
+ WMA_LOGE("Number of multicast addresses is: %u",
+ mcbc_param->ulMulticastAddrCnt);
+ WARN_ON(1);
return VOS_STATUS_E_FAILURE;
}
@@ -24782,208 +24787,322 @@ out:
}
#endif
-/*
- * Function : wma_enable_arp_ns_offload
- * Description : To configure ARP NS off load data to firmware
- * when target goes to wow mode.
- * Args : @wma - wma handle, @tpSirHostOffloadReq -
- * pHostOffloadParams,@bool bArpOnly
- * Returns : Returns Failure or Success based on WMI cmd.
- * Comments : Since firware expects ARP and NS to be configured
- * at a time, Arp info is cached in wma and send along
- * with NS info to make both work.
+/**
+ * wma_fill_arp_offload_params() - Fill ARP offload data
+ * @wma: wma handle
+ * @tpSirHostOffloadReq: offload request
+ * @buf_ptr: buffer pointer
+ *
+ * To fill ARP offload data to firmware
+ * when target goes to wow mode.
+ *
+ * Return: None
+ */
+static void wma_fill_arp_offload_params(tp_wma_handle wma,
+ tpSirHostOffloadReq hostoffloadreq, uint8_t **buf_ptr)
+{
+
+ int32_t i;
+ WMI_ARP_OFFLOAD_TUPLE *arp_tuple;
+ bool enableOrDisable = hostoffloadreq->enableOrDisable;
+
+ WMITLV_SET_HDR(*buf_ptr, WMITLV_TAG_ARRAY_STRUC,
+ (WMI_MAX_ARP_OFFLOADS*sizeof(WMI_ARP_OFFLOAD_TUPLE)));
+ *buf_ptr += WMI_TLV_HDR_SIZE;
+ for (i = 0; i < WMI_MAX_ARP_OFFLOADS; i++) {
+ arp_tuple = (WMI_ARP_OFFLOAD_TUPLE *)*buf_ptr;
+ WMITLV_SET_HDR(&arp_tuple->tlv_header,
+ WMITLV_TAG_STRUC_WMI_ARP_OFFLOAD_TUPLE,
+ WMITLV_GET_STRUCT_TLVLEN(WMI_ARP_OFFLOAD_TUPLE));
+
+ /* Fill data for ARP and NS in the first tupple for LA */
+ if ((enableOrDisable & SIR_OFFLOAD_ENABLE) && (i == 0)) {
+ /* Copy the target ip addr and flags */
+ arp_tuple->flags = WMI_ARPOFF_FLAGS_VALID;
+ A_MEMCPY(&arp_tuple->target_ipaddr,
+ hostoffloadreq->params.hostIpv4Addr,
+ SIR_IPV4_ADDR_LEN);
+ WMA_LOGD("ARPOffload IP4 address: %pI4",
+ hostoffloadreq->params.hostIpv4Addr);
+ }
+ *buf_ptr += sizeof(WMI_ARP_OFFLOAD_TUPLE);
+ }
+}
+
+#ifdef WLAN_NS_OFFLOAD
+/**
+ * wma_fill_ns_offload_params() - Fill NS offload data
+ * @wma: wma handle
+ * @tpSirHostOffloadReq: offload request
+ * @buf_ptr: buffer pointer
+ *
+ * To fill NS offload data to firmware
+ * when target goes to wow mode.
+ *
+ * Return: None
*/
-static VOS_STATUS wma_enable_arp_ns_offload(tp_wma_handle wma, tpSirHostOffloadReq pHostOffloadParams, bool bArpOnly)
+static void wma_fill_ns_offload_params(tp_wma_handle wma,
+ tpSirHostOffloadReq hostoffloadreq, uint8_t **buf_ptr)
{
+
int32_t i;
+ WMI_NS_OFFLOAD_TUPLE *ns_tuple;
+ tSirNsOffloadReq ns_req;
+
+ ns_req = hostoffloadreq->nsOffloadInfo;
+ WMITLV_SET_HDR(*buf_ptr, WMITLV_TAG_ARRAY_STRUC,
+ (WMI_MAX_NS_OFFLOADS*sizeof(WMI_NS_OFFLOAD_TUPLE)));
+ *buf_ptr += WMI_TLV_HDR_SIZE;
+ for (i = 0; i < WMI_MAX_NS_OFFLOADS; i++) {
+ ns_tuple = (WMI_NS_OFFLOAD_TUPLE *)*buf_ptr;
+ WMITLV_SET_HDR(&ns_tuple->tlv_header,
+ WMITLV_TAG_STRUC_WMI_NS_OFFLOAD_TUPLE,
+ (sizeof(WMI_NS_OFFLOAD_TUPLE) - WMI_TLV_HDR_SIZE));
+
+ /*
+ * Fill data only for NS offload in the first ARP tuple for LA
+ */
+ if ((hostoffloadreq->enableOrDisable & SIR_OFFLOAD_ENABLE)) {
+ ns_tuple->flags |= WMI_NSOFF_FLAGS_VALID;
+ /* Copy the target/solicitation/remote ip addr */
+ if (ns_req.targetIPv6AddrValid[i])
+ A_MEMCPY(&ns_tuple->target_ipaddr[0],
+ &ns_req.targetIPv6Addr[i],
+ sizeof(WMI_IPV6_ADDR));
+ A_MEMCPY(&ns_tuple->solicitation_ipaddr,
+ &ns_req.selfIPv6Addr[i],
+ sizeof(WMI_IPV6_ADDR));
+ if (ns_req.target_ipv6_addr_type[i]) {
+ ns_tuple->flags |=
+ WMI_NSOFF_FLAGS_IS_IPV6_ANYCAST;
+ }
+ WMA_LOGD("Index %d NS solicitedIp %pI6, targetIp %pI6",
+ i, &ns_req.selfIPv6Addr[i],
+ &ns_req.targetIPv6Addr[i]);
+
+ /* target MAC is optional, check if it is valid,
+ * if this is not valid, the target will use the known
+ * local MAC address rather than the tuple
+ */
+ WMI_CHAR_ARRAY_TO_MAC_ADDR(
+ ns_req.selfMacAddr,
+ &ns_tuple->target_mac);
+ if ((ns_tuple->target_mac.mac_addr31to0 != 0) ||
+ (ns_tuple->target_mac.mac_addr47to32 != 0)) {
+ ns_tuple->flags |= WMI_NSOFF_FLAGS_MAC_VALID;
+ }
+ }
+ *buf_ptr += sizeof(WMI_NS_OFFLOAD_TUPLE);
+ }
+}
+
+
+/**
+ * wma_fill_nsoffload_ext() - Fill NS offload ext data
+ * @wma: wma handle
+ * @tpSirHostOffloadReq: offload request
+ * @buf_ptr: buffer pointer
+ *
+ * To fill extended NS offload extended data to firmware
+ * when target goes to wow mode.
+ *
+ * Return: None
+ */
+static void wma_fill_nsoffload_ext(tp_wma_handle wma, tpSirHostOffloadReq
+ hostoffloadreq, uint8_t **buf_ptr)
+{
+ int32_t i;
+ WMI_NS_OFFLOAD_TUPLE *ns_tuple;
+ uint32_t count, num_ns_ext_tuples;
+ tSirNsOffloadReq ns_req;
+
+ ns_req = hostoffloadreq->nsOffloadInfo;
+ count = hostoffloadreq->num_ns_offload_count;
+ num_ns_ext_tuples = hostoffloadreq->num_ns_offload_count -
+ WMI_MAX_NS_OFFLOADS;
+
+ /* Populate extended NS offload tuples */
+ WMITLV_SET_HDR(*buf_ptr, WMITLV_TAG_ARRAY_STRUC,
+ (num_ns_ext_tuples * sizeof(WMI_NS_OFFLOAD_TUPLE)));
+ *buf_ptr += WMI_TLV_HDR_SIZE;
+ for (i = WMI_MAX_NS_OFFLOADS; i < count; i++) {
+ ns_tuple = (WMI_NS_OFFLOAD_TUPLE *)*buf_ptr;
+ WMITLV_SET_HDR(&ns_tuple->tlv_header,
+ WMITLV_TAG_STRUC_WMI_NS_OFFLOAD_TUPLE,
+ (sizeof(WMI_NS_OFFLOAD_TUPLE)-WMI_TLV_HDR_SIZE));
+
+ /*
+ * Fill data only for NS offload in the first ARP tuple for LA
+ */
+ if ((hostoffloadreq->enableOrDisable & SIR_OFFLOAD_ENABLE)) {
+ ns_tuple->flags |= WMI_NSOFF_FLAGS_VALID;
+ /* Copy the target/solicitation/remote ip addr */
+ if (ns_req.targetIPv6AddrValid[i])
+ A_MEMCPY(&ns_tuple->target_ipaddr[0],
+ &ns_req.targetIPv6Addr[i],
+ sizeof(WMI_IPV6_ADDR));
+ A_MEMCPY(&ns_tuple->solicitation_ipaddr,
+ &ns_req.selfIPv6Addr[i],
+ sizeof(WMI_IPV6_ADDR));
+ if (ns_req.target_ipv6_addr_type[i]) {
+ ns_tuple->flags |=
+ WMI_NSOFF_FLAGS_IS_IPV6_ANYCAST;
+ }
+ WMA_LOGD("Index %d NS solicitedIp %pI6, targetIp %pI6",
+ i, &ns_req.selfIPv6Addr[i],
+ &ns_req.targetIPv6Addr[i]);
+
+ /* target MAC is optional, check if it is valid,
+ * if this is not valid, the target will use the
+ * known local MAC address rather than the tuple
+ */
+ WMI_CHAR_ARRAY_TO_MAC_ADDR(
+ ns_req.selfMacAddr,
+ &ns_tuple->target_mac);
+ if ((ns_tuple->target_mac.mac_addr31to0 != 0) ||
+ (ns_tuple->target_mac.mac_addr47to32 != 0)) {
+ ns_tuple->flags |= WMI_NSOFF_FLAGS_MAC_VALID;
+ }
+ }
+ *buf_ptr += sizeof(WMI_NS_OFFLOAD_TUPLE);
+ }
+}
+#else
+static inline void wma_fill_ns_offload_params(tp_wma_handle wma,
+ tpSirHostOffloadReq hostoffloadreq, uint8_t **buf_ptr)
+{
+ return;
+}
+
+static inline void wma_fill_nsoffload_ext(tp_wma_handle wma,
+ tpSirHostOffloadReq hostoffloadreq, uint8_t **buf_ptr)
+{
+ return;
+}
+#endif
+
+
+/**
+ * wma_enable_arp_ns_offload() - enable ARP NS offload
+ * @wma: wma handle
+ * @tpSirHostOffloadReq: offload request
+ * @config_arp: flag
+ *
+ * To configure ARP NS off load data to firmware
+ * when target goes to wow mode.
+ *
+ * Return: VOS Status
+ */
+static VOS_STATUS wma_enable_arp_ns_offload(tp_wma_handle wma,
+ tpSirHostOffloadReq hostoffloadreq, bool config_arp)
+{
int32_t res;
WMI_SET_ARP_NS_OFFLOAD_CMD_fixed_param *cmd;
- WMI_NS_OFFLOAD_TUPLE *ns_tuple;
- WMI_ARP_OFFLOAD_TUPLE *arp_tuple;
A_UINT8* buf_ptr;
wmi_buf_t buf;
int32_t len;
+ VOS_STATUS status = VOS_STATUS_SUCCESS;
u_int8_t vdev_id;
+ tpSirHostOffloadReq ns_offload_req;
+ tpSirHostOffloadReq arp_offload_req;
uint32_t count = 0, num_ns_ext_tuples = 0;
/* Get the vdev id */
- if (!wma_find_vdev_by_bssid(wma, pHostOffloadParams->bssId, &vdev_id)) {
- WMA_LOGE("vdev handle is invalid for %pM", pHostOffloadParams->bssId);
- vos_mem_free(pHostOffloadParams);
- return VOS_STATUS_E_INVAL;
+ if (!wma_find_vdev_by_bssid(wma, hostoffloadreq->bssId, &vdev_id)) {
+ WMA_LOGE("Invalid vdev handle for %pM", hostoffloadreq->bssId);
+ status = VOS_STATUS_E_FAILURE;
+ goto err_vdev;
}
if (!wma->interfaces[vdev_id].vdev_up) {
-
WMA_LOGE("vdev %d is not up skipping arp/ns offload", vdev_id);
- vos_mem_free(pHostOffloadParams);
- return VOS_STATUS_E_FAILURE;
+ status = VOS_STATUS_E_FAILURE;
+ goto err_vdev;
}
- if (!bArpOnly)
- count = pHostOffloadParams->num_ns_offload_count;
+ /*
+ * config_arp is true means arp request comes from upper layer
+ * Hence ns request need to used from wma cached request.
+ */
+ if (config_arp) {
+ arp_offload_req = hostoffloadreq;
+ ns_offload_req = &wma->interfaces[vdev_id].ns_offload_req;
+ count = ns_offload_req->num_ns_offload_count;
+ } else {
+ ns_offload_req = hostoffloadreq;
+ arp_offload_req = &wma->interfaces[vdev_id].arp_offload_req;
+ count = hostoffloadreq->num_ns_offload_count;
+ }
len = sizeof(WMI_SET_ARP_NS_OFFLOAD_CMD_fixed_param) +
- WMI_TLV_HDR_SIZE + // TLV place holder size for array of NS tuples
+ WMI_TLV_HDR_SIZE + /* Add size for array of NS tuples */
WMI_MAX_NS_OFFLOADS*sizeof(WMI_NS_OFFLOAD_TUPLE) +
- WMI_TLV_HDR_SIZE + // TLV place holder size for array of ARP tuples
+ WMI_TLV_HDR_SIZE + /* Add size for array of ARP tuples */
WMI_MAX_ARP_OFFLOADS*sizeof(WMI_ARP_OFFLOAD_TUPLE);
- /*
- * If there are more than WMI_MAX_NS_OFFLOADS addresses then allocate
- * extra length for extended NS offload tuples which follows ARP offload
- * tuples. Host needs to fill this structure in following format:
- * 2 NS ofload tuples
- * 2 ARP offload tuples
- * N numbers of extended NS offload tuples if HDD has given more than
- * 2 NS offload addresses
- */
- if (!bArpOnly && count > WMI_MAX_NS_OFFLOADS) {
+ if (count > WMI_MAX_NS_OFFLOADS) {
num_ns_ext_tuples = count - WMI_MAX_NS_OFFLOADS;
- len += WMI_TLV_HDR_SIZE + num_ns_ext_tuples *
- sizeof(WMI_NS_OFFLOAD_TUPLE);
+ len += WMI_TLV_HDR_SIZE + num_ns_ext_tuples
+ * sizeof(WMI_NS_OFFLOAD_TUPLE);
}
buf = wmi_buf_alloc(wma->wmi_handle, len);
if (!buf) {
WMA_LOGE("%s: wmi_buf_alloc failed", __func__);
- vos_mem_free(pHostOffloadParams);
- return VOS_STATUS_E_NOMEM;
+ status = VOS_STATUS_E_NOMEM;
+ goto err_vdev;
}
buf_ptr = (A_UINT8*)wmi_buf_data(buf);
+
cmd = (WMI_SET_ARP_NS_OFFLOAD_CMD_fixed_param *)buf_ptr;
WMITLV_SET_HDR(&cmd->tlv_header,
- WMITLV_TAG_STRUC_WMI_SET_ARP_NS_OFFLOAD_CMD_fixed_param,
- WMITLV_GET_STRUCT_TLVLEN(WMI_SET_ARP_NS_OFFLOAD_CMD_fixed_param));
+ WMITLV_TAG_STRUC_WMI_SET_ARP_NS_OFFLOAD_CMD_fixed_param,
+ WMITLV_GET_STRUCT_TLVLEN(
+ WMI_SET_ARP_NS_OFFLOAD_CMD_fixed_param));
cmd->flags = 0;
cmd->vdev_id = vdev_id;
- if (!bArpOnly)
- cmd->num_ns_ext_tuples = num_ns_ext_tuples;
-
- WMA_LOGD("ARP NS Offload vdev_id: %d",cmd->vdev_id);
-
- /* Have copy of arp info to send along with NS, Since FW expects
- * both ARP and NS info in single cmd */
- if(bArpOnly)
- vos_mem_copy(&wma->mArpInfo, pHostOffloadParams, sizeof(tSirHostOffloadReq));
+ cmd->num_ns_ext_tuples = num_ns_ext_tuples;
buf_ptr += sizeof(WMI_SET_ARP_NS_OFFLOAD_CMD_fixed_param);
- WMITLV_SET_HDR(buf_ptr,WMITLV_TAG_ARRAY_STRUC,(WMI_MAX_NS_OFFLOADS*sizeof(WMI_NS_OFFLOAD_TUPLE)));
- buf_ptr += WMI_TLV_HDR_SIZE;
- for(i = 0; i < WMI_MAX_NS_OFFLOADS; i++ ){
- ns_tuple = (WMI_NS_OFFLOAD_TUPLE *)buf_ptr;
- WMITLV_SET_HDR(&ns_tuple->tlv_header,
- WMITLV_TAG_STRUC_WMI_NS_OFFLOAD_TUPLE,
- (sizeof(WMI_NS_OFFLOAD_TUPLE)-WMI_TLV_HDR_SIZE));
-
- /* Fill data only for NS offload in the first ARP tuple for LA */
- if (!bArpOnly &&
- ((pHostOffloadParams->enableOrDisable & SIR_OFFLOAD_ENABLE))) {
- ns_tuple->flags |= WMI_NSOFF_FLAGS_VALID;
-
-#ifdef WLAN_NS_OFFLOAD
- /*Copy the target/solicitation/remote ip addr */
- if(pHostOffloadParams->nsOffloadInfo.targetIPv6AddrValid[i])
- A_MEMCPY(&ns_tuple->target_ipaddr[0],
- &pHostOffloadParams->nsOffloadInfo.targetIPv6Addr[i], sizeof(WMI_IPV6_ADDR));
- A_MEMCPY(&ns_tuple->solicitation_ipaddr,
- &pHostOffloadParams->nsOffloadInfo.selfIPv6Addr[i], sizeof(WMI_IPV6_ADDR));
- if(pHostOffloadParams->nsOffloadInfo.target_ipv6_addr_type[i])
- ns_tuple->flags |= WMI_NSOFF_FLAGS_IS_IPV6_ANYCAST;
- WMA_LOGD("Index %d NS solicitedIp: %pI6, targetIp: %pI6", i,
- &pHostOffloadParams->nsOffloadInfo.selfIPv6Addr[i],
- &pHostOffloadParams->nsOffloadInfo.targetIPv6Addr[i]);
-
- /* target MAC is optional, check if it is valid, if this is not valid,
- * the target will use the known local MAC address rather than the tuple */
- WMI_CHAR_ARRAY_TO_MAC_ADDR(pHostOffloadParams->nsOffloadInfo.selfMacAddr,
- &ns_tuple->target_mac);
-#endif
- if ((ns_tuple->target_mac.mac_addr31to0 != 0) ||
- (ns_tuple->target_mac.mac_addr47to32 != 0))
- {
- ns_tuple->flags |= WMI_NSOFF_FLAGS_MAC_VALID;
- }
- }
- buf_ptr += sizeof(WMI_NS_OFFLOAD_TUPLE);
- }
-
- WMITLV_SET_HDR(buf_ptr,WMITLV_TAG_ARRAY_STRUC,(WMI_MAX_ARP_OFFLOADS*sizeof(WMI_ARP_OFFLOAD_TUPLE)));
- buf_ptr += WMI_TLV_HDR_SIZE;
- for(i = 0; i < WMI_MAX_ARP_OFFLOADS; i++){
- arp_tuple = (WMI_ARP_OFFLOAD_TUPLE *)buf_ptr;
- WMITLV_SET_HDR(&arp_tuple->tlv_header,
- WMITLV_TAG_STRUC_WMI_ARP_OFFLOAD_TUPLE,
- WMITLV_GET_STRUCT_TLVLEN(WMI_ARP_OFFLOAD_TUPLE));
-
- /* Fill data for ARP and NS in the first tupple for LA */
- if ((wma->mArpInfo.enableOrDisable & SIR_OFFLOAD_ENABLE) && (i==0)) {
- /*Copy the target ip addr and flags*/
- arp_tuple->flags = WMI_ARPOFF_FLAGS_VALID;
- A_MEMCPY(&arp_tuple->target_ipaddr,wma->mArpInfo.params.hostIpv4Addr,
- SIR_IPV4_ADDR_LEN);
- WMA_LOGD("ARPOffload IP4 address: %pI4",
- wma->mArpInfo.params.hostIpv4Addr);
- }
- buf_ptr += sizeof(WMI_ARP_OFFLOAD_TUPLE);
- }
-
- /* Populate extended NS offload tuples */
- WMITLV_SET_HDR(buf_ptr, WMITLV_TAG_ARRAY_STRUC,
- (num_ns_ext_tuples*sizeof(WMI_NS_OFFLOAD_TUPLE)));
- buf_ptr += WMI_TLV_HDR_SIZE;
-
- if (num_ns_ext_tuples) {
- for(i = WMI_MAX_NS_OFFLOADS; i < count; i++ ){
- ns_tuple = (WMI_NS_OFFLOAD_TUPLE *)buf_ptr;
- WMITLV_SET_HDR(&ns_tuple->tlv_header,
- WMITLV_TAG_STRUC_WMI_NS_OFFLOAD_TUPLE,
- (sizeof(WMI_NS_OFFLOAD_TUPLE)-WMI_TLV_HDR_SIZE));
-
- /* Fill data only for NS offload in the first ARP tuple for LA */
- if (!bArpOnly &&
- ((pHostOffloadParams->enableOrDisable & SIR_OFFLOAD_ENABLE))) {
- ns_tuple->flags |= WMI_NSOFF_FLAGS_VALID;
-#ifdef WLAN_NS_OFFLOAD
- /*Copy the target/solicitation/remote ip addr */
- if(pHostOffloadParams->nsOffloadInfo.targetIPv6AddrValid[i])
- A_MEMCPY(&ns_tuple->target_ipaddr[0],
- &pHostOffloadParams->nsOffloadInfo.targetIPv6Addr[i],
- sizeof(WMI_IPV6_ADDR));
- A_MEMCPY(&ns_tuple->solicitation_ipaddr,
- &pHostOffloadParams->nsOffloadInfo.selfIPv6Addr[i],
- sizeof(WMI_IPV6_ADDR));
- if(pHostOffloadParams->nsOffloadInfo.target_ipv6_addr_type[i])
- ns_tuple->flags |= WMI_NSOFF_FLAGS_IS_IPV6_ANYCAST;
- WMA_LOGD("Index %d NS solicitedIp: %pI6, targetIp: %pI6", i,
- &pHostOffloadParams->nsOffloadInfo.selfIPv6Addr[i],
- &pHostOffloadParams->nsOffloadInfo.targetIPv6Addr[i]);
-
- /* target MAC is optional, check if it is valid, if this is not valid,
- * the target will use the known local MAC address rather than the tuple */
- WMI_CHAR_ARRAY_TO_MAC_ADDR(pHostOffloadParams->nsOffloadInfo.selfMacAddr,
- &ns_tuple->target_mac);
-#endif
- if ((ns_tuple->target_mac.mac_addr31to0 != 0) ||
- (ns_tuple->target_mac.mac_addr47to32 != 0)) {
- ns_tuple->flags |= WMI_NSOFF_FLAGS_MAC_VALID;
- }
- }
- buf_ptr += sizeof(WMI_NS_OFFLOAD_TUPLE);
- }
+ if (config_arp)
+ WMA_LOGD(" %s: ARP Offload vdev_id: %d enable: %d ns_count: %u",
+ __func__, cmd->vdev_id,
+ hostoffloadreq->enableOrDisable,
+ hostoffloadreq->num_ns_offload_count);
+ else
+ WMA_LOGD(" %s: NS Offload vdev_id: %d enable: %d ns_count: %u",
+ __func__, cmd->vdev_id,
+ hostoffloadreq->enableOrDisable,
+ hostoffloadreq->num_ns_offload_count);
+
+ wma_fill_ns_offload_params(wma, ns_offload_req, &buf_ptr);
+ wma_fill_arp_offload_params(wma, arp_offload_req, &buf_ptr);
+ if (count > WMI_MAX_NS_OFFLOADS)
+ wma_fill_nsoffload_ext(wma, ns_offload_req, &buf_ptr);
+
+ res = wmi_unified_cmd_send(wma->wmi_handle, buf, len,
+ WMI_SET_ARP_NS_OFFLOAD_CMDID);
+ if (res) {
+ WMA_LOGE("Failed to enable ARP NDP/NSffload");
+ goto err_cmd_send;
}
- res = wmi_unified_cmd_send(wma->wmi_handle, buf, len, WMI_SET_ARP_NS_OFFLOAD_CMDID);
- if(res) {
- WMA_LOGE("Failed to enable ARP NDP/NSffload");
- wmi_buf_free(buf);
- vos_mem_free(pHostOffloadParams);
- return VOS_STATUS_E_FAILURE;
+ if (config_arp) {
+ vos_mem_copy(&wma->interfaces[vdev_id].arp_offload_req,
+ hostoffloadreq, sizeof(tSirHostOffloadReq));
+ } else {
+ vos_mem_copy(&wma->interfaces[vdev_id].ns_offload_req,
+ hostoffloadreq, sizeof(tSirHostOffloadReq));
}
- vos_mem_free(pHostOffloadParams);
- return VOS_STATUS_SUCCESS;
+ vos_mem_free(hostoffloadreq);
+ return status;
+err_cmd_send:
+ wmi_buf_free(buf);
+err_vdev:
+ vos_mem_free(hostoffloadreq);
+ return status;
}
typedef struct {
diff --git a/drivers/staging/qcacld-2.0/CORE/SERVICES/WMA/wma.h b/drivers/staging/qcacld-2.0/CORE/SERVICES/WMA/wma.h
index 8dedfab6f269..d88e9e0cf312 100644
--- a/drivers/staging/qcacld-2.0/CORE/SERVICES/WMA/wma.h
+++ b/drivers/staging/qcacld-2.0/CORE/SERVICES/WMA/wma.h
@@ -569,6 +569,10 @@ struct wma_txrx_node {
v_BOOL_t vdev_up;
u_int64_t tsfadjust;
void *addBssStaContext;
+ /* Have a back up of arp offload req */
+ tSirHostOffloadReq arp_offload_req;
+ /* tSirHostOffloadReq of ns offload req */
+ tSirHostOffloadReq ns_offload_req;
tANI_U8 aid;
/* Robust Management Frame (RMF) enabled/disabled */
tANI_U8 rmfEnabled;
@@ -763,10 +767,6 @@ typedef struct wma_handle {
u_int8_t no_of_suspend_ind;
u_int8_t no_of_resume_ind;
- /* Have a back up of arp info to send along
- * with ns info suppose if ns also enabled
- */
- tSirHostOffloadReq mArpInfo;
struct wma_tx_ack_work_ctx *ack_work_ctx;
u_int8_t powersave_mode;
v_BOOL_t ptrn_match_enable_all_vdev;
diff --git a/drivers/staging/qcacld-2.0/CORE/SERVICES/WMI/wmi_unified_priv.h b/drivers/staging/qcacld-2.0/CORE/SERVICES/WMI/wmi_unified_priv.h
index 780e49c26959..5a43e3fb299d 100644
--- a/drivers/staging/qcacld-2.0/CORE/SERVICES/WMI/wmi_unified_priv.h
+++ b/drivers/staging/qcacld-2.0/CORE/SERVICES/WMI/wmi_unified_priv.h
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2013-2014 The Linux Foundation. All rights reserved.
+ * Copyright (c) 2013-2016 The Linux Foundation. All rights reserved.
*
* Previously licensed under the ISC license by Qualcomm Atheros, Inc.
*
@@ -38,7 +38,7 @@
#include "adf_os_atomic.h"
#define WMI_UNIFIED_MAX_EVENT 0x100
-#define WMI_MAX_CMDS 128
+#define WMI_MAX_CMDS 256
typedef adf_nbuf_t wmi_buf_t;
diff --git a/drivers/staging/qcacld-2.0/CORE/VOSS/inc/vos_packet.h b/drivers/staging/qcacld-2.0/CORE/VOSS/inc/vos_packet.h
index 469da0a1a923..6d86b3a2f16d 100644
--- a/drivers/staging/qcacld-2.0/CORE/VOSS/inc/vos_packet.h
+++ b/drivers/staging/qcacld-2.0/CORE/VOSS/inc/vos_packet.h
@@ -62,7 +62,9 @@ typedef struct vos_pkt_t vos_pkt_t;
#define VOS_PKT_TRAC_TYPE_EAPOL NBUF_PKT_TRAC_TYPE_EAPOL
#define VOS_PKT_TRAC_TYPE_DHCP NBUF_PKT_TRAC_TYPE_DHCP
#define VOS_PKT_TRAC_TYPE_MGMT_ACTION NBUF_PKT_TRAC_TYPE_MGMT_ACTION /* Managment action frame */
-
+#define VOS_PKT_TRAC_TYPE_ARP NBUF_PKT_TRAC_TYPE_ARP
+#define VOS_PKT_TRAC_TYPE_NS NBUF_PKT_TRAC_TYPE_NS
+#define VOS_PKT_TRAC_TYPE_NA NBUF_PKT_TRAC_TYPE_NA
#define VOS_PKT_TRAC_DUMP_CMD 9999
/*---------------------------------------------------------------------------
diff --git a/drivers/staging/qcacld-2.0/CORE/VOSS/src/vos_api.c b/drivers/staging/qcacld-2.0/CORE/VOSS/src/vos_api.c
index 5b536b35f019..3004ccc4c7d0 100644
--- a/drivers/staging/qcacld-2.0/CORE/VOSS/src/vos_api.c
+++ b/drivers/staging/qcacld-2.0/CORE/VOSS/src/vos_api.c
@@ -2898,11 +2898,11 @@ VOS_STATUS vos_flush_logs(uint32_t is_fatal,
"%s: Triggering bug report: type:%d, indicator=%d reason_code=%d dump_trace=0x%x",
__func__, is_fatal, indicator, reason_code, dump_trace);
- if (dump_trace | DUMP_VOS_TRACE)
+ if (dump_trace & DUMP_VOS_TRACE)
vosTraceDumpAll(vos_context->pMACContext, 0, 0, 500, 0);
#ifdef QCA_PKT_PROTO_TRACE
- if (dump_trace | DUMP_PACKET_TRACE)
+ if (dump_trace & DUMP_PACKET_TRACE)
vos_pkt_trace_buf_dump();
#endif
if (WLAN_LOG_INDICATOR_HOST_ONLY == indicator) {
diff --git a/drivers/staging/qcacld-2.0/CORE/VOSS/src/vos_packet.c b/drivers/staging/qcacld-2.0/CORE/VOSS/src/vos_packet.c
index 1795ecbfb8e1..e81c6411f68b 100644
--- a/drivers/staging/qcacld-2.0/CORE/VOSS/src/vos_packet.c
+++ b/drivers/staging/qcacld-2.0/CORE/VOSS/src/vos_packet.c
@@ -57,6 +57,7 @@
#define VOS_PKT_TRAC_DHCP_SRV_PORT 67
#define VOS_PKT_TRAC_DHCP_CLI_PORT 68
#define VOS_PKT_TRAC_EAPOL_ETH_TYPE 0x888E
+#define VOS_PKT_TRAC_ARP_ETH_TYPE 0x0806
#ifdef QCA_PKT_PROTO_TRACE
#define VOS_PKT_TRAC_MAX_STRING_LEN 40
#define VOS_PKT_TRAC_MAX_TRACE_BUF 50
@@ -256,14 +257,11 @@ v_U8_t vos_pkt_get_proto_type
)
{
v_U8_t pkt_proto_type = 0;
- v_U16_t ether_type;
- v_U16_t SPort;
- v_U16_t DPort;
if (dot11_type)
{
if (dot11_type == (VOS_PKT_TRAC_TYPE_MGMT_ACTION & tracking_map))
- pkt_proto_type |= VOS_PKT_TRAC_TYPE_MGMT_ACTION;
+ pkt_proto_type = VOS_PKT_TRAC_TYPE_MGMT_ACTION;
/* Protocol type map */
return pkt_proto_type;
@@ -272,26 +270,48 @@ v_U8_t vos_pkt_get_proto_type
/* EAPOL Tracking enabled */
if (VOS_PKT_TRAC_TYPE_EAPOL & tracking_map)
{
- ether_type = (v_U16_t)(*(v_U16_t *)(skb->data + VOS_PKT_TRAC_ETH_TYPE_OFFSET));
- if (VOS_PKT_TRAC_EAPOL_ETH_TYPE == VOS_SWAP_U16(ether_type))
- {
- pkt_proto_type |= VOS_PKT_TRAC_TYPE_EAPOL;
+ if (adf_nbuf_is_eapol_pkt(skb) == A_STATUS_OK) {
+ pkt_proto_type = VOS_PKT_TRAC_TYPE_EAPOL;
+ return pkt_proto_type;
}
}
/* DHCP Tracking enabled */
if (VOS_PKT_TRAC_TYPE_DHCP & tracking_map)
{
- SPort = (v_U16_t)(*(v_U16_t *)(skb->data + VOS_PKT_TRAC_IP_OFFSET +
- VOS_PKT_TRAC_IP_HEADER_SIZE));
- DPort = (v_U16_t)(*(v_U16_t *)(skb->data + VOS_PKT_TRAC_IP_OFFSET +
- VOS_PKT_TRAC_IP_HEADER_SIZE + sizeof(v_U16_t)));
- if (((VOS_PKT_TRAC_DHCP_SRV_PORT == VOS_SWAP_U16(SPort)) &&
- (VOS_PKT_TRAC_DHCP_CLI_PORT == VOS_SWAP_U16(DPort))) ||
- ((VOS_PKT_TRAC_DHCP_CLI_PORT == VOS_SWAP_U16(SPort)) &&
- (VOS_PKT_TRAC_DHCP_SRV_PORT == VOS_SWAP_U16(DPort))))
- {
- pkt_proto_type |= VOS_PKT_TRAC_TYPE_DHCP;
+ if (adf_nbuf_is_dhcp_pkt(skb) == A_STATUS_OK) {
+ pkt_proto_type = VOS_PKT_TRAC_TYPE_DHCP;
+ return pkt_proto_type;
+ }
+ }
+
+ /* ARP Tracking enabled */
+ if (VOS_PKT_TRAC_TYPE_ARP & tracking_map) {
+ if (adf_nbuf_is_ipv4_arp_pkt(skb)) {
+ pkt_proto_type = VOS_PKT_TRAC_TYPE_ARP;
+ return pkt_proto_type;
+ }
+ }
+
+ /* IPV6 NS Tracking enabled */
+ if (VOS_PKT_TRAC_TYPE_NS & tracking_map) {
+ if (adf_nbuf_is_icmpv6_pkt(skb)) {
+ if (adf_nbuf_get_icmpv6_subtype(skb) ==
+ ADF_PROTO_ICMPV6_NS) {
+ pkt_proto_type = VOS_PKT_TRAC_TYPE_NS;
+ return pkt_proto_type;
+ }
+ }
+ }
+
+ /* IPV6 NA Tracking enabled */
+ if (VOS_PKT_TRAC_TYPE_NA & tracking_map) {
+ if (adf_nbuf_is_icmpv6_pkt(skb)) {
+ if (adf_nbuf_get_icmpv6_subtype(skb) ==
+ ADF_PROTO_ICMPV6_NA) {
+ pkt_proto_type = VOS_PKT_TRAC_TYPE_NA;
+ return pkt_proto_type;
+ }
}
}
@@ -329,9 +349,8 @@ void vos_pkt_trace_buf_update
do_gettimeofday(&tv);
trace_buffer[slot].event_sec_time = tv.tv_sec;
trace_buffer[slot].event_msec_time = tv.tv_usec;
- strncpy(trace_buffer[slot].event_string, event_string,
- (sizeof(trace_buffer[slot].event_string) < strlen(event_string)?
- sizeof(trace_buffer[slot].event_string) : strlen(event_string)));
+ strlcpy(trace_buffer[slot].event_string, event_string,
+ sizeof(trace_buffer[slot].event_string));
return;
}
diff --git a/drivers/usb/dwc3/dwc3-msm.c b/drivers/usb/dwc3/dwc3-msm.c
index b4244e92e2a5..84a5c9b92ed0 100644
--- a/drivers/usb/dwc3/dwc3-msm.c
+++ b/drivers/usb/dwc3/dwc3-msm.c
@@ -250,6 +250,7 @@ struct dwc3_msm {
int redrive_3p0_c2;
struct delayed_work vbus_notify_work;
bool pd_vbus_change;
+ bool xo_vote_for_charger;
};
#define USB_HSPHY_3P3_VOL_MIN 3050000 /* uV */
@@ -2013,7 +2014,13 @@ static int dwc3_msm_suspend(struct dwc3_msm *mdwc)
*/
clk_disable_unprepare(mdwc->iface_clk);
/* USB PHY no more requires TCXO */
- clk_disable_unprepare(mdwc->xo_clk);
+ if (!mdwc->xo_vote_for_charger) {
+ clk_disable_unprepare(mdwc->xo_clk);
+ dev_err(mdwc->dev, "%s unvote for TCXO buffer\n", __func__);
+ } else {
+ dev_err(mdwc->dev, "%s xo_vote_for_charger = %d\n",
+ __func__, mdwc->xo_vote_for_charger);
+ }
/* Perform controller power collapse */
if (!mdwc->in_host_mode && (!mdwc->vbus_active ||
@@ -2087,10 +2094,18 @@ static int dwc3_msm_resume(struct dwc3_msm *mdwc)
}
/* Vote for TCXO while waking up USB HSPHY */
- ret = clk_prepare_enable(mdwc->xo_clk);
- if (ret)
- dev_err(mdwc->dev, "%s failed to vote TCXO buffer%d\n",
- __func__, ret);
+ if (!mdwc->xo_vote_for_charger) {
+ ret = clk_prepare_enable(mdwc->xo_clk);
+ if (ret)
+ dev_err(mdwc->dev, "%s failed to vote TCXO buffer%d\n",
+ __func__, ret);
+ else
+ dev_err(mdwc->dev, "%s vote for TCXO buffer\n",
+ __func__);
+ } else {
+ dev_err(mdwc->dev, "%s xo_vote_for_charger = %d\n",
+ __func__, mdwc->xo_vote_for_charger);
+ }
/* Restore controller power collapse */
if (mdwc->lpm_flags & MDWC3_POWER_COLLAPSE) {
@@ -2533,6 +2548,33 @@ static int dwc3_msm_power_set_property_usb(struct power_supply *psy,
break;
}
+ if (mdwc->chg_type == DWC3_DCP_CHARGER || mdwc->chg_type == DWC3_TYPEC_CHARGER ||
+ mdwc->chg_type == DWC3_PD_CHARGER || mdwc->chg_type == DWC3_PD_DRP_CHARGER ||
+ mdwc->chg_type == DWC3_PROPRIETARY_CHARGER) {
+ if (!mdwc->xo_vote_for_charger) {
+ struct dwc3 *dwc = platform_get_drvdata(mdwc->dwc3);
+ if (atomic_read(&dwc->in_lpm)) {
+ int ret;
+ ret = clk_prepare_enable(mdwc->xo_clk);
+ if (ret)
+ dev_err(mdwc->dev, "%s failed to vote TCXO buffer%d\n",
+ __func__, ret);
+ else
+ dev_err(mdwc->dev, "%s TCXO enabled\n", __func__);
+ }
+ mdwc->xo_vote_for_charger = true;
+ }
+ } else {
+ if (mdwc->xo_vote_for_charger) {
+ struct dwc3 *dwc = platform_get_drvdata(mdwc->dwc3);
+ if (atomic_read(&dwc->in_lpm)) {
+ clk_disable_unprepare(mdwc->xo_clk);
+ dev_err(mdwc->dev, "%s TCXO disabled\n", __func__);
+ }
+ mdwc->xo_vote_for_charger = false;
+ }
+ }
+
if (mdwc->chg_type != DWC3_INVALID_CHARGER)
mdwc->chg_state = USB_CHG_STATE_DETECTED;
@@ -3313,6 +3355,7 @@ static int dwc3_msm_remove(struct platform_device *pdev)
clk_disable_unprepare(mdwc->sleep_clk);
clk_disable_unprepare(mdwc->xo_clk);
clk_put(mdwc->xo_clk);
+ mdwc->xo_vote_for_charger = false;
dwc3_msm_config_gdsc(mdwc, 0);
diff --git a/drivers/video/msm/mdss/mdss_rotator.c b/drivers/video/msm/mdss/mdss_rotator.c
index 8a5fb5e056ec..d324b04291d1 100644
--- a/drivers/video/msm/mdss/mdss_rotator.c
+++ b/drivers/video/msm/mdss/mdss_rotator.c
@@ -70,7 +70,7 @@ static struct msm_bus_scale_pdata rot_reg_bus_scale_table = {
};
static struct mdss_rot_mgr *rot_mgr;
-static void mdss_rotator_wq_handler(struct work_struct *work);
+static void mdss_rotator_work_handler(struct kthread_work *work);
static int mdss_rotator_bus_scale_set_quota(struct mdss_rot_bus_data_type *bus,
u64 quota)
@@ -834,6 +834,7 @@ static int mdss_rotator_init_queue(struct mdss_rot_mgr *mgr)
{
int i, size, ret = 0;
char name[32];
+ struct sched_param param = { .sched_priority = 5 };
size = sizeof(struct mdss_rot_queue) * mgr->queue_count;
mgr->queues = devm_kzalloc(&mgr->pdev->dev, size, GFP_KERNEL);
@@ -841,14 +842,18 @@ static int mdss_rotator_init_queue(struct mdss_rot_mgr *mgr)
return -ENOMEM;
for (i = 0; i < mgr->queue_count; i++) {
- snprintf(name, sizeof(name), "rot_workq_%d", i);
- pr_debug("work queue name=%s\n", name);
- mgr->queues[i].rot_work_queue = alloc_ordered_workqueue("%s",
- WQ_UNBOUND | WQ_MEM_RECLAIM | WQ_HIGHPRI, name);
- if (!mgr->queues[i].rot_work_queue) {
- ret = -EPERM;
+ snprintf(name, sizeof(name), "rot_thread_%d", i);
+ pr_info("work thread name=%s\n", name);
+ init_kthread_worker(&mgr->queues[i].worker);
+ mgr->queues[i].thread = kthread_run(kthread_worker_fn,
+ &mgr->queues[i].worker,
+ name);
+ if (IS_ERR(&mgr->queues[i].thread)) {
+ pr_err("Unable to start rotator thread: %d", i);
+ ret = -ENOMEM;
break;
}
+ sched_setscheduler(mgr->queues[i].thread, SCHED_FIFO, &param);
snprintf(name, sizeof(name), "rot_timeline_%d", i);
pr_debug("timeline name=%s\n", name);
@@ -878,8 +883,8 @@ static void mdss_rotator_deinit_queue(struct mdss_rot_mgr *mgr)
return;
for (i = 0; i < mgr->queue_count; i++) {
- if (mgr->queues[i].rot_work_queue)
- destroy_workqueue(mgr->queues[i].rot_work_queue);
+ if (mgr->queues[i].thread)
+ kthread_stop(mgr->queues[i].thread);
if (mgr->queues[i].timeline.timeline) {
struct sync_timeline *obj;
@@ -1016,7 +1021,7 @@ static void mdss_rotator_queue_request(struct mdss_rot_mgr *mgr,
entry = req->entries + i;
queue = entry->queue;
entry->output_fence = NULL;
- queue_work(queue->rot_work_queue, &entry->commit_work);
+ queue_kthread_work(&queue->worker, &entry->commit_work);
}
}
@@ -1513,7 +1518,8 @@ static int mdss_rotator_add_request(struct mdss_rot_mgr *mgr,
entry->request = req;
- INIT_WORK(&entry->commit_work, mdss_rotator_wq_handler);
+ init_kthread_work(&entry->commit_work,
+ mdss_rotator_work_handler);
ret = mdss_rotator_create_fence(entry);
if (ret) {
@@ -1565,7 +1571,7 @@ static void mdss_rotator_cancel_request(struct mdss_rot_mgr *mgr,
*/
for (i = req->count - 1; i >= 0; i--) {
entry = req->entries + i;
- cancel_work_sync(&entry->commit_work);
+ flush_kthread_work(&entry->commit_work);
}
for (i = req->count - 1; i >= 0; i--) {
@@ -1835,7 +1841,7 @@ static int mdss_rotator_handle_entry(struct mdss_rot_hw_resource *hw,
return ret;
}
-static void mdss_rotator_wq_handler(struct work_struct *work)
+static void mdss_rotator_work_handler(struct kthread_work *work)
{
struct mdss_rot_entry *entry;
struct mdss_rot_entry_container *request;
@@ -2020,7 +2026,7 @@ static int mdss_rotator_close_session(struct mdss_rot_mgr *mgr,
ATRACE_BEGIN(__func__);
mutex_lock(&perf->work_dis_lock);
if (mdss_rotator_is_work_pending(mgr, perf)) {
- pr_debug("Work is still pending, offload free to wq\n");
+ pr_debug("Work is still pending, offload free to worker\n");
mutex_lock(&mgr->bus_lock);
mgr->pending_close_bw_vote += perf->bw;
mutex_unlock(&mgr->bus_lock);
diff --git a/drivers/video/msm/mdss/mdss_rotator_internal.h b/drivers/video/msm/mdss/mdss_rotator_internal.h
index 2122efee6bda..d02c04043e91 100644
--- a/drivers/video/msm/mdss/mdss_rotator_internal.h
+++ b/drivers/video/msm/mdss/mdss_rotator_internal.h
@@ -70,9 +70,9 @@ struct mdss_rot_hw_resource {
};
struct mdss_rot_queue {
- struct workqueue_struct *rot_work_queue;
+ struct kthread_worker worker;
+ struct task_struct *thread;
struct mdss_rot_timeline timeline;
-
struct mutex hw_lock;
struct mdss_rot_hw_resource *hw;
};
@@ -87,7 +87,7 @@ struct mdss_rot_entry_container {
struct mdss_rot_entry {
struct mdp_rotation_item item;
- struct work_struct commit_work;
+ struct kthread_work commit_work;
struct mdss_rot_queue *queue;
struct mdss_rot_entry_container *request;
diff --git a/fs/eventpoll.c b/fs/eventpoll.c
index 1c6bba7e6aa1..08a6a6ee5ecb 100644
--- a/fs/eventpoll.c
+++ b/fs/eventpoll.c
@@ -1230,13 +1230,15 @@ static int ep_create_wakeup_source(struct epitem *epi)
const char *name;
struct wakeup_source *ws;
+ name = epi->ffd.file->f_path.dentry->d_name.name;
if (!epi->ep->ws) {
- epi->ep->ws = wakeup_source_register("eventpoll");
+ char buf[64];
+ snprintf(buf, sizeof(buf), "eventpoll pid:%d file:%s", current->pid, name);
+ epi->ep->ws = wakeup_source_register(buf);
if (!epi->ep->ws)
return -ENOMEM;
}
- name = epi->ffd.file->f_path.dentry->d_name.name;
ws = wakeup_source_register(name);
if (!ws)
diff --git a/fs/pstore/platform.c b/fs/pstore/platform.c
index 15ee78c5020b..ad1fe993d2d0 100644
--- a/fs/pstore/platform.c
+++ b/fs/pstore/platform.c
@@ -404,6 +404,40 @@ static int pstore_write_compat(enum pstore_type_id type,
size, psi);
}
+static int pstore_write_buf_user_compat(enum pstore_type_id type,
+ enum kmsg_dump_reason reason,
+ u64 *id, unsigned int part,
+ const char __user *buf,
+ bool compressed, size_t size,
+ struct pstore_info *psi)
+{
+ unsigned long flags = 0;
+ size_t i, bufsize = size;
+ long ret = 0;
+
+ if (unlikely(!access_ok(VERIFY_READ, buf, size)))
+ return -EFAULT;
+ if (bufsize > psinfo->bufsize)
+ bufsize = psinfo->bufsize;
+ spin_lock_irqsave(&psinfo->buf_lock, flags);
+ for (i = 0; i < size; ) {
+ size_t c = min(size - i, bufsize);
+
+ ret = __copy_from_user(psinfo->buf, buf + i, c);
+ if (unlikely(ret != 0)) {
+ ret = -EFAULT;
+ break;
+ }
+ ret = psi->write_buf(type, reason, id, part, psinfo->buf,
+ compressed, c, psi);
+ if (unlikely(ret < 0))
+ break;
+ i += c;
+ }
+ spin_unlock_irqrestore(&psinfo->buf_lock, flags);
+ return unlikely(ret < 0) ? ret : size;
+}
+
/*
* platform specific persistent storage driver registers with
* us here. If pstore is already mounted, call the platform
@@ -428,6 +462,8 @@ int pstore_register(struct pstore_info *psi)
if (!psi->write)
psi->write = pstore_write_compat;
+ if (!psi->write_buf_user)
+ psi->write_buf_user = pstore_write_buf_user_compat;
psinfo = psi;
mutex_init(&psinfo->read_mutex);
spin_unlock(&pstore_lock);
diff --git a/fs/pstore/pmsg.c b/fs/pstore/pmsg.c
index 5a2f05a16c1e..64b97a2966d9 100644
--- a/fs/pstore/pmsg.c
+++ b/fs/pstore/pmsg.c
@@ -19,48 +19,25 @@
#include "internal.h"
static DEFINE_MUTEX(pmsg_lock);
-#define PMSG_MAX_BOUNCE_BUFFER_SIZE (2*PAGE_SIZE)
static ssize_t write_pmsg(struct file *file, const char __user *buf,
size_t count, loff_t *ppos)
{
- size_t i, buffer_size;
- char *buffer;
+ u64 id;
+ int ret;
if (!count)
return 0;
+ /* check outside lock, page in any data. write_buf_user also checks */
if (!access_ok(VERIFY_READ, buf, count))
return -EFAULT;
- buffer_size = count;
- if (buffer_size > PMSG_MAX_BOUNCE_BUFFER_SIZE)
- buffer_size = PMSG_MAX_BOUNCE_BUFFER_SIZE;
- buffer = vmalloc(buffer_size);
- if (!buffer)
- return -ENOMEM;
-
mutex_lock(&pmsg_lock);
- for (i = 0; i < count; ) {
- size_t c = min(count - i, buffer_size);
- u64 id;
- long ret;
-
- ret = __copy_from_user(buffer, buf + i, c);
- if (unlikely(ret != 0)) {
- mutex_unlock(&pmsg_lock);
- vfree(buffer);
- return -EFAULT;
- }
- psinfo->write_buf(PSTORE_TYPE_PMSG, 0, &id, 0, buffer, 0, c,
- psinfo);
-
- i += c;
- }
-
+ ret = psinfo->write_buf_user(PSTORE_TYPE_PMSG, 0, &id, 0, buf, 0, count,
+ psinfo);
mutex_unlock(&pmsg_lock);
- vfree(buffer);
- return count;
+ return ret ? ret : count;
}
static const struct file_operations pmsg_fops = {
diff --git a/fs/pstore/ram.c b/fs/pstore/ram.c
index 58a40da3bdd7..c3b8d793d9da 100644
--- a/fs/pstore/ram.c
+++ b/fs/pstore/ram.c
@@ -307,6 +307,24 @@ static int notrace ramoops_pstore_write_buf(enum pstore_type_id type,
return 0;
}
+static int notrace ramoops_pstore_write_buf_user(enum pstore_type_id type,
+ enum kmsg_dump_reason reason,
+ u64 *id, unsigned int part,
+ const char __user *buf,
+ bool compressed, size_t size,
+ struct pstore_info *psi)
+{
+ if (type == PSTORE_TYPE_PMSG) {
+ struct ramoops_context *cxt = psi->data;
+
+ if (!cxt->mprz)
+ return -ENOMEM;
+ return persistent_ram_write_user(cxt->mprz, buf, size);
+ }
+
+ return -EINVAL;
+}
+
static int ramoops_pstore_erase(enum pstore_type_id type, u64 id, int count,
struct timespec time, struct pstore_info *psi)
{
@@ -345,6 +363,7 @@ static struct ramoops_context oops_cxt = {
.open = ramoops_pstore_open,
.read = ramoops_pstore_read,
.write_buf = ramoops_pstore_write_buf,
+ .write_buf_user = ramoops_pstore_write_buf_user,
.erase = ramoops_pstore_erase,
},
};
diff --git a/fs/pstore/ram_core.c b/fs/pstore/ram_core.c
index 76c3f80efdfa..aa9afe573155 100644
--- a/fs/pstore/ram_core.c
+++ b/fs/pstore/ram_core.c
@@ -17,15 +17,16 @@
#include <linux/device.h>
#include <linux/err.h>
#include <linux/errno.h>
-#include <linux/kernel.h>
#include <linux/init.h>
#include <linux/io.h>
+#include <linux/kernel.h>
#include <linux/list.h>
#include <linux/memblock.h>
+#include <linux/pstore_ram.h>
#include <linux/rslib.h>
#include <linux/slab.h>
+#include <linux/uaccess.h>
#include <linux/vmalloc.h>
-#include <linux/pstore_ram.h>
#include <asm/page.h>
struct persistent_ram_buffer {
@@ -303,6 +304,16 @@ static void notrace persistent_ram_update(struct persistent_ram_zone *prz,
persistent_ram_update_ecc(prz, start, count);
}
+static int notrace persistent_ram_update_user(struct persistent_ram_zone *prz,
+ const void __user *s, unsigned int start, unsigned int count)
+{
+ struct persistent_ram_buffer *buffer = prz->buffer;
+ int ret = unlikely(__copy_from_user(buffer->data + start, s, count)) ?
+ -EFAULT : 0;
+ persistent_ram_update_ecc(prz, start, count);
+ return ret;
+}
+
void persistent_ram_save_old(struct persistent_ram_zone *prz)
{
struct persistent_ram_buffer *buffer = prz->buffer;
@@ -356,6 +367,38 @@ int notrace persistent_ram_write(struct persistent_ram_zone *prz,
return count;
}
+int notrace persistent_ram_write_user(struct persistent_ram_zone *prz,
+ const void __user *s, unsigned int count)
+{
+ int rem, ret = 0, c = count;
+ size_t start;
+
+ if (unlikely(!access_ok(VERIFY_READ, s, count)))
+ return -EFAULT;
+ if (unlikely(c > prz->buffer_size)) {
+ s += c - prz->buffer_size;
+ c = prz->buffer_size;
+ }
+
+ buffer_size_add(prz, c);
+
+ start = buffer_start_add(prz, c);
+
+ rem = prz->buffer_size - start;
+ if (unlikely(rem < c)) {
+ ret = persistent_ram_update_user(prz, s, start, rem);
+ s += rem;
+ c -= rem;
+ start = 0;
+ }
+ if (likely(!ret))
+ ret = persistent_ram_update_user(prz, s, start, c);
+
+ persistent_ram_update_header_ecc(prz);
+
+ return unlikely(ret) ? ret : count;
+}
+
size_t persistent_ram_old_size(struct persistent_ram_zone *prz)
{
return prz->old_log_size;
diff --git a/include/linux/inet_diag.h b/include/linux/inet_diag.h
index 25de5e73845c..4f214275d13c 100644
--- a/include/linux/inet_diag.h
+++ b/include/linux/inet_diag.h
@@ -36,7 +36,7 @@ int inet_sk_diag_fill(struct sock *sk, struct inet_connection_sock *icsk,
struct sk_buff *skb, struct inet_diag_req_v2 *req,
struct user_namespace *user_ns,
u32 pid, u32 seq, u16 nlmsg_flags,
- const struct nlmsghdr *unlh);
+ const struct nlmsghdr *unlh, bool net_admin);
void inet_diag_dump_icsk(struct inet_hashinfo *h, struct sk_buff *skb,
struct netlink_callback *cb, struct inet_diag_req_v2 *r,
struct nlattr *bc);
diff --git a/include/linux/interrupt.h b/include/linux/interrupt.h
index 2357215b0ac4..bceb0928f8a3 100644
--- a/include/linux/interrupt.h
+++ b/include/linux/interrupt.h
@@ -402,6 +402,12 @@ enum
};
#define SOFTIRQ_STOP_IDLE_MASK (~(1 << RCU_SOFTIRQ))
+/* Softirq's where the handling might be long: */
+#define LONG_SOFTIRQ_MASK ((1 << NET_TX_SOFTIRQ) | \
+ (1 << NET_RX_SOFTIRQ) | \
+ (1 << BLOCK_SOFTIRQ) | \
+ (1 << BLOCK_IOPOLL_SOFTIRQ) | \
+ (1 << TASKLET_SOFTIRQ))
/* map softirq index to softirq name. update 'softirq_to_name' in
* kernel/softirq.c when adding a new softirq.
@@ -437,6 +443,7 @@ extern void raise_softirq_irqoff(unsigned int nr);
extern void raise_softirq(unsigned int nr);
DECLARE_PER_CPU(struct task_struct *, ksoftirqd);
+DECLARE_PER_CPU(__u32, active_softirqs);
static inline struct task_struct *this_cpu_ksoftirqd(void)
{
diff --git a/include/linux/power/htc_battery.h b/include/linux/power/htc_battery.h
index 94247c346f80..b5662e84e2f5 100644
--- a/include/linux/power/htc_battery.h
+++ b/include/linux/power/htc_battery.h
@@ -154,6 +154,7 @@ struct htc_battery_info {
struct power_supply *usb_psy;
struct power_supply *parallel_psy;
int critical_low_voltage_mv;
+ int force_shutdown_batt_vol;
int smooth_chg_full_delay_min;
int decreased_batt_level_check;
int batt_full_voltage_mv;
@@ -161,6 +162,7 @@ struct htc_battery_info {
int batt_eoc_current_ma;
int overload_curr_thr_ma;
struct wake_lock charger_exist_lock;
+ struct wake_lock batt_shutdown_lock;
struct delayed_work chg_full_check_work;
struct delayed_work is_usb_overheat_work;
struct delayed_work chk_unknown_chg_work;
diff --git a/include/linux/power_supply.h b/include/linux/power_supply.h
index 0aa38701e404..87ee0454808b 100644
--- a/include/linux/power_supply.h
+++ b/include/linux/power_supply.h
@@ -223,6 +223,7 @@ enum power_supply_property {
#ifdef CONFIG_HTC_BATT
POWER_SUPPLY_PROP_SYSTEM_SOC,
POWER_SUPPLY_PROP_TYPEC_SINK_CURRENT,
+ POWER_SUPPLY_PROP_CRITICAL_SHUTDOWN,
#endif /* CONFIG_HTC_BATT */
};
diff --git a/include/linux/pstore.h b/include/linux/pstore.h
index 8884f6e507f7..2eec52d597ce 100644
--- a/include/linux/pstore.h
+++ b/include/linux/pstore.h
@@ -22,12 +22,13 @@
#ifndef _LINUX_PSTORE_H
#define _LINUX_PSTORE_H
-#include <linux/time.h>
+#include <linux/compiler.h>
+#include <linux/errno.h>
#include <linux/kmsg_dump.h>
#include <linux/mutex.h>
-#include <linux/types.h>
#include <linux/spinlock.h>
-#include <linux/errno.h>
+#include <linux/time.h>
+#include <linux/types.h>
/* types */
enum pstore_type_id {
@@ -66,6 +67,10 @@ struct pstore_info {
enum kmsg_dump_reason reason, u64 *id,
unsigned int part, const char *buf, bool compressed,
size_t size, struct pstore_info *psi);
+ int (*write_buf_user)(enum pstore_type_id type,
+ enum kmsg_dump_reason reason, u64 *id,
+ unsigned int part, const char __user *buf,
+ bool compressed, size_t size, struct pstore_info *psi);
int (*erase)(enum pstore_type_id type, u64 id,
int count, struct timespec time,
struct pstore_info *psi);
diff --git a/include/linux/pstore_ram.h b/include/linux/pstore_ram.h
index 712757f320a4..45ac5a0d29ee 100644
--- a/include/linux/pstore_ram.h
+++ b/include/linux/pstore_ram.h
@@ -17,11 +17,12 @@
#ifndef __LINUX_PSTORE_RAM_H__
#define __LINUX_PSTORE_RAM_H__
+#include <linux/compiler.h>
#include <linux/device.h>
+#include <linux/init.h>
#include <linux/kernel.h>
#include <linux/list.h>
#include <linux/types.h>
-#include <linux/init.h>
struct persistent_ram_buffer;
struct rs_control;
@@ -59,7 +60,9 @@ void persistent_ram_free(struct persistent_ram_zone *prz);
void persistent_ram_zap(struct persistent_ram_zone *prz);
int persistent_ram_write(struct persistent_ram_zone *prz, const void *s,
- unsigned int count);
+ unsigned int count);
+int persistent_ram_write_user(struct persistent_ram_zone *prz,
+ const void __user *s, unsigned int count);
void persistent_ram_save_old(struct persistent_ram_zone *prz);
size_t persistent_ram_old_size(struct persistent_ram_zone *prz);
diff --git a/include/linux/trace_clock.h b/include/linux/trace_clock.h
index 1d7ca2739272..5ad5b6b2c1db 100644
--- a/include/linux/trace_clock.h
+++ b/include/linux/trace_clock.h
@@ -19,5 +19,6 @@ extern u64 notrace trace_clock(void);
extern u64 notrace trace_clock_jiffies(void);
extern u64 notrace trace_clock_global(void);
extern u64 notrace trace_clock_counter(void);
+extern u64 notrace trace_clock_boot(void);
#endif /* _LINUX_TRACE_CLOCK_H */
diff --git a/include/net/udp.h b/include/net/udp.h
index 07f9b70962f6..a274df0c3421 100644
--- a/include/net/udp.h
+++ b/include/net/udp.h
@@ -229,6 +229,7 @@ int udp_get_port(struct sock *sk, unsigned short snum,
int (*saddr_cmp)(const struct sock *,
const struct sock *));
void udp_err(struct sk_buff *, u32);
+int udp_abort(struct sock *sk, int err);
int udp_sendmsg(struct kiocb *iocb, struct sock *sk, struct msghdr *msg,
size_t len);
int udp_push_pending_frames(struct sock *sk);
diff --git a/include/soc/qcom/subsystem_restart.h b/include/soc/qcom/subsystem_restart.h
index 3a5f6e678b4f..c13b864b9bf1 100644
--- a/include/soc/qcom/subsystem_restart.h
+++ b/include/soc/qcom/subsystem_restart.h
@@ -17,6 +17,8 @@
#include <linux/spinlock.h>
#include <linux/interrupt.h>
+#define MAX_SSR_REASON_LEN 81U
+
struct subsys_device;
enum {
@@ -85,6 +87,7 @@ struct subsys_desc {
int sysmon_shutdown_ret;
bool system_debug;
const char *edge;
+ char last_crash_reason[MAX_SSR_REASON_LEN];
};
/**
diff --git a/include/uapi/linux/inet_diag.h b/include/uapi/linux/inet_diag.h
index d65c0a09efd3..e835704ab807 100644
--- a/include/uapi/linux/inet_diag.h
+++ b/include/uapi/linux/inet_diag.h
@@ -72,6 +72,8 @@ enum {
INET_DIAG_BC_AUTO,
INET_DIAG_BC_S_COND,
INET_DIAG_BC_D_COND,
+ INET_DIAG_BC_DEV_COND, /* u32 ifindex */
+ INET_DIAG_BC_MARK_COND,
};
struct inet_diag_hostcond {
@@ -81,6 +83,11 @@ struct inet_diag_hostcond {
__be32 addr[0];
};
+struct inet_diag_markcond {
+ __u32 mark;
+ __u32 mask;
+};
+
/* Base info structure. It contains socket identity (addrs/ports/cookie)
* and, alas, the information shown by netstat. */
struct inet_diag_msg {
@@ -111,9 +118,15 @@ enum {
INET_DIAG_SKMEMINFO,
INET_DIAG_SHUTDOWN,
INET_DIAG_DCTCPINFO,
+ INET_DIAG_PROTOCOL, /* response attribute only */
+ INET_DIAG_SKV6ONLY,
+ INET_DIAG_LOCALS,
+ INET_DIAG_PEERS,
+ INET_DIAG_PAD,
+ INET_DIAG_MARK,
};
-#define INET_DIAG_MAX INET_DIAG_DCTCPINFO
+#define INET_DIAG_MAX INET_DIAG_MARK
/* INET_DIAG_MEM */
diff --git a/include/uapi/media/msmb_ispif.h b/include/uapi/media/msmb_ispif.h
index 26bd8a2ce87f..7d4e489a3f04 100644
--- a/include/uapi/media/msmb_ispif.h
+++ b/include/uapi/media/msmb_ispif.h
@@ -105,7 +105,7 @@ enum ispif_cfg_type_t {
ISPIF_INIT,
ISPIF_CFG,
ISPIF_START_FRAME_BOUNDARY,
- ISPIF_RESTART_FRAME_BOUNDARY,
+ ISPIF_RECONFIG,
ISPIF_STOP_FRAME_BOUNDARY,
ISPIF_STOP_IMMEDIATELY,
ISPIF_RELEASE,
diff --git a/kernel/rcu/tree.c b/kernel/rcu/tree.c
index 6c5eeee441e9..69690c7d5ad2 100644
--- a/kernel/rcu/tree.c
+++ b/kernel/rcu/tree.c
@@ -1045,11 +1045,13 @@ static void rcu_dump_cpu_stacks(struct rcu_state *rsp)
}
}
-static void print_other_cpu_stall(struct rcu_state *rsp)
+static void print_other_cpu_stall(struct rcu_state *rsp, unsigned long gpnum)
{
int cpu;
long delta;
unsigned long flags;
+ unsigned long gpa;
+ unsigned long j;
int ndetected = 0;
struct rcu_node *rnp = rcu_get_root(rsp);
long totqlen = 0;
@@ -1102,10 +1104,22 @@ static void print_other_cpu_stall(struct rcu_state *rsp)
pr_cont("(detected by %d, t=%ld jiffies, g=%ld, c=%ld, q=%lu)\n",
smp_processor_id(), (long)(jiffies - rsp->gp_start),
(long)rsp->gpnum, (long)rsp->completed, totqlen);
- if (ndetected == 0)
- pr_err("INFO: Stall ended before state dump start\n");
- else
+ if (ndetected) {
rcu_dump_cpu_stacks(rsp);
+ } else {
+ if (ACCESS_ONCE(rsp->gpnum) != gpnum ||
+ ACCESS_ONCE(rsp->completed) == gpnum) {
+ pr_err("INFO: Stall ended before state dump start\n");
+ } else {
+ j = jiffies;
+ gpa = ACCESS_ONCE(rsp->gp_activity);
+ pr_err("All QSes seen, last %s kthread activity %ld (%ld-%ld), jiffies_till_next_fqs=%ld\n",
+ rsp->name, j - gpa, j, gpa,
+ jiffies_till_next_fqs);
+ /* In this case, the current CPU might be at fault. */
+ sched_show_task(current);
+ }
+ }
/* Complain about tasks blocking the grace period. */
@@ -1205,7 +1219,7 @@ static void check_cpu_stall(struct rcu_state *rsp, struct rcu_data *rdp)
ULONG_CMP_GE(j, js + RCU_STALL_RAT_DELAY)) {
/* They had a few time units to dump stack, so complain. */
- print_other_cpu_stall(rsp);
+ print_other_cpu_stall(rsp, gpnum);
}
}
@@ -1601,6 +1615,7 @@ static int rcu_gp_init(struct rcu_state *rsp)
struct rcu_data *rdp;
struct rcu_node *rnp = rcu_get_root(rsp);
+ ACCESS_ONCE(rsp->gp_activity) = jiffies;
rcu_bind_gp_kthread();
raw_spin_lock_irq(&rnp->lock);
smp_mb__after_unlock_lock();
@@ -1661,6 +1676,7 @@ static int rcu_gp_init(struct rcu_state *rsp)
rnp->grphi, rnp->qsmask);
raw_spin_unlock_irq(&rnp->lock);
cond_resched_rcu_qs();
+ ACCESS_ONCE(rsp->gp_activity) = jiffies;
}
mutex_unlock(&rsp->onoff_mutex);
@@ -1677,6 +1693,7 @@ static int rcu_gp_fqs(struct rcu_state *rsp, int fqs_state_in)
unsigned long maxj;
struct rcu_node *rnp = rcu_get_root(rsp);
+ ACCESS_ONCE(rsp->gp_activity) = jiffies;
rsp->n_force_qs++;
if (fqs_state == RCU_SAVE_DYNTICK) {
/* Collect dyntick-idle snapshots. */
@@ -1715,6 +1732,7 @@ static void rcu_gp_cleanup(struct rcu_state *rsp)
struct rcu_data *rdp;
struct rcu_node *rnp = rcu_get_root(rsp);
+ ACCESS_ONCE(rsp->gp_activity) = jiffies;
raw_spin_lock_irq(&rnp->lock);
smp_mb__after_unlock_lock();
gp_duration = jiffies - rsp->gp_start;
@@ -1751,6 +1769,7 @@ static void rcu_gp_cleanup(struct rcu_state *rsp)
nocb += rcu_future_gp_cleanup(rsp, rnp);
raw_spin_unlock_irq(&rnp->lock);
cond_resched_rcu_qs();
+ ACCESS_ONCE(rsp->gp_activity) = jiffies;
}
rnp = rcu_get_root(rsp);
raw_spin_lock_irq(&rnp->lock);
@@ -1800,6 +1819,7 @@ static int __noreturn rcu_gp_kthread(void *arg)
if (rcu_gp_init(rsp))
break;
cond_resched_rcu_qs();
+ ACCESS_ONCE(rsp->gp_activity) = jiffies;
WARN_ON(signal_pending(current));
trace_rcu_grace_period(rsp->name,
ACCESS_ONCE(rsp->gpnum),
@@ -1843,9 +1863,11 @@ static int __noreturn rcu_gp_kthread(void *arg)
ACCESS_ONCE(rsp->gpnum),
TPS("fqsend"));
cond_resched_rcu_qs();
+ ACCESS_ONCE(rsp->gp_activity) = jiffies;
} else {
/* Deal with stray signal. */
cond_resched_rcu_qs();
+ ACCESS_ONCE(rsp->gp_activity) = jiffies;
WARN_ON(signal_pending(current));
trace_rcu_grace_period(rsp->name,
ACCESS_ONCE(rsp->gpnum),
diff --git a/kernel/rcu/tree.h b/kernel/rcu/tree.h
index 0185bcc00504..81ee56afd6cf 100644
--- a/kernel/rcu/tree.h
+++ b/kernel/rcu/tree.h
@@ -493,6 +493,8 @@ struct rcu_state {
/* due to no GP active. */
unsigned long gp_start; /* Time at which GP started, */
/* but in jiffies. */
+ unsigned long gp_activity; /* Time of last GP kthread */
+ /* activity in jiffies. */
unsigned long jiffies_stall; /* Time at which to check */
/* for CPU stalls. */
unsigned long jiffies_resched; /* Time at which to resched */
diff --git a/kernel/sched/cpupri.c b/kernel/sched/cpupri.c
index 981fcd7dc394..d6f5d003793c 100644
--- a/kernel/sched/cpupri.c
+++ b/kernel/sched/cpupri.c
@@ -27,6 +27,8 @@
* of the License.
*/
+#include "sched.h"
+
#include <linux/gfp.h>
#include <linux/sched.h>
#include <linux/sched/rt.h>
@@ -51,6 +53,24 @@ static int convert_prio(int prio)
}
/**
+ * cpupri_find - remove a cpu from the mask if it is likely non-preemptible
+ * @lowest_mask: mask with selected CPUs (non-NULL)
+ */
+static void
+drop_nopreempt_cpus(struct cpumask *lowest_mask)
+{
+ unsigned cpu = cpumask_first(lowest_mask);
+ while (cpu < nr_cpu_ids) {
+ /* unlocked access */
+ struct task_struct *task = READ_ONCE(cpu_rq(cpu)->curr);
+ if (task_may_not_preempt(task, cpu)) {
+ cpumask_clear_cpu(cpu, lowest_mask);
+ }
+ cpu = cpumask_next(cpu, lowest_mask);
+ }
+}
+
+/**
* cpupri_find - find the best (lowest-pri) CPU in the system
* @cp: The cpupri context
* @p: The task
@@ -70,9 +90,11 @@ int cpupri_find(struct cpupri *cp, struct task_struct *p,
{
int idx = 0;
int task_pri = convert_prio(p->prio);
+ bool drop_nopreempts = task_pri <= MAX_RT_PRIO;
BUG_ON(task_pri >= CPUPRI_NR_PRIORITIES);
+retry:
for (idx = 0; idx < task_pri; idx++) {
struct cpupri_vec *vec = &cp->pri_to_cpu[idx];
int skip = 0;
@@ -108,7 +130,9 @@ int cpupri_find(struct cpupri *cp, struct task_struct *p,
if (lowest_mask) {
cpumask_and(lowest_mask, &p->cpus_allowed, vec->mask);
-
+ if (drop_nopreempts) {
+ drop_nopreempt_cpus(lowest_mask);
+ }
/*
* We have to ensure that we have at least one bit
* still set in the array, since the map could have
@@ -123,7 +147,14 @@ int cpupri_find(struct cpupri *cp, struct task_struct *p,
return 1;
}
-
+ /*
+ * If we can't find any non-preemptible cpu's, retry so we can
+ * find the lowest priority target and avoid priority inversion.
+ */
+ if (drop_nopreempts) {
+ drop_nopreempts = false;
+ goto retry;
+ }
return 0;
}
diff --git a/kernel/sched/fair.c b/kernel/sched/fair.c
index e3c4491b0d8f..50885d9c0e4c 100644
--- a/kernel/sched/fair.c
+++ b/kernel/sched/fair.c
@@ -6950,7 +6950,8 @@ static void update_cpu_capacity(struct sched_domain *sd, int cpu)
mcc->cpu = cpu;
#ifdef CONFIG_SCHED_DEBUG
raw_spin_unlock_irqrestore(&mcc->lock, flags);
- pr_info("CPU%d: update max cpu_capacity %lu\n", cpu, capacity);
+ printk_deferred(KERN_INFO "CPU%d: update max cpu_capacity %lu\n",
+ cpu, capacity);
goto skip_unlock;
#endif
}
diff --git a/kernel/sched/rt.c b/kernel/sched/rt.c
index 24ad9f1deb83..56316f26e25e 100644
--- a/kernel/sched/rt.c
+++ b/kernel/sched/rt.c
@@ -5,6 +5,7 @@
#include "sched.h"
+#include <linux/interrupt.h>
#include <linux/slab.h>
#include "walt.h"
@@ -1350,11 +1351,29 @@ static void yield_task_rt(struct rq *rq)
#ifdef CONFIG_SMP
static int find_lowest_rq(struct task_struct *task);
+/*
+ * Return whether the task on the given cpu is currently non-preemptible
+ * while handling a potentially long softint, or if the task is likely
+ * to block preemptions soon because it is a ksoftirq thread that is
+ * handling slow softints.
+ */
+bool
+task_may_not_preempt(struct task_struct *task, int cpu)
+{
+ __u32 softirqs = per_cpu(active_softirqs, cpu) |
+ __IRQ_STAT(cpu, __softirq_pending);
+ struct task_struct *cpu_ksoftirqd = per_cpu(ksoftirqd, cpu);
+ return ((softirqs & LONG_SOFTIRQ_MASK) &&
+ (task == cpu_ksoftirqd ||
+ task_thread_info(task)->preempt_count & SOFTIRQ_MASK));
+}
+
static int
select_task_rq_rt(struct task_struct *p, int cpu, int sd_flag, int flags)
{
struct task_struct *curr;
struct rq *rq;
+ bool may_not_preempt;
if (p->nr_cpus_allowed == 1)
goto out;
@@ -1369,7 +1388,12 @@ select_task_rq_rt(struct task_struct *p, int cpu, int sd_flag, int flags)
curr = READ_ONCE(rq->curr); /* unlocked access */
/*
- * If the current task on @p's runqueue is an RT task, then
+ * If the current task on @p's runqueue is a softirq task,
+ * it may run without preemption for a time that is
+ * ill-suited for a waiting RT task. Therefore, try to
+ * wake this RT task on another runqueue.
+ *
+ * Also, if the current task on @p's runqueue is an RT task, then
* try to see if we can wake this RT task up on another
* runqueue. Otherwise simply start this RT task
* on its current runqueue.
@@ -1390,17 +1414,21 @@ select_task_rq_rt(struct task_struct *p, int cpu, int sd_flag, int flags)
* This test is optimistic, if we get it wrong the load-balancer
* will have to sort it out.
*/
- if (curr && unlikely(rt_task(curr)) &&
- (curr->nr_cpus_allowed < 2 ||
- curr->prio <= p->prio)) {
+ may_not_preempt = task_may_not_preempt(curr, cpu);
+ if (curr && (may_not_preempt ||
+ (unlikely(rt_task(curr)) &&
+ (curr->nr_cpus_allowed < 2 ||
+ curr->prio <= p->prio)))) {
int target = find_lowest_rq(p);
-
- /*
- * Possible race. Don't bother moving it if the
+ /*
+ * If cpu is non-preemptible, prefer remote cpu
+ * even if it's running a higher-prio task.
+ * Otherwise: Possible race. Don't bother moving it if the
* destination CPU is not running a lower priority task.
- */
- if (target != -1 &&
- p->prio < cpu_rq(target)->rt.highest_prio.curr)
+ */
+ if (target != -1 &&
+ (may_not_preempt ||
+ p->prio < cpu_rq(target)->rt.highest_prio.curr))
cpu = target;
}
rcu_read_unlock();
diff --git a/kernel/sched/sched.h b/kernel/sched/sched.h
index 5aee6642c0ec..fba847e50001 100644
--- a/kernel/sched/sched.h
+++ b/kernel/sched/sched.h
@@ -1842,3 +1842,8 @@ static inline u64 irq_time_read(int cpu)
}
#endif /* CONFIG_64BIT */
#endif /* CONFIG_IRQ_TIME_ACCOUNTING */
+
+/*
+ * task_may_not_preempt - check whether a task may not be preemptible soon
+ */
+extern bool task_may_not_preempt(struct task_struct *task, int cpu);
diff --git a/kernel/softirq.c b/kernel/softirq.c
index 8b0708ad35a1..4726b886622f 100644
--- a/kernel/softirq.c
+++ b/kernel/softirq.c
@@ -58,6 +58,13 @@ static struct softirq_action softirq_vec[NR_SOFTIRQS] __cacheline_aligned_in_smp
DEFINE_PER_CPU(struct task_struct *, ksoftirqd);
+/*
+ * active_softirqs -- per cpu, a mask of softirqs that are being handled,
+ * with the expectation that approximate answers are acceptable and therefore
+ * no synchronization.
+ */
+DEFINE_PER_CPU(__u32, active_softirqs);
+
const char * const softirq_to_name[NR_SOFTIRQS] = {
"HI", "TIMER", "NET_TX", "NET_RX", "BLOCK", "BLOCK_IOPOLL",
"TASKLET", "SCHED", "HRTIMER", "RCU"
@@ -250,6 +257,7 @@ asmlinkage __visible void __do_softirq(void)
restart:
/* Reset the pending bitmask before enabling irqs */
set_softirq_pending(0);
+ __this_cpu_write(active_softirqs, pending);
local_irq_enable();
@@ -281,6 +289,7 @@ restart:
pending >>= softirq_bit;
}
+ __this_cpu_write(active_softirqs, 0);
rcu_bh_qs();
local_irq_disable();
diff --git a/kernel/trace/trace.c b/kernel/trace/trace.c
index 445f12467b6b..7922e8edef98 100644
--- a/kernel/trace/trace.c
+++ b/kernel/trace/trace.c
@@ -832,6 +832,7 @@ static struct {
{ trace_clock_jiffies, "uptime", 0 },
{ trace_clock, "perf", 1 },
{ ktime_get_mono_fast_ns, "mono", 1 },
+ { trace_clock_boot, "boot", 1 },
ARCH_TRACE_CLOCKS
};
diff --git a/kernel/trace/trace_clock.c b/kernel/trace/trace_clock.c
index 57b67b1f24d1..0bce235a7a33 100644
--- a/kernel/trace/trace_clock.c
+++ b/kernel/trace/trace_clock.c
@@ -135,3 +135,17 @@ u64 notrace trace_clock_counter(void)
{
return atomic64_add_return(1, &trace_counter);
}
+
+/*
+ * trace_clock_boot(): use CLOCK_BOOTTIME for tracing
+ * This should be equivalent to trace_clock_global for most users,
+ * but it has the added advantage of tracking time spent in suspend.
+ */
+u64 notrace trace_clock_boot(void)
+{
+ struct timespec uptime;
+ get_monotonic_boottime(&uptime);
+ return (uptime.tv_sec * 1000000000ull) + uptime.tv_nsec;
+}
+
+EXPORT_SYMBOL_GPL(trace_clock_boot);
diff --git a/net/ipv4/inet_diag.c b/net/ipv4/inet_diag.c
index 0a55318da183..2a2eecb16adf 100644
--- a/net/ipv4/inet_diag.c
+++ b/net/ipv4/inet_diag.c
@@ -48,6 +48,8 @@ struct inet_diag_entry {
struct in6_addr saddr_storage; /* for IPv4-mapped-IPv6 addresses */
struct in6_addr daddr_storage; /* for IPv4-mapped-IPv6 addresses */
#endif
+ u32 ifindex;
+ u32 mark;
};
static DEFINE_MUTEX(inet_diag_table_mutex);
@@ -89,7 +91,7 @@ int inet_sk_diag_fill(struct sock *sk, struct inet_connection_sock *icsk,
struct sk_buff *skb, struct inet_diag_req_v2 *req,
struct user_namespace *user_ns,
u32 portid, u32 seq, u16 nlmsg_flags,
- const struct nlmsghdr *unlh)
+ const struct nlmsghdr *unlh, bool net_admin)
{
const struct inet_sock *inet = inet_sk(sk);
struct inet_diag_msg *r;
@@ -150,6 +152,9 @@ int inet_sk_diag_fill(struct sock *sk, struct inet_connection_sock *icsk,
}
#endif
+ if (net_admin && nla_put_u32(skb, INET_DIAG_MARK, sk->sk_mark))
+ goto errout;
+
r->idiag_uid = from_kuid_munged(user_ns, sock_i_uid(sk));
r->idiag_inode = sock_i_ino(sk);
@@ -229,10 +234,12 @@ static int inet_csk_diag_fill(struct sock *sk,
struct sk_buff *skb, struct inet_diag_req_v2 *req,
struct user_namespace *user_ns,
u32 portid, u32 seq, u16 nlmsg_flags,
- const struct nlmsghdr *unlh)
+ const struct nlmsghdr *unlh,
+ bool net_admin)
{
return inet_sk_diag_fill(sk, inet_csk(sk),
- skb, req, user_ns, portid, seq, nlmsg_flags, unlh);
+ skb, req, user_ns, portid, seq, nlmsg_flags, unlh,
+ net_admin);
}
static int inet_twsk_diag_fill(struct inet_timewait_sock *tw,
@@ -292,14 +299,14 @@ static int sk_diag_fill(struct sock *sk, struct sk_buff *skb,
struct inet_diag_req_v2 *r,
struct user_namespace *user_ns,
u32 portid, u32 seq, u16 nlmsg_flags,
- const struct nlmsghdr *unlh)
+ const struct nlmsghdr *unlh, bool net_admin)
{
if (sk->sk_state == TCP_TIME_WAIT)
return inet_twsk_diag_fill(inet_twsk(sk), skb, r, portid, seq,
nlmsg_flags, unlh);
return inet_csk_diag_fill(sk, skb, r, user_ns, portid, seq,
- nlmsg_flags, unlh);
+ nlmsg_flags, unlh, net_admin);
}
struct sock *inet_diag_find_one_icsk(struct net *net,
@@ -368,7 +375,8 @@ int inet_diag_dump_one_icsk(struct inet_hashinfo *hashinfo,
err = sk_diag_fill(sk, rep, req,
sk_user_ns(NETLINK_CB(in_skb).sk),
NETLINK_CB(in_skb).portid,
- nlh->nlmsg_seq, 0, nlh);
+ nlh->nlmsg_seq, 0, nlh,
+ netlink_net_capable(in_skb, CAP_NET_ADMIN));
if (err < 0) {
WARN_ON(err == -EMSGSIZE);
nlmsg_free(rep);
@@ -507,6 +515,22 @@ static int inet_diag_bc_run(const struct nlattr *_bc,
yes = 0;
break;
}
+ case INET_DIAG_BC_DEV_COND: {
+ u32 ifindex;
+
+ ifindex = *((const u32 *)(op + 1));
+ if (ifindex != entry->ifindex)
+ yes = 0;
+ break;
+ }
+ case INET_DIAG_BC_MARK_COND: {
+ struct inet_diag_markcond *cond;
+
+ cond = (struct inet_diag_markcond *)(op + 1);
+ if ((entry->mark & cond->mask) != cond->mark)
+ yes = 0;
+ break;
+ }
}
if (yes) {
@@ -543,6 +567,8 @@ int inet_diag_bc_sk(const struct nlattr *bc, struct sock *sk)
entry.sport = inet->inet_num;
entry.dport = ntohs(inet->inet_dport);
entry.userlocks = sk->sk_userlocks;
+ entry.ifindex = sk->sk_bound_dev_if;
+ entry.mark = sk->sk_mark;
return inet_diag_bc_run(bc, &entry);
}
@@ -565,6 +591,17 @@ static int valid_cc(const void *bc, int len, int cc)
return 0;
}
+/* data is u32 ifindex */
+static bool valid_devcond(const struct inet_diag_bc_op *op, int len,
+ int *min_len)
+{
+ /* Check ifindex space. */
+ *min_len += sizeof(u32);
+ if (len < *min_len)
+ return false;
+
+ return true;
+}
/* Validate an inet_diag_hostcond. */
static bool valid_hostcond(const struct inet_diag_bc_op *op, int len,
int *min_len)
@@ -614,10 +651,25 @@ static inline bool valid_port_comparison(const struct inet_diag_bc_op *op,
return true;
}
-static int inet_diag_bc_audit(const void *bytecode, int bytecode_len)
+static bool valid_markcond(const struct inet_diag_bc_op *op, int len,
+ int *min_len)
+{
+ *min_len += sizeof(struct inet_diag_markcond);
+ return len >= *min_len;
+}
+
+static int inet_diag_bc_audit(const struct nlattr *attr,
+ const struct sk_buff *skb)
{
- const void *bc = bytecode;
- int len = bytecode_len;
+ bool net_admin = netlink_net_capable(skb, CAP_NET_ADMIN);
+ const void *bytecode, *bc;
+ int bytecode_len, len;
+
+ if (!attr || nla_len(attr) < sizeof(struct inet_diag_bc_op))
+ return -EINVAL;
+
+ bytecode = bc = nla_data(attr);
+ len = bytecode_len = nla_len(attr);
while (len > 0) {
const struct inet_diag_bc_op *op = bc;
@@ -630,6 +682,10 @@ static int inet_diag_bc_audit(const void *bytecode, int bytecode_len)
if (!valid_hostcond(bc, len, &min_len))
return -EINVAL;
break;
+ case INET_DIAG_BC_DEV_COND:
+ if (!valid_devcond(bc, len, &min_len))
+ return -EINVAL;
+ break;
case INET_DIAG_BC_S_GE:
case INET_DIAG_BC_S_LE:
case INET_DIAG_BC_D_GE:
@@ -637,6 +693,12 @@ static int inet_diag_bc_audit(const void *bytecode, int bytecode_len)
if (!valid_port_comparison(bc, len, &min_len))
return -EINVAL;
break;
+ case INET_DIAG_BC_MARK_COND:
+ if (!net_admin)
+ return -EPERM;
+ if (!valid_markcond(bc, len, &min_len))
+ return -EINVAL;
+ break;
case INET_DIAG_BC_AUTO:
case INET_DIAG_BC_JMP:
case INET_DIAG_BC_NOP:
@@ -665,7 +727,8 @@ static int inet_csk_diag_dump(struct sock *sk,
struct sk_buff *skb,
struct netlink_callback *cb,
struct inet_diag_req_v2 *r,
- const struct nlattr *bc)
+ const struct nlattr *bc,
+ bool net_admin)
{
if (!inet_diag_bc_sk(bc, sk))
return 0;
@@ -673,7 +736,8 @@ static int inet_csk_diag_dump(struct sock *sk,
return inet_csk_diag_fill(sk, skb, r,
sk_user_ns(NETLINK_CB(cb->skb).sk),
NETLINK_CB(cb->skb).portid,
- cb->nlh->nlmsg_seq, NLM_F_MULTI, cb->nlh);
+ cb->nlh->nlmsg_seq, NLM_F_MULTI, cb->nlh,
+ net_admin);
}
static int inet_twsk_diag_dump(struct sock *sk,
@@ -701,6 +765,7 @@ static int inet_twsk_diag_dump(struct sock *sk,
entry.sport = tw->tw_num;
entry.dport = ntohs(tw->tw_dport);
entry.userlocks = 0;
+ entry.mark = 0;
if (!inet_diag_bc_run(bc, &entry))
return 0;
@@ -827,6 +892,7 @@ static int inet_diag_dump_reqs(struct sk_buff *skb, struct sock *sk,
if (bc != NULL) {
entry.sport = inet->inet_num;
entry.userlocks = sk->sk_userlocks;
+ entry.mark = sk->sk_mark;
}
for (j = s_j; j < lopt->nr_table_entries; j++) {
@@ -876,6 +942,7 @@ void inet_diag_dump_icsk(struct inet_hashinfo *hashinfo, struct sk_buff *skb,
int i, num;
int s_i, s_num;
struct net *net = sock_net(skb->sk);
+ bool net_admin = netlink_net_capable(cb->skb, CAP_NET_ADMIN);
s_i = cb->args[1];
s_num = num = cb->args[2];
@@ -916,7 +983,8 @@ void inet_diag_dump_icsk(struct inet_hashinfo *hashinfo, struct sk_buff *skb,
cb->args[3] > 0)
goto syn_recv;
- if (inet_csk_diag_dump(sk, skb, cb, r, bc) < 0) {
+ if (inet_csk_diag_dump(sk, skb, cb, r,
+ bc, net_admin) < 0) {
spin_unlock_bh(&ilb->lock);
goto done;
}
@@ -988,7 +1056,8 @@ skip_listen_ht:
if (sk->sk_state == TCP_TIME_WAIT)
res = inet_twsk_diag_dump(sk, skb, cb, r, bc);
else
- res = inet_csk_diag_dump(sk, skb, cb, r, bc);
+ res = inet_csk_diag_dump(sk, skb, cb, r, bc,
+ net_admin);
if (res < 0) {
spin_unlock_bh(lock);
goto done;
@@ -1093,13 +1162,13 @@ static int inet_diag_rcv_msg_compat(struct sk_buff *skb, struct nlmsghdr *nlh)
if (nlh->nlmsg_flags & NLM_F_DUMP) {
if (nlmsg_attrlen(nlh, hdrlen)) {
struct nlattr *attr;
+ int err;
attr = nlmsg_find_attr(nlh, hdrlen,
INET_DIAG_REQ_BYTECODE);
- if (attr == NULL ||
- nla_len(attr) < sizeof(struct inet_diag_bc_op) ||
- inet_diag_bc_audit(nla_data(attr), nla_len(attr)))
- return -EINVAL;
+ err = inet_diag_bc_audit(attr, skb);
+ if (err)
+ return err;
}
{
struct netlink_dump_control c = {
@@ -1124,12 +1193,13 @@ static int inet_diag_handler_cmd(struct sk_buff *skb, struct nlmsghdr *h)
h->nlmsg_flags & NLM_F_DUMP) {
if (nlmsg_attrlen(h, hdrlen)) {
struct nlattr *attr;
+ int err;
+
attr = nlmsg_find_attr(h, hdrlen,
INET_DIAG_REQ_BYTECODE);
- if (attr == NULL ||
- nla_len(attr) < sizeof(struct inet_diag_bc_op) ||
- inet_diag_bc_audit(nla_data(attr), nla_len(attr)))
- return -EINVAL;
+ err = inet_diag_bc_audit(attr, skb);
+ if (err)
+ return err;
}
{
struct netlink_dump_control c = {
diff --git a/net/ipv4/udp.c b/net/ipv4/udp.c
index 44a7c83d1a36..c621c6fc6e80 100644
--- a/net/ipv4/udp.c
+++ b/net/ipv4/udp.c
@@ -2239,6 +2239,20 @@ unsigned int udp_poll(struct file *file, struct socket *sock, poll_table *wait)
}
EXPORT_SYMBOL(udp_poll);
+int udp_abort(struct sock *sk, int err)
+{
+ lock_sock(sk);
+
+ sk->sk_err = err;
+ sk->sk_error_report(sk);
+ udp_disconnect(sk, 0);
+
+ release_sock(sk);
+
+ return 0;
+}
+EXPORT_SYMBOL_GPL(udp_abort);
+
struct proto udp_prot = {
.name = "UDP",
.owner = THIS_MODULE,
@@ -2270,6 +2284,7 @@ struct proto udp_prot = {
.compat_getsockopt = compat_udp_getsockopt,
#endif
.clear_sk = sk_prot_clear_portaddr_nulls,
+ .diag_destroy = udp_abort,
};
EXPORT_SYMBOL(udp_prot);
diff --git a/net/ipv4/udp_diag.c b/net/ipv4/udp_diag.c
index 4a000f1dd757..9f5d1419f628 100644
--- a/net/ipv4/udp_diag.c
+++ b/net/ipv4/udp_diag.c
@@ -19,7 +19,7 @@
static int sk_diag_dump(struct sock *sk, struct sk_buff *skb,
struct netlink_callback *cb, struct inet_diag_req_v2 *req,
- struct nlattr *bc)
+ struct nlattr *bc, bool net_admin)
{
if (!inet_diag_bc_sk(bc, sk))
return 0;
@@ -27,7 +27,7 @@ static int sk_diag_dump(struct sock *sk, struct sk_buff *skb,
return inet_sk_diag_fill(sk, NULL, skb, req,
sk_user_ns(NETLINK_CB(cb->skb).sk),
NETLINK_CB(cb->skb).portid,
- cb->nlh->nlmsg_seq, NLM_F_MULTI, cb->nlh);
+ cb->nlh->nlmsg_seq, NLM_F_MULTI, cb->nlh, net_admin);
}
static int udp_dump_one(struct udp_table *tbl, struct sk_buff *in_skb,
@@ -73,7 +73,8 @@ static int udp_dump_one(struct udp_table *tbl, struct sk_buff *in_skb,
err = inet_sk_diag_fill(sk, NULL, rep, req,
sk_user_ns(NETLINK_CB(in_skb).sk),
NETLINK_CB(in_skb).portid,
- nlh->nlmsg_seq, 0, nlh);
+ nlh->nlmsg_seq, 0, nlh,
+ netlink_net_capable(in_skb, CAP_NET_ADMIN));
if (err < 0) {
WARN_ON(err == -EMSGSIZE);
kfree_skb(rep);
@@ -95,6 +96,7 @@ static void udp_dump(struct udp_table *table, struct sk_buff *skb, struct netlin
{
int num, s_num, slot, s_slot;
struct net *net = sock_net(skb->sk);
+ bool net_admin = netlink_net_capable(cb->skb, CAP_NET_ADMIN);
s_slot = cb->args[0];
num = s_num = cb->args[1];
@@ -129,7 +131,7 @@ static void udp_dump(struct udp_table *table, struct sk_buff *skb, struct netlin
r->id.idiag_dport)
goto next;
- if (sk_diag_dump(sk, skb, cb, r, bc) < 0) {
+ if (sk_diag_dump(sk, skb, cb, r, bc, net_admin) < 0) {
spin_unlock_bh(&hslot->lock);
goto done;
}
@@ -162,11 +164,87 @@ static void udp_diag_get_info(struct sock *sk, struct inet_diag_msg *r,
r->idiag_wqueue = sk_wmem_alloc_get(sk);
}
+#ifdef CONFIG_INET_DIAG_DESTROY
+static int __udp_diag_destroy(struct sk_buff *in_skb,
+ struct inet_diag_req_v2 *req,
+ struct udp_table *tbl)
+{
+ struct net *net = sock_net(in_skb->sk);
+ struct sock *sk;
+ int err;
+
+ rcu_read_lock();
+
+ if (req->sdiag_family == AF_INET)
+ sk = __udp4_lib_lookup(net,
+ req->id.idiag_dst[0], req->id.idiag_dport,
+ req->id.idiag_src[0], req->id.idiag_sport,
+ req->id.idiag_if, tbl);
+#if IS_ENABLED(CONFIG_IPV6)
+ else if (req->sdiag_family == AF_INET6) {
+ if (ipv6_addr_v4mapped((struct in6_addr *)req->id.idiag_dst) &&
+ ipv6_addr_v4mapped((struct in6_addr *)req->id.idiag_src))
+ sk = __udp4_lib_lookup(net,
+ req->id.idiag_dst[3], req->id.idiag_dport,
+ req->id.idiag_src[3], req->id.idiag_sport,
+ req->id.idiag_if, tbl);
+
+ else
+ sk = __udp6_lib_lookup(net,
+ (struct in6_addr *)req->id.idiag_dst,
+ req->id.idiag_dport,
+ (struct in6_addr *)req->id.idiag_src,
+ req->id.idiag_sport,
+ req->id.idiag_if, tbl);
+ }
+#endif
+ else {
+ rcu_read_unlock();
+ return -EINVAL;
+ }
+
+ if (sk && !atomic_inc_not_zero(&sk->sk_refcnt))
+ sk = NULL;
+
+ rcu_read_unlock();
+
+ if (!sk)
+ return -ENOENT;
+
+ if (sock_diag_check_cookie(sk, req->id.idiag_cookie)) {
+ sock_put(sk);
+ return -ENOENT;
+ }
+
+ err = sock_diag_destroy(sk, ECONNABORTED);
+
+ sock_put(sk);
+
+ return err;
+}
+
+static int udp_diag_destroy(struct sk_buff *in_skb,
+ struct inet_diag_req_v2 *req)
+{
+ return __udp_diag_destroy(in_skb, req, &udp_table);
+}
+
+static int udplite_diag_destroy(struct sk_buff *in_skb,
+ struct inet_diag_req_v2 *req)
+{
+ return __udp_diag_destroy(in_skb, req, &udplite_table);
+}
+
+#endif
+
static const struct inet_diag_handler udp_diag_handler = {
.dump = udp_diag_dump,
.dump_one = udp_diag_dump_one,
.idiag_get_info = udp_diag_get_info,
.idiag_type = IPPROTO_UDP,
+#ifdef CONFIG_INET_DIAG_DESTROY
+ .destroy = udp_diag_destroy,
+#endif
};
static void udplite_diag_dump(struct sk_buff *skb, struct netlink_callback *cb,
@@ -186,6 +264,9 @@ static const struct inet_diag_handler udplite_diag_handler = {
.dump_one = udplite_diag_dump_one,
.idiag_get_info = udp_diag_get_info,
.idiag_type = IPPROTO_UDPLITE,
+#ifdef CONFIG_INET_DIAG_DESTROY
+ .destroy = udplite_diag_destroy,
+#endif
};
static int __init udp_diag_init(void)
diff --git a/net/ipv6/icmp.c b/net/ipv6/icmp.c
index 070d591332c3..1415f1327dd6 100644
--- a/net/ipv6/icmp.c
+++ b/net/ipv6/icmp.c
@@ -97,7 +97,7 @@ static void icmpv6_err(struct sk_buff *skb, struct inet6_skb_parm *opt,
if (!(type & ICMPV6_INFOMSG_MASK))
if (icmp6->icmp6_type == ICMPV6_ECHO_REQUEST)
- ping_err(skb, offset, info);
+ ping_err(skb, offset, ntohl(info));
}
static int icmpv6_rcv(struct sk_buff *skb);
diff --git a/net/ipv6/ping.c b/net/ipv6/ping.c
index 75aa8c1c403b..51f5bce11761 100644
--- a/net/ipv6/ping.c
+++ b/net/ipv6/ping.c
@@ -85,7 +85,7 @@ int ping_v6_sendmsg(struct kiocb *iocb, struct sock *sk, struct msghdr *msg,
struct icmp6hdr user_icmph;
int addr_type;
struct in6_addr *daddr;
- int iif = 0;
+ int oif = 0;
struct flowi6 fl6;
int err;
int hlimit;
@@ -107,25 +107,30 @@ int ping_v6_sendmsg(struct kiocb *iocb, struct sock *sk, struct msghdr *msg,
if (u->sin6_family != AF_INET6) {
return -EAFNOSUPPORT;
}
- if (sk->sk_bound_dev_if &&
- sk->sk_bound_dev_if != u->sin6_scope_id) {
- return -EINVAL;
- }
daddr = &(u->sin6_addr);
- iif = u->sin6_scope_id;
+ if (__ipv6_addr_needs_scope_id(ipv6_addr_type(daddr)))
+ oif = u->sin6_scope_id;
} else {
if (sk->sk_state != TCP_ESTABLISHED)
return -EDESTADDRREQ;
daddr = &sk->sk_v6_daddr;
}
- if (!iif)
- iif = sk->sk_bound_dev_if;
+ if (!oif)
+ oif = sk->sk_bound_dev_if;
+
+ if (!oif)
+ oif = np->sticky_pktinfo.ipi6_ifindex;
+
+ if (!oif && ipv6_addr_is_multicast(daddr))
+ oif = np->mcast_oif;
+ else if (!oif)
+ oif = np->ucast_oif;
addr_type = ipv6_addr_type(daddr);
- if (__ipv6_addr_needs_scope_id(addr_type) && !iif)
- return -EINVAL;
- if (addr_type & IPV6_ADDR_MAPPED)
+ if ((__ipv6_addr_needs_scope_id(addr_type) && !oif) ||
+ (addr_type & IPV6_ADDR_MAPPED) ||
+ (oif && sk->sk_bound_dev_if && oif != sk->sk_bound_dev_if))
return -EINVAL;
/* TODO: use ip6_datagram_send_ctl to get options from cmsg */
@@ -135,17 +140,13 @@ int ping_v6_sendmsg(struct kiocb *iocb, struct sock *sk, struct msghdr *msg,
fl6.flowi6_proto = IPPROTO_ICMPV6;
fl6.saddr = np->saddr;
fl6.daddr = *daddr;
+ fl6.flowi6_oif = oif;
fl6.flowi6_mark = sk->sk_mark;
fl6.flowi6_uid = sock_i_uid(sk);
fl6.fl6_icmp_type = user_icmph.icmp6_type;
fl6.fl6_icmp_code = user_icmph.icmp6_code;
security_sk_classify_flow(sk, flowi6_to_flowi(&fl6));
- if (!fl6.flowi6_oif && ipv6_addr_is_multicast(&fl6.daddr))
- fl6.flowi6_oif = np->mcast_oif;
- else if (!fl6.flowi6_oif)
- fl6.flowi6_oif = np->ucast_oif;
-
dst = ip6_sk_dst_lookup_flow(sk, &fl6, daddr);
if (IS_ERR(dst))
return PTR_ERR(dst);
@@ -155,11 +156,6 @@ int ping_v6_sendmsg(struct kiocb *iocb, struct sock *sk, struct msghdr *msg,
if (!np)
return -EBADF;
- if (!fl6.flowi6_oif && ipv6_addr_is_multicast(&fl6.daddr))
- fl6.flowi6_oif = np->mcast_oif;
- else if (!fl6.flowi6_oif)
- fl6.flowi6_oif = np->ucast_oif;
-
pfh.icmph.type = user_icmph.icmp6_type;
pfh.icmph.code = user_icmph.icmp6_code;
pfh.icmph.checksum = 0;
diff --git a/net/ipv6/udp.c b/net/ipv6/udp.c
index 978641648951..e4a05fa60130 100644
--- a/net/ipv6/udp.c
+++ b/net/ipv6/udp.c
@@ -1507,6 +1507,7 @@ struct proto udpv6_prot = {
.compat_getsockopt = compat_udpv6_getsockopt,
#endif
.clear_sk = udp_v6_clear_sk,
+ .diag_destroy = udp_abort,
};
static struct inet_protosw udpv6_protosw = {
diff --git a/scripts/gcc-wrapper.py b/scripts/gcc-wrapper.py
deleted file mode 100755
index bb0ecb977165..000000000000
--- a/scripts/gcc-wrapper.py
+++ /dev/null
@@ -1,102 +0,0 @@
-#! /usr/bin/env python2
-# -*- coding: utf-8 -*-
-
-# Copyright (c) 2011-2015, The Linux Foundation. All rights reserved.
-#
-# Redistribution and use in source and binary forms, with or without
-# modification, are permitted provided that the following conditions are met:
-# * Redistributions of source code must retain the above copyright
-# notice, this list of conditions and the following disclaimer.
-# * Redistributions in binary form must reproduce the above copyright
-# notice, this list of conditions and the following disclaimer in the
-# documentation and/or other materials provided with the distribution.
-# * Neither the name of The Linux Foundation nor
-# the names of its contributors may be used to endorse or promote
-# products derived from this software without specific prior written
-# permission.
-#
-# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
-# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
-# IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
-# NON-INFRINGEMENT ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
-# CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
-# EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
-# PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
-# OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
-# WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
-# OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
-# ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-
-# Invoke gcc, looking for warnings, and causing a failure if there are
-# non-whitelisted warnings.
-
-import errno
-import re
-import os
-import sys
-import subprocess
-
-# Note that gcc uses unicode, which may depend on the locale. TODO:
-# force LANG to be set to en_US.UTF-8 to get consistent warnings.
-
-allowed_warnings = set([
- "fdt.c:932",
- "hid-magicmouse.c:579",
- "sysrq.c:956",
- "hci_sock.c:980",
- "pppopns.c:296",
- "pppopns.c:305",
- "pppopns.c:336",
- ])
-
-# Capture the name of the object file, can find it.
-ofile = None
-
-warning_re = re.compile(r'''(.*/|)([^/]+\.[a-z]+:\d+):(\d+:)? warning:''')
-def interpret_warning(line):
- """Decode the message from gcc. The messages we care about have a filename, and a warning"""
- line = line.rstrip('\n')
- m = warning_re.match(line)
- if m and m.group(2) not in allowed_warnings:
- print "error, forbidden warning:", m.group(2)
-
- # If there is a warning, remove any object if it exists.
- if ofile:
- try:
- os.remove(ofile)
- except OSError:
- pass
- sys.exit(1)
-
-def run_gcc():
- args = sys.argv[1:]
- # Look for -o
- try:
- i = args.index('-o')
- global ofile
- ofile = args[i+1]
- except (ValueError, IndexError):
- pass
-
- compiler = sys.argv[0]
-
- try:
- proc = subprocess.Popen(args, stderr=subprocess.PIPE)
- for line in proc.stderr:
- print line,
- interpret_warning(line)
-
- result = proc.wait()
- except OSError as e:
- result = e.errno
- if result == errno.ENOENT:
- print args[0] + ':',e.strerror
- print 'Is your PATH set correctly?'
- else:
- print ' '.join(args), str(e)
-
- return result
-
-if __name__ == '__main__':
- status = run_gcc()
- sys.exit(status)
diff --git a/sound/soc/codecs/wcd9335.c b/sound/soc/codecs/wcd9335.c
index 926ae130e92d..aa32fd1127fc 100755
--- a/sound/soc/codecs/wcd9335.c
+++ b/sound/soc/codecs/wcd9335.c
@@ -4372,9 +4372,11 @@ static int tasha_codec_hphl_dac_event(struct snd_soc_dapm_widget *w,
if (!ret) {
wcd_clsh_imped_config(codec, impedl, false);
set_bit(CLASSH_CONFIG, &tasha->status_mask);
- } else
+ } else {
dev_dbg(codec->dev, "%s: Failed to get mbhc impedance %d\n",
__func__, ret);
+ ret = 0;
+ }
break;
diff --git a/sound/soc/msm/msm-cpe-lsm.c b/sound/soc/msm/msm-cpe-lsm.c
index 8588a4bcb4be..5c21e2e30244 100644
--- a/sound/soc/msm/msm-cpe-lsm.c
+++ b/sound/soc/msm/msm-cpe-lsm.c
@@ -980,8 +980,7 @@ static int msm_cpe_lsm_get_conf_levels(
goto done;
}
- session->conf_levels = kzalloc(session->num_confidence_levels,
- GFP_KERNEL);
+ session->conf_levels = vzalloc(session->num_confidence_levels);
if (!session->conf_levels) {
pr_err("%s: No memory for confidence levels %u\n",
__func__, session->num_confidence_levels);
@@ -994,7 +993,7 @@ static int msm_cpe_lsm_get_conf_levels(
session->num_confidence_levels)) {
pr_err("%s: copy_from_user failed for confidence levels %u\n",
__func__, session->num_confidence_levels);
- kfree(session->conf_levels);
+ vfree(session->conf_levels);
session->conf_levels = NULL;
rc = -EFAULT;
goto done;
@@ -1237,12 +1236,12 @@ static int msm_cpe_lsm_ioctl_shared(struct snd_pcm_substream *substream,
break;
}
- session->snd_model_data = kzalloc(snd_model.data_size,
- GFP_KERNEL);
+ session->snd_model_data = vzalloc(snd_model.data_size);
if (!session->snd_model_data) {
dev_err(rtd->dev, "%s: No memory for sound model\n",
__func__);
- kfree(session->conf_levels);
+ vfree(session->conf_levels);
+ session->conf_levels = NULL;
return -ENOMEM;
}
session->snd_model_size = snd_model.data_size;
@@ -1252,8 +1251,10 @@ static int msm_cpe_lsm_ioctl_shared(struct snd_pcm_substream *substream,
dev_err(rtd->dev,
"%s: copy_from_user failed for snd_model\n",
__func__);
- kfree(session->conf_levels);
- kfree(session->snd_model_data);
+ vfree(session->conf_levels);
+ session->conf_levels = NULL;
+ vfree(session->snd_model_data);
+ session->snd_model_data = NULL;
return -EFAULT;
}
@@ -1263,8 +1264,10 @@ static int msm_cpe_lsm_ioctl_shared(struct snd_pcm_substream *substream,
dev_err(rtd->dev,
"%s: shared memory allocation failed, err = %d\n",
__func__, rc);
- kfree(session->snd_model_data);
- kfree(session->conf_levels);
+ vfree(session->conf_levels);
+ session->conf_levels = NULL;
+ vfree(session->snd_model_data);
+ session->snd_model_data = NULL;
return rc;
}
@@ -1276,8 +1279,10 @@ static int msm_cpe_lsm_ioctl_shared(struct snd_pcm_substream *substream,
"%s: snd_model_reg failed, err = %d\n",
__func__, rc);
lsm_ops->lsm_shmem_dealloc(cpe->core_handle, session);
- kfree(session->snd_model_data);
- kfree(session->conf_levels);
+ vfree(session->conf_levels);
+ session->conf_levels = NULL;
+ vfree(session->snd_model_data);
+ session->snd_model_data = NULL;
return rc;
}
@@ -1337,10 +1342,10 @@ static int msm_cpe_lsm_ioctl_shared(struct snd_pcm_substream *substream,
return rc;
}
- kfree(session->snd_model_data);
- kfree(session->conf_levels);
- session->snd_model_data = NULL;
+ vfree(session->conf_levels);
session->conf_levels = NULL;
+ vfree(session->snd_model_data);
+ session->snd_model_data = NULL;
rc = lsm_ops->lsm_shmem_dealloc(cpe->core_handle, session);
if (rc != 0) {
@@ -1496,16 +1501,16 @@ static int msm_cpe_lsm_ioctl_shared(struct snd_pcm_substream *substream,
rc = lsm_ops->lsm_set_data(cpe->core_handle, session,
det_params.detect_mode,
det_params.detect_failure);
+
+ vfree(session->conf_levels);
+ session->conf_levels = NULL;
+
if (rc) {
dev_err(rtd->dev,
"%s: lsm_set_data failed, err = %d\n",
__func__, rc);
return rc;
}
-
- kfree(session->conf_levels);
- session->conf_levels = NULL;
-
break;
case SNDRV_LSM_OUT_FORMAT_CFG: {
diff --git a/sound/soc/msm/qdsp6v2/msm-pcm-q6-noirq.c b/sound/soc/msm/qdsp6v2/msm-pcm-q6-noirq.c
index 7d433a1c5438..05c5e1e8a50a 100644
--- a/sound/soc/msm/qdsp6v2/msm-pcm-q6-noirq.c
+++ b/sound/soc/msm/qdsp6v2/msm-pcm-q6-noirq.c
@@ -390,6 +390,30 @@ static int msm_pcm_trigger(struct snd_pcm_substream *substream, int cmd)
return ret;
}
+static int msm_pcm_ioctl(struct snd_pcm_substream *substream,
+ unsigned int cmd, void *arg)
+{
+ struct snd_pcm_runtime *runtime = substream->runtime;
+ struct msm_audio *prtd = runtime->private_data;
+ int dir = (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) ? 0 : 1;
+ struct audio_buffer *buf;
+
+ switch (cmd) {
+ case SNDRV_PCM_IOCTL1_RESET:
+ pr_debug("%s: %s SNDRV_PCM_IOCTL1_RESET\n", __func__,
+ dir == 0 ? "P" : "C");
+ buf = q6asm_shared_io_buf(prtd->audio_client, dir);
+
+ if (buf && buf->data)
+ memset(buf->data, 0, buf->actual_size);
+ break;
+ default:
+ break;
+ }
+
+ return snd_pcm_lib_ioctl(substream, cmd, arg);
+}
+
static snd_pcm_uframes_t msm_pcm_pointer(struct snd_pcm_substream *substream)
{
struct snd_pcm_runtime *runtime = substream->runtime;
@@ -723,7 +747,7 @@ static struct snd_pcm_ops msm_pcm_ops = {
.prepare = msm_pcm_prepare,
.copy = msm_pcm_copy,
.hw_params = msm_pcm_hw_params,
- .ioctl = snd_pcm_lib_ioctl,
+ .ioctl = msm_pcm_ioctl,
.trigger = msm_pcm_trigger,
.pointer = msm_pcm_pointer,
.mmap = msm_pcm_mmap,
diff --git a/sound/soc/msm/qdsp6v2/msm-pcm-q6-v2.c b/sound/soc/msm/qdsp6v2/msm-pcm-q6-v2.c
index bc73018fcee6..3c117e755164 100644
--- a/sound/soc/msm/qdsp6v2/msm-pcm-q6-v2.c
+++ b/sound/soc/msm/qdsp6v2/msm-pcm-q6-v2.c
@@ -148,6 +148,13 @@ static void event_handler(uint32_t opcode,
case ASM_DATA_EVENT_WRITE_DONE_V2: {
pr_debug("ASM_DATA_EVENT_WRITE_DONE_V2\n");
pr_debug("Buffer Consumed = 0x%08x\n", *ptrmem);
+
+ if (payload[3]) {
+ pr_err("%s WRITE FAILED w/ err 0x%x\n",
+ __func__,
+ payload[3]);
+ }
+
prtd->pcm_irq_pos += prtd->pcm_count;
if (atomic_read(&prtd->start))
snd_pcm_period_elapsed(substream);
diff --git a/sound/soc/msm/qdsp6v2/msm-pcm-routing-v2.c b/sound/soc/msm/qdsp6v2/msm-pcm-routing-v2.c
index 77433384a139..97c914ac35a4 100755
--- a/sound/soc/msm/qdsp6v2/msm-pcm-routing-v2.c
+++ b/sound/soc/msm/qdsp6v2/msm-pcm-routing-v2.c
@@ -2270,6 +2270,7 @@ static int msm_routing_ec_ref_rx_put(struct snd_kcontrol *kcontrol,
int mux = ucontrol->value.enumerated.item[0];
struct soc_enum *e = (struct soc_enum *)kcontrol->private_value;
struct snd_soc_dapm_update *update = NULL;
+ int valid_port = true;
mutex_lock(&routing_lock);
switch (ucontrol->value.integer.value[0]) {
@@ -2345,7 +2346,12 @@ static int msm_routing_ec_ref_rx_put(struct snd_kcontrol *kcontrol,
msm_route_ec_ref_rx = 18;
ec_ref_port_id = AFE_PORT_ID_TERTIARY_TDM_TX;
break;
+ case 19:
+ msm_route_ec_ref_rx = 19;
+ ec_ref_port_id = AFE_PORT_ID_PRIMARY_PCM_RX;
+ break;
default:
+ valid_port = false;
msm_route_ec_ref_rx = 0; /* NONE */
pr_err("%s EC ref rx %ld not valid\n",
__func__, ucontrol->value.integer.value[0]);
@@ -2356,7 +2362,10 @@ static int msm_routing_ec_ref_rx_put(struct snd_kcontrol *kcontrol,
pr_debug("%s: msm_route_ec_ref_rx = %d\n",
__func__, msm_route_ec_ref_rx);
mutex_unlock(&routing_lock);
- snd_soc_dapm_mux_update_power(widget->dapm, kcontrol, mux, e, update);
+
+ if (valid_port)
+ snd_soc_dapm_mux_update_power(widget->dapm, kcontrol, mux, e, update);
+
return 0;
}
@@ -2365,7 +2374,7 @@ static const char *const ec_ref_rx[] = { "None", "SLIM_RX", "I2S_RX",
"TERT_MI2S_TX", "QUAT_MI2S_TX", "SEC_I2S_RX", "PROXY_RX",
"SLIM_5_RX", "SLIM_1_TX", "QUAT_TDM_TX_1",
"QUAT_TDM_RX_0", "QUAT_TDM_RX_1", "QUAT_TDM_RX_2", "SLIM_6_RX",
- "TERT_MI2S_RX", "QUAT_MI2S_RX", "TERT_TDM_TX_0"};
+ "TERT_MI2S_RX", "QUAT_MI2S_RX", "TERT_TDM_TX_0", "AUX_PCM_RX"};
static const struct soc_enum msm_route_ec_ref_rx_enum[] = {
SOC_ENUM_SINGLE_EXT(ARRAY_SIZE(ec_ref_rx), ec_ref_rx),
diff --git a/verity_rdev_keys.der.x509 b/verity_rdev_keys.der.x509
new file mode 100644
index 000000000000..7848032f2974
--- /dev/null
+++ b/verity_rdev_keys.der.x509
Binary files differ