summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--Documentation/devicetree/bindings/clock/sunxi.txt2
-rw-r--r--Documentation/devicetree/bindings/soc/qcom/qpnp-haptic.txt4
-rw-r--r--Makefile2
-rw-r--r--arch/arc/include/asm/entry-arcv2.h2
-rw-r--r--arch/arc/include/asm/ptrace.h2
-rw-r--r--arch/arm/boot/dts/qcom/msm-pm660l.dtsi3
-rw-r--r--arch/arm/boot/dts/qcom/msm-pmi8998.dtsi3
-rw-r--r--arch/arm/boot/dts/qcom/msm8996pro.dtsi57
-rw-r--r--arch/arm/boot/dts/qcom/msm8998-camera-sensor-mtp.dtsi54
-rw-r--r--arch/arm/boot/dts/qcom/msm8998-interposer-camera-sensor-mtp.dtsi12
-rw-r--r--arch/arm/boot/dts/qcom/msm8998-interposer-camera-sensor-qrd.dtsi12
-rw-r--r--arch/arm/boot/dts/qcom/msm8998-pinctrl.dtsi71
-rw-r--r--arch/arm/boot/dts/qcom/sdm660-camera-sensor-mtp.dtsi206
-rw-r--r--arch/arm/boot/dts/qcom/sdm660-camera.dtsi32
-rw-r--r--arch/arm/boot/dts/qcom/sdm660-pinctrl.dtsi70
-rw-r--r--arch/arm/mach-omap2/timer.c7
-rw-r--r--arch/arm64/configs/msm-auto-perf_defconfig2
-rw-r--r--arch/arm64/configs/msm-auto_defconfig2
-rw-r--r--arch/arm64/configs/msmcortex-perf_defconfig1
-rw-r--r--arch/arm64/configs/msmcortex_mediabox-perf_defconfig642
-rw-r--r--arch/mips/kernel/crash.c16
-rw-r--r--arch/mips/kernel/elf.c2
-rw-r--r--arch/mips/kernel/kgdb.c48
-rw-r--r--arch/sparc/include/asm/pgtable_64.h15
-rw-r--r--arch/sparc/mm/init_64.c2
-rw-r--r--arch/x86/kernel/ftrace.c12
-rw-r--r--arch/x86/xen/time.c6
-rw-r--r--crypto/testmgr.c5
-rw-r--r--drivers/bluetooth/bluetooth-power.c1
-rw-r--r--drivers/bluetooth/btfm_slim_codec.c3
-rw-r--r--drivers/char/adsprpc.c13
-rw-r--r--drivers/char/diag/diagchar_core.c2
-rw-r--r--drivers/clk/sunxi/clk-simple-gates.c2
-rw-r--r--drivers/crypto/msm/ota_crypto.c3
-rw-r--r--drivers/gpu/drm/amd/amdgpu/kv_dpm.c2
-rw-r--r--drivers/gpu/drm/msm/adreno/a5xx_gpu.c27
-rw-r--r--drivers/gpu/drm/msm/adreno/adreno_gpu.c15
-rw-r--r--drivers/gpu/drm/msm/hdmi-staging/sde_hdmi.c51
-rw-r--r--drivers/gpu/drm/msm/hdmi-staging/sde_hdmi.h9
-rw-r--r--drivers/gpu/drm/msm/hdmi-staging/sde_hdmi_bridge.c41
-rw-r--r--drivers/gpu/drm/msm/msm_drv.c19
-rw-r--r--drivers/gpu/drm/msm/msm_drv.h2
-rw-r--r--drivers/gpu/drm/msm/msm_gem.c53
-rw-r--r--drivers/gpu/drm/msm/msm_gem.h2
-rw-r--r--drivers/gpu/drm/msm/msm_gem_prime.c12
-rw-r--r--drivers/gpu/drm/msm/msm_gem_submit.c57
-rw-r--r--drivers/gpu/drm/msm/msm_gpu.c75
-rw-r--r--drivers/gpu/drm/msm/msm_gpu.h3
-rw-r--r--drivers/gpu/drm/msm/sde/sde_crtc.c8
-rw-r--r--drivers/gpu/drm/msm/sde/sde_rm.c26
-rw-r--r--drivers/input/misc/hbtp_input.c4
-rw-r--r--drivers/input/misc/vl53L0/stmvl53l0_module-cci.c20
-rw-r--r--drivers/input/misc/vl53L0/stmvl53l0_module.c28
-rw-r--r--drivers/input/serio/i8042-x86ia64io.h7
-rw-r--r--drivers/md/raid1.c2
-rw-r--r--drivers/media/platform/msm/camera_v2/isp/msm_isp.h4
-rw-r--r--drivers/media/platform/msm/camera_v2/isp/msm_isp47.c6
-rw-r--r--drivers/media/platform/msm/camera_v2/isp/msm_isp_axi_util.c133
-rw-r--r--drivers/media/platform/msm/camera_v2/isp/msm_isp_stats_util.c8
-rw-r--r--drivers/media/platform/msm/camera_v2/isp/msm_isp_util.c7
-rw-r--r--drivers/media/platform/msm/camera_v2/msm_buf_mgr/msm_generic_buf_mgr.c21
-rw-r--r--drivers/media/platform/msm/camera_v2/sensor/eeprom/msm_eeprom.c12
-rw-r--r--drivers/media/platform/msm/camera_v2/sensor/msm_sensor_driver.c26
-rw-r--r--drivers/misc/qseecom.c2
-rw-r--r--drivers/mmc/core/bus.h2
-rw-r--r--drivers/mmc/host/sdhci-msm-ice.c2
-rw-r--r--drivers/mmc/host/sdhci-msm.c1
-rw-r--r--drivers/net/ethernet/cavium/liquidio/lio_main.c9
-rw-r--r--drivers/net/macvlan.c11
-rw-r--r--drivers/net/phy/dp83640.c2
-rw-r--r--drivers/net/phy/phy.c2
-rw-r--r--drivers/net/wireless/ath/ath10k/qmi.c5
-rw-r--r--drivers/net/wireless/ath/ath10k/snoc.c4
-rw-r--r--drivers/net/wireless/ath/wil6210/cfg80211.c12
-rw-r--r--drivers/net/wireless/ath/wil6210/fw_inc.c4
-rw-r--r--drivers/net/wireless/ath/wil6210/main.c32
-rw-r--r--drivers/net/wireless/ath/wil6210/pmc.c4
-rw-r--r--drivers/net/wireless/ath/wil6210/rx_reorder.c12
-rw-r--r--drivers/net/wireless/ath/wil6210/txrx.c24
-rw-r--r--drivers/net/wireless/ath/wil6210/wil6210.h6
-rw-r--r--drivers/net/wireless/ath/wil6210/wmi.c3
-rw-r--r--drivers/net/wireless/cnss/Kconfig9
-rw-r--r--drivers/net/wireless/cnss/cnss_pci.c5
-rw-r--r--drivers/nfc/nq-nci.c1
-rw-r--r--drivers/platform/msm/ipa/ipa_v2/ipa_debugfs.c3
-rw-r--r--drivers/platform/msm/ipa/ipa_v2/ipa_qmi_service.h3
-rw-r--r--drivers/platform/msm/ipa/ipa_v2/ipa_utils.c2
-rw-r--r--drivers/platform/msm/ipa/ipa_v2/rmnet_ipa.c103
-rw-r--r--drivers/platform/msm/ipa/ipa_v2/rmnet_ipa_fd_ioctl.c30
-rw-r--r--drivers/platform/msm/ipa/ipa_v3/ipa_client.c24
-rw-r--r--drivers/platform/msm/ipa/ipa_v3/ipa_debugfs.c3
-rw-r--r--drivers/platform/msm/ipa/ipa_v3/ipa_dp.c2
-rw-r--r--drivers/platform/msm/ipa/ipa_v3/ipa_qmi_service.h3
-rw-r--r--drivers/platform/msm/ipa/ipa_v3/ipa_utils.c2
-rw-r--r--drivers/platform/msm/ipa/ipa_v3/ipahal/ipahal_reg.c18
-rw-r--r--drivers/platform/msm/ipa/ipa_v3/rmnet_ipa.c99
-rw-r--r--drivers/platform/msm/ipa/ipa_v3/rmnet_ipa_fd_ioctl.c31
-rw-r--r--drivers/platform/msm/msm_ext_display.c17
-rw-r--r--drivers/power/supply/qcom/qpnp-fg-gen3.c10
-rw-r--r--drivers/scsi/ufs/ufs-qcom-ice.c2
-rw-r--r--drivers/scsi/ufs/ufshcd.c23
-rw-r--r--drivers/scsi/ufs/ufshcd.h22
-rw-r--r--drivers/soc/qcom/icnss_utils.c36
-rw-r--r--drivers/soc/qcom/memshare/msm_memshare.c11
-rw-r--r--drivers/soc/qcom/memshare/msm_memshare.h3
-rw-r--r--drivers/soc/qcom/qpnp-haptic.c956
-rw-r--r--drivers/staging/android/ion/ion.c22
-rw-r--r--drivers/staging/android/ion/ion.h17
-rw-r--r--drivers/usb/gadget/function/f_midi.c4
-rw-r--r--drivers/usb/gadget/function/f_mtp.c6
-rw-r--r--drivers/usb/gadget/function/f_qdss.c26
-rw-r--r--drivers/video/fbdev/msm/mdss_hdmi_edid.c42
-rw-r--r--drivers/video/fbdev/msm/mdss_hdmi_edid.h1
-rw-r--r--drivers/video/fbdev/msm/mdss_hdmi_tx.c8
-rw-r--r--drivers/video/fbdev/msm/mdss_mdp_util.c2
-rw-r--r--fs/f2fs/super.c90
-rw-r--r--fs/nfsd/nfssvc.c36
-rw-r--r--include/linux/msm_ext_display.h2
-rw-r--r--include/sound/apr_audio-v2.h36
-rw-r--r--include/sound/q6asm-v2.h8
-rw-r--r--include/uapi/drm/drm.h22
-rw-r--r--include/uapi/drm/drm_fourcc.h8
-rw-r--r--include/uapi/drm/drm_mode.h8
-rw-r--r--include/uapi/drm/drm_sarea.h8
-rw-r--r--include/uapi/drm/msm_drm.h2
-rw-r--r--include/uapi/linux/ipv6_route.h2
-rw-r--r--include/uapi/linux/msm_audio.h10
-rw-r--r--include/uapi/linux/msm_ipa.h14
-rw-r--r--include/uapi/linux/rmnet_ipa_fd_ioctl.h17
-rw-r--r--include/uapi/sound/compress_offload.h7
-rw-r--r--net/9p/client.c4
-rw-r--r--net/core/neighbour.c3
-rw-r--r--net/core/netpoll.c10
-rw-r--r--net/ipv4/route.c2
-rw-r--r--net/ipv4/tcp.c1
-rw-r--r--net/ipv6/ip6_tunnel.c34
-rw-r--r--net/ipv6/ip6mr.c13
-rw-r--r--net/ipv6/raw.c3
-rw-r--r--net/ipv6/route.c4
-rw-r--r--net/l2tp/l2tp_core.c8
-rw-r--r--net/l2tp/l2tp_core.h3
-rw-r--r--net/l2tp/l2tp_debugfs.c10
-rw-r--r--net/l2tp/l2tp_netlink.c7
-rw-r--r--net/l2tp/l2tp_ppp.c19
-rw-r--r--net/packet/af_packet.c4
-rw-r--r--net/rds/cong.c4
-rw-r--r--net/sched/act_mirred.c5
-rw-r--r--net/sctp/socket.c3
-rw-r--r--net/wireless/db.txt109
-rw-r--r--sound/core/seq/seq_lock.c9
-rw-r--r--sound/firewire/lib.h2
-rw-r--r--sound/soc/codecs/wsa881x-analog.c4
-rw-r--r--sound/soc/msm/qdsp6v2/audio_cal_utils.c2
-rw-r--r--sound/soc/msm/qdsp6v2/msm-compress-q6-v2.c49
-rw-r--r--sound/soc/msm/qdsp6v2/msm-dai-q6-hdmi-v2.c4
-rw-r--r--sound/soc/msm/qdsp6v2/msm-dai-q6-v2.c74
-rw-r--r--sound/soc/msm/qdsp6v2/msm-pcm-q6-v2.c7
-rw-r--r--sound/soc/msm/qdsp6v2/msm-qti-pp-config.c281
-rw-r--r--sound/soc/msm/qdsp6v2/msm-qti-pp-config.h5
-rw-r--r--sound/soc/msm/qdsp6v2/q6asm.c164
-rw-r--r--sound/usb/stream.c13
161 files changed, 3834 insertions, 975 deletions
diff --git a/Documentation/devicetree/bindings/clock/sunxi.txt b/Documentation/devicetree/bindings/clock/sunxi.txt
index 8a47b77abfca..e8c74a6e738b 100644
--- a/Documentation/devicetree/bindings/clock/sunxi.txt
+++ b/Documentation/devicetree/bindings/clock/sunxi.txt
@@ -18,6 +18,7 @@ Required properties:
"allwinner,sun4i-a10-cpu-clk" - for the CPU multiplexer clock
"allwinner,sun4i-a10-axi-clk" - for the AXI clock
"allwinner,sun8i-a23-axi-clk" - for the AXI clock on A23
+ "allwinner,sun4i-a10-gates-clk" - for generic gates on all compatible SoCs
"allwinner,sun4i-a10-axi-gates-clk" - for the AXI gates
"allwinner,sun4i-a10-ahb-clk" - for the AHB clock
"allwinner,sun5i-a13-ahb-clk" - for the AHB clock on A13
@@ -43,6 +44,7 @@ Required properties:
"allwinner,sun6i-a31-apb0-gates-clk" - for the APB0 gates on A31
"allwinner,sun7i-a20-apb0-gates-clk" - for the APB0 gates on A20
"allwinner,sun8i-a23-apb0-gates-clk" - for the APB0 gates on A23
+ "allwinner,sun8i-h3-apb0-gates-clk" - for the APB0 gates on H3
"allwinner,sun9i-a80-apb0-gates-clk" - for the APB0 gates on A80
"allwinner,sun4i-a10-apb1-clk" - for the APB1 clock
"allwinner,sun9i-a80-apb1-clk" - for the APB1 bus clock on A80
diff --git a/Documentation/devicetree/bindings/soc/qcom/qpnp-haptic.txt b/Documentation/devicetree/bindings/soc/qcom/qpnp-haptic.txt
index 337649824257..aa3363b52a03 100644
--- a/Documentation/devicetree/bindings/soc/qcom/qpnp-haptic.txt
+++ b/Documentation/devicetree/bindings/soc/qcom/qpnp-haptic.txt
@@ -76,6 +76,10 @@ Optional properties when qcom,actuator-type is "lra"
at End of Pattern
- qcom,lra-res-cal-period : Auto resonance calibration period. The values range from
4 to 32(default)
+- qcom,lra-auto-mode : If this property is specified, haptics mode for LRA
+ actuators will be automatically configured along with
+ other required settings runtime based on the duration
+ of the pattern.
- qcom,perform-lra-auto-resonance-search : boolean, define this property if:
a) the underlying PMI chip does not have a register in the MISC block to
read the error percentage in RC clock
diff --git a/Makefile b/Makefile
index 933d159a74d7..5545fe6cab62 100644
--- a/Makefile
+++ b/Makefile
@@ -1,6 +1,6 @@
VERSION = 4
PATCHLEVEL = 4
-SUBLEVEL = 65
+SUBLEVEL = 66
EXTRAVERSION =
NAME = Blurry Fish Butt
diff --git a/arch/arc/include/asm/entry-arcv2.h b/arch/arc/include/asm/entry-arcv2.h
index b5ff87e6f4b7..aee1a77934cf 100644
--- a/arch/arc/include/asm/entry-arcv2.h
+++ b/arch/arc/include/asm/entry-arcv2.h
@@ -16,6 +16,7 @@
;
; Now manually save: r12, sp, fp, gp, r25
+ PUSH r30
PUSH r12
; Saving pt_regs->sp correctly requires some extra work due to the way
@@ -72,6 +73,7 @@
POPAX AUX_USER_SP
1:
POP r12
+ POP r30
.endm
diff --git a/arch/arc/include/asm/ptrace.h b/arch/arc/include/asm/ptrace.h
index 69095da1fcfd..47111d565a95 100644
--- a/arch/arc/include/asm/ptrace.h
+++ b/arch/arc/include/asm/ptrace.h
@@ -84,7 +84,7 @@ struct pt_regs {
unsigned long fp;
unsigned long sp; /* user/kernel sp depending on where we came from */
- unsigned long r12;
+ unsigned long r12, r30;
/*------- Below list auto saved by h/w -----------*/
unsigned long r0, r1, r2, r3, r4, r5, r6, r7, r8, r9, r10, r11;
diff --git a/arch/arm/boot/dts/qcom/msm-pm660l.dtsi b/arch/arm/boot/dts/qcom/msm-pm660l.dtsi
index 679149a78833..0f18ba5c94c7 100644
--- a/arch/arm/boot/dts/qcom/msm-pm660l.dtsi
+++ b/arch/arm/boot/dts/qcom/msm-pm660l.dtsi
@@ -380,9 +380,6 @@
qcom,led-name = "led:switch_1";
qcom,led-mask = <4>;
qcom,default-led-trigger = "switch1_trigger";
- pinctrl-names = "led_enable","led_disable";
- pinctrl-0 = <&led_enable>;
- pinctrl-1 = <&led_disable>;
};
};
diff --git a/arch/arm/boot/dts/qcom/msm-pmi8998.dtsi b/arch/arm/boot/dts/qcom/msm-pmi8998.dtsi
index 2d2b628ca815..ad32ab01c5fb 100644
--- a/arch/arm/boot/dts/qcom/msm-pmi8998.dtsi
+++ b/arch/arm/boot/dts/qcom/msm-pmi8998.dtsi
@@ -762,9 +762,6 @@
qcom,led-name = "led:switch_1";
qcom,led-mask = <4>;
qcom,default-led-trigger = "switch1_trigger";
- pinctrl-names = "led_enable","led_disable";
- pinctrl-0 = <&led_enable>;
- pinctrl-1 = <&led_disable>;
};
};
};
diff --git a/arch/arm/boot/dts/qcom/msm8996pro.dtsi b/arch/arm/boot/dts/qcom/msm8996pro.dtsi
index 2f29fabb7d7e..ca89a517df5c 100644
--- a/arch/arm/boot/dts/qcom/msm8996pro.dtsi
+++ b/arch/arm/boot/dts/qcom/msm8996pro.dtsi
@@ -1505,5 +1505,62 @@
qcom,bus-max = <0>;
};
};
+
+ qcom,gpu-pwrlevels-2 {
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ qcom,speed-bin = <2>;
+
+ qcom,initial-pwrlevel = <3>;
+
+ qcom,gpu-pwrlevel@0 {
+ reg = <0>;
+ qcom,gpu-freq = <510000000>;
+ qcom,bus-freq = <11>;
+ qcom,bus-min = <11>;
+ qcom,bus-max = <11>;
+ };
+
+ qcom,gpu-pwrlevel@1 {
+ reg = <1>;
+ qcom,gpu-freq = <401800000>;
+ qcom,bus-freq = <8>;
+ qcom,bus-min = <7>;
+ qcom,bus-max = <9>;
+ };
+
+ qcom,gpu-pwrlevel@2 {
+ reg = <2>;
+ qcom,gpu-freq = <315000000>;
+ qcom,bus-freq = <6>;
+ qcom,bus-min = <5>;
+ qcom,bus-max = <7>;
+ };
+
+ qcom,gpu-pwrlevel@3 {
+ reg = <3>;
+ qcom,gpu-freq = <214000000>;
+ qcom,bus-freq = <4>;
+ qcom,bus-min = <3>;
+ qcom,bus-max = <5>;
+ };
+
+ qcom,gpu-pwrlevel@4 {
+ reg = <4>;
+ qcom,gpu-freq = <133000000>;
+ qcom,bus-freq = <3>;
+ qcom,bus-min = <2>;
+ qcom,bus-max = <4>;
+ };
+
+ qcom,gpu-pwrlevel@5 {
+ reg = <5>;
+ qcom,gpu-freq = <27000000>;
+ qcom,bus-freq = <0>;
+ qcom,bus-min = <0>;
+ qcom,bus-max = <0>;
+ };
+ };
};
};
diff --git a/arch/arm/boot/dts/qcom/msm8998-camera-sensor-mtp.dtsi b/arch/arm/boot/dts/qcom/msm8998-camera-sensor-mtp.dtsi
index d7372f2bb2e4..2095b4e07069 100644
--- a/arch/arm/boot/dts/qcom/msm8998-camera-sensor-mtp.dtsi
+++ b/arch/arm/boot/dts/qcom/msm8998-camera-sensor-mtp.dtsi
@@ -334,19 +334,22 @@
qcom,gpio-no-mux = <0>;
pinctrl-names = "cam_default", "cam_suspend";
pinctrl-0 = <&cam_sensor_mclk1_active
- &cam_sensor_front_active>;
+ &cam_sensor_front_active &led_enable>;
pinctrl-1 = <&cam_sensor_mclk1_suspend
- &cam_sensor_front_suspend>;
+ &cam_sensor_front_suspend &led_disable>;
gpios = <&tlmm 14 0>,
<&tlmm 28 0>,
- <&pm8998_gpios 9 0>;
+ <&pm8998_gpios 9 0>,
+ <&tlmm 21 0>;
qcom,gpio-reset = <1>;
qcom,gpio-vdig = <2>;
- qcom,gpio-req-tbl-num = <0 1 2>;
- qcom,gpio-req-tbl-flags = <1 0 0>;
+ qcom,gpio-flash-en = <3>;
+ qcom,gpio-req-tbl-num = <0 1 2 3>;
+ qcom,gpio-req-tbl-flags = <1 0 0 0>;
qcom,gpio-req-tbl-label = "CAMIF_MCLK2",
"CAM_RESET2",
- "CAM_VDIG";
+ "CAM_VDIG",
+ "FLASH_EN";
qcom,sensor-position = <1>;
qcom,sensor-mode = <0>;
qcom,cci-master = <1>;
@@ -356,6 +359,45 @@
clock-names = "cam_src_clk", "cam_clk";
qcom,clock-rates = <24000000 0>;
};
+
+ qcom,camera@3 {
+ cell-index = <3>;
+ compatible = "qcom,camera";
+ reg = <0x03>;
+ qcom,csiphy-sd-index = <1>;
+ qcom,csid-sd-index = <1>;
+ qcom,mount-angle = <270>;
+ qcom,led-flash-src = <&led_flash1>;
+ cam_vio-supply = <&pm8998_lvs1>;
+ cam_vana-supply = <&pm8998_l22>;
+ cam_vdig-supply = <&pm8998_s3>;
+ qcom,cam-vreg-name = "cam_vio", "cam_vana", "cam_vdig";
+ qcom,cam-vreg-min-voltage =
+ <0 2864000 1352000>;
+ qcom,cam-vreg-max-voltage =
+ <0 2864000 1352000>;
+ qcom,cam-vreg-op-mode = <0 80000 105000>;
+ qcom,gpio-no-mux = <0>;
+ pinctrl-names = "cam_default", "cam_suspend";
+ pinctrl-0 = <&cam_sensor_mclk3_active
+ &cam_sensor_front_iris_active>;
+ pinctrl-1 = <&cam_sensor_mclk3_suspend
+ &cam_sensor_front_iris_suspend>;
+ gpios = <&tlmm 16 0>,
+ <&tlmm 23 0>;
+ qcom,gpio-reset = <1>;
+ qcom,gpio-req-tbl-num = <0 1>;
+ qcom,gpio-req-tbl-flags = <1 0>;
+ qcom,gpio-req-tbl-label = "CAMIF_MCLK3",
+ "CAM_RESET3";
+ qcom,sensor-position = <1>;
+ qcom,sensor-mode = <0>;
+ qcom,cci-master = <1>;
+ clocks = <&clock_mmss clk_mclk3_clk_src>,
+ <&clock_mmss clk_mmss_camss_mclk3_clk>;
+ clock-names = "cam_src_clk", "cam_clk";
+ qcom,clock-rates = <24000000 0>;
+ };
};
&pm8998_gpios {
gpio@c800 { /* GPIO 9 - CAMERA SENSOR 2 VDIG */
diff --git a/arch/arm/boot/dts/qcom/msm8998-interposer-camera-sensor-mtp.dtsi b/arch/arm/boot/dts/qcom/msm8998-interposer-camera-sensor-mtp.dtsi
index 722c18a26388..d00ae0f3730c 100644
--- a/arch/arm/boot/dts/qcom/msm8998-interposer-camera-sensor-mtp.dtsi
+++ b/arch/arm/boot/dts/qcom/msm8998-interposer-camera-sensor-mtp.dtsi
@@ -12,6 +12,12 @@
*/
&soc {
+ /delete-node/qcom,camera-flash@0;
+ /delete-node/qcom,camera-flash@1;
+ /delete-node/gpio-regulator@0;
+};
+
+&soc {
tlmm: pinctrl@03400000 {
cam_sensor_rear_active: cam_sensor_rear_active {
/* RESET, STANDBY */
@@ -132,19 +138,17 @@
};
};
-&soc {
- /delete-node/gpio-regulator@0;
-};
-
&cci {
/delete-node/qcom,camera@0;
/delete-node/qcom,camera@1;
/delete-node/qcom,camera@2;
+ /delete-node/qcom,camera@3;
/delete-node/qcom,eeprom@0;
/delete-node/qcom,eeprom@1;
/delete-node/qcom,eeprom@2;
/delete-node/qcom,actuator@0;
/delete-node/qcom,actuator@1;
+ /delete-node/qcom,tof@0;
/delete-node/qcom,ois@0;
};
diff --git a/arch/arm/boot/dts/qcom/msm8998-interposer-camera-sensor-qrd.dtsi b/arch/arm/boot/dts/qcom/msm8998-interposer-camera-sensor-qrd.dtsi
index 8b68ece2239f..42414db3cc48 100644
--- a/arch/arm/boot/dts/qcom/msm8998-interposer-camera-sensor-qrd.dtsi
+++ b/arch/arm/boot/dts/qcom/msm8998-interposer-camera-sensor-qrd.dtsi
@@ -12,6 +12,12 @@
*/
&soc {
+ /delete-node/qcom,camera-flash@0;
+ /delete-node/qcom,camera-flash@1;
+ /delete-node/gpio-regulator@0;
+};
+
+&soc {
tlmm: pinctrl@03400000 {
cam_sensor_rear_active: cam_sensor_rear_active {
/* RESET, STANDBY */
@@ -170,19 +176,17 @@
};
};
-&soc {
- /delete-node/gpio-regulator@0;
-};
-
&cci {
/delete-node/qcom,camera@0;
/delete-node/qcom,camera@1;
/delete-node/qcom,camera@2;
+ /delete-node/qcom,camera@3;
/delete-node/qcom,eeprom@0;
/delete-node/qcom,eeprom@1;
/delete-node/qcom,eeprom@2;
/delete-node/qcom,actuator@0;
/delete-node/qcom,actuator@1;
+ /delete-node/qcom,tof@0;
/delete-node/qcom,ois@0;
};
diff --git a/arch/arm/boot/dts/qcom/msm8998-pinctrl.dtsi b/arch/arm/boot/dts/qcom/msm8998-pinctrl.dtsi
index cdf4bede6eb3..318dc5d7c791 100644
--- a/arch/arm/boot/dts/qcom/msm8998-pinctrl.dtsi
+++ b/arch/arm/boot/dts/qcom/msm8998-pinctrl.dtsi
@@ -996,7 +996,7 @@
cam_sensor_mclk0_active: cam_sensor_mclk0_active {
/* MCLK0 */
mux {
- /* CLK, DATA */
+ /* CLK */
pins = "gpio13";
function = "cam_mclk";
};
@@ -1011,7 +1011,7 @@
cam_sensor_mclk0_suspend: cam_sensor_mclk0_suspend {
/* MCLK0 */
mux {
- /* CLK, DATA */
+ /* CLK */
pins = "gpio13";
function = "cam_mclk";
};
@@ -1305,7 +1305,7 @@
cam_sensor_mclk1_active: cam_sensor_mclk1_active {
/* MCLK1 */
mux {
- /* CLK, DATA */
+ /* CLK */
pins = "gpio14";
function = "cam_mclk";
};
@@ -1320,7 +1320,7 @@
cam_sensor_mclk1_suspend: cam_sensor_mclk1_suspend {
/* MCLK1 */
mux {
- /* CLK, DATA */
+ /* CLK */
pins = "gpio14";
function = "cam_mclk";
};
@@ -1332,6 +1332,36 @@
};
};
+ cam_sensor_mclk3_active: cam_sensor_mclk3_active {
+ /* MCLK3 */
+ mux {
+ /* CLK */
+ pins = "gpio16";
+ function = "cam_mclk";
+ };
+
+ config {
+ pins = "gpio16";
+ bias-disable; /* No PULL */
+ drive-strength = <2>; /* 2 MA */
+ };
+ };
+
+ cam_sensor_mclk3_suspend: cam_sensor_mclk3_suspend {
+ /* MCLK3 */
+ mux {
+ /* CLK */
+ pins = "gpio16";
+ function = "cam_mclk";
+ };
+
+ config {
+ pins = "gpio16";
+ bias-pull-down; /* PULL DOWN */
+ drive-strength = <2>; /* 2 MA */
+ };
+ };
+
cam_sensor_rear2_active: cam_sensor_rear2_active {
/* RESET, STANDBY */
mux {
@@ -1468,7 +1498,7 @@
cam_sensor_mclk2_active: cam_sensor_mclk2_active {
/* MCLK1 */
mux {
- /* CLK, DATA */
+ /* CLK */
pins = "gpio15";
function = "cam_mclk";
};
@@ -1483,7 +1513,7 @@
cam_sensor_mclk2_suspend: cam_sensor_mclk2_suspend {
/* MCLK1 */
mux {
- /* CLK, DATA */
+ /* CLK */
pins = "gpio15";
function = "cam_mclk";
};
@@ -1509,6 +1539,21 @@
};
};
+
+ cam_sensor_front_iris_active: cam_sensor_front_iris_active {
+ /* RESET */
+ mux {
+ pins = "gpio23";
+ function = "gpio";
+ };
+
+ config {
+ pins = "gpio23";
+ bias-disable; /* No PULL */
+ drive-strength = <2>; /* 2 MA */
+ };
+ };
+
blsp2_uart1_active: blsp2_uart1_active {
mux {
pins = "gpio53", "gpio54", "gpio55", "gpio56";
@@ -1575,6 +1620,20 @@
};
};
+ cam_sensor_front_iris_suspend: cam_sensor_front_iris_suspend {
+ /* RESET */
+ mux {
+ pins = "gpio23";
+ function = "gpio";
+ };
+
+ config {
+ pins = "gpio23";
+ bias-disable; /* No PULL */
+ drive-strength = <2>; /* 2 MA */
+ };
+ };
+
pmx_mdss: pmx_mdss {
mdss_dsi_active: mdss_dsi_active {
mux {
diff --git a/arch/arm/boot/dts/qcom/sdm660-camera-sensor-mtp.dtsi b/arch/arm/boot/dts/qcom/sdm660-camera-sensor-mtp.dtsi
index 191beaa4d53b..3d37d169a97c 100644
--- a/arch/arm/boot/dts/qcom/sdm660-camera-sensor-mtp.dtsi
+++ b/arch/arm/boot/dts/qcom/sdm660-camera-sensor-mtp.dtsi
@@ -29,6 +29,36 @@
qcom,switch-source = <&pm660l_switch1>;
status = "ok";
};
+
+ cam_avdd_gpio_regulator: cam_avdd_fixed_regulator {
+ compatible = "regulator-fixed";
+ regulator-name = "cam_avdd_gpio_regulator";
+ regulator-min-microvolt = <3600000>;
+ regulator-max-microvolt = <3600000>;
+ enable-active-high;
+ gpio = <&tlmm 51 0>;
+ vin-supply = <&pm660l_bob>;
+ };
+
+ cam_dvdd_gpio_regulator: cam_dvdd_fixed_regulator {
+ compatible = "regulator-fixed";
+ regulator-name = "cam_dvdd_gpio_regulator";
+ regulator-min-microvolt = <1350000>;
+ regulator-max-microvolt = <1350000>;
+ enable-active-high;
+ gpio = <&pm660l_gpios 3 0>;
+ vin-supply = <&pm660_s5>;
+ };
+
+ cam_rear_dvdd_gpio_regulator: cam_rear_dvdd_fixed_regulator {
+ compatible = "regulator-fixed";
+ regulator-name = "cam_rear_dvdd_gpio_regulator";
+ regulator-min-microvolt = <1350000>;
+ regulator-max-microvolt = <1350000>;
+ enable-active-high;
+ gpio = <&pm660l_gpios 4 0>;
+ vin-supply = <&pm660_s5>;
+ };
};
&cci {
@@ -98,12 +128,12 @@
reg = <0>;
compatible = "qcom,eeprom";
cam_vio-supply = <&pm660_l11>;
- cam_vana-supply = <&pm660l_bob>;
- cam_vdig-supply = <&pm660_s5>;
+ cam_vana-supply = <&cam_avdd_gpio_regulator>;
+ cam_vdig-supply = <&cam_rear_dvdd_gpio_regulator>;
qcom,cam-vreg-name = "cam_vio", "cam_vana", "cam_vdig";
- qcom,cam-vreg-min-voltage = <1780000 3300000 1350000>;
- qcom,cam-vreg-max-voltage = <1950000 3600000 1350000>;
- qcom,cam-vreg-op-mode = <105000 80000 105000>;
+ qcom,cam-vreg-min-voltage = <1780000 0 0>;
+ qcom,cam-vreg-max-voltage = <1950000 0 0>;
+ qcom,cam-vreg-op-mode = <105000 0 0>;
qcom,gpio-no-mux = <0>;
pinctrl-names = "cam_default", "cam_suspend";
pinctrl-0 = <&cam_sensor_mclk0_active
@@ -114,19 +144,13 @@
&cam_actuator_vaf_suspend>;
gpios = <&tlmm 32 0>,
<&tlmm 46 0>,
- <&pm660l_gpios 4 0>,
- <&tlmm 51 0>,
<&tlmm 50 0>;
qcom,gpio-reset = <1>;
- qcom,gpio-vdig = <2>;
- qcom,gpio-vana = <3>;
- qcom,gpio-vaf = <4>;
- qcom,gpio-req-tbl-num = <0 1 2 3 4>;
- qcom,gpio-req-tbl-flags = <1 0 0 0 0>;
+ qcom,gpio-vaf = <2>;
+ qcom,gpio-req-tbl-num = <0 1 2>;
+ qcom,gpio-req-tbl-flags = <1 0 0>;
qcom,gpio-req-tbl-label = "CAMIF_MCLK0",
"CAM_RESET0",
- "CAM_VDIG",
- "CAM_VANA",
"CAM_VAF";
qcom,sensor-position = <0>;
qcom,sensor-mode = <0>;
@@ -143,12 +167,12 @@
reg = <0x1>;
compatible = "qcom,eeprom";
cam_vio-supply = <&pm660_l11>;
- cam_vana-supply = <&pm660l_bob>;
- cam_vdig-supply = <&pm660_s5>;
+ cam_vana-supply = <&cam_avdd_gpio_regulator>;
+ cam_vdig-supply = <&cam_dvdd_gpio_regulator>;
qcom,cam-vreg-name = "cam_vio", "cam_vana", "cam_vdig";
- qcom,cam-vreg-min-voltage = <1780000 3300000 1350000>;
- qcom,cam-vreg-max-voltage = <1950000 3600000 1350000>;
- qcom,cam-vreg-op-mode = <105000 80000 105000>;
+ qcom,cam-vreg-min-voltage = <1780000 0 0>;
+ qcom,cam-vreg-max-voltage = <1950000 0 0>;
+ qcom,cam-vreg-op-mode = <105000 0 0>;
qcom,gpio-no-mux = <0>;
pinctrl-names = "cam_default", "cam_suspend";
pinctrl-0 = <&cam_sensor_mclk2_active
@@ -156,18 +180,12 @@
pinctrl-1 = <&cam_sensor_mclk2_suspend
&cam_sensor_rear2_suspend>;
gpios = <&tlmm 34 0>,
- <&tlmm 48 0>,
- <&pm660l_gpios 3 0>,
- <&tlmm 51 0>;
+ <&tlmm 48 0>;
qcom,gpio-reset = <1>;
- qcom,gpio-vdig = <2>;
- qcom,gpio-vana = <3>;
- qcom,gpio-req-tbl-num = <0 1 2 3>;
- qcom,gpio-req-tbl-flags = <1 0 0 0>;
+ qcom,gpio-req-tbl-num = <0 1>;
+ qcom,gpio-req-tbl-flags = <1 0>;
qcom,gpio-req-tbl-label = "CAMIF_MCLK",
- "CAM_RESET",
- "CAM_VDIG",
- "CAM_VANA";
+ "CAM_RESET";
qcom,sensor-position = <0>;
qcom,sensor-mode = <0>;
qcom,cci-master = <1>;
@@ -184,11 +202,11 @@
compatible = "qcom,eeprom";
cam_vio-supply = <&pm660_l11>;
cam_vana-supply = <&pm660l_bob>;
- cam_vdig-supply = <&pm660_s5>;
+ cam_vdig-supply = <&cam_dvdd_gpio_regulator>;
qcom,cam-vreg-name = "cam_vio", "cam_vana", "cam_vdig";
- qcom,cam-vreg-min-voltage = <1780000 3300000 1350000>;
- qcom,cam-vreg-max-voltage = <1950000 3600000 1350000>;
- qcom,cam-vreg-op-mode = <105000 80000 105000>;
+ qcom,cam-vreg-min-voltage = <1780000 3300000 0>;
+ qcom,cam-vreg-max-voltage = <1950000 3600000 0>;
+ qcom,cam-vreg-op-mode = <105000 80000 0>;
qcom,gpio-no-mux = <0>;
pinctrl-names = "cam_default", "cam_suspend";
pinctrl-0 = <&cam_sensor_mclk1_active
@@ -199,18 +217,15 @@
&cam_actuator_vaf_suspend>;
gpios = <&tlmm 33 0>,
<&tlmm 47 0>,
- <&pm660_gpios 3 0>,
<&tlmm 44 0>,
<&tlmm 50 0>;
qcom,gpio-reset = <1>;
- qcom,gpio-vdig = <2>;
- qcom,gpio-vana = <3>;
- qcom,gpio-vaf = <4>;
- qcom,gpio-req-tbl-num = <0 1 2 3 4>;
- qcom,gpio-req-tbl-flags = <1 0 0 0 0>;
+ qcom,gpio-vana = <2>;
+ qcom,gpio-vaf = <3>;
+ qcom,gpio-req-tbl-num = <0 1 2 3>;
+ qcom,gpio-req-tbl-flags = <1 0 0 0>;
qcom,gpio-req-tbl-label = "CAMIF_MCLK2",
"CAM_RESET2",
- "CAM_VDIG",
"CAM_VANA",
"CAM_VAF";
qcom,sensor-position = <1>;
@@ -235,12 +250,12 @@
qcom,ois-src = <&ois0>;
qcom,eeprom-src = <&eeprom0>;
cam_vio-supply = <&pm660_l11>;
- cam_vana-supply = <&pm660l_bob>;
- cam_vdig-supply = <&pm660_s5>;
+ cam_vana-supply = <&cam_avdd_gpio_regulator>;
+ cam_vdig-supply = <&cam_rear_dvdd_gpio_regulator>;
qcom,cam-vreg-name = "cam_vio", "cam_vana", "cam_vdig";
- qcom,cam-vreg-min-voltage = <1780000 3300000 1350000>;
- qcom,cam-vreg-max-voltage = <1950000 3600000 1350000>;
- qcom,cam-vreg-op-mode = <105000 80000 105000>;
+ qcom,cam-vreg-min-voltage = <1780000 0 0>;
+ qcom,cam-vreg-max-voltage = <1950000 0 0>;
+ qcom,cam-vreg-op-mode = <105000 0 0>;
qcom,gpio-no-mux = <0>;
pinctrl-names = "cam_default", "cam_suspend";
pinctrl-0 = <&cam_sensor_mclk0_active
@@ -248,18 +263,12 @@
pinctrl-1 = <&cam_sensor_mclk0_suspend
&cam_sensor_rear_suspend>;
gpios = <&tlmm 32 0>,
- <&tlmm 46 0>,
- <&pm660l_gpios 4 0>,
- <&tlmm 51 0>;
+ <&tlmm 46 0>;
qcom,gpio-reset = <1>;
- qcom,gpio-vdig = <2>;
- qcom,gpio-vana = <3>;
- qcom,gpio-req-tbl-num = <0 1 2 3>;
- qcom,gpio-req-tbl-flags = <1 0 0 0>;
+ qcom,gpio-req-tbl-num = <0 1>;
+ qcom,gpio-req-tbl-flags = <1 0>;
qcom,gpio-req-tbl-label = "CAMIF_MCLK0",
- "CAM_RESET0",
- "CAM_VDIG",
- "CAM_VANA";
+ "CAM_RESET0";
qcom,sensor-position = <0>;
qcom,sensor-mode = <0>;
qcom,cci-master = <0>;
@@ -280,12 +289,12 @@
qcom,actuator-src = <&actuator1>;
qcom,eeprom-src = <&eeprom1>;
cam_vio-supply = <&pm660_l11>;
- cam_vana-supply = <&pm660l_bob>;
- cam_vdig-supply = <&pm660_s5>;
+ cam_vana-supply = <&cam_avdd_gpio_regulator>;
+ cam_vdig-supply = <&cam_dvdd_gpio_regulator>;
qcom,cam-vreg-name = "cam_vio", "cam_vana", "cam_vdig";
- qcom,cam-vreg-min-voltage = <1780000 3300000 1350000>;
- qcom,cam-vreg-max-voltage = <1950000 3600000 1350000>;
- qcom,cam-vreg-op-mode = <105000 80000 105000>;
+ qcom,cam-vreg-min-voltage = <1780000 0 0>;
+ qcom,cam-vreg-max-voltage = <1950000 0 0>;
+ qcom,cam-vreg-op-mode = <105000 0 0>;
qcom,gpio-no-mux = <0>;
pinctrl-names = "cam_default", "cam_suspend";
pinctrl-0 = <&cam_sensor_mclk2_active
@@ -293,18 +302,12 @@
pinctrl-1 = <&cam_sensor_mclk2_suspend
&cam_sensor_rear2_suspend>;
gpios = <&tlmm 34 0>,
- <&tlmm 48 0>,
- <&pm660l_gpios 3 0>,
- <&tlmm 51 0>;
+ <&tlmm 48 0>;
qcom,gpio-reset = <1>;
- qcom,gpio-vdig = <2>;
- qcom,gpio-vana = <3>;
- qcom,gpio-req-tbl-num = <0 1 2 3>;
- qcom,gpio-req-tbl-flags = <1 0 0 0>;
+ qcom,gpio-req-tbl-num = <0 1>;
+ qcom,gpio-req-tbl-flags = <1 0>;
qcom,gpio-req-tbl-label = "CAMIF_MCLK",
- "CAM_RESET",
- "CAM_VDIG",
- "CAM_VANA";
+ "CAM_RESET";
qcom,sensor-position = <0>;
qcom,sensor-mode = <0>;
qcom,cci-master = <1>;
@@ -325,12 +328,12 @@
qcom,actuator-src = <&actuator2>;
qcom,eeprom-src = <&eeprom2>;
cam_vio-supply = <&pm660_l11>;
- cam_vana-supply = <&pm660l_bob>;
- cam_vdig-supply = <&pm660_s5>;
+ cam_vana-supply = <&cam_avdd_gpio_regulator>;
+ cam_vdig-supply = <&cam_dvdd_gpio_regulator>;
qcom,cam-vreg-name = "cam_vio", "cam_vana", "cam_vdig";
- qcom,cam-vreg-min-voltage = <1780000 3300000 1350000>;
- qcom,cam-vreg-max-voltage = <1950000 3600000 1350000>;
- qcom,cam-vreg-op-mode = <105000 80000 105000>;
+ qcom,cam-vreg-min-voltage = <1780000 0 0>;
+ qcom,cam-vreg-max-voltage = <1950000 0 0>;
+ qcom,cam-vreg-op-mode = <105000 0 0>;
qcom,gpio-no-mux = <0>;
pinctrl-names = "cam_default", "cam_suspend";
pinctrl-0 = <&cam_sensor_mclk1_active
@@ -338,18 +341,12 @@
pinctrl-1 = <&cam_sensor_mclk1_suspend
&cam_sensor_front_suspend>;
gpios = <&tlmm 33 0>,
- <&tlmm 47 0>,
- <&pm660l_gpios 3 0>,
- <&tlmm 51 0>;
+ <&tlmm 47 0>;
qcom,gpio-reset = <1>;
- qcom,gpio-vdig = <2>;
- qcom,gpio-vana = <3>;
- qcom,gpio-req-tbl-num = <0 1 2 3>;
- qcom,gpio-req-tbl-flags = <1 0 0 0>;
+ qcom,gpio-req-tbl-num = <0 1>;
+ qcom,gpio-req-tbl-flags = <1 0>;
qcom,gpio-req-tbl-label = "CAMIF_MCLK2",
- "CAM_RESET2",
- "CAM_VDIG",
- "CAM_VANA";
+ "CAM_RESET2";
qcom,sensor-position = <1>;
qcom,sensor-mode = <0>;
qcom,cci-master = <1>;
@@ -359,6 +356,45 @@
clock-names = "cam_src_clk", "cam_clk";
qcom,clock-rates = <24000000 0>;
};
+
+ qcom,camera@3 {
+ cell-index = <3>;
+ compatible = "qcom,camera";
+ reg = <0x03>;
+ qcom,csiphy-sd-index = <1>;
+ qcom,csid-sd-index = <1>;
+ qcom,mount-angle = <90>;
+ qcom,led-flash-src = <&led_flash1>;
+ qcom,actuator-src = <&actuator2>;
+ qcom,eeprom-src = <&eeprom2>;
+ cam_vio-supply = <&pm660_l11>;
+ cam_vana-supply = <&cam_avdd_gpio_regulator>;
+ cam_vdig-supply = <&cam_dvdd_gpio_regulator>;
+ qcom,cam-vreg-name = "cam_vio", "cam_vana", "cam_vdig";
+ qcom,cam-vreg-min-voltage = <1780000 0 0>;
+ qcom,cam-vreg-max-voltage = <1950000 0 0>;
+ qcom,cam-vreg-op-mode = <105000 0 0>;
+ qcom,gpio-no-mux = <0>;
+ pinctrl-names = "cam_default", "cam_suspend";
+ pinctrl-0 = <&cam_sensor_mclk3_active
+ &cam_sensor_front_iris_active>;
+ pinctrl-1 = <&cam_sensor_mclk3_suspend
+ &cam_sensor_front_iris_suspend>;
+ gpios = <&tlmm 35 0>,
+ <&tlmm 52 0>;
+ qcom,gpio-reset = <1>;
+ qcom,gpio-req-tbl-num = <0 1>;
+ qcom,gpio-req-tbl-flags = <1 0>;
+ qcom,gpio-req-tbl-label = "CAMIF_MCLK3",
+ "CAM_RESET3";
+ qcom,sensor-position = <1>;
+ qcom,sensor-mode = <0>;
+ qcom,cci-master = <1>;
+ clocks = <&clock_mmss MCLK3_CLK_SRC>,
+ <&clock_mmss MMSS_CAMSS_MCLK3_CLK>;
+ clock-names = "cam_src_clk", "cam_clk";
+ qcom,clock-rates = <24000000 0>;
+ };
};
&pm660l_gpios {
diff --git a/arch/arm/boot/dts/qcom/sdm660-camera.dtsi b/arch/arm/boot/dts/qcom/sdm660-camera.dtsi
index f3b81b5df1de..8ad33a5cb68a 100644
--- a/arch/arm/boot/dts/qcom/sdm660-camera.dtsi
+++ b/arch/arm/boot/dts/qcom/sdm660-camera.dtsi
@@ -514,7 +514,8 @@
camss-vdd-supply = <&gdsc_camss_top>;
smmu-vdd-supply = <&gdsc_bimc_smmu>;
qcom,vdd-names = "vdd", "camss-vdd", "smmu-vdd";
- clocks = <&clock_rpmcc MMSSNOC_AXI_CLK>,
+ clocks = <&clock_mmss MMSS_THROTTLE_CAMSS_AXI_CLK>,
+ <&clock_rpmcc MMSSNOC_AXI_CLK>,
<&clock_mmss MMSS_MNOC_AHB_CLK>,
<&clock_mmss MMSS_BIMC_SMMU_AHB_CLK>,
<&clock_mmss MMSS_BIMC_SMMU_AXI_CLK>,
@@ -527,16 +528,17 @@
<&clock_mmss MMSS_CAMSS_VFE_VBIF_AHB_CLK>,
<&clock_mmss MMSS_CAMSS_VFE_VBIF_AXI_CLK>,
<&clock_mmss MMSS_CAMSS_CSI_VFE0_CLK>;
- clock-names = "mmssnoc_axi", "mnoc_ahb_clk",
- "bimc_smmu_ahb_clk", "bimc_smmu_axi_clk",
- "camss_ahb_clk", "camss_top_ahb_clk", "vfe_clk_src",
+ clock-names = "mmss_throttle_camss_axi_clk", "mmssnoc_axi",
+ "mnoc_ahb_clk", "bimc_smmu_ahb_clk",
+ "bimc_smmu_axi_clk", "camss_ahb_clk",
+ "camss_top_ahb_clk", "vfe_clk_src",
"camss_vfe_clk", "camss_vfe_stream_clk",
"camss_vfe_ahb_clk", "camss_vfe_vbif_ahb_clk",
"camss_vfe_vbif_axi_clk",
"camss_csi_vfe_clk";
- qcom,clock-rates = <0 0 0 0 0 0 404000000 0 0 0 0 0 0
- 0 0 0 0 0 0 480000000 0 0 0 0 0 0
- 0 0 0 0 0 0 576000000 0 0 0 0 0 0>;
+ qcom,clock-rates = <0 0 0 0 0 0 0 404000000 0 0 0 0 0 0
+ 0 0 0 0 0 0 0 480000000 0 0 0 0 0 0
+ 0 0 0 0 0 0 0 576000000 0 0 0 0 0 0>;
status = "ok";
qos-entries = <8>;
qos-regs = <0x404 0x408 0x40c 0x410 0x414 0x418
@@ -595,7 +597,8 @@
camss-vdd-supply = <&gdsc_camss_top>;
smmu-vdd-supply = <&gdsc_bimc_smmu>;
qcom,vdd-names = "vdd", "camss-vdd", "smmu-vdd";
- clocks = <&clock_rpmcc MMSSNOC_AXI_CLK>,
+ clocks = <&clock_mmss MMSS_THROTTLE_CAMSS_AXI_CLK>,
+ <&clock_rpmcc MMSSNOC_AXI_CLK>,
<&clock_mmss MMSS_MNOC_AHB_CLK>,
<&clock_mmss MMSS_BIMC_SMMU_AHB_CLK>,
<&clock_mmss MMSS_BIMC_SMMU_AXI_CLK>,
@@ -608,16 +611,17 @@
<&clock_mmss MMSS_CAMSS_VFE_VBIF_AHB_CLK>,
<&clock_mmss MMSS_CAMSS_VFE_VBIF_AXI_CLK>,
<&clock_mmss MMSS_CAMSS_CSI_VFE1_CLK>;
- clock-names = "mmssnoc_axi", "mnoc_ahb_clk",
- "bimc_smmu_ahb_clk", "bimc_smmu_axi_clk",
- "camss_ahb_clk", "camss_top_ahb_clk", "vfe_clk_src",
+ clock-names = "mmss_throttle_camss_axi_clk", "mmssnoc_axi",
+ "mnoc_ahb_clk", "bimc_smmu_ahb_clk",
+ "bimc_smmu_axi_clk", "camss_ahb_clk",
+ "camss_top_ahb_clk", "vfe_clk_src",
"camss_vfe_clk", "camss_vfe_stream_clk",
"camss_vfe_ahb_clk", "camss_vfe_vbif_ahb_clk",
"camss_vfe_vbif_axi_clk",
"camss_csi_vfe_clk";
- qcom,clock-rates = <0 0 0 0 0 0 404000000 0 0 0 0 0 0
- 0 0 0 0 0 0 480000000 0 0 0 0 0 0
- 0 0 0 0 0 0 576000000 0 0 0 0 0 0>;
+ qcom,clock-rates = <0 0 0 0 0 0 0 404000000 0 0 0 0 0 0
+ 0 0 0 0 0 0 0 480000000 0 0 0 0 0 0
+ 0 0 0 0 0 0 0 576000000 0 0 0 0 0 0>;
status = "ok";
qos-entries = <8>;
qos-regs = <0x404 0x408 0x40c 0x410 0x414 0x418
diff --git a/arch/arm/boot/dts/qcom/sdm660-pinctrl.dtsi b/arch/arm/boot/dts/qcom/sdm660-pinctrl.dtsi
index efe58563a1f3..d902078b1048 100644
--- a/arch/arm/boot/dts/qcom/sdm660-pinctrl.dtsi
+++ b/arch/arm/boot/dts/qcom/sdm660-pinctrl.dtsi
@@ -1104,7 +1104,7 @@
cam_sensor_mclk0_active: cam_sensor_mclk0_active {
/* MCLK0 */
mux {
- /* CLK, DATA */
+ /* CLK */
pins = "gpio32";
function = "cam_mclk";
};
@@ -1119,7 +1119,7 @@
cam_sensor_mclk0_suspend: cam_sensor_mclk0_suspend {
/* MCLK0 */
mux {
- /* CLK, DATA */
+ /* CLK */
pins = "gpio32";
function = "cam_mclk";
};
@@ -1162,7 +1162,7 @@
cam_sensor_mclk1_active: cam_sensor_mclk1_active {
/* MCLK1 */
mux {
- /* CLK, DATA */
+ /* CLK */
pins = "gpio33";
function = "cam_mclk";
};
@@ -1177,7 +1177,7 @@
cam_sensor_mclk1_suspend: cam_sensor_mclk1_suspend {
/* MCLK1 */
mux {
- /* CLK, DATA */
+ /* CLK */
pins = "gpio33";
function = "cam_mclk";
};
@@ -1219,7 +1219,7 @@
cam_sensor_mclk2_active: cam_sensor_mclk2_active {
/* MCLK1 */
mux {
- /* CLK, DATA */
+ /* CLK */
pins = "gpio34";
function = "cam_mclk";
};
@@ -1234,7 +1234,7 @@
cam_sensor_mclk2_suspend: cam_sensor_mclk2_suspend {
/* MCLK1 */
mux {
- /* CLK, DATA */
+ /* CLK */
pins = "gpio34";
function = "cam_mclk";
};
@@ -1274,6 +1274,64 @@
};
};
+ cam_sensor_mclk3_active: cam_sensor_mclk3_active {
+ /* MCLK3 */
+ mux {
+ /* CLK */
+ pins = "gpio35";
+ function = "cam_mclk";
+ };
+
+ config {
+ pins = "gpio35";
+ bias-disable; /* No PULL */
+ drive-strength = <2>; /* 2 MA */
+ };
+ };
+
+ cam_sensor_mclk3_suspend: cam_sensor_mclk3_suspend {
+ /* MCLK3 */
+ mux {
+ /* CLK */
+ pins = "gpio35";
+ function = "cam_mclk";
+ };
+
+ config {
+ pins = "gpio35";
+ bias-pull-down; /* PULL DOWN */
+ drive-strength = <2>; /* 2 MA */
+ };
+ };
+
+ cam_sensor_front_iris_active: cam_sensor_front_iris_active {
+ /* RESET */
+ mux {
+ pins = "gpio52";
+ function = "gpio";
+ };
+
+ config {
+ pins = "gpio52";
+ bias-disable; /* No PULL */
+ drive-strength = <2>; /* 2 MA */
+ };
+ };
+
+ cam_sensor_front_iris_suspend: cam_sensor_front_iris_suspend {
+ /* RESET */
+ mux {
+ pins = "gpio52";
+ function = "gpio";
+ };
+
+ config {
+ pins = "gpio52";
+ bias-disable; /* No PULL */
+ drive-strength = <2>; /* 2 MA */
+ };
+ };
+
/* HS UART CONFIGURATION */
blsp1_uart1_active: blsp1_uart1_active {
mux {
diff --git a/arch/arm/mach-omap2/timer.c b/arch/arm/mach-omap2/timer.c
index f86692dbcfd5..83fc403aec3c 100644
--- a/arch/arm/mach-omap2/timer.c
+++ b/arch/arm/mach-omap2/timer.c
@@ -496,8 +496,7 @@ void __init omap_init_time(void)
__omap_sync32k_timer_init(1, "timer_32k_ck", "ti,timer-alwon",
2, "timer_sys_ck", NULL, false);
- if (of_have_populated_dt())
- clocksource_probe();
+ clocksource_probe();
}
#if defined(CONFIG_ARCH_OMAP3) || defined(CONFIG_SOC_AM43XX)
@@ -505,6 +504,8 @@ void __init omap3_secure_sync32k_timer_init(void)
{
__omap_sync32k_timer_init(12, "secure_32k_fck", "ti,timer-secure",
2, "timer_sys_ck", NULL, false);
+
+ clocksource_probe();
}
#endif /* CONFIG_ARCH_OMAP3 */
@@ -513,6 +514,8 @@ void __init omap3_gptimer_timer_init(void)
{
__omap_sync32k_timer_init(2, "timer_sys_ck", NULL,
1, "timer_sys_ck", "ti,timer-alwon", true);
+
+ clocksource_probe();
}
#endif
diff --git a/arch/arm64/configs/msm-auto-perf_defconfig b/arch/arm64/configs/msm-auto-perf_defconfig
index aa384f105165..eb1ebee6c2a0 100644
--- a/arch/arm64/configs/msm-auto-perf_defconfig
+++ b/arch/arm64/configs/msm-auto-perf_defconfig
@@ -273,6 +273,7 @@ CONFIG_CNSS_CRYPTO=y
CONFIG_ATH_CARDS=y
CONFIG_WIL6210=m
CONFIG_CNSS=y
+CONFIG_CNSS_ASYNC=y
CONFIG_CLD_LL_CORE=y
CONFIG_BUS_AUTO_SUSPEND=y
CONFIG_INPUT_EVDEV=y
@@ -340,6 +341,7 @@ CONFIG_WCD9335_CODEC=y
CONFIG_REGULATOR=y
CONFIG_REGULATOR_FIXED_VOLTAGE=y
CONFIG_REGULATOR_FAN53555=y
+CONFIG_REGULATOR_ONSEMI_NCP6335D=y
CONFIG_REGULATOR_RPM_SMD=y
CONFIG_REGULATOR_QPNP=y
CONFIG_REGULATOR_QPNP_LABIBB=y
diff --git a/arch/arm64/configs/msm-auto_defconfig b/arch/arm64/configs/msm-auto_defconfig
index df5060eadd9c..e3fbb5166478 100644
--- a/arch/arm64/configs/msm-auto_defconfig
+++ b/arch/arm64/configs/msm-auto_defconfig
@@ -274,6 +274,7 @@ CONFIG_CNSS_CRYPTO=y
CONFIG_ATH_CARDS=y
CONFIG_WIL6210=m
CONFIG_CNSS=y
+CONFIG_CNSS_ASYNC=y
CONFIG_CLD_LL_CORE=y
CONFIG_BUS_AUTO_SUSPEND=y
CONFIG_INPUT_EVDEV=y
@@ -343,6 +344,7 @@ CONFIG_WCD9335_CODEC=y
CONFIG_REGULATOR=y
CONFIG_REGULATOR_FIXED_VOLTAGE=y
CONFIG_REGULATOR_FAN53555=y
+CONFIG_REGULATOR_ONSEMI_NCP6335D=y
CONFIG_REGULATOR_RPM_SMD=y
CONFIG_REGULATOR_QPNP=y
CONFIG_REGULATOR_QPNP_LABIBB=y
diff --git a/arch/arm64/configs/msmcortex-perf_defconfig b/arch/arm64/configs/msmcortex-perf_defconfig
index 2fda53fb832b..778dcfecaf1c 100644
--- a/arch/arm64/configs/msmcortex-perf_defconfig
+++ b/arch/arm64/configs/msmcortex-perf_defconfig
@@ -65,7 +65,6 @@ CONFIG_CMA=y
CONFIG_CMA_DEBUGFS=y
CONFIG_ZSMALLOC=y
CONFIG_BALANCE_ANON_FILE_RECLAIM=y
-CONFIG_FORCE_ALLOC_FROM_DMA_ZONE=y
CONFIG_SECCOMP=y
CONFIG_ARMV8_DEPRECATED=y
CONFIG_SWP_EMULATION=y
diff --git a/arch/arm64/configs/msmcortex_mediabox-perf_defconfig b/arch/arm64/configs/msmcortex_mediabox-perf_defconfig
new file mode 100644
index 000000000000..cb0a5977c167
--- /dev/null
+++ b/arch/arm64/configs/msmcortex_mediabox-perf_defconfig
@@ -0,0 +1,642 @@
+CONFIG_LOCALVERSION="-perf"
+# CONFIG_LOCALVERSION_AUTO is not set
+CONFIG_AUDIT=y
+# CONFIG_AUDITSYSCALL is not set
+CONFIG_NO_HZ=y
+CONFIG_HIGH_RES_TIMERS=y
+CONFIG_IRQ_TIME_ACCOUNTING=y
+CONFIG_RCU_EXPERT=y
+CONFIG_RCU_FAST_NO_HZ=y
+CONFIG_IKCONFIG=y
+CONFIG_IKCONFIG_PROC=y
+CONFIG_LOG_CPU_MAX_BUF_SHIFT=17
+CONFIG_CGROUP_FREEZER=y
+CONFIG_CPUSETS=y
+CONFIG_CGROUP_CPUACCT=y
+CONFIG_CGROUP_SCHEDTUNE=y
+CONFIG_RT_GROUP_SCHED=y
+CONFIG_SCHED_HMP=y
+CONFIG_SCHED_HMP_CSTATE_AWARE=y
+CONFIG_SCHED_CORE_CTL=y
+CONFIG_NAMESPACES=y
+# CONFIG_UTS_NS is not set
+# CONFIG_PID_NS is not set
+CONFIG_SCHED_AUTOGROUP=y
+CONFIG_SCHED_TUNE=y
+CONFIG_BLK_DEV_INITRD=y
+# CONFIG_RD_XZ is not set
+# CONFIG_RD_LZO is not set
+# CONFIG_RD_LZ4 is not set
+CONFIG_CC_OPTIMIZE_FOR_SIZE=y
+CONFIG_KALLSYMS_ALL=y
+# CONFIG_AIO is not set
+# CONFIG_MEMBARRIER is not set
+CONFIG_EMBEDDED=y
+# CONFIG_SLUB_DEBUG is not set
+# CONFIG_COMPAT_BRK is not set
+CONFIG_PROFILING=y
+CONFIG_CC_STACKPROTECTOR_REGULAR=y
+CONFIG_ARCH_MMAP_RND_COMPAT_BITS=16
+CONFIG_MODULES=y
+CONFIG_MODULE_UNLOAD=y
+CONFIG_MODULE_FORCE_UNLOAD=y
+CONFIG_MODVERSIONS=y
+CONFIG_MODULE_SIG=y
+CONFIG_MODULE_SIG_FORCE=y
+CONFIG_MODULE_SIG_SHA512=y
+CONFIG_PARTITION_ADVANCED=y
+CONFIG_ARCH_QCOM=y
+CONFIG_ARCH_MSM8998=y
+CONFIG_ARCH_MSMHAMSTER=y
+CONFIG_PCI=y
+CONFIG_PCI_MSM=y
+CONFIG_SCHED_MC=y
+CONFIG_NR_CPUS=8
+CONFIG_QCOM_TLB_EL2_HANDLER=y
+CONFIG_PREEMPT=y
+CONFIG_HZ_100=y
+CONFIG_ARM64_REG_REBALANCE_ON_CTX_SW=y
+CONFIG_CMA=y
+CONFIG_CMA_DEBUGFS=y
+CONFIG_ZSMALLOC=y
+CONFIG_BALANCE_ANON_FILE_RECLAIM=y
+CONFIG_FORCE_ALLOC_FROM_DMA_ZONE=y
+CONFIG_SECCOMP=y
+CONFIG_ARMV8_DEPRECATED=y
+CONFIG_SWP_EMULATION=y
+CONFIG_CP15_BARRIER_EMULATION=y
+CONFIG_SETEND_EMULATION=y
+CONFIG_RANDOMIZE_BASE=y
+# CONFIG_RANDOMIZE_MODULE_REGION_FULL is not set
+# CONFIG_EFI is not set
+CONFIG_BUILD_ARM64_APPENDED_DTB_IMAGE=y
+# CONFIG_CORE_DUMP_DEFAULT_ELF_HEADERS is not set
+CONFIG_COMPAT=y
+CONFIG_PM_AUTOSLEEP=y
+CONFIG_PM_WAKELOCKS=y
+CONFIG_PM_WAKELOCKS_LIMIT=0
+# CONFIG_PM_WAKELOCKS_GC is not set
+CONFIG_CPU_FREQ=y
+CONFIG_CPU_FREQ_GOV_POWERSAVE=y
+CONFIG_CPU_FREQ_GOV_USERSPACE=y
+CONFIG_CPU_FREQ_GOV_ONDEMAND=y
+CONFIG_CPU_FREQ_GOV_INTERACTIVE=y
+CONFIG_CPU_FREQ_GOV_CONSERVATIVE=y
+CONFIG_CPU_BOOST=y
+CONFIG_NET=y
+CONFIG_PACKET=y
+CONFIG_UNIX=y
+CONFIG_XFRM_USER=y
+CONFIG_XFRM_STATISTICS=y
+CONFIG_NET_KEY=y
+CONFIG_INET=y
+CONFIG_IP_MULTICAST=y
+CONFIG_IP_ADVANCED_ROUTER=y
+CONFIG_IP_MULTIPLE_TABLES=y
+CONFIG_IP_ROUTE_VERBOSE=y
+CONFIG_IP_PNP=y
+CONFIG_IP_PNP_DHCP=y
+CONFIG_INET_AH=y
+CONFIG_INET_ESP=y
+CONFIG_INET_IPCOMP=y
+CONFIG_INET_DIAG_DESTROY=y
+CONFIG_IPV6_ROUTER_PREF=y
+CONFIG_IPV6_ROUTE_INFO=y
+CONFIG_IPV6_OPTIMISTIC_DAD=y
+CONFIG_INET6_AH=y
+CONFIG_INET6_ESP=y
+CONFIG_INET6_IPCOMP=y
+CONFIG_IPV6_MIP6=y
+CONFIG_IPV6_MULTIPLE_TABLES=y
+CONFIG_IPV6_SUBTREES=y
+CONFIG_NETFILTER=y
+CONFIG_NF_CONNTRACK=y
+CONFIG_NF_CONNTRACK_SECMARK=y
+CONFIG_NF_CONNTRACK_EVENTS=y
+CONFIG_NF_CT_PROTO_DCCP=y
+CONFIG_NF_CT_PROTO_SCTP=y
+CONFIG_NF_CT_PROTO_UDPLITE=y
+CONFIG_NF_CONNTRACK_AMANDA=y
+CONFIG_NF_CONNTRACK_FTP=y
+CONFIG_NF_CONNTRACK_H323=y
+CONFIG_NF_CONNTRACK_IRC=y
+CONFIG_NF_CONNTRACK_NETBIOS_NS=y
+CONFIG_NF_CONNTRACK_PPTP=y
+CONFIG_NF_CONNTRACK_SANE=y
+CONFIG_NF_CONNTRACK_TFTP=y
+CONFIG_NF_CT_NETLINK=y
+CONFIG_NETFILTER_XT_TARGET_CLASSIFY=y
+CONFIG_NETFILTER_XT_TARGET_CONNMARK=y
+CONFIG_NETFILTER_XT_TARGET_CONNSECMARK=y
+CONFIG_NETFILTER_XT_TARGET_IDLETIMER=y
+CONFIG_NETFILTER_XT_TARGET_HARDIDLETIMER=y
+CONFIG_NETFILTER_XT_TARGET_LOG=y
+CONFIG_NETFILTER_XT_TARGET_MARK=y
+CONFIG_NETFILTER_XT_TARGET_NFLOG=y
+CONFIG_NETFILTER_XT_TARGET_NFQUEUE=y
+CONFIG_NETFILTER_XT_TARGET_NOTRACK=y
+CONFIG_NETFILTER_XT_TARGET_TEE=y
+CONFIG_NETFILTER_XT_TARGET_TPROXY=y
+CONFIG_NETFILTER_XT_TARGET_TRACE=y
+CONFIG_NETFILTER_XT_TARGET_SECMARK=y
+CONFIG_NETFILTER_XT_TARGET_TCPMSS=y
+CONFIG_NETFILTER_XT_MATCH_COMMENT=y
+CONFIG_NETFILTER_XT_MATCH_CONNLIMIT=y
+CONFIG_NETFILTER_XT_MATCH_CONNMARK=y
+CONFIG_NETFILTER_XT_MATCH_CONNTRACK=y
+CONFIG_NETFILTER_XT_MATCH_DSCP=y
+CONFIG_NETFILTER_XT_MATCH_ESP=y
+CONFIG_NETFILTER_XT_MATCH_HASHLIMIT=y
+CONFIG_NETFILTER_XT_MATCH_HELPER=y
+CONFIG_NETFILTER_XT_MATCH_IPRANGE=y
+# CONFIG_NETFILTER_XT_MATCH_L2TP is not set
+CONFIG_NETFILTER_XT_MATCH_LENGTH=y
+CONFIG_NETFILTER_XT_MATCH_LIMIT=y
+CONFIG_NETFILTER_XT_MATCH_MAC=y
+CONFIG_NETFILTER_XT_MATCH_MARK=y
+CONFIG_NETFILTER_XT_MATCH_MULTIPORT=y
+CONFIG_NETFILTER_XT_MATCH_POLICY=y
+CONFIG_NETFILTER_XT_MATCH_PKTTYPE=y
+CONFIG_NETFILTER_XT_MATCH_QTAGUID=y
+CONFIG_NETFILTER_XT_MATCH_QUOTA=y
+CONFIG_NETFILTER_XT_MATCH_QUOTA2=y
+CONFIG_NETFILTER_XT_MATCH_SOCKET=y
+CONFIG_NETFILTER_XT_MATCH_STATE=y
+CONFIG_NETFILTER_XT_MATCH_STATISTIC=y
+CONFIG_NETFILTER_XT_MATCH_STRING=y
+CONFIG_NETFILTER_XT_MATCH_TIME=y
+CONFIG_NETFILTER_XT_MATCH_U32=y
+CONFIG_NF_CONNTRACK_IPV4=y
+CONFIG_IP_NF_IPTABLES=y
+CONFIG_IP_NF_MATCH_AH=y
+CONFIG_IP_NF_MATCH_ECN=y
+CONFIG_IP_NF_MATCH_RPFILTER=y
+CONFIG_IP_NF_MATCH_TTL=y
+CONFIG_IP_NF_FILTER=y
+CONFIG_IP_NF_TARGET_REJECT=y
+CONFIG_IP_NF_NAT=y
+CONFIG_IP_NF_TARGET_MASQUERADE=y
+CONFIG_IP_NF_TARGET_NETMAP=y
+CONFIG_IP_NF_TARGET_REDIRECT=y
+CONFIG_IP_NF_MANGLE=y
+CONFIG_IP_NF_RAW=y
+CONFIG_IP_NF_SECURITY=y
+CONFIG_IP_NF_ARPTABLES=y
+CONFIG_IP_NF_ARPFILTER=y
+CONFIG_IP_NF_ARP_MANGLE=y
+CONFIG_NF_CONNTRACK_IPV6=y
+CONFIG_IP6_NF_IPTABLES=y
+CONFIG_IP6_NF_MATCH_RPFILTER=y
+CONFIG_IP6_NF_FILTER=y
+CONFIG_IP6_NF_TARGET_REJECT=y
+CONFIG_IP6_NF_MANGLE=y
+CONFIG_IP6_NF_RAW=y
+CONFIG_BRIDGE_NF_EBTABLES=y
+CONFIG_BRIDGE_EBT_BROUTE=y
+CONFIG_L2TP=y
+CONFIG_L2TP_V3=y
+CONFIG_L2TP_IP=y
+CONFIG_L2TP_ETH=y
+CONFIG_BRIDGE=y
+CONFIG_NET_SCHED=y
+CONFIG_NET_SCH_HTB=y
+CONFIG_NET_SCH_PRIO=y
+CONFIG_NET_SCH_MULTIQ=y
+CONFIG_NET_SCH_INGRESS=y
+CONFIG_NET_CLS_FW=y
+CONFIG_NET_CLS_U32=y
+CONFIG_CLS_U32_MARK=y
+CONFIG_NET_CLS_FLOW=y
+CONFIG_NET_EMATCH=y
+CONFIG_NET_EMATCH_CMP=y
+CONFIG_NET_EMATCH_NBYTE=y
+CONFIG_NET_EMATCH_U32=y
+CONFIG_NET_EMATCH_META=y
+CONFIG_NET_EMATCH_TEXT=y
+CONFIG_NET_CLS_ACT=y
+CONFIG_NET_ACT_GACT=y
+CONFIG_NET_ACT_MIRRED=y
+CONFIG_NET_ACT_SKBEDIT=y
+CONFIG_RMNET_DATA=y
+CONFIG_RMNET_DATA_FC=y
+CONFIG_RMNET_DATA_DEBUG_PKT=y
+CONFIG_SOCKEV_NLMCAST=y
+CONFIG_BT=y
+CONFIG_MSM_BT_POWER=y
+CONFIG_BTFM_SLIM=y
+CONFIG_BTFM_SLIM_WCN3990=y
+CONFIG_CFG80211=y
+CONFIG_CFG80211_INTERNAL_REGDB=y
+CONFIG_CFG80211_WEXT=y
+CONFIG_MAC80211=m
+CONFIG_MAC80211_MESH=y
+CONFIG_MAC80211_LEDS=y
+CONFIG_RFKILL=y
+CONFIG_NFC_NQ=y
+CONFIG_IPC_ROUTER=y
+CONFIG_IPC_ROUTER_SECURITY=y
+CONFIG_FW_LOADER_USER_HELPER_FALLBACK=y
+CONFIG_DMA_CMA=y
+# CONFIG_PNP_DEBUG_MESSAGES is not set
+CONFIG_ZRAM=y
+CONFIG_BLK_DEV_LOOP=y
+CONFIG_BLK_DEV_RAM=y
+CONFIG_BLK_DEV_RAM_SIZE=8192
+CONFIG_QSEECOM=y
+CONFIG_HDCP_QSEECOM=y
+CONFIG_SCSI=y
+CONFIG_BLK_DEV_SD=y
+CONFIG_CHR_DEV_SG=y
+CONFIG_CHR_DEV_SCH=y
+CONFIG_SCSI_CONSTANTS=y
+CONFIG_SCSI_LOGGING=y
+CONFIG_SCSI_SCAN_ASYNC=y
+CONFIG_SCSI_UFSHCD=y
+CONFIG_SCSI_UFSHCD_PLATFORM=y
+CONFIG_SCSI_UFS_QCOM=y
+CONFIG_SCSI_UFS_QCOM_ICE=y
+CONFIG_MD=y
+CONFIG_BLK_DEV_MD=y
+CONFIG_MD_LINEAR=y
+CONFIG_BLK_DEV_DM=y
+CONFIG_DM_CRYPT=y
+CONFIG_DM_REQ_CRYPT=y
+CONFIG_DM_UEVENT=y
+CONFIG_DM_VERITY=y
+CONFIG_DM_VERITY_FEC=y
+CONFIG_DM_ANDROID_VERITY=y
+CONFIG_NETDEVICES=y
+CONFIG_BONDING=y
+CONFIG_DUMMY=y
+CONFIG_TUN=y
+CONFIG_SKY2=y
+CONFIG_RNDIS_IPA=y
+CONFIG_SMSC911X=y
+CONFIG_PPP=y
+CONFIG_PPP_BSDCOMP=y
+CONFIG_PPP_DEFLATE=y
+CONFIG_PPP_MPPE=y
+CONFIG_PPPOLAC=y
+CONFIG_PPPOPNS=y
+CONFIG_USB_USBNET=y
+CONFIG_WCNSS_MEM_PRE_ALLOC=y
+CONFIG_ATH_CARDS=y
+CONFIG_WIL6210=m
+CONFIG_ATH10K=m
+CONFIG_ATH10K_TARGET_SNOC=m
+CONFIG_ATH10K_SNOC=y
+CONFIG_CLD_LL_CORE=y
+CONFIG_INPUT_EVDEV=y
+CONFIG_INPUT_KEYRESET=y
+CONFIG_KEYBOARD_GPIO=y
+# CONFIG_INPUT_MOUSE is not set
+CONFIG_INPUT_TOUCHSCREEN=y
+CONFIG_TOUCHSCREEN_SYNAPTICS_DSX_CORE_v21=y
+CONFIG_TOUCHSCREEN_SYNAPTICS_DSX_FW_UPDATE_v21=y
+CONFIG_SECURE_TOUCH=y
+CONFIG_TOUCHSCREEN_ST=y
+CONFIG_TOUCHSCREEN_ST_I2C=y
+CONFIG_INPUT_MISC=y
+CONFIG_INPUT_HBTP_INPUT=y
+CONFIG_INPUT_QPNP_POWER_ON=y
+CONFIG_INPUT_UINPUT=y
+# CONFIG_SERIO_SERPORT is not set
+# CONFIG_VT is not set
+# CONFIG_LEGACY_PTYS is not set
+# CONFIG_DEVMEM is not set
+# CONFIG_DEVKMEM is not set
+CONFIG_SERIAL_MSM_HS=y
+CONFIG_SERIAL_MSM_SMD=y
+CONFIG_DIAG_CHAR=y
+CONFIG_HW_RANDOM=y
+CONFIG_HW_RANDOM_MSM_LEGACY=y
+CONFIG_MSM_ADSPRPC=y
+CONFIG_MSM_RDBG=m
+CONFIG_I2C_CHARDEV=y
+CONFIG_I2C_MSM_V2=y
+CONFIG_SLIMBUS_MSM_NGD=y
+CONFIG_SOUNDWIRE=y
+CONFIG_SPI=y
+CONFIG_SPI_QUP=y
+CONFIG_SPI_SPIDEV=y
+CONFIG_SPMI=y
+CONFIG_PINCTRL_MSM8998=y
+CONFIG_PINCTRL_SDM660=y
+CONFIG_GPIOLIB=y
+CONFIG_GPIO_SYSFS=y
+CONFIG_GPIO_QPNP_PIN=y
+CONFIG_POWER_RESET_QCOM=y
+CONFIG_QCOM_DLOAD_MODE=y
+CONFIG_POWER_RESET_XGENE=y
+CONFIG_POWER_RESET_SYSCON=y
+CONFIG_QPNP_FG_GEN3=y
+CONFIG_MSM_BCL_CTL=y
+CONFIG_MSM_BCL_PERIPHERAL_CTL=y
+CONFIG_BATTERY_BCL=y
+CONFIG_QPNP_SMB2=y
+CONFIG_SMB138X_CHARGER=y
+CONFIG_QPNP_QNOVO=y
+CONFIG_MSM_PM=y
+CONFIG_APSS_CORE_EA=y
+CONFIG_MSM_APM=y
+CONFIG_SENSORS_QPNP_ADC_VOLTAGE=y
+CONFIG_CPU_THERMAL=y
+CONFIG_LIMITS_MONITOR=y
+CONFIG_LIMITS_LITE_HW=y
+CONFIG_THERMAL_MONITOR=y
+CONFIG_THERMAL_TSENS8974=y
+CONFIG_THERMAL_QPNP=y
+CONFIG_THERMAL_QPNP_ADC_TM=y
+CONFIG_QCOM_THERMAL_LIMITS_DCVS=y
+CONFIG_MFD_SPMI_PMIC=y
+CONFIG_MFD_I2C_PMIC=y
+CONFIG_WCD9335_CODEC=y
+CONFIG_WCD934X_CODEC=y
+CONFIG_REGULATOR_FIXED_VOLTAGE=y
+CONFIG_REGULATOR_RPM_SMD=y
+CONFIG_REGULATOR_QPNP=y
+CONFIG_REGULATOR_QPNP_LABIBB=y
+CONFIG_REGULATOR_QPNP_LCDB=y
+CONFIG_REGULATOR_SPM=y
+CONFIG_REGULATOR_CPR3_HMSS=y
+CONFIG_REGULATOR_CPR3_MMSS=y
+CONFIG_REGULATOR_CPRH_KBSS=y
+CONFIG_REGULATOR_MEM_ACC=y
+CONFIG_REGULATOR_PROXY_CONSUMER=y
+CONFIG_REGULATOR_STUB=y
+CONFIG_MEDIA_SUPPORT=y
+CONFIG_MEDIA_CAMERA_SUPPORT=y
+CONFIG_MEDIA_DIGITAL_TV_SUPPORT=y
+CONFIG_MEDIA_CONTROLLER=y
+CONFIG_VIDEO_V4L2_SUBDEV_API=y
+CONFIG_VIDEO_ADV_DEBUG=y
+CONFIG_VIDEO_FIXED_MINOR_RANGES=y
+CONFIG_V4L_PLATFORM_DRIVERS=y
+CONFIG_MSM_CAMERA=y
+CONFIG_MSM_CAMERA_DEBUG=y
+CONFIG_MSMB_CAMERA=y
+CONFIG_MSMB_CAMERA_DEBUG=y
+CONFIG_MSM_CAMERA_SENSOR=y
+CONFIG_MSM_CPP=y
+CONFIG_MSM_CCI=y
+CONFIG_MSM_CSI20_HEADER=y
+CONFIG_MSM_CSI22_HEADER=y
+CONFIG_MSM_CSI30_HEADER=y
+CONFIG_MSM_CSI31_HEADER=y
+CONFIG_MSM_CSIPHY=y
+CONFIG_MSM_CSID=y
+CONFIG_MSM_EEPROM=y
+CONFIG_MSM_ISPIF=y
+CONFIG_IMX134=y
+CONFIG_IMX132=y
+CONFIG_OV9724=y
+CONFIG_OV5648=y
+CONFIG_GC0339=y
+CONFIG_OV8825=y
+CONFIG_OV8865=y
+CONFIG_s5k4e1=y
+CONFIG_OV12830=y
+CONFIG_MSM_V4L2_VIDEO_OVERLAY_DEVICE=y
+CONFIG_MSMB_JPEG=y
+CONFIG_MSM_FD=y
+CONFIG_MSM_JPEGDMA=y
+CONFIG_MSM_VIDC_V4L2=y
+CONFIG_MSM_VIDC_VMEM=y
+CONFIG_MSM_VIDC_GOVERNORS=y
+CONFIG_MSM_SDE_ROTATOR=y
+CONFIG_MSM_SDE_ROTATOR_EVTLOG_DEBUG=y
+CONFIG_DVB_MPQ=m
+CONFIG_DVB_MPQ_DEMUX=m
+CONFIG_DVB_MPQ_MEDIA_BOX_DEMUX=y
+CONFIG_TSPP=m
+CONFIG_DRM=y
+CONFIG_LOGO=y
+# CONFIG_LOGO_LINUX_MONO is not set
+# CONFIG_LOGO_LINUX_VGA16 is not set
+CONFIG_SOUND=y
+CONFIG_SND=y
+CONFIG_SND_USB_AUDIO=y
+CONFIG_SND_USB_AUDIO_QMI=y
+CONFIG_SND_SOC=y
+CONFIG_SND_SOC_MSM8998=y
+CONFIG_UHID=y
+CONFIG_HID_APPLE=y
+CONFIG_HID_ELECOM=y
+CONFIG_HID_MAGICMOUSE=y
+CONFIG_HID_MICROSOFT=y
+CONFIG_HID_MULTITOUCH=y
+CONFIG_HID_PLANTRONICS=y
+CONFIG_USB=y
+CONFIG_USB_ANNOUNCE_NEW_DEVICES=y
+CONFIG_USB_XHCI_HCD=y
+CONFIG_USB_EHCI_HCD=y
+CONFIG_USB_EHCI_HCD_PLATFORM=y
+CONFIG_USB_OHCI_HCD=y
+CONFIG_USB_OHCI_HCD_PLATFORM=y
+CONFIG_USB_STORAGE=y
+CONFIG_USB_DWC3=y
+CONFIG_USB_ISP1760=y
+CONFIG_USB_ISP1760_HOST_ROLE=y
+CONFIG_USB_PD_POLICY=y
+CONFIG_QPNP_USB_PDPHY=y
+CONFIG_USB_EHSET_TEST_FIXTURE=y
+CONFIG_USB_OTG_WAKELOCK=y
+CONFIG_NOP_USB_XCEIV=y
+CONFIG_USB_MSM_SSPHY_QMP=y
+CONFIG_MSM_QUSB_PHY=y
+CONFIG_DUAL_ROLE_USB_INTF=y
+CONFIG_USB_GADGET=y
+CONFIG_USB_GADGET_VBUS_DRAW=500
+CONFIG_USB_CONFIGFS=y
+CONFIG_USB_CONFIGFS_NCM=y
+CONFIG_USB_CONFIGFS_MASS_STORAGE=y
+CONFIG_USB_CONFIGFS_F_FS=y
+CONFIG_USB_CONFIGFS_F_MTP=y
+CONFIG_USB_CONFIGFS_F_PTP=y
+CONFIG_USB_CONFIGFS_F_ACC=y
+CONFIG_USB_CONFIGFS_UEVENT=y
+CONFIG_USB_CONFIGFS_F_MIDI=y
+CONFIG_USB_CONFIGFS_F_HID=y
+CONFIG_USB_CONFIGFS_F_DIAG=y
+CONFIG_USB_CONFIGFS_F_GSI=y
+CONFIG_USB_CONFIGFS_F_CDEV=y
+CONFIG_USB_CONFIGFS_F_QDSS=y
+CONFIG_USB_CONFIGFS_F_CCID=y
+CONFIG_MMC=y
+CONFIG_MMC_PERF_PROFILING=y
+CONFIG_MMC_CLKGATE=y
+CONFIG_MMC_BLOCK_MINORS=32
+CONFIG_MMC_TEST=y
+CONFIG_MMC_SDHCI=y
+CONFIG_MMC_SDHCI_PLTFM=y
+CONFIG_MMC_SDHCI_MSM=y
+CONFIG_LEDS_QPNP=y
+CONFIG_LEDS_QPNP_FLASH_V2=y
+CONFIG_LEDS_QPNP_WLED=y
+CONFIG_LEDS_SYSCON=y
+CONFIG_SWITCH=y
+CONFIG_RTC_CLASS=y
+CONFIG_RTC_DRV_QPNP=y
+CONFIG_ESOC=y
+CONFIG_ESOC_DEV=y
+CONFIG_ESOC_CLIENT=y
+CONFIG_ESOC_MDM_4x=y
+CONFIG_ESOC_MDM_DRV=y
+CONFIG_DMADEVICES=y
+CONFIG_QCOM_SPS_DMA=y
+CONFIG_UIO=y
+CONFIG_UIO_MSM_SHAREDMEM=y
+CONFIG_STAGING=y
+CONFIG_ASHMEM=y
+CONFIG_ANDROID_TIMED_GPIO=y
+CONFIG_ANDROID_LOW_MEMORY_KILLER=y
+CONFIG_ION=y
+CONFIG_ION_MSM=y
+CONFIG_QPNP_REVID=y
+CONFIG_QPNP_COINCELL=y
+CONFIG_SPS=y
+CONFIG_SPS_SUPPORT_NDP_BAM=y
+CONFIG_IPA=y
+CONFIG_RMNET_IPA=y
+CONFIG_GSI=y
+CONFIG_IPA3=y
+CONFIG_RMNET_IPA3=y
+CONFIG_GPIO_USB_DETECT=y
+CONFIG_SEEMP_CORE=y
+CONFIG_USB_BAM=y
+CONFIG_MSM_MDSS_PLL=y
+CONFIG_REMOTE_SPINLOCK_MSM=y
+CONFIG_MSM_TIMER_LEAP=y
+CONFIG_IOMMU_IO_PGTABLE_FAST=y
+CONFIG_ARM_SMMU=y
+CONFIG_IOMMU_DEBUG=y
+CONFIG_IOMMU_DEBUG_TRACKING=y
+CONFIG_IOMMU_TESTS=y
+CONFIG_MSM_SMEM=y
+CONFIG_QPNP_HAPTIC=y
+CONFIG_MSM_SMD=y
+CONFIG_MSM_GLINK=y
+CONFIG_MSM_GLINK_LOOPBACK_SERVER=y
+CONFIG_MSM_GLINK_SMD_XPRT=y
+CONFIG_MSM_GLINK_SMEM_NATIVE_XPRT=y
+CONFIG_MSM_GLINK_SPI_XPRT=y
+CONFIG_MSM_SPCOM=y
+CONFIG_MSM_SPSS_UTILS=y
+CONFIG_MSM_SMEM_LOGGING=y
+CONFIG_MSM_SMP2P=y
+CONFIG_MSM_SMP2P_TEST=y
+CONFIG_MSM_QMI_INTERFACE=y
+CONFIG_MSM_RPM_SMD=y
+CONFIG_QCOM_BUS_SCALING=y
+CONFIG_MSM_SERVICE_LOCATOR=y
+CONFIG_MSM_IPC_ROUTER_SMD_XPRT=y
+CONFIG_MSM_SYSMON_GLINK_COMM=y
+CONFIG_MSM_IPC_ROUTER_GLINK_XPRT=y
+CONFIG_MSM_GLINK_PKT=y
+CONFIG_MSM_SPM=y
+CONFIG_QCOM_WATCHDOG_V2=y
+CONFIG_QCOM_IRQ_HELPER=y
+CONFIG_QCOM_MEMORY_DUMP_V2=y
+CONFIG_ICNSS=y
+CONFIG_MSM_RUN_QUEUE_STATS=y
+CONFIG_MSM_BOOT_STATS=y
+CONFIG_MSM_ADSP_LOADER=y
+CONFIG_MSM_PERFORMANCE=y
+CONFIG_MSM_SUBSYSTEM_RESTART=y
+CONFIG_MSM_PIL=y
+CONFIG_MSM_PIL_SSR_GENERIC=y
+CONFIG_MSM_PIL_MSS_QDSP6V5=y
+CONFIG_TRACER_PKT=y
+CONFIG_QCOM_FORCE_WDOG_BITE_ON_PANIC=y
+CONFIG_MSM_MPM_OF=y
+CONFIG_MSM_EVENT_TIMER=y
+CONFIG_MSM_AVTIMER=y
+CONFIG_QCOM_REMOTEQDSS=y
+CONFIG_MSM_SERVICE_NOTIFIER=y
+CONFIG_MSM_RPM_RBCPR_STATS_V2_LOG=y
+CONFIG_MSM_RPM_LOG=y
+CONFIG_MSM_RPM_STATS_LOG=y
+CONFIG_QSEE_IPC_IRQ_BRIDGE=y
+CONFIG_QCOM_SMCINVOKE=y
+CONFIG_QCOM_EARLY_RANDOM=y
+CONFIG_MEM_SHARE_QMI_SERVICE=y
+CONFIG_QCOM_BIMC_BWMON=y
+CONFIG_ARM_MEMLAT_MON=y
+CONFIG_DEVFREQ_GOV_QCOM_BW_HWMON=y
+CONFIG_DEVFREQ_GOV_MEMLAT=y
+CONFIG_QCOM_DEVFREQ_DEVBW=y
+CONFIG_SPDM_SCM=y
+CONFIG_DEVFREQ_SPDM=y
+CONFIG_EXTCON=y
+CONFIG_IIO=y
+CONFIG_QCOM_RRADC=y
+CONFIG_QCOM_TADC=y
+CONFIG_PWM=y
+CONFIG_PWM_QPNP=y
+CONFIG_ARM_GIC_V3_ACL=y
+CONFIG_ANDROID=y
+CONFIG_ANDROID_BINDER_IPC=y
+CONFIG_ANDROID_BINDER_DEVICES="binder,hwbinder"
+CONFIG_MSM_TZ_LOG=y
+CONFIG_SENSORS_SSC=y
+CONFIG_EXT2_FS=y
+CONFIG_EXT2_FS_XATTR=y
+CONFIG_EXT3_FS=y
+CONFIG_EXT4_FS_SECURITY=y
+CONFIG_EXT4_ENCRYPTION=y
+CONFIG_EXT4_FS_ENCRYPTION=y
+CONFIG_EXT4_FS_ICE_ENCRYPTION=y
+CONFIG_FUSE_FS=y
+CONFIG_MSDOS_FS=y
+CONFIG_VFAT_FS=y
+CONFIG_TMPFS_POSIX_ACL=y
+CONFIG_ECRYPT_FS=y
+CONFIG_ECRYPT_FS_MESSAGING=y
+CONFIG_NLS_CODEPAGE_437=y
+CONFIG_NLS_ISO8859_1=y
+CONFIG_PRINTK_TIME=y
+CONFIG_DEBUG_INFO=y
+CONFIG_MAGIC_SYSRQ=y
+CONFIG_PANIC_TIMEOUT=5
+CONFIG_SCHEDSTATS=y
+CONFIG_TIMER_STATS=y
+# CONFIG_DEBUG_PREEMPT is not set
+CONFIG_IPC_LOGGING=y
+CONFIG_CPU_FREQ_SWITCH_PROFILER=y
+CONFIG_DEBUG_SET_MODULE_RONX=y
+CONFIG_DEBUG_ALIGN_RODATA=y
+CONFIG_CORESIGHT=y
+CONFIG_CORESIGHT_EVENT=y
+CONFIG_CORESIGHT_LINK_AND_SINK_TMC=y
+CONFIG_CORESIGHT_QCOM_REPLICATOR=y
+CONFIG_CORESIGHT_STM=y
+CONFIG_CORESIGHT_HWEVENT=y
+CONFIG_CORESIGHT_CTI=y
+CONFIG_CORESIGHT_TPDA=y
+CONFIG_CORESIGHT_TPDM=y
+CONFIG_CORESIGHT_QPDI=y
+CONFIG_CORESIGHT_SOURCE_DUMMY=y
+CONFIG_PFK=y
+CONFIG_SECURITY=y
+CONFIG_SECURITY_SELINUX=y
+CONFIG_SECURITY_SMACK=y
+CONFIG_CRYPTO_ECHAINIV=y
+CONFIG_CRYPTO_XCBC=y
+CONFIG_CRYPTO_MD4=y
+CONFIG_CRYPTO_TWOFISH=y
+CONFIG_CRYPTO_ANSI_CPRNG=y
+CONFIG_CRYPTO_DEV_QCRYPTO=y
+CONFIG_CRYPTO_DEV_QCOM_MSM_QCE=y
+CONFIG_CRYPTO_DEV_QCEDEV=y
+CONFIG_CRYPTO_DEV_OTA_CRYPTO=y
+CONFIG_CRYPTO_DEV_QCOM_ICE=y
+CONFIG_SYSTEM_TRUSTED_KEYS="verity.x509.pem"
+CONFIG_ARM64_CRYPTO=y
+CONFIG_CRYPTO_SHA1_ARM64_CE=y
+CONFIG_CRYPTO_SHA2_ARM64_CE=y
+CONFIG_CRYPTO_GHASH_ARM64_CE=y
+CONFIG_CRYPTO_AES_ARM64_CE_CCM=y
+CONFIG_CRYPTO_AES_ARM64_CE_BLK=y
+CONFIG_CRYPTO_AES_ARM64_NEON_BLK=y
+CONFIG_CRYPTO_CRC32_ARM64=y
+CONFIG_QMI_ENCDEC=y
diff --git a/arch/mips/kernel/crash.c b/arch/mips/kernel/crash.c
index d434d5d5ae6e..610f0f3bdb34 100644
--- a/arch/mips/kernel/crash.c
+++ b/arch/mips/kernel/crash.c
@@ -14,12 +14,22 @@ static int crashing_cpu = -1;
static cpumask_t cpus_in_crash = CPU_MASK_NONE;
#ifdef CONFIG_SMP
-static void crash_shutdown_secondary(void *ignore)
+static void crash_shutdown_secondary(void *passed_regs)
{
- struct pt_regs *regs;
+ struct pt_regs *regs = passed_regs;
int cpu = smp_processor_id();
- regs = task_pt_regs(current);
+ /*
+ * If we are passed registers, use those. Otherwise get the
+ * regs from the last interrupt, which should be correct, as
+ * we are in an interrupt. But if the regs are not there,
+ * pull them from the top of the stack. They are probably
+ * wrong, but we need something to keep from crashing again.
+ */
+ if (!regs)
+ regs = get_irq_regs();
+ if (!regs)
+ regs = task_pt_regs(current);
if (!cpu_online(cpu))
return;
diff --git a/arch/mips/kernel/elf.c b/arch/mips/kernel/elf.c
index 4a4d9e067c89..3afffc30ee12 100644
--- a/arch/mips/kernel/elf.c
+++ b/arch/mips/kernel/elf.c
@@ -206,7 +206,7 @@ int arch_check_elf(void *_ehdr, bool has_interpreter,
else if ((prog_req.fr1 && prog_req.frdefault) ||
(prog_req.single && !prog_req.frdefault))
/* Make sure 64-bit MIPS III/IV/64R1 will not pick FR1 */
- state->overall_fp_mode = ((current_cpu_data.fpu_id & MIPS_FPIR_F64) &&
+ state->overall_fp_mode = ((raw_current_cpu_data.fpu_id & MIPS_FPIR_F64) &&
cpu_has_mips_r2_r6) ?
FP_FR1 : FP_FR0;
else if (prog_req.fr1)
diff --git a/arch/mips/kernel/kgdb.c b/arch/mips/kernel/kgdb.c
index de63d36af895..732d6171ac6a 100644
--- a/arch/mips/kernel/kgdb.c
+++ b/arch/mips/kernel/kgdb.c
@@ -244,9 +244,6 @@ static int compute_signal(int tt)
void sleeping_thread_to_gdb_regs(unsigned long *gdb_regs, struct task_struct *p)
{
int reg;
- struct thread_info *ti = task_thread_info(p);
- unsigned long ksp = (unsigned long)ti + THREAD_SIZE - 32;
- struct pt_regs *regs = (struct pt_regs *)ksp - 1;
#if (KGDB_GDB_REG_SIZE == 32)
u32 *ptr = (u32 *)gdb_regs;
#else
@@ -254,25 +251,46 @@ void sleeping_thread_to_gdb_regs(unsigned long *gdb_regs, struct task_struct *p)
#endif
for (reg = 0; reg < 16; reg++)
- *(ptr++) = regs->regs[reg];
+ *(ptr++) = 0;
/* S0 - S7 */
- for (reg = 16; reg < 24; reg++)
- *(ptr++) = regs->regs[reg];
+ *(ptr++) = p->thread.reg16;
+ *(ptr++) = p->thread.reg17;
+ *(ptr++) = p->thread.reg18;
+ *(ptr++) = p->thread.reg19;
+ *(ptr++) = p->thread.reg20;
+ *(ptr++) = p->thread.reg21;
+ *(ptr++) = p->thread.reg22;
+ *(ptr++) = p->thread.reg23;
for (reg = 24; reg < 28; reg++)
*(ptr++) = 0;
/* GP, SP, FP, RA */
- for (reg = 28; reg < 32; reg++)
- *(ptr++) = regs->regs[reg];
-
- *(ptr++) = regs->cp0_status;
- *(ptr++) = regs->lo;
- *(ptr++) = regs->hi;
- *(ptr++) = regs->cp0_badvaddr;
- *(ptr++) = regs->cp0_cause;
- *(ptr++) = regs->cp0_epc;
+ *(ptr++) = (long)p;
+ *(ptr++) = p->thread.reg29;
+ *(ptr++) = p->thread.reg30;
+ *(ptr++) = p->thread.reg31;
+
+ *(ptr++) = p->thread.cp0_status;
+
+ /* lo, hi */
+ *(ptr++) = 0;
+ *(ptr++) = 0;
+
+ /*
+ * BadVAddr, Cause
+ * Ideally these would come from the last exception frame up the stack
+ * but that requires unwinding, otherwise we can't know much for sure.
+ */
+ *(ptr++) = 0;
+ *(ptr++) = 0;
+
+ /*
+ * PC
+ * use return address (RA), i.e. the moment after return from resume()
+ */
+ *(ptr++) = p->thread.reg31;
}
void kgdb_arch_set_pc(struct pt_regs *regs, unsigned long pc)
diff --git a/arch/sparc/include/asm/pgtable_64.h b/arch/sparc/include/asm/pgtable_64.h
index 408b715c95a5..9d81579f3d54 100644
--- a/arch/sparc/include/asm/pgtable_64.h
+++ b/arch/sparc/include/asm/pgtable_64.h
@@ -668,26 +668,27 @@ static inline unsigned long pmd_pfn(pmd_t pmd)
return pte_pfn(pte);
}
-#ifdef CONFIG_TRANSPARENT_HUGEPAGE
-static inline unsigned long pmd_dirty(pmd_t pmd)
+#define __HAVE_ARCH_PMD_WRITE
+static inline unsigned long pmd_write(pmd_t pmd)
{
pte_t pte = __pte(pmd_val(pmd));
- return pte_dirty(pte);
+ return pte_write(pte);
}
-static inline unsigned long pmd_young(pmd_t pmd)
+#ifdef CONFIG_TRANSPARENT_HUGEPAGE
+static inline unsigned long pmd_dirty(pmd_t pmd)
{
pte_t pte = __pte(pmd_val(pmd));
- return pte_young(pte);
+ return pte_dirty(pte);
}
-static inline unsigned long pmd_write(pmd_t pmd)
+static inline unsigned long pmd_young(pmd_t pmd)
{
pte_t pte = __pte(pmd_val(pmd));
- return pte_write(pte);
+ return pte_young(pte);
}
static inline unsigned long pmd_trans_huge(pmd_t pmd)
diff --git a/arch/sparc/mm/init_64.c b/arch/sparc/mm/init_64.c
index 3d3414c14792..965655afdbb6 100644
--- a/arch/sparc/mm/init_64.c
+++ b/arch/sparc/mm/init_64.c
@@ -1493,7 +1493,7 @@ bool kern_addr_valid(unsigned long addr)
if ((long)addr < 0L) {
unsigned long pa = __pa(addr);
- if ((addr >> max_phys_bits) != 0UL)
+ if ((pa >> max_phys_bits) != 0UL)
return false;
return pfn_valid(pa >> PAGE_SHIFT);
diff --git a/arch/x86/kernel/ftrace.c b/arch/x86/kernel/ftrace.c
index eb6bd34582c6..1b96bfe09d42 100644
--- a/arch/x86/kernel/ftrace.c
+++ b/arch/x86/kernel/ftrace.c
@@ -977,6 +977,18 @@ void prepare_ftrace_return(unsigned long self_addr, unsigned long *parent,
unsigned long return_hooker = (unsigned long)
&return_to_handler;
+ /*
+ * When resuming from suspend-to-ram, this function can be indirectly
+ * called from early CPU startup code while the CPU is in real mode,
+ * which would fail miserably. Make sure the stack pointer is a
+ * virtual address.
+ *
+ * This check isn't as accurate as virt_addr_valid(), but it should be
+ * good enough for this purpose, and it's fast.
+ */
+ if (unlikely((long)__builtin_frame_address(0) >= 0))
+ return;
+
if (unlikely(ftrace_graph_is_dead()))
return;
diff --git a/arch/x86/xen/time.c b/arch/x86/xen/time.c
index f1ba6a092854..8846257d8792 100644
--- a/arch/x86/xen/time.c
+++ b/arch/x86/xen/time.c
@@ -343,11 +343,11 @@ static int xen_vcpuop_set_next_event(unsigned long delta,
WARN_ON(!clockevent_state_oneshot(evt));
single.timeout_abs_ns = get_abs_timeout(delta);
- single.flags = VCPU_SSHOTTMR_future;
+ /* Get an event anyway, even if the timeout is already expired */
+ single.flags = 0;
ret = HYPERVISOR_vcpu_op(VCPUOP_set_singleshot_timer, cpu, &single);
-
- BUG_ON(ret != 0 && ret != -ETIME);
+ BUG_ON(ret != 0);
return ret;
}
diff --git a/crypto/testmgr.c b/crypto/testmgr.c
index 8374ca8b6579..6d4da8fd24fd 100644
--- a/crypto/testmgr.c
+++ b/crypto/testmgr.c
@@ -488,6 +488,8 @@ static int __test_aead(struct crypto_aead *tfm, int enc,
aead_request_set_callback(req, CRYPTO_TFM_REQ_MAY_BACKLOG,
tcrypt_complete, &result);
+ iv_len = crypto_aead_ivsize(tfm);
+
for (i = 0, j = 0; i < tcount; i++) {
if (template[i].np)
continue;
@@ -508,7 +510,6 @@ static int __test_aead(struct crypto_aead *tfm, int enc,
memcpy(input, template[i].input, template[i].ilen);
memcpy(assoc, template[i].assoc, template[i].alen);
- iv_len = crypto_aead_ivsize(tfm);
if (template[i].iv)
memcpy(iv, template[i].iv, iv_len);
else
@@ -617,7 +618,7 @@ static int __test_aead(struct crypto_aead *tfm, int enc,
j++;
if (template[i].iv)
- memcpy(iv, template[i].iv, MAX_IVLEN);
+ memcpy(iv, template[i].iv, iv_len);
else
memset(iv, 0, MAX_IVLEN);
diff --git a/drivers/bluetooth/bluetooth-power.c b/drivers/bluetooth/bluetooth-power.c
index b05b999fbbdc..59245ba320f6 100644
--- a/drivers/bluetooth/bluetooth-power.c
+++ b/drivers/bluetooth/bluetooth-power.c
@@ -704,6 +704,7 @@ static long bt_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
} else {
BT_PWR_ERR("BT chip state is already :%d no change d\n"
, pwr_state);
+ ret = 0;
}
break;
default:
diff --git a/drivers/bluetooth/btfm_slim_codec.c b/drivers/bluetooth/btfm_slim_codec.c
index 1ed366fd3d71..4dd8e6833ccf 100644
--- a/drivers/bluetooth/btfm_slim_codec.c
+++ b/drivers/bluetooth/btfm_slim_codec.c
@@ -332,6 +332,9 @@ static int btfm_slim_dai_get_channel_map(struct snd_soc_dai *dai,
*tx_num = 0;
*rx_num = num;
break;
+ default:
+ BTFMSLIM_ERR("Unsupported DAI %d", dai->id);
+ return -EINVAL;
}
do {
diff --git a/drivers/char/adsprpc.c b/drivers/char/adsprpc.c
index 7e44b38bbfca..b1432ccf5358 100644
--- a/drivers/char/adsprpc.c
+++ b/drivers/char/adsprpc.c
@@ -2126,11 +2126,9 @@ void fastrpc_glink_notify_state(void *handle, const void *priv, unsigned event)
link->port_state = FASTRPC_LINK_DISCONNECTED;
break;
case GLINK_REMOTE_DISCONNECTED:
- if (me->channel[cid].chan &&
- link->link_state == FASTRPC_LINK_STATE_UP) {
+ if (me->channel[cid].chan) {
fastrpc_glink_close(me->channel[cid].chan, cid);
me->channel[cid].chan = 0;
- link->port_state = FASTRPC_LINK_DISCONNECTED;
}
break;
default:
@@ -2296,10 +2294,9 @@ static int fastrpc_glink_open(int cid)
if (err)
goto bail;
- if (link->port_state == FASTRPC_LINK_CONNECTED ||
- link->port_state == FASTRPC_LINK_CONNECTING) {
+ VERIFY(err, (link->port_state == FASTRPC_LINK_DISCONNECTED));
+ if (err)
goto bail;
- }
link->port_state = FASTRPC_LINK_CONNECTING;
cfg->priv = (void *)(uintptr_t)cid;
@@ -2458,7 +2455,9 @@ static int fastrpc_channel_open(struct fastrpc_file *fl)
if ((kref_get_unless_zero(&me->channel[cid].kref) == 0) ||
(me->channel[cid].chan == 0)) {
if (me->glink) {
- fastrpc_glink_register(cid, me);
+ VERIFY(err, 0 == fastrpc_glink_register(cid, me));
+ if (err)
+ goto bail;
VERIFY(err, 0 == fastrpc_glink_open(cid));
} else {
VERIFY(err, !smd_named_open_on_edge(FASTRPC_SMD_GUID,
diff --git a/drivers/char/diag/diagchar_core.c b/drivers/char/diag/diagchar_core.c
index 682c035c5bd4..dc2d9fc4282c 100644
--- a/drivers/char/diag/diagchar_core.c
+++ b/drivers/char/diag/diagchar_core.c
@@ -2341,7 +2341,9 @@ long diagchar_ioctl(struct file *filp,
mutex_unlock(&driver->dci_mutex);
break;
case DIAG_IOCTL_DCI_EVENT_STATUS:
+ mutex_lock(&driver->dci_mutex);
result = diag_ioctl_dci_event_status(ioarg);
+ mutex_unlock(&driver->dci_mutex);
break;
case DIAG_IOCTL_DCI_CLEAR_LOGS:
mutex_lock(&driver->dci_mutex);
diff --git a/drivers/clk/sunxi/clk-simple-gates.c b/drivers/clk/sunxi/clk-simple-gates.c
index 0214c6548afd..97cb4221de25 100644
--- a/drivers/clk/sunxi/clk-simple-gates.c
+++ b/drivers/clk/sunxi/clk-simple-gates.c
@@ -98,6 +98,8 @@ static void __init sunxi_simple_gates_init(struct device_node *node)
sunxi_simple_gates_setup(node, NULL, 0);
}
+CLK_OF_DECLARE(sun4i_a10_gates, "allwinner,sun4i-a10-gates-clk",
+ sunxi_simple_gates_init);
CLK_OF_DECLARE(sun4i_a10_apb0, "allwinner,sun4i-a10-apb0-gates-clk",
sunxi_simple_gates_init);
CLK_OF_DECLARE(sun4i_a10_apb1, "allwinner,sun4i-a10-apb1-gates-clk",
diff --git a/drivers/crypto/msm/ota_crypto.c b/drivers/crypto/msm/ota_crypto.c
index 674913cb20bf..a568bf46f09f 100644
--- a/drivers/crypto/msm/ota_crypto.c
+++ b/drivers/crypto/msm/ota_crypto.c
@@ -239,6 +239,9 @@ static void req_done(unsigned long data)
if (!list_empty(&podev->ready_commands)) {
new_req = container_of(podev->ready_commands.next,
struct ota_async_req, rlist);
+ if (!new_req)
+ break;
+
list_del(&new_req->rlist);
pqce->active_command = new_req;
spin_unlock_irqrestore(&podev->lock, flags);
diff --git a/drivers/gpu/drm/amd/amdgpu/kv_dpm.c b/drivers/gpu/drm/amd/amdgpu/kv_dpm.c
index 7e9154c7f1db..d1c9525d81eb 100644
--- a/drivers/gpu/drm/amd/amdgpu/kv_dpm.c
+++ b/drivers/gpu/drm/amd/amdgpu/kv_dpm.c
@@ -2258,7 +2258,7 @@ static void kv_apply_state_adjust_rules(struct amdgpu_device *adev,
if (pi->caps_stable_p_state) {
stable_p_state_sclk = (max_limits->sclk * 75) / 100;
- for (i = table->count - 1; i >= 0; i++) {
+ for (i = table->count - 1; i >= 0; i--) {
if (stable_p_state_sclk >= table->entries[i].clk) {
stable_p_state_sclk = table->entries[i].clk;
break;
diff --git a/drivers/gpu/drm/msm/adreno/a5xx_gpu.c b/drivers/gpu/drm/msm/adreno/a5xx_gpu.c
index de2ee1ffb735..dbd4fb8b2212 100644
--- a/drivers/gpu/drm/msm/adreno/a5xx_gpu.c
+++ b/drivers/gpu/drm/msm/adreno/a5xx_gpu.c
@@ -15,6 +15,9 @@
#include "msm_iommu.h"
#include "a5xx_gpu.h"
+#define SECURE_VA_START 0xc0000000
+#define SECURE_VA_SIZE SZ_256M
+
static void a5xx_flush(struct msm_gpu *gpu, struct msm_ringbuffer *ring)
{
struct adreno_gpu *adreno_gpu = to_adreno_gpu(gpu);
@@ -133,6 +136,12 @@ static int a5xx_submit(struct msm_gpu *gpu, struct msm_gem_submit *submit)
OUT_PKT7(ring, CP_YIELD_ENABLE, 1);
OUT_RING(ring, 0x02);
+ /* Turn on secure mode if the submission is secure */
+ if (submit->secure) {
+ OUT_PKT7(ring, CP_SET_SECURE_MODE, 1);
+ OUT_RING(ring, 1);
+ }
+
/* Record the always on counter before command execution */
if (submit->profile_buf_iova) {
uint64_t gpuaddr = submit->profile_buf_iova +
@@ -212,6 +221,11 @@ static int a5xx_submit(struct msm_gpu *gpu, struct msm_gem_submit *submit)
OUT_RING(ring, upper_32_bits(rbmemptr(adreno_gpu, ring->id, fence)));
OUT_RING(ring, submit->fence);
+ if (submit->secure) {
+ OUT_PKT7(ring, CP_SET_SECURE_MODE, 1);
+ OUT_RING(ring, 0);
+ }
+
/* Yield the floor on command completion */
OUT_PKT7(ring, CP_CONTEXT_SWITCH_YIELD, 4);
/*
@@ -762,14 +776,10 @@ static int a5xx_hw_init(struct msm_gpu *gpu)
ADRENO_PROTECT_RW(0x10000, 0x8000));
gpu_write(gpu, REG_A5XX_RBBM_SECVID_TSB_CNTL, 0);
- /*
- * Disable the trusted memory range - we don't actually supported secure
- * memory rendering at this point in time and we don't want to block off
- * part of the virtual memory space.
- */
+
gpu_write64(gpu, REG_A5XX_RBBM_SECVID_TSB_TRUSTED_BASE_LO,
- REG_A5XX_RBBM_SECVID_TSB_TRUSTED_BASE_HI, 0x00000000);
- gpu_write(gpu, REG_A5XX_RBBM_SECVID_TSB_TRUSTED_SIZE, 0x00000000);
+ REG_A5XX_RBBM_SECVID_TSB_TRUSTED_BASE_HI, SECURE_VA_START);
+ gpu_write(gpu, REG_A5XX_RBBM_SECVID_TSB_TRUSTED_SIZE, SECURE_VA_SIZE);
/* Put the GPU into 64 bit by default */
gpu_write(gpu, REG_A5XX_CP_ADDR_MODE_CNTL, 0x1);
@@ -1405,6 +1415,9 @@ struct msm_gpu *a5xx_gpu_init(struct drm_device *dev)
a5xx_config.va_start = 0x800000000;
a5xx_config.va_end = 0x8ffffffff;
+ a5xx_config.secure_va_start = SECURE_VA_START;
+ a5xx_config.secure_va_end = SECURE_VA_START + SECURE_VA_SIZE - 1;
+
ret = adreno_gpu_init(dev, pdev, adreno_gpu, &funcs, &a5xx_config);
if (ret) {
a5xx_destroy(&(a5xx_gpu->base.base));
diff --git a/drivers/gpu/drm/msm/adreno/adreno_gpu.c b/drivers/gpu/drm/msm/adreno/adreno_gpu.c
index 9952fa8dcda5..0929dc1ce78e 100644
--- a/drivers/gpu/drm/msm/adreno/adreno_gpu.c
+++ b/drivers/gpu/drm/msm/adreno/adreno_gpu.c
@@ -563,6 +563,15 @@ int adreno_gpu_init(struct drm_device *drm, struct platform_device *pdev,
return ret;
}
+ if (gpu->secure_aspace) {
+ mmu = gpu->secure_aspace->mmu;
+ if (mmu) {
+ ret = mmu->funcs->attach(mmu, NULL, 0);
+ if (ret)
+ return ret;
+ }
+ }
+
mutex_lock(&drm->struct_mutex);
adreno_gpu->memptrs_bo = msm_gem_new(drm, sizeof(*adreno_gpu->memptrs),
MSM_BO_UNCACHED);
@@ -608,6 +617,12 @@ void adreno_gpu_cleanup(struct adreno_gpu *gpu)
aspace->mmu->funcs->detach(aspace->mmu);
msm_gem_address_space_put(aspace);
}
+
+ if (gpu->base.secure_aspace) {
+ aspace = gpu->base.secure_aspace;
+ aspace->mmu->funcs->detach(aspace->mmu);
+ msm_gem_address_space_put(aspace);
+ }
}
static void adreno_snapshot_os(struct msm_gpu *gpu,
diff --git a/drivers/gpu/drm/msm/hdmi-staging/sde_hdmi.c b/drivers/gpu/drm/msm/hdmi-staging/sde_hdmi.c
index 1ff3ee2bdca6..c377f3759e67 100644
--- a/drivers/gpu/drm/msm/hdmi-staging/sde_hdmi.c
+++ b/drivers/gpu/drm/msm/hdmi-staging/sde_hdmi.c
@@ -934,7 +934,6 @@ static void _sde_hdmi_hotplug_work(struct work_struct *work)
} else
sde_free_edid((void **)&sde_hdmi->edid_ctrl);
- sde_hdmi_notify_clients(connector, sde_hdmi->connected);
drm_helper_hpd_irq_event(connector->dev);
}
@@ -964,8 +963,7 @@ static void _sde_hdmi_connector_irq(struct sde_hdmi *sde_hdmi)
hpd_int_ctrl |= HDMI_HPD_INT_CTRL_INT_CONNECT;
hdmi_write(hdmi, REG_HDMI_HPD_INT_CTRL, hpd_int_ctrl);
- if (!sde_hdmi->non_pluggable)
- queue_work(hdmi->workq, &sde_hdmi->hpd_work);
+ queue_work(hdmi->workq, &sde_hdmi->hpd_work);
}
}
@@ -1054,6 +1052,25 @@ static int _sde_hdmi_get_cable_status(struct platform_device *pdev, u32 vote)
return hdmi->power_on && display->connected;
}
+static void _sde_hdmi_audio_codec_ready(struct platform_device *pdev)
+{
+ struct sde_hdmi *display = platform_get_drvdata(pdev);
+
+ if (!display) {
+ SDE_ERROR("invalid param(s), display %pK\n", display);
+ return;
+ }
+
+ mutex_lock(&display->display_lock);
+ if (!display->codec_ready) {
+ display->codec_ready = true;
+
+ if (display->client_notify_pending)
+ sde_hdmi_notify_clients(display, display->connected);
+ }
+ mutex_unlock(&display->display_lock);
+}
+
static int _sde_hdmi_ext_disp_init(struct sde_hdmi *display)
{
int rc = 0;
@@ -1073,6 +1090,8 @@ static int _sde_hdmi_ext_disp_init(struct sde_hdmi *display)
_sde_hdmi_get_audio_edid_blk;
display->ext_audio_data.codec_ops.cable_status =
_sde_hdmi_get_cable_status;
+ display->ext_audio_data.codec_ops.codec_ready =
+ _sde_hdmi_audio_codec_ready;
if (!display->pdev->dev.of_node) {
SDE_ERROR("[%s]cannot find sde_hdmi of_node\n", display->name);
@@ -1101,17 +1120,14 @@ static int _sde_hdmi_ext_disp_init(struct sde_hdmi *display)
return rc;
}
-void sde_hdmi_notify_clients(struct drm_connector *connector,
- bool connected)
+void sde_hdmi_notify_clients(struct sde_hdmi *display, bool connected)
{
- struct sde_connector *c_conn = to_sde_connector(connector);
- struct sde_hdmi *display = (struct sde_hdmi *)c_conn->display;
int state = connected ?
EXT_DISPLAY_CABLE_CONNECT : EXT_DISPLAY_CABLE_DISCONNECT;
if (display && display->ext_audio_data.intf_ops.hpd) {
struct hdmi *hdmi = display->ctrl.ctrl;
- u32 flags = MSM_EXT_DISP_HPD_VIDEO;
+ u32 flags = MSM_EXT_DISP_HPD_ASYNC_VIDEO;
if (hdmi->hdmi_mode)
flags |= MSM_EXT_DISP_HPD_AUDIO;
@@ -1121,21 +1137,6 @@ void sde_hdmi_notify_clients(struct drm_connector *connector,
}
}
-void sde_hdmi_ack_state(struct drm_connector *connector,
- enum drm_connector_status status)
-{
- struct sde_connector *c_conn = to_sde_connector(connector);
- struct sde_hdmi *display = (struct sde_hdmi *)c_conn->display;
-
- if (display) {
- struct hdmi *hdmi = display->ctrl.ctrl;
-
- if (hdmi->hdmi_mode && display->ext_audio_data.intf_ops.notify)
- display->ext_audio_data.intf_ops.notify(
- display->ext_pdev, status);
- }
-}
-
void sde_hdmi_set_mode(struct hdmi *hdmi, bool power_on)
{
uint32_t ctrl = 0;
@@ -1427,8 +1428,8 @@ int sde_hdmi_get_info(struct msm_display_info *info,
MSM_DISPLAY_CAP_EDID | MSM_DISPLAY_CAP_VID_MODE;
}
info->is_connected = hdmi_display->connected;
- info->max_width = 1920;
- info->max_height = 1080;
+ info->max_width = 4096;
+ info->max_height = 2160;
info->compression = MSM_DISPLAY_COMPRESS_NONE;
mutex_unlock(&hdmi_display->display_lock);
diff --git a/drivers/gpu/drm/msm/hdmi-staging/sde_hdmi.h b/drivers/gpu/drm/msm/hdmi-staging/sde_hdmi.h
index ecdace10d0c3..ffa9a27e7dfe 100644
--- a/drivers/gpu/drm/msm/hdmi-staging/sde_hdmi.h
+++ b/drivers/gpu/drm/msm/hdmi-staging/sde_hdmi.h
@@ -84,6 +84,8 @@ struct sde_hdmi_ctrl {
* @connected: If HDMI display is connected.
* @is_tpg_enabled: TPG state.
* @hpd_work: HPD work structure.
+ * @codec_ready: If audio codec is ready.
+ * @client_notify_pending: If there is client notification pending.
* @root: Debug fs root entry.
*/
struct sde_hdmi {
@@ -109,6 +111,8 @@ struct sde_hdmi {
bool is_tpg_enabled;
struct work_struct hpd_work;
+ bool codec_ready;
+ bool client_notify_pending;
/* DEBUG FS */
struct dentry *root;
@@ -379,13 +383,12 @@ int sde_hdmi_config_avmute(struct hdmi *hdmi, bool set);
/**
* sde_hdmi_notify_clients() - notify hdmi clients of the connection status.
- * @connector: Handle to the drm_connector.
+ * @display: Handle to sde_hdmi.
* @connected: connection status.
*
* Return: void.
*/
-void sde_hdmi_notify_clients(struct drm_connector *connector,
- bool connected);
+void sde_hdmi_notify_clients(struct sde_hdmi *display, bool connected);
/**
* sde_hdmi_ack_state() - acknowledge the connection status.
diff --git a/drivers/gpu/drm/msm/hdmi-staging/sde_hdmi_bridge.c b/drivers/gpu/drm/msm/hdmi-staging/sde_hdmi_bridge.c
index 6c82c3d4826d..34268aaedfc0 100644
--- a/drivers/gpu/drm/msm/hdmi-staging/sde_hdmi_bridge.c
+++ b/drivers/gpu/drm/msm/hdmi-staging/sde_hdmi_bridge.c
@@ -372,6 +372,8 @@ static void _sde_hdmi_bridge_pre_enable(struct drm_bridge *bridge)
struct sde_hdmi_bridge *sde_hdmi_bridge = to_hdmi_bridge(bridge);
struct hdmi *hdmi = sde_hdmi_bridge->hdmi;
struct hdmi_phy *phy = hdmi->phy;
+ struct sde_connector *c_conn = to_sde_connector(hdmi->connector);
+ struct sde_hdmi *display = (struct sde_hdmi *)c_conn->display;
DRM_DEBUG("power up");
@@ -388,41 +390,20 @@ static void _sde_hdmi_bridge_pre_enable(struct drm_bridge *bridge)
if (hdmi->hdcp_ctrl && hdmi->is_hdcp_supported)
hdmi_hdcp_ctrl_on(hdmi->hdcp_ctrl);
- sde_hdmi_ack_state(hdmi->connector, EXT_DISPLAY_CABLE_CONNECT);
-}
-
-static void sde_hdmi_force_update_audio(struct drm_connector *connector,
- enum drm_connector_status status)
-{
- struct sde_connector *c_conn = to_sde_connector(connector);
- struct sde_hdmi *display = (struct sde_hdmi *)c_conn->display;
-
- if (display && display->non_pluggable) {
- display->ext_audio_data.intf_ops.hpd(display->ext_pdev,
- display->ext_audio_data.type,
- status,
- MSM_EXT_DISP_HPD_AUDIO);
- }
+ mutex_lock(&display->display_lock);
+ if (display->codec_ready)
+ sde_hdmi_notify_clients(display, display->connected);
+ else
+ display->client_notify_pending = true;
+ mutex_unlock(&display->display_lock);
}
static void _sde_hdmi_bridge_enable(struct drm_bridge *bridge)
{
- struct sde_hdmi_bridge *sde_hdmi_bridge = to_hdmi_bridge(bridge);
- struct hdmi *hdmi = sde_hdmi_bridge->hdmi;
-
- /* force update audio ops when there's no HPD event */
- sde_hdmi_force_update_audio(hdmi->connector,
- EXT_DISPLAY_CABLE_CONNECT);
}
static void _sde_hdmi_bridge_disable(struct drm_bridge *bridge)
{
- struct sde_hdmi_bridge *sde_hdmi_bridge = to_hdmi_bridge(bridge);
- struct hdmi *hdmi = sde_hdmi_bridge->hdmi;
-
- /* force update audio ops when there's no HPD event */
- sde_hdmi_force_update_audio(hdmi->connector,
- EXT_DISPLAY_CABLE_DISCONNECT);
}
static void _sde_hdmi_bridge_post_disable(struct drm_bridge *bridge)
@@ -430,6 +411,10 @@ static void _sde_hdmi_bridge_post_disable(struct drm_bridge *bridge)
struct sde_hdmi_bridge *sde_hdmi_bridge = to_hdmi_bridge(bridge);
struct hdmi *hdmi = sde_hdmi_bridge->hdmi;
struct hdmi_phy *phy = hdmi->phy;
+ struct sde_connector *c_conn = to_sde_connector(hdmi->connector);
+ struct sde_hdmi *display = (struct sde_hdmi *)c_conn->display;
+
+ sde_hdmi_notify_clients(display, display->connected);
if (hdmi->hdcp_ctrl && hdmi->is_hdcp_supported)
hdmi_hdcp_ctrl_off(hdmi->hdcp_ctrl);
@@ -446,8 +431,6 @@ static void _sde_hdmi_bridge_post_disable(struct drm_bridge *bridge)
_sde_hdmi_bridge_power_off(bridge);
hdmi->power_on = false;
}
-
- sde_hdmi_ack_state(hdmi->connector, EXT_DISPLAY_CABLE_DISCONNECT);
}
static void _sde_hdmi_bridge_set_avi_infoframe(struct hdmi *hdmi,
diff --git a/drivers/gpu/drm/msm/msm_drv.c b/drivers/gpu/drm/msm/msm_drv.c
index 7d378f7ebaa4..22addb797db3 100644
--- a/drivers/gpu/drm/msm/msm_drv.c
+++ b/drivers/gpu/drm/msm/msm_drv.c
@@ -1208,23 +1208,34 @@ static int msm_ioctl_gem_info(struct drm_device *dev, void *data,
if (args->flags & ~MSM_INFO_FLAGS)
return -EINVAL;
- if (!ctx || !ctx->aspace)
- return -EINVAL;
-
obj = drm_gem_object_lookup(dev, file, args->handle);
if (!obj)
return -ENOENT;
if (args->flags & MSM_INFO_IOVA) {
+ struct msm_gem_address_space *aspace = NULL;
+ struct msm_drm_private *priv = dev->dev_private;
+ struct msm_gem_object *msm_obj = to_msm_bo(obj);
uint64_t iova;
- ret = msm_gem_get_iova(obj, ctx->aspace, &iova);
+ if (msm_obj->flags & MSM_BO_SECURE && priv->gpu)
+ aspace = priv->gpu->secure_aspace;
+ else if (ctx)
+ aspace = ctx->aspace;
+
+ if (!aspace) {
+ ret = -EINVAL;
+ goto out;
+ }
+
+ ret = msm_gem_get_iova(obj, aspace, &iova);
if (!ret)
args->offset = iova;
} else {
args->offset = msm_gem_mmap_offset(obj);
}
+out:
drm_gem_object_unreference_unlocked(obj);
return ret;
diff --git a/drivers/gpu/drm/msm/msm_drv.h b/drivers/gpu/drm/msm/msm_drv.h
index bd75a1ba1f8b..94f429cb83a7 100644
--- a/drivers/gpu/drm/msm/msm_drv.h
+++ b/drivers/gpu/drm/msm/msm_drv.h
@@ -469,7 +469,7 @@ int msm_gem_new_handle(struct drm_device *dev, struct drm_file *file,
struct drm_gem_object *msm_gem_new(struct drm_device *dev,
uint32_t size, uint32_t flags);
struct drm_gem_object *msm_gem_import(struct drm_device *dev,
- uint32_t size, struct sg_table *sgt);
+ uint32_t size, struct sg_table *sgt, u32 flags);
void msm_gem_sync(struct drm_gem_object *obj, u32 op);
int msm_framebuffer_prepare(struct drm_framebuffer *fb,
diff --git a/drivers/gpu/drm/msm/msm_gem.c b/drivers/gpu/drm/msm/msm_gem.c
index d35d03c2935d..4674c5423cbd 100644
--- a/drivers/gpu/drm/msm/msm_gem.c
+++ b/drivers/gpu/drm/msm/msm_gem.c
@@ -18,12 +18,31 @@
#include <linux/spinlock.h>
#include <linux/shmem_fs.h>
#include <linux/dma-buf.h>
+#include <soc/qcom/secure_buffer.h>
#include "msm_drv.h"
#include "msm_gem.h"
#include "msm_gpu.h"
#include "msm_mmu.h"
+static int protect_pages(struct msm_gem_object *msm_obj)
+{
+ int perm = PERM_READ | PERM_WRITE;
+ int src = VMID_HLOS;
+ int dst = VMID_CP_PIXEL;
+
+ return hyp_assign_table(msm_obj->sgt, &src, 1, &dst, &perm, 1);
+}
+
+static int unprotect_pages(struct msm_gem_object *msm_obj)
+{
+ int perm = PERM_READ | PERM_WRITE | PERM_EXEC;
+ int src = VMID_CP_PIXEL;
+ int dst = VMID_HLOS;
+
+ return hyp_assign_table(msm_obj->sgt, &src, 1, &dst, &perm, 1);
+}
+
static void *get_dmabuf_ptr(struct drm_gem_object *obj)
{
return (obj && obj->import_attach) ? obj->import_attach->dmabuf : NULL;
@@ -109,6 +128,20 @@ static struct page **get_pages(struct drm_gem_object *obj)
if (msm_obj->flags & (MSM_BO_WC|MSM_BO_UNCACHED))
dma_sync_sg_for_device(dev->dev, msm_obj->sgt->sgl,
msm_obj->sgt->nents, DMA_BIDIRECTIONAL);
+
+ /* Secure the pages if we need to */
+ if (use_pages(obj) && msm_obj->flags & MSM_BO_SECURE) {
+ int ret = protect_pages(msm_obj);
+
+ if (ret)
+ return ERR_PTR(ret);
+
+ /*
+ * Set a flag to indicate the pages are locked by us and
+ * need to be unlocked when the pages get freed
+ */
+ msm_obj->flags |= MSM_BO_LOCKED;
+ }
}
return msm_obj->pages;
@@ -119,12 +152,17 @@ static void put_pages(struct drm_gem_object *obj)
struct msm_gem_object *msm_obj = to_msm_bo(obj);
if (msm_obj->pages) {
+ if (msm_obj->flags & MSM_BO_LOCKED) {
+ unprotect_pages(msm_obj);
+ msm_obj->flags &= ~MSM_BO_LOCKED;
+ }
+
sg_free_table(msm_obj->sgt);
kfree(msm_obj->sgt);
- if (use_pages(obj))
+ if (use_pages(obj)) {
drm_gem_put_pages(obj, msm_obj->pages, true, false);
- else {
+ } else {
drm_mm_remove_node(msm_obj->vram_node);
drm_free_large(msm_obj->pages);
}
@@ -153,6 +191,12 @@ int msm_gem_mmap_obj(struct drm_gem_object *obj,
{
struct msm_gem_object *msm_obj = to_msm_bo(obj);
+ /* We can't mmap secure objects */
+ if (msm_obj->flags & MSM_BO_SECURE) {
+ drm_gem_vm_close(vma);
+ return -EACCES;
+ }
+
vma->vm_flags &= ~VM_PFNMAP;
vma->vm_flags |= VM_MIXEDMAP;
@@ -756,7 +800,7 @@ fail:
}
struct drm_gem_object *msm_gem_import(struct drm_device *dev,
- uint32_t size, struct sg_table *sgt)
+ uint32_t size, struct sg_table *sgt, u32 flags)
{
struct msm_gem_object *msm_obj;
struct drm_gem_object *obj;
@@ -789,6 +833,9 @@ struct drm_gem_object *msm_gem_import(struct drm_device *dev,
goto fail;
}
+ /* OR the passed in flags */
+ msm_obj->flags |= flags;
+
ret = drm_prime_sg_to_page_addr_arrays(sgt, msm_obj->pages, NULL, npages);
if (ret)
goto fail;
diff --git a/drivers/gpu/drm/msm/msm_gem.h b/drivers/gpu/drm/msm/msm_gem.h
index 0b19d11bc666..d5204221d902 100644
--- a/drivers/gpu/drm/msm/msm_gem.h
+++ b/drivers/gpu/drm/msm/msm_gem.h
@@ -24,6 +24,7 @@
/* Additional internal-use only BO flags: */
#define MSM_BO_STOLEN 0x10000000 /* try to use stolen/splash memory */
+#define MSM_BO_LOCKED 0x20000000 /* Pages have been securely locked */
struct msm_gem_address_space {
const char *name;
@@ -118,6 +119,7 @@ struct msm_gem_submit {
bool valid;
uint64_t profile_buf_iova;
void *profile_buf_vaddr;
+ bool secure;
unsigned int nr_cmds;
unsigned int nr_bos;
struct {
diff --git a/drivers/gpu/drm/msm/msm_gem_prime.c b/drivers/gpu/drm/msm/msm_gem_prime.c
index 121975b07cd4..678018804f3a 100644
--- a/drivers/gpu/drm/msm/msm_gem_prime.c
+++ b/drivers/gpu/drm/msm/msm_gem_prime.c
@@ -19,6 +19,7 @@
#include "msm_gem.h"
#include <linux/dma-buf.h>
+#include <linux/ion.h>
struct sg_table *msm_gem_prime_get_sg_table(struct drm_gem_object *obj)
{
@@ -55,7 +56,16 @@ int msm_gem_prime_mmap(struct drm_gem_object *obj, struct vm_area_struct *vma)
struct drm_gem_object *msm_gem_prime_import_sg_table(struct drm_device *dev,
struct dma_buf_attachment *attach, struct sg_table *sg)
{
- return msm_gem_import(dev, attach->dmabuf->size, sg);
+ u32 flags = 0;
+
+ /*
+ * Check to see if this is a secure buffer by way of Ion and set the
+ * appropriate flag if so.
+ */
+ if (ion_dma_buf_is_secure(attach->dmabuf))
+ flags |= MSM_BO_SECURE;
+
+ return msm_gem_import(dev, attach->dmabuf->size, sg, flags);
}
int msm_gem_prime_pin(struct drm_gem_object *obj)
diff --git a/drivers/gpu/drm/msm/msm_gem_submit.c b/drivers/gpu/drm/msm/msm_gem_submit.c
index 8e0f15c416fd..ea7b4441fe99 100644
--- a/drivers/gpu/drm/msm/msm_gem_submit.c
+++ b/drivers/gpu/drm/msm/msm_gem_submit.c
@@ -50,6 +50,7 @@ static struct msm_gem_submit *submit_create(struct drm_device *dev,
submit->profile_buf_vaddr = NULL;
submit->profile_buf_iova = 0;
+ submit->secure = false;
INIT_LIST_HEAD(&submit->bo_list);
ww_acquire_init(&submit->ticket, &reservation_ww_class);
@@ -66,7 +67,8 @@ copy_from_user_inatomic(void *to, const void __user *from, unsigned long n)
return -EFAULT;
}
-static int submit_lookup_objects(struct msm_gem_submit *submit,
+static int submit_lookup_objects(struct msm_gpu *gpu,
+ struct msm_gem_submit *submit,
struct drm_msm_gem_submit *args, struct drm_file *file)
{
unsigned i;
@@ -119,6 +121,20 @@ static int submit_lookup_objects(struct msm_gem_submit *submit,
msm_obj = to_msm_bo(obj);
+ /*
+ * If the buffer is marked as secure make sure that we can
+ * handle secure buffers and then mark the submission as secure
+ */
+ if (msm_obj->flags & MSM_BO_SECURE) {
+ if (!gpu->secure_aspace) {
+ DRM_ERROR("Cannot handle secure buffers\n");
+ ret = -EINVAL;
+ goto out_unlock;
+ }
+
+ submit->secure = true;
+ }
+
if (!list_empty(&msm_obj->submit_entry)) {
DRM_ERROR("handle %u at index %u already on submit list\n",
submit_bo.handle, i);
@@ -143,12 +159,17 @@ out:
return ret;
}
-static void submit_unlock_unpin_bo(struct msm_gem_submit *submit, int i)
+static void submit_unlock_unpin_bo(struct msm_gpu *gpu,
+ struct msm_gem_submit *submit, int i)
{
struct msm_gem_object *msm_obj = submit->bos[i].obj;
+ struct msm_gem_address_space *aspace;
+
+ aspace = (msm_obj->flags & MSM_BO_SECURE) ?
+ gpu->secure_aspace : submit->aspace;
if (submit->bos[i].flags & BO_PINNED)
- msm_gem_put_iova(&msm_obj->base, submit->aspace);
+ msm_gem_put_iova(&msm_obj->base, aspace);
if (submit->bos[i].flags & BO_LOCKED)
ww_mutex_unlock(&msm_obj->resv->lock);
@@ -160,7 +181,8 @@ static void submit_unlock_unpin_bo(struct msm_gem_submit *submit, int i)
}
/* This is where we make sure all the bo's are reserved and pin'd: */
-static int submit_validate_objects(struct msm_gem_submit *submit)
+static int submit_validate_objects(struct msm_gpu *gpu,
+ struct msm_gem_submit *submit)
{
int contended, slow_locked = -1, i, ret = 0;
@@ -169,8 +191,12 @@ retry:
for (i = 0; i < submit->nr_bos; i++) {
struct msm_gem_object *msm_obj = submit->bos[i].obj;
+ struct msm_gem_address_space *aspace;
uint64_t iova;
+ aspace = (msm_obj->flags & MSM_BO_SECURE) ?
+ gpu->secure_aspace : submit->aspace;
+
if (slow_locked == i)
slow_locked = -1;
@@ -186,8 +212,7 @@ retry:
/* if locking succeeded, pin bo: */
- ret = msm_gem_get_iova_locked(&msm_obj->base,
- submit->aspace, &iova);
+ ret = msm_gem_get_iova_locked(&msm_obj->base, aspace, &iova);
/* this would break the logic in the fail path.. there is no
* reason for this to happen, but just to be on the safe side
@@ -215,10 +240,10 @@ retry:
fail:
for (; i >= 0; i--)
- submit_unlock_unpin_bo(submit, i);
+ submit_unlock_unpin_bo(gpu, submit, i);
if (slow_locked > 0)
- submit_unlock_unpin_bo(submit, slow_locked);
+ submit_unlock_unpin_bo(gpu, submit, slow_locked);
if (ret == -EDEADLK) {
struct msm_gem_object *msm_obj = submit->bos[contended].obj;
@@ -267,6 +292,11 @@ static int submit_reloc(struct msm_gem_submit *submit, struct msm_gem_object *ob
return -EINVAL;
}
+ if (obj->flags & MSM_BO_SECURE) {
+ DRM_ERROR("cannot do relocs on a secure buffer\n");
+ return -EINVAL;
+ }
+
/* For now, just map the entire thing. Eventually we probably
* to do it page-by-page, w/ kmap() if not vmap()d..
*/
@@ -327,13 +357,14 @@ static int submit_reloc(struct msm_gem_submit *submit, struct msm_gem_object *ob
return 0;
}
-static void submit_cleanup(struct msm_gem_submit *submit, bool fail)
+static void submit_cleanup(struct msm_gpu *gpu, struct msm_gem_submit *submit,
+ bool fail)
{
unsigned i;
for (i = 0; i < submit->nr_bos; i++) {
struct msm_gem_object *msm_obj = submit->bos[i].obj;
- submit_unlock_unpin_bo(submit, i);
+ submit_unlock_unpin_bo(gpu, submit, i);
list_del_init(&msm_obj->submit_entry);
drm_gem_object_unreference(&msm_obj->base);
}
@@ -373,11 +404,11 @@ int msm_ioctl_gem_submit(struct drm_device *dev, void *data,
goto out;
}
- ret = submit_lookup_objects(submit, args, file);
+ ret = submit_lookup_objects(gpu, submit, args, file);
if (ret)
goto out;
- ret = submit_validate_objects(submit);
+ ret = submit_validate_objects(gpu, submit);
if (ret)
goto out;
@@ -460,7 +491,7 @@ int msm_ioctl_gem_submit(struct drm_device *dev, void *data,
out:
if (submit)
- submit_cleanup(submit, !!ret);
+ submit_cleanup(gpu, submit, !!ret);
mutex_unlock(&dev->struct_mutex);
return ret;
}
diff --git a/drivers/gpu/drm/msm/msm_gpu.c b/drivers/gpu/drm/msm/msm_gpu.c
index 2f01db8b08c3..47fa02e8d1fc 100644
--- a/drivers/gpu/drm/msm/msm_gpu.c
+++ b/drivers/gpu/drm/msm/msm_gpu.c
@@ -572,12 +572,16 @@ int msm_gpu_submit(struct msm_gpu *gpu, struct msm_gem_submit *submit)
WARN_ON(is_active(msm_obj) && (msm_obj->gpu != gpu));
if (!is_active(msm_obj)) {
+ struct msm_gem_address_space *aspace;
uint64_t iova;
+ aspace = (msm_obj->flags & MSM_BO_SECURE) ?
+ gpu->secure_aspace : submit->aspace;
+
/* ring takes a reference to the bo and iova: */
drm_gem_object_reference(&msm_obj->base);
msm_gem_get_iova_locked(&msm_obj->base,
- submit->aspace, &iova);
+ aspace, &iova);
}
if (submit->bos[i].flags & MSM_SUBMIT_BO_READ)
@@ -757,11 +761,49 @@ static int get_clocks(struct platform_device *pdev, struct msm_gpu *gpu)
return 0;
}
+static struct msm_gem_address_space *
+msm_gpu_create_address_space(struct msm_gpu *gpu, struct device *dev,
+ int type, u64 start, u64 end, const char *name)
+{
+ struct msm_gem_address_space *aspace;
+ struct iommu_domain *iommu;
+
+ /*
+ * If start == end then assume we don't want an address space; this is
+ * mainly for targets to opt out of secure
+ */
+ if (start == end)
+ return NULL;
+
+ iommu = iommu_domain_alloc(&platform_bus_type);
+ if (!iommu) {
+ dev_info(gpu->dev->dev,
+ "%s: no IOMMU, fallback to VRAM carveout!\n",
+ gpu->name);
+ return NULL;
+ }
+
+ iommu->geometry.aperture_start = start;
+ iommu->geometry.aperture_end = end;
+
+ dev_info(gpu->dev->dev, "%s: using IOMMU '%s'\n", gpu->name, name);
+
+ aspace = msm_gem_address_space_create(dev, iommu, type, name);
+ if (IS_ERR(aspace)) {
+ dev_err(gpu->dev->dev, "%s: failed to init IOMMU '%s': %ld\n",
+ gpu->name, name, PTR_ERR(aspace));
+
+ iommu_domain_free(iommu);
+ aspace = NULL;
+ }
+
+ return aspace;
+}
+
int msm_gpu_init(struct drm_device *drm, struct platform_device *pdev,
struct msm_gpu *gpu, const struct msm_gpu_funcs *funcs,
const char *name, struct msm_gpu_config *config)
{
- struct iommu_domain *iommu;
int i, ret, nr_rings;
if (WARN_ON(gpu->num_perfcntrs > ARRAY_SIZE(gpu->last_cntrs)))
@@ -831,30 +873,13 @@ int msm_gpu_init(struct drm_device *drm, struct platform_device *pdev,
if (IS_ERR(gpu->gpu_cx))
gpu->gpu_cx = NULL;
- /* Setup IOMMU.. eventually we will (I think) do this once per context
- * and have separate page tables per context. For now, to keep things
- * simple and to get something working, just use a single address space:
- */
- iommu = iommu_domain_alloc(&platform_bus_type);
- if (iommu) {
- /* TODO 32b vs 64b address space.. */
- iommu->geometry.aperture_start = config->va_start;
- iommu->geometry.aperture_end = config->va_end;
-
- dev_info(drm->dev, "%s: using IOMMU\n", name);
- gpu->aspace = msm_gem_address_space_create(&pdev->dev,
- iommu, MSM_IOMMU_DOMAIN_USER, "gpu");
- if (IS_ERR(gpu->aspace)) {
- ret = PTR_ERR(gpu->aspace);
- dev_err(drm->dev, "failed to init iommu: %d\n", ret);
- gpu->aspace = NULL;
- iommu_domain_free(iommu);
- goto fail;
- }
+ gpu->aspace = msm_gpu_create_address_space(gpu, &pdev->dev,
+ MSM_IOMMU_DOMAIN_USER, config->va_start, config->va_end,
+ "gpu");
- } else {
- dev_info(drm->dev, "%s: no IOMMU, fallback to VRAM carveout!\n", name);
- }
+ gpu->secure_aspace = msm_gpu_create_address_space(gpu, &pdev->dev,
+ MSM_IOMMU_DOMAIN_SECURE, config->secure_va_start,
+ config->secure_va_end, "gpu_secure");
nr_rings = config->nr_rings;
diff --git a/drivers/gpu/drm/msm/msm_gpu.h b/drivers/gpu/drm/msm/msm_gpu.h
index 29e2e59b580b..d273ea30151e 100644
--- a/drivers/gpu/drm/msm/msm_gpu.h
+++ b/drivers/gpu/drm/msm/msm_gpu.h
@@ -38,6 +38,8 @@ struct msm_gpu_config {
int nr_rings;
uint64_t va_start;
uint64_t va_end;
+ uint64_t secure_va_start;
+ uint64_t secure_va_end;
};
/* So far, with hardware that I've seen to date, we can have:
@@ -114,6 +116,7 @@ struct msm_gpu {
int irq;
struct msm_gem_address_space *aspace;
+ struct msm_gem_address_space *secure_aspace;
/* Power Control: */
struct regulator *gpu_reg, *gpu_cx;
diff --git a/drivers/gpu/drm/msm/sde/sde_crtc.c b/drivers/gpu/drm/msm/sde/sde_crtc.c
index 41322045ced3..adfe9e54e6f4 100644
--- a/drivers/gpu/drm/msm/sde/sde_crtc.c
+++ b/drivers/gpu/drm/msm/sde/sde_crtc.c
@@ -1134,12 +1134,12 @@ static int sde_crtc_atomic_check(struct drm_crtc *crtc,
/* get plane state for all drm planes associated with crtc state */
drm_atomic_crtc_state_for_each_plane(plane, state) {
- pstate = drm_atomic_get_plane_state(state->state, plane);
+ pstate = drm_atomic_get_existing_plane_state(
+ state->state, plane);
if (IS_ERR_OR_NULL(pstate)) {
- rc = PTR_ERR(pstate);
- SDE_ERROR("%s: failed to get plane%d state, %d\n",
+ SDE_DEBUG("%s: failed to get plane%d state, %d\n",
sde_crtc->name, plane->base.id, rc);
- goto end;
+ continue;
}
if (cnt >= ARRAY_SIZE(pstates))
continue;
diff --git a/drivers/gpu/drm/msm/sde/sde_rm.c b/drivers/gpu/drm/msm/sde/sde_rm.c
index 1d27b27d265c..fca0768e2734 100644
--- a/drivers/gpu/drm/msm/sde/sde_rm.c
+++ b/drivers/gpu/drm/msm/sde/sde_rm.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2016, The Linux Foundation. All rights reserved.
+ * Copyright (c) 2016-2017, The Linux Foundation. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 and
@@ -1074,12 +1074,6 @@ void _sde_rm_release_rsvp(
}
kfree(rsvp);
-
- (void) msm_property_set_property(
- sde_connector_get_propinfo(conn),
- sde_connector_get_property_values(conn->state),
- CONNECTOR_PROP_TOPOLOGY_NAME,
- SDE_RM_TOPOLOGY_UNKNOWN);
}
void sde_rm_release(struct sde_rm *rm, struct drm_encoder *enc)
@@ -1115,6 +1109,12 @@ void sde_rm_release(struct sde_rm *rm, struct drm_encoder *enc)
SDE_DEBUG("release rsvp[s%de%d]\n", rsvp->seq,
rsvp->enc_id);
_sde_rm_release_rsvp(rm, rsvp, conn);
+
+ (void) msm_property_set_property(
+ sde_connector_get_propinfo(conn),
+ sde_connector_get_property_values(conn->state),
+ CONNECTOR_PROP_TOPOLOGY_NAME,
+ SDE_RM_TOPOLOGY_UNKNOWN);
}
}
@@ -1132,8 +1132,12 @@ static int _sde_rm_commit_rsvp(
sde_connector_get_property_values(conn_state),
CONNECTOR_PROP_TOPOLOGY_NAME,
rsvp->topology);
- if (ret)
+ if (ret) {
+ SDE_ERROR("failed to set topology name property, ret %d\n",
+ ret);
_sde_rm_release_rsvp(rm, rsvp, conn_state->connector);
+ return ret;
+ }
/* Swap next rsvp to be the active */
for (type = 0; type < SDE_HW_BLK_MAX; type++) {
@@ -1226,6 +1230,12 @@ int sde_rm_reserve(
_sde_rm_release_rsvp(rm, rsvp_cur, conn_state->connector);
rsvp_cur = NULL;
_sde_rm_print_rsvps(rm, SDE_RM_STAGE_AFTER_CLEAR);
+ (void) msm_property_set_property(
+ sde_connector_get_propinfo(
+ conn_state->connector),
+ sde_connector_get_property_values(conn_state),
+ CONNECTOR_PROP_TOPOLOGY_NAME,
+ SDE_RM_TOPOLOGY_UNKNOWN);
}
/* Check the proposed reservation, store it in hw's "next" field */
diff --git a/drivers/input/misc/hbtp_input.c b/drivers/input/misc/hbtp_input.c
index 599605a3cf76..0362095d4c38 100644
--- a/drivers/input/misc/hbtp_input.c
+++ b/drivers/input/misc/hbtp_input.c
@@ -1452,8 +1452,10 @@ static int __init hbtp_init(void)
hbtp->sensor_data = kzalloc(sizeof(struct hbtp_sensor_data),
GFP_KERNEL);
- if (!hbtp->sensor_data)
+ if (!hbtp->sensor_data) {
+ error = -ENOMEM;
goto err_sensordata;
+ }
mutex_init(&hbtp->mutex);
mutex_init(&hbtp->sensormutex);
diff --git a/drivers/input/misc/vl53L0/stmvl53l0_module-cci.c b/drivers/input/misc/vl53L0/stmvl53l0_module-cci.c
index fecafe8db949..8520a74c9961 100644
--- a/drivers/input/misc/vl53L0/stmvl53l0_module-cci.c
+++ b/drivers/input/misc/vl53L0/stmvl53l0_module-cci.c
@@ -111,11 +111,11 @@ static int stmvl53l0_get_dt_data(struct device *dev, struct cci_data *data)
vl53l0_errmsg("failed %d\n", __LINE__);
return rc;
}
+ vl53l0_dbgmsg("vreg-name: %s min_volt: %d max_volt: %d",
+ vreg_cfg->cam_vreg->reg_name,
+ vreg_cfg->cam_vreg->min_voltage,
+ vreg_cfg->cam_vreg->max_voltage);
}
- vl53l0_dbgmsg("vreg-name: %s min_volt: %d max_volt: %d",
- vreg_cfg->cam_vreg->reg_name,
- vreg_cfg->cam_vreg->min_voltage,
- vreg_cfg->cam_vreg->max_voltage);
rc = msm_sensor_driver_get_gpio_data(&(data->gconf), of_node);
if ((rc < 0) || (data->gconf == NULL)) {
@@ -289,6 +289,11 @@ static int32_t stmvl53l0_platform_probe(struct platform_device *pdev)
if (vl53l0_data) {
vl53l0_data->client_object =
kzalloc(sizeof(struct cci_data), GFP_KERNEL);
+ if (!vl53l0_data->client_object) {
+ rc = -ENOMEM;
+ kfree(vl53l0_data);
+ return rc;
+ }
cci_object = (struct cci_data *)vl53l0_data->client_object;
}
cci_object->client =
@@ -380,6 +385,11 @@ int stmvl53l0_power_up_cci(void *cci_object, unsigned int *preset_flag)
vl53l0_dbgmsg("Enter");
/* need to init cci first */
+ if (!data) {
+ pr_err("%s:%d failed\n", __func__, __LINE__);
+ return -EINVAL;
+ }
+
ret = stmvl53l0_cci_init(data);
if (ret) {
vl53l0_errmsg("stmvl53l0_cci_init failed %d\n", __LINE__);
@@ -429,7 +439,7 @@ int stmvl53l0_power_up_cci(void *cci_object, unsigned int *preset_flag)
}
/* actual power up */
- if (data && data->device_type == MSM_CAMERA_PLATFORM_DEVICE) {
+ if (data->device_type == MSM_CAMERA_PLATFORM_DEVICE) {
ret = stmvl53l0_vreg_control(data, 1);
if (ret < 0) {
vl53l0_errmsg("stmvl53l0_vreg_control failed %d\n",
diff --git a/drivers/input/misc/vl53L0/stmvl53l0_module.c b/drivers/input/misc/vl53L0/stmvl53l0_module.c
index c46be43a03e5..27672d97448a 100644
--- a/drivers/input/misc/vl53L0/stmvl53l0_module.c
+++ b/drivers/input/misc/vl53L0/stmvl53l0_module.c
@@ -2115,10 +2115,10 @@ static int stmvl53l0_init_client(struct stmvl53l0_data *data)
VL53L0_Error Status = VL53L0_ERROR_NONE;
VL53L0_DeviceInfo_t DeviceInfo;
VL53L0_DEV vl53l0_dev = data;
- uint32_t refSpadCount;
- uint8_t isApertureSpads;
- uint8_t VhvSettings;
- uint8_t PhaseCal;
+ uint32_t refSpadCount = 0;
+ uint8_t isApertureSpads = 0;
+ uint8_t VhvSettings = 0;
+ uint8_t PhaseCal = 0;
vl53l0_dbgmsg("Enter\n");
@@ -2380,17 +2380,17 @@ static int stmvl53l0_config_use_case(struct stmvl53l0_data *data)
vl53l0_dev,
VL53L0_CHECKENABLE_SIGMA_FINAL_RANGE,
1);
- }
- if (Status == VL53L0_ERROR_NONE) {
- Status = papi_func_tbl->SetLimitCheckEnable(
- vl53l0_dev,
- VL53L0_CHECKENABLE_SIGNAL_RATE_FINAL_RANGE,
- 1);
- } else {
- vl53l0_errmsg(
- "SetLimitCheckEnable(SIGMA_FINAL_RANGE) failed with errcode = %d\n",
- Status);
+ if (Status == VL53L0_ERROR_NONE) {
+ Status = papi_func_tbl->SetLimitCheckEnable(
+ vl53l0_dev,
+ VL53L0_CHECKENABLE_SIGNAL_RATE_FINAL_RANGE,
+ 1);
+ } else {
+ vl53l0_errmsg(
+ "SetLimitCheckEnable(SIGMA_FINAL_RANGE) failed with errcode = %d\n",
+ Status);
+ }
}
diff --git a/drivers/input/serio/i8042-x86ia64io.h b/drivers/input/serio/i8042-x86ia64io.h
index 25eab453f2b2..e7b96f1ac2c5 100644
--- a/drivers/input/serio/i8042-x86ia64io.h
+++ b/drivers/input/serio/i8042-x86ia64io.h
@@ -685,6 +685,13 @@ static const struct dmi_system_id __initconst i8042_dmi_reset_table[] = {
DMI_MATCH(DMI_PRODUCT_NAME, "20046"),
},
},
+ {
+ /* Clevo P650RS, 650RP6, Sager NP8152-S, and others */
+ .matches = {
+ DMI_MATCH(DMI_SYS_VENDOR, "Notebook"),
+ DMI_MATCH(DMI_PRODUCT_NAME, "P65xRP"),
+ },
+ },
{ }
};
diff --git a/drivers/md/raid1.c b/drivers/md/raid1.c
index 9be39988bf06..d81be5e471d0 100644
--- a/drivers/md/raid1.c
+++ b/drivers/md/raid1.c
@@ -570,7 +570,7 @@ static int read_balance(struct r1conf *conf, struct r1bio *r1_bio, int *max_sect
if (best_dist_disk < 0) {
if (is_badblock(rdev, this_sector, sectors,
&first_bad, &bad_sectors)) {
- if (first_bad < this_sector)
+ if (first_bad <= this_sector)
/* Cannot use this */
continue;
best_good_sectors = first_bad - this_sector;
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 b283f6277b87..f37e183e35de 100644
--- a/drivers/media/platform/msm/camera_v2/isp/msm_isp.h
+++ b/drivers/media/platform/msm/camera_v2/isp/msm_isp.h
@@ -469,6 +469,7 @@ struct msm_vfe_axi_stream {
*/
uint32_t vfe_mask;
uint32_t composite_irq[MSM_ISP_COMP_IRQ_MAX];
+ int lpm_mode;
};
struct msm_vfe_axi_composite_info {
@@ -738,6 +739,7 @@ struct msm_vfe_common_dev_data {
struct msm_vfe_axi_stream streams[VFE_AXI_SRC_MAX * MAX_VFE];
struct msm_vfe_stats_stream stats_streams[MSM_ISP_STATS_MAX * MAX_VFE];
struct mutex vfe_common_mutex;
+ uint8_t pd_buf_idx;
/* Irq debug Info */
struct msm_vfe_irq_dump vfe_irq_dump;
struct msm_vfe_tasklet tasklets[MAX_VFE + 1];
@@ -836,8 +838,6 @@ struct vfe_device {
uint32_t bus_err_ign_mask;
uint32_t recovery_irq0_mask;
uint32_t recovery_irq1_mask;
- /* Store the buf_idx for pd stats RDI stream */
- uint8_t pd_buf_idx;
/* total bandwidth per vfe */
uint64_t total_bandwidth;
};
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 a66ca7e93537..b80ef1dc900b 100644
--- a/drivers/media/platform/msm/camera_v2/isp/msm_isp47.c
+++ b/drivers/media/platform/msm/camera_v2/isp/msm_isp47.c
@@ -1859,10 +1859,10 @@ void msm_vfe47_cfg_axi_ub_equal_default(
axi_data->free_wm[i])
break;
- rdi_ub_offset = ((SRC_TO_INTF(
+ rdi_ub_offset = (SRC_TO_INTF(
HANDLE_TO_IDX(axi_data->free_wm[i])) -
- VFE_RAW_0 * 2) + plane) *
- axi_data->hw_info->min_wm_ub;
+ VFE_RAW_0) *
+ axi_data->hw_info->min_wm_ub * 2;
wm_ub_size = axi_data->hw_info->min_wm_ub * 2;
msm_camera_io_w(rdi_ub_offset << 16 | (wm_ub_size - 1),
vfe_dev->vfe_base +
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 63e46125c292..0c0a9f997fa0 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
@@ -27,6 +27,9 @@ static void __msm_isp_axi_stream_update(
struct msm_vfe_axi_stream *stream_info,
struct msm_isp_timestamp *ts);
+static int msm_isp_update_stream_bandwidth(
+ struct msm_vfe_axi_stream *stream_info, int enable);
+
#define DUAL_VFE_AND_VFE1(s, v) ((s->stream_src < RDI_INTF_0) && \
v->is_split && vfe_dev->pdev->id == ISP_VFE1)
@@ -995,6 +998,7 @@ static void msm_isp_update_pd_stats_idx(struct vfe_device *vfe_dev,
uint32_t pingpong_status = 0, pingpong_bit = 0;
struct msm_isp_buffer *done_buf = NULL;
int vfe_idx = -1;
+ unsigned long flags;
if (frame_src < VFE_RAW_0 || frame_src > VFE_RAW_2)
return;
@@ -1012,10 +1016,14 @@ static void msm_isp_update_pd_stats_idx(struct vfe_device *vfe_dev,
pingpong_bit = ((pingpong_status >>
pd_stream_info->wm[vfe_idx][0]) & 0x1);
done_buf = pd_stream_info->buf[pingpong_bit];
+ spin_lock_irqsave(&vfe_dev->common_data->
+ common_dev_data_lock, flags);
if (done_buf)
- vfe_dev->pd_buf_idx = done_buf->buf_idx;
+ vfe_dev->common_data->pd_buf_idx = done_buf->buf_idx;
else
- vfe_dev->pd_buf_idx = 0xF;
+ vfe_dev->common_data->pd_buf_idx = 0xF;
+ spin_unlock_irqrestore(&vfe_dev->common_data->
+ common_dev_data_lock, flags);
}
}
@@ -2426,46 +2434,42 @@ static void msm_isp_update_intf_stream_cnt(
/*Factor in Q2 format*/
#define ISP_DEFAULT_FORMAT_FACTOR 6
#define ISP_BUS_UTILIZATION_FACTOR 6
-static int msm_isp_update_stream_bandwidth(struct vfe_device *vfe_dev)
+static int msm_isp_update_stream_bandwidth(
+ struct msm_vfe_axi_stream *stream_info, int enable)
{
int i, rc = 0;
- struct msm_vfe_axi_stream *stream_info;
- uint64_t total_pix_bandwidth = 0, total_rdi_bandwidth = 0;
- uint32_t num_pix_streams = 0;
+ uint64_t total_bandwidth = 0;
int vfe_idx;
+ struct vfe_device *vfe_dev;
- for (i = 0; i < VFE_AXI_SRC_MAX; i++) {
- stream_info = msm_isp_get_stream_common_data(vfe_dev, i);
- if (stream_info->state == ACTIVE ||
- stream_info->state == START_PENDING) {
- vfe_idx = msm_isp_get_vfe_idx_for_stream(vfe_dev,
- stream_info);
- if (stream_info->stream_src < RDI_INTF_0) {
- total_pix_bandwidth +=
+ for (i = 0; i < stream_info->num_isp; i++) {
+ vfe_dev = stream_info->vfe_dev[i];
+ vfe_idx = msm_isp_get_vfe_idx_for_stream(vfe_dev,
+ stream_info);
+ if (enable) {
+ total_bandwidth =
+ vfe_dev->total_bandwidth +
stream_info->bandwidth[vfe_idx];
- num_pix_streams++;
- } else {
- total_rdi_bandwidth +=
+ } else {
+ total_bandwidth = vfe_dev->total_bandwidth -
stream_info->bandwidth[vfe_idx];
- }
}
- }
- vfe_dev->total_bandwidth = total_pix_bandwidth + total_rdi_bandwidth;
- rc = msm_isp_update_bandwidth(ISP_VFE0 + vfe_dev->pdev->id,
- (vfe_dev->total_bandwidth + vfe_dev->hw_info->min_ab),
- (vfe_dev->total_bandwidth + vfe_dev->hw_info->min_ib));
-
- if (rc < 0)
- pr_err("%s: update failed\n", __func__);
+ vfe_dev->total_bandwidth = total_bandwidth;
+ rc = msm_isp_update_bandwidth(ISP_VFE0 + vfe_dev->pdev->id,
+ (total_bandwidth + vfe_dev->hw_info->min_ab),
+ (total_bandwidth + vfe_dev->hw_info->min_ib));
+ if (rc < 0)
+ pr_err("%s: update failed rc %d stream src %d vfe dev %d\n",
+ __func__, rc, stream_info->stream_src,
+ vfe_dev->pdev->id);
+ }
return rc;
}
int msm_isp_ab_ib_update_lpm_mode(struct vfe_device *vfe_dev, void *arg)
{
int i, rc = 0;
- uint64_t total_bandwidth = 0;
- int vfe_idx;
uint32_t intf;
unsigned long flags;
struct msm_vfe_axi_stream *stream_info;
@@ -2489,21 +2493,15 @@ int msm_isp_ab_ib_update_lpm_mode(struct vfe_device *vfe_dev, void *arg)
intf = SRC_TO_INTF(stream_info->stream_src);
vfe_dev->axi_data.src_info[intf].lpm =
ab_ib_vote->lpm_mode;
- if (stream_info->state == ACTIVE) {
- vfe_idx =
- msm_isp_get_vfe_idx_for_stream(vfe_dev,
- stream_info);
- total_bandwidth +=
- stream_info->bandwidth[
- vfe_idx];
- stream_info->state = PAUSED;
+ if (stream_info->lpm_mode) {
+ spin_unlock_irqrestore(&stream_info->lock,
+ flags);
+ continue;
}
+ stream_info->lpm_mode = ab_ib_vote->lpm_mode;
spin_unlock_irqrestore(&stream_info->lock, flags);
+ msm_isp_update_stream_bandwidth(stream_info, 0);
}
- vfe_dev->total_bandwidth -= total_bandwidth;
- rc = msm_isp_update_bandwidth(ISP_VFE0 + vfe_dev->pdev->id,
- (vfe_dev->total_bandwidth - vfe_dev->hw_info->min_ab),
- (vfe_dev->total_bandwidth - vfe_dev->hw_info->min_ib));
} else {
for (i = 0; i < ab_ib_vote->num_src; i++) {
stream_info =
@@ -2515,24 +2513,19 @@ int msm_isp_ab_ib_update_lpm_mode(struct vfe_device *vfe_dev, void *arg)
intf = SRC_TO_INTF(stream_info->stream_src);
vfe_dev->axi_data.src_info[intf].lpm =
ab_ib_vote->lpm_mode;
- if (stream_info->state == PAUSED) {
- vfe_idx =
- msm_isp_get_vfe_idx_for_stream(vfe_dev,
- stream_info);
- total_bandwidth +=
- stream_info->bandwidth[
- vfe_idx];
- stream_info->state = ACTIVE;
+ if (stream_info->lpm_mode == 0) {
+ spin_unlock_irqrestore(&stream_info->lock,
+ flags);
+ continue;
}
+ stream_info->lpm_mode = 0;
spin_unlock_irqrestore(&stream_info->lock, flags);
+ msm_isp_update_stream_bandwidth(stream_info, 1);
}
- vfe_dev->total_bandwidth += total_bandwidth;
- rc = msm_isp_update_bandwidth(ISP_VFE0 + vfe_dev->pdev->id,
- (vfe_dev->total_bandwidth + vfe_dev->hw_info->min_ab),
- (vfe_dev->total_bandwidth + vfe_dev->hw_info->min_ib));
}
return rc;
}
+
static int msm_isp_init_stream_ping_pong_reg(
struct msm_vfe_axi_stream *stream_info)
{
@@ -2941,7 +2934,7 @@ static void __msm_isp_stop_axi_streams(struct vfe_device *vfe_dev,
* be INACTIVE
*/
intf = SRC_TO_INTF(stream_info->stream_src);
- if ((!vfe_dev->axi_data.src_info[intf].lpm) ||
+ if (stream_info->lpm_mode == 0 &&
stream_info->state != PAUSED) {
while (stream_info->state != ACTIVE)
__msm_isp_axi_stream_update(stream_info,
@@ -2959,16 +2952,14 @@ static void __msm_isp_stop_axi_streams(struct vfe_device *vfe_dev,
vfe_dev->hw_info->vfe_ops.axi_ops.
clear_wm_irq_mask(vfe_dev, stream_info);
}
- if (stream_info->state == ACTIVE &&
- !vfe_dev->axi_data.src_info[intf].lpm) {
- init_completion(&stream_info->inactive_comp);
- stream_info->state = STOP_PENDING;
- } else if (vfe_dev->axi_data.src_info[intf].lpm ||
+ init_completion(&stream_info->inactive_comp);
+ stream_info->state = STOP_PENDING;
+ if (stream_info->lpm_mode ||
stream_info->state == PAUSED) {
/* don't wait for reg update */
- stream_info->state = STOP_PENDING;
- msm_isp_axi_stream_enable_cfg(stream_info);
- stream_info->state = INACTIVE;
+ while (stream_info->state != INACTIVE)
+ __msm_isp_axi_stream_update(stream_info,
+ &timestamp);
}
spin_unlock_irqrestore(&stream_info->lock, flags);
}
@@ -3029,6 +3020,8 @@ static void __msm_isp_stop_axi_streams(struct vfe_device *vfe_dev,
/* clear buffers that are dequeued */
for (i = 0; i < num_streams; i++) {
stream_info = streams[i];
+ if (stream_info->lpm_mode == 0)
+ msm_isp_update_stream_bandwidth(stream_info, 0);
for (bufq_id = 0; bufq_id < VFE_BUF_QUEUE_MAX; bufq_id++) {
bufq_handle = stream_info->bufq_handle[bufq_id];
if (!bufq_handle)
@@ -3044,12 +3037,6 @@ static void __msm_isp_stop_axi_streams(struct vfe_device *vfe_dev,
}
}
- for (k = 0; k < MAX_VFE; k++) {
- if (!update_vfes[k])
- continue;
- msm_isp_update_stream_bandwidth(update_vfes[k]);
- }
-
for (i = 0; i < num_streams; i++) {
stream_info = streams[i];
intf = SRC_TO_INTF(stream_info->stream_src);
@@ -3143,7 +3130,14 @@ static int msm_isp_start_axi_stream(struct vfe_device *vfe_dev_ioctl,
cfg_wm_irq_mask(vfe_dev, stream_info);
}
}
- intf = SRC_TO_INTF(stream_info->stream_src);
+ intf = SRC_TO_INTF(stream_info->stream_src);
+ stream_info->lpm_mode = vfe_dev_ioctl->
+ axi_data.src_info[intf].lpm;
+ if (stream_info->lpm_mode == 0) {
+ spin_unlock_irqrestore(&stream_info->lock, flags);
+ msm_isp_update_stream_bandwidth(stream_info, 1);
+ spin_lock_irqsave(&stream_info->lock, flags);
+ }
init_completion(&stream_info->active_comp);
stream_info->state = START_PENDING;
msm_isp_update_intf_stream_cnt(stream_info, 1);
@@ -3153,7 +3147,7 @@ static int msm_isp_start_axi_stream(struct vfe_device *vfe_dev_ioctl,
vfe_dev_ioctl->pdev->id);
if (src_state) {
src_mask |= (1 << SRC_TO_INTF(stream_info->stream_src));
- if (vfe_dev_ioctl->axi_data.src_info[intf].lpm) {
+ if (stream_info->lpm_mode) {
while (stream_info->state != ACTIVE)
__msm_isp_axi_stream_update(
stream_info, &timestamp);
@@ -3187,7 +3181,6 @@ static int msm_isp_start_axi_stream(struct vfe_device *vfe_dev_ioctl,
vfe_dev = update_vfes[i];
if (!vfe_dev)
continue;
- msm_isp_update_stream_bandwidth(vfe_dev);
vfe_dev->hw_info->vfe_ops.axi_ops.reload_wm(vfe_dev,
vfe_dev->vfe_base, wm_reload_mask[i]);
diff --git a/drivers/media/platform/msm/camera_v2/isp/msm_isp_stats_util.c b/drivers/media/platform/msm/camera_v2/isp/msm_isp_stats_util.c
index 73068a615380..ee695bf5dfd9 100644
--- a/drivers/media/platform/msm/camera_v2/isp/msm_isp_stats_util.c
+++ b/drivers/media/platform/msm/camera_v2/isp/msm_isp_stats_util.c
@@ -229,8 +229,12 @@ static int32_t msm_isp_stats_buf_divert(struct vfe_device *vfe_dev,
stats_event->pd_stats_idx = 0xF;
if (stream_info->stats_type == MSM_ISP_STATS_BF) {
- stats_event->pd_stats_idx = vfe_dev->pd_buf_idx;
- vfe_dev->pd_buf_idx = 0xF;
+ spin_lock_irqsave(&vfe_dev->common_data->
+ common_dev_data_lock, flags);
+ stats_event->pd_stats_idx = vfe_dev->common_data->pd_buf_idx;
+ vfe_dev->common_data->pd_buf_idx = 0xF;
+ spin_unlock_irqrestore(&vfe_dev->common_data->
+ common_dev_data_lock, flags);
}
if (comp_stats_type_mask == NULL) {
stats_event->stats_mask =
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 c8f5c051424e..2f8134bc3efb 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
@@ -2225,8 +2225,6 @@ static void msm_vfe_iommu_fault_handler(struct iommu_domain *domain,
mutex_lock(&vfe_dev->core_mutex);
if (vfe_dev->vfe_open_cnt > 0) {
- atomic_set(&vfe_dev->error_info.overflow_state,
- HALT_ENFORCED);
pr_err_ratelimited("%s: fault address is %lx\n",
__func__, iova);
msm_isp_process_iommu_page_fault(vfe_dev);
@@ -2316,7 +2314,7 @@ int msm_isp_open_node(struct v4l2_subdev *sd, struct v4l2_subdev_fh *fh)
/* Register page fault handler */
vfe_dev->buf_mgr->pagefault_debug_disable = 0;
/* initialize pd_buf_idx with an invalid index 0xF */
- vfe_dev->pd_buf_idx = 0xF;
+ vfe_dev->common_data->pd_buf_idx = 0xF;
cam_smmu_reg_client_page_fault_handler(
vfe_dev->buf_mgr->iommu_hdl,
@@ -2342,6 +2340,7 @@ int msm_isp_close_node(struct v4l2_subdev *sd, struct v4l2_subdev_fh *fh)
{
long rc = 0;
int wm;
+ int i;
struct vfe_device *vfe_dev = v4l2_get_subdevdata(sd);
ISP_DBG("%s E open_cnt %u\n", __func__, vfe_dev->vfe_open_cnt);
mutex_lock(&vfe_dev->realtime_mutex);
@@ -2391,6 +2390,8 @@ int msm_isp_close_node(struct v4l2_subdev *sd, struct v4l2_subdev_fh *fh)
msm_isp_end_avtimer();
vfe_dev->vt_enable = 0;
}
+ for (i = 0; i < VFE_SRC_MAX; i++)
+ vfe_dev->axi_data.src_info[i].lpm = 0;
MSM_ISP_DUAL_VFE_MUTEX_UNLOCK(vfe_dev);
vfe_dev->is_split = 0;
diff --git a/drivers/media/platform/msm/camera_v2/msm_buf_mgr/msm_generic_buf_mgr.c b/drivers/media/platform/msm/camera_v2/msm_buf_mgr/msm_generic_buf_mgr.c
index af6206f83048..f732f5180e81 100644
--- a/drivers/media/platform/msm/camera_v2/msm_buf_mgr/msm_generic_buf_mgr.c
+++ b/drivers/media/platform/msm/camera_v2/msm_buf_mgr/msm_generic_buf_mgr.c
@@ -540,20 +540,24 @@ static long msm_buf_mngr_subdev_ioctl(struct v4l2_subdev *sd,
k_ioctl = *ptr;
switch (k_ioctl.id) {
case MSM_CAMERA_BUF_MNGR_IOCTL_ID_GET_BUF_BY_IDX: {
- struct msm_buf_mngr_info buf_info, *tmp = NULL;
if (k_ioctl.size != sizeof(struct msm_buf_mngr_info))
return -EINVAL;
if (!k_ioctl.ioctl_ptr)
return -EINVAL;
-
- MSM_CAM_GET_IOCTL_ARG_PTR(&tmp, &k_ioctl.ioctl_ptr,
- sizeof(tmp));
- if (copy_from_user(&buf_info, tmp,
- sizeof(struct msm_buf_mngr_info))) {
- return -EFAULT;
+#ifndef CONFIG_COMPAT
+ {
+ struct msm_buf_mngr_info buf_info, *tmp = NULL;
+
+ MSM_CAM_GET_IOCTL_ARG_PTR(&tmp,
+ &k_ioctl.ioctl_ptr, sizeof(tmp));
+ if (copy_from_user(&buf_info, tmp,
+ sizeof(struct msm_buf_mngr_info))) {
+ return -EFAULT;
+ }
+ k_ioctl.ioctl_ptr = (uintptr_t)&buf_info;
}
- k_ioctl.ioctl_ptr = (uintptr_t)&buf_info;
+#endif
argp = &k_ioctl;
rc = msm_cam_buf_mgr_ops(cmd, argp);
}
@@ -674,6 +678,7 @@ static long msm_camera_buf_mgr_internal_compat_ioctl(struct file *file,
return -EINVAL;
}
k_ioctl.ioctl_ptr = (__u64)&buf_info;
+ k_ioctl.size = sizeof(struct msm_buf_mngr_info);
rc = msm_camera_buf_mgr_fetch_buf_info(&buf_info32, &buf_info,
(unsigned long)tmp_compat_ioctl_ptr);
if (rc < 0) {
diff --git a/drivers/media/platform/msm/camera_v2/sensor/eeprom/msm_eeprom.c b/drivers/media/platform/msm/camera_v2/sensor/eeprom/msm_eeprom.c
index e60947ecad21..31d2fdc24322 100644
--- a/drivers/media/platform/msm/camera_v2/sensor/eeprom/msm_eeprom.c
+++ b/drivers/media/platform/msm/camera_v2/sensor/eeprom/msm_eeprom.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2011-2016, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2011-2017, The Linux Foundation. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 and
@@ -1269,6 +1269,11 @@ static int msm_eeprom_spi_remove(struct spi_device *sdev)
return 0;
}
+ if (!e_ctrl->eboard_info) {
+ pr_err("%s: board info is NULL\n", __func__);
+ return 0;
+ }
+
msm_camera_i2c_dev_put_clk_info(
&e_ctrl->i2c_client.spi_client->spi_master->dev,
&e_ctrl->eboard_info->power_info.clk_info,
@@ -1788,6 +1793,11 @@ static int msm_eeprom_platform_remove(struct platform_device *pdev)
return 0;
}
+ if (!e_ctrl->eboard_info) {
+ pr_err("%s: board info is NULL\n", __func__);
+ return 0;
+ }
+
msm_camera_put_clk_info(e_ctrl->pdev,
&e_ctrl->eboard_info->power_info.clk_info,
&e_ctrl->eboard_info->power_info.clk_ptr,
diff --git a/drivers/media/platform/msm/camera_v2/sensor/msm_sensor_driver.c b/drivers/media/platform/msm/camera_v2/sensor/msm_sensor_driver.c
index 344f1a6f8d92..7027fedaf721 100644
--- a/drivers/media/platform/msm/camera_v2/sensor/msm_sensor_driver.c
+++ b/drivers/media/platform/msm/camera_v2/sensor/msm_sensor_driver.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2013-2016, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2013-2017, The Linux Foundation. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 and
@@ -1353,18 +1353,20 @@ static int32_t msm_sensor_driver_i2c_probe(struct i2c_client *client,
if (s_ctrl->sensor_i2c_client != NULL) {
s_ctrl->sensor_i2c_client->client = client;
s_ctrl->sensordata->power_info.dev = &client->dev;
+
+ /* Get clocks information */
+ rc = msm_camera_i2c_dev_get_clk_info(
+ &s_ctrl->sensor_i2c_client->client->dev,
+ &s_ctrl->sensordata->power_info.clk_info,
+ &s_ctrl->sensordata->power_info.clk_ptr,
+ &s_ctrl->sensordata->power_info.clk_info_size);
+ if (rc < 0) {
+ pr_err("failed: msm_camera_i2c_dev_get_clk_info rc %d",
+ rc);
+ goto FREE_S_CTRL;
+ }
+ return rc;
}
- /* Get clocks information */
- rc = msm_camera_i2c_dev_get_clk_info(
- &s_ctrl->sensor_i2c_client->client->dev,
- &s_ctrl->sensordata->power_info.clk_info,
- &s_ctrl->sensordata->power_info.clk_ptr,
- &s_ctrl->sensordata->power_info.clk_info_size);
- if (rc < 0) {
- pr_err("failed: msm_camera_i2c_dev_get_clk_info rc %d", rc);
- goto FREE_S_CTRL;
- }
- return rc;
FREE_S_CTRL:
kfree(s_ctrl);
return rc;
diff --git a/drivers/misc/qseecom.c b/drivers/misc/qseecom.c
index 9855bee67627..ee5bafc1515e 100644
--- a/drivers/misc/qseecom.c
+++ b/drivers/misc/qseecom.c
@@ -7750,7 +7750,7 @@ static int qseecom_retrieve_ce_data(struct platform_device *pdev)
uint32_t hlos_num_ce_hw_instances;
uint32_t disk_encrypt_pipe;
uint32_t file_encrypt_pipe;
- uint32_t hlos_ce_hw_instance[MAX_CE_PIPE_PAIR_PER_UNIT];
+ uint32_t hlos_ce_hw_instance[MAX_CE_PIPE_PAIR_PER_UNIT] = {0};
int i;
const int *tbl;
int size;
diff --git a/drivers/mmc/core/bus.h b/drivers/mmc/core/bus.h
index 00a19710b6b4..3f3f24b2a757 100644
--- a/drivers/mmc/core/bus.h
+++ b/drivers/mmc/core/bus.h
@@ -15,7 +15,7 @@
static ssize_t mmc_##name##_show (struct device *dev, struct device_attribute *attr, char *buf) \
{ \
struct mmc_card *card = mmc_dev_to_card(dev); \
- return sprintf(buf, fmt, args); \
+ return snprintf(buf, PAGE_SIZE, fmt, args); \
} \
static DEVICE_ATTR(name, S_IRUGO, mmc_##name##_show, NULL)
diff --git a/drivers/mmc/host/sdhci-msm-ice.c b/drivers/mmc/host/sdhci-msm-ice.c
index 2799b21fb6e3..e73bdfd424cc 100644
--- a/drivers/mmc/host/sdhci-msm-ice.c
+++ b/drivers/mmc/host/sdhci-msm-ice.c
@@ -377,7 +377,7 @@ int sdhci_msm_ice_cmdq_cfg(struct sdhci_host *host,
struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host);
struct sdhci_msm_host *msm_host = pltfm_host->priv;
int err = 0;
- short key_index;
+ short key_index = 0;
sector_t lba = 0;
unsigned int bypass = SDHCI_MSM_ICE_ENABLE_BYPASS;
struct request *req;
diff --git a/drivers/mmc/host/sdhci-msm.c b/drivers/mmc/host/sdhci-msm.c
index 987d61bdda2d..ca72ebfd55a3 100644
--- a/drivers/mmc/host/sdhci-msm.c
+++ b/drivers/mmc/host/sdhci-msm.c
@@ -5004,6 +5004,7 @@ static struct platform_driver sdhci_msm_driver = {
.driver = {
.name = "sdhci_msm",
.owner = THIS_MODULE,
+ .probe_type = PROBE_PREFER_ASYNCHRONOUS,
.of_match_table = sdhci_msm_dt_match,
.pm = SDHCI_MSM_PMOPS,
},
diff --git a/drivers/net/ethernet/cavium/liquidio/lio_main.c b/drivers/net/ethernet/cavium/liquidio/lio_main.c
index 7445da218bd9..cc1725616f9d 100644
--- a/drivers/net/ethernet/cavium/liquidio/lio_main.c
+++ b/drivers/net/ethernet/cavium/liquidio/lio_main.c
@@ -2823,7 +2823,7 @@ static int liquidio_xmit(struct sk_buff *skb, struct net_device *netdev)
if (!g) {
netif_info(lio, tx_err, lio->netdev,
"Transmit scatter gather: glist null!\n");
- goto lio_xmit_failed;
+ goto lio_xmit_dma_failed;
}
cmdsetup.s.gather = 1;
@@ -2894,7 +2894,7 @@ static int liquidio_xmit(struct sk_buff *skb, struct net_device *netdev)
else
status = octnet_send_nic_data_pkt(oct, &ndata, xmit_more);
if (status == IQ_SEND_FAILED)
- goto lio_xmit_failed;
+ goto lio_xmit_dma_failed;
netif_info(lio, tx_queued, lio->netdev, "Transmit queued successfully\n");
@@ -2908,12 +2908,13 @@ static int liquidio_xmit(struct sk_buff *skb, struct net_device *netdev)
return NETDEV_TX_OK;
+lio_xmit_dma_failed:
+ dma_unmap_single(&oct->pci_dev->dev, ndata.cmd.dptr,
+ ndata.datasize, DMA_TO_DEVICE);
lio_xmit_failed:
stats->tx_dropped++;
netif_info(lio, tx_err, lio->netdev, "IQ%d Transmit dropped:%llu\n",
iq_no, stats->tx_dropped);
- dma_unmap_single(&oct->pci_dev->dev, ndata.cmd.dptr,
- ndata.datasize, DMA_TO_DEVICE);
recv_buffer_free(skb);
return NETDEV_TX_OK;
}
diff --git a/drivers/net/macvlan.c b/drivers/net/macvlan.c
index 06c8bfeaccd6..40cd86614677 100644
--- a/drivers/net/macvlan.c
+++ b/drivers/net/macvlan.c
@@ -1110,6 +1110,7 @@ static int macvlan_port_create(struct net_device *dev)
static void macvlan_port_destroy(struct net_device *dev)
{
struct macvlan_port *port = macvlan_port_get_rtnl(dev);
+ struct sk_buff *skb;
dev->priv_flags &= ~IFF_MACVLAN_PORT;
netdev_rx_handler_unregister(dev);
@@ -1118,7 +1119,15 @@ static void macvlan_port_destroy(struct net_device *dev)
* but we need to cancel it and purge left skbs if any.
*/
cancel_work_sync(&port->bc_work);
- __skb_queue_purge(&port->bc_queue);
+
+ while ((skb = __skb_dequeue(&port->bc_queue))) {
+ const struct macvlan_dev *src = MACVLAN_SKB_CB(skb)->src;
+
+ if (src)
+ dev_put(src->dev);
+
+ kfree_skb(skb);
+ }
kfree_rcu(port, rcu);
}
diff --git a/drivers/net/phy/dp83640.c b/drivers/net/phy/dp83640.c
index e6cefd0e3262..84b9cca152eb 100644
--- a/drivers/net/phy/dp83640.c
+++ b/drivers/net/phy/dp83640.c
@@ -1436,8 +1436,6 @@ static bool dp83640_rxtstamp(struct phy_device *phydev,
skb_info->tmo = jiffies + SKB_TIMESTAMP_TIMEOUT;
skb_queue_tail(&dp83640->rx_queue, skb);
schedule_delayed_work(&dp83640->ts_work, SKB_TIMESTAMP_TIMEOUT);
- } else {
- netif_rx_ni(skb);
}
return true;
diff --git a/drivers/net/phy/phy.c b/drivers/net/phy/phy.c
index bba0ca786aaa..851c0e121807 100644
--- a/drivers/net/phy/phy.c
+++ b/drivers/net/phy/phy.c
@@ -538,7 +538,7 @@ void phy_stop_machine(struct phy_device *phydev)
cancel_delayed_work_sync(&phydev->state_queue);
mutex_lock(&phydev->lock);
- if (phydev->state > PHY_UP)
+ if (phydev->state > PHY_UP && phydev->state != PHY_HALTED)
phydev->state = PHY_UP;
mutex_unlock(&phydev->lock);
}
diff --git a/drivers/net/wireless/ath/ath10k/qmi.c b/drivers/net/wireless/ath/ath10k/qmi.c
index 9bab797dcdbc..10223605b027 100644
--- a/drivers/net/wireless/ath/ath10k/qmi.c
+++ b/drivers/net/wireless/ath/ath10k/qmi.c
@@ -888,12 +888,13 @@ void ath10k_snoc_stop_qmi_service(struct ath10k *ar)
ath10k_dbg(ar, ATH10K_DBG_SNOC, "Removing QMI service..\n");
+ wake_up_all(&ath10k_fw_ready_wait_event);
+ cancel_work_sync(&qmi_cfg->event_work);
+ cancel_work_sync(&qmi_cfg->qmi_recv_msg_work);
qmi_svc_event_notifier_unregister(WLFW_SERVICE_ID_V01,
WLFW_SERVICE_VERS_V01,
WLFW_SERVICE_INS_ID_V01,
&qmi_cfg->wlfw_clnt_nb);
-
- wake_up_all(&ath10k_fw_ready_wait_event);
destroy_workqueue(qmi_cfg->event_wq);
qmi_cfg = NULL;
}
diff --git a/drivers/net/wireless/ath/ath10k/snoc.c b/drivers/net/wireless/ath/ath10k/snoc.c
index 08618cedf775..0cc98e45b65c 100644
--- a/drivers/net/wireless/ath/ath10k/snoc.c
+++ b/drivers/net/wireless/ath/ath10k/snoc.c
@@ -1146,8 +1146,10 @@ static int ath10k_snoc_hif_power_up(struct ath10k *ar)
if (ar->state == ATH10K_STATE_ON ||
test_bit(ATH10K_FLAG_CRASH_FLUSH, &ar->dev_flags)) {
ret = ath10k_snoc_bus_configure(ar);
- if (ret)
+ if (ret) {
ath10k_err(ar, "failed to configure bus: %d\n", ret);
+ return ret;
+ }
}
ret = ath10k_snoc_init_pipes(ar);
if (ret) {
diff --git a/drivers/net/wireless/ath/wil6210/cfg80211.c b/drivers/net/wireless/ath/wil6210/cfg80211.c
index 423cdecd7a95..d68d6c926029 100644
--- a/drivers/net/wireless/ath/wil6210/cfg80211.c
+++ b/drivers/net/wireless/ath/wil6210/cfg80211.c
@@ -1654,12 +1654,6 @@ static int wil_cfg80211_set_power_mgmt(struct wiphy *wiphy,
{
struct wil6210_priv *wil = wiphy_to_wil(wiphy);
enum wmi_ps_profile_type ps_profile;
- int rc;
-
- if (!test_bit(WMI_FW_CAPABILITY_PS_CONFIG, wil->fw_capabilities)) {
- wil_err(wil, "set_power_mgmt not supported\n");
- return -EOPNOTSUPP;
- }
wil_dbg_misc(wil, "enabled=%d, timeout=%d\n",
enabled, timeout);
@@ -1669,11 +1663,7 @@ static int wil_cfg80211_set_power_mgmt(struct wiphy *wiphy,
else
ps_profile = WMI_PS_PROFILE_TYPE_PS_DISABLED;
- rc = wmi_ps_dev_profile_cfg(wil, ps_profile);
- if (rc)
- wil_err(wil, "wmi_ps_dev_profile_cfg failed (%d)\n", rc);
-
- return rc;
+ return wil_ps_update(wil, ps_profile);
}
static struct cfg80211_ops wil_cfg80211_ops = {
diff --git a/drivers/net/wireless/ath/wil6210/fw_inc.c b/drivers/net/wireless/ath/wil6210/fw_inc.c
index f4901587c005..e01acac88825 100644
--- a/drivers/net/wireless/ath/wil6210/fw_inc.c
+++ b/drivers/net/wireless/ath/wil6210/fw_inc.c
@@ -554,5 +554,7 @@ bool wil_fw_verify_file_exists(struct wil6210_priv *wil, const char *name)
rc = request_firmware(&fw, name, wil_to_dev(wil));
if (!rc)
release_firmware(fw);
- return rc != -ENOENT;
+ else
+ wil_dbg_fw(wil, "<%s> not available: %d\n", name, rc);
+ return !rc;
}
diff --git a/drivers/net/wireless/ath/wil6210/main.c b/drivers/net/wireless/ath/wil6210/main.c
index fca8acffeed5..45a5fb6d23a0 100644
--- a/drivers/net/wireless/ath/wil6210/main.c
+++ b/drivers/net/wireless/ath/wil6210/main.c
@@ -576,6 +576,9 @@ int wil_priv_init(struct wil6210_priv *wil)
if (rx_ring_overflow_thrsh == WIL6210_RX_HIGH_TRSH_INIT)
rx_ring_overflow_thrsh = WIL6210_RX_HIGH_TRSH_DEFAULT;
+
+ wil->ps_profile = WMI_PS_PROFILE_TYPE_DEFAULT;
+
return 0;
out_wmi_wq:
@@ -901,6 +904,24 @@ void wil_abort_scan(struct wil6210_priv *wil, bool sync)
}
}
+int wil_ps_update(struct wil6210_priv *wil, enum wmi_ps_profile_type ps_profile)
+{
+ int rc;
+
+ if (!test_bit(WMI_FW_CAPABILITY_PS_CONFIG, wil->fw_capabilities)) {
+ wil_err(wil, "set_power_mgmt not supported\n");
+ return -EOPNOTSUPP;
+ }
+
+ rc = wmi_ps_dev_profile_cfg(wil, ps_profile);
+ if (rc)
+ wil_err(wil, "wmi_ps_dev_profile_cfg failed (%d)\n", rc);
+ else
+ wil->ps_profile = ps_profile;
+
+ return rc;
+}
+
/*
* We reset all the structures, and we reset the UMAC.
* After calling this routine, you're expected to reload
@@ -950,15 +971,15 @@ int wil_reset(struct wil6210_priv *wil, bool load_fw)
/* Disable device led before reset*/
wmi_led_cfg(wil, false);
+ mutex_lock(&wil->p2p_wdev_mutex);
+ wil_abort_scan(wil, false);
+ mutex_unlock(&wil->p2p_wdev_mutex);
+
/* prevent NAPI from being scheduled and prevent wmi commands */
mutex_lock(&wil->wmi_mutex);
bitmap_zero(wil->status, wil_status_last);
mutex_unlock(&wil->wmi_mutex);
- mutex_lock(&wil->p2p_wdev_mutex);
- wil_abort_scan(wil, false);
- mutex_unlock(&wil->p2p_wdev_mutex);
-
wil_mask_irq(wil);
wmi_event_flush(wil);
@@ -1035,6 +1056,9 @@ int wil_reset(struct wil6210_priv *wil, bool load_fw)
return rc;
}
+ if (wil->ps_profile != WMI_PS_PROFILE_TYPE_DEFAULT)
+ wil_ps_update(wil, wil->ps_profile);
+
if (wil->tt_data_set)
wmi_set_tt_cfg(wil, &wil->tt_data);
diff --git a/drivers/net/wireless/ath/wil6210/pmc.c b/drivers/net/wireless/ath/wil6210/pmc.c
index b067fdf086d4..2e301b6b32a9 100644
--- a/drivers/net/wireless/ath/wil6210/pmc.c
+++ b/drivers/net/wireless/ath/wil6210/pmc.c
@@ -200,7 +200,7 @@ void wil_pmc_alloc(struct wil6210_priv *wil,
release_pmc_skbs:
wil_err(wil, "exit on error: Releasing skbs...\n");
- for (i = 0; pmc->descriptors[i].va && i < num_descriptors; i++) {
+ for (i = 0; i < num_descriptors && pmc->descriptors[i].va; i++) {
dma_free_coherent(dev,
descriptor_size,
pmc->descriptors[i].va,
@@ -283,7 +283,7 @@ void wil_pmc_free(struct wil6210_priv *wil, int send_pmc_cmd)
int i;
for (i = 0;
- pmc->descriptors[i].va && i < pmc->num_descriptors; i++) {
+ i < pmc->num_descriptors && pmc->descriptors[i].va; i++) {
dma_free_coherent(dev,
pmc->descriptor_size,
pmc->descriptors[i].va,
diff --git a/drivers/net/wireless/ath/wil6210/rx_reorder.c b/drivers/net/wireless/ath/wil6210/rx_reorder.c
index 7404b6f39c6a..a43cffcf1bbf 100644
--- a/drivers/net/wireless/ath/wil6210/rx_reorder.c
+++ b/drivers/net/wireless/ath/wil6210/rx_reorder.c
@@ -343,8 +343,16 @@ __acquires(&sta->tid_rx_lock) __releases(&sta->tid_rx_lock)
wil_err(wil, "BACK requested unsupported ba_policy == 1\n");
status = WLAN_STATUS_INVALID_QOS_PARAM;
}
- if (status == WLAN_STATUS_SUCCESS)
- agg_wsize = wil_agg_size(wil, req_agg_wsize);
+ if (status == WLAN_STATUS_SUCCESS) {
+ if (req_agg_wsize == 0) {
+ wil_dbg_misc(wil, "Suggest BACK wsize %d\n",
+ WIL_MAX_AGG_WSIZE);
+ agg_wsize = WIL_MAX_AGG_WSIZE;
+ } else {
+ agg_wsize = min_t(u16,
+ WIL_MAX_AGG_WSIZE, req_agg_wsize);
+ }
+ }
rc = wmi_addba_rx_resp(wil, cid, tid, dialog_token, status,
agg_amsdu, agg_wsize, agg_timeout);
diff --git a/drivers/net/wireless/ath/wil6210/txrx.c b/drivers/net/wireless/ath/wil6210/txrx.c
index 8b5411e4dc34..35bbf3a91f3e 100644
--- a/drivers/net/wireless/ath/wil6210/txrx.c
+++ b/drivers/net/wireless/ath/wil6210/txrx.c
@@ -37,6 +37,10 @@ bool rx_align_2;
module_param(rx_align_2, bool, 0444);
MODULE_PARM_DESC(rx_align_2, " align Rx buffers on 4*n+2, default - no");
+bool rx_large_buf;
+module_param(rx_large_buf, bool, 0444);
+MODULE_PARM_DESC(rx_large_buf, " allocate 8KB RX buffers, default - no");
+
static inline uint wil_rx_snaplen(void)
{
return rx_align_2 ? 6 : 0;
@@ -255,7 +259,7 @@ static int wil_vring_alloc_skb(struct wil6210_priv *wil, struct vring *vring,
u32 i, int headroom)
{
struct device *dev = wil_to_dev(wil);
- unsigned int sz = mtu_max + ETH_HLEN + wil_rx_snaplen();
+ unsigned int sz = wil->rx_buf_len + ETH_HLEN + wil_rx_snaplen();
struct vring_rx_desc dd, *d = &dd;
volatile struct vring_rx_desc *_d = &vring->va[i].rx;
dma_addr_t pa;
@@ -419,7 +423,7 @@ static struct sk_buff *wil_vring_reap_rx(struct wil6210_priv *wil,
struct sk_buff *skb;
dma_addr_t pa;
unsigned int snaplen = wil_rx_snaplen();
- unsigned int sz = mtu_max + ETH_HLEN + snaplen;
+ unsigned int sz = wil->rx_buf_len + ETH_HLEN + snaplen;
u16 dmalen;
u8 ftype;
int cid;
@@ -780,6 +784,20 @@ void wil_rx_handle(struct wil6210_priv *wil, int *quota)
wil_rx_refill(wil, v->size);
}
+static void wil_rx_buf_len_init(struct wil6210_priv *wil)
+{
+ wil->rx_buf_len = rx_large_buf ?
+ WIL_MAX_ETH_MTU : TXRX_BUF_LEN_DEFAULT - WIL_MAX_MPDU_OVERHEAD;
+ if (mtu_max > wil->rx_buf_len) {
+ /* do not allow RX buffers to be smaller than mtu_max, for
+ * backward compatibility (mtu_max parameter was also used
+ * to support receiving large packets)
+ */
+ wil_info(wil, "Override RX buffer to mtu_max(%d)\n", mtu_max);
+ wil->rx_buf_len = mtu_max;
+ }
+}
+
int wil_rx_init(struct wil6210_priv *wil, u16 size)
{
struct vring *vring = &wil->vring_rx;
@@ -792,6 +810,8 @@ int wil_rx_init(struct wil6210_priv *wil, u16 size)
return -EINVAL;
}
+ wil_rx_buf_len_init(wil);
+
vring->size = size;
rc = wil_vring_alloc(wil, vring);
if (rc)
diff --git a/drivers/net/wireless/ath/wil6210/wil6210.h b/drivers/net/wireless/ath/wil6210/wil6210.h
index 0529d10a8268..eee528127e97 100644
--- a/drivers/net/wireless/ath/wil6210/wil6210.h
+++ b/drivers/net/wireless/ath/wil6210/wil6210.h
@@ -33,6 +33,7 @@ extern unsigned short rx_ring_overflow_thrsh;
extern int agg_wsize;
extern u32 vring_idle_trsh;
extern bool rx_align_2;
+extern bool rx_large_buf;
extern bool debug_fw;
extern bool disable_ap_sme;
@@ -670,6 +671,7 @@ struct wil6210_priv {
struct work_struct probe_client_worker;
/* DMA related */
struct vring vring_rx;
+ unsigned int rx_buf_len;
struct vring vring_tx[WIL6210_MAX_TX_RINGS];
struct vring_tx_data vring_tx_data[WIL6210_MAX_TX_RINGS];
u8 vring2cid_tid[WIL6210_MAX_TX_RINGS][2]; /* [0] - CID, [1] - TID */
@@ -705,6 +707,8 @@ struct wil6210_priv {
/* High Access Latency Policy voting */
struct wil_halp halp;
+ enum wmi_ps_profile_type ps_profile;
+
struct wil_ftm_priv ftm;
bool tt_data_set;
struct wmi_tt_data tt_data;
@@ -824,6 +828,8 @@ int wil_if_add(struct wil6210_priv *wil);
void wil_if_remove(struct wil6210_priv *wil);
int wil_priv_init(struct wil6210_priv *wil);
void wil_priv_deinit(struct wil6210_priv *wil);
+int wil_ps_update(struct wil6210_priv *wil,
+ enum wmi_ps_profile_type ps_profile);
int wil_reset(struct wil6210_priv *wil, bool no_fw);
void wil_fw_error_recovery(struct wil6210_priv *wil);
void wil_set_recovery_state(struct wil6210_priv *wil, int state);
diff --git a/drivers/net/wireless/ath/wil6210/wmi.c b/drivers/net/wireless/ath/wil6210/wmi.c
index 41afbdc34c18..97e22281314c 100644
--- a/drivers/net/wireless/ath/wil6210/wmi.c
+++ b/drivers/net/wireless/ath/wil6210/wmi.c
@@ -1436,7 +1436,8 @@ int wmi_rx_chain_add(struct wil6210_priv *wil, struct vring *vring)
struct wmi_cfg_rx_chain_cmd cmd = {
.action = WMI_RX_CHAIN_ADD,
.rx_sw_ring = {
- .max_mpdu_size = cpu_to_le16(wil_mtu2macbuf(mtu_max)),
+ .max_mpdu_size = cpu_to_le16(
+ wil_mtu2macbuf(wil->rx_buf_len)),
.ring_mem_base = cpu_to_le64(vring->pa),
.ring_size = cpu_to_le16(vring->size),
},
diff --git a/drivers/net/wireless/cnss/Kconfig b/drivers/net/wireless/cnss/Kconfig
index 4558dc30fec1..8e69a2b469b9 100644
--- a/drivers/net/wireless/cnss/Kconfig
+++ b/drivers/net/wireless/cnss/Kconfig
@@ -9,6 +9,15 @@ config CNSS
This driver also adds support to integrate WLAN module to subsystem
restart framework.
+config CNSS_ASYNC
+ bool "Enable/disable cnss pci platform driver asynchronous probe"
+ depends on CNSS
+ ---help---
+ If enabled, CNSS PCI platform driver would do asynchronous probe.
+ Using asynchronous probe will allow CNSS PCI platform driver to
+ probe in parallel with other device drivers and will help to
+ reduce kernel boot time.
+
config CNSS_MAC_BUG
bool "Enable/disable 0-4K memory initialization for QCA6174"
depends on CNSS
diff --git a/drivers/net/wireless/cnss/cnss_pci.c b/drivers/net/wireless/cnss/cnss_pci.c
index f53ed2693879..48d358c4722a 100644
--- a/drivers/net/wireless/cnss/cnss_pci.c
+++ b/drivers/net/wireless/cnss/cnss_pci.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2013-2016, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2013-2017, The Linux Foundation. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 and
@@ -3067,6 +3067,9 @@ static struct platform_driver cnss_driver = {
.name = "cnss",
.owner = THIS_MODULE,
.of_match_table = cnss_dt_match,
+#ifdef CONFIG_CNSS_ASYNC
+ .probe_type = PROBE_PREFER_ASYNCHRONOUS,
+#endif
},
};
diff --git a/drivers/nfc/nq-nci.c b/drivers/nfc/nq-nci.c
index f4ad5bde06a8..538d8f91ce1b 100644
--- a/drivers/nfc/nq-nci.c
+++ b/drivers/nfc/nq-nci.c
@@ -1206,6 +1206,7 @@ static struct i2c_driver nqx = {
.owner = THIS_MODULE,
.name = "nq-nci",
.of_match_table = msm_match_table,
+ .probe_type = PROBE_PREFER_ASYNCHRONOUS,
.pm = &nfc_pm_ops,
},
};
diff --git a/drivers/platform/msm/ipa/ipa_v2/ipa_debugfs.c b/drivers/platform/msm/ipa/ipa_v2/ipa_debugfs.c
index e48c19c522a7..cb95f6e98956 100644
--- a/drivers/platform/msm/ipa/ipa_v2/ipa_debugfs.c
+++ b/drivers/platform/msm/ipa/ipa_v2/ipa_debugfs.c
@@ -80,6 +80,9 @@ const char *ipa_event_name[] = {
__stringify(ECM_DISCONNECT),
__stringify(IPA_TETHERING_STATS_UPDATE_STATS),
__stringify(IPA_TETHERING_STATS_UPDATE_NETWORK_STATS),
+ __stringify(IPA_QUOTA_REACH),
+ __stringify(IPA_SSR_BEFORE_SHUTDOWN),
+ __stringify(IPA_SSR_AFTER_POWERUP),
};
const char *ipa_hdr_l2_type_name[] = {
diff --git a/drivers/platform/msm/ipa/ipa_v2/ipa_qmi_service.h b/drivers/platform/msm/ipa/ipa_v2/ipa_qmi_service.h
index 96554af9aefd..1f5d619ef573 100644
--- a/drivers/platform/msm/ipa/ipa_v2/ipa_qmi_service.h
+++ b/drivers/platform/msm/ipa/ipa_v2/ipa_qmi_service.h
@@ -177,6 +177,9 @@ int rmnet_ipa_set_tether_client_pipe(struct wan_ioctl_set_tether_client_pipe
int rmnet_ipa_query_tethering_stats(struct wan_ioctl_query_tether_stats *data,
bool reset);
+int rmnet_ipa_query_tethering_stats_all(
+ struct wan_ioctl_query_tether_stats_all *data);
+
int rmnet_ipa_reset_tethering_stats(struct wan_ioctl_reset_tether_stats *data);
int ipa_qmi_get_data_stats(struct ipa_get_data_stats_req_msg_v01 *req,
diff --git a/drivers/platform/msm/ipa/ipa_v2/ipa_utils.c b/drivers/platform/msm/ipa/ipa_v2/ipa_utils.c
index d53121292c03..be3c890db25c 100644
--- a/drivers/platform/msm/ipa/ipa_v2/ipa_utils.c
+++ b/drivers/platform/msm/ipa/ipa_v2/ipa_utils.c
@@ -946,7 +946,7 @@ int ipa2_get_ep_mapping(enum ipa_client_type client)
void ipa2_set_client(int index, enum ipacm_client_enum client, bool uplink)
{
- if (client >= IPACM_CLIENT_MAX || client < IPACM_CLIENT_USB) {
+ if (client > IPACM_CLIENT_MAX || client < IPACM_CLIENT_USB) {
IPAERR("Bad client number! client =%d\n", client);
} else if (index >= IPA_MAX_NUM_PIPES || index < 0) {
IPAERR("Bad pipe index! index =%d\n", index);
diff --git a/drivers/platform/msm/ipa/ipa_v2/rmnet_ipa.c b/drivers/platform/msm/ipa/ipa_v2/rmnet_ipa.c
index 774077494ea5..da014427852b 100644
--- a/drivers/platform/msm/ipa/ipa_v2/rmnet_ipa.c
+++ b/drivers/platform/msm/ipa/ipa_v2/rmnet_ipa.c
@@ -2334,6 +2334,29 @@ static struct platform_driver rmnet_ipa_driver = {
.remove = ipa_wwan_remove,
};
+/**
+ * rmnet_ipa_send_ssr_notification(bool ssr_done) - send SSR notification
+ *
+ * This function sends the SSR notification before modem shutdown and
+ * after_powerup from SSR framework, to user-space module
+ */
+static void rmnet_ipa_send_ssr_notification(bool ssr_done)
+{
+ struct ipa_msg_meta msg_meta;
+ int rc;
+
+ memset(&msg_meta, 0, sizeof(struct ipa_msg_meta));
+ if (ssr_done)
+ msg_meta.msg_type = IPA_SSR_AFTER_POWERUP;
+ else
+ msg_meta.msg_type = IPA_SSR_BEFORE_SHUTDOWN;
+ rc = ipa_send_msg(&msg_meta, NULL, NULL);
+ if (rc) {
+ IPAWANERR("ipa_send_msg failed: %d\n", rc);
+ return;
+ }
+}
+
static int ssr_notifier_cb(struct notifier_block *this,
unsigned long code,
void *data)
@@ -2341,6 +2364,8 @@ static int ssr_notifier_cb(struct notifier_block *this,
if (ipa_rmnet_ctx.ipa_rmnet_ssr) {
if (SUBSYS_BEFORE_SHUTDOWN == code) {
pr_info("IPA received MPSS BEFORE_SHUTDOWN\n");
+ /* send SSR before-shutdown notification to IPACM */
+ rmnet_ipa_send_ssr_notification(false);
atomic_set(&is_ssr, 1);
ipa_q6_pre_shutdown_cleanup();
if (ipa_netdevs[0])
@@ -2517,6 +2542,26 @@ static void rmnet_ipa_get_network_stats_and_update(void)
}
/**
+ * rmnet_ipa_send_quota_reach_ind() - send quota_reach notification from
+ * IPA Modem
+ * This function sends the quota_reach indication from the IPA Modem driver
+ * via QMI, to user-space module
+ */
+static void rmnet_ipa_send_quota_reach_ind(void)
+{
+ struct ipa_msg_meta msg_meta;
+ int rc;
+
+ memset(&msg_meta, 0, sizeof(struct ipa_msg_meta));
+ msg_meta.msg_type = IPA_QUOTA_REACH;
+ rc = ipa_send_msg(&msg_meta, NULL, NULL);
+ if (rc) {
+ IPAWANERR("ipa_send_msg failed: %d\n", rc);
+ return;
+ }
+}
+
+/**
* rmnet_ipa_poll_tethering_stats() - Tethering stats polling IOCTL handler
* @data - IOCTL data
*
@@ -2796,7 +2841,7 @@ int rmnet_ipa_query_tethering_stats_modem(
IPAWANERR("reset the pipe stats\n");
} else {
/* print tethered-client enum */
- IPAWANDBG_LOW("Tethered-client enum(%d)\n", data->ipa_client);
+ IPAWANDBG("Tethered-client enum(%d)\n", data->ipa_client);
}
rc = ipa_qmi_get_data_stats(req, resp);
@@ -2805,10 +2850,6 @@ int rmnet_ipa_query_tethering_stats_modem(
kfree(req);
kfree(resp);
return rc;
- } else if (reset) {
- kfree(req);
- kfree(resp);
- return 0;
}
if (resp->dl_dst_pipe_stats_list_valid) {
@@ -2854,7 +2895,7 @@ int rmnet_ipa_query_tethering_stats_modem(
}
}
}
- IPAWANDBG_LOW("v4_rx_p(%lu) v6_rx_p(%lu) v4_rx_b(%lu) v6_rx_b(%lu)\n",
+ IPAWANDBG("v4_rx_p(%lu) v6_rx_p(%lu) v4_rx_b(%lu) v6_rx_b(%lu)\n",
(unsigned long int) data->ipv4_rx_packets,
(unsigned long int) data->ipv6_rx_packets,
(unsigned long int) data->ipv4_rx_bytes,
@@ -2904,7 +2945,7 @@ int rmnet_ipa_query_tethering_stats_modem(
}
}
}
- IPAWANDBG_LOW("tx_p_v4(%lu)v6(%lu)tx_b_v4(%lu) v6(%lu)\n",
+ IPAWANDBG("tx_p_v4(%lu)v6(%lu)tx_b_v4(%lu) v6(%lu)\n",
(unsigned long int) data->ipv4_tx_packets,
(unsigned long int) data->ipv6_tx_packets,
(unsigned long int) data->ipv4_tx_bytes,
@@ -2946,6 +2987,49 @@ int rmnet_ipa_query_tethering_stats(struct wan_ioctl_query_tether_stats *data,
return rc;
}
+int rmnet_ipa_query_tethering_stats_all(
+ struct wan_ioctl_query_tether_stats_all *data)
+{
+ struct wan_ioctl_query_tether_stats tether_stats;
+ enum ipa_upstream_type upstream_type;
+ int rc = 0;
+
+ memset(&tether_stats, 0, sizeof(struct wan_ioctl_query_tether_stats));
+ /* get IPA backhaul type */
+ upstream_type = find_upstream_type(data->upstreamIface);
+
+ if (upstream_type == IPA_UPSTEAM_MAX) {
+ IPAWANERR(" Wrong upstreamIface name %s\n",
+ data->upstreamIface);
+ } else if (upstream_type == IPA_UPSTEAM_WLAN) {
+ IPAWANDBG_LOW(" query wifi-backhaul stats\n");
+ rc = rmnet_ipa_query_tethering_stats_wifi(
+ &tether_stats, data->reset_stats);
+ if (rc) {
+ IPAWANERR("wlan WAN_IOC_QUERY_TETHER_STATS failed\n");
+ return rc;
+ }
+ data->tx_bytes = tether_stats.ipv4_tx_bytes
+ + tether_stats.ipv6_tx_bytes;
+ data->rx_bytes = tether_stats.ipv4_rx_bytes
+ + tether_stats.ipv6_rx_bytes;
+ } else {
+ IPAWANDBG_LOW(" query modem-backhaul stats\n");
+ tether_stats.ipa_client = data->ipa_client;
+ rc = rmnet_ipa_query_tethering_stats_modem(
+ &tether_stats, data->reset_stats);
+ if (rc) {
+ IPAWANERR("modem WAN_IOC_QUERY_TETHER_STATS failed\n");
+ return rc;
+ }
+ data->tx_bytes = tether_stats.ipv4_tx_bytes
+ + tether_stats.ipv6_tx_bytes;
+ data->rx_bytes = tether_stats.ipv4_rx_bytes
+ + tether_stats.ipv6_rx_bytes;
+ }
+ return rc;
+}
+
int rmnet_ipa_reset_tethering_stats(struct wan_ioctl_reset_tether_stats *data)
{
enum ipa_upstream_type upstream_type;
@@ -3047,6 +3131,8 @@ void ipa_broadcast_quota_reach_ind(u32 mux_id,
IPAWANERR("putting nlmsg: <%s> <%s> <%s>\n",
alert_msg, iface_name_l, iface_name_m);
kobject_uevent_env(&(ipa_netdevs[0]->dev.kobj), KOBJ_CHANGE, envp);
+
+ rmnet_ipa_send_quota_reach_ind();
}
/**
@@ -3071,6 +3157,9 @@ void ipa_q6_handshake_complete(bool ssr_bootup)
*/
ipa2_proxy_clk_unvote();
+ /* send SSR power-up notification to IPACM */
+ rmnet_ipa_send_ssr_notification(true);
+
/*
* It is required to recover the network stats after
* SSR recovery
diff --git a/drivers/platform/msm/ipa/ipa_v2/rmnet_ipa_fd_ioctl.c b/drivers/platform/msm/ipa/ipa_v2/rmnet_ipa_fd_ioctl.c
index 46bfe021eb4b..02bdd0334e7f 100644
--- a/drivers/platform/msm/ipa/ipa_v2/rmnet_ipa_fd_ioctl.c
+++ b/drivers/platform/msm/ipa/ipa_v2/rmnet_ipa_fd_ioctl.c
@@ -47,6 +47,10 @@
#define WAN_IOC_QUERY_DL_FILTER_STATS32 _IOWR(WAN_IOC_MAGIC, \
WAN_IOCTL_QUERY_DL_FILTER_STATS, \
compat_uptr_t)
+#define WAN_IOC_QUERY_TETHER_STATS_ALL32 _IOWR(WAN_IOC_MAGIC, \
+ WAN_IOCTL_QUERY_TETHER_STATS_ALL, \
+ compat_uptr_t)
+
#endif
static unsigned int dev_num = 1;
@@ -238,6 +242,32 @@ static long wan_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)
}
break;
+ case WAN_IOC_QUERY_TETHER_STATS_ALL:
+ IPAWANDBG_LOW("got WAN_IOC_QUERY_TETHER_STATS_ALL :>>>\n");
+ pyld_sz = sizeof(struct wan_ioctl_query_tether_stats_all);
+ param = kzalloc(pyld_sz, GFP_KERNEL);
+ if (!param) {
+ retval = -ENOMEM;
+ break;
+ }
+ if (copy_from_user(param, (u8 *)arg, pyld_sz)) {
+ retval = -EFAULT;
+ break;
+ }
+
+ if (rmnet_ipa_query_tethering_stats_all(
+ (struct wan_ioctl_query_tether_stats_all *)param)) {
+ IPAWANERR("WAN_IOC_QUERY_TETHER_STATS failed\n");
+ retval = -EFAULT;
+ break;
+ }
+
+ if (copy_to_user((u8 *)arg, param, pyld_sz)) {
+ retval = -EFAULT;
+ break;
+ }
+ break;
+
case WAN_IOC_RESET_TETHER_STATS:
IPAWANDBG_LOW("got WAN_IOC_RESET_TETHER_STATS :>>>\n");
pyld_sz = sizeof(struct wan_ioctl_reset_tether_stats);
diff --git a/drivers/platform/msm/ipa/ipa_v3/ipa_client.c b/drivers/platform/msm/ipa/ipa_v3/ipa_client.c
index 81eae05d7ed9..e349ade46075 100644
--- a/drivers/platform/msm/ipa/ipa_v3/ipa_client.c
+++ b/drivers/platform/msm/ipa/ipa_v3/ipa_client.c
@@ -857,6 +857,8 @@ static int ipa3_reset_with_open_aggr_frame_wa(u32 clnt_hdl,
struct gsi_xfer_elem xfer_elem;
int i;
int aggr_active_bitmap = 0;
+ bool pipe_suspended = false;
+ struct ipa_ep_cfg_ctrl ctrl;
IPADBG("Applying reset channel with open aggregation frame WA\n");
ipahal_write_reg(IPA_AGGR_FORCE_CLOSE, (1 << clnt_hdl));
@@ -883,6 +885,15 @@ static int ipa3_reset_with_open_aggr_frame_wa(u32 clnt_hdl,
if (result)
return -EFAULT;
+ ipahal_read_reg_n_fields(IPA_ENDP_INIT_CTRL_n, clnt_hdl, &ctrl);
+ if (ctrl.ipa_ep_suspend) {
+ IPADBG("pipe is suspended, remove suspend\n");
+ pipe_suspended = true;
+ ctrl.ipa_ep_suspend = false;
+ ipahal_write_reg_n_fields(IPA_ENDP_INIT_CTRL_n,
+ clnt_hdl, &ctrl);
+ }
+
/* Start channel and put 1 Byte descriptor on it */
gsi_res = gsi_start_channel(ep->gsi_chan_hdl);
if (gsi_res != GSI_STATUS_SUCCESS) {
@@ -942,6 +953,13 @@ static int ipa3_reset_with_open_aggr_frame_wa(u32 clnt_hdl,
*/
msleep(IPA_POLL_AGGR_STATE_SLEEP_MSEC);
+ if (pipe_suspended) {
+ IPADBG("suspend the pipe again\n");
+ ctrl.ipa_ep_suspend = true;
+ ipahal_write_reg_n_fields(IPA_ENDP_INIT_CTRL_n,
+ clnt_hdl, &ctrl);
+ }
+
/* Restore channels properties */
result = ipa3_restore_channel_properties(ep, &orig_chan_props,
&orig_chan_scratch);
@@ -956,6 +974,12 @@ queue_xfer_fail:
ipa3_stop_gsi_channel(clnt_hdl);
dma_free_coherent(ipa3_ctx->pdev, 1, buff, dma_addr);
start_chan_fail:
+ if (pipe_suspended) {
+ IPADBG("suspend the pipe again\n");
+ ctrl.ipa_ep_suspend = true;
+ ipahal_write_reg_n_fields(IPA_ENDP_INIT_CTRL_n,
+ clnt_hdl, &ctrl);
+ }
ipa3_restore_channel_properties(ep, &orig_chan_props,
&orig_chan_scratch);
restore_props_fail:
diff --git a/drivers/platform/msm/ipa/ipa_v3/ipa_debugfs.c b/drivers/platform/msm/ipa/ipa_v3/ipa_debugfs.c
index 72eb3808c7a4..fbf84ab7d2d4 100644
--- a/drivers/platform/msm/ipa/ipa_v3/ipa_debugfs.c
+++ b/drivers/platform/msm/ipa/ipa_v3/ipa_debugfs.c
@@ -61,6 +61,9 @@ const char *ipa3_event_name[] = {
__stringify(ECM_DISCONNECT),
__stringify(IPA_TETHERING_STATS_UPDATE_STATS),
__stringify(IPA_TETHERING_STATS_UPDATE_NETWORK_STATS),
+ __stringify(IPA_QUOTA_REACH),
+ __stringify(IPA_SSR_BEFORE_SHUTDOWN),
+ __stringify(IPA_SSR_AFTER_POWERUP),
};
const char *ipa3_hdr_l2_type_name[] = {
diff --git a/drivers/platform/msm/ipa/ipa_v3/ipa_dp.c b/drivers/platform/msm/ipa/ipa_v3/ipa_dp.c
index f23062702f28..0492fa27c5b7 100644
--- a/drivers/platform/msm/ipa/ipa_v3/ipa_dp.c
+++ b/drivers/platform/msm/ipa/ipa_v3/ipa_dp.c
@@ -1568,7 +1568,7 @@ int ipa3_teardown_sys_pipe(u32 clnt_hdl)
BUG();
return result;
}
- result = gsi_reset_channel(ep->gsi_chan_hdl);
+ result = ipa3_reset_gsi_channel(clnt_hdl);
if (result != GSI_STATUS_SUCCESS) {
IPAERR("Failed to reset chan: %d.\n", result);
BUG();
diff --git a/drivers/platform/msm/ipa/ipa_v3/ipa_qmi_service.h b/drivers/platform/msm/ipa/ipa_v3/ipa_qmi_service.h
index 6cd82f84bf13..d5d850309696 100644
--- a/drivers/platform/msm/ipa/ipa_v3/ipa_qmi_service.h
+++ b/drivers/platform/msm/ipa/ipa_v3/ipa_qmi_service.h
@@ -190,6 +190,9 @@ int rmnet_ipa3_set_tether_client_pipe(struct wan_ioctl_set_tether_client_pipe
int rmnet_ipa3_query_tethering_stats(struct wan_ioctl_query_tether_stats *data,
bool reset);
+int rmnet_ipa3_query_tethering_stats_all(
+ struct wan_ioctl_query_tether_stats_all *data);
+
int rmnet_ipa3_reset_tethering_stats(struct wan_ioctl_reset_tether_stats *data);
int ipa3_qmi_get_data_stats(struct ipa_get_data_stats_req_msg_v01 *req,
diff --git a/drivers/platform/msm/ipa/ipa_v3/ipa_utils.c b/drivers/platform/msm/ipa/ipa_v3/ipa_utils.c
index 5ffc1f23f47c..d19de2a7bdb5 100644
--- a/drivers/platform/msm/ipa/ipa_v3/ipa_utils.c
+++ b/drivers/platform/msm/ipa/ipa_v3/ipa_utils.c
@@ -1002,7 +1002,7 @@ u8 ipa3_get_qmb_master_sel(enum ipa_client_type client)
void ipa3_set_client(int index, enum ipacm_client_enum client, bool uplink)
{
- if (client >= IPACM_CLIENT_MAX || client < IPACM_CLIENT_USB) {
+ if (client > IPACM_CLIENT_MAX || client < IPACM_CLIENT_USB) {
IPAERR("Bad client number! client =%d\n", client);
} else if (index >= IPA3_MAX_NUM_PIPES || index < 0) {
IPAERR("Bad pipe index! index =%d\n", index);
diff --git a/drivers/platform/msm/ipa/ipa_v3/ipahal/ipahal_reg.c b/drivers/platform/msm/ipa/ipa_v3/ipahal/ipahal_reg.c
index 3855e0d46ca9..585f9e6bd492 100644
--- a/drivers/platform/msm/ipa/ipa_v3/ipahal/ipahal_reg.c
+++ b/drivers/platform/msm/ipa/ipa_v3/ipahal/ipahal_reg.c
@@ -646,6 +646,21 @@ static void ipareg_construct_endp_init_ctrl_n(enum ipahal_reg_name reg,
IPA_ENDP_INIT_CTRL_n_ENDP_DELAY_BMSK);
}
+static void ipareg_parse_endp_init_ctrl_n(enum ipahal_reg_name reg,
+ void *fields, u32 val)
+{
+ struct ipa_ep_cfg_ctrl *ep_ctrl =
+ (struct ipa_ep_cfg_ctrl *)fields;
+
+ ep_ctrl->ipa_ep_suspend =
+ ((val & IPA_ENDP_INIT_CTRL_n_ENDP_SUSPEND_BMSK) >>
+ IPA_ENDP_INIT_CTRL_n_ENDP_SUSPEND_SHFT);
+
+ ep_ctrl->ipa_ep_delay =
+ ((val & IPA_ENDP_INIT_CTRL_n_ENDP_DELAY_BMSK) >>
+ IPA_ENDP_INIT_CTRL_n_ENDP_DELAY_SHFT);
+}
+
static void ipareg_construct_endp_init_ctrl_scnd_n(enum ipahal_reg_name reg,
const void *fields, u32 *val)
{
@@ -1018,7 +1033,8 @@ static struct ipahal_reg_obj ipahal_reg_objs[IPA_HW_MAX][IPA_REG_MAX] = {
ipareg_construct_endp_init_nat_n, ipareg_parse_dummy,
0x0000080C, 0x70},
[IPA_HW_v3_0][IPA_ENDP_INIT_CTRL_n] = {
- ipareg_construct_endp_init_ctrl_n, ipareg_parse_dummy,
+ ipareg_construct_endp_init_ctrl_n,
+ ipareg_parse_endp_init_ctrl_n,
0x00000800, 0x70},
[IPA_HW_v3_0][IPA_ENDP_INIT_CTRL_SCND_n] = {
ipareg_construct_endp_init_ctrl_scnd_n, ipareg_parse_dummy,
diff --git a/drivers/platform/msm/ipa/ipa_v3/rmnet_ipa.c b/drivers/platform/msm/ipa/ipa_v3/rmnet_ipa.c
index 04e5862cd960..1bd4f7fda1b7 100644
--- a/drivers/platform/msm/ipa/ipa_v3/rmnet_ipa.c
+++ b/drivers/platform/msm/ipa/ipa_v3/rmnet_ipa.c
@@ -2455,6 +2455,29 @@ static struct platform_driver rmnet_ipa_driver = {
.remove = ipa3_wwan_remove,
};
+/**
+ * rmnet_ipa_send_ssr_notification(bool ssr_done) - send SSR notification
+ *
+ * This function sends the SSR notification before modem shutdown and
+ * after_powerup from SSR framework, to user-space module
+ */
+static void rmnet_ipa_send_ssr_notification(bool ssr_done)
+{
+ struct ipa_msg_meta msg_meta;
+ int rc;
+
+ memset(&msg_meta, 0, sizeof(struct ipa_msg_meta));
+ if (ssr_done)
+ msg_meta.msg_type = IPA_SSR_AFTER_POWERUP;
+ else
+ msg_meta.msg_type = IPA_SSR_BEFORE_SHUTDOWN;
+ rc = ipa_send_msg(&msg_meta, NULL, NULL);
+ if (rc) {
+ IPAWANERR("ipa_send_msg failed: %d\n", rc);
+ return;
+ }
+}
+
static int ipa3_ssr_notifier_cb(struct notifier_block *this,
unsigned long code,
void *data)
@@ -2465,6 +2488,8 @@ static int ipa3_ssr_notifier_cb(struct notifier_block *this,
switch (code) {
case SUBSYS_BEFORE_SHUTDOWN:
IPAWANINFO("IPA received MPSS BEFORE_SHUTDOWN\n");
+ /* send SSR before-shutdown notification to IPACM */
+ rmnet_ipa_send_ssr_notification(false);
atomic_set(&rmnet_ipa3_ctx->is_ssr, 1);
ipa3_q6_pre_shutdown_cleanup();
if (IPA_NETDEV())
@@ -2641,6 +2666,26 @@ static void rmnet_ipa_get_network_stats_and_update(void)
}
/**
+ * rmnet_ipa_send_quota_reach_ind() - send quota_reach notification from
+ * IPA Modem
+ * This function sends the quota_reach indication from the IPA Modem driver
+ * via QMI, to user-space module
+ */
+static void rmnet_ipa_send_quota_reach_ind(void)
+{
+ struct ipa_msg_meta msg_meta;
+ int rc;
+
+ memset(&msg_meta, 0, sizeof(struct ipa_msg_meta));
+ msg_meta.msg_type = IPA_QUOTA_REACH;
+ rc = ipa_send_msg(&msg_meta, NULL, NULL);
+ if (rc) {
+ IPAWANERR("ipa_send_msg failed: %d\n", rc);
+ return;
+ }
+}
+
+/**
* rmnet_ipa3_poll_tethering_stats() - Tethering stats polling IOCTL handler
* @data - IOCTL data
*
@@ -2921,7 +2966,7 @@ static int rmnet_ipa3_query_tethering_stats_modem(
IPAWANERR("reset the pipe stats\n");
} else {
/* print tethered-client enum */
- IPAWANDBG_LOW("Tethered-client enum(%d)\n", data->ipa_client);
+ IPAWANDBG("Tethered-client enum(%d)\n", data->ipa_client);
}
rc = ipa3_qmi_get_data_stats(req, resp);
@@ -2930,10 +2975,6 @@ static int rmnet_ipa3_query_tethering_stats_modem(
kfree(req);
kfree(resp);
return rc;
- } else if (reset) {
- kfree(req);
- kfree(resp);
- return 0;
}
if (resp->dl_dst_pipe_stats_list_valid) {
@@ -3071,6 +3112,49 @@ int rmnet_ipa3_query_tethering_stats(struct wan_ioctl_query_tether_stats *data,
return rc;
}
+int rmnet_ipa3_query_tethering_stats_all(
+ struct wan_ioctl_query_tether_stats_all *data)
+{
+ struct wan_ioctl_query_tether_stats tether_stats;
+ enum ipa_upstream_type upstream_type;
+ int rc = 0;
+
+ memset(&tether_stats, 0, sizeof(struct wan_ioctl_query_tether_stats));
+ /* get IPA backhaul type */
+ upstream_type = find_upstream_type(data->upstreamIface);
+
+ if (upstream_type == IPA_UPSTEAM_MAX) {
+ IPAWANERR(" Wrong upstreamIface name %s\n",
+ data->upstreamIface);
+ } else if (upstream_type == IPA_UPSTEAM_WLAN) {
+ IPAWANDBG_LOW(" query wifi-backhaul stats\n");
+ rc = rmnet_ipa3_query_tethering_stats_wifi(
+ &tether_stats, data->reset_stats);
+ if (rc) {
+ IPAWANERR("wlan WAN_IOC_QUERY_TETHER_STATS failed\n");
+ return rc;
+ }
+ data->tx_bytes = tether_stats.ipv4_tx_bytes
+ + tether_stats.ipv6_tx_bytes;
+ data->rx_bytes = tether_stats.ipv4_rx_bytes
+ + tether_stats.ipv6_rx_bytes;
+ } else {
+ IPAWANDBG_LOW(" query modem-backhaul stats\n");
+ tether_stats.ipa_client = data->ipa_client;
+ rc = rmnet_ipa3_query_tethering_stats_modem(
+ &tether_stats, data->reset_stats);
+ if (rc) {
+ IPAWANERR("modem WAN_IOC_QUERY_TETHER_STATS failed\n");
+ return rc;
+ }
+ data->tx_bytes = tether_stats.ipv4_tx_bytes
+ + tether_stats.ipv6_tx_bytes;
+ data->rx_bytes = tether_stats.ipv4_rx_bytes
+ + tether_stats.ipv6_rx_bytes;
+ }
+ return rc;
+}
+
int rmnet_ipa3_reset_tethering_stats(struct wan_ioctl_reset_tether_stats *data)
{
enum ipa_upstream_type upstream_type;
@@ -3168,6 +3252,8 @@ void ipa3_broadcast_quota_reach_ind(u32 mux_id,
alert_msg, iface_name_l, iface_name_m);
kobject_uevent_env(&(IPA_NETDEV()->dev.kobj),
KOBJ_CHANGE, envp);
+
+ rmnet_ipa_send_quota_reach_ind();
}
/**
@@ -3192,6 +3278,9 @@ void ipa3_q6_handshake_complete(bool ssr_bootup)
*/
ipa3_proxy_clk_unvote();
+ /* send SSR power-up notification to IPACM */
+ rmnet_ipa_send_ssr_notification(true);
+
/*
* It is required to recover the network stats after
* SSR recovery
diff --git a/drivers/platform/msm/ipa/ipa_v3/rmnet_ipa_fd_ioctl.c b/drivers/platform/msm/ipa/ipa_v3/rmnet_ipa_fd_ioctl.c
index ffd127a21ed1..51bbec464e4d 100644
--- a/drivers/platform/msm/ipa/ipa_v3/rmnet_ipa_fd_ioctl.c
+++ b/drivers/platform/msm/ipa/ipa_v3/rmnet_ipa_fd_ioctl.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2013-2016, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2013-2017, The Linux Foundation. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 and
@@ -47,6 +47,9 @@
#define WAN_IOC_QUERY_DL_FILTER_STATS32 _IOWR(WAN_IOC_MAGIC, \
WAN_IOCTL_QUERY_DL_FILTER_STATS, \
compat_uptr_t)
+#define WAN_IOC_QUERY_TETHER_STATS_ALL32 _IOWR(WAN_IOC_MAGIC, \
+ WAN_IOCTL_QUERY_TETHER_STATS_ALL, \
+ compat_uptr_t)
#endif
static unsigned int dev_num = 1;
@@ -265,6 +268,32 @@ static long ipa3_wan_ioctl(struct file *filp,
}
break;
+ case WAN_IOC_QUERY_TETHER_STATS_ALL:
+ IPAWANDBG_LOW("got WAN_IOC_QUERY_TETHER_STATS_ALL :>>>\n");
+ pyld_sz = sizeof(struct wan_ioctl_query_tether_stats_all);
+ param = kzalloc(pyld_sz, GFP_KERNEL);
+ if (!param) {
+ retval = -ENOMEM;
+ break;
+ }
+ if (copy_from_user(param, (u8 *)arg, pyld_sz)) {
+ retval = -EFAULT;
+ break;
+ }
+
+ if (rmnet_ipa3_query_tethering_stats_all(
+ (struct wan_ioctl_query_tether_stats_all *)param)) {
+ IPAWANERR("WAN_IOC_QUERY_TETHER_STATS failed\n");
+ retval = -EFAULT;
+ break;
+ }
+
+ if (copy_to_user((u8 *)arg, param, pyld_sz)) {
+ retval = -EFAULT;
+ break;
+ }
+ break;
+
case WAN_IOC_RESET_TETHER_STATS:
IPAWANDBG_LOW("device %s got WAN_IOC_RESET_TETHER_STATS :>>>\n",
DRIVER_NAME);
diff --git a/drivers/platform/msm/msm_ext_display.c b/drivers/platform/msm/msm_ext_display.c
index 6f9a13040cd5..c7c1b1567bf3 100644
--- a/drivers/platform/msm/msm_ext_display.c
+++ b/drivers/platform/msm/msm_ext_display.c
@@ -654,6 +654,7 @@ int msm_ext_disp_register_audio_codec(struct platform_device *pdev,
{
int ret = 0;
struct msm_ext_disp *ext_disp = NULL;
+ struct msm_ext_disp_list *node = NULL;
if (!pdev || !ops) {
pr_err("Invalid params\n");
@@ -671,17 +672,23 @@ int msm_ext_disp_register_audio_codec(struct platform_device *pdev,
if ((ext_disp->current_disp != EXT_DISPLAY_TYPE_MAX)
&& ext_disp->ops) {
pr_err("Codec already registered\n");
- ret = -EINVAL;
- goto end;
+ mutex_unlock(&ext_disp->lock);
+ return -EINVAL;
}
ext_disp->ops = ops;
- pr_debug("audio codec registered\n");
-
-end:
mutex_unlock(&ext_disp->lock);
+ list_for_each_entry(node, &ext_disp->display_list, list) {
+ struct msm_ext_disp_init_data *data = node->data;
+
+ if (data->codec_ops.codec_ready)
+ data->codec_ops.codec_ready(data->pdev);
+ }
+
+ pr_debug("audio codec registered\n");
+
return ret;
}
diff --git a/drivers/power/supply/qcom/qpnp-fg-gen3.c b/drivers/power/supply/qcom/qpnp-fg-gen3.c
index 4368709118ac..d0f7a5e1e227 100644
--- a/drivers/power/supply/qcom/qpnp-fg-gen3.c
+++ b/drivers/power/supply/qcom/qpnp-fg-gen3.c
@@ -3366,6 +3366,16 @@ static int fg_hw_init(struct fg_chip *chip)
return rc;
}
+ if (is_debug_batt_id(chip)) {
+ val = ESR_NO_PULL_DOWN;
+ rc = fg_masked_write(chip, BATT_INFO_ESR_PULL_DN_CFG(chip),
+ ESR_PULL_DOWN_MODE_MASK, val);
+ if (rc < 0) {
+ pr_err("Error in writing esr_pull_down, rc=%d\n", rc);
+ return rc;
+ }
+ }
+
return 0;
}
diff --git a/drivers/scsi/ufs/ufs-qcom-ice.c b/drivers/scsi/ufs/ufs-qcom-ice.c
index 814d1dcfe90e..0c862639fa3e 100644
--- a/drivers/scsi/ufs/ufs-qcom-ice.c
+++ b/drivers/scsi/ufs/ufs-qcom-ice.c
@@ -394,8 +394,8 @@ int ufs_qcom_ice_cfg_start(struct ufs_qcom_host *qcom_host,
}
+ memset(&ice_set, 0, sizeof(ice_set));
if (qcom_host->ice.vops->config_start) {
- memset(&ice_set, 0, sizeof(ice_set));
spin_lock_irqsave(
&qcom_host->ice_work_lock, flags);
diff --git a/drivers/scsi/ufs/ufshcd.c b/drivers/scsi/ufs/ufshcd.c
index 7e2f5e06c036..9e64e0c34f57 100644
--- a/drivers/scsi/ufs/ufshcd.c
+++ b/drivers/scsi/ufs/ufshcd.c
@@ -1506,6 +1506,7 @@ start:
}
spin_unlock_irqrestore(hba->host->host_lock, flags);
out:
+ hba->ufs_stats.clk_hold.ts = ktime_get();
return rc;
}
EXPORT_SYMBOL_GPL(ufshcd_hold);
@@ -1610,6 +1611,7 @@ static void __ufshcd_release(struct ufs_hba *hba, bool no_sched)
hba->clk_gating.state = REQ_CLKS_OFF;
trace_ufshcd_clk_gating(dev_name(hba->dev), hba->clk_gating.state);
+ hba->ufs_stats.clk_rel.ts = ktime_get();
hrtimer_start(&hba->clk_gating.gate_hrtimer,
ms_to_ktime(hba->clk_gating.delay_ms),
@@ -2056,8 +2058,10 @@ static void ufshcd_hibern8_exit_work(struct work_struct *work)
/* Exit from hibern8 */
if (ufshcd_is_link_hibern8(hba)) {
+ hba->ufs_stats.clk_hold.ctx = H8_EXIT_WORK;
ufshcd_hold(hba, false);
ret = ufshcd_uic_hibern8_exit(hba);
+ hba->ufs_stats.clk_rel.ctx = H8_EXIT_WORK;
ufshcd_release(hba, false);
if (!ret) {
spin_lock_irqsave(hba->host->host_lock, flags);
@@ -2483,6 +2487,7 @@ ufshcd_send_uic_cmd(struct ufs_hba *hba, struct uic_command *uic_cmd)
int ret;
unsigned long flags;
+ hba->ufs_stats.clk_hold.ctx = UIC_CMD_SEND;
ufshcd_hold_all(hba);
mutex_lock(&hba->uic_cmd_mutex);
ufshcd_add_delay_before_dme_cmd(hba);
@@ -2496,6 +2501,7 @@ ufshcd_send_uic_cmd(struct ufs_hba *hba, struct uic_command *uic_cmd)
ufshcd_save_tstamp_of_last_dme_cmd(hba);
mutex_unlock(&hba->uic_cmd_mutex);
ufshcd_release_all(hba);
+ hba->ufs_stats.clk_rel.ctx = UIC_CMD_SEND;
ufsdbg_error_inject_dispatcher(hba,
ERR_INJECT_UIC, 0, &ret);
@@ -2973,6 +2979,7 @@ static int ufshcd_queuecommand(struct Scsi_Host *host, struct scsi_cmnd *cmd)
goto out;
}
+ hba->ufs_stats.clk_hold.ctx = QUEUE_CMD;
err = ufshcd_hold(hba, true);
if (err) {
err = SCSI_MLQUEUE_HOST_BUSY;
@@ -2986,6 +2993,7 @@ static int ufshcd_queuecommand(struct Scsi_Host *host, struct scsi_cmnd *cmd)
if (err) {
clear_bit_unlock(tag, &hba->lrb_in_use);
err = SCSI_MLQUEUE_HOST_BUSY;
+ hba->ufs_stats.clk_rel.ctx = QUEUE_CMD;
ufshcd_release(hba, true);
goto out;
}
@@ -4357,8 +4365,10 @@ static int ufshcd_uic_change_pwr_mode(struct ufs_hba *hba, u8 mode)
uic_cmd.command = UIC_CMD_DME_SET;
uic_cmd.argument1 = UIC_ARG_MIB(PA_PWRMODE);
uic_cmd.argument3 = mode;
+ hba->ufs_stats.clk_hold.ctx = PWRCTL_CMD_SEND;
ufshcd_hold_all(hba);
ret = ufshcd_uic_pwr_ctrl(hba, &uic_cmd);
+ hba->ufs_stats.clk_rel.ctx = PWRCTL_CMD_SEND;
ufshcd_release_all(hba);
out:
return ret;
@@ -5526,6 +5536,7 @@ static void __ufshcd_transfer_req_compl(struct ufs_hba *hba,
update_req_stats(hba, lrbp);
/* Mark completed command as NULL in LRB */
lrbp->cmd = NULL;
+ hba->ufs_stats.clk_rel.ctx = XFR_REQ_COMPL;
__ufshcd_release(hba, false);
__ufshcd_hibern8_release(hba, false);
if (cmd->request) {
@@ -6048,6 +6059,7 @@ static void ufshcd_err_handler(struct work_struct *work)
if (unlikely((hba->clk_gating.state != CLKS_ON) &&
ufshcd_is_auto_hibern8_supported(hba))) {
spin_unlock_irqrestore(hba->host->host_lock, flags);
+ hba->ufs_stats.clk_hold.ctx = ERR_HNDLR_WORK;
ufshcd_hold(hba, false);
spin_lock_irqsave(hba->host->host_lock, flags);
clks_enabled = true;
@@ -6191,8 +6203,10 @@ skip_err_handling:
hba->silence_err_logs = false;
- if (clks_enabled)
+ if (clks_enabled) {
__ufshcd_release(hba, false);
+ hba->ufs_stats.clk_rel.ctx = ERR_HNDLR_WORK;
+ }
out:
ufshcd_clear_eh_in_progress(hba);
spin_unlock_irqrestore(hba->host->host_lock, flags);
@@ -6428,7 +6442,8 @@ static irqreturn_t ufshcd_intr(int irq, void *__hba)
spin_lock(hba->host->host_lock);
intr_status = ufshcd_readl(hba, REG_INTERRUPT_STATUS);
-
+ hba->ufs_stats.last_intr_status = intr_status;
+ hba->ufs_stats.last_intr_ts = ktime_get();
/*
* There could be max of hba->nutrs reqs in flight and in worst case
* if the reqs get finished 1 by 1 after the interrupt status is
@@ -6507,6 +6522,7 @@ static int ufshcd_issue_tm_cmd(struct ufs_hba *hba, int lun_id, int task_id,
* the maximum wait time is bounded by %TM_CMD_TIMEOUT.
*/
wait_event(hba->tm_tag_wq, ufshcd_get_tm_free_slot(hba, &free_slot));
+ hba->ufs_stats.clk_hold.ctx = TM_CMD_SEND;
ufshcd_hold_all(hba);
spin_lock_irqsave(host->host_lock, flags);
@@ -6564,6 +6580,7 @@ static int ufshcd_issue_tm_cmd(struct ufs_hba *hba, int lun_id, int task_id,
clear_bit(free_slot, &hba->tm_condition);
ufshcd_put_tm_slot(hba, free_slot);
wake_up(&hba->tm_tag_wq);
+ hba->ufs_stats.clk_rel.ctx = TM_CMD_SEND;
ufshcd_release_all(hba);
return err;
@@ -9458,6 +9475,7 @@ static int ufshcd_devfreq_scale(struct ufs_hba *hba, bool scale_up)
int ret = 0;
/* let's not get into low power until clock scaling is completed */
+ hba->ufs_stats.clk_hold.ctx = CLK_SCALE_WORK;
ufshcd_hold_all(hba);
ret = ufshcd_clock_scaling_prepare(hba);
@@ -9521,6 +9539,7 @@ scale_up_gear:
clk_scaling_unprepare:
ufshcd_clock_scaling_unprepare(hba);
out:
+ hba->ufs_stats.clk_rel.ctx = CLK_SCALE_WORK;
ufshcd_release_all(hba);
return ret;
}
diff --git a/drivers/scsi/ufs/ufshcd.h b/drivers/scsi/ufs/ufshcd.h
index 12d8f7ff53ed..d66205ff9f5d 100644
--- a/drivers/scsi/ufs/ufshcd.h
+++ b/drivers/scsi/ufs/ufshcd.h
@@ -3,7 +3,7 @@
*
* This code is based on drivers/scsi/ufs/ufshcd.h
* Copyright (C) 2011-2013 Samsung India Software Operations
- * Copyright (c) 2013-2016, The Linux Foundation. All rights reserved.
+ * Copyright (c) 2013-2017, The Linux Foundation. All rights reserved.
*
* Authors:
* Santosh Yaraganavi <santosh.sy@samsung.com>
@@ -588,6 +588,22 @@ struct ufshcd_req_stat {
};
#endif
+enum ufshcd_ctx {
+ QUEUE_CMD,
+ ERR_HNDLR_WORK,
+ H8_EXIT_WORK,
+ UIC_CMD_SEND,
+ PWRCTL_CMD_SEND,
+ TM_CMD_SEND,
+ XFR_REQ_COMPL,
+ CLK_SCALE_WORK,
+};
+
+struct ufshcd_clk_ctx {
+ ktime_t ts;
+ enum ufshcd_ctx ctx;
+};
+
/**
* struct ufs_stats - keeps usage/err statistics
* @enabled: enable tag stats for debugfs
@@ -616,6 +632,10 @@ struct ufs_stats {
int query_stats_arr[UPIU_QUERY_OPCODE_MAX][MAX_QUERY_IDN];
#endif
+ u32 last_intr_status;
+ ktime_t last_intr_ts;
+ struct ufshcd_clk_ctx clk_hold;
+ struct ufshcd_clk_ctx clk_rel;
u32 hibern8_exit_cnt;
ktime_t last_hibern8_exit_tstamp;
struct ufs_uic_err_reg_hist pa_err;
diff --git a/drivers/soc/qcom/icnss_utils.c b/drivers/soc/qcom/icnss_utils.c
index 5e187d5df8b3..a7a0ffa2c18e 100644
--- a/drivers/soc/qcom/icnss_utils.c
+++ b/drivers/soc/qcom/icnss_utils.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2016, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2016-2017, The Linux Foundation. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 and
@@ -16,7 +16,7 @@
#define ICNSS_MAX_CH_NUM 45
static DEFINE_MUTEX(unsafe_channel_list_lock);
-static DEFINE_MUTEX(dfs_nol_info_lock);
+static DEFINE_SPINLOCK(dfs_nol_info_lock);
static struct icnss_unsafe_channel_list {
u16 unsafe_ch_count;
@@ -77,27 +77,24 @@ EXPORT_SYMBOL(icnss_get_wlan_unsafe_channel);
int icnss_wlan_set_dfs_nol(const void *info, u16 info_len)
{
void *temp;
+ void *old_nol_info;
struct icnss_dfs_nol_info *dfs_info;
- mutex_lock(&dfs_nol_info_lock);
- if (!info || !info_len) {
- mutex_unlock(&dfs_nol_info_lock);
+ if (!info || !info_len)
return -EINVAL;
- }
- temp = kmalloc(info_len, GFP_KERNEL);
- if (!temp) {
- mutex_unlock(&dfs_nol_info_lock);
+ temp = kmalloc(info_len, GFP_ATOMIC);
+ if (!temp)
return -ENOMEM;
- }
memcpy(temp, info, info_len);
+ spin_lock_bh(&dfs_nol_info_lock);
dfs_info = &dfs_nol_info;
- kfree(dfs_info->dfs_nol_info);
-
+ old_nol_info = dfs_info->dfs_nol_info;
dfs_info->dfs_nol_info = temp;
dfs_info->dfs_nol_info_len = info_len;
- mutex_unlock(&dfs_nol_info_lock);
+ spin_unlock_bh(&dfs_nol_info_lock);
+ kfree(old_nol_info);
return 0;
}
@@ -108,24 +105,21 @@ int icnss_wlan_get_dfs_nol(void *info, u16 info_len)
int len;
struct icnss_dfs_nol_info *dfs_info;
- mutex_lock(&dfs_nol_info_lock);
- if (!info || !info_len) {
- mutex_unlock(&dfs_nol_info_lock);
+ if (!info || !info_len)
return -EINVAL;
- }
- dfs_info = &dfs_nol_info;
+ spin_lock_bh(&dfs_nol_info_lock);
+ dfs_info = &dfs_nol_info;
if (dfs_info->dfs_nol_info == NULL ||
dfs_info->dfs_nol_info_len == 0) {
- mutex_unlock(&dfs_nol_info_lock);
+ spin_unlock_bh(&dfs_nol_info_lock);
return -ENOENT;
}
len = min(info_len, dfs_info->dfs_nol_info_len);
-
memcpy(info, dfs_info->dfs_nol_info, len);
- mutex_unlock(&dfs_nol_info_lock);
+ spin_unlock_bh(&dfs_nol_info_lock);
return len;
}
diff --git a/drivers/soc/qcom/memshare/msm_memshare.c b/drivers/soc/qcom/memshare/msm_memshare.c
index b8417513ca55..c11114528d2a 100644
--- a/drivers/soc/qcom/memshare/msm_memshare.c
+++ b/drivers/soc/qcom/memshare/msm_memshare.c
@@ -498,6 +498,7 @@ static int handle_alloc_generic_req(void *req_h, void *req, void *conn_h)
struct mem_alloc_generic_resp_msg_v01 *alloc_resp;
int rc, resp = 0;
int client_id;
+ uint32_t size = 0;
alloc_req = (struct mem_alloc_generic_req_msg_v01 *)req;
pr_debug("memshare: alloc request client id: %d proc _id: %d\n",
@@ -528,7 +529,11 @@ static int handle_alloc_generic_req(void *req_h, void *req, void *conn_h)
__func__, memblock[client_id].client_id,
memblock[client_id].free_memory);
if (!memblock[client_id].alloted) {
- rc = memshare_alloc(memsh_drv->dev, alloc_req->num_bytes,
+ if (alloc_req->client_id == 1 && alloc_req->num_bytes > 0)
+ size = alloc_req->num_bytes + MEMSHARE_GUARD_BYTES;
+ else
+ size = alloc_req->num_bytes;
+ rc = memshare_alloc(memsh_drv->dev, size,
&memblock[client_id]);
if (rc) {
pr_err("In %s,Unable to allocate memory for requested client\n",
@@ -963,8 +968,10 @@ static int memshare_child_probe(struct platform_device *pdev)
* Memshare allocation for guaranteed clients
*/
if (memblock[num_clients].guarantee) {
+ if (client_id == 1 && size > 0)
+ size += MEMSHARE_GUARD_BYTES;
rc = memshare_alloc(memsh_child->dev,
- memblock[num_clients].size,
+ size,
&memblock[num_clients]);
if (rc) {
pr_err("In %s, Unable to allocate memory for guaranteed clients, rc: %d\n",
diff --git a/drivers/soc/qcom/memshare/msm_memshare.h b/drivers/soc/qcom/memshare/msm_memshare.h
index 398907532977..c7123fb1314b 100644
--- a/drivers/soc/qcom/memshare/msm_memshare.h
+++ b/drivers/soc/qcom/memshare/msm_memshare.h
@@ -1,4 +1,4 @@
-/* Copyright (c) 2013-2016, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2013-2017, The Linux Foundation. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 and
@@ -24,6 +24,7 @@
#define GPS 0
#define CHECK 0
#define FREE 1
+#define MEMSHARE_GUARD_BYTES (4*1024)
struct mem_blocks {
/* Client Id information */
diff --git a/drivers/soc/qcom/qpnp-haptic.c b/drivers/soc/qcom/qpnp-haptic.c
index 70cf11359e97..d86f8671705a 100644
--- a/drivers/soc/qcom/qpnp-haptic.c
+++ b/drivers/soc/qcom/qpnp-haptic.c
@@ -85,6 +85,7 @@
#define QPNP_HAP_PM660_RES_CAL_PERIOD_MAX 256
#define QPNP_HAP_WF_SOURCE_MASK GENMASK(5, 4)
#define QPNP_HAP_WF_SOURCE_SHIFT 4
+#define QPNP_HAP_VMAX_OVD_BIT BIT(6)
#define QPNP_HAP_VMAX_MASK GENMASK(5, 1)
#define QPNP_HAP_VMAX_SHIFT 1
#define QPNP_HAP_VMAX_MIN_MV 116
@@ -117,6 +118,8 @@
#define QPNP_HAP_WAV_REP_MAX 128
#define QPNP_HAP_WAV_S_REP_MIN 1
#define QPNP_HAP_WAV_S_REP_MAX 8
+#define QPNP_HAP_WF_AMP_MASK GENMASK(5, 1)
+#define QPNP_HAP_WF_OVD_BIT BIT(6)
#define QPNP_HAP_BRAKE_PAT_MASK 0x3
#define QPNP_HAP_ILIM_MIN_MA 400
#define QPNP_HAP_ILIM_MAX_MA 800
@@ -135,21 +138,20 @@
#define QPNP_HAP_WAV_SINE 0
#define QPNP_HAP_WAV_SQUARE 1
#define QPNP_HAP_WAV_SAMP_LEN 8
-#define QPNP_HAP_WAV_SAMP_MAX 0x7E
+#define QPNP_HAP_WAV_SAMP_MAX 0x3E
#define QPNP_HAP_BRAKE_PAT_LEN 4
-#define QPNP_HAP_PLAY_EN 0x80
+#define QPNP_HAP_PLAY_EN_BIT BIT(7)
#define QPNP_HAP_EN_BIT BIT(7)
#define QPNP_HAP_BRAKE_MASK BIT(0)
#define QPNP_HAP_AUTO_RES_MASK BIT(7)
#define AUTO_RES_ENABLE BIT(7)
#define AUTO_RES_ERR_BIT 0x10
#define SC_FOUND_BIT 0x08
-#define SC_MAX_DURATION 5
+#define SC_MAX_COUNT 5
#define QPNP_HAP_TIMEOUT_MS_MAX 15000
#define QPNP_HAP_STR_SIZE 20
#define QPNP_HAP_MAX_RETRIES 5
-#define QPNP_HAP_CYCLS 5
#define QPNP_TEST_TIMER_MS 5
#define QPNP_HAP_TIME_REQ_FOR_BACK_EMF_GEN 20000
@@ -262,6 +264,22 @@ struct qpnp_pwm_info {
};
/*
+ * qpnp_hap_lra_ares_cfg - Haptic auto_resonance configuration
+ * @ lra_qwd_drive_duration - LRA QWD drive duration
+ * @ calibrate_at_eop - Calibrate at EOP
+ * @ lra_res_cal_period - LRA resonance calibration period
+ * @ auto_res_mode - auto resonace mode
+ * @ lra_high_z - high z option line
+ */
+struct qpnp_hap_lra_ares_cfg {
+ int lra_qwd_drive_duration;
+ int calibrate_at_eop;
+ enum qpnp_hap_high_z lra_high_z;
+ u16 lra_res_cal_period;
+ u8 auto_res_mode;
+};
+
+/*
* qpnp_hap - Haptic data structure
* @ spmi - spmi device
* @ hap_timer - hrtimer
@@ -270,6 +288,7 @@ struct qpnp_pwm_info {
* @ work - worker
* @ sc_work - worker to handle short circuit condition
* @ pwm_info - pwm info
+ * @ ares_cfg - auto resonance configuration
* @ lock - mutex lock
* @ wf_lock - mutex lock for waveform
* @ init_drive_period_code - the initial lra drive period code
@@ -281,10 +300,7 @@ struct qpnp_pwm_info {
percentage variation on the higher side.
* @ drive_period_code_min_limit - calculated drive period code with
percentage variation on the lower side
- * @ lra_res_cal_period - LRA resonance calibration period
* @ play_mode - play mode
- * @ auto_res_mode - auto resonace mode
- * @ lra_high_z - high z option line
* @ timeout_ms - max timeout in ms
* @ time_required_to_generate_back_emf_us - the time required for sufficient
back-emf to be generated for auto resonance to be successful
@@ -293,6 +309,7 @@ struct qpnp_pwm_info {
* @ sc_deb_cycles - short circuit debounce cycles
* @ int_pwm_freq_khz - internal pwm frequency in khz
* @ wave_play_rate_us - play rate for waveform
+ * @ play_time_ms - play time set by the user
* @ ext_pwm_freq_khz - external pwm frequency in khz
* @ wave_rep_cnt - waveform repeat count
* @ wave_s_rep_cnt - waveform sample repeat count
@@ -305,14 +322,12 @@ struct qpnp_pwm_info {
* @ wave_samp - array of wave samples
* @ shadow_wave_samp - shadow array of wave samples
* @ brake_pat - pattern for active breaking
- * @ reg_play - play register
- * @ lra_res_cal_period - period for resonance calibration
- * @ sc_duration - counter to determine the duration of short circuit condition
+ * @ sc_count - counter to determine the duration of short circuit condition
* @ lra_hw_auto_resonance - enable hardware auto resonance
* @ state - current state of haptics
+ * @ module_en - haptics module enable status
* @ wf_update - waveform update flag
* @ pwm_cfg_state - pwm mode configuration state
- * @ buffer_cfg_state - buffer mode configuration state
* @ en_brake - brake state
* @ sup_brake_pat - support custom brake pattern
* @ correct_lra_drive_freq - correct LRA Drive Frequency
@@ -320,6 +335,9 @@ struct qpnp_pwm_info {
* @ clk_trim_error_code - MISC clock trim error code
* @ perform_lra_auto_resonance_search - whether lra auto resonance search
* algorithm should be performed or not.
+ * @ auto_mode - Auto mode selection
+ * @ override_auto_mode_config - Flag to override auto mode configuration with
+ * user specified values through sysfs.
*/
struct qpnp_hap {
struct platform_device *pdev;
@@ -333,14 +351,12 @@ struct qpnp_hap {
struct hrtimer hap_test_timer;
struct work_struct test_work;
struct qpnp_pwm_info pwm_info;
+ struct qpnp_hap_lra_ares_cfg ares_cfg;
struct mutex lock;
struct mutex wf_lock;
spinlock_t bus_lock;
struct completion completion;
enum qpnp_hap_mode play_mode;
- enum qpnp_hap_high_z lra_high_z;
- int lra_qwd_drive_duration;
- int calibrate_at_eop;
u32 misc_clk_trim_error_reg;
u32 init_drive_period_code;
u32 timeout_ms;
@@ -350,6 +366,7 @@ struct qpnp_hap {
u32 sc_deb_cycles;
u32 int_pwm_freq_khz;
u32 wave_play_rate_us;
+ u32 play_time_ms;
u32 ext_pwm_freq_khz;
u32 wave_rep_cnt;
u32 wave_s_rep_cnt;
@@ -360,7 +377,6 @@ struct qpnp_hap {
u16 last_rate_cfg;
u16 drive_period_code_max_limit;
u16 drive_period_code_min_limit;
- u16 lra_res_cal_period;
u8 drive_period_code_max_limit_percent_variation;
u8 drive_period_code_min_limit_percent_variation;
u8 act_type;
@@ -368,23 +384,24 @@ struct qpnp_hap {
u8 wave_samp[QPNP_HAP_WAV_SAMP_LEN];
u8 shadow_wave_samp[QPNP_HAP_WAV_SAMP_LEN];
u8 brake_pat[QPNP_HAP_BRAKE_PAT_LEN];
- u8 reg_play;
- u8 sc_duration;
+ u8 sc_count;
u8 ext_pwm_dtest_line;
u8 pmic_subtype;
- u8 auto_res_mode;
u8 clk_trim_error_code;
bool lra_hw_auto_resonance;
bool vcc_pon_enabled;
bool state;
+ bool module_en;
bool manage_pon_supply;
bool wf_update;
bool pwm_cfg_state;
- bool buffer_cfg_state;
bool en_brake;
bool sup_brake_pat;
bool correct_lra_drive_freq;
bool perform_lra_auto_resonance_search;
+ bool auto_mode;
+ bool override_auto_mode_config;
+ bool play_irq_en;
};
static struct qpnp_hap *ghap;
@@ -502,36 +519,50 @@ static void qpnp_handle_sc_irq(struct work_struct *work)
/* clear short circuit register */
if (val & SC_FOUND_BIT) {
- hap->sc_duration++;
+ hap->sc_count++;
val = QPNP_HAP_SC_CLR;
qpnp_hap_write_reg(hap, QPNP_HAP_SC_CLR_REG(hap->base), val);
}
}
+#define QPNP_HAP_CYCLES 4
static int qpnp_hap_mod_enable(struct qpnp_hap *hap, bool on)
{
+ unsigned long wait_time_us;
u8 val;
int rc, i;
+ if (hap->module_en == on)
+ return 0;
+
if (!on) {
- for (i = 0; i < QPNP_HAP_MAX_RETRIES; i++) {
- /* wait for 4 cycles of play rate */
- unsigned long sleep_time =
- QPNP_HAP_CYCLS * hap->wave_play_rate_us;
+ /*
+ * Wait for 4 cycles of play rate for play time is > 20 ms and
+ * wait for play time when play time is < 20 ms. This way, there
+ * will be an improvement in waiting time polling BUSY status.
+ */
+ if (hap->play_time_ms <= 20)
+ wait_time_us = hap->play_time_ms * 1000;
+ else
+ wait_time_us = QPNP_HAP_CYCLES * hap->wave_play_rate_us;
+ for (i = 0; i < QPNP_HAP_MAX_RETRIES; i++) {
rc = qpnp_hap_read_reg(hap, QPNP_HAP_STATUS(hap->base),
&val);
+ if (rc < 0)
+ return rc;
pr_debug("HAP_STATUS=0x%x\n", val);
- /* wait for QPNP_HAP_CYCLS cycles of play rate */
+ /* wait for play_rate cycles */
if (val & QPNP_HAP_STATUS_BUSY) {
- usleep_range(sleep_time, sleep_time + 1);
+ usleep_range(wait_time_us, wait_time_us + 1);
if (hap->play_mode == QPNP_HAP_DIRECT ||
hap->play_mode == QPNP_HAP_PWM)
break;
- } else
+ } else {
break;
+ }
}
if (i >= QPNP_HAP_MAX_RETRIES)
@@ -543,27 +574,18 @@ static int qpnp_hap_mod_enable(struct qpnp_hap *hap, bool on)
if (rc < 0)
return rc;
+ hap->module_en = on;
return 0;
}
-static int qpnp_hap_play(struct qpnp_hap *hap, int on)
+static int qpnp_hap_play(struct qpnp_hap *hap, bool on)
{
u8 val;
int rc;
- val = hap->reg_play;
- if (on)
- val |= QPNP_HAP_PLAY_EN;
- else
- val &= ~QPNP_HAP_PLAY_EN;
-
+ val = on ? QPNP_HAP_PLAY_EN_BIT : 0;
rc = qpnp_hap_write_reg(hap, QPNP_HAP_PLAY_REG(hap->base), val);
- if (rc < 0)
- return rc;
-
- hap->reg_play = val;
-
- return 0;
+ return rc;
}
/* sysfs show debug registers */
@@ -624,13 +646,13 @@ static irqreturn_t qpnp_hap_sc_irq(int irq, void *_hap)
pr_debug("Short circuit detected\n");
- if (hap->sc_duration < SC_MAX_DURATION) {
+ if (hap->sc_count < SC_MAX_COUNT) {
qpnp_hap_read_reg(hap, QPNP_HAP_STATUS(hap->base), &val);
if (val & SC_FOUND_BIT)
schedule_delayed_work(&hap->sc_work,
QPNP_HAP_SC_IRQ_STATUS_DELAY);
else
- hap->sc_duration = 0;
+ hap->sc_count = 0;
} else {
/* Disable haptics module if the duration of short circuit
* exceeds the maximum limit (5 secs).
@@ -645,9 +667,11 @@ static irqreturn_t qpnp_hap_sc_irq(int irq, void *_hap)
}
/* configuration api for buffer mode */
-static int qpnp_hap_buffer_config(struct qpnp_hap *hap)
+static int qpnp_hap_buffer_config(struct qpnp_hap *hap, u8 *wave_samp,
+ bool overdrive)
{
- u8 val = 0;
+ u8 buf[QPNP_HAP_WAV_SAMP_LEN], val;
+ u8 *ptr;
int rc, i;
/* Configure the WAVE_REPEAT register */
@@ -668,16 +692,27 @@ static int qpnp_hap_buffer_config(struct qpnp_hap *hap)
if (rc)
return rc;
+ /* Don't set override bit in waveform sample for PM660 */
+ if (hap->pmic_subtype == PM660_SUBTYPE)
+ overdrive = false;
+
+ if (wave_samp)
+ ptr = wave_samp;
+ else
+ ptr = hap->wave_samp;
+
/* Configure WAVE_SAMPLE1 to WAVE_SAMPLE8 register */
- for (i = 0, val = 0; i < QPNP_HAP_WAV_SAMP_LEN; i++) {
- val = hap->wave_samp[i];
- rc = qpnp_hap_write_reg(hap,
- QPNP_HAP_WAV_S_REG_BASE(hap->base) + i, val);
- if (rc)
- return rc;
+ for (i = 0; i < QPNP_HAP_WAV_SAMP_LEN; i++) {
+ buf[i] = ptr[i] & QPNP_HAP_WF_AMP_MASK;
+ if (buf[i])
+ buf[i] |= (overdrive ? QPNP_HAP_WF_OVD_BIT : 0);
}
- hap->buffer_cfg_state = true;
+ rc = qpnp_hap_write_mult_reg(hap, QPNP_HAP_WAV_S_REG_BASE(hap->base),
+ buf, QPNP_HAP_WAV_SAMP_LEN);
+ if (rc)
+ return rc;
+
return 0;
}
@@ -736,10 +771,12 @@ static int qpnp_hap_pwm_config(struct qpnp_hap *hap)
return 0;
}
-static int qpnp_hap_lra_auto_res_config(struct qpnp_hap *hap)
+static int qpnp_hap_lra_auto_res_config(struct qpnp_hap *hap,
+ struct qpnp_hap_lra_ares_cfg *tmp_cfg)
{
+ struct qpnp_hap_lra_ares_cfg *ares_cfg;
int rc;
- u8 val, mask;
+ u8 val = 0, mask = 0;
/* disable auto resonance for ERM */
if (hap->act_type == QPNP_HAP_ERM) {
@@ -751,59 +788,73 @@ static int qpnp_hap_lra_auto_res_config(struct qpnp_hap *hap)
if (hap->lra_hw_auto_resonance) {
rc = qpnp_hap_masked_write_reg(hap,
- QPNP_HAP_PM660_HW_AUTO_RES_MODE_BIT,
QPNP_HAP_AUTO_RES_CTRL(hap->base),
+ QPNP_HAP_PM660_HW_AUTO_RES_MODE_BIT,
QPNP_HAP_PM660_HW_AUTO_RES_MODE_BIT);
if (rc)
return rc;
}
- if (hap->lra_res_cal_period < QPNP_HAP_RES_CAL_PERIOD_MIN)
- hap->lra_res_cal_period = QPNP_HAP_RES_CAL_PERIOD_MIN;
+ if (tmp_cfg)
+ ares_cfg = tmp_cfg;
+ else
+ ares_cfg = &hap->ares_cfg;
+
+ if (ares_cfg->lra_res_cal_period < QPNP_HAP_RES_CAL_PERIOD_MIN)
+ ares_cfg->lra_res_cal_period = QPNP_HAP_RES_CAL_PERIOD_MIN;
if (hap->pmic_subtype == PM660_SUBTYPE) {
- if (hap->lra_res_cal_period >
+ if (ares_cfg->lra_res_cal_period >
QPNP_HAP_PM660_RES_CAL_PERIOD_MAX)
- hap->lra_res_cal_period =
+ ares_cfg->lra_res_cal_period =
QPNP_HAP_PM660_RES_CAL_PERIOD_MAX;
- if (hap->auto_res_mode == QPNP_HAP_PM660_AUTO_RES_QWD)
- hap->lra_res_cal_period = 0;
+ if (ares_cfg->auto_res_mode == QPNP_HAP_PM660_AUTO_RES_QWD)
+ ares_cfg->lra_res_cal_period = 0;
+
+ if (ares_cfg->lra_res_cal_period)
+ val = ilog2(ares_cfg->lra_res_cal_period /
+ QPNP_HAP_RES_CAL_PERIOD_MIN) + 1;
} else {
- if (hap->lra_res_cal_period > QPNP_HAP_RES_CAL_PERIOD_MAX)
- hap->lra_res_cal_period = QPNP_HAP_RES_CAL_PERIOD_MAX;
- }
+ if (ares_cfg->lra_res_cal_period > QPNP_HAP_RES_CAL_PERIOD_MAX)
+ ares_cfg->lra_res_cal_period =
+ QPNP_HAP_RES_CAL_PERIOD_MAX;
- val = mask = 0;
- if (hap->lra_res_cal_period)
- val = ilog2(hap->lra_res_cal_period /
- QPNP_HAP_RES_CAL_PERIOD_MIN);
+ if (ares_cfg->lra_res_cal_period)
+ val = ilog2(ares_cfg->lra_res_cal_period /
+ QPNP_HAP_RES_CAL_PERIOD_MIN);
+ }
if (hap->pmic_subtype == PM660_SUBTYPE) {
- val |= hap->auto_res_mode <<
+ val |= ares_cfg->auto_res_mode <<
QPNP_HAP_PM660_AUTO_RES_MODE_SHIFT;
mask = QPNP_HAP_PM660_AUTO_RES_MODE_BIT;
- val |= hap->lra_high_z <<
+ val |= ares_cfg->lra_high_z <<
QPNP_HAP_PM660_CALIBRATE_DURATION_SHIFT;
mask |= QPNP_HAP_PM660_CALIBRATE_DURATION_MASK;
- if (hap->lra_qwd_drive_duration != -EINVAL) {
- val |= hap->lra_qwd_drive_duration <<
+ if (ares_cfg->lra_qwd_drive_duration != -EINVAL) {
+ val |= ares_cfg->lra_qwd_drive_duration <<
QPNP_HAP_PM660_QWD_DRIVE_DURATION_SHIFT;
mask |= QPNP_HAP_PM660_QWD_DRIVE_DURATION_BIT;
}
- if (hap->calibrate_at_eop != -EINVAL) {
- val |= hap->calibrate_at_eop <<
+ if (ares_cfg->calibrate_at_eop != -EINVAL) {
+ val |= ares_cfg->calibrate_at_eop <<
QPNP_HAP_PM660_CALIBRATE_AT_EOP_SHIFT;
mask |= QPNP_HAP_PM660_CALIBRATE_AT_EOP_BIT;
}
mask |= QPNP_HAP_PM660_LRA_RES_CAL_PER_MASK;
} else {
- val |= (hap->auto_res_mode << QPNP_HAP_AUTO_RES_MODE_SHIFT);
- val |= (hap->lra_high_z << QPNP_HAP_LRA_HIGH_Z_SHIFT);
+ val |= (ares_cfg->auto_res_mode <<
+ QPNP_HAP_AUTO_RES_MODE_SHIFT);
+ val |= (ares_cfg->lra_high_z << QPNP_HAP_LRA_HIGH_Z_SHIFT);
mask = QPNP_HAP_AUTO_RES_MODE_MASK | QPNP_HAP_LRA_HIGH_Z_MASK |
QPNP_HAP_LRA_RES_CAL_PER_MASK;
}
+ pr_debug("mode: %d hi_z period: %d cal_period: %d\n",
+ ares_cfg->auto_res_mode, ares_cfg->lra_high_z,
+ ares_cfg->lra_res_cal_period);
+
rc = qpnp_hap_masked_write_reg(hap,
QPNP_HAP_LRA_AUTO_RES_REG(hap->base), mask, val);
return rc;
@@ -822,19 +873,29 @@ static int qpnp_hap_play_mode_config(struct qpnp_hap *hap)
}
/* configuration api for max voltage */
-static int qpnp_hap_vmax_config(struct qpnp_hap *hap)
+static int qpnp_hap_vmax_config(struct qpnp_hap *hap, int vmax_mv,
+ bool overdrive)
{
u8 val = 0;
int rc;
- if (hap->vmax_mv < QPNP_HAP_VMAX_MIN_MV)
- hap->vmax_mv = QPNP_HAP_VMAX_MIN_MV;
- else if (hap->vmax_mv > QPNP_HAP_VMAX_MAX_MV)
- hap->vmax_mv = QPNP_HAP_VMAX_MAX_MV;
+ if (vmax_mv < 0)
+ return -EINVAL;
- val = (hap->vmax_mv / QPNP_HAP_VMAX_MIN_MV) << QPNP_HAP_VMAX_SHIFT;
+ /* Allow setting override bit in VMAX_CFG only for PM660 */
+ if (hap->pmic_subtype != PM660_SUBTYPE)
+ overdrive = false;
+
+ if (vmax_mv < QPNP_HAP_VMAX_MIN_MV)
+ vmax_mv = QPNP_HAP_VMAX_MIN_MV;
+ else if (vmax_mv > QPNP_HAP_VMAX_MAX_MV)
+ vmax_mv = QPNP_HAP_VMAX_MAX_MV;
+
+ val = (vmax_mv / QPNP_HAP_VMAX_MIN_MV) << QPNP_HAP_VMAX_SHIFT;
+ if (overdrive)
+ val |= QPNP_HAP_VMAX_OVD_BIT;
rc = qpnp_hap_masked_write_reg(hap, QPNP_HAP_VMAX_REG(hap->base),
- QPNP_HAP_VMAX_MASK, val);
+ QPNP_HAP_VMAX_MASK | QPNP_HAP_VMAX_OVD_BIT, val);
return rc;
}
@@ -912,6 +973,41 @@ static int qpnp_hap_int_pwm_config(struct qpnp_hap *hap)
return rc;
}
+static int qpnp_hap_brake_config(struct qpnp_hap *hap, u8 *brake_pat)
+{
+ int rc, i;
+ u32 temp;
+ u8 *pat_ptr, val;
+
+ if (!hap->en_brake)
+ return 0;
+
+ /* Configure BRAKE register */
+ rc = qpnp_hap_masked_write_reg(hap, QPNP_HAP_EN_CTL2_REG(hap->base),
+ QPNP_HAP_BRAKE_MASK, (u8)hap->en_brake);
+ if (rc)
+ return rc;
+
+ if (!brake_pat)
+ pat_ptr = hap->brake_pat;
+ else
+ pat_ptr = brake_pat;
+
+ if (hap->sup_brake_pat) {
+ for (i = QPNP_HAP_BRAKE_PAT_LEN - 1, val = 0; i >= 0; i--) {
+ pat_ptr[i] &= QPNP_HAP_BRAKE_PAT_MASK;
+ temp = i << 1;
+ val |= pat_ptr[i] << temp;
+ }
+ rc = qpnp_hap_write_reg(hap, QPNP_HAP_BRAKE_REG(hap->base),
+ val);
+ if (rc)
+ return rc;
+ }
+
+ return 0;
+}
+
/* DT parsing api for buffer mode */
static int qpnp_hap_parse_buffer_dt(struct qpnp_hap *hap)
{
@@ -920,6 +1016,9 @@ static int qpnp_hap_parse_buffer_dt(struct qpnp_hap *hap)
u32 temp;
int rc, i;
+ if (hap->wave_rep_cnt > 0 || hap->wave_s_rep_cnt > 0)
+ return 0;
+
hap->wave_rep_cnt = QPNP_HAP_WAV_REP_MIN;
rc = of_property_read_u32(pdev->dev.of_node,
"qcom,wave-rep-cnt", &temp);
@@ -1251,6 +1350,25 @@ static ssize_t qpnp_hap_wf_s_rep_store(struct device *dev,
return count;
}
+static int parse_string(const char *in_buf, char *out_buf)
+{
+ int i;
+
+ if (snprintf(out_buf, QPNP_HAP_STR_SIZE, "%s", in_buf)
+ > QPNP_HAP_STR_SIZE)
+ return -EINVAL;
+
+ for (i = 0; i < strlen(out_buf); i++) {
+ if (out_buf[i] == ' ' || out_buf[i] == '\n' ||
+ out_buf[i] == '\t') {
+ out_buf[i] = '\0';
+ break;
+ }
+ }
+
+ return 0;
+}
+
/* sysfs store function for play mode*/
static ssize_t qpnp_hap_play_mode_store(struct device *dev,
struct device_attribute *attr, const char *buf, size_t count)
@@ -1259,17 +1377,12 @@ static ssize_t qpnp_hap_play_mode_store(struct device *dev,
struct qpnp_hap *hap = container_of(timed_dev, struct qpnp_hap,
timed_dev);
char str[QPNP_HAP_STR_SIZE + 1];
- int rc = 0, temp, old_mode, i;
+ int rc = 0, temp, old_mode;
- if (snprintf(str, QPNP_HAP_STR_SIZE, "%s", buf) > QPNP_HAP_STR_SIZE)
- return -EINVAL;
+ rc = parse_string(buf, str);
+ if (rc < 0)
+ return rc;
- for (i = 0; i < strlen(str); i++) {
- if (str[i] == ' ' || str[i] == '\n' || str[i] == '\t') {
- str[i] = '\0';
- break;
- }
- }
if (strcmp(str, "buffer") == 0)
temp = QPNP_HAP_BUFFER;
else if (strcmp(str, "direct") == 0)
@@ -1284,10 +1397,10 @@ static ssize_t qpnp_hap_play_mode_store(struct device *dev,
if (temp == hap->play_mode)
return count;
- if (temp == QPNP_HAP_BUFFER && !hap->buffer_cfg_state) {
+ if (temp == QPNP_HAP_BUFFER) {
rc = qpnp_hap_parse_buffer_dt(hap);
if (!rc)
- rc = qpnp_hap_buffer_config(hap);
+ rc = qpnp_hap_buffer_config(hap, NULL, false);
} else if (temp == QPNP_HAP_PWM && !hap->pwm_cfg_state) {
rc = qpnp_hap_parse_pwm_dt(hap);
if (!rc)
@@ -1436,6 +1549,245 @@ static ssize_t qpnp_hap_ramp_test_data_show(struct device *dev,
}
+static ssize_t qpnp_hap_auto_res_mode_show(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ struct timed_output_dev *timed_dev = dev_get_drvdata(dev);
+ struct qpnp_hap *hap = container_of(timed_dev, struct qpnp_hap,
+ timed_dev);
+ char *str;
+
+ if (hap->pmic_subtype == PM660_SUBTYPE) {
+ switch (hap->ares_cfg.auto_res_mode) {
+ case QPNP_HAP_PM660_AUTO_RES_ZXD:
+ str = "ZXD";
+ break;
+ case QPNP_HAP_PM660_AUTO_RES_QWD:
+ str = "QWD";
+ break;
+ default:
+ str = "None";
+ break;
+ }
+ } else {
+ switch (hap->ares_cfg.auto_res_mode) {
+ case QPNP_HAP_AUTO_RES_NONE:
+ str = "None";
+ break;
+ case QPNP_HAP_AUTO_RES_ZXD:
+ str = "ZXD";
+ break;
+ case QPNP_HAP_AUTO_RES_QWD:
+ str = "QWD";
+ break;
+ case QPNP_HAP_AUTO_RES_MAX_QWD:
+ str = "MAX_QWD";
+ break;
+ case QPNP_HAP_AUTO_RES_ZXD_EOP:
+ str = "ZXD_EOP";
+ break;
+ default:
+ str = "None";
+ break;
+ }
+ }
+
+ return snprintf(buf, PAGE_SIZE, "%s\n", str);
+}
+
+static ssize_t qpnp_hap_auto_res_mode_store(struct device *dev,
+ struct device_attribute *attr, const char *buf, size_t count)
+{
+ struct timed_output_dev *timed_dev = dev_get_drvdata(dev);
+ struct qpnp_hap *hap = container_of(timed_dev, struct qpnp_hap,
+ timed_dev);
+ char str[QPNP_HAP_STR_SIZE + 1];
+ int rc = 0, temp;
+
+ rc = parse_string(buf, str);
+ if (rc < 0)
+ return rc;
+
+ if (hap->pmic_subtype == PM660_SUBTYPE) {
+ if (strcmp(str, "ZXD") == 0 ||
+ strcmp(str, "zxd") == 0)
+ temp = QPNP_HAP_PM660_AUTO_RES_ZXD;
+ else if (strcmp(str, "QWD") == 0 ||
+ strcmp(str, "qwd") == 0)
+ temp = QPNP_HAP_PM660_AUTO_RES_QWD;
+ else {
+ pr_err("Should be ZXD or QWD\n");
+ return -EINVAL;
+ }
+ } else {
+ if (strcmp(str, "None") == 0)
+ temp = QPNP_HAP_AUTO_RES_NONE;
+ else if (strcmp(str, "ZXD") == 0 ||
+ strcmp(str, "zxd") == 0)
+ temp = QPNP_HAP_AUTO_RES_ZXD;
+ else if (strcmp(str, "QWD") == 0 ||
+ strcmp(str, "qwd") == 0)
+ temp = QPNP_HAP_AUTO_RES_QWD;
+ else if (strcmp(str, "ZXD_EOP") == 0 ||
+ strcmp(str, "zxd_eop") == 0)
+ temp = QPNP_HAP_AUTO_RES_ZXD_EOP;
+ else if (strcmp(str, "MAX_QWD") == 0 ||
+ strcmp(str, "max_qwd") == 0)
+ temp = QPNP_HAP_AUTO_RES_MAX_QWD;
+ else {
+ pr_err("Should be None or ZXD or QWD or ZXD_EOP or MAX_QWD\n");
+ return -EINVAL;
+ }
+ }
+
+ hap->ares_cfg.auto_res_mode = temp;
+ return count;
+}
+
+static ssize_t qpnp_hap_hi_z_period_show(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ struct timed_output_dev *timed_dev = dev_get_drvdata(dev);
+ struct qpnp_hap *hap = container_of(timed_dev, struct qpnp_hap,
+ timed_dev);
+ char *str;
+
+ switch (hap->ares_cfg.lra_high_z) {
+ case QPNP_HAP_LRA_HIGH_Z_NONE:
+ str = "high_z_none";
+ break;
+ case QPNP_HAP_LRA_HIGH_Z_OPT1:
+ str = "high_z_opt1";
+ break;
+ case QPNP_HAP_LRA_HIGH_Z_OPT2:
+ str = "high_z_opt2";
+ break;
+ case QPNP_HAP_LRA_HIGH_Z_OPT3:
+ str = "high_z_opt3";
+ break;
+ }
+
+ return snprintf(buf, PAGE_SIZE, "%s\n", str);
+}
+
+static ssize_t qpnp_hap_hi_z_period_store(struct device *dev,
+ struct device_attribute *attr, const char *buf, size_t count)
+{
+ struct timed_output_dev *timed_dev = dev_get_drvdata(dev);
+ struct qpnp_hap *hap = container_of(timed_dev, struct qpnp_hap,
+ timed_dev);
+ int data, rc;
+
+ rc = kstrtoint(buf, 10, &data);
+ if (rc)
+ return rc;
+
+ if (data < QPNP_HAP_LRA_HIGH_Z_NONE
+ || data > QPNP_HAP_LRA_HIGH_Z_OPT3) {
+ pr_err("Invalid high Z configuration\n");
+ return -EINVAL;
+ }
+
+ hap->ares_cfg.lra_high_z = data;
+ return count;
+}
+
+static ssize_t qpnp_hap_calib_period_show(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ struct timed_output_dev *timed_dev = dev_get_drvdata(dev);
+ struct qpnp_hap *hap = container_of(timed_dev, struct qpnp_hap,
+ timed_dev);
+
+ return snprintf(buf, PAGE_SIZE, "%d\n",
+ hap->ares_cfg.lra_res_cal_period);
+}
+
+static ssize_t qpnp_hap_calib_period_store(struct device *dev,
+ struct device_attribute *attr, const char *buf, size_t count)
+{
+ struct timed_output_dev *timed_dev = dev_get_drvdata(dev);
+ struct qpnp_hap *hap = container_of(timed_dev, struct qpnp_hap,
+ timed_dev);
+ int data, rc;
+
+ rc = kstrtoint(buf, 10, &data);
+ if (rc)
+ return rc;
+
+ if (data < QPNP_HAP_RES_CAL_PERIOD_MIN) {
+ pr_err("Invalid auto resonance calibration period\n");
+ return -EINVAL;
+ }
+
+ if (hap->pmic_subtype == PM660_SUBTYPE) {
+ if (data > QPNP_HAP_PM660_RES_CAL_PERIOD_MAX) {
+ pr_err("Invalid auto resonance calibration period\n");
+ return -EINVAL;
+ }
+ } else {
+ if (data > QPNP_HAP_RES_CAL_PERIOD_MAX) {
+ pr_err("Invalid auto resonance calibration period\n");
+ return -EINVAL;
+ }
+ }
+
+ hap->ares_cfg.lra_res_cal_period = data;
+ return count;
+}
+
+static ssize_t qpnp_hap_override_auto_mode_show(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ struct timed_output_dev *timed_dev = dev_get_drvdata(dev);
+ struct qpnp_hap *hap = container_of(timed_dev, struct qpnp_hap,
+ timed_dev);
+
+ return snprintf(buf, PAGE_SIZE, "%d\n", hap->override_auto_mode_config);
+}
+
+static ssize_t qpnp_hap_override_auto_mode_store(struct device *dev,
+ struct device_attribute *attr, const char *buf, size_t count)
+{
+ struct timed_output_dev *timed_dev = dev_get_drvdata(dev);
+ struct qpnp_hap *hap = container_of(timed_dev, struct qpnp_hap,
+ timed_dev);
+ int data, rc;
+
+ rc = kstrtoint(buf, 10, &data);
+ if (rc)
+ return rc;
+
+ hap->override_auto_mode_config = data;
+ return count;
+}
+
+static ssize_t qpnp_hap_vmax_show(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ struct timed_output_dev *timed_dev = dev_get_drvdata(dev);
+ struct qpnp_hap *hap = container_of(timed_dev, struct qpnp_hap,
+ timed_dev);
+
+ return snprintf(buf, PAGE_SIZE, "%d\n", hap->vmax_mv);
+}
+
+static ssize_t qpnp_hap_vmax_store(struct device *dev,
+ struct device_attribute *attr, const char *buf, size_t count)
+{
+ struct timed_output_dev *timed_dev = dev_get_drvdata(dev);
+ struct qpnp_hap *hap = container_of(timed_dev, struct qpnp_hap,
+ timed_dev);
+ int data, rc;
+
+ rc = kstrtoint(buf, 10, &data);
+ if (rc)
+ return rc;
+
+ hap->vmax_mv = data;
+ return count;
+}
+
/* sysfs attributes */
static struct device_attribute qpnp_hap_attrs[] = {
__ATTR(wf_s0, 0664, qpnp_hap_wf_s0_show, qpnp_hap_wf_s0_store),
@@ -1457,6 +1809,16 @@ static struct device_attribute qpnp_hap_attrs[] = {
qpnp_hap_ramp_test_data_store),
__ATTR(min_max_test, 0664, qpnp_hap_min_max_test_data_show,
qpnp_hap_min_max_test_data_store),
+ __ATTR(auto_res_mode, 0664, qpnp_hap_auto_res_mode_show,
+ qpnp_hap_auto_res_mode_store),
+ __ATTR(high_z_period, 0664, qpnp_hap_hi_z_period_show,
+ qpnp_hap_hi_z_period_store),
+ __ATTR(calib_period, 0664, qpnp_hap_calib_period_show,
+ qpnp_hap_calib_period_store),
+ __ATTR(override_auto_mode_config, 0664,
+ qpnp_hap_override_auto_mode_show,
+ qpnp_hap_override_auto_mode_store),
+ __ATTR(vmax_mv, 0664, qpnp_hap_vmax_show, qpnp_hap_vmax_store),
};
static int calculate_lra_code(struct qpnp_hap *hap)
@@ -1515,9 +1877,47 @@ static int calculate_lra_code(struct qpnp_hap *hap)
static int qpnp_hap_auto_res_enable(struct qpnp_hap *hap, int enable)
{
int rc = 0;
- u8 val;
+ u32 back_emf_delay_us = hap->time_required_to_generate_back_emf_us;
+ u8 val, auto_res_mode_qwd;
+
+ if (hap->act_type != QPNP_HAP_LRA)
+ return 0;
+
+ if (hap->pmic_subtype == PM660_SUBTYPE)
+ auto_res_mode_qwd = (hap->ares_cfg.auto_res_mode ==
+ QPNP_HAP_PM660_AUTO_RES_QWD);
+ else
+ auto_res_mode_qwd = (hap->ares_cfg.auto_res_mode ==
+ QPNP_HAP_AUTO_RES_QWD);
+
+ /*
+ * Do not enable auto resonance if auto mode is enabled and auto
+ * resonance mode is QWD, meaning short pattern.
+ */
+ if (hap->auto_mode && auto_res_mode_qwd && enable) {
+ pr_debug("auto_mode enabled, not enabling auto_res\n");
+ return 0;
+ }
+
+ if (!hap->correct_lra_drive_freq && !auto_res_mode_qwd) {
+ pr_debug("correct_lra_drive_freq: %d auto_res_mode_qwd: %d\n",
+ hap->correct_lra_drive_freq, auto_res_mode_qwd);
+ return 0;
+ }
val = enable ? AUTO_RES_ENABLE : 0;
+ /*
+ * For auto resonance detection to work properly, sufficient back-emf
+ * has to be generated. In general, back-emf takes some time to build
+ * up. When the auto resonance mode is chosen as QWD, high-z will be
+ * applied for every LRA cycle and hence there won't be enough back-emf
+ * at the start-up. Hence, the motor needs to vibrate for few LRA cycles
+ * after the PLAY bit is asserted. Enable the auto resonance after
+ * 'time_required_to_generate_back_emf_us' is completed.
+ */
+ if (enable)
+ usleep_range(back_emf_delay_us, back_emf_delay_us + 1);
+
if (hap->pmic_subtype == PM660_SUBTYPE)
rc = qpnp_hap_masked_write_reg(hap,
QPNP_HAP_AUTO_RES_CTRL(hap->base),
@@ -1534,6 +1934,7 @@ static int qpnp_hap_auto_res_enable(struct qpnp_hap *hap, int enable)
else
hap->status_flags &= ~AUTO_RESONANCE_ENABLED;
+ pr_debug("auto_res %sabled\n", enable ? "en" : "dis");
return rc;
}
@@ -1617,65 +2018,57 @@ static enum hrtimer_restart detect_auto_res_error(struct hrtimer *timer)
return HRTIMER_RESTART;
}
+static bool is_sw_lra_auto_resonance_control(struct qpnp_hap *hap)
+{
+ if (hap->act_type != QPNP_HAP_LRA)
+ return false;
+
+ if (hap->lra_hw_auto_resonance)
+ return false;
+
+ if (!hap->correct_lra_drive_freq)
+ return false;
+
+ if (hap->auto_mode && hap->play_mode == QPNP_HAP_BUFFER)
+ return false;
+
+ return true;
+}
+
/* set api for haptics */
-static int qpnp_hap_set(struct qpnp_hap *hap, int on)
+static int qpnp_hap_set(struct qpnp_hap *hap, bool on)
{
- u8 auto_res_mode_qwd;
int rc = 0;
unsigned long timeout_ns = POLL_TIME_AUTO_RES_ERR_NS;
- u32 back_emf_delay_us = hap->time_required_to_generate_back_emf_us;
if (hap->play_mode == QPNP_HAP_PWM) {
- if (on)
+ if (on) {
rc = pwm_enable(hap->pwm_info.pwm_dev);
- else
+ if (rc < 0)
+ return rc;
+ } else {
pwm_disable(hap->pwm_info.pwm_dev);
+ }
} else if (hap->play_mode == QPNP_HAP_BUFFER ||
hap->play_mode == QPNP_HAP_DIRECT) {
if (on) {
- /*
- * For auto resonance detection to work properly,
- * sufficient back-emf has to be generated. In general,
- * back-emf takes some time to build up. When the auto
- * resonance mode is chosen as QWD, high-z will be
- * applied for every LRA cycle and hence there won't be
- * enough back-emf at the start-up. Hence, the motor
- * needs to vibrate for few LRA cycles after the PLAY
- * bit is asserted. So disable the auto resonance here
- * and enable it after the sleep of
- * 'time_required_to_generate_back_emf_us' is completed.
- */
- if (hap->pmic_subtype == PM660_SUBTYPE)
- auto_res_mode_qwd = (hap->auto_res_mode ==
- QPNP_HAP_PM660_AUTO_RES_QWD);
- else
- auto_res_mode_qwd = (hap->auto_res_mode ==
- QPNP_HAP_AUTO_RES_QWD);
-
- if ((hap->act_type == QPNP_HAP_LRA) &&
- (hap->correct_lra_drive_freq ||
- auto_res_mode_qwd))
- qpnp_hap_auto_res_enable(hap, 0);
+ rc = qpnp_hap_auto_res_enable(hap, 0);
+ if (rc < 0)
+ return rc;
rc = qpnp_hap_mod_enable(hap, on);
if (rc < 0)
return rc;
rc = qpnp_hap_play(hap, on);
+ if (rc < 0)
+ return rc;
- if ((hap->act_type == QPNP_HAP_LRA) &&
- (hap->correct_lra_drive_freq ||
- auto_res_mode_qwd)) {
- usleep_range(back_emf_delay_us,
- (back_emf_delay_us + 1));
+ rc = qpnp_hap_auto_res_enable(hap, 1);
+ if (rc < 0)
+ return rc;
- rc = qpnp_hap_auto_res_enable(hap, 1);
- if (rc < 0)
- return rc;
- }
- if (hap->act_type == QPNP_HAP_LRA &&
- hap->correct_lra_drive_freq &&
- !hap->lra_hw_auto_resonance) {
+ if (is_sw_lra_auto_resonance_control(hap)) {
/*
* Start timer to poll Auto Resonance error bit
*/
@@ -1683,7 +2076,7 @@ static int qpnp_hap_set(struct qpnp_hap *hap, int on)
hrtimer_cancel(&hap->auto_res_err_poll_timer);
hrtimer_start(&hap->auto_res_err_poll_timer,
ktime_set(0, timeout_ns),
- HRTIMER_MODE_REL);
+ HRTIMER_MODE_REL);
mutex_unlock(&hap->lock);
}
} else {
@@ -1691,54 +2084,182 @@ static int qpnp_hap_set(struct qpnp_hap *hap, int on)
if (rc < 0)
return rc;
- if (hap->act_type == QPNP_HAP_LRA &&
- hap->correct_lra_drive_freq &&
- (hap->status_flags & AUTO_RESONANCE_ENABLED) &&
- !hap->lra_hw_auto_resonance) {
+ if (is_sw_lra_auto_resonance_control(hap) &&
+ (hap->status_flags & AUTO_RESONANCE_ENABLED))
update_lra_frequency(hap);
- }
rc = qpnp_hap_mod_enable(hap, on);
- if (hap->act_type == QPNP_HAP_LRA &&
- hap->correct_lra_drive_freq &&
- !hap->lra_hw_auto_resonance) {
+ if (rc < 0)
+ return rc;
+
+ if (is_sw_lra_auto_resonance_control(hap))
hrtimer_cancel(&hap->auto_res_err_poll_timer);
- }
}
}
return rc;
}
+static int qpnp_hap_auto_mode_config(struct qpnp_hap *hap, int time_ms)
+{
+ struct qpnp_hap_lra_ares_cfg ares_cfg;
+ enum qpnp_hap_mode old_play_mode;
+ u8 old_ares_mode;
+ u8 brake_pat[QPNP_HAP_BRAKE_PAT_LEN] = {0};
+ u8 wave_samp[QPNP_HAP_WAV_SAMP_LEN] = {0};
+ int rc, vmax_mv;
+
+ /* For now, this is for LRA only */
+ if (hap->act_type == QPNP_HAP_ERM)
+ return 0;
+
+ old_ares_mode = hap->ares_cfg.auto_res_mode;
+ old_play_mode = hap->play_mode;
+ pr_debug("auto_mode, time_ms: %d\n", time_ms);
+ if (time_ms <= 20) {
+ wave_samp[0] = QPNP_HAP_WAV_SAMP_MAX;
+ wave_samp[1] = QPNP_HAP_WAV_SAMP_MAX;
+ if (time_ms > 15)
+ wave_samp[2] = QPNP_HAP_WAV_SAMP_MAX;
+
+ /* short pattern */
+ rc = qpnp_hap_parse_buffer_dt(hap);
+ if (!rc)
+ rc = qpnp_hap_buffer_config(hap, wave_samp, true);
+ if (rc < 0) {
+ pr_err("Error in configuring buffer mode %d\n",
+ rc);
+ return rc;
+ }
+
+ ares_cfg.lra_high_z = QPNP_HAP_LRA_HIGH_Z_OPT1;
+ ares_cfg.lra_res_cal_period = QPNP_HAP_RES_CAL_PERIOD_MIN;
+ if (hap->pmic_subtype == PM660_SUBTYPE) {
+ ares_cfg.auto_res_mode =
+ QPNP_HAP_PM660_AUTO_RES_QWD;
+ ares_cfg.lra_qwd_drive_duration = 0;
+ ares_cfg.calibrate_at_eop = 0;
+ } else {
+ ares_cfg.auto_res_mode = QPNP_HAP_AUTO_RES_QWD;
+ ares_cfg.lra_qwd_drive_duration = -EINVAL;
+ ares_cfg.calibrate_at_eop = -EINVAL;
+ }
+
+ vmax_mv = QPNP_HAP_VMAX_MAX_MV;
+ rc = qpnp_hap_vmax_config(hap, vmax_mv, true);
+ if (rc < 0)
+ return rc;
+
+ rc = qpnp_hap_brake_config(hap, brake_pat);
+ if (rc < 0)
+ return rc;
+
+ /* enable play_irq for buffer mode */
+ if (hap->play_irq >= 0 && !hap->play_irq_en) {
+ enable_irq(hap->play_irq);
+ hap->play_irq_en = true;
+ }
+
+ hap->play_mode = QPNP_HAP_BUFFER;
+ hap->wave_shape = QPNP_HAP_WAV_SQUARE;
+ } else {
+ /* long pattern */
+ ares_cfg.lra_high_z = QPNP_HAP_LRA_HIGH_Z_OPT1;
+ if (hap->pmic_subtype == PM660_SUBTYPE) {
+ ares_cfg.auto_res_mode =
+ QPNP_HAP_PM660_AUTO_RES_ZXD;
+ ares_cfg.lra_res_cal_period =
+ QPNP_HAP_PM660_RES_CAL_PERIOD_MAX;
+ ares_cfg.lra_qwd_drive_duration = 0;
+ ares_cfg.calibrate_at_eop = 1;
+ } else {
+ ares_cfg.auto_res_mode = QPNP_HAP_AUTO_RES_ZXD_EOP;
+ ares_cfg.lra_res_cal_period =
+ QPNP_HAP_RES_CAL_PERIOD_MAX;
+ ares_cfg.lra_qwd_drive_duration = -EINVAL;
+ ares_cfg.calibrate_at_eop = -EINVAL;
+ }
+
+ vmax_mv = hap->vmax_mv;
+ rc = qpnp_hap_vmax_config(hap, vmax_mv, false);
+ if (rc < 0)
+ return rc;
+
+ brake_pat[0] = 0x3;
+ rc = qpnp_hap_brake_config(hap, brake_pat);
+ if (rc < 0)
+ return rc;
+
+ /* enable play_irq for direct mode */
+ if (hap->play_irq >= 0 && hap->play_irq_en) {
+ disable_irq(hap->play_irq);
+ hap->play_irq_en = false;
+ }
+
+ hap->play_mode = QPNP_HAP_DIRECT;
+ hap->wave_shape = QPNP_HAP_WAV_SINE;
+ }
+
+ if (hap->override_auto_mode_config) {
+ rc = qpnp_hap_lra_auto_res_config(hap, NULL);
+ } else {
+ hap->ares_cfg.auto_res_mode = ares_cfg.auto_res_mode;
+ rc = qpnp_hap_lra_auto_res_config(hap, &ares_cfg);
+ }
+
+ if (rc < 0) {
+ hap->ares_cfg.auto_res_mode = old_ares_mode;
+ return rc;
+ }
+
+ rc = qpnp_hap_play_mode_config(hap);
+ if (rc < 0) {
+ hap->play_mode = old_play_mode;
+ return rc;
+ }
+
+ rc = qpnp_hap_masked_write_reg(hap, QPNP_HAP_CFG2_REG(hap->base),
+ QPNP_HAP_WAV_SHAPE_MASK, hap->wave_shape);
+ if (rc < 0)
+ return rc;
+
+ return 0;
+}
+
/* enable interface from timed output class */
-static void qpnp_hap_td_enable(struct timed_output_dev *dev, int value)
+static void qpnp_hap_td_enable(struct timed_output_dev *dev, int time_ms)
{
struct qpnp_hap *hap = container_of(dev, struct qpnp_hap,
timed_dev);
+ int rc;
- mutex_lock(&hap->lock);
+ if (time_ms <= 0)
+ return;
- if (hap->act_type == QPNP_HAP_LRA &&
- hap->correct_lra_drive_freq &&
- !hap->lra_hw_auto_resonance)
+ if (time_ms < 10)
+ time_ms = 10;
+
+ mutex_lock(&hap->lock);
+ if (is_sw_lra_auto_resonance_control(hap))
hrtimer_cancel(&hap->auto_res_err_poll_timer);
hrtimer_cancel(&hap->hap_timer);
- if (value == 0) {
- if (hap->state == 0) {
+ if (hap->auto_mode) {
+ rc = qpnp_hap_auto_mode_config(hap, time_ms);
+ if (rc < 0) {
+ pr_err("Unable to do auto mode config\n");
mutex_unlock(&hap->lock);
return;
}
- hap->state = 0;
- } else {
- value = (value > hap->timeout_ms ?
- hap->timeout_ms : value);
- hap->state = 1;
- hrtimer_start(&hap->hap_timer,
- ktime_set(value / 1000, (value % 1000) * 1000000),
- HRTIMER_MODE_REL);
}
+
+ time_ms = (time_ms > hap->timeout_ms ? hap->timeout_ms : time_ms);
+ hap->play_time_ms = time_ms;
+ hap->state = 1;
+ hrtimer_start(&hap->hap_timer,
+ ktime_set(time_ms / 1000, (time_ms % 1000) * 1000000),
+ HRTIMER_MODE_REL);
mutex_unlock(&hap->lock);
schedule_work(&hap->work);
}
@@ -1824,7 +2345,7 @@ static void qpnp_hap_worker(struct work_struct *work)
/* Disable haptics module if the duration of short circuit
* exceeds the maximum limit (5 secs).
*/
- if (hap->sc_duration == SC_MAX_DURATION) {
+ if (hap->sc_count >= SC_MAX_COUNT) {
rc = qpnp_hap_write_reg(hap, QPNP_HAP_EN_CTL_REG(hap->base),
val);
} else {
@@ -1890,7 +2411,7 @@ static int qpnp_haptic_suspend(struct device *dev)
hrtimer_cancel(&hap->hap_timer);
cancel_work_sync(&hap->work);
/* turn-off haptic */
- qpnp_hap_set(hap, 0);
+ qpnp_hap_set(hap, false);
return 0;
}
@@ -1902,8 +2423,7 @@ static SIMPLE_DEV_PM_OPS(qpnp_haptic_pm_ops, qpnp_haptic_suspend, NULL);
static int qpnp_hap_config(struct qpnp_hap *hap)
{
u8 val = 0;
- u32 temp;
- int rc, i;
+ int rc;
/*
* This denotes the percentage error in rc clock multiplied by 10
@@ -1917,7 +2437,7 @@ static int qpnp_hap_config(struct qpnp_hap *hap)
return rc;
/* Configure auto resonance parameters */
- rc = qpnp_hap_lra_auto_res_config(hap);
+ rc = qpnp_hap_lra_auto_res_config(hap, NULL);
if (rc)
return rc;
@@ -1927,7 +2447,7 @@ static int qpnp_hap_config(struct qpnp_hap *hap)
return rc;
/* Configure the VMAX register */
- rc = qpnp_hap_vmax_config(hap);
+ rc = qpnp_hap_vmax_config(hap, hap->vmax_mv, false);
if (rc)
return rc;
@@ -2037,32 +2557,12 @@ static int qpnp_hap_config(struct qpnp_hap *hap)
hap->drive_period_code_min_limit);
}
- /* Configure BRAKE register */
- rc = qpnp_hap_masked_write_reg(hap, QPNP_HAP_EN_CTL2_REG(hap->base),
- QPNP_HAP_BRAKE_MASK, (u8)hap->en_brake);
- if (rc)
- return rc;
-
- if (hap->en_brake && hap->sup_brake_pat) {
- for (i = QPNP_HAP_BRAKE_PAT_LEN - 1, val = 0; i >= 0; i--) {
- hap->brake_pat[i] &= QPNP_HAP_BRAKE_PAT_MASK;
- temp = i << 1;
- val |= hap->brake_pat[i] << temp;
- }
- rc = qpnp_hap_write_reg(hap, QPNP_HAP_BRAKE_REG(hap->base),
- val);
- if (rc)
- return rc;
- }
-
- /* Cache play register */
- rc = qpnp_hap_read_reg(hap, QPNP_HAP_PLAY_REG(hap->base), &val);
+ rc = qpnp_hap_brake_config(hap, NULL);
if (rc < 0)
return rc;
- hap->reg_play = val;
if (hap->play_mode == QPNP_HAP_BUFFER)
- rc = qpnp_hap_buffer_config(hap);
+ rc = qpnp_hap_buffer_config(hap, NULL, false);
else if (hap->play_mode == QPNP_HAP_PWM)
rc = qpnp_hap_pwm_config(hap);
else if (hap->play_mode == QPNP_HAP_AUDIO)
@@ -2083,8 +2583,10 @@ static int qpnp_hap_config(struct qpnp_hap *hap)
}
/* use play_irq only for buffer mode */
- if (hap->play_mode != QPNP_HAP_BUFFER)
+ if (hap->play_mode != QPNP_HAP_BUFFER) {
disable_irq(hap->play_irq);
+ hap->play_irq_en = false;
+ }
}
/* setup short circuit irq */
@@ -2099,7 +2601,7 @@ static int qpnp_hap_config(struct qpnp_hap *hap)
}
}
- hap->sc_duration = 0;
+ hap->sc_count = 0;
return rc;
}
@@ -2173,30 +2675,31 @@ static int qpnp_hap_parse_dt(struct qpnp_hap *hap)
"qcom,lra-auto-res-mode", &temp_str);
if (!rc) {
if (hap->pmic_subtype == PM660_SUBTYPE) {
- hap->auto_res_mode =
+ hap->ares_cfg.auto_res_mode =
QPNP_HAP_PM660_AUTO_RES_QWD;
if (strcmp(temp_str, "zxd") == 0)
- hap->auto_res_mode =
+ hap->ares_cfg.auto_res_mode =
QPNP_HAP_PM660_AUTO_RES_ZXD;
else if (strcmp(temp_str, "qwd") == 0)
- hap->auto_res_mode =
+ hap->ares_cfg.auto_res_mode =
QPNP_HAP_PM660_AUTO_RES_QWD;
} else {
- hap->auto_res_mode = QPNP_HAP_AUTO_RES_ZXD_EOP;
+ hap->ares_cfg.auto_res_mode =
+ QPNP_HAP_AUTO_RES_ZXD_EOP;
if (strcmp(temp_str, "none") == 0)
- hap->auto_res_mode =
+ hap->ares_cfg.auto_res_mode =
QPNP_HAP_AUTO_RES_NONE;
else if (strcmp(temp_str, "zxd") == 0)
- hap->auto_res_mode =
+ hap->ares_cfg.auto_res_mode =
QPNP_HAP_AUTO_RES_ZXD;
else if (strcmp(temp_str, "qwd") == 0)
- hap->auto_res_mode =
+ hap->ares_cfg.auto_res_mode =
QPNP_HAP_AUTO_RES_QWD;
else if (strcmp(temp_str, "max-qwd") == 0)
- hap->auto_res_mode =
+ hap->ares_cfg.auto_res_mode =
QPNP_HAP_AUTO_RES_MAX_QWD;
else
- hap->auto_res_mode =
+ hap->ares_cfg.auto_res_mode =
QPNP_HAP_AUTO_RES_ZXD_EOP;
}
} else if (rc != -EINVAL) {
@@ -2204,42 +2707,48 @@ static int qpnp_hap_parse_dt(struct qpnp_hap *hap)
return rc;
}
- hap->lra_high_z = QPNP_HAP_LRA_HIGH_Z_OPT3;
+ hap->ares_cfg.lra_high_z = QPNP_HAP_LRA_HIGH_Z_OPT3;
rc = of_property_read_string(pdev->dev.of_node,
"qcom,lra-high-z", &temp_str);
if (!rc) {
if (strcmp(temp_str, "none") == 0)
- hap->lra_high_z = QPNP_HAP_LRA_HIGH_Z_NONE;
+ hap->ares_cfg.lra_high_z =
+ QPNP_HAP_LRA_HIGH_Z_NONE;
+ else if (strcmp(temp_str, "opt1") == 0)
+ hap->ares_cfg.lra_high_z =
+ QPNP_HAP_LRA_HIGH_Z_OPT1;
+ else if (strcmp(temp_str, "opt2") == 0)
+ hap->ares_cfg.lra_high_z =
+ QPNP_HAP_LRA_HIGH_Z_OPT2;
+ else
+ hap->ares_cfg.lra_high_z =
+ QPNP_HAP_LRA_HIGH_Z_OPT3;
+
if (hap->pmic_subtype == PM660_SUBTYPE) {
if (strcmp(temp_str, "opt0") == 0)
- hap->lra_high_z =
+ hap->ares_cfg.lra_high_z =
QPNP_HAP_LRA_HIGH_Z_NONE;
}
- else if (strcmp(temp_str, "opt1") == 0)
- hap->lra_high_z = QPNP_HAP_LRA_HIGH_Z_OPT1;
- else if (strcmp(temp_str, "opt2") == 0)
- hap->lra_high_z = QPNP_HAP_LRA_HIGH_Z_OPT2;
- else
- hap->lra_high_z = QPNP_HAP_LRA_HIGH_Z_OPT3;
} else if (rc != -EINVAL) {
pr_err("Unable to read LRA high-z\n");
return rc;
}
- hap->lra_qwd_drive_duration = -EINVAL;
+ hap->ares_cfg.lra_qwd_drive_duration = -EINVAL;
rc = of_property_read_u32(pdev->dev.of_node,
"qcom,lra-qwd-drive-duration",
- &hap->lra_qwd_drive_duration);
+ &hap->ares_cfg.lra_qwd_drive_duration);
- hap->calibrate_at_eop = -EINVAL;
+ hap->ares_cfg.calibrate_at_eop = -EINVAL;
rc = of_property_read_u32(pdev->dev.of_node,
- "qcom,lra-calibrate-at-eop", &hap->calibrate_at_eop);
+ "qcom,lra-calibrate-at-eop",
+ &hap->ares_cfg.calibrate_at_eop);
- hap->lra_res_cal_period = QPNP_HAP_RES_CAL_PERIOD_MAX;
+ hap->ares_cfg.lra_res_cal_period = QPNP_HAP_RES_CAL_PERIOD_MAX;
rc = of_property_read_u32(pdev->dev.of_node,
"qcom,lra-res-cal-period", &temp);
if (!rc) {
- hap->lra_res_cal_period = temp;
+ hap->ares_cfg.lra_res_cal_period = temp;
} else if (rc != -EINVAL) {
pr_err("Unable to read cal period\n");
return rc;
@@ -2271,7 +2780,7 @@ static int qpnp_hap_parse_dt(struct qpnp_hap *hap)
hap->drive_period_code_min_limit_percent_variation =
(u8) temp;
- if (hap->auto_res_mode == QPNP_HAP_AUTO_RES_QWD) {
+ if (hap->ares_cfg.auto_res_mode == QPNP_HAP_AUTO_RES_QWD) {
hap->time_required_to_generate_back_emf_us =
QPNP_HAP_TIME_REQ_FOR_BACK_EMF_GEN;
rc = of_property_read_u32(pdev->dev.of_node,
@@ -2409,6 +2918,8 @@ static int qpnp_hap_parse_dt(struct qpnp_hap *hap)
if (of_find_property(pdev->dev.of_node, "vcc_pon-supply", NULL))
hap->manage_pon_supply = true;
+ hap->auto_mode = of_property_read_bool(pdev->dev.of_node,
+ "qcom,lra-auto-mode");
return 0;
}
@@ -2503,12 +3014,9 @@ static int qpnp_haptic_probe(struct platform_device *pdev)
hap->timed_dev.get_time = qpnp_hap_get_time;
hap->timed_dev.enable = qpnp_hap_td_enable;
- if (hap->act_type == QPNP_HAP_LRA && hap->correct_lra_drive_freq &&
- !hap->lra_hw_auto_resonance) {
- hrtimer_init(&hap->auto_res_err_poll_timer, CLOCK_MONOTONIC,
- HRTIMER_MODE_REL);
- hap->auto_res_err_poll_timer.function = detect_auto_res_error;
- }
+ hrtimer_init(&hap->auto_res_err_poll_timer, CLOCK_MONOTONIC,
+ HRTIMER_MODE_REL);
+ hap->auto_res_err_poll_timer.function = detect_auto_res_error;
rc = timed_output_dev_register(&hap->timed_dev);
if (rc < 0) {
@@ -2546,9 +3054,7 @@ sysfs_fail:
timed_output_dev_unregister(&hap->timed_dev);
timed_output_fail:
cancel_work_sync(&hap->work);
- if (hap->act_type == QPNP_HAP_LRA && hap->correct_lra_drive_freq &&
- !hap->lra_hw_auto_resonance)
- hrtimer_cancel(&hap->auto_res_err_poll_timer);
+ hrtimer_cancel(&hap->auto_res_err_poll_timer);
hrtimer_cancel(&hap->hap_timer);
mutex_destroy(&hap->lock);
mutex_destroy(&hap->wf_lock);
@@ -2566,9 +3072,7 @@ static int qpnp_haptic_remove(struct platform_device *pdev)
&qpnp_hap_attrs[i].attr);
cancel_work_sync(&hap->work);
- if (hap->act_type == QPNP_HAP_LRA && hap->correct_lra_drive_freq &&
- !hap->lra_hw_auto_resonance)
- hrtimer_cancel(&hap->auto_res_err_poll_timer);
+ hrtimer_cancel(&hap->auto_res_err_poll_timer);
hrtimer_cancel(&hap->hap_timer);
timed_output_dev_unregister(&hap->timed_dev);
mutex_destroy(&hap->lock);
diff --git a/drivers/staging/android/ion/ion.c b/drivers/staging/android/ion/ion.c
index bfb7dd2d920d..49ed6de1a95e 100644
--- a/drivers/staging/android/ion/ion.c
+++ b/drivers/staging/android/ion/ion.c
@@ -1473,6 +1473,28 @@ int ion_share_dma_buf_fd(struct ion_client *client, struct ion_handle *handle)
}
EXPORT_SYMBOL(ion_share_dma_buf_fd);
+bool ion_dma_buf_is_secure(struct dma_buf *dmabuf)
+{
+ struct ion_buffer *buffer;
+ enum ion_heap_type type;
+
+ /* Return false if we didn't create the buffer */
+ if (!dmabuf || dmabuf->ops != &dma_buf_ops)
+ return false;
+
+ buffer = dmabuf->priv;
+
+ if (!buffer || !buffer->heap)
+ return false;
+
+ type = buffer->heap->type;
+
+ return (type == (enum ion_heap_type)ION_HEAP_TYPE_SECURE_DMA ||
+ type == (enum ion_heap_type)ION_HEAP_TYPE_SYSTEM_SECURE) ?
+ true : false;
+}
+EXPORT_SYMBOL(ion_dma_buf_is_secure);
+
struct ion_handle *ion_import_dma_buf(struct ion_client *client, int fd)
{
struct dma_buf *dmabuf;
diff --git a/drivers/staging/android/ion/ion.h b/drivers/staging/android/ion/ion.h
index 5f99ea16617a..73902ebafca6 100644
--- a/drivers/staging/android/ion/ion.h
+++ b/drivers/staging/android/ion/ion.h
@@ -2,7 +2,7 @@
* drivers/staging/android/ion/ion.h
*
* Copyright (C) 2011 Google, Inc.
- * Copyright (c) 2011-2014, The Linux Foundation. All rights reserved.
+ * Copyright (c) 2011-2014,2017 The Linux Foundation. All rights reserved.
*
* This software is licensed under the terms of the GNU General Public
* License version 2, as published by the Free Software Foundation, and
@@ -209,6 +209,16 @@ int ion_share_dma_buf_fd(struct ion_client *client, struct ion_handle *handle);
*/
struct ion_handle *ion_import_dma_buf(struct ion_client *client, int fd);
+/**
+ * ion_dma_buf_is_secure() - Returns true if the dma buf is secure
+ * dmabuf
+ * @dmabuf: pointer to a dma-buf
+ *
+ * Given a dma-buf pointer, return true if ion created it and it is from
+ * a secure heap.
+ */
+bool ion_dma_buf_is_secure(struct dma_buf *dmabuf);
+
#else
static inline void ion_reserve(struct ion_platform_data *data)
{
@@ -272,5 +282,10 @@ static inline int ion_handle_get_flags(struct ion_client *client,
return -ENODEV;
}
+bool ion_dma_buf_is_secure(struct dma_buf *dmabuf)
+{
+ return false;
+}
+
#endif /* CONFIG_ION */
#endif /* _LINUX_ION_H */
diff --git a/drivers/usb/gadget/function/f_midi.c b/drivers/usb/gadget/function/f_midi.c
index 4ebd744434c6..79f554f1fb23 100644
--- a/drivers/usb/gadget/function/f_midi.c
+++ b/drivers/usb/gadget/function/f_midi.c
@@ -370,7 +370,9 @@ static int f_midi_set_alt(struct usb_function *f, unsigned intf, unsigned alt)
/* allocate a bunch of read buffers and queue them all at once. */
for (i = 0; i < midi->qlen && err == 0; i++) {
struct usb_request *req =
- midi_alloc_ep_req(midi->out_ep, midi->buflen);
+ midi_alloc_ep_req(midi->out_ep,
+ max_t(unsigned, midi->buflen,
+ bulk_out_desc.wMaxPacketSize));
if (req == NULL)
return -ENOMEM;
diff --git a/drivers/usb/gadget/function/f_mtp.c b/drivers/usb/gadget/function/f_mtp.c
index 7bfeb93f012c..6ee21d039415 100644
--- a/drivers/usb/gadget/function/f_mtp.c
+++ b/drivers/usb/gadget/function/f_mtp.c
@@ -1490,6 +1490,7 @@ mtp_function_bind(struct usb_configuration *c, struct usb_function *f)
mtp_fullspeed_out_desc.bEndpointAddress;
}
+ fi_mtp->func_inst.f = &dev->function;
DBG(cdev, "%s speed %s: IN/%s, OUT/%s\n",
gadget_is_superspeed(c->cdev->gadget) ? "super" :
(gadget_is_dualspeed(c->cdev->gadget) ? "dual" : "full"),
@@ -1501,9 +1502,10 @@ static void
mtp_function_unbind(struct usb_configuration *c, struct usb_function *f)
{
struct mtp_dev *dev = func_to_mtp(f);
+ struct mtp_instance *fi_mtp;
struct usb_request *req;
int i;
-
+ fi_mtp = container_of(f->fi, struct mtp_instance, func_inst);
mtp_string_defs[INTERFACE_STRING_INDEX].id = 0;
mutex_lock(&dev->read_mutex);
while ((req = mtp_req_get(dev, &dev->tx_idle)))
@@ -1517,6 +1519,7 @@ mtp_function_unbind(struct usb_configuration *c, struct usb_function *f)
dev->is_ptp = false;
kfree(f->os_desc_table);
f->os_desc_n = 0;
+ fi_mtp->func_inst.f = NULL;
}
static int mtp_function_set_alt(struct usb_function *f,
@@ -1916,7 +1919,6 @@ struct usb_function *function_alloc_mtp_ptp(struct usb_function_instance *fi,
dev->function.setup = mtp_ctrlreq_configfs;
dev->function.free_func = mtp_free;
dev->is_ptp = !mtp_config;
- fi->f = &dev->function;
return &dev->function;
}
diff --git a/drivers/usb/gadget/function/f_qdss.c b/drivers/usb/gadget/function/f_qdss.c
index 88db253aeef4..777acb489875 100644
--- a/drivers/usb/gadget/function/f_qdss.c
+++ b/drivers/usb/gadget/function/f_qdss.c
@@ -474,6 +474,7 @@ static void usb_qdss_disconnect_work(struct work_struct *work)
{
struct f_qdss *qdss;
int status;
+ unsigned long flags;
qdss = container_of(work, struct f_qdss, disconnect_w);
pr_debug("usb_qdss_disconnect_work\n");
@@ -496,6 +497,14 @@ static void usb_qdss_disconnect_work(struct work_struct *work)
status = set_qdss_data_connection(qdss, 0);
if (status)
pr_err("qdss_disconnect error");
+
+ spin_lock_irqsave(&qdss->lock, flags);
+ if (qdss->endless_req) {
+ usb_ep_free_request(qdss->port.data,
+ qdss->endless_req);
+ qdss->endless_req = NULL;
+ }
+ spin_unlock_irqrestore(&qdss->lock, flags);
}
/*
@@ -528,6 +537,8 @@ static void usb_qdss_connect_work(struct work_struct *work)
{
struct f_qdss *qdss;
int status;
+ struct usb_request *req = NULL;
+ unsigned long flags;
qdss = container_of(work, struct f_qdss, connect_w);
@@ -548,8 +559,13 @@ static void usb_qdss_connect_work(struct work_struct *work)
if (qdss->ch.notify)
qdss->ch.notify(qdss->ch.priv, USB_QDSS_CONNECT,
NULL, &qdss->ch);
+ spin_lock_irqsave(&qdss->lock, flags);
+ req = qdss->endless_req;
+ spin_unlock_irqrestore(&qdss->lock, flags);
+ if (!req)
+ return;
- status = usb_ep_queue(qdss->port.data, qdss->endless_req, GFP_ATOMIC);
+ status = usb_ep_queue(qdss->port.data, req, GFP_ATOMIC);
if (status)
pr_err("%s: usb_ep_queue error (%d)\n", __func__, status);
}
@@ -849,9 +865,11 @@ void usb_qdss_close(struct usb_qdss_ch *ch)
return;
}
- usb_ep_dequeue(qdss->port.data, qdss->endless_req);
- usb_ep_free_request(qdss->port.data, qdss->endless_req);
- qdss->endless_req = NULL;
+ if (qdss->endless_req) {
+ usb_ep_dequeue(qdss->port.data, qdss->endless_req);
+ usb_ep_free_request(qdss->port.data, qdss->endless_req);
+ qdss->endless_req = NULL;
+ }
gadget = qdss->gadget;
ch->app_conn = 0;
spin_unlock_irqrestore(&qdss_lock, flags);
diff --git a/drivers/video/fbdev/msm/mdss_hdmi_edid.c b/drivers/video/fbdev/msm/mdss_hdmi_edid.c
index 599f6cb44c63..102c22cba7dd 100644
--- a/drivers/video/fbdev/msm/mdss_hdmi_edid.c
+++ b/drivers/video/fbdev/msm/mdss_hdmi_edid.c
@@ -1283,6 +1283,7 @@ static void hdmi_edid_extract_speaker_allocation_data(
static void hdmi_edid_extract_sink_caps(struct hdmi_edid_ctrl *edid_ctrl,
const u8 *in_buf)
{
+ u8 len;
const u8 *vsd = NULL;
if (!edid_ctrl) {
@@ -1297,13 +1298,29 @@ static void hdmi_edid_extract_sink_caps(struct hdmi_edid_ctrl *edid_ctrl,
edid_ctrl->basic_audio_supp = false;
pr_debug("%s: basic audio supported: %s\n", __func__,
edid_ctrl->basic_audio_supp ? "true" : "false");
+ vsd = hdmi_edid_find_block(in_buf, DBC_START_OFFSET,
+ VENDOR_SPECIFIC_DATA_BLOCK, &len);
+
+ if (vsd == NULL || len == 0 || len > MAX_DATA_BLOCK_SIZE)
+ return;
+
+ /* Max TMDS clock is in multiples of 5Mhz. */
+ edid_ctrl->sink_caps.max_pclk_in_hz = vsd[7] * 5000000;
vsd = hdmi_edid_find_hfvsdb(in_buf);
if (vsd) {
- /* Max pixel clock is in multiples of 5Mhz. */
- edid_ctrl->sink_caps.max_pclk_in_hz =
- vsd[5]*5000000;
+ /*
+ * HF-VSDB define larger TMDS clock than VSDB. If sink
+ * supports TMDS Character Rates > 340M, the sink shall
+ * set Max_TMDS_Character_Rates appropriately and non-zero.
+ * Or, if sink dose not support TMDS Character Rates > 340M,
+ * the sink shall set this filed to 0. The max TMDS support
+ * clock Rate = Max_TMDS_Character_Rates * 5Mhz.
+ */
+ if (vsd[5] != 0)
+ edid_ctrl->sink_caps.max_pclk_in_hz =
+ vsd[5] * 5000000;
edid_ctrl->sink_caps.scdc_present =
(vsd[6] & 0x80) ? true : false;
edid_ctrl->sink_caps.scramble_support =
@@ -2425,6 +2442,25 @@ bool hdmi_edid_is_dvi_mode(void *input)
}
/**
+ * hdmi_edid_get_sink_caps_max_tmds_clk() - get max tmds clock supported.
+ * Sink side's limitation should be concerned as well.
+ * @input: edid parser data
+ *
+ * Return: max tmds clock
+ */
+u32 hdmi_edid_get_sink_caps_max_tmds_clk(void *input)
+{
+ struct hdmi_edid_ctrl *edid_ctrl = (struct hdmi_edid_ctrl *)input;
+
+ if (!edid_ctrl) {
+ DEV_ERR("%s: invalid input\n", __func__);
+ return 0;
+ }
+
+ return edid_ctrl->sink_caps.max_pclk_in_hz;
+}
+
+/**
* hdmi_edid_get_deep_color() - get deep color info supported by sink
* @input: edid parser data
*
diff --git a/drivers/video/fbdev/msm/mdss_hdmi_edid.h b/drivers/video/fbdev/msm/mdss_hdmi_edid.h
index 557e9326a81d..af802bb45f89 100644
--- a/drivers/video/fbdev/msm/mdss_hdmi_edid.h
+++ b/drivers/video/fbdev/msm/mdss_hdmi_edid.h
@@ -81,5 +81,6 @@ void hdmi_edid_config_override(void *input, bool enable,
struct hdmi_edid_override_data *data);
void hdmi_edid_set_max_pclk_rate(void *input, u32 max_pclk_khz);
bool hdmi_edid_is_audio_supported(void *input);
+u32 hdmi_edid_get_sink_caps_max_tmds_clk(void *input);
#endif /* __HDMI_EDID_H__ */
diff --git a/drivers/video/fbdev/msm/mdss_hdmi_tx.c b/drivers/video/fbdev/msm/mdss_hdmi_tx.c
index 42845f9ff192..8fa229aaa174 100644
--- a/drivers/video/fbdev/msm/mdss_hdmi_tx.c
+++ b/drivers/video/fbdev/msm/mdss_hdmi_tx.c
@@ -2224,6 +2224,14 @@ static int hdmi_tx_read_sink_info(struct hdmi_tx_ctrl *hdmi_ctrl)
status = hdmi_edid_parser(data);
if (status)
DEV_ERR("%s: edid parse failed\n", __func__);
+ else
+ /*
+ * Updata HDMI max supported TMDS clock, consider
+ * both sink and source capicity.
+ */
+ hdmi_edid_set_max_pclk_rate(data,
+ min(hdmi_edid_get_sink_caps_max_tmds_clk(data) / 1000,
+ hdmi_ctrl->max_pclk_khz));
}
bail:
if (hdmi_tx_enable_power(hdmi_ctrl, HDMI_TX_DDC_PM, false))
diff --git a/drivers/video/fbdev/msm/mdss_mdp_util.c b/drivers/video/fbdev/msm/mdss_mdp_util.c
index d0bf61679f61..22656175edf8 100644
--- a/drivers/video/fbdev/msm/mdss_mdp_util.c
+++ b/drivers/video/fbdev/msm/mdss_mdp_util.c
@@ -1095,7 +1095,7 @@ static int mdss_mdp_get_img(struct msmfb_data *img,
return ret;
}
}
- if (!*start) {
+ if (start && !*start) {
pr_err("start address is zero!\n");
mdss_mdp_put_img(data, rotator, dir);
return -ENOMEM;
diff --git a/fs/f2fs/super.c b/fs/f2fs/super.c
index 92ac61c3ccf7..d2e75fe2e072 100644
--- a/fs/f2fs/super.c
+++ b/fs/f2fs/super.c
@@ -918,6 +918,79 @@ loff_t max_file_size(unsigned bits)
return result;
}
+static inline bool sanity_check_area_boundary(struct super_block *sb,
+ struct f2fs_super_block *raw_super)
+{
+ u32 segment0_blkaddr = le32_to_cpu(raw_super->segment0_blkaddr);
+ u32 cp_blkaddr = le32_to_cpu(raw_super->cp_blkaddr);
+ u32 sit_blkaddr = le32_to_cpu(raw_super->sit_blkaddr);
+ u32 nat_blkaddr = le32_to_cpu(raw_super->nat_blkaddr);
+ u32 ssa_blkaddr = le32_to_cpu(raw_super->ssa_blkaddr);
+ u32 main_blkaddr = le32_to_cpu(raw_super->main_blkaddr);
+ u32 segment_count_ckpt = le32_to_cpu(raw_super->segment_count_ckpt);
+ u32 segment_count_sit = le32_to_cpu(raw_super->segment_count_sit);
+ u32 segment_count_nat = le32_to_cpu(raw_super->segment_count_nat);
+ u32 segment_count_ssa = le32_to_cpu(raw_super->segment_count_ssa);
+ u32 segment_count_main = le32_to_cpu(raw_super->segment_count_main);
+ u32 segment_count = le32_to_cpu(raw_super->segment_count);
+ u32 log_blocks_per_seg = le32_to_cpu(raw_super->log_blocks_per_seg);
+
+ if (segment0_blkaddr != cp_blkaddr) {
+ f2fs_msg(sb, KERN_INFO,
+ "Mismatch start address, segment0(%u) cp_blkaddr(%u)",
+ segment0_blkaddr, cp_blkaddr);
+ return true;
+ }
+
+ if (cp_blkaddr + (segment_count_ckpt << log_blocks_per_seg) !=
+ sit_blkaddr) {
+ f2fs_msg(sb, KERN_INFO,
+ "Wrong CP boundary, start(%u) end(%u) blocks(%u)",
+ cp_blkaddr, sit_blkaddr,
+ segment_count_ckpt << log_blocks_per_seg);
+ return true;
+ }
+
+ if (sit_blkaddr + (segment_count_sit << log_blocks_per_seg) !=
+ nat_blkaddr) {
+ f2fs_msg(sb, KERN_INFO,
+ "Wrong SIT boundary, start(%u) end(%u) blocks(%u)",
+ sit_blkaddr, nat_blkaddr,
+ segment_count_sit << log_blocks_per_seg);
+ return true;
+ }
+
+ if (nat_blkaddr + (segment_count_nat << log_blocks_per_seg) !=
+ ssa_blkaddr) {
+ f2fs_msg(sb, KERN_INFO,
+ "Wrong NAT boundary, start(%u) end(%u) blocks(%u)",
+ nat_blkaddr, ssa_blkaddr,
+ segment_count_nat << log_blocks_per_seg);
+ return true;
+ }
+
+ if (ssa_blkaddr + (segment_count_ssa << log_blocks_per_seg) !=
+ main_blkaddr) {
+ f2fs_msg(sb, KERN_INFO,
+ "Wrong SSA boundary, start(%u) end(%u) blocks(%u)",
+ ssa_blkaddr, main_blkaddr,
+ segment_count_ssa << log_blocks_per_seg);
+ return true;
+ }
+
+ if (main_blkaddr + (segment_count_main << log_blocks_per_seg) !=
+ segment0_blkaddr + (segment_count << log_blocks_per_seg)) {
+ f2fs_msg(sb, KERN_INFO,
+ "Wrong MAIN_AREA boundary, start(%u) end(%u) blocks(%u)",
+ main_blkaddr,
+ segment0_blkaddr + (segment_count << log_blocks_per_seg),
+ segment_count_main << log_blocks_per_seg);
+ return true;
+ }
+
+ return false;
+}
+
static int sanity_check_raw_super(struct super_block *sb,
struct f2fs_super_block *raw_super)
{
@@ -973,6 +1046,23 @@ static int sanity_check_raw_super(struct super_block *sb,
le32_to_cpu(raw_super->log_sectorsize));
return 1;
}
+
+ /* check reserved ino info */
+ if (le32_to_cpu(raw_super->node_ino) != 1 ||
+ le32_to_cpu(raw_super->meta_ino) != 2 ||
+ le32_to_cpu(raw_super->root_ino) != 3) {
+ f2fs_msg(sb, KERN_INFO,
+ "Invalid Fs Meta Ino: node(%u) meta(%u) root(%u)",
+ le32_to_cpu(raw_super->node_ino),
+ le32_to_cpu(raw_super->meta_ino),
+ le32_to_cpu(raw_super->root_ino));
+ return 1;
+ }
+
+ /* check CP/SIT/NAT/SSA/MAIN_AREA area boundary */
+ if (sanity_check_area_boundary(sb, raw_super))
+ return 1;
+
return 0;
}
diff --git a/fs/nfsd/nfssvc.c b/fs/nfsd/nfssvc.c
index ad4e2377dd63..5be1fa6b676d 100644
--- a/fs/nfsd/nfssvc.c
+++ b/fs/nfsd/nfssvc.c
@@ -656,6 +656,37 @@ static __be32 map_new_errors(u32 vers, __be32 nfserr)
return nfserr;
}
+/*
+ * A write procedure can have a large argument, and a read procedure can
+ * have a large reply, but no NFSv2 or NFSv3 procedure has argument and
+ * reply that can both be larger than a page. The xdr code has taken
+ * advantage of this assumption to be a sloppy about bounds checking in
+ * some cases. Pending a rewrite of the NFSv2/v3 xdr code to fix that
+ * problem, we enforce these assumptions here:
+ */
+static bool nfs_request_too_big(struct svc_rqst *rqstp,
+ struct svc_procedure *proc)
+{
+ /*
+ * The ACL code has more careful bounds-checking and is not
+ * susceptible to this problem:
+ */
+ if (rqstp->rq_prog != NFS_PROGRAM)
+ return false;
+ /*
+ * Ditto NFSv4 (which can in theory have argument and reply both
+ * more than a page):
+ */
+ if (rqstp->rq_vers >= 4)
+ return false;
+ /* The reply will be small, we're OK: */
+ if (proc->pc_xdrressize > 0 &&
+ proc->pc_xdrressize < XDR_QUADLEN(PAGE_SIZE))
+ return false;
+
+ return rqstp->rq_arg.len > PAGE_SIZE;
+}
+
int
nfsd_dispatch(struct svc_rqst *rqstp, __be32 *statp)
{
@@ -668,6 +699,11 @@ nfsd_dispatch(struct svc_rqst *rqstp, __be32 *statp)
rqstp->rq_vers, rqstp->rq_proc);
proc = rqstp->rq_procinfo;
+ if (nfs_request_too_big(rqstp, proc)) {
+ dprintk("nfsd: NFSv%d argument too large\n", rqstp->rq_vers);
+ *statp = rpc_garbage_args;
+ return 1;
+ }
/*
* Give the xdr decoder a chance to change this if it wants
* (necessary in the NFSv4.0 compound case)
diff --git a/include/linux/msm_ext_display.h b/include/linux/msm_ext_display.h
index fc53e861eba4..9a03b79e09d7 100644
--- a/include/linux/msm_ext_display.h
+++ b/include/linux/msm_ext_display.h
@@ -114,6 +114,7 @@ struct msm_ext_disp_intf_ops {
* @cable_status: cable connected/disconnected
* @get_intf_id: id of connected interface
* @acknowledge: acknowledge audio status
+ * @codec_ready: notify when codec is ready
*/
struct msm_ext_disp_audio_codec_ops {
int (*audio_info_setup)(struct platform_device *pdev,
@@ -124,6 +125,7 @@ struct msm_ext_disp_audio_codec_ops {
int (*get_intf_id)(struct platform_device *pdev);
void (*teardown_done)(struct platform_device *pdev);
int (*acknowledge)(struct platform_device *pdev, u32 ack);
+ void (*codec_ready)(struct platform_device *pdev);
};
/*
diff --git a/include/sound/apr_audio-v2.h b/include/sound/apr_audio-v2.h
index bcb53faaf678..40cd9a752c53 100644
--- a/include/sound/apr_audio-v2.h
+++ b/include/sound/apr_audio-v2.h
@@ -15,6 +15,7 @@
#define _APR_AUDIO_V2_H_
#include <linux/qdsp6v2/apr.h>
+#include <linux/msm_audio.h>
/* size of header needed for passing data out of band */
#define APR_CMD_OB_HDR_SZ 12
@@ -447,6 +448,18 @@ struct adm_param_data_v5 {
#define ASM_STREAM_PP_EVENT 0x00013214
#define DSP_STREAM_CMD "ADSP Stream Cmd"
#define DSP_STREAM_CALLBACK "ADSP Stream Callback Event"
+#define DSP_STREAM_CALLBACK_QUEUE_SIZE 1024
+
+struct dsp_stream_callback_list {
+ struct list_head list;
+ struct msm_adsp_event_data event;
+};
+
+struct dsp_stream_callback_prtd {
+ uint16_t event_count;
+ struct list_head event_queue;
+ spinlock_t prtd_spin_lock;
+};
/* set customized mixing on matrix mixer */
#define ADM_CMD_SET_PSPD_MTMX_STRTR_PARAMS_V5 0x00010344
@@ -10320,10 +10333,33 @@ struct asm_session_mtmx_strtr_param_clk_rec_t {
u32 flags;
} __packed;
+
+/* Parameter used by #ASM_SESSION_MTMX_STRTR_MODULE_ID_AVSYNC to
+ * realize smoother adjustment of audio session clock for a specified session.
+ * The desired audio session clock adjustment(in micro seconds) is specified
+ * using the command #ASM_SESSION_CMD_ADJUST_SESSION_CLOCK_V2.
+ * Delaying/Advancing the session clock would be implemented by inserting
+ * interpolated/dropping audio samples in the playback path respectively.
+ * Also, this parameter has to be configured before the Audio Session is put
+ * to RUN state to avoid cold start latency/glitches in the playback.
+ */
+
+#define ASM_SESSION_MTMX_PARAM_ADJUST_SESSION_TIME_CTL 0x00013217
+
+struct asm_session_mtmx_param_adjust_session_time_ctl_t {
+ /* Specifies whether the module is enabled or not
+ * @values
+ * 0 -- disabled
+ * 1 -- enabled
+ */
+ u32 enable;
+};
+
union asm_session_mtmx_strtr_param_config {
struct asm_session_mtmx_strtr_param_window_v2_t window_param;
struct asm_session_mtmx_strtr_param_render_mode_t render_param;
struct asm_session_mtmx_strtr_param_clk_rec_t clk_rec_param;
+ struct asm_session_mtmx_param_adjust_session_time_ctl_t adj_time_param;
} __packed;
struct asm_mtmx_strtr_params {
diff --git a/include/sound/q6asm-v2.h b/include/sound/q6asm-v2.h
index 41fcdeb50831..b2bb8d493839 100644
--- a/include/sound/q6asm-v2.h
+++ b/include/sound/q6asm-v2.h
@@ -655,6 +655,10 @@ int q6asm_send_mtmx_strtr_render_mode(struct audio_client *ac,
int q6asm_send_mtmx_strtr_clk_rec_mode(struct audio_client *ac,
uint32_t clk_rec_mode);
+/* Enable adjust session clock in DSP */
+int q6asm_send_mtmx_strtr_enable_adjust_session_clock(struct audio_client *ac,
+ bool enable);
+
/* Retrieve the current DSP path delay */
int q6asm_get_path_delay(struct audio_client *ac);
@@ -662,4 +666,8 @@ int q6asm_get_path_delay(struct audio_client *ac);
uint8_t q6asm_get_buf_index_from_token(uint32_t token);
uint8_t q6asm_get_stream_id_from_token(uint32_t token);
+/* Adjust session clock in DSP */
+int q6asm_adjust_session_clock(struct audio_client *ac,
+ uint32_t adjust_time_lsw,
+ uint32_t adjust_time_msw);
#endif /* __Q6_ASM_H__ */
diff --git a/include/uapi/drm/drm.h b/include/uapi/drm/drm.h
index 3801584a0c53..24c76d138317 100644
--- a/include/uapi/drm/drm.h
+++ b/include/uapi/drm/drm.h
@@ -58,6 +58,10 @@ typedef unsigned long drm_handle_t;
#endif
+#if defined(__cplusplus)
+extern "C" {
+#endif
+
#define DRM_NAME "drm" /**< Name in kernel, /dev, and /proc */
#define DRM_MIN_ORDER 5 /**< At least 2^5 bytes = 32 bytes */
#define DRM_MAX_ORDER 22 /**< Up to 2^22 bytes = 4MB */
@@ -372,7 +376,11 @@ struct drm_buf_pub {
*/
struct drm_buf_map {
int count; /**< Length of the buffer list */
+#ifdef __cplusplus
+ void __user *virt;
+#else
void __user *virtual; /**< Mmap'd area in user-virtual */
+#endif
struct drm_buf_pub __user *list; /**< Buffer information */
};
@@ -679,7 +687,15 @@ struct drm_prime_handle {
__s32 fd;
};
-#include <drm/drm_mode.h>
+#if defined(__cplusplus)
+}
+#endif
+
+#include "drm_mode.h"
+
+#if defined(__cplusplus)
+extern "C" {
+#endif
#define DRM_IOCTL_BASE 'd'
#define DRM_IO(nr) _IO(DRM_IOCTL_BASE,nr)
@@ -874,4 +890,8 @@ typedef struct drm_scatter_gather drm_scatter_gather_t;
typedef struct drm_set_version drm_set_version_t;
#endif
+#if defined(__cplusplus)
+}
+#endif
+
#endif
diff --git a/include/uapi/drm/drm_fourcc.h b/include/uapi/drm/drm_fourcc.h
index 53d7c80f5eb0..7f203a5f83cb 100644
--- a/include/uapi/drm/drm_fourcc.h
+++ b/include/uapi/drm/drm_fourcc.h
@@ -26,6 +26,10 @@
#include <linux/types.h>
+#if defined(__cplusplus)
+extern "C" {
+#endif
+
#define fourcc_code(a, b, c, d) ((__u32)(a) | ((__u32)(b) << 8) | \
((__u32)(c) << 16) | ((__u32)(d) << 24))
@@ -237,4 +241,8 @@
*/
#define DRM_FORMAT_MOD_QCOM_COMPRESSED fourcc_mod_code(QCOM, 1)
+#if defined(__cplusplus)
+}
+#endif
+
#endif /* DRM_FOURCC_H */
diff --git a/include/uapi/drm/drm_mode.h b/include/uapi/drm/drm_mode.h
index 1c5e74f1ea39..0630e0f64b9c 100644
--- a/include/uapi/drm/drm_mode.h
+++ b/include/uapi/drm/drm_mode.h
@@ -29,6 +29,10 @@
#include <linux/types.h>
+#if defined(__cplusplus)
+extern "C" {
+#endif
+
#define DRM_DISPLAY_INFO_LEN 32
#define DRM_CONNECTOR_NAME_LEN 32
#define DRM_DISPLAY_MODE_LEN 32
@@ -599,4 +603,8 @@ struct drm_mode_destroy_blob {
__u32 blob_id;
};
+#if defined(__cplusplus)
+}
+#endif
+
#endif
diff --git a/include/uapi/drm/drm_sarea.h b/include/uapi/drm/drm_sarea.h
index 413a5642d49f..12285bc929a1 100644
--- a/include/uapi/drm/drm_sarea.h
+++ b/include/uapi/drm/drm_sarea.h
@@ -34,6 +34,10 @@
#include <drm/drm.h>
+#if defined(__cplusplus)
+extern "C" {
+#endif
+
/* SAREA area needs to be at least a page */
#if defined(__alpha__)
#define SAREA_MAX 0x2000U
@@ -83,4 +87,8 @@ typedef struct drm_sarea_frame drm_sarea_frame_t;
typedef struct drm_sarea drm_sarea_t;
#endif
+#if defined(__cplusplus)
+}
+#endif
+
#endif /* _DRM_SAREA_H_ */
diff --git a/include/uapi/drm/msm_drm.h b/include/uapi/drm/msm_drm.h
index db65513ad656..07e6e00a89f6 100644
--- a/include/uapi/drm/msm_drm.h
+++ b/include/uapi/drm/msm_drm.h
@@ -78,6 +78,7 @@ struct drm_msm_param {
#define MSM_BO_SCANOUT 0x00000001 /* scanout capable */
#define MSM_BO_GPU_READONLY 0x00000002
#define MSM_BO_PRIVILEGED 0x00000004
+#define MSM_BO_SECURE 0x00000008 /* Allocate and map as secure */
#define MSM_BO_CACHE_MASK 0x000f0000
/* cache modes */
#define MSM_BO_CACHED 0x00010000
@@ -86,6 +87,7 @@ struct drm_msm_param {
#define MSM_BO_FLAGS (MSM_BO_SCANOUT | \
MSM_BO_GPU_READONLY | \
+ MSM_BO_SECURE | \
MSM_BO_CACHED | \
MSM_BO_WC | \
MSM_BO_UNCACHED)
diff --git a/include/uapi/linux/ipv6_route.h b/include/uapi/linux/ipv6_route.h
index f6598d1c886e..316e838b7470 100644
--- a/include/uapi/linux/ipv6_route.h
+++ b/include/uapi/linux/ipv6_route.h
@@ -34,7 +34,7 @@
#define RTF_PREF(pref) ((pref) << 27)
#define RTF_PREF_MASK 0x18000000
-#define RTF_PCPU 0x40000000
+#define RTF_PCPU 0x40000000 /* read-only: can not be set by user */
#define RTF_LOCAL 0x80000000
diff --git a/include/uapi/linux/msm_audio.h b/include/uapi/linux/msm_audio.h
index 36b66c7cde76..f306949eb5e6 100644
--- a/include/uapi/linux/msm_audio.h
+++ b/include/uapi/linux/msm_audio.h
@@ -460,4 +460,14 @@ struct msm_hwacc_effects_config {
__s32 topology;
};
+#define ADSP_STREAM_PP_EVENT 0
+#define ADSP_STREAM_ENCDEC_EVENT 1
+#define ADSP_STREAM_EVENT_MAX 2
+
+struct msm_adsp_event_data {
+ __u32 event_type;
+ __u32 payload_len;
+ __u8 payload[0];
+};
+
#endif
diff --git a/include/uapi/linux/msm_ipa.h b/include/uapi/linux/msm_ipa.h
index 16e4b8e30b07..51569b7e7aa0 100644
--- a/include/uapi/linux/msm_ipa.h
+++ b/include/uapi/linux/msm_ipa.h
@@ -394,10 +394,20 @@ enum ipa_tethering_stats_event {
IPA_TETHERING_STATS_UPDATE_STATS = IPA_ECM_EVENT_MAX,
IPA_TETHERING_STATS_UPDATE_NETWORK_STATS,
IPA_TETHERING_STATS_EVENT_MAX,
- IPA_EVENT_MAX_NUM = IPA_TETHERING_STATS_EVENT_MAX
};
-#define IPA_EVENT_MAX ((int)IPA_EVENT_MAX_NUM)
+enum ipa_quota_event {
+ IPA_QUOTA_REACH = IPA_TETHERING_STATS_EVENT_MAX,
+ IPA_QUOTA_EVENT_MAX,
+};
+
+enum ipa_ssr_event {
+ IPA_SSR_BEFORE_SHUTDOWN = IPA_QUOTA_EVENT_MAX,
+ IPA_SSR_AFTER_POWERUP,
+ IPA_SSR_EVENT_MAX
+};
+
+#define IPA_EVENT_MAX_NUM ((int)IPA_SSR_EVENT_MAX)
/**
* enum ipa_rm_resource_name - IPA RM clients identification names
diff --git a/include/uapi/linux/rmnet_ipa_fd_ioctl.h b/include/uapi/linux/rmnet_ipa_fd_ioctl.h
index 228bfe8274c6..f04ac495a5c0 100644
--- a/include/uapi/linux/rmnet_ipa_fd_ioctl.h
+++ b/include/uapi/linux/rmnet_ipa_fd_ioctl.h
@@ -1,4 +1,4 @@
-/* Copyright (c) 2013-2016, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2013-2017, The Linux Foundation. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 and
@@ -32,6 +32,7 @@
#define WAN_IOCTL_RESET_TETHER_STATS 7
#define WAN_IOCTL_QUERY_DL_FILTER_STATS 8
#define WAN_IOCTL_ADD_FLT_RULE_EX 9
+#define WAN_IOCTL_QUERY_TETHER_STATS_ALL 10
/* User space may not have this defined. */
#ifndef IFNAMSIZ
@@ -99,6 +100,16 @@ struct wan_ioctl_query_tether_stats {
uint64_t ipv6_rx_bytes;
};
+struct wan_ioctl_query_tether_stats_all {
+ /* Name of the upstream interface */
+ char upstreamIface[IFNAMSIZ];
+ /* enum of tether interface */
+ enum ipacm_client_enum ipa_client;
+ uint8_t reset_stats;
+ uint64_t tx_bytes;
+ uint64_t rx_bytes;
+};
+
struct wan_ioctl_reset_tether_stats {
/* Name of the upstream interface, not support now */
char upstreamIface[IFNAMSIZ];
@@ -155,4 +166,8 @@ struct wan_ioctl_query_dl_filter_stats {
WAN_IOCTL_ADD_FLT_RULE_EX, \
struct ipa_install_fltr_rule_req_ex_msg_v01 *)
+#define WAN_IOC_QUERY_TETHER_STATS_ALL _IOWR(WAN_IOC_MAGIC, \
+ WAN_IOCTL_QUERY_TETHER_STATS_ALL, \
+ struct wan_ioctl_query_tether_stats_all *)
+
#endif /* _RMNET_IPA_FD_IOCTL_H */
diff --git a/include/uapi/sound/compress_offload.h b/include/uapi/sound/compress_offload.h
index 30481056cce1..866ec3d2af69 100644
--- a/include/uapi/sound/compress_offload.h
+++ b/include/uapi/sound/compress_offload.h
@@ -149,6 +149,8 @@ struct snd_compr_audio_info {
* @SNDRV_COMPRESS_CLK_REC_MODE: clock recovery mode ( none or auto)
* @SNDRV_COMPRESS_RENDER_WINDOW: render window
* @SNDRV_COMPRESS_START_DELAY: start delay
+ * @SNDRV_COMPRESS_ENABLE_ADJUST_SESSION_CLOCK: enable dsp drift correction
+ * @SNDRV_COMPRESS_ADJUST_SESSION_CLOCK: set drift correction value
*/
enum sndrv_compress_encoder {
SNDRV_COMPRESS_ENCODER_PADDING = 1,
@@ -160,6 +162,8 @@ enum sndrv_compress_encoder {
SNDRV_COMPRESS_CLK_REC_MODE = 7,
SNDRV_COMPRESS_RENDER_WINDOW = 8,
SNDRV_COMPRESS_START_DELAY = 9,
+ SNDRV_COMPRESS_ENABLE_ADJUST_SESSION_CLOCK = 10,
+ SNDRV_COMPRESS_ADJUST_SESSION_CLOCK = 11,
};
#define SNDRV_COMPRESS_PATH_DELAY SNDRV_COMPRESS_PATH_DELAY
@@ -167,6 +171,9 @@ enum sndrv_compress_encoder {
#define SNDRV_COMPRESS_CLK_REC_MODE SNDRV_COMPRESS_CLK_REC_MODE
#define SNDRV_COMPRESS_RENDER_WINDOW SNDRV_COMPRESS_RENDER_WINDOW
#define SNDRV_COMPRESS_START_DELAY SNDRV_COMPRESS_START_DELAY
+#define SNDRV_COMPRESS_ENABLE_ADJUST_SESSION_CLOCK \
+ SNDRV_COMPRESS_ENABLE_ADJUST_SESSION_CLOCK
+#define SNDRV_COMPRESS_ADJUST_SESSION_CLOCK SNDRV_COMPRESS_ADJUST_SESSION_CLOCK
/**
* struct snd_compr_metadata - compressed stream metadata
diff --git a/net/9p/client.c b/net/9p/client.c
index ea79ee9a7348..f5feac4ff4ec 100644
--- a/net/9p/client.c
+++ b/net/9p/client.c
@@ -2101,6 +2101,10 @@ int p9_client_readdir(struct p9_fid *fid, char *data, u32 count, u64 offset)
trace_9p_protocol_dump(clnt, req->rc);
goto free_and_error;
}
+ if (rsize < count) {
+ pr_err("bogus RREADDIR count (%d > %d)\n", count, rsize);
+ count = rsize;
+ }
p9_debug(P9_DEBUG_9P, "<<< RREADDIR count %d\n", count);
diff --git a/net/core/neighbour.c b/net/core/neighbour.c
index f1e575d7f21a..54ab748238d1 100644
--- a/net/core/neighbour.c
+++ b/net/core/neighbour.c
@@ -859,7 +859,8 @@ static void neigh_probe(struct neighbour *neigh)
if (skb)
skb = skb_clone(skb, GFP_ATOMIC);
write_unlock(&neigh->lock);
- neigh->ops->solicit(neigh, skb);
+ if (neigh->ops->solicit)
+ neigh->ops->solicit(neigh, skb);
atomic_inc(&neigh->probes);
kfree_skb(skb);
}
diff --git a/net/core/netpoll.c b/net/core/netpoll.c
index 94acfc89ad97..440aa9f6e0a8 100644
--- a/net/core/netpoll.c
+++ b/net/core/netpoll.c
@@ -105,15 +105,21 @@ static void queue_process(struct work_struct *work)
while ((skb = skb_dequeue(&npinfo->txq))) {
struct net_device *dev = skb->dev;
struct netdev_queue *txq;
+ unsigned int q_index;
if (!netif_device_present(dev) || !netif_running(dev)) {
kfree_skb(skb);
continue;
}
- txq = skb_get_tx_queue(dev, skb);
-
local_irq_save(flags);
+ /* check if skb->queue_mapping is still valid */
+ q_index = skb_get_queue_mapping(skb);
+ if (unlikely(q_index >= dev->real_num_tx_queues)) {
+ q_index = q_index % dev->real_num_tx_queues;
+ skb_set_queue_mapping(skb, q_index);
+ }
+ txq = netdev_get_tx_queue(dev, q_index);
HARD_TX_LOCK(dev, txq, smp_processor_id());
if (netif_xmit_frozen_or_stopped(txq) ||
netpoll_start_xmit(skb, dev, txq) != NETDEV_TX_OK) {
diff --git a/net/ipv4/route.c b/net/ipv4/route.c
index d162ce41f761..7e31491e9396 100644
--- a/net/ipv4/route.c
+++ b/net/ipv4/route.c
@@ -2571,7 +2571,7 @@ static int inet_rtm_getroute(struct sk_buff *in_skb, struct nlmsghdr *nlh)
skb_reset_network_header(skb);
/* Bugfix: need to give ip_route_input enough of an IP header to not gag. */
- ip_hdr(skb)->protocol = IPPROTO_ICMP;
+ ip_hdr(skb)->protocol = IPPROTO_UDP;
skb_reserve(skb, MAX_HEADER + sizeof(struct iphdr));
src = tb[RTA_SRC] ? nla_get_in_addr(tb[RTA_SRC]) : 0;
diff --git a/net/ipv4/tcp.c b/net/ipv4/tcp.c
index 4ab7735e43ab..62815497f29c 100644
--- a/net/ipv4/tcp.c
+++ b/net/ipv4/tcp.c
@@ -2269,6 +2269,7 @@ int tcp_disconnect(struct sock *sk, int flags)
tcp_init_send_head(sk);
memset(&tp->rx_opt, 0, sizeof(tp->rx_opt));
__sk_dst_reset(sk);
+ tcp_saved_syn_free(tp);
WARN_ON(inet->inet_num && !icsk->icsk_bind_hash);
diff --git a/net/ipv6/ip6_tunnel.c b/net/ipv6/ip6_tunnel.c
index 8b11a49c7dd7..600975c5eacf 100644
--- a/net/ipv6/ip6_tunnel.c
+++ b/net/ipv6/ip6_tunnel.c
@@ -1049,7 +1049,7 @@ static int ip6_tnl_xmit2(struct sk_buff *skb,
struct ip6_tnl *t = netdev_priv(dev);
struct net *net = t->net;
struct net_device_stats *stats = &t->dev->stats;
- struct ipv6hdr *ipv6h = ipv6_hdr(skb);
+ struct ipv6hdr *ipv6h;
struct ipv6_tel_txoption opt;
struct dst_entry *dst = NULL, *ndst = NULL;
struct net_device *tdev;
@@ -1061,26 +1061,28 @@ static int ip6_tnl_xmit2(struct sk_buff *skb,
/* NBMA tunnel */
if (ipv6_addr_any(&t->parms.raddr)) {
- struct in6_addr *addr6;
- struct neighbour *neigh;
- int addr_type;
+ if (skb->protocol == htons(ETH_P_IPV6)) {
+ struct in6_addr *addr6;
+ struct neighbour *neigh;
+ int addr_type;
- if (!skb_dst(skb))
- goto tx_err_link_failure;
+ if (!skb_dst(skb))
+ goto tx_err_link_failure;
- neigh = dst_neigh_lookup(skb_dst(skb),
- &ipv6_hdr(skb)->daddr);
- if (!neigh)
- goto tx_err_link_failure;
+ neigh = dst_neigh_lookup(skb_dst(skb),
+ &ipv6_hdr(skb)->daddr);
+ if (!neigh)
+ goto tx_err_link_failure;
- addr6 = (struct in6_addr *)&neigh->primary_key;
- addr_type = ipv6_addr_type(addr6);
+ addr6 = (struct in6_addr *)&neigh->primary_key;
+ addr_type = ipv6_addr_type(addr6);
- if (addr_type == IPV6_ADDR_ANY)
- addr6 = &ipv6_hdr(skb)->daddr;
+ if (addr_type == IPV6_ADDR_ANY)
+ addr6 = &ipv6_hdr(skb)->daddr;
- memcpy(&fl6->daddr, addr6, sizeof(fl6->daddr));
- neigh_release(neigh);
+ memcpy(&fl6->daddr, addr6, sizeof(fl6->daddr));
+ neigh_release(neigh);
+ }
} else if (!(t->parms.flags &
(IP6_TNL_F_USE_ORIG_TCLASS | IP6_TNL_F_USE_ORIG_FWMARK))) {
/* enable the cache only only if the routing decision does
diff --git a/net/ipv6/ip6mr.c b/net/ipv6/ip6mr.c
index d9843e5a667f..8361d73ab653 100644
--- a/net/ipv6/ip6mr.c
+++ b/net/ipv6/ip6mr.c
@@ -774,7 +774,8 @@ failure:
* Delete a VIF entry
*/
-static int mif6_delete(struct mr6_table *mrt, int vifi, struct list_head *head)
+static int mif6_delete(struct mr6_table *mrt, int vifi, int notify,
+ struct list_head *head)
{
struct mif_device *v;
struct net_device *dev;
@@ -820,7 +821,7 @@ static int mif6_delete(struct mr6_table *mrt, int vifi, struct list_head *head)
dev->ifindex, &in6_dev->cnf);
}
- if (v->flags & MIFF_REGISTER)
+ if ((v->flags & MIFF_REGISTER) && !notify)
unregister_netdevice_queue(dev, head);
dev_put(dev);
@@ -1330,7 +1331,6 @@ static int ip6mr_device_event(struct notifier_block *this,
struct mr6_table *mrt;
struct mif_device *v;
int ct;
- LIST_HEAD(list);
if (event != NETDEV_UNREGISTER)
return NOTIFY_DONE;
@@ -1339,10 +1339,9 @@ static int ip6mr_device_event(struct notifier_block *this,
v = &mrt->vif6_table[0];
for (ct = 0; ct < mrt->maxvif; ct++, v++) {
if (v->dev == dev)
- mif6_delete(mrt, ct, &list);
+ mif6_delete(mrt, ct, 1, NULL);
}
}
- unregister_netdevice_many(&list);
return NOTIFY_DONE;
}
@@ -1551,7 +1550,7 @@ static void mroute_clean_tables(struct mr6_table *mrt, bool all)
for (i = 0; i < mrt->maxvif; i++) {
if (!all && (mrt->vif6_table[i].flags & VIFF_STATIC))
continue;
- mif6_delete(mrt, i, &list);
+ mif6_delete(mrt, i, 0, &list);
}
unregister_netdevice_many(&list);
@@ -1704,7 +1703,7 @@ int ip6_mroute_setsockopt(struct sock *sk, int optname, char __user *optval, uns
if (copy_from_user(&mifi, optval, sizeof(mifi_t)))
return -EFAULT;
rtnl_lock();
- ret = mif6_delete(mrt, mifi, NULL);
+ ret = mif6_delete(mrt, mifi, 0, NULL);
rtnl_unlock();
return ret;
diff --git a/net/ipv6/raw.c b/net/ipv6/raw.c
index d503b7f373a3..6896830feabb 100644
--- a/net/ipv6/raw.c
+++ b/net/ipv6/raw.c
@@ -1145,8 +1145,7 @@ static int rawv6_ioctl(struct sock *sk, int cmd, unsigned long arg)
spin_lock_bh(&sk->sk_receive_queue.lock);
skb = skb_peek(&sk->sk_receive_queue);
if (skb)
- amount = skb_tail_pointer(skb) -
- skb_transport_header(skb);
+ amount = skb->len;
spin_unlock_bh(&sk->sk_receive_queue.lock);
return put_user(amount, (int __user *)arg);
}
diff --git a/net/ipv6/route.c b/net/ipv6/route.c
index 31e172cd84ac..ff1499293938 100644
--- a/net/ipv6/route.c
+++ b/net/ipv6/route.c
@@ -1756,6 +1756,10 @@ static struct rt6_info *ip6_route_info_create(struct fib6_config *cfg)
int addr_type;
int err = -EINVAL;
+ /* RTF_PCPU is an internal flag; can not be set by userspace */
+ if (cfg->fc_flags & RTF_PCPU)
+ goto out;
+
if (cfg->fc_dst_len > 128 || cfg->fc_src_len > 128)
goto out;
#ifndef CONFIG_IPV6_SUBTREES
diff --git a/net/l2tp/l2tp_core.c b/net/l2tp/l2tp_core.c
index ec17cbe8a02b..d3dec414fd44 100644
--- a/net/l2tp/l2tp_core.c
+++ b/net/l2tp/l2tp_core.c
@@ -278,7 +278,8 @@ struct l2tp_session *l2tp_session_find(struct net *net, struct l2tp_tunnel *tunn
}
EXPORT_SYMBOL_GPL(l2tp_session_find);
-struct l2tp_session *l2tp_session_find_nth(struct l2tp_tunnel *tunnel, int nth)
+struct l2tp_session *l2tp_session_get_nth(struct l2tp_tunnel *tunnel, int nth,
+ bool do_ref)
{
int hash;
struct l2tp_session *session;
@@ -288,6 +289,9 @@ struct l2tp_session *l2tp_session_find_nth(struct l2tp_tunnel *tunnel, int nth)
for (hash = 0; hash < L2TP_HASH_SIZE; hash++) {
hlist_for_each_entry(session, &tunnel->session_hlist[hash], hlist) {
if (++count > nth) {
+ l2tp_session_inc_refcount(session);
+ if (do_ref && session->ref)
+ session->ref(session);
read_unlock_bh(&tunnel->hlist_lock);
return session;
}
@@ -298,7 +302,7 @@ struct l2tp_session *l2tp_session_find_nth(struct l2tp_tunnel *tunnel, int nth)
return NULL;
}
-EXPORT_SYMBOL_GPL(l2tp_session_find_nth);
+EXPORT_SYMBOL_GPL(l2tp_session_get_nth);
/* Lookup a session by interface name.
* This is very inefficient but is only used by management interfaces.
diff --git a/net/l2tp/l2tp_core.h b/net/l2tp/l2tp_core.h
index 763e8e241ce3..555d962a62d2 100644
--- a/net/l2tp/l2tp_core.h
+++ b/net/l2tp/l2tp_core.h
@@ -243,7 +243,8 @@ out:
struct l2tp_session *l2tp_session_find(struct net *net,
struct l2tp_tunnel *tunnel,
u32 session_id);
-struct l2tp_session *l2tp_session_find_nth(struct l2tp_tunnel *tunnel, int nth);
+struct l2tp_session *l2tp_session_get_nth(struct l2tp_tunnel *tunnel, int nth,
+ bool do_ref);
struct l2tp_session *l2tp_session_find_by_ifname(struct net *net, char *ifname);
struct l2tp_tunnel *l2tp_tunnel_find(struct net *net, u32 tunnel_id);
struct l2tp_tunnel *l2tp_tunnel_find_nth(struct net *net, int nth);
diff --git a/net/l2tp/l2tp_debugfs.c b/net/l2tp/l2tp_debugfs.c
index 2d6760a2ae34..d100aed3d06f 100644
--- a/net/l2tp/l2tp_debugfs.c
+++ b/net/l2tp/l2tp_debugfs.c
@@ -53,7 +53,7 @@ static void l2tp_dfs_next_tunnel(struct l2tp_dfs_seq_data *pd)
static void l2tp_dfs_next_session(struct l2tp_dfs_seq_data *pd)
{
- pd->session = l2tp_session_find_nth(pd->tunnel, pd->session_idx);
+ pd->session = l2tp_session_get_nth(pd->tunnel, pd->session_idx, true);
pd->session_idx++;
if (pd->session == NULL) {
@@ -238,10 +238,14 @@ static int l2tp_dfs_seq_show(struct seq_file *m, void *v)
}
/* Show the tunnel or session context */
- if (pd->session == NULL)
+ if (!pd->session) {
l2tp_dfs_seq_tunnel_show(m, pd->tunnel);
- else
+ } else {
l2tp_dfs_seq_session_show(m, pd->session);
+ if (pd->session->deref)
+ pd->session->deref(pd->session);
+ l2tp_session_dec_refcount(pd->session);
+ }
out:
return 0;
diff --git a/net/l2tp/l2tp_netlink.c b/net/l2tp/l2tp_netlink.c
index 2caaa84ce92d..665cc74df5c5 100644
--- a/net/l2tp/l2tp_netlink.c
+++ b/net/l2tp/l2tp_netlink.c
@@ -827,7 +827,7 @@ static int l2tp_nl_cmd_session_dump(struct sk_buff *skb, struct netlink_callback
goto out;
}
- session = l2tp_session_find_nth(tunnel, si);
+ session = l2tp_session_get_nth(tunnel, si, false);
if (session == NULL) {
ti++;
tunnel = NULL;
@@ -837,8 +837,11 @@ static int l2tp_nl_cmd_session_dump(struct sk_buff *skb, struct netlink_callback
if (l2tp_nl_session_send(skb, NETLINK_CB(cb->skb).portid,
cb->nlh->nlmsg_seq, NLM_F_MULTI,
- session, L2TP_CMD_SESSION_GET) < 0)
+ session, L2TP_CMD_SESSION_GET) < 0) {
+ l2tp_session_dec_refcount(session);
break;
+ }
+ l2tp_session_dec_refcount(session);
si++;
}
diff --git a/net/l2tp/l2tp_ppp.c b/net/l2tp/l2tp_ppp.c
index 1ad18c55064c..8ab9c5d74416 100644
--- a/net/l2tp/l2tp_ppp.c
+++ b/net/l2tp/l2tp_ppp.c
@@ -467,6 +467,10 @@ static void pppol2tp_session_close(struct l2tp_session *session)
static void pppol2tp_session_destruct(struct sock *sk)
{
struct l2tp_session *session = sk->sk_user_data;
+
+ skb_queue_purge(&sk->sk_receive_queue);
+ skb_queue_purge(&sk->sk_write_queue);
+
if (session) {
sk->sk_user_data = NULL;
BUG_ON(session->magic != L2TP_SESSION_MAGIC);
@@ -505,9 +509,6 @@ static int pppol2tp_release(struct socket *sock)
l2tp_session_queue_purge(session);
sock_put(sk);
}
- skb_queue_purge(&sk->sk_receive_queue);
- skb_queue_purge(&sk->sk_write_queue);
-
release_sock(sk);
/* This will delete the session context via
@@ -1574,7 +1575,7 @@ static void pppol2tp_next_tunnel(struct net *net, struct pppol2tp_seq_data *pd)
static void pppol2tp_next_session(struct net *net, struct pppol2tp_seq_data *pd)
{
- pd->session = l2tp_session_find_nth(pd->tunnel, pd->session_idx);
+ pd->session = l2tp_session_get_nth(pd->tunnel, pd->session_idx, true);
pd->session_idx++;
if (pd->session == NULL) {
@@ -1701,10 +1702,14 @@ static int pppol2tp_seq_show(struct seq_file *m, void *v)
/* Show the tunnel or session context.
*/
- if (pd->session == NULL)
+ if (!pd->session) {
pppol2tp_seq_tunnel_show(m, pd->tunnel);
- else
+ } else {
pppol2tp_seq_session_show(m, pd->session);
+ if (pd->session->deref)
+ pd->session->deref(pd->session);
+ l2tp_session_dec_refcount(pd->session);
+ }
out:
return 0;
@@ -1863,4 +1868,4 @@ MODULE_DESCRIPTION("PPP over L2TP over UDP");
MODULE_LICENSE("GPL");
MODULE_VERSION(PPPOL2TP_DRV_VERSION);
MODULE_ALIAS("pppox-proto-" __stringify(PX_PROTO_OL2TP));
-MODULE_ALIAS_L2TP_PWTYPE(11);
+MODULE_ALIAS_L2TP_PWTYPE(7);
diff --git a/net/packet/af_packet.c b/net/packet/af_packet.c
index d76800108ddb..f8d6a0ca9c03 100644
--- a/net/packet/af_packet.c
+++ b/net/packet/af_packet.c
@@ -3626,6 +3626,8 @@ packet_setsockopt(struct socket *sock, int level, int optname, char __user *optv
return -EBUSY;
if (copy_from_user(&val, optval, sizeof(val)))
return -EFAULT;
+ if (val > INT_MAX)
+ return -EINVAL;
po->tp_reserve = val;
return 0;
}
@@ -4150,6 +4152,8 @@ static int packet_set_ring(struct sock *sk, union tpacket_req_u *req_u,
rb->frames_per_block = req->tp_block_size / req->tp_frame_size;
if (unlikely(rb->frames_per_block == 0))
goto out;
+ if (unlikely(req->tp_block_size > UINT_MAX / req->tp_block_nr))
+ goto out;
if (unlikely((rb->frames_per_block * req->tp_block_nr) !=
req->tp_frame_nr))
goto out;
diff --git a/net/rds/cong.c b/net/rds/cong.c
index e6144b8246fd..6641bcf7c185 100644
--- a/net/rds/cong.c
+++ b/net/rds/cong.c
@@ -299,7 +299,7 @@ void rds_cong_set_bit(struct rds_cong_map *map, __be16 port)
i = be16_to_cpu(port) / RDS_CONG_MAP_PAGE_BITS;
off = be16_to_cpu(port) % RDS_CONG_MAP_PAGE_BITS;
- __set_bit_le(off, (void *)map->m_page_addrs[i]);
+ set_bit_le(off, (void *)map->m_page_addrs[i]);
}
void rds_cong_clear_bit(struct rds_cong_map *map, __be16 port)
@@ -313,7 +313,7 @@ void rds_cong_clear_bit(struct rds_cong_map *map, __be16 port)
i = be16_to_cpu(port) / RDS_CONG_MAP_PAGE_BITS;
off = be16_to_cpu(port) % RDS_CONG_MAP_PAGE_BITS;
- __clear_bit_le(off, (void *)map->m_page_addrs[i]);
+ clear_bit_le(off, (void *)map->m_page_addrs[i]);
}
static int rds_cong_test_bit(struct rds_cong_map *map, __be16 port)
diff --git a/net/sched/act_mirred.c b/net/sched/act_mirred.c
index e384d6aefa3a..1090a52c03cd 100644
--- a/net/sched/act_mirred.c
+++ b/net/sched/act_mirred.c
@@ -36,14 +36,15 @@ static DEFINE_SPINLOCK(mirred_list_lock);
static void tcf_mirred_release(struct tc_action *a, int bind)
{
struct tcf_mirred *m = to_mirred(a);
- struct net_device *dev = rcu_dereference_protected(m->tcfm_dev, 1);
+ struct net_device *dev;
/* We could be called either in a RCU callback or with RTNL lock held. */
spin_lock_bh(&mirred_list_lock);
list_del(&m->tcfm_list);
- spin_unlock_bh(&mirred_list_lock);
+ dev = rcu_dereference_protected(m->tcfm_dev, 1);
if (dev)
dev_put(dev);
+ spin_unlock_bh(&mirred_list_lock);
}
static const struct nla_policy mirred_policy[TCA_MIRRED_MAX + 1] = {
diff --git a/net/sctp/socket.c b/net/sctp/socket.c
index 5758818435f3..c96d666cef29 100644
--- a/net/sctp/socket.c
+++ b/net/sctp/socket.c
@@ -6394,6 +6394,9 @@ int sctp_inet_listen(struct socket *sock, int backlog)
if (sock->state != SS_UNCONNECTED)
goto out;
+ if (!sctp_sstate(sk, LISTENING) && !sctp_sstate(sk, CLOSED))
+ goto out;
+
/* If backlog is zero, disable listening. */
if (!backlog) {
if (sctp_sstate(sk, CLOSED))
diff --git a/net/wireless/db.txt b/net/wireless/db.txt
index 44cb3dc1b2de..3c431e49aef1 100644
--- a/net/wireless/db.txt
+++ b/net/wireless/db.txt
@@ -84,7 +84,7 @@ country AT: DFS-ETSI
(5900 - 5920 @ 10), (30)
(5910 - 5930 @ 10), (30)
# 60 gHz band channels 1-4, ref: Etsi En 302 567
- (57240 - 65880 @ 2160), (40), NO-OUTDOOR
+ (57000 - 66000 @ 2160), (40)
country AU: DFS-FCC
(2402 - 2482 @ 40), (20)
@@ -93,7 +93,6 @@ country AU: DFS-FCC
(5490 - 5590 @ 80), (24), DFS
(5650 - 5730 @ 80), (24), DFS
(5735 - 5835 @ 80), (30)
-
# 60 gHz band channels 1-4
(57240 - 65880 @ 2160), (43), NO-OUTDOOR
@@ -139,7 +138,7 @@ country BE: DFS-ETSI
(5900 - 5920 @ 10), (30)
(5910 - 5930 @ 10), (30)
# 60 gHz band channels 1-4, ref: Etsi En 302 567
- (57240 - 65880 @ 2160), (40)
+ (57000 - 66000 @ 2160), (40)
country BF: DFS-FCC
(2402 - 2482 @ 40), (20)
@@ -163,7 +162,7 @@ country BG: DFS-ETSI
(5900 - 5920 @ 10), (30)
(5910 - 5930 @ 10), (30)
# 60 gHz band channels 1-4, ref: Etsi En 302 567
- (57240 - 65880 @ 2160), (40), NO-OUTDOOR
+ (57000 - 66000 @ 2160), (40)
country BH:
(2402 - 2482 @ 40), (20)
@@ -193,7 +192,6 @@ country BO: DFS-ETSI
(2402 - 2482 @ 40), (20)
(5250 - 5330 @ 80), (30), DFS
(5735 - 5835 @ 80), (30)
-
# 60 gHz band channels 1-3, FCC
(57240 - 63720 @ 2160), (40)
@@ -203,7 +201,6 @@ country BR: DFS-FCC
(5250 - 5330 @ 80), (24), DFS, AUTO-BW
(5490 - 5730 @ 160), (24), DFS
(5735 - 5835 @ 80), (30)
-
# 60 gHz band channels 1-3
(57240 - 63720 @ 2160), (40)
@@ -239,7 +236,6 @@ country CA: DFS-FCC
(5490 - 5590 @ 80), (24), DFS
(5650 - 5730 @ 80), (24), DFS
(5735 - 5835 @ 80), (30)
-
# 60 gHz band channels 1-3
(57240 - 63720 @ 2160), (40)
@@ -264,9 +260,8 @@ country CH: DFS-ETSI
(5890 - 5910 @ 10), (30)
(5900 - 5920 @ 10), (30)
(5910 - 5930 @ 10), (30)
-
# 60 gHz band channels 1-4, ref: Etsi En 302 567
- (57240 - 65880 @ 2160), (40), NO-OUTDOOR
+ (57000 - 66000 @ 2160), (40)
country CI: DFS-FCC
(2402 - 2482 @ 40), (20)
@@ -279,7 +274,6 @@ country CL:
(2402 - 2482 @ 40), (20)
(5170 - 5330 @ 160), (20)
(5735 - 5835 @ 80), (20)
-
# 60 gHz band channels 1-3
(57240 - 63720 @ 2160), (50), NO-OUTDOOR
@@ -304,7 +298,6 @@ country CR: DFS-FCC
(5250 - 5330 @ 20), (24), DFS
(5490 - 5730 @ 20), (24), DFS
(5735 - 5835 @ 20), (30)
-
# 60 gHz band channels 1-3
(57240 - 63720 @ 2160), (30)
@@ -330,7 +323,7 @@ country CY: DFS-ETSI
(5900 - 5920 @ 10), (30)
(5910 - 5930 @ 10), (30)
# 60 gHz band channels 1-4, ref: Etsi En 302 567
- (57240 - 65880 @ 2160), (40), NO-OUTDOOR
+ (57000 - 66000 @ 2160), (40)
# Data from http://www.ctu.eu/164/download/VOR/VOR-12-08-2005-34.pdf
# and http://www.ctu.eu/164/download/VOR/VOR-12-05-2007-6-AN.pdf
@@ -349,7 +342,7 @@ country CZ: DFS-ETSI
(5900 - 5920 @ 10), (30)
(5910 - 5930 @ 10), (30)
# 60 gHz band channels 1-4, ref: Etsi En 302 567
- (57240 - 65880 @ 2160), (40), NO-OUTDOOR
+ (57000 - 66000 @ 2160), (40)
# Data from "Frequenznutzungsplan" (as published in April 2008), downloaded from
# http://www.bundesnetzagentur.de/cae/servlet/contentblob/38448/publicationFile/2659/Frequenznutzungsplan2008_Id17448pdf.pdf
@@ -372,7 +365,7 @@ country DE: DFS-ETSI
(5900 - 5920 @ 10), (30)
(5910 - 5930 @ 10), (30)
# 60 gHz band channels 1-4, ref: Etsi En 302 567
- (57240 - 65880 @ 2160), (40), NO-OUTDOOR
+ (57000 - 66000 @ 2160), (40)
country DK: DFS-ETSI
(2402 - 2482 @ 40), (20)
@@ -389,7 +382,7 @@ country DK: DFS-ETSI
(5900 - 5920 @ 10), (30)
(5910 - 5930 @ 10), (30)
# 60 gHz band channels 1-4, ref: Etsi En 302 567
- (57240 - 65880 @ 2160), (40), NO-OUTDOOR
+ (57000 - 66000 @ 2160), (40)
country DM: DFS-FCC
(2402 - 2472 @ 40), (30)
@@ -415,7 +408,6 @@ country EC: DFS-FCC
(5250 - 5330 @ 20), (24), DFS
(5490 - 5730 @ 20), (24), DFS
(5735 - 5835 @ 20), (30)
-
# 60 gHz band channels 1-3, FCC
(57240 - 63720 @ 2160), (40)
@@ -434,7 +426,7 @@ country EE: DFS-ETSI
(5900 - 5920 @ 10), (30)
(5910 - 5930 @ 10), (30)
# 60 gHz band channels 1-4, ref: Etsi En 302 567
- (57240 - 65880 @ 2160), (40), NO-OUTDOOR
+ (57000 - 66000 @ 2160), (40)
country EG: DFS-ETSI
(2402 - 2482 @ 40), (20)
@@ -456,7 +448,7 @@ country ES: DFS-ETSI
(5900 - 5920 @ 10), (30)
(5910 - 5930 @ 10), (30)
# 60 gHz band channels 1-4, ref: Etsi En 302 567
- (57240 - 65880 @ 2160), (40), NO-OUTDOOR
+ (57000 - 66000 @ 2160), (40)
country ET: DFS-ETSI
(2402 - 2482 @ 40), (20)
@@ -479,7 +471,7 @@ country FI: DFS-ETSI
(5900 - 5920 @ 10), (30)
(5910 - 5930 @ 10), (30)
# 60 gHz band channels 1-4, ref: Etsi En 302 567
- (57240 - 65880 @ 2160), (40), NO-OUTDOOR
+ (57000 - 66000 @ 2160), (40)
country FM: DFS-FCC
(2402 - 2472 @ 40), (30)
@@ -503,7 +495,7 @@ country FR: DFS-ETSI
(5900 - 5920 @ 10), (30)
(5910 - 5930 @ 10), (30)
# 60 gHz band channels 1-4, ref: Etsi En 302 567
- (57240 - 65880 @ 2160), (40), NO-OUTDOOR
+ (57000 - 66000 @ 2160), (40)
country GB: DFS-ETSI
(2402 - 2482 @ 40), (20)
@@ -520,7 +512,7 @@ country GB: DFS-ETSI
(5900 - 5920 @ 10), (30)
(5910 - 5930 @ 10), (30)
# 60 gHz band channels 1-4, ref: Etsi En 302 567
- (57240 - 65880 @ 2160), (40), NO-OUTDOOR
+ (57000 - 66000 @ 2160), (40)
country GD: DFS-FCC
(2402 - 2472 @ 40), (30)
@@ -574,7 +566,7 @@ country GR: DFS-ETSI
(5900 - 5920 @ 10), (30)
(5910 - 5930 @ 10), (30)
# 60 gHz band channels 1-4, ref: Etsi En 302 567
- (57240 - 65880 @ 2160), (40), NO-OUTDOOR
+ (57000 - 66000 @ 2160), (40)
country GT: DFS-ETSI
(2402 - 2482 @ 40), (20)
@@ -588,7 +580,6 @@ country GU: DFS-FCC
(5250 - 5330 @ 80), (24), DFS, AUTO-BW
(5490 - 5730 @ 160), (24), DFS
(5735 - 5835 @ 80), (30)
-
# 60 gHz band channels 1-3, FCC
(57240 - 63720 @ 2160), (40)
@@ -602,7 +593,6 @@ country HK: DFS-FCC
(5250 - 5330 @ 80), (24), DFS, AUTO-BW
(5490 - 5730 @ 160), (24), DFS
(5735 - 5835 @ 80), (30)
-
# 60 gHz band channels 1-4, ref: FCC/EU
(57240 - 65880 @ 2160), (40)
@@ -611,7 +601,6 @@ country HN:
(5170 - 5330 @ 160), (24)
(5490 - 5730 @ 160), (24)
(5735 - 5835 @ 80), (30)
-
# 60 gHz band channels 1-3, FCC
(57240 - 63720 @ 2160), (40)
@@ -630,7 +619,7 @@ country HR: DFS-ETSI
(5900 - 5920 @ 10), (30)
(5910 - 5930 @ 10), (30)
# 60 gHz band channels 1-4, ref: Etsi En 302 567
- (57240 - 65880 @ 2160), (40), NO-OUTDOOR
+ (57000 - 66000 @ 2160), (40)
country HT: DFS-FCC
(2402 - 2472 @ 40), (30)
@@ -654,7 +643,7 @@ country HU: DFS-ETSI
(5900 - 5920 @ 10), (30)
(5910 - 5930 @ 10), (30)
# 60 gHz band channels 1-4, ref: Etsi En 302 567
- (57240 - 65880 @ 2160), (40), NO-OUTDOOR
+ (57000 - 66000 @ 2160), (40)
country ID:
# ref: http://www.postel.go.id/content/ID/regulasi/standardisasi/kepdir/bwa%205,8%20ghz.pdf
@@ -676,15 +665,14 @@ country IE: DFS-ETSI
(5900 - 5920 @ 10), (30)
(5910 - 5930 @ 10), (30)
# 60 gHz band channels 1-4, ref: Etsi En 302 567
- (57240 - 65880 @ 2160), (40), NO-OUTDOOR
+ (57000 - 66000 @ 2160), (40)
country IL: DFS-ETSI
(2402 - 2482 @ 40), (20)
(5170 - 5250 @ 80), (23), AUTO-BW
(5250 - 5330 @ 80), (23), DFS, AUTO-BW
-
# 60 gHz band channels 1-4, base on Etsi En 302 567
- (57240 - 65880 @ 2160), (40), NO-OUTDOOR
+ (57000 - 66000 @ 2160), (40)
country IN:
(2402 - 2482 @ 40), (20)
@@ -710,7 +698,7 @@ country IS: DFS-ETSI
(5900 - 5920 @ 10), (30)
(5910 - 5930 @ 10), (30)
# 60 gHz band channels 1-4, ref: Etsi En 302 567
- (57240 - 65880 @ 2160), (40), NO-OUTDOOR
+ (57000 - 66000 @ 2160), (40)
country IT: DFS-ETSI
(2402 - 2482 @ 40), (20)
@@ -727,7 +715,7 @@ country IT: DFS-ETSI
(5900 - 5920 @ 10), (30)
(5910 - 5930 @ 10), (30)
# 60 gHz band channels 1-4, ref: Etsi En 302 567
- (57240 - 65880 @ 2160), (40), NO-OUTDOOR
+ (57000 - 66000 @ 2160), (40)
country JM: DFS-FCC
(2402 - 2482 @ 40), (20)
@@ -735,7 +723,6 @@ country JM: DFS-FCC
(5250 - 5330 @ 80), (24), DFS, AUTO-BW
(5490 - 5730 @ 160), (24), DFS
(5735 - 5835 @ 80), (30)
-
# 60 gHz band channels 1-3, FCC
(57240 - 63720 @ 2160), (40)
@@ -743,9 +730,8 @@ country JO:
(2402 - 2482 @ 40), (20)
(5170 - 5250 @ 80), (23)
(5735 - 5835 @ 80), (23)
-
# 60 gHz band channels 1-4, ref: Etsi En 302 567
- (57240 - 65880 @ 2160), (40), NO-OUTDOOR
+ ((57000 - 66000 @ 2160), (40)
country JP: DFS-JP
(2402 - 2482 @ 40), (20)
@@ -835,9 +821,8 @@ country LI: DFS-ETSI
(5890 - 5910 @ 10), (30)
(5900 - 5920 @ 10), (30)
(5910 - 5930 @ 10), (30)
-
# 60 gHz band channels 1-4, ref: Etsi En 302 567
- (57240 - 65880 @ 2160), (40), NO-OUTDOOR
+ (57000 - 66000 @ 2160), (40)
country LK: DFS-FCC
(2402 - 2482 @ 40), (20)
@@ -867,7 +852,7 @@ country LT: DFS-ETSI
(5900 - 5920 @ 10), (30)
(5910 - 5930 @ 10), (30)
# 60 gHz band channels 1-4, ref: Etsi En 302 567
- (57240 - 65880 @ 2160), (40), NO-OUTDOOR
+ (57000 - 66000 @ 2160), (40)
country LU: DFS-ETSI
(2402 - 2482 @ 40), (20)
@@ -884,7 +869,7 @@ country LU: DFS-ETSI
(5900 - 5920 @ 10), (30)
(5910 - 5930 @ 10), (30)
# 60 gHz band channels 1-4, ref: Etsi En 302 567
- (57240 - 65880 @ 2160), (40), NO-OUTDOOR
+ (57000 - 66000 @ 2160), (40)
country LV: DFS-ETSI
(2402 - 2482 @ 40), (20)
@@ -900,17 +885,15 @@ country LV: DFS-ETSI
(5890 - 5910 @ 10), (30)
(5900 - 5920 @ 10), (30)
(5910 - 5930 @ 10), (30)
-
# 60 gHz band channels 1-4, ref: Etsi En 302 567
- (57240 - 65880 @ 2160), (40), NO-OUTDOOR
+ (57000 - 66000 @ 2160), (40)
country MA: DFS-ETSI
(2402 - 2482 @ 40), (20)
(5170 - 5250 @ 80), (23), AUTO-BW
(5250 - 5330 @ 80), (23), DFS, AUTO-BW
-
# 60 gHz band channels 1-4, ref: Etsi En 302 567
- (57240 - 65880 @ 2160), (40), NO-OUTDOOR
+ (57000 - 66000 @ 2160), (40)
country MC: DFS-ETSI
(2402 - 2482 @ 40), (20)
@@ -997,7 +980,7 @@ country MT: DFS-ETSI
(5900 - 5920 @ 10), (30)
(5910 - 5930 @ 10), (30)
# 60 gHz band channels 1-4, ref: Etsi En 302 567
- (57240 - 65880 @ 2160), (40), NO-OUTDOOR
+ (57000 - 66000 @ 2160), (40)
country MU: DFS-FCC
(2402 - 2482 @ 40), (20)
@@ -1024,7 +1007,6 @@ country MX: DFS-FCC
(5250 - 5330 @ 80), (24), DFS, AUTO-BW
(5490 - 5730 @ 160), (24), DFS
(5735 - 5835 @ 80), (30)
-
# 60 gHz band channels 1-3, FCC
(57240 - 63720 @ 2160), (40)
@@ -1034,7 +1016,6 @@ country MY: DFS-FCC
(5250 - 5330 @ 80), (24), DFS, AUTO-BW
(5490 - 5650 @ 160), (24), DFS
(5735 - 5815 @ 80), (24)
-
# 60 gHz band channels 1-3
(57240 - 63720 @ 2160), (40)
@@ -1056,7 +1037,6 @@ country NI: DFS-FCC
(5250 - 5330 @ 80), (24), DFS, AUTO-BW
(5490 - 5730 @ 160), (24), DFS
(5735 - 5835 @ 80), (30)
-
# 60 gHz band channels 1-3, FCC
(57240 - 63720 @ 2160), (40)
@@ -1075,7 +1055,7 @@ country NL: DFS-ETSI
(5900 - 5920 @ 10), (30)
(5910 - 5930 @ 10), (30)
# 60 gHz band channels 1-4, ref: Etsi En 302 567
- (57240 - 65880 @ 2160), (40), NO-OUTDOOR
+ (57000 - 66000 @ 2160), (40)
country NO: DFS-ETSI
(2402 - 2482 @ 40), (20)
@@ -1092,7 +1072,7 @@ country NO: DFS-ETSI
(5900 - 5920 @ 10), (30)
(5910 - 5930 @ 10), (30)
# 60 gHz band channels 1-4, ref: Etsi En 302 567
- (57240 - 65880 @ 2160), (40), NO-OUTDOOR
+ (57000 - 66000 @ 2160), (40)
country NP:
(2402 - 2482 @ 40), (20)
@@ -1105,9 +1085,8 @@ country NZ: DFS-FCC
(5250 - 5330 @ 80), (24), DFS, AUTO-BW
(5490 - 5730 @ 160), (24), DFS
(5735 - 5835 @ 80), (30)
-
# 60 gHz band channels 1-4, ref: Etsi En 302 567
- (57240 - 65880 @ 2160), (40), NO-OUTDOOR
+ (57000 - 66000 @ 2160), (40)
country OM: DFS-ETSI
(2402 - 2482 @ 40), (20)
@@ -1147,9 +1126,8 @@ country PH: DFS-FCC
(5250 - 5330 @ 80), (24), DFS, AUTO-BW
(5490 - 5730 @ 160), (24), DFS
(5735 - 5835 @ 80), (30)
-
# 60 gHz band channels 1-4, ref: Etsi En 302 567
- (57240 - 65880 @ 2160), (40), NO-OUTDOOR
+ (57000 - 66000 @ 2160), (40)
country PK:
(2402 - 2482 @ 40), (30)
@@ -1170,7 +1148,7 @@ country PL: DFS-ETSI
(5900 - 5920 @ 10), (30)
(5910 - 5930 @ 10), (30)
# 60 gHz band channels 1-4, ref: Etsi En 302 567
- (57240 - 65880 @ 2160), (40), NO-OUTDOOR
+ (57000 - 66000 @ 2160), (40)
country PM: DFS-ETSI
(2402 - 2482 @ 40), (20)
@@ -1207,7 +1185,7 @@ country PT: DFS-ETSI
(5900 - 5920 @ 10), (30)
(5910 - 5930 @ 10), (30)
# 60 gHz band channels 1-4, ref: Etsi En 302 567
- (57240 - 65880 @ 2160), (40), NO-OUTDOOR
+ (57000 - 66000 @ 2160), (40)
country PW: DFS-FCC
(2402 - 2472 @ 40), (30)
@@ -1222,7 +1200,6 @@ country PY: DFS-FCC
(5250 - 5330 @ 80), (24), DFS, AUTO-BW
(5490 - 5730 @ 160), (24), DFS
(5735 - 5835 @ 80), (30)
-
# 60 gHz band channels 1-3, FCC
(57240 - 63720 @ 2160), (40)
@@ -1251,7 +1228,7 @@ country RO: DFS-ETSI
(5900 - 5920 @ 10), (30)
(5910 - 5930 @ 10), (30)
# 60 gHz band channels 1-4, ref: Etsi En 302 567
- (57240 - 65880 @ 2160), (40), NO-OUTDOOR
+ (57000 - 66000 @ 2160), (40)
# Source:
# http://www.ratel.rs/upload/documents/Plan_namene/Plan_namene-sl_glasnik.pdf
@@ -1261,14 +1238,13 @@ country RS: DFS-ETSI
(5250 - 5330 @ 80), (23), DFS, AUTO-BW
(5490 - 5710 @ 160), (30), DFS
# 60 gHz band channels 1-4, ref: Etsi En 302 567
- (57240 - 65880 @ 2160), (40), NO-OUTDOOR
+ (57000 - 66000 @ 2160), (40)
country RU:
(2402 - 2482 @ 40), (20)
(5170 - 5330 @ 160), (23)
(5490 - 5730 @ 160), (30)
(5735 - 5835 @ 80), (30)
-
# 60 gHz band channels 1-4
(57240 - 65880 @ 2160), (40)
@@ -1300,7 +1276,7 @@ country SE: DFS-ETSI
(5900 - 5920 @ 10), (30)
(5910 - 5930 @ 10), (30)
# 60 gHz band channels 1-4, ref: Etsi En 302 567
- (57240 - 65880 @ 2160), (40), NO-OUTDOOR
+ (57000 - 66000 @ 2160), (40)
country SG: DFS-FCC
(2402 - 2482 @ 40), (20)
@@ -1308,9 +1284,8 @@ country SG: DFS-FCC
(5250 - 5330 @ 80), (24), DFS, AUTO-BW
(5490 - 5730 @ 160), (24), DFS
(5735 - 5835 @ 80), (30)
-
# 60 gHz band channels 1-4, ref: Etsi En 302 567
- (57240 - 65880 @ 2160), (40), NO-OUTDOOR
+ (57000 - 66000 @ 2160), (40), NO-OUTDOOR
country SI: DFS-ETSI
(2402 - 2482 @ 40), (20)
@@ -1327,7 +1302,7 @@ country SI: DFS-ETSI
(5900 - 5920 @ 10), (30)
(5910 - 5930 @ 10), (30)
# 60 gHz band channels 1-4, ref: Etsi En 302 567
- (57240 - 65880 @ 2160), (40), NO-OUTDOOR
+ (57000 - 66000 @ 2160), (40)
country SK: DFS-ETSI
(2402 - 2482 @ 40), (20)
@@ -1344,7 +1319,7 @@ country SK: DFS-ETSI
(5900 - 5920 @ 10), (30)
(5910 - 5930 @ 10), (30)
# 60 gHz band channels 1-4, ref: Etsi En 302 567
- (57240 - 65880 @ 2160), (40), NO-OUTDOOR
+ (57000 - 66000 @ 2160), (40)
country SN:
(2402 - 2482 @ 40), (20)
@@ -1392,7 +1367,6 @@ country TH: DFS-FCC
(5250 - 5330 @ 80), (24), DFS, AUTO-BW
(5490 - 5730 @ 160), (24), DFS
(5735 - 5835 @ 80), (30)
-
# 60 gHz band channels 1-4
(57240 - 65880 @ 2160), (40)
@@ -1412,7 +1386,6 @@ country TT:
(5170 - 5330 @ 160), (27)
(5490 - 5730 @ 160), (36)
(5735 - 5835 @ 80), (36)
-
# 60 gHz band channels 1-3, FCC
(57240 - 63720 @ 2160), (40)
@@ -1422,7 +1395,6 @@ country TW: DFS-FCC
(5250 - 5330 @ 80), (24), DFS, AUTO-BW
(5490 - 5730 @ 160), (24), DFS
(5735 - 5835 @ 80), (30)
-
# 60 gHz band channels 1-3, FCC
(57240 - 63720 @ 2160), (40)
@@ -1481,7 +1453,6 @@ country UY: DFS-FCC
(5170 - 5250 @ 80), (23), AUTO-BW
(5250 - 5330 @ 80), (23), DFS, AUTO-BW
(5735 - 5835 @ 80), (30)
-
# 60 gHz band channels 1-4
(57240 - 65880 @ 2160), (40)
@@ -1515,7 +1486,6 @@ country VN: DFS-FCC
(5250 - 5330 @ 80), (24), DFS, AUTO-BW
(5490 - 5730 @ 160), (24), DFS
(5735 - 5835 @ 80), (30)
-
# 60 gHz band channels 1-4
(57240 - 65880 @ 2160), (40)
@@ -1560,7 +1530,6 @@ country ZA: DFS-FCC
(5250 - 5330 @ 80), (24), DFS, AUTO-BW
(5490 - 5730 @ 160), (24), DFS
(5735 - 5835 @ 80), (30)
-
# 60 gHz band channels 1-4
(57240 - 65880 @ 2160), (40), NO-OUTDOOR
diff --git a/sound/core/seq/seq_lock.c b/sound/core/seq/seq_lock.c
index 3b693e924db7..12ba83367b1b 100644
--- a/sound/core/seq/seq_lock.c
+++ b/sound/core/seq/seq_lock.c
@@ -28,19 +28,16 @@
/* wait until all locks are released */
void snd_use_lock_sync_helper(snd_use_lock_t *lockp, const char *file, int line)
{
- int max_count = 5 * HZ;
+ int warn_count = 5 * HZ;
if (atomic_read(lockp) < 0) {
pr_warn("ALSA: seq_lock: lock trouble [counter = %d] in %s:%d\n", atomic_read(lockp), file, line);
return;
}
while (atomic_read(lockp) > 0) {
- if (max_count == 0) {
- pr_warn("ALSA: seq_lock: timeout [%d left] in %s:%d\n", atomic_read(lockp), file, line);
- break;
- }
+ if (warn_count-- == 0)
+ pr_warn("ALSA: seq_lock: waiting [%d left] in %s:%d\n", atomic_read(lockp), file, line);
schedule_timeout_uninterruptible(1);
- max_count--;
}
}
diff --git a/sound/firewire/lib.h b/sound/firewire/lib.h
index f3f6f84c48d6..bb5f8cdea3e2 100644
--- a/sound/firewire/lib.h
+++ b/sound/firewire/lib.h
@@ -42,7 +42,7 @@ struct snd_fw_async_midi_port {
struct snd_rawmidi_substream *substream;
snd_fw_async_midi_port_fill fill;
- unsigned int consume_bytes;
+ int consume_bytes;
};
int snd_fw_async_midi_port_init(struct snd_fw_async_midi_port *port,
diff --git a/sound/soc/codecs/wsa881x-analog.c b/sound/soc/codecs/wsa881x-analog.c
index fa1d099e082a..ff160dcb0952 100644
--- a/sound/soc/codecs/wsa881x-analog.c
+++ b/sound/soc/codecs/wsa881x-analog.c
@@ -1309,7 +1309,6 @@ static int wsa881x_i2c_probe(struct i2c_client *client,
ret = -EINVAL;
goto err;
}
- i2c_set_clientdata(client, pdata);
dev_set_drvdata(&client->dev, client);
pdata->regmap[WSA881X_DIGITAL_SLAVE] =
@@ -1367,7 +1366,7 @@ err:
static int wsa881x_i2c_remove(struct i2c_client *client)
{
- struct wsa881x_pdata *wsa881x = i2c_get_clientdata(client);
+ struct wsa881x_pdata *wsa881x = client->dev.platform_data;
snd_soc_unregister_codec(&client->dev);
i2c_set_clientdata(client, NULL);
@@ -1414,6 +1413,7 @@ static struct i2c_driver wsa881x_codec_driver = {
.driver = {
.name = "wsa881x-i2c-codec",
.owner = THIS_MODULE,
+ .probe_type = PROBE_PREFER_ASYNCHRONOUS,
#ifdef CONFIG_PM_SLEEP
.pm = &wsa881x_i2c_pm_ops,
#endif
diff --git a/sound/soc/msm/qdsp6v2/audio_cal_utils.c b/sound/soc/msm/qdsp6v2/audio_cal_utils.c
index 0194dc4d58f1..4f2531a3da63 100644
--- a/sound/soc/msm/qdsp6v2/audio_cal_utils.c
+++ b/sound/soc/msm/qdsp6v2/audio_cal_utils.c
@@ -643,7 +643,9 @@ done:
return cal_block;
err:
kfree(cal_block->cal_info);
+ cal_block->cal_info = NULL;
kfree(cal_block->client_info);
+ cal_block->client_info = NULL;
kfree(cal_block);
cal_block = NULL;
return cal_block;
diff --git a/sound/soc/msm/qdsp6v2/msm-compress-q6-v2.c b/sound/soc/msm/qdsp6v2/msm-compress-q6-v2.c
index 5bd3b6d7014e..426b4d0b0a35 100644
--- a/sound/soc/msm/qdsp6v2/msm-compress-q6-v2.c
+++ b/sound/soc/msm/qdsp6v2/msm-compress-q6-v2.c
@@ -302,6 +302,39 @@ exit:
return ret;
}
+static int msm_compr_enable_adjust_session_clock(struct audio_client *ac,
+ bool enable)
+{
+ int ret;
+
+ pr_debug("%s, enable adjust_session %d\n", __func__, enable);
+
+ ret = q6asm_send_mtmx_strtr_enable_adjust_session_clock(ac, enable);
+ if (ret)
+ pr_err("%s, adjust session clock can't be set error %d\n",
+ __func__, ret);
+
+ return ret;
+}
+
+static int msm_compr_adjust_session_clock(struct audio_client *ac,
+ uint32_t adjust_session_lsw, uint32_t adjust_session_msw)
+{
+ int ret;
+
+ pr_debug("%s, adjust_session_time_msw 0x%x adjust_session_time_lsw 0x%x\n",
+ __func__, adjust_session_msw, adjust_session_lsw);
+
+ ret = q6asm_adjust_session_clock(ac,
+ adjust_session_lsw,
+ adjust_session_msw);
+ if (ret)
+ pr_err("%s, adjust session clock can't be set error %d\n",
+ __func__, ret);
+
+ return ret;
+}
+
static int msm_compr_set_volume(struct snd_compr_stream *cstream,
uint32_t volume_l, uint32_t volume_r)
{
@@ -716,8 +749,7 @@ static void compr_event_handler(uint32_t opcode,
return;
}
- ret = msm_adsp_inform_mixer_ctl(rtd, DSP_STREAM_CALLBACK,
- payload);
+ ret = msm_adsp_inform_mixer_ctl(rtd, payload);
if (ret) {
pr_err("%s: failed to inform mixer ctrl. err = %d\n",
__func__, ret);
@@ -1550,6 +1582,7 @@ static int msm_compr_playback_open(struct snd_compr_stream *cstream)
pr_debug("%s: session ID %d\n", __func__, prtd->audio_client->session);
prtd->audio_client->perf_mode = false;
prtd->session_id = prtd->audio_client->session;
+ msm_adsp_init_mixer_ctl_pp_event_queue(rtd);
return 0;
}
@@ -1705,7 +1738,7 @@ static int msm_compr_playback_free(struct snd_compr_stream *cstream)
q6asm_audio_client_buf_free_contiguous(dir, ac);
q6asm_audio_client_free(ac);
-
+ msm_adsp_clean_mixer_ctl_pp_event_queue(soc_prtd);
kfree(pdata->audio_effects[soc_prtd->dai_link->be_id]);
pdata->audio_effects[soc_prtd->dai_link->be_id] = NULL;
kfree(pdata->dec_params[soc_prtd->dai_link->be_id]);
@@ -2875,6 +2908,14 @@ static int msm_compr_set_metadata(struct snd_compr_stream *cstream,
} else if (metadata->key == SNDRV_COMPRESS_START_DELAY) {
prtd->start_delay_lsw = metadata->value[0];
prtd->start_delay_msw = metadata->value[1];
+ } else if (metadata->key ==
+ SNDRV_COMPRESS_ENABLE_ADJUST_SESSION_CLOCK) {
+ return msm_compr_enable_adjust_session_clock(ac,
+ metadata->value[0]);
+ } else if (metadata->key == SNDRV_COMPRESS_ADJUST_SESSION_CLOCK) {
+ return msm_compr_adjust_session_clock(ac,
+ metadata->value[0],
+ metadata->value[1]);
}
return 0;
@@ -3937,7 +3978,6 @@ static int msm_compr_add_audio_adsp_stream_callback_control(
.access = SNDRV_CTL_ELEM_ACCESS_READWRITE,
.info = msm_adsp_stream_callback_info,
.get = msm_adsp_stream_callback_get,
- .put = msm_adsp_stream_callback_put,
.private_value = 0,
}
};
@@ -3978,6 +4018,7 @@ static int msm_compr_add_audio_adsp_stream_callback_control(
}
kctl->private_data = NULL;
+
free_mixer_str:
kfree(mixer_str);
done:
diff --git a/sound/soc/msm/qdsp6v2/msm-dai-q6-hdmi-v2.c b/sound/soc/msm/qdsp6v2/msm-dai-q6-hdmi-v2.c
index 26b7f3f26b26..45868f508a60 100644
--- a/sound/soc/msm/qdsp6v2/msm-dai-q6-hdmi-v2.c
+++ b/sound/soc/msm/qdsp6v2/msm-dai-q6-hdmi-v2.c
@@ -174,7 +174,7 @@ static const struct snd_kcontrol_new hdmi_config_controls[] = {
{
.access = SNDRV_CTL_ELEM_ACCESS_READ,
.iface = SNDRV_CTL_ELEM_IFACE_PCM,
- .name = "HDMI RX Drift",
+ .name = "HDMI Drift",
.info = msm_dai_q6_ext_disp_drift_info,
.get = msm_dai_q6_ext_disp_drift_get,
},
@@ -191,7 +191,7 @@ static const struct snd_kcontrol_new display_port_config_controls[] = {
{
.access = SNDRV_CTL_ELEM_ACCESS_READ,
.iface = SNDRV_CTL_ELEM_IFACE_PCM,
- .name = "DISPLAY Port RX Drift",
+ .name = "DISPLAY_PORT Drift",
.info = msm_dai_q6_ext_disp_drift_info,
.get = msm_dai_q6_ext_disp_drift_get,
},
diff --git a/sound/soc/msm/qdsp6v2/msm-dai-q6-v2.c b/sound/soc/msm/qdsp6v2/msm-dai-q6-v2.c
index 201ca652c10b..9ed61288a3e4 100644
--- a/sound/soc/msm/qdsp6v2/msm-dai-q6-v2.c
+++ b/sound/soc/msm/qdsp6v2/msm-dai-q6-v2.c
@@ -2321,6 +2321,44 @@ static const struct snd_kcontrol_new afe_enc_config_controls[] = {
msm_dai_q6_afe_input_bit_format_put),
};
+static int msm_dai_q6_slim_rx_drift_info(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_info *uinfo)
+{
+ uinfo->type = SNDRV_CTL_ELEM_TYPE_BYTES;
+ uinfo->count = sizeof(struct afe_param_id_dev_timing_stats);
+
+ return 0;
+}
+
+static int msm_dai_q6_slim_rx_drift_get(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
+{
+ int ret = -EINVAL;
+ struct afe_param_id_dev_timing_stats timing_stats;
+ struct snd_soc_dai *dai = kcontrol->private_data;
+ struct msm_dai_q6_dai_data *dai_data = dev_get_drvdata(dai->dev);
+
+ if (!test_bit(STATUS_PORT_STARTED, dai_data->status_mask)) {
+ pr_err("%s: afe port not started. dai_data->status_mask = %ld\n",
+ __func__, *dai_data->status_mask);
+ goto done;
+ }
+
+ memset(&timing_stats, 0, sizeof(struct afe_param_id_dev_timing_stats));
+ ret = afe_get_av_dev_drift(&timing_stats, dai->id);
+ if (ret) {
+ pr_err("%s: Error getting AFE Drift for port %d, err=%d\n",
+ __func__, dai->id, ret);
+
+ goto done;
+ }
+
+ memcpy(ucontrol->value.bytes.data, (void *)&timing_stats,
+ sizeof(struct afe_param_id_dev_timing_stats));
+done:
+ return ret;
+}
+
static const char * const afe_cal_mode_text[] = {
"CAL_MODE_DEFAULT", "CAL_MODE_NONE"
};
@@ -2373,6 +2411,29 @@ static const struct snd_kcontrol_new usb_audio_cfg_controls[] = {
msm_dai_q6_usb_audio_endian_cfg_put),
};
+static const struct snd_kcontrol_new avd_drift_config_controls[] = {
+ {
+ .access = SNDRV_CTL_ELEM_ACCESS_READ,
+ .iface = SNDRV_CTL_ELEM_IFACE_PCM,
+ .name = "SLIMBUS_0_RX DRIFT",
+ .info = msm_dai_q6_slim_rx_drift_info,
+ .get = msm_dai_q6_slim_rx_drift_get,
+ },
+ {
+ .access = SNDRV_CTL_ELEM_ACCESS_READ,
+ .iface = SNDRV_CTL_ELEM_IFACE_PCM,
+ .name = "SLIMBUS_6_RX DRIFT",
+ .info = msm_dai_q6_slim_rx_drift_info,
+ .get = msm_dai_q6_slim_rx_drift_get,
+ },
+ {
+ .access = SNDRV_CTL_ELEM_ACCESS_READ,
+ .iface = SNDRV_CTL_ELEM_IFACE_PCM,
+ .name = "SLIMBUS_7_RX DRIFT",
+ .info = msm_dai_q6_slim_rx_drift_info,
+ .get = msm_dai_q6_slim_rx_drift_get,
+ },
+};
static int msm_dai_q6_dai_probe(struct snd_soc_dai *dai)
{
struct msm_dai_q6_dai_data *dai_data;
@@ -2422,6 +2483,9 @@ static int msm_dai_q6_dai_probe(struct snd_soc_dai *dai)
rc = snd_ctl_add(dai->component->card->snd_card,
snd_ctl_new1(&afe_enc_config_controls[2],
dai_data));
+ rc = snd_ctl_add(dai->component->card->snd_card,
+ snd_ctl_new1(&avd_drift_config_controls[2],
+ dai));
break;
case RT_PROXY_DAI_001_RX:
rc = snd_ctl_add(dai->component->card->snd_card,
@@ -2449,6 +2513,16 @@ static int msm_dai_q6_dai_probe(struct snd_soc_dai *dai)
snd_ctl_new1(&usb_audio_cfg_controls[3],
dai_data));
break;
+ case SLIMBUS_0_RX:
+ rc = snd_ctl_add(dai->component->card->snd_card,
+ snd_ctl_new1(&avd_drift_config_controls[0],
+ dai));
+ break;
+ case SLIMBUS_6_RX:
+ rc = snd_ctl_add(dai->component->card->snd_card,
+ snd_ctl_new1(&avd_drift_config_controls[1],
+ dai));
+ break;
}
if (IS_ERR_VALUE(rc))
dev_err(dai->dev, "%s: err add config ctl, DAI = %s\n",
diff --git a/sound/soc/msm/qdsp6v2/msm-pcm-q6-v2.c b/sound/soc/msm/qdsp6v2/msm-pcm-q6-v2.c
index 73eadfa4eebb..8f43aee3974c 100644
--- a/sound/soc/msm/qdsp6v2/msm-pcm-q6-v2.c
+++ b/sound/soc/msm/qdsp6v2/msm-pcm-q6-v2.c
@@ -239,8 +239,7 @@ static void event_handler(uint32_t opcode,
return;
}
- ret = msm_adsp_inform_mixer_ctl(rtd, DSP_STREAM_CALLBACK,
- payload);
+ ret = msm_adsp_inform_mixer_ctl(rtd, payload);
if (ret) {
pr_err("%s: failed to inform mixer ctl. err = %d\n",
__func__, ret);
@@ -691,6 +690,7 @@ static int msm_pcm_open(struct snd_pcm_substream *substream)
prtd->set_channel_map = false;
prtd->reset_event = false;
runtime->private_data = prtd;
+ msm_adsp_init_mixer_ctl_pp_event_queue(soc_prtd);
return 0;
}
@@ -833,6 +833,7 @@ static int msm_pcm_playback_close(struct snd_pcm_substream *substream)
}
msm_pcm_routing_dereg_phy_stream(soc_prtd->dai_link->be_id,
SNDRV_PCM_STREAM_PLAYBACK);
+ msm_adsp_clean_mixer_ctl_pp_event_queue(soc_prtd);
kfree(prtd);
runtime->private_data = NULL;
@@ -1187,7 +1188,6 @@ static int msm_pcm_add_audio_adsp_stream_callback_control(
.access = SNDRV_CTL_ELEM_ACCESS_READWRITE,
.info = msm_adsp_stream_callback_info,
.get = msm_adsp_stream_callback_get,
- .put = msm_adsp_stream_callback_put,
.private_value = 0,
}
};
@@ -1231,6 +1231,7 @@ static int msm_pcm_add_audio_adsp_stream_callback_control(
}
kctl->private_data = NULL;
+
free_mixer_str:
kfree(mixer_str);
done:
diff --git a/sound/soc/msm/qdsp6v2/msm-qti-pp-config.c b/sound/soc/msm/qdsp6v2/msm-qti-pp-config.c
index d4e78604f868..cac28f43e5ae 100644
--- a/sound/soc/msm/qdsp6v2/msm-qti-pp-config.c
+++ b/sound/soc/msm/qdsp6v2/msm-qti-pp-config.c
@@ -45,21 +45,6 @@ enum {
EQ_BAND_MAX,
};
-struct msm_audio_eq_band {
- uint16_t band_idx; /* The band index, 0 .. 11 */
- uint32_t filter_type; /* Filter band type */
- uint32_t center_freq_hz; /* Filter band center frequency */
- uint32_t filter_gain; /* Filter band initial gain (dB) */
- /* Range is +12 dB to -12 dB with 1dB increments. */
- uint32_t q_factor;
-} __packed;
-
-struct msm_audio_eq_stream_config {
- uint32_t enable; /* Number of consequtive bands specified */
- uint32_t num_bands;
- struct msm_audio_eq_band eq_bands[EQ_BAND_MAX];
-} __packed;
-
/* Audio Sphere data structures */
struct msm_audio_pp_asphere_state_s {
uint32_t enabled;
@@ -817,18 +802,133 @@ static int msm_qti_pp_asphere_set(struct snd_kcontrol *kcontrol,
return 0;
}
+int msm_adsp_init_mixer_ctl_pp_event_queue(struct snd_soc_pcm_runtime *rtd)
+{
+ struct snd_kcontrol *kctl;
+ const char *deviceNo = "NN";
+ char *mixer_str = NULL;
+ int ctl_len = 0, ret = 0;
+ const char *mixer_ctl_name = DSP_STREAM_CALLBACK;
+ struct dsp_stream_callback_prtd *kctl_prtd = NULL;
+
+ if (!rtd) {
+ pr_err("%s: rtd is NULL\n", __func__);
+ ret = -EINVAL;
+ goto done;
+ }
+
+ ctl_len = strlen(mixer_ctl_name) + 1 + strlen(deviceNo) + 1;
+ mixer_str = kzalloc(ctl_len, GFP_KERNEL);
+ if (!mixer_str) {
+ ret = -EINVAL;
+ goto done;
+ }
+
+ snprintf(mixer_str, ctl_len, "%s %d", mixer_ctl_name,
+ rtd->pcm->device);
+ kctl = snd_soc_card_get_kcontrol(rtd->card, mixer_str);
+ kfree(mixer_str);
+ if (!kctl) {
+ pr_err("%s: failed to get kctl.\n", __func__);
+ ret = -EINVAL;
+ goto done;
+ }
+
+ if (kctl->private_data != NULL) {
+ pr_err("%s: kctl_prtd is not NULL at initialization.\n",
+ __func__);
+ return -EINVAL;
+ }
+
+ kctl_prtd = kzalloc(sizeof(struct dsp_stream_callback_prtd),
+ GFP_KERNEL);
+ if (!kctl_prtd) {
+ ret = -ENOMEM;
+ goto done;
+ }
+
+ spin_lock_init(&kctl_prtd->prtd_spin_lock);
+ INIT_LIST_HEAD(&kctl_prtd->event_queue);
+ kctl_prtd->event_count = 0;
+ kctl->private_data = kctl_prtd;
+
+done:
+ return ret;
+}
+
+int msm_adsp_clean_mixer_ctl_pp_event_queue(struct snd_soc_pcm_runtime *rtd)
+{
+ struct snd_kcontrol *kctl;
+ const char *deviceNo = "NN";
+ char *mixer_str = NULL;
+ int ctl_len = 0, ret = 0;
+ struct dsp_stream_callback_list *node, *n;
+ unsigned long spin_flags;
+ const char *mixer_ctl_name = DSP_STREAM_CALLBACK;
+ struct dsp_stream_callback_prtd *kctl_prtd = NULL;
+
+ if (!rtd) {
+ pr_err("%s: rtd is NULL\n", __func__);
+ ret = -EINVAL;
+ goto done;
+ }
+
+ ctl_len = strlen(mixer_ctl_name) + 1 + strlen(deviceNo) + 1;
+ mixer_str = kzalloc(ctl_len, GFP_KERNEL);
+ if (!mixer_str) {
+ ret = -EINVAL;
+ goto done;
+ }
+
+ snprintf(mixer_str, ctl_len, "%s %d", mixer_ctl_name,
+ rtd->pcm->device);
+ kctl = snd_soc_card_get_kcontrol(rtd->card, mixer_str);
+ kfree(mixer_str);
+ if (!kctl) {
+ pr_err("%s: failed to get kctl.\n", __func__);
+ ret = -EINVAL;
+ goto done;
+ }
+
+ kctl_prtd = (struct dsp_stream_callback_prtd *)
+ kctl->private_data;
+ if (kctl_prtd != NULL) {
+ spin_lock_irqsave(&kctl_prtd->prtd_spin_lock, spin_flags);
+ /* clean the queue */
+ list_for_each_entry_safe(node, n,
+ &kctl_prtd->event_queue, list) {
+ list_del(&node->list);
+ kctl_prtd->event_count--;
+ pr_debug("%s: %d remaining events after del.\n",
+ __func__, kctl_prtd->event_count);
+ kfree(node);
+ }
+ spin_unlock_irqrestore(&kctl_prtd->prtd_spin_lock, spin_flags);
+ }
+
+ kfree(kctl_prtd);
+ kctl->private_data = NULL;
+
+done:
+ return ret;
+}
int msm_adsp_inform_mixer_ctl(struct snd_soc_pcm_runtime *rtd,
- const char *mixer_ctl_name,
uint32_t *payload)
{
/* adsp pp event notifier */
struct snd_kcontrol *kctl;
struct snd_ctl_elem_value control;
- uint32_t payload_size = 0;
const char *deviceNo = "NN";
char *mixer_str = NULL;
int ctl_len = 0, ret = 0;
+ struct dsp_stream_callback_list *new_event;
+ struct dsp_stream_callback_list *oldest_event;
+ unsigned long spin_flags;
+ struct dsp_stream_callback_prtd *kctl_prtd = NULL;
+ struct msm_adsp_event_data *event_data = NULL;
+ const char *mixer_ctl_name = DSP_STREAM_CALLBACK;
+ struct snd_ctl_elem_info kctl_info;
if (!rtd || !payload) {
pr_err("%s: %s is NULL\n", __func__,
@@ -837,6 +937,12 @@ int msm_adsp_inform_mixer_ctl(struct snd_soc_pcm_runtime *rtd,
goto done;
}
+ if (rtd->card->snd_card == NULL) {
+ pr_err("%s: snd_card is null.\n", __func__);
+ ret = -EINVAL;
+ goto done;
+ }
+
ctl_len = strlen(mixer_ctl_name) + 1 + strlen(deviceNo) + 1;
mixer_str = kzalloc(ctl_len, GFP_ATOMIC);
if (!mixer_str) {
@@ -854,21 +960,59 @@ int msm_adsp_inform_mixer_ctl(struct snd_soc_pcm_runtime *rtd,
goto done;
}
- control.id = kctl->id;
- payload_size = payload[0];
- /* Copy complete payload */
- memcpy(control.value.bytes.data, (void *)payload,
- sizeof(payload_size) + payload_size);
- kctl->put(kctl, &control);
- if (rtd->card->snd_card == NULL) {
- pr_err("%s: snd_card is null.\n", __func__);
+ event_data = (struct msm_adsp_event_data *)payload;
+ kctl->info(kctl, &kctl_info);
+ if (sizeof(struct msm_adsp_event_data)
+ + event_data->payload_len > kctl_info.count) {
+ pr_err("%s: payload length exceeds limit of %u bytes.\n",
+ __func__, kctl_info.count);
ret = -EINVAL;
goto done;
}
+ kctl_prtd = (struct dsp_stream_callback_prtd *)
+ kctl->private_data;
+ if (kctl_prtd == NULL) {
+ /* queue is not initialized */
+ ret = -EINVAL;
+ pr_err("%s: event queue is not initialized.\n", __func__);
+ goto done;
+ }
+
+ new_event = kzalloc(sizeof(struct dsp_stream_callback_list)
+ + event_data->payload_len,
+ GFP_ATOMIC);
+ if (new_event == NULL) {
+ ret = -ENOMEM;
+ goto done;
+ }
+ memcpy((void *)&new_event->event, (void *)payload,
+ event_data->payload_len
+ + sizeof(struct msm_adsp_event_data));
+
+ spin_lock_irqsave(&kctl_prtd->prtd_spin_lock, spin_flags);
+ while (kctl_prtd->event_count >= DSP_STREAM_CALLBACK_QUEUE_SIZE) {
+ pr_info("%s: queue of size %d is full. delete oldest one.\n",
+ __func__, DSP_STREAM_CALLBACK_QUEUE_SIZE);
+ oldest_event = list_first_entry(&kctl_prtd->event_queue,
+ struct dsp_stream_callback_list, list);
+ pr_info("%s: event deleted: type %d length %d\n",
+ __func__, oldest_event->event.event_type,
+ oldest_event->event.payload_len);
+ list_del(&oldest_event->list);
+ kctl_prtd->event_count--;
+ kfree(oldest_event);
+ }
+
+ list_add_tail(&new_event->list, &kctl_prtd->event_queue);
+ kctl_prtd->event_count++;
+ spin_unlock_irqrestore(&kctl_prtd->prtd_spin_lock, spin_flags);
+
+ control.id = kctl->id;
snd_ctl_notify(rtd->card->snd_card,
SNDRV_CTL_EVENT_MASK_INFO,
&control.id);
+
done:
return ret;
}
@@ -877,44 +1021,8 @@ int msm_adsp_stream_cmd_info(struct snd_kcontrol *kcontrol,
struct snd_ctl_elem_info *uinfo)
{
uinfo->type = SNDRV_CTL_ELEM_TYPE_BYTES;
- uinfo->count = 512;
-
- return 0;
-}
-
-int msm_adsp_stream_callback_put(struct snd_kcontrol *kcontrol,
- struct snd_ctl_elem_value *ucontrol)
-{
- uint32_t payload_size = 0, last_payload_size = 0;
-
- /* fetch payload size in first four bytes */
- memcpy(&payload_size, ucontrol->value.bytes.data, sizeof(uint32_t));
-
- if (kcontrol->private_data == NULL) {
- /* buffer is empty */
- kcontrol->private_data =
- kzalloc(payload_size + sizeof(payload_size),
- GFP_ATOMIC);
- if (kcontrol->private_data == NULL)
- return -ENOMEM;
- } else {
- memcpy(&last_payload_size, kcontrol->private_data,
- sizeof(uint32_t));
- if (last_payload_size < payload_size) {
- /* new payload size exceeds old one.
- * reallocate buffer
- */
- kfree(kcontrol->private_data);
- kcontrol->private_data =
- kzalloc(payload_size + sizeof(payload_size),
- GFP_ATOMIC);
- if (kcontrol->private_data == NULL)
- return -ENOMEM;
- }
- }
-
- memcpy(kcontrol->private_data, ucontrol->value.bytes.data,
- sizeof(uint32_t) + payload_size);
+ uinfo->count =
+ sizeof(((struct snd_ctl_elem_value *)0)->value.bytes.data);
return 0;
}
@@ -923,26 +1031,53 @@ int msm_adsp_stream_callback_get(struct snd_kcontrol *kcontrol,
struct snd_ctl_elem_value *ucontrol)
{
uint32_t payload_size = 0;
+ struct dsp_stream_callback_list *oldest_event;
+ unsigned long spin_flags;
+ struct dsp_stream_callback_prtd *kctl_prtd = NULL;
+ int ret = 0;
- if (kcontrol->private_data == NULL) {
- pr_err("%s: ASM Stream PP Event Data Unavailable\n", __func__);
- return -EINVAL;
+ kctl_prtd = (struct dsp_stream_callback_prtd *)
+ kcontrol->private_data;
+ if (kctl_prtd == NULL) {
+ pr_err("%s: ASM Stream PP event queue is not initialized.\n",
+ __func__);
+ ret = -EINVAL;
+ goto done;
+ }
+
+ spin_lock_irqsave(&kctl_prtd->prtd_spin_lock, spin_flags);
+ pr_debug("%s: %d events in queue.\n", __func__, kctl_prtd->event_count);
+ if (list_empty(&kctl_prtd->event_queue)) {
+ pr_err("%s: ASM Stream PP event queue is empty.\n", __func__);
+ ret = -EINVAL;
+ spin_unlock_irqrestore(&kctl_prtd->prtd_spin_lock, spin_flags);
+ goto done;
}
- memcpy(&payload_size, kcontrol->private_data, sizeof(uint32_t));
- memcpy(ucontrol->value.bytes.data, kcontrol->private_data,
- sizeof(uint32_t) + payload_size);
- kfree(kcontrol->private_data);
- kcontrol->private_data = NULL;
+ oldest_event = list_first_entry(&kctl_prtd->event_queue,
+ struct dsp_stream_callback_list, list);
+ list_del(&oldest_event->list);
+ kctl_prtd->event_count--;
+ spin_unlock_irqrestore(&kctl_prtd->prtd_spin_lock, spin_flags);
- return 0;
+ payload_size = oldest_event->event.payload_len;
+ pr_debug("%s: event fetched: type %d length %d\n",
+ __func__, oldest_event->event.event_type,
+ oldest_event->event.payload_len);
+ memcpy(ucontrol->value.bytes.data, &oldest_event->event,
+ sizeof(struct msm_adsp_event_data) + payload_size);
+ kfree(oldest_event);
+
+done:
+ return ret;
}
int msm_adsp_stream_callback_info(struct snd_kcontrol *kcontrol,
struct snd_ctl_elem_info *uinfo)
{
uinfo->type = SNDRV_CTL_ELEM_TYPE_BYTES;
- uinfo->count = 512;
+ uinfo->count =
+ sizeof(((struct snd_ctl_elem_value *)0)->value.bytes.data);
return 0;
}
diff --git a/sound/soc/msm/qdsp6v2/msm-qti-pp-config.h b/sound/soc/msm/qdsp6v2/msm-qti-pp-config.h
index 70ce20fbd8f8..6ffcbdbd543e 100644
--- a/sound/soc/msm/qdsp6v2/msm-qti-pp-config.h
+++ b/sound/soc/msm/qdsp6v2/msm-qti-pp-config.h
@@ -14,12 +14,11 @@
#include <sound/soc.h>
int msm_adsp_inform_mixer_ctl(struct snd_soc_pcm_runtime *rtd,
- const char *mixer_ctl_name,
uint32_t *payload);
+int msm_adsp_init_mixer_ctl_pp_event_queue(struct snd_soc_pcm_runtime *rtd);
+int msm_adsp_clean_mixer_ctl_pp_event_queue(struct snd_soc_pcm_runtime *rtd);
int msm_adsp_stream_cmd_info(struct snd_kcontrol *kcontrol,
struct snd_ctl_elem_info *uinfo);
-int msm_adsp_stream_callback_put(struct snd_kcontrol *kcontrol,
- struct snd_ctl_elem_value *ucontrol);
int msm_adsp_stream_callback_get(struct snd_kcontrol *kcontrol,
struct snd_ctl_elem_value *ucontrol);
int msm_adsp_stream_callback_info(struct snd_kcontrol *kcontrol,
diff --git a/sound/soc/msm/qdsp6v2/q6asm.c b/sound/soc/msm/qdsp6v2/q6asm.c
index 0cf386a3c2fc..4aebcb6fa77e 100644
--- a/sound/soc/msm/qdsp6v2/q6asm.c
+++ b/sound/soc/msm/qdsp6v2/q6asm.c
@@ -1675,7 +1675,7 @@ static int32_t q6asm_callback(struct apr_client_data *data, void *priv)
int32_t ret = 0;
union asm_token_struct asm_token;
uint8_t buf_index;
- char *pp_event_package = NULL;
+ struct msm_adsp_event_data *pp_event_package = NULL;
uint32_t payload_size = 0;
if (ac == NULL) {
@@ -2046,22 +2046,29 @@ static int32_t q6asm_callback(struct apr_client_data *data, void *priv)
pr_debug("%s: ASM_STREAM_PP_EVENT payload[0][0x%x] payload[1][0x%x]",
__func__, payload[0], payload[1]);
/* repack payload for asm_stream_pp_event
- * package is composed of size + actual payload
+ * package is composed of event type + size + actual payload
*/
payload_size = data->payload_size;
- pp_event_package =
- kzalloc(payload_size + sizeof(payload_size),
+ pp_event_package = kzalloc(payload_size
+ + sizeof(struct msm_adsp_event_data),
GFP_ATOMIC);
if (!pp_event_package)
return -ENOMEM;
- memcpy((void *)pp_event_package,
- &payload_size, sizeof(payload_size));
- memcpy((void *)pp_event_package + sizeof(payload_size),
+
+ pp_event_package->event_type = ASM_STREAM_PP_EVENT;
+ pp_event_package->payload_len = payload_size;
+ memcpy((void *)pp_event_package->payload,
data->payload, payload_size);
ac->cb(data->opcode, data->token,
(void *)pp_event_package, ac->priv);
kfree(pp_event_package);
return 0;
+ case ASM_SESSION_CMDRSP_ADJUST_SESSION_CLOCK_V2:
+ pr_debug("%s: ASM_SESSION_CMDRSP_ADJUST_SESSION_CLOCK_V2 sesion %d status 0x%x msw %u lsw %u\n",
+ __func__, ac->session, payload[0], payload[2],
+ payload[1]);
+ wake_up(&ac->cmd_wait);
+ break;
case ASM_SESSION_CMDRSP_GET_PATH_DELAY_V2:
pr_debug("%s: ASM_SESSION_CMDRSP_GET_PATH_DELAY_V2 session %d status 0x%x msw %u lsw %u\n",
__func__, ac->session, payload[0], payload[2],
@@ -2602,7 +2609,9 @@ int q6asm_open_write_compressed(struct audio_client *ac, uint32_t format,
case FORMAT_GEN_COMPR:
open.fmt_id = ASM_MEDIA_FMT_GENERIC_COMPRESSED;
break;
-
+ case FORMAT_TRUEHD:
+ open.fmt_id = ASM_MEDIA_FMT_TRUEHD;
+ break;
default:
pr_err("%s: Invalid format[%d]\n", __func__, format);
rc = -EINVAL;
@@ -2775,9 +2784,6 @@ static int __q6asm_open_write(struct audio_client *ac, uint32_t format,
case FORMAT_GEN_COMPR:
open.dec_fmt_id = ASM_MEDIA_FMT_GENERIC_COMPRESSED;
break;
- case FORMAT_TRUEHD:
- open.dec_fmt_id = ASM_MEDIA_FMT_TRUEHD;
- break;
default:
pr_err("%s: Invalid format 0x%x\n", __func__, format);
rc = -EINVAL;
@@ -8039,6 +8045,80 @@ exit:
return rc;
}
+int q6asm_send_mtmx_strtr_enable_adjust_session_clock(struct audio_client *ac,
+ bool enable)
+{
+ struct asm_mtmx_strtr_params matrix;
+ struct asm_session_mtmx_param_adjust_session_time_ctl_t adjust_time;
+ int sz = 0;
+ int rc = 0;
+
+ pr_debug("%s: adjust session enable %d\n", __func__, enable);
+
+ if (!ac) {
+ pr_err("%s: audio client handle is NULL\n", __func__);
+ rc = -EINVAL;
+ goto exit;
+ }
+
+ if (ac->apr == NULL) {
+ pr_err("%s: ac->apr is NULL\n", __func__);
+ rc = -EINVAL;
+ goto exit;
+ }
+
+ adjust_time.enable = enable;
+ memset(&matrix, 0, sizeof(struct asm_mtmx_strtr_params));
+ sz = sizeof(struct asm_mtmx_strtr_params);
+ q6asm_add_hdr(ac, &matrix.hdr, sz, TRUE);
+ atomic_set(&ac->cmd_state, -1);
+ matrix.hdr.opcode = ASM_SESSION_CMD_SET_MTMX_STRTR_PARAMS_V2;
+
+ matrix.param.data_payload_addr_lsw = 0;
+ matrix.param.data_payload_addr_msw = 0;
+ matrix.param.mem_map_handle = 0;
+ matrix.param.data_payload_size =
+ sizeof(struct asm_stream_param_data_v2) +
+ sizeof(struct asm_session_mtmx_param_adjust_session_time_ctl_t);
+ matrix.param.direction = 0; /* RX */
+ matrix.data.module_id = ASM_SESSION_MTMX_STRTR_MODULE_ID_AVSYNC;
+ matrix.data.param_id = ASM_SESSION_MTMX_PARAM_ADJUST_SESSION_TIME_CTL;
+ matrix.data.param_size =
+ sizeof(struct asm_session_mtmx_param_adjust_session_time_ctl_t);
+ matrix.data.reserved = 0;
+ matrix.config.adj_time_param.enable = adjust_time.enable;
+
+ rc = apr_send_pkt(ac->apr, (uint32_t *) &matrix);
+ if (rc < 0) {
+ pr_err("%s: enable adjust session failed failed paramid [0x%x]\n",
+ __func__, matrix.data.param_id);
+ rc = -EINVAL;
+ goto exit;
+ }
+
+ rc = wait_event_timeout(ac->cmd_wait,
+ (atomic_read(&ac->cmd_state) >= 0), 5*HZ);
+ if (!rc) {
+ pr_err("%s: enable adjust session failed failed paramid [0x%x]\n",
+ __func__, matrix.data.param_id);
+ rc = -ETIMEDOUT;
+ goto exit;
+ }
+
+ if (atomic_read(&ac->cmd_state) > 0) {
+ pr_err("%s: DSP returned error[%s]\n",
+ __func__, adsp_err_get_err_str(
+ atomic_read(&ac->cmd_state)));
+ rc = adsp_err_get_lnx_err_code(
+ atomic_read(&ac->cmd_state));
+ goto exit;
+ }
+ rc = 0;
+exit:
+ return rc;
+}
+
+
static int __q6asm_cmd(struct audio_client *ac, int cmd, uint32_t stream_id)
{
struct apr_hdr hdr;
@@ -8428,6 +8508,68 @@ fail_cmd:
return -EINVAL;
}
+int q6asm_adjust_session_clock(struct audio_client *ac,
+ uint32_t adjust_time_lsw,
+ uint32_t adjust_time_msw)
+{
+ int rc = 0;
+ int sz = 0;
+ struct asm_session_cmd_adjust_session_clock_v2 adjust_clock;
+
+ pr_debug("%s: adjust_time_lsw is %x, adjust_time_msw is %x\n", __func__,
+ adjust_time_lsw, adjust_time_msw);
+
+ if (!ac) {
+ pr_err("%s: audio client handle is NULL\n", __func__);
+ rc = -EINVAL;
+ goto fail_cmd;
+ }
+
+ if (ac->apr == NULL) {
+ pr_err("%s: ac->apr is NULL", __func__);
+ rc = -EINVAL;
+ goto fail_cmd;
+ }
+
+ sz = sizeof(struct asm_session_cmd_adjust_session_clock_v2);
+ q6asm_add_hdr(ac, &adjust_clock.hdr, sz, TRUE);
+ atomic_set(&ac->cmd_state, -1);
+ adjust_clock.hdr.opcode = ASM_SESSION_CMD_ADJUST_SESSION_CLOCK_V2;
+
+ adjust_clock.adjustime_lsw = adjust_time_lsw;
+ adjust_clock.adjustime_msw = adjust_time_msw;
+
+
+ rc = apr_send_pkt(ac->apr, (uint32_t *) &adjust_clock);
+ if (rc < 0) {
+ pr_err("%s: adjust_clock send failed paramid [0x%x]\n",
+ __func__, adjust_clock.hdr.opcode);
+ rc = -EINVAL;
+ goto fail_cmd;
+ }
+
+ rc = wait_event_timeout(ac->cmd_wait,
+ (atomic_read(&ac->cmd_state) >= 0), 5*HZ);
+ if (!rc) {
+ pr_err("%s: timeout, adjust_clock paramid[0x%x]\n",
+ __func__, adjust_clock.hdr.opcode);
+ rc = -ETIMEDOUT;
+ goto fail_cmd;
+ }
+
+ if (atomic_read(&ac->cmd_state) > 0) {
+ pr_err("%s: DSP returned error[%s]\n",
+ __func__, adsp_err_get_err_str(
+ atomic_read(&ac->cmd_state)));
+ rc = adsp_err_get_lnx_err_code(
+ atomic_read(&ac->cmd_state));
+ goto fail_cmd;
+ }
+ rc = 0;
+fail_cmd:
+ return rc;
+}
+
/*
* q6asm_get_path_delay() - get the path delay for an audio session
* @ac: audio client handle
diff --git a/sound/usb/stream.c b/sound/usb/stream.c
index 2bb503576134..a7d7c3a0ac3e 100644
--- a/sound/usb/stream.c
+++ b/sound/usb/stream.c
@@ -652,6 +652,16 @@ int snd_usb_parse_audio_interface(struct snd_usb_audio *chip, int iface_no)
case UAC_VERSION_3: {
int wMaxPacketSize;
+ /*
+ * Allocate a dummy instance of fmt and set format type
+ * to UAC_FORMAT_TYPE_I for BADD support; free fmt
+ * after its last usage
+ */
+ fmt = kzalloc(sizeof(*fmt), GFP_KERNEL);
+ if (!fmt)
+ return -ENOMEM;
+
+ fmt->bFormatType = UAC_FORMAT_TYPE_I;
format = UAC_FORMAT_TYPE_I_PCM;
clock = BADD_CLOCK_SOURCE;
wMaxPacketSize = le16_to_cpu(get_endpoint(alts, 0)
@@ -678,6 +688,7 @@ int snd_usb_parse_audio_interface(struct snd_usb_audio *chip, int iface_no)
dev_err(&dev->dev,
"%u:%d: invalid wMaxPacketSize\n",
iface_no, altno);
+ kfree(fmt);
continue;
}
}
@@ -776,6 +787,8 @@ populate_fp:
continue;
}
+ if (protocol == UAC_VERSION_3)
+ kfree(fmt);
/* Create chmap */
if (fp->channels != num_channels)
chconfig = 0;