diff options
233 files changed, 8601 insertions, 1289 deletions
diff --git a/Documentation/devicetree/bindings/sound/qcom-audio-dev.txt b/Documentation/devicetree/bindings/sound/qcom-audio-dev.txt index 80c3f7c462b1..102857a13a86 100644 --- a/Documentation/devicetree/bindings/sound/qcom-audio-dev.txt +++ b/Documentation/devicetree/bindings/sound/qcom-audio-dev.txt @@ -2678,3 +2678,107 @@ Example 2: qcom,spkr-tdm-rx = <&dai_quat_tdm_rx_0>; qcom,mic-tdm-tx = <&dai_quat_tdm_tx_0>; }; + +* msm-dai-group-mi2s + +[First Level Nodes] + +Required properties: + + - compatible : "qcom,msm-dai-group-mi2s" + - qcom,msm-cpudai-mi2s-group-id: ID of the group device. MI2S interface + supports up to 8 groups: + Secondary RX: 4354 + Secondary TX: 4355 + Tertiary RX: 4356 + Tertiary TX: 4357 + Quaternary RX: 4358 + Quaternary TX: 4359 + + - qcom,msm-cpudai-mi2s-group-num-ports: Number of ports in + msm-cpudai-mi2s-group-port-id array. + Max number of ports supported by DSP is 8. + + - qcom,msm-cpudai-mi2s-group-port-id: Array of mi2s port IDs of the group. + The size of the array is determined by + the value in msm-cpudai-mi2s-group-num-ports. + Each group supports up to 4 ports: + Secondary RX: 4160, 4162, 4164, 4166, + Secondary TX: 4161, 4163, 4165, 4167, + Tertiary RX: 4168, 4170, 4172, 4174, + Tertiary TX: 4169, 4171, 4173, 4175, + Quaternary RX: 4128, 4130, 4132, 4134, + Quaternary TX: 4129, 4131, 4133, 4135, + + - qcom,msm-cpudai-mi2s-channel-mode: group mi2s line channel mode. + I2S_SD0 : 0x1 + I2S_SD1 : 0x2 + I2S_SD2 : 0x3 + I2S_SD3 : 0x4 + I2S_QUAD01 : 0x5 + I2S_QUAD23 : 0x6 + I2S_6CHS : 0x7 + I2S_8CHS : 0x8 + + - qcom,msm-cpudai-mi2s-sync-mode: group mi2s master mode. + 0 - Slave + 1 - Master + + - qcom,msm-cpudai-mi2s-mclk: mi2s mclk value if required. + 0 - not provided any mclk + others - the real mclk value, at least + equal with bclk. + + - qcom,msm-cpudai-mi2s-bclk: mi2s bclk value required, the clk value should + equal channels * bit_width * rate. + + [Second Level Nodes] + +Required properties: + + - compatible : "qcom,msm-dai-group-mi2s-dev" + - qcom,msm-dai-q6-mi2s-dev-id: mi2s port ID. + - qcom,msm-cpudai-mi2s-channel-mode: mi2s port line channel mode + I2S_SD0 : 0x1 + I2S_SD1 : 0x2 + I2S_SD2 : 0x3 + I2S_SD3 : 0x4 + I2S_QUAD01 : 0x5 + I2S_QUAD23 : 0x6 + I2S_6CHS : 0x7 + I2S_8CHS : 0x8 + + - qcom,msm-cpudai-mi2s-data-align: Indicate how data is packed + within the slot. For example, 32 slot width in case of + sample bit width is 24. + 0 - MSB + 1 - LSB + +Optional properties: + + - pinctrl-names: Pinctrl state names for each pin group + configuration. + + - pinctrl-x: Defines pinctrl state for each pin group. + +Example: + qcom,msm-dai-group-mi2s-tert-tx { + compatible = "qcom,msm-dai-group-mi2s"; + qcom,msm-cpudai-mi2s-group-id = <4357>; + qcom,msm-cpudai-mi2s-group-num-ports = <2>; + qcom,msm-cpudai-mi2s-group-port-id = <4167 4169>; + qcom,msm-cpudai-mi2s-channel-mode = <5>; + dai_tert_mi2s_tx_1:qcom,msm-dai-q6-mi2s-tert-tx-1 { + compatible = "qcom,msm-dai-group-mi2s-dev"; + qcom,msm-cpudai-mi2s-dev-id = <4167>; + qcom,msm-cpudai-mi2s-dev-channel-mode = <1>; + qcom,msm-cpudai-mi2s-data-align = <0>; + }; + + dai_tert_mi2s_tx_2:qcom,msm-dai-q6-mi2s-tert-tx-2 { + compatible = "qcom,msm-dai-group-mi2s-dev"; + qcom,msm-cpudai-mi2s-dev-id = <4169>; + qcom,msm-cpudai-mi2s-dev-channel-mode = <2>; + qcom,msm-cpudai-mi2s-data-align = <0>; + }; + }; diff --git a/Documentation/sysctl/fs.txt b/Documentation/sysctl/fs.txt index 35e17f748ca7..af5859b2d0f9 100644 --- a/Documentation/sysctl/fs.txt +++ b/Documentation/sysctl/fs.txt @@ -34,7 +34,9 @@ Currently, these files are in /proc/sys/fs: - overflowgid - pipe-user-pages-hard - pipe-user-pages-soft +- protected_fifos - protected_hardlinks +- protected_regular - protected_symlinks - suid_dumpable - super-max @@ -182,6 +184,24 @@ applied. ============================================================== +protected_fifos: + +The intent of this protection is to avoid unintentional writes to +an attacker-controlled FIFO, where a program expected to create a regular +file. + +When set to "0", writing to FIFOs is unrestricted. + +When set to "1" don't allow O_CREAT open on FIFOs that we don't own +in world writable sticky directories, unless they are owned by the +owner of the directory. + +When set to "2" it also applies to group writable sticky directories. + +This protection is based on the restrictions in Openwall. + +============================================================== + protected_hardlinks: A long-standing class of security issues is the hardlink-based @@ -202,6 +222,22 @@ This protection is based on the restrictions in Openwall and grsecurity. ============================================================== +protected_regular: + +This protection is similar to protected_fifos, but it +avoids writes to an attacker-controlled regular file, where a program +expected to create one. + +When set to "0", writing to regular files is unrestricted. + +When set to "1" don't allow O_CREAT open on regular files that we +don't own in world writable sticky directories, unless they are +owned by the owner of the directory. + +When set to "2" it also applies to group writable sticky directories. + +============================================================== + protected_symlinks: A long-standing class of security issues is the symlink-based diff --git a/MAINTAINERS b/MAINTAINERS index 414c3c43d276..13cc0bc83c1c 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -10221,6 +10221,7 @@ F: arch/alpha/kernel/srm_env.c STABLE BRANCH M: Greg Kroah-Hartman <gregkh@linuxfoundation.org> +M: Sasha Levin <sashal@kernel.org> L: stable@vger.kernel.org S: Supported F: Documentation/stable_kernel_rules.txt @@ -1,6 +1,6 @@ VERSION = 4 PATCHLEVEL = 4 -SUBLEVEL = 165 +SUBLEVEL = 167 EXTRAVERSION = NAME = Blurry Fish Butt @@ -617,7 +617,11 @@ all: vmlinux ifeq ($(cc-name),clang) ifneq ($(CROSS_COMPILE),) -CLANG_TARGET := --target=$(notdir $(CROSS_COMPILE:%-=%)) +CLANG_TRIPLE ?= $(CROSS_COMPILE) +CLANG_TARGET := --target=$(notdir $(CLANG_TRIPLE:%-=%)) +ifeq ($(shell $(srctree)/scripts/clang-android.sh $(CC) $(CLANG_TARGET)), y) +$(error "Clang with Android --target detected. Did you specify CLANG_TRIPLE?") +endif GCC_TOOLCHAIN_DIR := $(dir $(shell which $(LD))) CLANG_PREFIX := --prefix=$(GCC_TOOLCHAIN_DIR) GCC_TOOLCHAIN := $(realpath $(GCC_TOOLCHAIN_DIR)/..) @@ -725,18 +729,7 @@ ifdef CONFIG_KCOV endif ifeq ($(cc-name),clang) -ifneq ($(CROSS_COMPILE),) -CLANG_TRIPLE ?= $(CROSS_COMPILE) -CLANG_TARGET := --target=$(notdir $(CLANG_TRIPLE:%-=%)) -GCC_TOOLCHAIN := $(realpath $(dir $(shell which $(LD)))/..) -endif -ifneq ($(GCC_TOOLCHAIN),) -CLANG_GCC_TC := --gcc-toolchain=$(GCC_TOOLCHAIN) -endif -KBUILD_CFLAGS += $(CLANG_TARGET) $(CLANG_GCC_TC) -KBUILD_AFLAGS += $(CLANG_TARGET) $(CLANG_GCC_TC) KBUILD_CPPFLAGS += $(call cc-option,-Qunused-arguments,) -KBUILD_CFLAGS += $(call cc-disable-warning, unused-variable) KBUILD_CFLAGS += $(call cc-disable-warning, format-invalid-specifier) KBUILD_CFLAGS += $(call cc-disable-warning, gnu) KBUILD_CFLAGS += $(call cc-disable-warning, address-of-packed-member) @@ -748,8 +741,6 @@ KBUILD_CFLAGS += $(call cc-disable-warning, tautological-compare) # See modpost pattern 2 KBUILD_CFLAGS += $(call cc-option, -mno-global-merge,) KBUILD_CFLAGS += $(call cc-option, -fcatch-undefined-behavior) -KBUILD_CFLAGS += $(call cc-option, -no-integrated-as) -KBUILD_AFLAGS += $(call cc-option, -no-integrated-as) else # These warnings generated too much noise in a regular build. @@ -823,6 +814,9 @@ KBUILD_CFLAGS += $(call cc-option,-Wdeclaration-after-statement,) # disable pointer signed / unsigned warnings in gcc 4.0 KBUILD_CFLAGS += $(call cc-disable-warning, pointer-sign) +# disable stringop warnings in gcc 8+ +KBUILD_CFLAGS += $(call cc-disable-warning, stringop-truncation) + # disable invalid "can't wrap" optimizations for signed / pointers KBUILD_CFLAGS += $(call cc-option,-fno-strict-overflow) diff --git a/arch/arc/Kconfig b/arch/arc/Kconfig index c4ee25e88a7b..e983f410135a 100644 --- a/arch/arc/Kconfig +++ b/arch/arc/Kconfig @@ -96,7 +96,7 @@ endmenu choice prompt "ARC Instruction Set" - default ISA_ARCOMPACT + default ISA_ARCV2 config ISA_ARCOMPACT bool "ARCompact ISA" diff --git a/arch/arc/Makefile b/arch/arc/Makefile index 9d64eacdd2aa..fffaff9c7b2c 100644 --- a/arch/arc/Makefile +++ b/arch/arc/Makefile @@ -12,7 +12,7 @@ ifeq ($(CROSS_COMPILE),) CROSS_COMPILE := arc-linux- endif -KBUILD_DEFCONFIG := nsim_700_defconfig +KBUILD_DEFCONFIG := nsim_hs_defconfig cflags-y += -fno-common -pipe -fno-builtin -mmedium-calls -D__linux__ cflags-$(CONFIG_ISA_ARCOMPACT) += -mA7 diff --git a/arch/arc/configs/axs101_defconfig b/arch/arc/configs/axs101_defconfig index dbee1934dfc6..3023f91c77c2 100644 --- a/arch/arc/configs/axs101_defconfig +++ b/arch/arc/configs/axs101_defconfig @@ -17,6 +17,7 @@ CONFIG_PERF_EVENTS=y # CONFIG_VM_EVENT_COUNTERS is not set # CONFIG_SLUB_DEBUG is not set # CONFIG_COMPAT_BRK is not set +CONFIG_ISA_ARCOMPACT=y CONFIG_MODULES=y CONFIG_PARTITION_ADVANCED=y CONFIG_ARC_PLAT_AXS10X=y @@ -97,6 +98,7 @@ CONFIG_NTFS_FS=y CONFIG_TMPFS=y CONFIG_JFFS2_FS=y CONFIG_NFS_FS=y +CONFIG_NFS_V3_ACL=y CONFIG_NLS_CODEPAGE_437=y CONFIG_NLS_ISO8859_1=y # CONFIG_ENABLE_WARN_DEPRECATED is not set diff --git a/arch/arc/configs/axs103_defconfig b/arch/arc/configs/axs103_defconfig index 561eac854cc3..f18107185f53 100644 --- a/arch/arc/configs/axs103_defconfig +++ b/arch/arc/configs/axs103_defconfig @@ -103,6 +103,7 @@ CONFIG_NTFS_FS=y CONFIG_TMPFS=y CONFIG_JFFS2_FS=y CONFIG_NFS_FS=y +CONFIG_NFS_V3_ACL=y CONFIG_NLS_CODEPAGE_437=y CONFIG_NLS_ISO8859_1=y # CONFIG_ENABLE_WARN_DEPRECATED is not set diff --git a/arch/arc/configs/axs103_smp_defconfig b/arch/arc/configs/axs103_smp_defconfig index aa4f261b6508..6e1dd8521d2a 100644 --- a/arch/arc/configs/axs103_smp_defconfig +++ b/arch/arc/configs/axs103_smp_defconfig @@ -104,6 +104,7 @@ CONFIG_NTFS_FS=y CONFIG_TMPFS=y CONFIG_JFFS2_FS=y CONFIG_NFS_FS=y +CONFIG_NFS_V3_ACL=y CONFIG_NLS_CODEPAGE_437=y CONFIG_NLS_ISO8859_1=y # CONFIG_ENABLE_WARN_DEPRECATED is not set diff --git a/arch/arc/configs/nsim_700_defconfig b/arch/arc/configs/nsim_700_defconfig index 138f9d887957..86e5a62556a8 100644 --- a/arch/arc/configs/nsim_700_defconfig +++ b/arch/arc/configs/nsim_700_defconfig @@ -16,6 +16,7 @@ CONFIG_KALLSYMS_ALL=y CONFIG_EMBEDDED=y # CONFIG_SLUB_DEBUG is not set # CONFIG_COMPAT_BRK is not set +CONFIG_ISA_ARCOMPACT=y CONFIG_KPROBES=y CONFIG_MODULES=y # CONFIG_LBDAF is not set diff --git a/arch/arc/configs/nsimosci_defconfig b/arch/arc/configs/nsimosci_defconfig index 31e1d95764ff..a4d7b919224a 100644 --- a/arch/arc/configs/nsimosci_defconfig +++ b/arch/arc/configs/nsimosci_defconfig @@ -17,6 +17,7 @@ CONFIG_KALLSYMS_ALL=y CONFIG_EMBEDDED=y # CONFIG_SLUB_DEBUG is not set # CONFIG_COMPAT_BRK is not set +CONFIG_ISA_ARCOMPACT=y CONFIG_KPROBES=y CONFIG_MODULES=y # CONFIG_LBDAF is not set @@ -69,5 +70,6 @@ CONFIG_EXT2_FS_XATTR=y CONFIG_TMPFS=y # CONFIG_MISC_FILESYSTEMS is not set CONFIG_NFS_FS=y +CONFIG_NFS_V3_ACL=y # CONFIG_ENABLE_WARN_DEPRECATED is not set # CONFIG_ENABLE_MUST_CHECK is not set diff --git a/arch/arc/configs/nsimosci_hs_defconfig b/arch/arc/configs/nsimosci_hs_defconfig index fcae66683ca0..b3fb49c8bd14 100644 --- a/arch/arc/configs/nsimosci_hs_defconfig +++ b/arch/arc/configs/nsimosci_hs_defconfig @@ -69,5 +69,6 @@ CONFIG_EXT2_FS_XATTR=y CONFIG_TMPFS=y # CONFIG_MISC_FILESYSTEMS is not set CONFIG_NFS_FS=y +CONFIG_NFS_V3_ACL=y # CONFIG_ENABLE_WARN_DEPRECATED is not set # CONFIG_ENABLE_MUST_CHECK is not set diff --git a/arch/arc/configs/nsimosci_hs_smp_defconfig b/arch/arc/configs/nsimosci_hs_smp_defconfig index b01b659168ea..710c167bbdd8 100644 --- a/arch/arc/configs/nsimosci_hs_smp_defconfig +++ b/arch/arc/configs/nsimosci_hs_smp_defconfig @@ -88,6 +88,7 @@ CONFIG_EXT2_FS_XATTR=y CONFIG_TMPFS=y # CONFIG_MISC_FILESYSTEMS is not set CONFIG_NFS_FS=y +CONFIG_NFS_V3_ACL=y # CONFIG_ENABLE_WARN_DEPRECATED is not set # CONFIG_ENABLE_MUST_CHECK is not set CONFIG_FTRACE=y diff --git a/arch/arc/configs/tb10x_defconfig b/arch/arc/configs/tb10x_defconfig index 3b4dc9cebcf1..7469b754ac77 100644 --- a/arch/arc/configs/tb10x_defconfig +++ b/arch/arc/configs/tb10x_defconfig @@ -19,6 +19,7 @@ CONFIG_KALLSYMS_ALL=y # CONFIG_AIO is not set CONFIG_EMBEDDED=y # CONFIG_COMPAT_BRK is not set +CONFIG_ISA_ARCOMPACT=y CONFIG_SLAB=y CONFIG_MODULES=y CONFIG_MODULE_FORCE_LOAD=y diff --git a/arch/arc/configs/vdk_hs38_defconfig b/arch/arc/configs/vdk_hs38_defconfig index a07f20de221b..772073e5ba04 100644 --- a/arch/arc/configs/vdk_hs38_defconfig +++ b/arch/arc/configs/vdk_hs38_defconfig @@ -89,6 +89,7 @@ CONFIG_NTFS_FS=y CONFIG_TMPFS=y CONFIG_JFFS2_FS=y CONFIG_NFS_FS=y +CONFIG_NFS_V3_ACL=y CONFIG_NLS_CODEPAGE_437=y CONFIG_NLS_ISO8859_1=y # CONFIG_ENABLE_WARN_DEPRECATED is not set diff --git a/arch/arc/configs/vdk_hs38_smp_defconfig b/arch/arc/configs/vdk_hs38_smp_defconfig index f36c047b33ca..50e215a163ff 100644 --- a/arch/arc/configs/vdk_hs38_smp_defconfig +++ b/arch/arc/configs/vdk_hs38_smp_defconfig @@ -91,6 +91,7 @@ CONFIG_NTFS_FS=y CONFIG_TMPFS=y CONFIG_JFFS2_FS=y CONFIG_NFS_FS=y +CONFIG_NFS_V3_ACL=y CONFIG_NLS_CODEPAGE_437=y CONFIG_NLS_ISO8859_1=y # CONFIG_ENABLE_WARN_DEPRECATED is not set diff --git a/arch/arm/boot/dts/qcom/Makefile b/arch/arm/boot/dts/qcom/Makefile index 09223b41d3d6..a84b606f94db 100644 --- a/arch/arm/boot/dts/qcom/Makefile +++ b/arch/arm/boot/dts/qcom/Makefile @@ -293,7 +293,9 @@ dtb-$(CONFIG_ARCH_SDM630) += sdm630-rumi.dtb \ sdm630-pm660a-headset-jacktype-no-rcm.dtb \ sdm455-mtp.dtb \ sdm455-qrd.dtb \ - sdm455-cdp.dtb + sdm455-cdp.dtb \ + sdm455-rcm.dtb \ + sdm455-internal-codec-rcm.dtb ifeq ($(CONFIG_ARM64),y) always := $(dtb-y) diff --git a/arch/arm/boot/dts/qcom/apq8096-auto-dragonboard.dtsi b/arch/arm/boot/dts/qcom/apq8096-auto-dragonboard.dtsi index 111266ca59f0..f484eea9f01a 100644 --- a/arch/arm/boot/dts/qcom/apq8096-auto-dragonboard.dtsi +++ b/arch/arm/boot/dts/qcom/apq8096-auto-dragonboard.dtsi @@ -729,7 +729,19 @@ <&dai_quat_tdm_rx_1>, <&dai_quat_tdm_rx_2>, <&dai_quat_tdm_rx_3>, <&dai_quat_tdm_tx_0>, <&dai_quat_tdm_tx_1>, <&dai_quat_tdm_tx_2>, - <&dai_quat_tdm_tx_3>; + <&dai_quat_tdm_tx_3>, <&dai_sec_mi2s_rx_1>, + <&dai_sec_mi2s_rx_2>, <&dai_sec_mi2s_rx_3>, + <&dai_sec_mi2s_rx_4>, <&dai_sec_mi2s_tx_1>, + <&dai_sec_mi2s_tx_2>, <&dai_sec_mi2s_tx_3>, + <&dai_sec_mi2s_tx_4>, <&dai_tert_mi2s_rx_1>, + <&dai_tert_mi2s_rx_2>, <&dai_tert_mi2s_rx_3>, + <&dai_tert_mi2s_rx_4>, <&dai_tert_mi2s_tx_1>, + <&dai_tert_mi2s_tx_2>, <&dai_tert_mi2s_tx_3>, + <&dai_tert_mi2s_tx_4>, <&dai_quat_mi2s_rx_1>, + <&dai_quat_mi2s_rx_2>, <&dai_quat_mi2s_rx_3>, + <&dai_quat_mi2s_rx_4>, <&dai_quat_mi2s_tx_1>, + <&dai_quat_mi2s_tx_2>, <&dai_quat_mi2s_tx_3>, + <&dai_quat_mi2s_tx_4>; asoc-cpu-names = "msm-dai-q6-auxpcm.1", "msm-dai-q6-auxpcm.2", "msm-dai-q6-hdmi.8", "msm-dai-q6-mi2s.1", "msm-dai-q6-mi2s.2", "msm-dai-q6-mi2s.3", @@ -753,7 +765,19 @@ "msm-dai-q6-tdm.36914", "msm-dai-q6-tdm.36916", "msm-dai-q6-tdm.36918", "msm-dai-q6-tdm.36913", "msm-dai-q6-tdm.36915", "msm-dai-q6-tdm.36917", - "msm-dai-q6-tdm.36919"; + "msm-dai-q6-tdm.36919", "msm-dai-q6-mi2s.4160", + "msm-dai-q6-mi2s.4162", "msm-dai-q6-mi2s.4164", + "msm-dai-q6-mi2s.4166", "msm-dai-q6-mi2s.4161", + "msm-dai-q6-mi2s.4163", "msm-dai-q6-mi2s.4165", + "msm-dai-q6-mi2s.4167", "msm-dai-q6-mi2s.4168", + "msm-dai-q6-mi2s.4170", "msm-dai-q6-mi2s.4172", + "msm-dai-q6-mi2s.4174", "msm-dai-q6-mi2s.4169", + "msm-dai-q6-mi2s.4171", "msm-dai-q6-mi2s.4173", + "msm-dai-q6-mi2s.4175", "msm-dai-q6-mi2s.4128", + "msm-dai-q6-mi2s.4130", "msm-dai-q6-mi2s.4132", + "msm-dai-q6-mi2s.4134", "msm-dai-q6-mi2s.4129", + "msm-dai-q6-mi2s.4131", "msm-dai-q6-mi2s.4133", + "msm-dai-q6-mi2s.4135"; asoc-codec = <&stub_codec>; asoc-codec-names = "msm-stub-codec.1"; }; diff --git a/arch/arm/boot/dts/qcom/msm8996-agave-adp.dtsi b/arch/arm/boot/dts/qcom/msm8996-agave-adp.dtsi index 211bcd607efb..db99055e095f 100644 --- a/arch/arm/boot/dts/qcom/msm8996-agave-adp.dtsi +++ b/arch/arm/boot/dts/qcom/msm8996-agave-adp.dtsi @@ -1106,7 +1106,19 @@ <&dai_quat_tdm_rx_1>, <&dai_quat_tdm_rx_2>, <&dai_quat_tdm_rx_3>, <&dai_quat_tdm_tx_0>, <&dai_quat_tdm_tx_1>, <&dai_quat_tdm_tx_2>, - <&dai_quat_tdm_tx_3>; + <&dai_quat_tdm_tx_3>, <&dai_sec_mi2s_rx_1>, + <&dai_sec_mi2s_rx_2>, <&dai_sec_mi2s_rx_3>, + <&dai_sec_mi2s_rx_4>, <&dai_sec_mi2s_tx_1>, + <&dai_sec_mi2s_tx_2>, <&dai_sec_mi2s_tx_3>, + <&dai_sec_mi2s_tx_4>, <&dai_tert_mi2s_rx_1>, + <&dai_tert_mi2s_rx_2>, <&dai_tert_mi2s_rx_3>, + <&dai_tert_mi2s_rx_4>, <&dai_tert_mi2s_tx_1>, + <&dai_tert_mi2s_tx_2>, <&dai_tert_mi2s_tx_3>, + <&dai_tert_mi2s_tx_4>, <&dai_quat_mi2s_rx_1>, + <&dai_quat_mi2s_rx_2>, <&dai_quat_mi2s_rx_3>, + <&dai_quat_mi2s_rx_4>, <&dai_quat_mi2s_tx_1>, + <&dai_quat_mi2s_tx_2>, <&dai_quat_mi2s_tx_3>, + <&dai_quat_mi2s_tx_4>; asoc-cpu-names = "msm-dai-q6-auxpcm.1", "msm-dai-q6-auxpcm.2", "msm-dai-q6-hdmi.8", "msm-dai-q6-mi2s.1", "msm-dai-q6-mi2s.2", "msm-dai-q6-mi2s.3", @@ -1130,7 +1142,19 @@ "msm-dai-q6-tdm.36914", "msm-dai-q6-tdm.36916", "msm-dai-q6-tdm.36918", "msm-dai-q6-tdm.36913", "msm-dai-q6-tdm.36915", "msm-dai-q6-tdm.36917", - "msm-dai-q6-tdm.36919"; + "msm-dai-q6-tdm.36919", "msm-dai-q6-mi2s.4160", + "msm-dai-q6-mi2s.4162", "msm-dai-q6-mi2s.4164", + "msm-dai-q6-mi2s.4166", "msm-dai-q6-mi2s.4161", + "msm-dai-q6-mi2s.4163", "msm-dai-q6-mi2s.4165", + "msm-dai-q6-mi2s.4167", "msm-dai-q6-mi2s.4168", + "msm-dai-q6-mi2s.4170", "msm-dai-q6-mi2s.4172", + "msm-dai-q6-mi2s.4174", "msm-dai-q6-mi2s.4169", + "msm-dai-q6-mi2s.4171", "msm-dai-q6-mi2s.4173", + "msm-dai-q6-mi2s.4175", "msm-dai-q6-mi2s.4128", + "msm-dai-q6-mi2s.4130", "msm-dai-q6-mi2s.4132", + "msm-dai-q6-mi2s.4134", "msm-dai-q6-mi2s.4129", + "msm-dai-q6-mi2s.4131", "msm-dai-q6-mi2s.4133", + "msm-dai-q6-mi2s.4135"; asoc-codec = <&stub_codec>; asoc-codec-names = "msm-stub-codec.1"; }; @@ -1441,7 +1465,6 @@ &usb2s { status = "ok"; qcom,no-wakeup-src-in-hostmode; - qcom,disable-host-mode-pm; }; &usb3 { @@ -1450,7 +1473,6 @@ vdda33-supply = <&pm8994_l24>; vdda18-supply = <&pm8994_l12>; qcom,no-wakeup-src-in-hostmode; - qcom,disable-host-mode-pm; }; &blsp1_uart2 { diff --git a/arch/arm/boot/dts/qcom/msm8996-auto-cdp.dtsi b/arch/arm/boot/dts/qcom/msm8996-auto-cdp.dtsi index c2f62be67892..b0ff859d560f 100644 --- a/arch/arm/boot/dts/qcom/msm8996-auto-cdp.dtsi +++ b/arch/arm/boot/dts/qcom/msm8996-auto-cdp.dtsi @@ -959,7 +959,19 @@ <&dai_quat_tdm_rx_1>, <&dai_quat_tdm_rx_2>, <&dai_quat_tdm_rx_3>, <&dai_quat_tdm_tx_0>, <&dai_quat_tdm_tx_1>, <&dai_quat_tdm_tx_2>, - <&dai_quat_tdm_tx_3>; + <&dai_quat_tdm_tx_3>, <&dai_sec_mi2s_rx_1>, + <&dai_sec_mi2s_rx_2>, <&dai_sec_mi2s_rx_3>, + <&dai_sec_mi2s_rx_4>, <&dai_sec_mi2s_tx_1>, + <&dai_sec_mi2s_tx_2>, <&dai_sec_mi2s_tx_3>, + <&dai_sec_mi2s_tx_4>, <&dai_tert_mi2s_rx_1>, + <&dai_tert_mi2s_rx_2>, <&dai_tert_mi2s_rx_3>, + <&dai_tert_mi2s_rx_4>, <&dai_tert_mi2s_tx_1>, + <&dai_tert_mi2s_tx_2>, <&dai_tert_mi2s_tx_3>, + <&dai_tert_mi2s_tx_4>, <&dai_quat_mi2s_rx_1>, + <&dai_quat_mi2s_rx_2>, <&dai_quat_mi2s_rx_3>, + <&dai_quat_mi2s_rx_4>, <&dai_quat_mi2s_tx_1>, + <&dai_quat_mi2s_tx_2>, <&dai_quat_mi2s_tx_3>, + <&dai_quat_mi2s_tx_4>; asoc-cpu-names = "msm-dai-q6-auxpcm.1", "msm-dai-q6-auxpcm.2", "msm-dai-q6-hdmi.8", "msm-dai-q6-mi2s.1", "msm-dai-q6-mi2s.2", "msm-dai-q6-mi2s.3", @@ -983,7 +995,19 @@ "msm-dai-q6-tdm.36914", "msm-dai-q6-tdm.36916", "msm-dai-q6-tdm.36918", "msm-dai-q6-tdm.36913", "msm-dai-q6-tdm.36915", "msm-dai-q6-tdm.36917", - "msm-dai-q6-tdm.36919"; + "msm-dai-q6-tdm.36919", "msm-dai-q6-mi2s.4160", + "msm-dai-q6-mi2s.4162", "msm-dai-q6-mi2s.4164", + "msm-dai-q6-mi2s.4166", "msm-dai-q6-mi2s.4161", + "msm-dai-q6-mi2s.4163", "msm-dai-q6-mi2s.4165", + "msm-dai-q6-mi2s.4167", "msm-dai-q6-mi2s.4168", + "msm-dai-q6-mi2s.4170", "msm-dai-q6-mi2s.4172", + "msm-dai-q6-mi2s.4174", "msm-dai-q6-mi2s.4169", + "msm-dai-q6-mi2s.4171", "msm-dai-q6-mi2s.4173", + "msm-dai-q6-mi2s.4175", "msm-dai-q6-mi2s.4128", + "msm-dai-q6-mi2s.4130", "msm-dai-q6-mi2s.4132", + "msm-dai-q6-mi2s.4134", "msm-dai-q6-mi2s.4129", + "msm-dai-q6-mi2s.4131", "msm-dai-q6-mi2s.4133", + "msm-dai-q6-mi2s.4135"; asoc-codec = <&stub_codec>; asoc-codec-names = "msm-stub-codec.1"; }; @@ -1272,7 +1296,6 @@ status = "ok"; vbus_dwc3-supply = <&usb2_otg_switch>; qcom,no-wakeup-src-in-hostmode; - qcom,disable-host-mode-pm; dwc3@7600000 { dr_mode = "host"; }; @@ -1284,7 +1307,6 @@ vdda33-supply = <&pm8994_l24>; vdda18-supply = <&pm8994_l12>; qcom,no-wakeup-src-in-hostmode; - qcom,disable-host-mode-pm; }; &blsp1_uart2 { @@ -1435,11 +1457,6 @@ / { reserved-memory { - lk_mem: lk_pool@0x91600000 { - reg = <0 0x91600000 0 0x00600000>; - label = "lk_pool"; - }; - early_camera_mem: early_camera_mem@b3fff000 { reg = <0 0xb3fff000 0 0x800000>; label = "early_camera_mem"; @@ -1468,3 +1485,10 @@ &ssc_sensors { status = "disabled"; }; + +&soc { + early_domain: early_domain { + compatible = "qcom,early_domain"; + status = "disabled"; + }; +}; diff --git a/arch/arm/boot/dts/qcom/msm8996-mmxf-adp.dtsi b/arch/arm/boot/dts/qcom/msm8996-mmxf-adp.dtsi index c0969a6aa106..4367a876a64d 100644 --- a/arch/arm/boot/dts/qcom/msm8996-mmxf-adp.dtsi +++ b/arch/arm/boot/dts/qcom/msm8996-mmxf-adp.dtsi @@ -554,7 +554,19 @@ <&dai_quat_tdm_rx_1>, <&dai_quat_tdm_rx_2>, <&dai_quat_tdm_rx_3>, <&dai_quat_tdm_tx_0>, <&dai_quat_tdm_tx_1>, <&dai_quat_tdm_tx_2>, - <&dai_quat_tdm_tx_3>; + <&dai_quat_tdm_tx_3>, <&dai_sec_mi2s_rx_1>, + <&dai_sec_mi2s_rx_2>, <&dai_sec_mi2s_rx_3>, + <&dai_sec_mi2s_rx_4>, <&dai_sec_mi2s_tx_1>, + <&dai_sec_mi2s_tx_2>, <&dai_sec_mi2s_tx_3>, + <&dai_sec_mi2s_tx_4>, <&dai_tert_mi2s_rx_1>, + <&dai_tert_mi2s_rx_2>, <&dai_tert_mi2s_rx_3>, + <&dai_tert_mi2s_rx_4>, <&dai_tert_mi2s_tx_1>, + <&dai_tert_mi2s_tx_2>, <&dai_tert_mi2s_tx_3>, + <&dai_tert_mi2s_tx_4>, <&dai_quat_mi2s_rx_1>, + <&dai_quat_mi2s_rx_2>, <&dai_quat_mi2s_rx_3>, + <&dai_quat_mi2s_rx_4>, <&dai_quat_mi2s_tx_1>, + <&dai_quat_mi2s_tx_2>, <&dai_quat_mi2s_tx_3>, + <&dai_quat_mi2s_tx_4>; asoc-cpu-names = "msm-dai-q6-auxpcm.1", "msm-dai-q6-auxpcm.2", "msm-dai-q6-hdmi.8", "msm-dai-q6-mi2s.1", "msm-dai-q6-mi2s.2", "msm-dai-q6-mi2s.3", @@ -578,7 +590,19 @@ "msm-dai-q6-tdm.36914", "msm-dai-q6-tdm.36916", "msm-dai-q6-tdm.36918", "msm-dai-q6-tdm.36913", "msm-dai-q6-tdm.36915", "msm-dai-q6-tdm.36917", - "msm-dai-q6-tdm.36919"; + "msm-dai-q6-tdm.36919", "msm-dai-q6-mi2s.4160", + "msm-dai-q6-mi2s.4162", "msm-dai-q6-mi2s.4164", + "msm-dai-q6-mi2s.4166", "msm-dai-q6-mi2s.4161", + "msm-dai-q6-mi2s.4163", "msm-dai-q6-mi2s.4165", + "msm-dai-q6-mi2s.4167", "msm-dai-q6-mi2s.4168", + "msm-dai-q6-mi2s.4170", "msm-dai-q6-mi2s.4172", + "msm-dai-q6-mi2s.4174", "msm-dai-q6-mi2s.4169", + "msm-dai-q6-mi2s.4171", "msm-dai-q6-mi2s.4173", + "msm-dai-q6-mi2s.4175", "msm-dai-q6-mi2s.4128", + "msm-dai-q6-mi2s.4130", "msm-dai-q6-mi2s.4132", + "msm-dai-q6-mi2s.4134", "msm-dai-q6-mi2s.4129", + "msm-dai-q6-mi2s.4131", "msm-dai-q6-mi2s.4133", + "msm-dai-q6-mi2s.4135"; asoc-codec = <&stub_codec>; asoc-codec-names = "msm-stub-codec.1"; }; diff --git a/arch/arm/boot/dts/qcom/msm8996.dtsi b/arch/arm/boot/dts/qcom/msm8996.dtsi index 4ca58d03115c..aa1d28a082a8 100644 --- a/arch/arm/boot/dts/qcom/msm8996.dtsi +++ b/arch/arm/boot/dts/qcom/msm8996.dtsi @@ -3560,6 +3560,234 @@ }; }; + qcom,msm-dai-group-mi2s-sec-rx { + compatible = "qcom,msm-dai-group-mi2s"; + qcom,msm-cpudai-mi2s-group-id = <4354>; + qcom,msm-cpudai-mi2s-group-num-ports = <4>; + qcom,msm-cpudai-mi2s-group-port-id = <4160 4162 4164 4166>; + qcom,msm-cpudai-mi2s-channel-mode = <2>; + qcom,msm-cpudai-mi2s-sync-mode = <1>; + qcom,msm-cpudai-mi2s-mclk = <12288000>; + qcom,msm-cpudai-mi2s-bclk = <3072000>; + dai_sec_mi2s_rx_1:qcom,msm-dai-q6-mi2s-sec-rx-1 { + compatible = "qcom,msm-dai-group-mi2s-dev"; + qcom,msm-cpudai-mi2s-dev-id = <4160>; + qcom,msm-cpudai-mi2s-dev-channel-mode = <2>; + qcom,msm-cpudai-mi2s-data-align = <0>; + }; + + dai_sec_mi2s_rx_2:qcom,msm-dai-q6-mi2s-sec-rx-2 { + compatible = "qcom,msm-dai-group-mi2s-dev"; + qcom,msm-cpudai-mi2s-dev-id = <4162>; + qcom,msm-cpudai-mi2s-dev-channel-mode = <2>; + qcom,msm-cpudai-mi2s-data-align = <0>; + }; + + dai_sec_mi2s_rx_3:qcom,msm-dai-q6-mi2s-sec-rx-3 { + compatible = "qcom,msm-dai-group-mi2s-dev"; + qcom,msm-cpudai-mi2s-dev-id = <4164>; + qcom,msm-cpudai-mi2s-dev-channel-mode = <2>; + qcom,msm-cpudai-mi2s-data-align = <0>; + }; + + dai_sec_mi2s_rx_4:qcom,msm-dai-q6-mi2s-sec-rx-4 { + compatible = "qcom,msm-dai-group-mi2s-dev"; + qcom,msm-cpudai-mi2s-dev-id = <4166>; + qcom,msm-cpudai-mi2s-dev-channel-mode = <2>; + qcom,msm-cpudai-mi2s-data-align = <0>; + }; + }; + + qcom,msm-dai-group-mi2s-sec-tx { + compatible = "qcom,msm-dai-group-mi2s"; + qcom,msm-cpudai-mi2s-group-id = <4355>; + qcom,msm-cpudai-mi2s-group-num-ports = <4>; + qcom,msm-cpudai-mi2s-group-port-id = <4161 4163 4165 4167>; + qcom,msm-cpudai-mi2s-channel-mode = <1>; + qcom,msm-cpudai-mi2s-sync-mode = <1>; + qcom,msm-cpudai-mi2s-mclk = <12288000>; + qcom,msm-cpudai-mi2s-bclk = <3072000>; + dai_sec_mi2s_tx_1:qcom,msm-dai-q6-mi2s-sec-tx-1 { + compatible = "qcom,msm-dai-group-mi2s-dev"; + qcom,msm-cpudai-mi2s-dev-id = <4161>; + qcom,msm-cpudai-mi2s-dev-channel-mode = <1>; + qcom,msm-cpudai-mi2s-data-align = <0>; + }; + + dai_sec_mi2s_tx_2:qcom,msm-dai-q6-mi2s-sec-tx-2 { + compatible = "qcom,msm-dai-group-mi2s-dev"; + qcom,msm-cpudai-mi2s-dev-id = <4163>; + qcom,msm-cpudai-mi2s-dev-channel-mode = <1>; + qcom,msm-cpudai-mi2s-data-align = <0>; + }; + + dai_sec_mi2s_tx_3:qcom,msm-dai-q6-mi2s-sec-tx-3 { + compatible = "qcom,msm-dai-group-mi2s-dev"; + qcom,msm-cpudai-mi2s-dev-id = <4165>; + qcom,msm-cpudai-mi2s-dev-channel-mode = <1>; + qcom,msm-cpudai-mi2s-data-align = <0>; + }; + + dai_sec_mi2s_tx_4:qcom,msm-dai-q6-mi2s-sec-tx-4 { + compatible = "qcom,msm-dai-group-mi2s-dev"; + qcom,msm-cpudai-mi2s-dev-id = <4167>; + qcom,msm-cpudai-mi2s-dev-channel-mode = <1>; + qcom,msm-cpudai-mi2s-data-align = <0>; + }; + }; + + qcom,msm-dai-group-mi2s-tert-rx { + compatible = "qcom,msm-dai-group-mi2s"; + qcom,msm-cpudai-mi2s-group-id = <4356>; + qcom,msm-cpudai-mi2s-group-num-ports = <4>; + qcom,msm-cpudai-mi2s-group-port-id = <4168 4170 4172 4174>; + qcom,msm-cpudai-mi2s-channel-mode = <5>; + qcom,msm-cpudai-mi2s-sync-mode = <1>; + qcom,msm-cpudai-mi2s-mclk = <3072000>; + qcom,msm-cpudai-mi2s-bclk = <3072000>; + dai_tert_mi2s_rx_1:qcom,msm-dai-q6-mi2s-tert-rx-1 { + compatible = "qcom,msm-dai-group-mi2s-dev"; + qcom,msm-cpudai-mi2s-dev-id = <4168>; + qcom,msm-cpudai-mi2s-dev-channel-mode = <1>; + qcom,msm-cpudai-mi2s-data-align = <0>; + }; + + dai_tert_mi2s_rx_2:qcom,msm-dai-q6-mi2s-tert-rx-2 { + compatible = "qcom,msm-dai-group-mi2s-dev"; + qcom,msm-cpudai-mi2s-dev-id = <4170>; + qcom,msm-cpudai-mi2s-dev-channel-mode = <2>; + qcom,msm-cpudai-mi2s-data-align = <0>; + }; + + dai_tert_mi2s_rx_3:qcom,msm-dai-q6-mi2s-tert-rx-3 { + compatible = "qcom,msm-dai-group-mi2s-dev"; + qcom,msm-cpudai-mi2s-dev-id = <4172>; + qcom,msm-cpudai-mi2s-dev-channel-mode = <1>; + qcom,msm-cpudai-mi2s-data-align = <0>; + }; + + dai_tert_mi2s_rx_4:qcom,msm-dai-q6-mi2s-tert-rx-4 { + compatible = "qcom,msm-dai-group-mi2s-dev"; + qcom,msm-cpudai-mi2s-dev-id = <4174>; + qcom,msm-cpudai-mi2s-dev-channel-mode = <2>; + qcom,msm-cpudai-mi2s-data-align = <0>; + }; + }; + + qcom,msm-dai-group-mi2s-tert-tx { + compatible = "qcom,msm-dai-group-mi2s"; + qcom,msm-cpudai-mi2s-group-id = <4357>; + qcom,msm-cpudai-mi2s-group-num-ports = <4>; + qcom,msm-cpudai-mi2s-group-port-id = <4169 4171 4173 4175>; + qcom,msm-cpudai-mi2s-channel-mode = <5>; + qcom,msm-cpudai-mi2s-sync-mode = <1>; + qcom,msm-cpudai-mi2s-mclk = <3072000>; + qcom,msm-cpudai-mi2s-bclk = <3072000>; + dai_tert_mi2s_tx_1:qcom,msm-dai-q6-mi2s-tert-tx-1 { + compatible = "qcom,msm-dai-group-mi2s-dev"; + qcom,msm-cpudai-mi2s-dev-id = <4169>; + qcom,msm-cpudai-mi2s-dev-channel-mode = <1>; + qcom,msm-cpudai-mi2s-data-align = <0>; + }; + + dai_tert_mi2s_tx_2:qcom,msm-dai-q6-mi2s-tert-tx-2 { + compatible = "qcom,msm-dai-group-mi2s-dev"; + qcom,msm-cpudai-mi2s-dev-id = <4171>; + qcom,msm-cpudai-mi2s-dev-channel-mode = <2>; + qcom,msm-cpudai-mi2s-data-align = <0>; + }; + + dai_tert_mi2s_tx_3:qcom,msm-dai-q6-mi2s-tert-tx-3 { + compatible = "qcom,msm-dai-group-mi2s-dev"; + qcom,msm-cpudai-mi2s-dev-id = <4173>; + qcom,msm-cpudai-mi2s-dev-channel-mode = <1>; + qcom,msm-cpudai-mi2s-data-align = <0>; + }; + + dai_tert_mi2s_tx_4:qcom,msm-dai-q6-mi2s-tert-tx-4 { + compatible = "qcom,msm-dai-group-mi2s-dev"; + qcom,msm-cpudai-mi2s-dev-id = <4175>; + qcom,msm-cpudai-mi2s-dev-channel-mode = <2>; + qcom,msm-cpudai-mi2s-data-align = <0>; + }; + }; + + qcom,msm-dai-group-mi2s-quat-rx { + compatible = "qcom,msm-dai-group-mi2s"; + qcom,msm-cpudai-mi2s-group-id = <4358>; + qcom,msm-cpudai-mi2s-group-num-ports = <4>; + qcom,msm-cpudai-mi2s-group-port-id = <4128 4130 4132 4134>; + qcom,msm-cpudai-mi2s-channel-mode = <8>; + qcom,msm-cpudai-mi2s-sync-mode = <1>; + qcom,msm-cpudai-mi2s-mclk = <0>; + qcom,msm-cpudai-mi2s-bclk = <3072000>; + dai_quat_mi2s_rx_1:qcom,msm-dai-q6-mi2s-quat-rx-1 { + compatible = "qcom,msm-dai-group-mi2s-dev"; + qcom,msm-cpudai-mi2s-dev-id = <4128>; + qcom,msm-cpudai-mi2s-dev-channel-mode = <1>; + qcom,msm-cpudai-mi2s-data-align = <0>; + }; + + dai_quat_mi2s_rx_2:qcom,msm-dai-q6-mi2s-quat-rx-2 { + compatible = "qcom,msm-dai-group-mi2s-dev"; + qcom,msm-cpudai-mi2s-dev-id = <4130>; + qcom,msm-cpudai-mi2s-dev-channel-mode = <2>; + qcom,msm-cpudai-mi2s-data-align = <0>; + }; + + dai_quat_mi2s_rx_3:qcom,msm-dai-q6-mi2s-quat-rx-3 { + compatible = "qcom,msm-dai-group-mi2s-dev"; + qcom,msm-cpudai-mi2s-dev-id = <4132>; + qcom,msm-cpudai-mi2s-dev-channel-mode = <3>; + qcom,msm-cpudai-mi2s-data-align = <0>; + }; + + dai_quat_mi2s_rx_4:qcom,msm-dai-q6-mi2s-quat-rx-4 { + compatible = "qcom,msm-dai-group-mi2s-dev"; + qcom,msm-cpudai-mi2s-dev-id = <4134>; + qcom,msm-cpudai-mi2s-dev-channel-mode = <4>; + qcom,msm-cpudai-mi2s-data-align = <0>; + }; + }; + + qcom,msm-dai-group-mi2s-quat-tx { + compatible = "qcom,msm-dai-group-mi2s"; + qcom,msm-cpudai-mi2s-group-id = <4359>; + qcom,msm-cpudai-mi2s-group-num-ports = <4>; + qcom,msm-cpudai-mi2s-group-port-id = <4129 4131 4133 4135>; + qcom,msm-cpudai-mi2s-channel-mode = <7>; + qcom,msm-cpudai-mi2s-sync-mode = <1>; + qcom,msm-cpudai-mi2s-mclk = <0>; + qcom,msm-cpudai-mi2s-bclk = <3072000>; + dai_quat_mi2s_tx_1:qcom,msm-dai-q6-mi2s-quat-tx-1 { + compatible = "qcom,msm-dai-group-mi2s-dev"; + qcom,msm-cpudai-mi2s-dev-id = <4129>; + qcom,msm-cpudai-mi2s-dev-channel-mode = <1>; + qcom,msm-cpudai-mi2s-data-align = <0>; + }; + + dai_quat_mi2s_tx_2:qcom,msm-dai-q6-mi2s-quat-tx-2 { + compatible = "qcom,msm-dai-group-mi2s-dev"; + qcom,msm-cpudai-mi2s-dev-id = <4131>; + qcom,msm-cpudai-mi2s-dev-channel-mode = <2>; + qcom,msm-cpudai-mi2s-data-align = <0>; + }; + + dai_quat_mi2s_tx_3:qcom,msm-dai-q6-mi2s-quat-tx-3 { + compatible = "qcom,msm-dai-group-mi2s-dev"; + qcom,msm-cpudai-mi2s-dev-id = <4133>; + qcom,msm-cpudai-mi2s-dev-channel-mode = <3>; + qcom,msm-cpudai-mi2s-data-align = <0>; + }; + + dai_quat_mi2s_tx_4:qcom,msm-dai-q6-mi2s-quat-tx-4 { + compatible = "qcom,msm-dai-group-mi2s-dev"; + qcom,msm-cpudai-mi2s-dev-id = <4135>; + qcom,msm-cpudai-mi2s-dev-channel-mode = <4>; + qcom,msm-cpudai-mi2s-data-align = <0>; + }; + }; + qcom,msm-dai-tdm-pri-rx { compatible = "qcom,msm-dai-tdm"; qcom,msm-cpudai-tdm-group-id = <37120>; diff --git a/arch/arm/boot/dts/qcom/sdm455-internal-codec-rcm.dts b/arch/arm/boot/dts/qcom/sdm455-internal-codec-rcm.dts new file mode 100644 index 000000000000..a43de6111483 --- /dev/null +++ b/arch/arm/boot/dts/qcom/sdm455-internal-codec-rcm.dts @@ -0,0 +1,24 @@ +/* Copyright (c) 2018, The Linux Foundation. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 and + * only version 2 as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + */ + + +/dts-v1/; + +#include "sdm455.dtsi" +#include "sdm455-rcm.dtsi" +#include "sdm660-internal-codec.dtsi" + +/ { + model = "Qualcomm Technologies, Inc. SDM455 Int. Audio Codec RCM"; + compatible = "qcom,sdm630-cdp", "qcom,sdm630", "qcom,cdp"; + qcom,board-id = <21 1>; +}; diff --git a/arch/arm/boot/dts/qcom/sdm455-rcm.dts b/arch/arm/boot/dts/qcom/sdm455-rcm.dts new file mode 100644 index 000000000000..868f8b940737 --- /dev/null +++ b/arch/arm/boot/dts/qcom/sdm455-rcm.dts @@ -0,0 +1,34 @@ +/* Copyright (c) 2018, The Linux Foundation. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 and + * only version 2 as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + */ + + +/dts-v1/; + +#include "sdm455.dtsi" +#include "sdm455-rcm.dtsi" +#include "sdm660-external-codec.dtsi" + +/ { + model = "Qualcomm Technologies, Inc. SDM 630 PM660 + PM660L RCM"; + compatible = "qcom,sdm630-cdp", "qcom,sdm630", "qcom,cdp"; + qcom,board-id = <21 0>; +}; + +&tavil_snd { + qcom,msm-mbhc-hphl-swh = <0>; + qcom,msm-mbhc-gnd-swh = <0>; +}; + +&tasha_snd { + qcom,msm-mbhc-hphl-swh = <0>; + qcom,msm-mbhc-gnd-swh = <0>; +}; diff --git a/arch/arm/boot/dts/qcom/sdm455-rcm.dtsi b/arch/arm/boot/dts/qcom/sdm455-rcm.dtsi new file mode 100644 index 000000000000..bc54d29450e1 --- /dev/null +++ b/arch/arm/boot/dts/qcom/sdm455-rcm.dtsi @@ -0,0 +1,13 @@ +/* Copyright (c) 2018, The Linux Foundation. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 and + * only version 2 as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + */ + +#include "sdm630-cdp.dtsi" diff --git a/arch/arm/boot/dts/qcom/vplatform-lfv-msm8996-audio-common.dtsi b/arch/arm/boot/dts/qcom/vplatform-lfv-msm8996-audio-common.dtsi index 3928836b8e80..1aec20a24824 100644 --- a/arch/arm/boot/dts/qcom/vplatform-lfv-msm8996-audio-common.dtsi +++ b/arch/arm/boot/dts/qcom/vplatform-lfv-msm8996-audio-common.dtsi @@ -48,7 +48,19 @@ <&dai_quat_tdm_rx_1>, <&dai_quat_tdm_rx_2>, <&dai_quat_tdm_rx_3>, <&dai_quat_tdm_tx_0>, <&dai_quat_tdm_tx_1>, <&dai_quat_tdm_tx_2>, - <&dai_quat_tdm_tx_3>; + <&dai_quat_tdm_tx_3>, <&dai_sec_mi2s_rx_1>, + <&dai_sec_mi2s_rx_2>, <&dai_sec_mi2s_rx_3>, + <&dai_sec_mi2s_rx_4>, <&dai_sec_mi2s_tx_1>, + <&dai_sec_mi2s_tx_2>, <&dai_sec_mi2s_tx_3>, + <&dai_sec_mi2s_tx_4>, <&dai_tert_mi2s_rx_1>, + <&dai_tert_mi2s_rx_2>, <&dai_tert_mi2s_rx_3>, + <&dai_tert_mi2s_rx_4>, <&dai_tert_mi2s_tx_1>, + <&dai_tert_mi2s_tx_2>, <&dai_tert_mi2s_tx_3>, + <&dai_tert_mi2s_tx_4>, <&dai_quat_mi2s_rx_1>, + <&dai_quat_mi2s_rx_2>, <&dai_quat_mi2s_rx_3>, + <&dai_quat_mi2s_rx_4>, <&dai_quat_mi2s_tx_1>, + <&dai_quat_mi2s_tx_2>, <&dai_quat_mi2s_tx_3>, + <&dai_quat_mi2s_tx_4>; asoc-cpu-names = "msm-dai-q6-auxpcm.1", "msm-dai-q6-auxpcm.2", "msm-dai-q6-hdmi.8", "msm-dai-q6-mi2s.1", "msm-dai-q6-mi2s.2", "msm-dai-q6-mi2s.3", @@ -72,7 +84,19 @@ "msm-dai-q6-tdm.36914", "msm-dai-q6-tdm.36916", "msm-dai-q6-tdm.36918", "msm-dai-q6-tdm.36913", "msm-dai-q6-tdm.36915", "msm-dai-q6-tdm.36917", - "msm-dai-q6-tdm.36919"; + "msm-dai-q6-tdm.36919", "msm-dai-q6-mi2s.4160", + "msm-dai-q6-mi2s.4162", "msm-dai-q6-mi2s.4164", + "msm-dai-q6-mi2s.4166", "msm-dai-q6-mi2s.4161", + "msm-dai-q6-mi2s.4163", "msm-dai-q6-mi2s.4165", + "msm-dai-q6-mi2s.4167", "msm-dai-q6-mi2s.4168", + "msm-dai-q6-mi2s.4170", "msm-dai-q6-mi2s.4172", + "msm-dai-q6-mi2s.4174", "msm-dai-q6-mi2s.4169", + "msm-dai-q6-mi2s.4171", "msm-dai-q6-mi2s.4173", + "msm-dai-q6-mi2s.4175", "msm-dai-q6-mi2s.4128", + "msm-dai-q6-mi2s.4130", "msm-dai-q6-mi2s.4132", + "msm-dai-q6-mi2s.4134", "msm-dai-q6-mi2s.4129", + "msm-dai-q6-mi2s.4131", "msm-dai-q6-mi2s.4133", + "msm-dai-q6-mi2s.4135"; asoc-codec = <&stub_codec>; asoc-codec-names = "msm-stub-codec.1"; }; @@ -249,6 +273,234 @@ }; }; + qcom,msm-dai-group-mi2s-sec-rx { + compatible = "qcom,msm-dai-group-mi2s"; + qcom,msm-cpudai-mi2s-group-id = <4354>; + qcom,msm-cpudai-mi2s-group-num-ports = <4>; + qcom,msm-cpudai-mi2s-group-port-id = <4160 4162 4164 4166>; + qcom,msm-cpudai-mi2s-channel-mode = <2>; + qcom,msm-cpudai-mi2s-sync-mode = <1>; + qcom,msm-cpudai-mi2s-mclk = <12288000>; + qcom,msm-cpudai-mi2s-bclk = <3072000>; + dai_sec_mi2s_rx_1:qcom,msm-dai-q6-mi2s-sec-rx-1 { + compatible = "qcom,msm-dai-group-mi2s-dev"; + qcom,msm-cpudai-mi2s-dev-id = <4160>; + qcom,msm-cpudai-mi2s-dev-channel-mode = <2>; + qcom,msm-cpudai-mi2s-data-align = <0>; + }; + + dai_sec_mi2s_rx_2:qcom,msm-dai-q6-mi2s-sec-rx-2 { + compatible = "qcom,msm-dai-group-mi2s-dev"; + qcom,msm-cpudai-mi2s-dev-id = <4162>; + qcom,msm-cpudai-mi2s-dev-channel-mode = <2>; + qcom,msm-cpudai-mi2s-data-align = <0>; + }; + + dai_sec_mi2s_rx_3:qcom,msm-dai-q6-mi2s-sec-rx-3 { + compatible = "qcom,msm-dai-group-mi2s-dev"; + qcom,msm-cpudai-mi2s-dev-id = <4164>; + qcom,msm-cpudai-mi2s-dev-channel-mode = <2>; + qcom,msm-cpudai-mi2s-data-align = <0>; + }; + + dai_sec_mi2s_rx_4:qcom,msm-dai-q6-mi2s-sec-rx-4 { + compatible = "qcom,msm-dai-group-mi2s-dev"; + qcom,msm-cpudai-mi2s-dev-id = <4166>; + qcom,msm-cpudai-mi2s-dev-channel-mode = <2>; + qcom,msm-cpudai-mi2s-data-align = <0>; + }; + }; + + qcom,msm-dai-group-mi2s-sec-tx { + compatible = "qcom,msm-dai-group-mi2s"; + qcom,msm-cpudai-mi2s-group-id = <4355>; + qcom,msm-cpudai-mi2s-group-num-ports = <4>; + qcom,msm-cpudai-mi2s-group-port-id = <4161 4163 4165 4167>; + qcom,msm-cpudai-mi2s-channel-mode = <1>; + qcom,msm-cpudai-mi2s-sync-mode = <1>; + qcom,msm-cpudai-mi2s-mclk = <12288000>; + qcom,msm-cpudai-mi2s-bclk = <3072000>; + dai_sec_mi2s_tx_1:qcom,msm-dai-q6-mi2s-sec-tx-1 { + compatible = "qcom,msm-dai-group-mi2s-dev"; + qcom,msm-cpudai-mi2s-dev-id = <4161>; + qcom,msm-cpudai-mi2s-dev-channel-mode = <1>; + qcom,msm-cpudai-mi2s-data-align = <0>; + }; + + dai_sec_mi2s_tx_2:qcom,msm-dai-q6-mi2s-sec-tx-2 { + compatible = "qcom,msm-dai-group-mi2s-dev"; + qcom,msm-cpudai-mi2s-dev-id = <4163>; + qcom,msm-cpudai-mi2s-dev-channel-mode = <1>; + qcom,msm-cpudai-mi2s-data-align = <0>; + }; + + dai_sec_mi2s_tx_3:qcom,msm-dai-q6-mi2s-sec-tx-3 { + compatible = "qcom,msm-dai-group-mi2s-dev"; + qcom,msm-cpudai-mi2s-dev-id = <4165>; + qcom,msm-cpudai-mi2s-dev-channel-mode = <1>; + qcom,msm-cpudai-mi2s-data-align = <0>; + }; + + dai_sec_mi2s_tx_4:qcom,msm-dai-q6-mi2s-sec-tx-4 { + compatible = "qcom,msm-dai-group-mi2s-dev"; + qcom,msm-cpudai-mi2s-dev-id = <4167>; + qcom,msm-cpudai-mi2s-dev-channel-mode = <1>; + qcom,msm-cpudai-mi2s-data-align = <0>; + }; + }; + + qcom,msm-dai-group-mi2s-tert-rx { + compatible = "qcom,msm-dai-group-mi2s"; + qcom,msm-cpudai-mi2s-group-id = <4356>; + qcom,msm-cpudai-mi2s-group-num-ports = <4>; + qcom,msm-cpudai-mi2s-group-port-id = <4168 4170 4172 4174>; + qcom,msm-cpudai-mi2s-channel-mode = <5>; + qcom,msm-cpudai-mi2s-sync-mode = <1>; + qcom,msm-cpudai-mi2s-mclk = <3072000>; + qcom,msm-cpudai-mi2s-bclk = <3072000>; + dai_tert_mi2s_rx_1:qcom,msm-dai-q6-mi2s-tert-rx-1 { + compatible = "qcom,msm-dai-group-mi2s-dev"; + qcom,msm-cpudai-mi2s-dev-id = <4168>; + qcom,msm-cpudai-mi2s-dev-channel-mode = <1>; + qcom,msm-cpudai-mi2s-data-align = <0>; + }; + + dai_tert_mi2s_rx_2:qcom,msm-dai-q6-mi2s-tert-rx-2 { + compatible = "qcom,msm-dai-group-mi2s-dev"; + qcom,msm-cpudai-mi2s-dev-id = <4170>; + qcom,msm-cpudai-mi2s-dev-channel-mode = <2>; + qcom,msm-cpudai-mi2s-data-align = <0>; + }; + + dai_tert_mi2s_rx_3:qcom,msm-dai-q6-mi2s-tert-rx-3 { + compatible = "qcom,msm-dai-group-mi2s-dev"; + qcom,msm-cpudai-mi2s-dev-id = <4172>; + qcom,msm-cpudai-mi2s-dev-channel-mode = <1>; + qcom,msm-cpudai-mi2s-data-align = <0>; + }; + + dai_tert_mi2s_rx_4:qcom,msm-dai-q6-mi2s-tert-rx-4 { + compatible = "qcom,msm-dai-group-mi2s-dev"; + qcom,msm-cpudai-mi2s-dev-id = <4174>; + qcom,msm-cpudai-mi2s-dev-channel-mode = <2>; + qcom,msm-cpudai-mi2s-data-align = <0>; + }; + }; + + qcom,msm-dai-group-mi2s-tert-tx { + compatible = "qcom,msm-dai-group-mi2s"; + qcom,msm-cpudai-mi2s-group-id = <4357>; + qcom,msm-cpudai-mi2s-group-num-ports = <4>; + qcom,msm-cpudai-mi2s-group-port-id = <4169 4171 4173 4175>; + qcom,msm-cpudai-mi2s-channel-mode = <5>; + qcom,msm-cpudai-mi2s-sync-mode = <1>; + qcom,msm-cpudai-mi2s-mclk = <3072000>; + qcom,msm-cpudai-mi2s-bclk = <3072000>; + dai_tert_mi2s_tx_1:qcom,msm-dai-q6-mi2s-tert-tx-1 { + compatible = "qcom,msm-dai-group-mi2s-dev"; + qcom,msm-cpudai-mi2s-dev-id = <4169>; + qcom,msm-cpudai-mi2s-dev-channel-mode = <1>; + qcom,msm-cpudai-mi2s-data-align = <0>; + }; + + dai_tert_mi2s_tx_2:qcom,msm-dai-q6-mi2s-tert-tx-2 { + compatible = "qcom,msm-dai-group-mi2s-dev"; + qcom,msm-cpudai-mi2s-dev-id = <4171>; + qcom,msm-cpudai-mi2s-dev-channel-mode = <2>; + qcom,msm-cpudai-mi2s-data-align = <0>; + }; + + dai_tert_mi2s_tx_3:qcom,msm-dai-q6-mi2s-tert-tx-3 { + compatible = "qcom,msm-dai-group-mi2s-dev"; + qcom,msm-cpudai-mi2s-dev-id = <4173>; + qcom,msm-cpudai-mi2s-dev-channel-mode = <1>; + qcom,msm-cpudai-mi2s-data-align = <0>; + }; + + dai_tert_mi2s_tx_4:qcom,msm-dai-q6-mi2s-tert-tx-4 { + compatible = "qcom,msm-dai-group-mi2s-dev"; + qcom,msm-cpudai-mi2s-dev-id = <4175>; + qcom,msm-cpudai-mi2s-dev-channel-mode = <2>; + qcom,msm-cpudai-mi2s-data-align = <0>; + }; + }; + + qcom,msm-dai-group-mi2s-quat-rx { + compatible = "qcom,msm-dai-group-mi2s"; + qcom,msm-cpudai-mi2s-group-id = <4358>; + qcom,msm-cpudai-mi2s-group-num-ports = <4>; + qcom,msm-cpudai-mi2s-group-port-id = <4128 4130 4132 4134>; + qcom,msm-cpudai-mi2s-channel-mode = <8>; + qcom,msm-cpudai-mi2s-sync-mode = <1>; + qcom,msm-cpudai-mi2s-mclk = <0>; + qcom,msm-cpudai-mi2s-bclk = <3072000>; + dai_quat_mi2s_rx_1:qcom,msm-dai-q6-mi2s-quat-rx-1 { + compatible = "qcom,msm-dai-group-mi2s-dev"; + qcom,msm-cpudai-mi2s-dev-id = <4128>; + qcom,msm-cpudai-mi2s-dev-channel-mode = <1>; + qcom,msm-cpudai-mi2s-data-align = <0>; + }; + + dai_quat_mi2s_rx_2:qcom,msm-dai-q6-mi2s-quat-rx-2 { + compatible = "qcom,msm-dai-group-mi2s-dev"; + qcom,msm-cpudai-mi2s-dev-id = <4130>; + qcom,msm-cpudai-mi2s-dev-channel-mode = <2>; + qcom,msm-cpudai-mi2s-data-align = <0>; + }; + + dai_quat_mi2s_rx_3:qcom,msm-dai-q6-mi2s-quat-rx-3 { + compatible = "qcom,msm-dai-group-mi2s-dev"; + qcom,msm-cpudai-mi2s-dev-id = <4132>; + qcom,msm-cpudai-mi2s-dev-channel-mode = <3>; + qcom,msm-cpudai-mi2s-data-align = <0>; + }; + + dai_quat_mi2s_rx_4:qcom,msm-dai-q6-mi2s-quat-rx-4 { + compatible = "qcom,msm-dai-group-mi2s-dev"; + qcom,msm-cpudai-mi2s-dev-id = <4134>; + qcom,msm-cpudai-mi2s-dev-channel-mode = <4>; + qcom,msm-cpudai-mi2s-data-align = <0>; + }; + }; + + qcom,msm-dai-group-mi2s-quat-tx { + compatible = "qcom,msm-dai-group-mi2s"; + qcom,msm-cpudai-mi2s-group-id = <4359>; + qcom,msm-cpudai-mi2s-group-num-ports = <4>; + qcom,msm-cpudai-mi2s-group-port-id = <4129 4131 4133 4135>; + qcom,msm-cpudai-mi2s-channel-mode = <7>; + qcom,msm-cpudai-mi2s-sync-mode = <1>; + qcom,msm-cpudai-mi2s-mclk = <0>; + qcom,msm-cpudai-mi2s-bclk = <3072000>; + dai_quat_mi2s_tx_1:qcom,msm-dai-q6-mi2s-quat-tx-1 { + compatible = "qcom,msm-dai-group-mi2s-dev"; + qcom,msm-cpudai-mi2s-dev-id = <4129>; + qcom,msm-cpudai-mi2s-dev-channel-mode = <1>; + qcom,msm-cpudai-mi2s-data-align = <0>; + }; + + dai_quat_mi2s_tx_2:qcom,msm-dai-q6-mi2s-quat-tx-2 { + compatible = "qcom,msm-dai-group-mi2s-dev"; + qcom,msm-cpudai-mi2s-dev-id = <4131>; + qcom,msm-cpudai-mi2s-dev-channel-mode = <2>; + qcom,msm-cpudai-mi2s-data-align = <0>; + }; + + dai_quat_mi2s_tx_3:qcom,msm-dai-q6-mi2s-quat-tx-3 { + compatible = "qcom,msm-dai-group-mi2s-dev"; + qcom,msm-cpudai-mi2s-dev-id = <4133>; + qcom,msm-cpudai-mi2s-dev-channel-mode = <3>; + qcom,msm-cpudai-mi2s-data-align = <0>; + }; + + dai_quat_mi2s_tx_4:qcom,msm-dai-q6-mi2s-quat-tx-4 { + compatible = "qcom,msm-dai-group-mi2s-dev"; + qcom,msm-cpudai-mi2s-dev-id = <4135>; + qcom,msm-cpudai-mi2s-dev-channel-mode = <4>; + qcom,msm-cpudai-mi2s-data-align = <0>; + }; + }; + qcom,msm-dai-tdm-pri-rx { compatible = "qcom,msm-dai-tdm"; qcom,msm-cpudai-tdm-group-id = <37120>; diff --git a/arch/arm/boot/dts/qcom/vplatform-lfv-msm8996-usb.dtsi b/arch/arm/boot/dts/qcom/vplatform-lfv-msm8996-usb.dtsi index faaf00b6ac25..b7505743986e 100644 --- a/arch/arm/boot/dts/qcom/vplatform-lfv-msm8996-usb.dtsi +++ b/arch/arm/boot/dts/qcom/vplatform-lfv-msm8996-usb.dtsi @@ -88,7 +88,6 @@ resets = <&clock_virt USB_30_BCR>; reset-names = "core_reset"; - qcom,disable-host-mode-pm; dwc3@6a00000 { compatible = "snps,dwc3"; diff --git a/arch/arm/kernel/ptrace.c b/arch/arm/kernel/ptrace.c index d54c53b7ab63..ae738a6319f6 100644 --- a/arch/arm/kernel/ptrace.c +++ b/arch/arm/kernel/ptrace.c @@ -932,18 +932,19 @@ asmlinkage int syscall_trace_enter(struct pt_regs *regs, int scno) { current_thread_info()->syscall = scno; - /* Do the secure computing check first; failures should be fast. */ + if (test_thread_flag(TIF_SYSCALL_TRACE)) + tracehook_report_syscall(regs, PTRACE_SYSCALL_ENTER); + + /* Do seccomp after ptrace; syscall may have changed. */ #ifdef CONFIG_HAVE_ARCH_SECCOMP_FILTER - if (secure_computing() == -1) + if (secure_computing(NULL) == -1) return -1; #else /* XXX: remove this once OABI gets fixed */ - secure_computing_strict(scno); + secure_computing_strict(current_thread_info()->syscall); #endif - if (test_thread_flag(TIF_SYSCALL_TRACE)) - tracehook_report_syscall(regs, PTRACE_SYSCALL_ENTER); - + /* Tracer or seccomp may have changed syscall. */ scno = current_thread_info()->syscall; if (test_thread_flag(TIF_SYSCALL_TRACEPOINT)) diff --git a/arch/arm64/Makefile b/arch/arm64/Makefile index cc8b41e151b9..e8361ff258f2 100644 --- a/arch/arm64/Makefile +++ b/arch/arm64/Makefile @@ -10,7 +10,7 @@ # # Copyright (C) 1995-2001 by Russell King -LDFLAGS_vmlinux :=-p --no-undefined -X +LDFLAGS_vmlinux :=--no-undefined -X CPPFLAGS_vmlinux.lds = -DTEXT_OFFSET=$(TEXT_OFFSET) OBJCOPYFLAGS :=-O binary -R .note -R .note.gnu.build-id -R .comment -S GZFLAGS :=-9 diff --git a/arch/arm64/configs/cuttlefish_defconfig b/arch/arm64/configs/cuttlefish_defconfig new file mode 100644 index 000000000000..c620078b587c --- /dev/null +++ b/arch/arm64/configs/cuttlefish_defconfig @@ -0,0 +1,411 @@ +# CONFIG_USELIB is not set +CONFIG_AUDIT=y +CONFIG_NO_HZ=y +CONFIG_HIGH_RES_TIMERS=y +CONFIG_TASKSTATS=y +CONFIG_TASK_DELAY_ACCT=y +CONFIG_TASK_XACCT=y +CONFIG_TASK_IO_ACCOUNTING=y +CONFIG_IKCONFIG=y +CONFIG_IKCONFIG_PROC=y +CONFIG_CGROUP_FREEZER=y +CONFIG_CPUSETS=y +# CONFIG_PROC_PID_CPUSET is not set +CONFIG_CGROUP_CPUACCT=y +CONFIG_CGROUP_SCHEDTUNE=y +CONFIG_MEMCG=y +CONFIG_MEMCG_SWAP=y +CONFIG_RT_GROUP_SCHED=y +CONFIG_SCHED_AUTOGROUP=y +CONFIG_SCHED_TUNE=y +CONFIG_DEFAULT_USE_ENERGY_AWARE=y +CONFIG_BLK_DEV_INITRD=y +# CONFIG_RD_BZIP2 is not set +# CONFIG_RD_LZMA is not set +# CONFIG_RD_XZ is not set +# CONFIG_RD_LZO is not set +# CONFIG_RD_LZ4 is not set +CONFIG_SGETMASK_SYSCALL=y +# CONFIG_SYSFS_SYSCALL is not set +CONFIG_KALLSYMS_ALL=y +CONFIG_BPF_SYSCALL=y +CONFIG_EMBEDDED=y +# CONFIG_VM_EVENT_COUNTERS is not set +# CONFIG_COMPAT_BRK is not set +CONFIG_PROFILING=y +CONFIG_JUMP_LABEL=y +CONFIG_CC_STACKPROTECTOR_STRONG=y +CONFIG_MODULES=y +CONFIG_MODULE_UNLOAD=y +CONFIG_MODVERSIONS=y +CONFIG_PCI=y +CONFIG_PCI_MSI=y +CONFIG_PCI_HOST_GENERIC=y +CONFIG_PREEMPT=y +CONFIG_HZ_100=y +# CONFIG_SPARSEMEM_VMEMMAP is not set +CONFIG_KSM=y +CONFIG_TRANSPARENT_HUGEPAGE=y +CONFIG_ZSMALLOC=y +CONFIG_SECCOMP=y +CONFIG_ARMV8_DEPRECATED=y +CONFIG_SWP_EMULATION=y +CONFIG_CP15_BARRIER_EMULATION=y +CONFIG_SETEND_EMULATION=y +CONFIG_ARM64_SW_TTBR0_PAN=y +CONFIG_RANDOMIZE_BASE=y +CONFIG_CMDLINE="console=ttyAMA0" +CONFIG_CMDLINE_EXTEND=y +# CONFIG_EFI is not set +# CONFIG_CORE_DUMP_DEFAULT_ELF_HEADERS is not set +CONFIG_COMPAT=y +CONFIG_PM_WAKELOCKS=y +CONFIG_PM_WAKELOCKS_LIMIT=0 +# CONFIG_PM_WAKELOCKS_GC is not set +CONFIG_PM_DEBUG=y +CONFIG_ARM_CPUIDLE=y +CONFIG_CPU_FREQ=y +CONFIG_CPU_FREQ_DEFAULT_GOV_SCHEDUTIL=y +CONFIG_CPU_FREQ_GOV_POWERSAVE=y +CONFIG_CPU_FREQ_GOV_CONSERVATIVE=y +CONFIG_CPUFREQ_DT=y +CONFIG_ARM_BIG_LITTLE_CPUFREQ=y +CONFIG_ARM_DT_BL_CPUFREQ=y +CONFIG_NET=y +CONFIG_PACKET=y +CONFIG_UNIX=y +CONFIG_XFRM_USER=y +CONFIG_NET_KEY=y +CONFIG_INET=y +CONFIG_IP_MULTICAST=y +CONFIG_IP_ADVANCED_ROUTER=y +CONFIG_IP_MULTIPLE_TABLES=y +CONFIG_NET_IPGRE_DEMUX=y +CONFIG_NET_IPVTI=y +CONFIG_INET_ESP=y +# CONFIG_INET_XFRM_MODE_BEET is not set +# CONFIG_INET_LRO is not set +CONFIG_INET_UDP_DIAG=y +CONFIG_INET_DIAG_DESTROY=y +CONFIG_TCP_CONG_ADVANCED=y +# CONFIG_TCP_CONG_BIC is not set +# CONFIG_TCP_CONG_WESTWOOD is not set +# CONFIG_TCP_CONG_HTCP is not set +CONFIG_IPV6_ROUTER_PREF=y +CONFIG_IPV6_ROUTE_INFO=y +CONFIG_IPV6_OPTIMISTIC_DAD=y +CONFIG_INET6_ESP=y +CONFIG_INET6_IPCOMP=y +CONFIG_IPV6_MIP6=y +CONFIG_IPV6_VTI=y +CONFIG_IPV6_MULTIPLE_TABLES=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_MARK=y +CONFIG_NETFILTER_XT_TARGET_NFLOG=y +CONFIG_NETFILTER_XT_TARGET_NFQUEUE=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_BPF=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_HASHLIMIT=y +CONFIG_NETFILTER_XT_MATCH_HELPER=y +CONFIG_NETFILTER_XT_MATCH_IPRANGE=y +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_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_ECN=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_L2TP=y +CONFIG_NET_SCHED=y +CONFIG_NET_SCH_HTB=y +CONFIG_NET_CLS_U32=y +CONFIG_NET_EMATCH=y +CONFIG_NET_EMATCH_U32=y +CONFIG_NET_CLS_ACT=y +CONFIG_CFG80211=y +# CONFIG_CFG80211_DEFAULT_PS is not set +CONFIG_MAC80211=y +# CONFIG_MAC80211_RC_MINSTREL is not set +CONFIG_RFKILL=y +# CONFIG_UEVENT_HELPER is not set +CONFIG_DEVTMPFS=y +# CONFIG_ALLOW_DEV_COREDUMP is not set +CONFIG_DEBUG_DEVRES=y +CONFIG_OF_UNITTEST=y +CONFIG_ZRAM=y +CONFIG_BLK_DEV_LOOP=y +CONFIG_BLK_DEV_RAM=y +CONFIG_BLK_DEV_RAM_SIZE=8192 +CONFIG_VIRTIO_BLK=y +CONFIG_UID_SYS_STATS=y +CONFIG_SCSI=y +# CONFIG_SCSI_PROC_FS is not set +CONFIG_BLK_DEV_SD=y +CONFIG_SCSI_VIRTIO=y +CONFIG_MD=y +CONFIG_BLK_DEV_DM=y +CONFIG_DM_CRYPT=y +CONFIG_DM_UEVENT=y +CONFIG_DM_VERITY=y +CONFIG_DM_VERITY_FEC=y +CONFIG_DM_VERITY_AVB=y +CONFIG_NETDEVICES=y +CONFIG_NETCONSOLE=y +CONFIG_NETCONSOLE_DYNAMIC=y +CONFIG_TUN=y +CONFIG_VIRTIO_NET=y +# CONFIG_ETHERNET is not set +CONFIG_PHYLIB=y +CONFIG_PPP=y +CONFIG_PPP_BSDCOMP=y +CONFIG_PPP_DEFLATE=y +CONFIG_PPP_MPPE=y +CONFIG_PPTP=y +CONFIG_PPPOL2TP=y +CONFIG_USB_USBNET=y +# CONFIG_USB_NET_AX8817X is not set +# CONFIG_USB_NET_AX88179_178A is not set +# CONFIG_USB_NET_CDCETHER is not set +# CONFIG_USB_NET_CDC_NCM is not set +# CONFIG_USB_NET_NET1080 is not set +# CONFIG_USB_NET_CDC_SUBSET is not set +# CONFIG_USB_NET_ZAURUS is not set +CONFIG_VIRT_WIFI=y +CONFIG_INPUT_EVDEV=y +CONFIG_INPUT_KEYRESET=y +# CONFIG_INPUT_KEYBOARD is not set +# CONFIG_INPUT_MOUSE is not set +CONFIG_INPUT_JOYSTICK=y +CONFIG_JOYSTICK_XPAD=y +CONFIG_JOYSTICK_XPAD_FF=y +CONFIG_JOYSTICK_XPAD_LEDS=y +CONFIG_INPUT_TABLET=y +CONFIG_TABLET_USB_ACECAD=y +CONFIG_TABLET_USB_AIPTEK=y +CONFIG_TABLET_USB_GTCO=y +CONFIG_TABLET_USB_HANWANG=y +CONFIG_TABLET_USB_KBTAB=y +CONFIG_INPUT_MISC=y +CONFIG_INPUT_UINPUT=y +CONFIG_INPUT_GPIO=y +# CONFIG_VT is not set +# CONFIG_LEGACY_PTYS is not set +# CONFIG_DEVMEM is not set +# CONFIG_DEVKMEM is not set +CONFIG_SERIAL_8250=y +# CONFIG_SERIAL_8250_DEPRECATED_OPTIONS is not set +CONFIG_SERIAL_8250_CONSOLE=y +CONFIG_SERIAL_8250_NR_UARTS=48 +CONFIG_SERIAL_8250_EXTENDED=y +CONFIG_SERIAL_8250_MANY_PORTS=y +CONFIG_SERIAL_8250_SHARE_IRQ=y +CONFIG_SERIAL_AMBA_PL011=y +CONFIG_SERIAL_AMBA_PL011_CONSOLE=y +CONFIG_VIRTIO_CONSOLE=y +CONFIG_HW_RANDOM=y +CONFIG_HW_RANDOM_VIRTIO=y +# CONFIG_DEVPORT is not set +# CONFIG_I2C_COMPAT is not set +# CONFIG_I2C_HELPER_AUTO is not set +CONFIG_GPIOLIB=y +# CONFIG_HWMON is not set +CONFIG_CPU_THERMAL=y +CONFIG_MEDIA_SUPPORT=y +# CONFIG_DVB_TUNER_DIB0070 is not set +# CONFIG_DVB_TUNER_DIB0090 is not set +# CONFIG_VGA_ARB is not set +CONFIG_DRM=y +# CONFIG_DRM_FBDEV_EMULATION is not set +CONFIG_DRM_VIRTIO_GPU=y +CONFIG_SOUND=y +CONFIG_SND=y +CONFIG_HIDRAW=y +CONFIG_UHID=y +CONFIG_HID_A4TECH=y +CONFIG_HID_ACRUX=y +CONFIG_HID_ACRUX_FF=y +CONFIG_HID_APPLE=y +CONFIG_HID_BELKIN=y +CONFIG_HID_CHERRY=y +CONFIG_HID_CHICONY=y +CONFIG_HID_PRODIKEYS=y +CONFIG_HID_CYPRESS=y +CONFIG_HID_DRAGONRISE=y +CONFIG_DRAGONRISE_FF=y +CONFIG_HID_EMS_FF=y +CONFIG_HID_ELECOM=y +CONFIG_HID_EZKEY=y +CONFIG_HID_HOLTEK=y +CONFIG_HID_KEYTOUCH=y +CONFIG_HID_KYE=y +CONFIG_HID_UCLOGIC=y +CONFIG_HID_WALTOP=y +CONFIG_HID_GYRATION=y +CONFIG_HID_TWINHAN=y +CONFIG_HID_KENSINGTON=y +CONFIG_HID_LCPOWER=y +CONFIG_HID_LOGITECH=y +CONFIG_HID_LOGITECH_DJ=y +CONFIG_LOGITECH_FF=y +CONFIG_LOGIRUMBLEPAD2_FF=y +CONFIG_LOGIG940_FF=y +CONFIG_HID_MAGICMOUSE=y +CONFIG_HID_MICROSOFT=y +CONFIG_HID_MONTEREY=y +CONFIG_HID_MULTITOUCH=y +CONFIG_HID_NTRIG=y +CONFIG_HID_ORTEK=y +CONFIG_HID_PANTHERLORD=y +CONFIG_PANTHERLORD_FF=y +CONFIG_HID_PETALYNX=y +CONFIG_HID_PICOLCD=y +CONFIG_HID_PRIMAX=y +CONFIG_HID_ROCCAT=y +CONFIG_HID_SAITEK=y +CONFIG_HID_SAMSUNG=y +CONFIG_HID_SONY=y +CONFIG_HID_SPEEDLINK=y +CONFIG_HID_SUNPLUS=y +CONFIG_HID_GREENASIA=y +CONFIG_GREENASIA_FF=y +CONFIG_HID_SMARTJOYPLUS=y +CONFIG_SMARTJOYPLUS_FF=y +CONFIG_HID_TIVO=y +CONFIG_HID_TOPSEED=y +CONFIG_HID_THRUSTMASTER=y +CONFIG_HID_WACOM=y +CONFIG_HID_WIIMOTE=y +CONFIG_HID_ZEROPLUS=y +CONFIG_HID_ZYDACRON=y +CONFIG_USB_HIDDEV=y +CONFIG_USB_ANNOUNCE_NEW_DEVICES=y +CONFIG_USB_EHCI_HCD=y +CONFIG_USB_GADGET=y +CONFIG_USB_CONFIGFS=y +CONFIG_USB_CONFIGFS_F_FS=y +CONFIG_USB_CONFIGFS_F_ACC=y +CONFIG_USB_CONFIGFS_F_AUDIO_SRC=y +CONFIG_USB_CONFIGFS_UEVENT=y +CONFIG_USB_CONFIGFS_F_MIDI=y +CONFIG_MMC=y +# CONFIG_MMC_BLOCK is not set +CONFIG_RTC_CLASS=y +# CONFIG_RTC_HCTOSYS is not set +# CONFIG_RTC_SYSTOHC is not set +CONFIG_RTC_DRV_PL031=y +CONFIG_VIRTIO_PCI=y +# CONFIG_VIRTIO_PCI_LEGACY is not set +CONFIG_VIRTIO_BALLOON=y +CONFIG_VIRTIO_MMIO=y +CONFIG_VIRTIO_MMIO_CMDLINE_DEVICES=y +CONFIG_STAGING=y +CONFIG_ASHMEM=y +CONFIG_ANDROID_TIMED_GPIO=y +CONFIG_SYNC=y +CONFIG_ANDROID_VSOC=y +CONFIG_ION=y +# CONFIG_COMMON_CLK_XGENE is not set +CONFIG_MAILBOX=y +# CONFIG_IOMMU_SUPPORT is not set +CONFIG_ANDROID=y +CONFIG_ANDROID_BINDER_IPC=y +CONFIG_EXT4_FS=y +CONFIG_EXT4_FS_SECURITY=y +CONFIG_EXT4_ENCRYPTION=y +CONFIG_F2FS_FS=y +CONFIG_F2FS_FS_SECURITY=y +CONFIG_F2FS_FS_ENCRYPTION=y +# CONFIG_DNOTIFY is not set +CONFIG_QUOTA=y +CONFIG_QFMT_V2=y +CONFIG_FUSE_FS=y +CONFIG_MSDOS_FS=y +CONFIG_VFAT_FS=y +CONFIG_TMPFS=y +CONFIG_TMPFS_POSIX_ACL=y +CONFIG_SDCARD_FS=y +CONFIG_PSTORE=y +CONFIG_PSTORE_CONSOLE=y +CONFIG_PSTORE_RAM=y +CONFIG_PRINTK_TIME=y +CONFIG_DEBUG_INFO=y +# CONFIG_ENABLE_MUST_CHECK is not set +CONFIG_FRAME_WARN=1024 +# CONFIG_SECTION_MISMATCH_WARN_ONLY is not set +CONFIG_MAGIC_SYSRQ=y +CONFIG_DEBUG_STACK_USAGE=y +CONFIG_DEBUG_MEMORY_INIT=y +CONFIG_PANIC_TIMEOUT=5 +CONFIG_SCHEDSTATS=y +CONFIG_TIMER_STATS=y +CONFIG_RCU_CPU_STALL_TIMEOUT=60 +CONFIG_ENABLE_DEFAULT_TRACERS=y +CONFIG_DEBUG_SET_MODULE_RONX=y +CONFIG_SECURITY_PERF_EVENTS_RESTRICT=y +CONFIG_SECURITY=y +CONFIG_SECURITY_NETWORK=y +CONFIG_LSM_MMAP_MIN_ADDR=65536 +CONFIG_HARDENED_USERCOPY=y +CONFIG_SECURITY_SELINUX=y +CONFIG_CRYPTO_SHA512=y +CONFIG_CRYPTO_LZ4=y +CONFIG_CRYPTO_ZSTD=y +CONFIG_CRYPTO_ANSI_CPRNG=y +CONFIG_XZ_DEC=y diff --git a/arch/arm64/kernel/ptrace.c b/arch/arm64/kernel/ptrace.c index 6204b7600d1b..c67bd311e815 100644 --- a/arch/arm64/kernel/ptrace.c +++ b/arch/arm64/kernel/ptrace.c @@ -1354,13 +1354,13 @@ static void tracehook_report_syscall(struct pt_regs *regs, asmlinkage int syscall_trace_enter(struct pt_regs *regs) { - /* Do the secure computing check first; failures should be fast. */ - if (secure_computing() == -1) - return -1; - if (test_thread_flag(TIF_SYSCALL_TRACE)) tracehook_report_syscall(regs, PTRACE_SYSCALL_ENTER); + /* Do the secure computing after ptrace; failures should be fast. */ + if (secure_computing(NULL) == -1) + return -1; + if (test_thread_flag(TIF_SYSCALL_TRACEPOINT)) trace_sys_enter(regs, regs->syscallno); diff --git a/arch/mips/include/asm/syscall.h b/arch/mips/include/asm/syscall.h index 47bc45a67e9b..032a497356f3 100644 --- a/arch/mips/include/asm/syscall.h +++ b/arch/mips/include/asm/syscall.h @@ -51,7 +51,7 @@ static inline unsigned long mips_get_syscall_arg(unsigned long *arg, #ifdef CONFIG_64BIT case 4: case 5: case 6: case 7: #ifdef CONFIG_MIPS32_O32 - if (test_thread_flag(TIF_32BIT_REGS)) + if (test_tsk_thread_flag(task, TIF_32BIT_REGS)) return get_user(*arg, (int *)usp + n); else #endif diff --git a/arch/mips/kernel/ptrace.c b/arch/mips/kernel/ptrace.c index 9d04392f7ef0..816c4b281c0f 100644 --- a/arch/mips/kernel/ptrace.c +++ b/arch/mips/kernel/ptrace.c @@ -1023,7 +1023,7 @@ asmlinkage long syscall_trace_enter(struct pt_regs *regs, long syscall) current_thread_info()->syscall = syscall; - if (secure_computing() == -1) + if (secure_computing(NULL) == -1) return -1; if (test_thread_flag(TIF_SYSCALL_TRACE) && diff --git a/arch/mips/ralink/mt7620.c b/arch/mips/ralink/mt7620.c index c5f45fc96c74..9c19f5493b85 100644 --- a/arch/mips/ralink/mt7620.c +++ b/arch/mips/ralink/mt7620.c @@ -81,7 +81,7 @@ static struct rt2880_pmx_func pcie_rst_grp[] = { }; static struct rt2880_pmx_func nd_sd_grp[] = { FUNC("nand", MT7620_GPIO_MODE_NAND, 45, 15), - FUNC("sd", MT7620_GPIO_MODE_SD, 45, 15) + FUNC("sd", MT7620_GPIO_MODE_SD, 47, 13) }; static struct rt2880_pmx_group mt7620a_pinmux_data[] = { diff --git a/arch/powerpc/kernel/ptrace.c b/arch/powerpc/kernel/ptrace.c index 3b63655efa3c..e776567b281a 100644 --- a/arch/powerpc/kernel/ptrace.c +++ b/arch/powerpc/kernel/ptrace.c @@ -1783,7 +1783,7 @@ static int do_seccomp(struct pt_regs *regs) * have already loaded -ENOSYS into r3, or seccomp has put * something else in r3 (via SECCOMP_RET_ERRNO/TRACE). */ - if (__secure_computing()) + if (__secure_computing(NULL)) return -1; /* diff --git a/arch/powerpc/kvm/trace.h b/arch/powerpc/kvm/trace.h index 2e0e67ef3544..e8cedf32345a 100644 --- a/arch/powerpc/kvm/trace.h +++ b/arch/powerpc/kvm/trace.h @@ -5,8 +5,6 @@ #undef TRACE_SYSTEM #define TRACE_SYSTEM kvm -#define TRACE_INCLUDE_PATH . -#define TRACE_INCLUDE_FILE trace /* * Tracepoint for guest mode entry. @@ -119,4 +117,10 @@ TRACE_EVENT(kvm_check_requests, #endif /* _TRACE_KVM_H */ /* This part must be outside protection */ +#undef TRACE_INCLUDE_PATH +#undef TRACE_INCLUDE_FILE + +#define TRACE_INCLUDE_PATH . +#define TRACE_INCLUDE_FILE trace + #include <trace/define_trace.h> diff --git a/arch/powerpc/kvm/trace_booke.h b/arch/powerpc/kvm/trace_booke.h index 7ec534d1db9f..7eadbf449a1f 100644 --- a/arch/powerpc/kvm/trace_booke.h +++ b/arch/powerpc/kvm/trace_booke.h @@ -5,8 +5,6 @@ #undef TRACE_SYSTEM #define TRACE_SYSTEM kvm_booke -#define TRACE_INCLUDE_PATH . -#define TRACE_INCLUDE_FILE trace_booke #define kvm_trace_symbol_exit \ {0, "CRITICAL"}, \ @@ -217,4 +215,11 @@ TRACE_EVENT(kvm_booke_queue_irqprio, #endif /* This part must be outside protection */ + +#undef TRACE_INCLUDE_PATH +#undef TRACE_INCLUDE_FILE + +#define TRACE_INCLUDE_PATH . +#define TRACE_INCLUDE_FILE trace_booke + #include <trace/define_trace.h> diff --git a/arch/powerpc/kvm/trace_hv.h b/arch/powerpc/kvm/trace_hv.h index 33d9daff5783..d1bfe017d751 100644 --- a/arch/powerpc/kvm/trace_hv.h +++ b/arch/powerpc/kvm/trace_hv.h @@ -8,8 +8,6 @@ #undef TRACE_SYSTEM #define TRACE_SYSTEM kvm_hv -#define TRACE_INCLUDE_PATH . -#define TRACE_INCLUDE_FILE trace_hv #define kvm_trace_symbol_hcall \ {H_REMOVE, "H_REMOVE"}, \ @@ -474,4 +472,11 @@ TRACE_EVENT(kvmppc_run_vcpu_exit, #endif /* _TRACE_KVM_HV_H */ /* This part must be outside protection */ + +#undef TRACE_INCLUDE_PATH +#undef TRACE_INCLUDE_FILE + +#define TRACE_INCLUDE_PATH . +#define TRACE_INCLUDE_FILE trace_hv + #include <trace/define_trace.h> diff --git a/arch/powerpc/kvm/trace_pr.h b/arch/powerpc/kvm/trace_pr.h index 810507cb688a..1e40aa2aa5af 100644 --- a/arch/powerpc/kvm/trace_pr.h +++ b/arch/powerpc/kvm/trace_pr.h @@ -7,8 +7,6 @@ #undef TRACE_SYSTEM #define TRACE_SYSTEM kvm_pr -#define TRACE_INCLUDE_PATH . -#define TRACE_INCLUDE_FILE trace_pr TRACE_EVENT(kvm_book3s_reenter, TP_PROTO(int r, struct kvm_vcpu *vcpu), @@ -271,4 +269,11 @@ TRACE_EVENT(kvm_unmap_hva, #endif /* _TRACE_KVM_H */ /* This part must be outside protection */ + +#undef TRACE_INCLUDE_PATH +#undef TRACE_INCLUDE_FILE + +#define TRACE_INCLUDE_PATH . +#define TRACE_INCLUDE_FILE trace_pr + #include <trace/define_trace.h> diff --git a/arch/powerpc/mm/numa.c b/arch/powerpc/mm/numa.c index 3c4faa4c2742..bb3df222ae71 100644 --- a/arch/powerpc/mm/numa.c +++ b/arch/powerpc/mm/numa.c @@ -1319,7 +1319,7 @@ static long vphn_get_associativity(unsigned long cpu, switch (rc) { case H_FUNCTION: - printk(KERN_INFO + printk_once(KERN_INFO "VPHN is not supported. Disabling polling...\n"); stop_topology_update(); break; diff --git a/arch/s390/kernel/ptrace.c b/arch/s390/kernel/ptrace.c index 02bd587b610b..fe35d5c27d3c 100644 --- a/arch/s390/kernel/ptrace.c +++ b/arch/s390/kernel/ptrace.c @@ -826,7 +826,7 @@ asmlinkage long do_syscall_trace_enter(struct pt_regs *regs) long ret = 0; /* Do the secure computing check first. */ - if (secure_computing()) { + if (secure_computing(NULL)) { /* seccomp failures shouldn't expose any additional code. */ ret = -1; goto out; diff --git a/arch/s390/mm/pgtable.c b/arch/s390/mm/pgtable.c index 05ae254f84cf..1866b6a5171a 100644 --- a/arch/s390/mm/pgtable.c +++ b/arch/s390/mm/pgtable.c @@ -637,6 +637,8 @@ void gmap_discard(struct gmap *gmap, unsigned long from, unsigned long to) vmaddr |= gaddr & ~PMD_MASK; /* Find vma in the parent mm */ vma = find_vma(gmap->mm, vmaddr); + if (!vma) + continue; size = min(to - gaddr, PMD_SIZE - (gaddr & ~PMD_MASK)); zap_page_range(vma, vmaddr, size, NULL); } diff --git a/arch/tile/kernel/ptrace.c b/arch/tile/kernel/ptrace.c index 6239aa155f6d..35d786a840e6 100644 --- a/arch/tile/kernel/ptrace.c +++ b/arch/tile/kernel/ptrace.c @@ -262,7 +262,7 @@ int do_syscall_trace_enter(struct pt_regs *regs) if (work & _TIF_NOHZ) user_exit(); - if (secure_computing() == -1) + if (secure_computing(NULL) == -1) return -1; if (work & _TIF_SYSCALL_TRACE) { diff --git a/arch/x86/configs/x86_64_cuttlefish_defconfig b/arch/x86/configs/x86_64_cuttlefish_defconfig index c5ccb61274c5..8e4a038e9ac2 100644 --- a/arch/x86/configs/x86_64_cuttlefish_defconfig +++ b/arch/x86/configs/x86_64_cuttlefish_defconfig @@ -247,6 +247,7 @@ CONFIG_USB_USBNET=y # CONFIG_USB_NET_CDC_SUBSET is not set # CONFIG_USB_NET_ZAURUS is not set CONFIG_MAC80211_HWSIM=y +CONFIG_VIRT_WIFI=y CONFIG_INPUT_EVDEV=y CONFIG_INPUT_KEYRESET=y # CONFIG_INPUT_KEYBOARD is not set diff --git a/arch/x86/entry/common.c b/arch/x86/entry/common.c index a9e501303e15..c611c1ed064b 100644 --- a/arch/x86/entry/common.c +++ b/arch/x86/entry/common.c @@ -64,22 +64,16 @@ static void do_audit_syscall_entry(struct pt_regs *regs, u32 arch) } /* - * We can return 0 to resume the syscall or anything else to go to phase - * 2. If we resume the syscall, we need to put something appropriate in - * regs->orig_ax. - * - * NB: We don't have full pt_regs here, but regs->orig_ax and regs->ax - * are fully functional. - * - * For phase 2's benefit, our return value is: - * 0: resume the syscall - * 1: go to phase 2; no seccomp phase 2 needed - * anything else: go to phase 2; pass return value to seccomp + * Returns the syscall nr to run (which should match regs->orig_ax) or -1 + * to skip the syscall. */ -unsigned long syscall_trace_enter_phase1(struct pt_regs *regs, u32 arch) +long syscall_trace_enter(struct pt_regs *regs) { + u32 arch = is_ia32_task() ? AUDIT_ARCH_I386 : AUDIT_ARCH_X86_64; + struct thread_info *ti = pt_regs_to_thread_info(regs); unsigned long ret = 0; + bool emulated = false; u32 work; if (IS_ENABLED(CONFIG_DEBUG_ENTRY)) @@ -98,11 +92,29 @@ unsigned long syscall_trace_enter_phase1(struct pt_regs *regs, u32 arch) } #endif + /* + * If we stepped into a sysenter/syscall insn, it trapped in + * kernel mode; do_debug() cleared TF and set TIF_SINGLESTEP. + * If user-mode had set TF itself, then it's still clear from + * do_debug() and we need to set it again to restore the user + * state. If we entered on the slow path, TF was already set. + */ + if (work & _TIF_SINGLESTEP) + regs->flags |= X86_EFLAGS_TF; + + if (unlikely(work & _TIF_SYSCALL_EMU)) + emulated = true; + + if ((emulated || (work & _TIF_SYSCALL_TRACE)) && + tracehook_report_syscall_entry(regs)) + return -1L; + + if (emulated) + return -1L; + #ifdef CONFIG_SECCOMP /* - * Do seccomp first -- it should minimize exposure of other - * code, and keeping seccomp fast is probably more valuable - * than the rest of this. + * Do seccomp after ptrace, to catch any tracer changes. */ if (work & _TIF_SECCOMP) { struct seccomp_data sd; @@ -129,79 +141,12 @@ unsigned long syscall_trace_enter_phase1(struct pt_regs *regs, u32 arch) sd.args[5] = regs->bp; } - BUILD_BUG_ON(SECCOMP_PHASE1_OK != 0); - BUILD_BUG_ON(SECCOMP_PHASE1_SKIP != 1); - - ret = seccomp_phase1(&sd); - if (ret == SECCOMP_PHASE1_SKIP) { - regs->orig_ax = -1; - ret = 0; - } else if (ret != SECCOMP_PHASE1_OK) { - return ret; /* Go directly to phase 2 */ - } - - work &= ~_TIF_SECCOMP; - } -#endif - - /* Do our best to finish without phase 2. */ - if (work == 0) - return ret; /* seccomp and/or nohz only (ret == 0 here) */ - -#ifdef CONFIG_AUDITSYSCALL - if (work == _TIF_SYSCALL_AUDIT) { - /* - * If there is no more work to be done except auditing, - * then audit in phase 1. Phase 2 always audits, so, if - * we audit here, then we can't go on to phase 2. - */ - do_audit_syscall_entry(regs, arch); - return 0; + ret = __secure_computing(&sd); + if (ret == -1) + return ret; } #endif - return 1; /* Something is enabled that we can't handle in phase 1 */ -} - -/* Returns the syscall nr to run (which should match regs->orig_ax). */ -long syscall_trace_enter_phase2(struct pt_regs *regs, u32 arch, - unsigned long phase1_result) -{ - struct thread_info *ti = pt_regs_to_thread_info(regs); - long ret = 0; - u32 work = ACCESS_ONCE(ti->flags) & _TIF_WORK_SYSCALL_ENTRY; - - if (IS_ENABLED(CONFIG_DEBUG_ENTRY)) - BUG_ON(regs != task_pt_regs(current)); - - /* - * If we stepped into a sysenter/syscall insn, it trapped in - * kernel mode; do_debug() cleared TF and set TIF_SINGLESTEP. - * If user-mode had set TF itself, then it's still clear from - * do_debug() and we need to set it again to restore the user - * state. If we entered on the slow path, TF was already set. - */ - if (work & _TIF_SINGLESTEP) - regs->flags |= X86_EFLAGS_TF; - -#ifdef CONFIG_SECCOMP - /* - * Call seccomp_phase2 before running the other hooks so that - * they can see any changes made by a seccomp tracer. - */ - if (phase1_result > 1 && seccomp_phase2(phase1_result)) { - /* seccomp failures shouldn't expose any additional code. */ - return -1; - } -#endif - - if (unlikely(work & _TIF_SYSCALL_EMU)) - ret = -1L; - - if ((ret || test_thread_flag(TIF_SYSCALL_TRACE)) && - tracehook_report_syscall_entry(regs)) - ret = -1L; - if (unlikely(test_thread_flag(TIF_SYSCALL_TRACEPOINT))) trace_sys_enter(regs, regs->orig_ax); @@ -210,17 +155,6 @@ long syscall_trace_enter_phase2(struct pt_regs *regs, u32 arch, return ret ?: regs->orig_ax; } -long syscall_trace_enter(struct pt_regs *regs) -{ - u32 arch = is_ia32_task() ? AUDIT_ARCH_I386 : AUDIT_ARCH_X86_64; - unsigned long phase1_result = syscall_trace_enter_phase1(regs, arch); - - if (phase1_result == 0) - return regs->orig_ax; - else - return syscall_trace_enter_phase2(regs, arch, phase1_result); -} - #define EXIT_TO_USERMODE_LOOP_FLAGS \ (_TIF_SIGPENDING | _TIF_NOTIFY_RESUME | _TIF_UPROBE | \ _TIF_NEED_RESCHED | _TIF_USER_RETURN_NOTIFY) diff --git a/arch/x86/entry/entry_64.S b/arch/x86/entry/entry_64.S index 9a66d730c78f..4ada6445bc24 100644 --- a/arch/x86/entry/entry_64.S +++ b/arch/x86/entry/entry_64.S @@ -187,12 +187,19 @@ entry_SYSCALL_64_fastpath: sbb %rcx, %rcx /* array_index_mask_nospec() */ and %rcx, %rax movq %r10, %rcx + + /* + * This call instruction is handled specially in stub_ptregs_64. + * It might end up jumping to the slow path. If it jumps, RAX is + * clobbered. + */ #ifdef CONFIG_RETPOLINE movq sys_call_table(, %rax, 8), %rax call __x86_indirect_thunk_rax #else call *sys_call_table(, %rax, 8) #endif +.Lentry_SYSCALL_64_after_fastpath_call: movq %rax, RAX(%rsp) 1: @@ -254,25 +261,13 @@ GLOBAL(int_ret_from_sys_call_irqs_off) /* Do syscall entry tracing */ tracesys: - movq %rsp, %rdi - movl $AUDIT_ARCH_X86_64, %esi - call syscall_trace_enter_phase1 - test %rax, %rax - jnz tracesys_phase2 /* if needed, run the slow path */ - RESTORE_C_REGS_EXCEPT_RAX /* else restore clobbered regs */ - movq ORIG_RAX(%rsp), %rax - jmp entry_SYSCALL_64_fastpath /* and return to the fast path */ - -tracesys_phase2: SAVE_EXTRA_REGS movq %rsp, %rdi - movl $AUDIT_ARCH_X86_64, %esi - movq %rax, %rdx - call syscall_trace_enter_phase2 + call syscall_trace_enter /* * Reload registers from stack in case ptrace changed them. - * We don't reload %rax because syscall_trace_entry_phase2() returned + * We don't reload %rax because syscall_trace_enter() returned * the value it wants us to use in the table lookup. */ RESTORE_C_REGS_EXCEPT_RAX @@ -397,6 +392,38 @@ opportunistic_sysret_failed: jmp restore_c_regs_and_iret END(entry_SYSCALL_64) +ENTRY(stub_ptregs_64) + /* + * Syscalls marked as needing ptregs land here. + * If we are on the fast path, we need to save the extra regs. + * If we are on the slow path, the extra regs are already saved. + * + * RAX stores a pointer to the C function implementing the syscall. + */ + cmpq $.Lentry_SYSCALL_64_after_fastpath_call, (%rsp) + jne 1f + + /* Called from fast path -- pop return address and jump to slow path */ + popq %rax + jmp tracesys /* called from fast path */ + +1: + /* Called from C */ + jmp *%rax /* called from C */ +END(stub_ptregs_64) + +.macro ptregs_stub func +ENTRY(ptregs_\func) + leaq \func(%rip), %rax + jmp stub_ptregs_64 +END(ptregs_\func) +.endm + +/* Instantiate ptregs_stub for each ptregs-using syscall */ +#define __SYSCALL_64_QUAL_(sym) +#define __SYSCALL_64_QUAL_ptregs(sym) ptregs_stub sym +#define __SYSCALL_64(nr, sym, qual) __SYSCALL_64_QUAL_##qual(sym) +#include <asm/syscalls_64.h> .macro FORK_LIKE func ENTRY(stub_\func) @@ -862,7 +889,7 @@ ENTRY(\sym) call \do_sym - jmp error_exit /* %ebx: no swapgs flag */ + jmp error_exit .endif END(\sym) .endm @@ -1124,7 +1151,6 @@ END(paranoid_exit) /* * Save all registers in pt_regs, and switch gs if needed. - * Return: EBX=0: came from user mode; EBX=1: otherwise */ ENTRY(error_entry) cld @@ -1137,7 +1163,6 @@ ENTRY(error_entry) * the kernel CR3 here. */ SWITCH_KERNEL_CR3 - xorl %ebx, %ebx testb $3, CS+8(%rsp) jz .Lerror_kernelspace @@ -1171,7 +1196,6 @@ ENTRY(error_entry) * for these here too. */ .Lerror_kernelspace: - incl %ebx leaq native_irq_return_iret(%rip), %rcx cmpq %rcx, RIP+8(%rsp) je .Lerror_bad_iret @@ -1202,28 +1226,19 @@ ENTRY(error_entry) /* * Pretend that the exception came from user mode: set up pt_regs - * as if we faulted immediately after IRET and clear EBX so that - * error_exit knows that we will be returning to user mode. + * as if we faulted immediately after IRET. */ mov %rsp, %rdi call fixup_bad_iret mov %rax, %rsp - decl %ebx jmp .Lerror_entry_from_usermode_after_swapgs END(error_entry) - -/* - * On entry, EBS is a "return to kernel mode" flag: - * 1: already in kernel mode, don't need SWAPGS - * 0: user gsbase is loaded, we need SWAPGS and standard preparation for return to usermode - */ ENTRY(error_exit) - movl %ebx, %eax DISABLE_INTERRUPTS(CLBR_NONE) TRACE_IRQS_OFF - testl %eax, %eax - jnz retint_kernel + testb $3, CS(%rsp) + jz retint_kernel jmp retint_user END(error_exit) diff --git a/arch/x86/entry/syscall_32.c b/arch/x86/entry/syscall_32.c index 9a6649857106..8f895ee13a1c 100644 --- a/arch/x86/entry/syscall_32.c +++ b/arch/x86/entry/syscall_32.c @@ -6,17 +6,11 @@ #include <asm/asm-offsets.h> #include <asm/syscall.h> -#ifdef CONFIG_IA32_EMULATION -#define SYM(sym, compat) compat -#else -#define SYM(sym, compat) sym -#endif - -#define __SYSCALL_I386(nr, sym, compat) extern asmlinkage long SYM(sym, compat)(unsigned long, unsigned long, unsigned long, unsigned long, unsigned long, unsigned long) ; +#define __SYSCALL_I386(nr, sym, qual) extern asmlinkage long sym(unsigned long, unsigned long, unsigned long, unsigned long, unsigned long, unsigned long) ; #include <asm/syscalls_32.h> #undef __SYSCALL_I386 -#define __SYSCALL_I386(nr, sym, compat) [nr] = SYM(sym, compat), +#define __SYSCALL_I386(nr, sym, qual) [nr] = sym, extern asmlinkage long sys_ni_syscall(unsigned long, unsigned long, unsigned long, unsigned long, unsigned long, unsigned long); diff --git a/arch/x86/entry/syscall_64.c b/arch/x86/entry/syscall_64.c index 41283d22be7a..9dbc5abb6162 100644 --- a/arch/x86/entry/syscall_64.c +++ b/arch/x86/entry/syscall_64.c @@ -6,19 +6,14 @@ #include <asm/asm-offsets.h> #include <asm/syscall.h> -#define __SYSCALL_COMMON(nr, sym, compat) __SYSCALL_64(nr, sym, compat) +#define __SYSCALL_64_QUAL_(sym) sym +#define __SYSCALL_64_QUAL_ptregs(sym) ptregs_##sym -#ifdef CONFIG_X86_X32_ABI -# define __SYSCALL_X32(nr, sym, compat) __SYSCALL_64(nr, sym, compat) -#else -# define __SYSCALL_X32(nr, sym, compat) /* nothing */ -#endif - -#define __SYSCALL_64(nr, sym, compat) extern asmlinkage long sym(unsigned long, unsigned long, unsigned long, unsigned long, unsigned long, unsigned long) ; +#define __SYSCALL_64(nr, sym, qual) extern asmlinkage long __SYSCALL_64_QUAL_##qual(sym)(unsigned long, unsigned long, unsigned long, unsigned long, unsigned long, unsigned long); #include <asm/syscalls_64.h> #undef __SYSCALL_64 -#define __SYSCALL_64(nr, sym, compat) [nr] = sym, +#define __SYSCALL_64(nr, sym, qual) [nr] = __SYSCALL_64_QUAL_##qual(sym), extern long sys_ni_syscall(unsigned long, unsigned long, unsigned long, unsigned long, unsigned long, unsigned long); diff --git a/arch/x86/entry/syscalls/syscall_64.tbl b/arch/x86/entry/syscalls/syscall_64.tbl index 314a90bfc09c..aa51cdd2a11a 100644 --- a/arch/x86/entry/syscalls/syscall_64.tbl +++ b/arch/x86/entry/syscalls/syscall_64.tbl @@ -21,7 +21,7 @@ 12 common brk sys_brk 13 64 rt_sigaction sys_rt_sigaction 14 common rt_sigprocmask sys_rt_sigprocmask -15 64 rt_sigreturn stub_rt_sigreturn +15 64 rt_sigreturn stub_rt_sigreturn/ptregs 16 64 ioctl sys_ioctl 17 common pread64 sys_pread64 18 common pwrite64 sys_pwrite64 @@ -62,10 +62,10 @@ 53 common socketpair sys_socketpair 54 64 setsockopt sys_setsockopt 55 64 getsockopt sys_getsockopt -56 common clone stub_clone -57 common fork stub_fork -58 common vfork stub_vfork -59 64 execve stub_execve +56 common clone stub_clone/ptregs +57 common fork stub_fork/ptregs +58 common vfork stub_vfork/ptregs +59 64 execve stub_execve/ptregs 60 common exit sys_exit 61 common wait4 sys_wait4 62 common kill sys_kill @@ -328,7 +328,7 @@ 319 common memfd_create sys_memfd_create 320 common kexec_file_load sys_kexec_file_load 321 common bpf sys_bpf -322 64 execveat stub_execveat +322 64 execveat stub_execveat/ptregs 323 common userfaultfd sys_userfaultfd 324 common membarrier sys_membarrier 325 common mlock2 sys_mlock2 @@ -345,7 +345,7 @@ 517 x32 recvfrom compat_sys_recvfrom 518 x32 sendmsg compat_sys_sendmsg 519 x32 recvmsg compat_sys_recvmsg -520 x32 execve stub_x32_execve +520 x32 execve stub_x32_execve/ptregs 521 x32 ptrace compat_sys_ptrace 522 x32 rt_sigpending compat_sys_rt_sigpending 523 x32 rt_sigtimedwait compat_sys_rt_sigtimedwait @@ -370,4 +370,4 @@ 542 x32 getsockopt compat_sys_getsockopt 543 x32 io_setup compat_sys_io_setup 544 x32 io_submit compat_sys_io_submit -545 x32 execveat stub_x32_execveat +545 x32 execveat stub_x32_execveat/ptregs diff --git a/arch/x86/entry/syscalls/syscalltbl.sh b/arch/x86/entry/syscalls/syscalltbl.sh index 0e7f8ec071e7..cd3d3015d7df 100644 --- a/arch/x86/entry/syscalls/syscalltbl.sh +++ b/arch/x86/entry/syscalls/syscalltbl.sh @@ -3,13 +3,63 @@ in="$1" out="$2" +syscall_macro() { + abi="$1" + nr="$2" + entry="$3" + + # Entry can be either just a function name or "function/qualifier" + real_entry="${entry%%/*}" + qualifier="${entry:${#real_entry}}" # Strip the function name + qualifier="${qualifier:1}" # Strip the slash, if any + + echo "__SYSCALL_${abi}($nr, $real_entry, $qualifier)" +} + +emit() { + abi="$1" + nr="$2" + entry="$3" + compat="$4" + + if [ "$abi" == "64" -a -n "$compat" ]; then + echo "a compat entry for a 64-bit syscall makes no sense" >&2 + exit 1 + fi + + if [ -z "$compat" ]; then + if [ -n "$entry" ]; then + syscall_macro "$abi" "$nr" "$entry" + fi + else + echo "#ifdef CONFIG_X86_32" + if [ -n "$entry" ]; then + syscall_macro "$abi" "$nr" "$entry" + fi + echo "#else" + syscall_macro "$abi" "$nr" "$compat" + echo "#endif" + fi +} + grep '^[0-9]' "$in" | sort -n | ( while read nr abi name entry compat; do abi=`echo "$abi" | tr '[a-z]' '[A-Z]'` - if [ -n "$compat" ]; then - echo "__SYSCALL_${abi}($nr, $entry, $compat)" - elif [ -n "$entry" ]; then - echo "__SYSCALL_${abi}($nr, $entry, $entry)" + if [ "$abi" == "COMMON" -o "$abi" == "64" ]; then + # COMMON is the same as 64, except that we don't expect X32 + # programs to use it. Our expectation has nothing to do with + # any generated code, so treat them the same. + emit 64 "$nr" "$entry" "$compat" + elif [ "$abi" == "X32" ]; then + # X32 is equivalent to 64 on an X32-compatible kernel. + echo "#ifdef CONFIG_X86_X32_ABI" + emit 64 "$nr" "$entry" "$compat" + echo "#endif" + elif [ "$abi" == "I386" ]; then + emit "$abi" "$nr" "$entry" "$compat" + else + echo "Unknown abi $abi" >&2 + exit 1 fi done ) > "$out" diff --git a/arch/x86/entry/vsyscall/vsyscall_64.c b/arch/x86/entry/vsyscall/vsyscall_64.c index 2d359991a273..8054f25d9b42 100644 --- a/arch/x86/entry/vsyscall/vsyscall_64.c +++ b/arch/x86/entry/vsyscall/vsyscall_64.c @@ -213,7 +213,7 @@ bool emulate_vsyscall(struct pt_regs *regs, unsigned long address) */ regs->orig_ax = syscall_nr; regs->ax = -ENOSYS; - tmp = secure_computing(); + tmp = secure_computing(NULL); if ((!tmp && regs->orig_ax != syscall_nr) || regs->ip != address) { warn_bad_vsyscall(KERN_DEBUG, regs, "seccomp tried to change syscall nr or ip"); diff --git a/arch/x86/include/asm/ptrace.h b/arch/x86/include/asm/ptrace.h index 6271281f947d..25479a144894 100644 --- a/arch/x86/include/asm/ptrace.h +++ b/arch/x86/include/asm/ptrace.h @@ -83,10 +83,6 @@ extern void send_sigtrap(struct task_struct *tsk, struct pt_regs *regs, int error_code, int si_code); -extern unsigned long syscall_trace_enter_phase1(struct pt_regs *, u32 arch); -extern long syscall_trace_enter_phase2(struct pt_regs *, u32 arch, - unsigned long phase1_result); - extern long syscall_trace_enter(struct pt_regs *); static inline unsigned long regs_return_value(struct pt_regs *regs) diff --git a/arch/x86/kernel/asm-offsets_32.c b/arch/x86/kernel/asm-offsets_32.c index 6ce39025f467..fdeb0ce07c16 100644 --- a/arch/x86/kernel/asm-offsets_32.c +++ b/arch/x86/kernel/asm-offsets_32.c @@ -7,7 +7,7 @@ #include <linux/lguest.h> #include "../../../drivers/lguest/lg.h" -#define __SYSCALL_I386(nr, sym, compat) [nr] = 1, +#define __SYSCALL_I386(nr, sym, qual) [nr] = 1, static char syscalls[] = { #include <asm/syscalls_32.h> }; diff --git a/arch/x86/kernel/asm-offsets_64.c b/arch/x86/kernel/asm-offsets_64.c index d8f42f902a0f..5de52cf589be 100644 --- a/arch/x86/kernel/asm-offsets_64.c +++ b/arch/x86/kernel/asm-offsets_64.c @@ -4,17 +4,11 @@ #include <asm/ia32.h> -#define __SYSCALL_64(nr, sym, compat) [nr] = 1, -#define __SYSCALL_COMMON(nr, sym, compat) [nr] = 1, -#ifdef CONFIG_X86_X32_ABI -# define __SYSCALL_X32(nr, sym, compat) [nr] = 1, -#else -# define __SYSCALL_X32(nr, sym, compat) /* nothing */ -#endif +#define __SYSCALL_64(nr, sym, qual) [nr] = 1, static char syscalls_64[] = { #include <asm/syscalls_64.h> }; -#define __SYSCALL_I386(nr, sym, compat) [nr] = 1, +#define __SYSCALL_I386(nr, sym, qual) [nr] = 1, static char syscalls_ia32[] = { #include <asm/syscalls_32.h> }; diff --git a/arch/x86/kvm/mmu.c b/arch/x86/kvm/mmu.c index 2b71f2c03b9e..a5b533aea958 100644 --- a/arch/x86/kvm/mmu.c +++ b/arch/x86/kvm/mmu.c @@ -4174,9 +4174,9 @@ static void mmu_pte_write_flush_tlb(struct kvm_vcpu *vcpu, bool zap_page, } static u64 mmu_pte_write_fetch_gpte(struct kvm_vcpu *vcpu, gpa_t *gpa, - const u8 *new, int *bytes) + int *bytes) { - u64 gentry; + u64 gentry = 0; int r; /* @@ -4188,22 +4188,12 @@ static u64 mmu_pte_write_fetch_gpte(struct kvm_vcpu *vcpu, gpa_t *gpa, /* Handle a 32-bit guest writing two halves of a 64-bit gpte */ *gpa &= ~(gpa_t)7; *bytes = 8; - r = kvm_vcpu_read_guest(vcpu, *gpa, &gentry, 8); - if (r) - gentry = 0; - new = (const u8 *)&gentry; } - switch (*bytes) { - case 4: - gentry = *(const u32 *)new; - break; - case 8: - gentry = *(const u64 *)new; - break; - default: - gentry = 0; - break; + if (*bytes == 4 || *bytes == 8) { + r = kvm_vcpu_read_guest_atomic(vcpu, *gpa, &gentry, *bytes); + if (r) + gentry = 0; } return gentry; @@ -4313,8 +4303,6 @@ void kvm_mmu_pte_write(struct kvm_vcpu *vcpu, gpa_t gpa, pgprintk("%s: gpa %llx bytes %d\n", __func__, gpa, bytes); - gentry = mmu_pte_write_fetch_gpte(vcpu, &gpa, new, &bytes); - /* * No need to care whether allocation memory is successful * or not since pte prefetch is skiped if it does not have @@ -4323,6 +4311,9 @@ void kvm_mmu_pte_write(struct kvm_vcpu *vcpu, gpa_t gpa, mmu_topup_memory_caches(vcpu); spin_lock(&vcpu->kvm->mmu_lock); + + gentry = mmu_pte_write_fetch_gpte(vcpu, &gpa, &bytes); + ++vcpu->kvm->stat.mmu_pte_write; kvm_mmu_audit(vcpu, AUDIT_PRE_PTE_WRITE); diff --git a/arch/x86/um/sys_call_table_32.c b/arch/x86/um/sys_call_table_32.c index 439c0994b696..bfce503dffae 100644 --- a/arch/x86/um/sys_call_table_32.c +++ b/arch/x86/um/sys_call_table_32.c @@ -25,11 +25,11 @@ #define old_mmap sys_old_mmap -#define __SYSCALL_I386(nr, sym, compat) extern asmlinkage long sym(unsigned long, unsigned long, unsigned long, unsigned long, unsigned long, unsigned long) ; +#define __SYSCALL_I386(nr, sym, qual) extern asmlinkage long sym(unsigned long, unsigned long, unsigned long, unsigned long, unsigned long, unsigned long) ; #include <asm/syscalls_32.h> #undef __SYSCALL_I386 -#define __SYSCALL_I386(nr, sym, compat) [ nr ] = sym, +#define __SYSCALL_I386(nr, sym, qual) [ nr ] = sym, extern asmlinkage long sys_ni_syscall(unsigned long, unsigned long, unsigned long, unsigned long, unsigned long, unsigned long); diff --git a/arch/x86/um/sys_call_table_64.c b/arch/x86/um/sys_call_table_64.c index b74ea6c2c0e7..f306413d3eb6 100644 --- a/arch/x86/um/sys_call_table_64.c +++ b/arch/x86/um/sys_call_table_64.c @@ -35,14 +35,11 @@ #define stub_execveat sys_execveat #define stub_rt_sigreturn sys_rt_sigreturn -#define __SYSCALL_COMMON(nr, sym, compat) __SYSCALL_64(nr, sym, compat) -#define __SYSCALL_X32(nr, sym, compat) /* Not supported */ - -#define __SYSCALL_64(nr, sym, compat) extern asmlinkage long sym(unsigned long, unsigned long, unsigned long, unsigned long, unsigned long, unsigned long) ; +#define __SYSCALL_64(nr, sym, qual) extern asmlinkage long sym(unsigned long, unsigned long, unsigned long, unsigned long, unsigned long, unsigned long) ; #include <asm/syscalls_64.h> #undef __SYSCALL_64 -#define __SYSCALL_64(nr, sym, compat) [ nr ] = sym, +#define __SYSCALL_64(nr, sym, qual) [ nr ] = sym, extern asmlinkage long sys_ni_syscall(unsigned long, unsigned long, unsigned long, unsigned long, unsigned long, unsigned long); diff --git a/arch/x86/um/user-offsets.c b/arch/x86/um/user-offsets.c index ce7e3607a870..470564bbd08e 100644 --- a/arch/x86/um/user-offsets.c +++ b/arch/x86/um/user-offsets.c @@ -9,14 +9,12 @@ #include <asm/types.h> #ifdef __i386__ -#define __SYSCALL_I386(nr, sym, compat) [nr] = 1, +#define __SYSCALL_I386(nr, sym, qual) [nr] = 1, static char syscalls[] = { #include <asm/syscalls_32.h> }; #else -#define __SYSCALL_64(nr, sym, compat) [nr] = 1, -#define __SYSCALL_COMMON(nr, sym, compat) [nr] = 1, -#define __SYSCALL_X32(nr, sym, compat) /* Not supported */ +#define __SYSCALL_64(nr, sym, qual) [nr] = 1, static char syscalls[] = { #include <asm/syscalls_64.h> }; diff --git a/arch/xtensa/kernel/asm-offsets.c b/arch/xtensa/kernel/asm-offsets.c index b123ace3b67c..cbefed1800c1 100644 --- a/arch/xtensa/kernel/asm-offsets.c +++ b/arch/xtensa/kernel/asm-offsets.c @@ -90,14 +90,14 @@ int main(void) DEFINE(THREAD_SP, offsetof (struct task_struct, thread.sp)); DEFINE(THREAD_CPENABLE, offsetof (struct thread_info, cpenable)); #if XTENSA_HAVE_COPROCESSORS - DEFINE(THREAD_XTREGS_CP0, offsetof (struct thread_info, xtregs_cp)); - DEFINE(THREAD_XTREGS_CP1, offsetof (struct thread_info, xtregs_cp)); - DEFINE(THREAD_XTREGS_CP2, offsetof (struct thread_info, xtregs_cp)); - DEFINE(THREAD_XTREGS_CP3, offsetof (struct thread_info, xtregs_cp)); - DEFINE(THREAD_XTREGS_CP4, offsetof (struct thread_info, xtregs_cp)); - DEFINE(THREAD_XTREGS_CP5, offsetof (struct thread_info, xtregs_cp)); - DEFINE(THREAD_XTREGS_CP6, offsetof (struct thread_info, xtregs_cp)); - DEFINE(THREAD_XTREGS_CP7, offsetof (struct thread_info, xtregs_cp)); + DEFINE(THREAD_XTREGS_CP0, offsetof(struct thread_info, xtregs_cp.cp0)); + DEFINE(THREAD_XTREGS_CP1, offsetof(struct thread_info, xtregs_cp.cp1)); + DEFINE(THREAD_XTREGS_CP2, offsetof(struct thread_info, xtregs_cp.cp2)); + DEFINE(THREAD_XTREGS_CP3, offsetof(struct thread_info, xtregs_cp.cp3)); + DEFINE(THREAD_XTREGS_CP4, offsetof(struct thread_info, xtregs_cp.cp4)); + DEFINE(THREAD_XTREGS_CP5, offsetof(struct thread_info, xtregs_cp.cp5)); + DEFINE(THREAD_XTREGS_CP6, offsetof(struct thread_info, xtregs_cp.cp6)); + DEFINE(THREAD_XTREGS_CP7, offsetof(struct thread_info, xtregs_cp.cp7)); #endif DEFINE(THREAD_XTREGS_USER, offsetof (struct thread_info, xtregs_user)); DEFINE(XTREGS_USER_SIZE, sizeof(xtregs_user_t)); diff --git a/arch/xtensa/kernel/process.c b/arch/xtensa/kernel/process.c index 17a378c15a15..26516094dbd4 100644 --- a/arch/xtensa/kernel/process.c +++ b/arch/xtensa/kernel/process.c @@ -83,18 +83,21 @@ void coprocessor_release_all(struct thread_info *ti) void coprocessor_flush_all(struct thread_info *ti) { - unsigned long cpenable; + unsigned long cpenable, old_cpenable; int i; preempt_disable(); + RSR_CPENABLE(old_cpenable); cpenable = ti->cpenable; + WSR_CPENABLE(cpenable); for (i = 0; i < XCHAL_CP_MAX; i++) { if ((cpenable & 1) != 0 && coprocessor_owner[i] == ti) coprocessor_flush(ti, i); cpenable >>= 1; } + WSR_CPENABLE(old_cpenable); preempt_enable(); } diff --git a/build.config.cuttlefish.aarch64 b/build.config.cuttlefish.aarch64 new file mode 100644 index 000000000000..e36bae42443e --- /dev/null +++ b/build.config.cuttlefish.aarch64 @@ -0,0 +1,16 @@ +ARCH=arm64 +BRANCH=android-4.4 +CLANG_TRIPLE=aarch64-linux-gnu- +CROSS_COMPILE=aarch64-linux-androidkernel- +DEFCONFIG=cuttlefish_defconfig +EXTRA_CMDS='' +KERNEL_DIR=common +POST_DEFCONFIG_CMDS="check_defconfig" +CLANG_PREBUILT_BIN=prebuilts-master/clang/host/linux-x86/clang-r346389b/bin +LINUX_GCC_CROSS_COMPILE_PREBUILTS_BIN=prebuilts/gcc/linux-x86/aarch64/aarch64-linux-android-4.9/bin +FILES=" +arch/arm64/boot/Image.gz +vmlinux +System.map +" +STOP_SHIP_TRACEPRINTK=1 diff --git a/build.config.cuttlefish.x86_64 b/build.config.cuttlefish.x86_64 index ce8c226a1db4..0a77fa871e83 100644 --- a/build.config.cuttlefish.x86_64 +++ b/build.config.cuttlefish.x86_64 @@ -6,7 +6,7 @@ DEFCONFIG=x86_64_cuttlefish_defconfig EXTRA_CMDS='' KERNEL_DIR=common POST_DEFCONFIG_CMDS="check_defconfig" -CLANG_PREBUILT_BIN=prebuilts-master/clang/host/linux-x86/clang-r328903/bin +CLANG_PREBUILT_BIN=prebuilts-master/clang/host/linux-x86/clang-r346389b/bin LINUX_GCC_CROSS_COMPILE_PREBUILTS_BIN=prebuilts/gcc/linux-x86/x86/x86_64-linux-android-4.9/bin FILES=" arch/x86/boot/bzImage diff --git a/drivers/android/binder.c b/drivers/android/binder.c index 644b9abcc67f..f22e4abba9b4 100644 --- a/drivers/android/binder.c +++ b/drivers/android/binder.c @@ -3138,7 +3138,6 @@ static void binder_transaction(struct binder_proc *proc, t->buffer = NULL; goto err_binder_alloc_buf_failed; } - t->buffer->allow_user_free = 0; t->buffer->debug_id = t->debug_id; t->buffer->transaction = t; t->buffer->target_node = target_node; @@ -3634,14 +3633,18 @@ static int binder_thread_write(struct binder_proc *proc, buffer = binder_alloc_prepare_to_free(&proc->alloc, data_ptr); - if (buffer == NULL) { - binder_user_error("%d:%d BC_FREE_BUFFER u%016llx no match\n", - proc->pid, thread->pid, (u64)data_ptr); - break; - } - if (!buffer->allow_user_free) { - binder_user_error("%d:%d BC_FREE_BUFFER u%016llx matched unreturned buffer\n", - proc->pid, thread->pid, (u64)data_ptr); + if (IS_ERR_OR_NULL(buffer)) { + if (PTR_ERR(buffer) == -EPERM) { + binder_user_error( + "%d:%d BC_FREE_BUFFER u%016llx matched unreturned or currently freeing buffer\n", + proc->pid, thread->pid, + (u64)data_ptr); + } else { + binder_user_error( + "%d:%d BC_FREE_BUFFER u%016llx no match\n", + proc->pid, thread->pid, + (u64)data_ptr); + } break; } binder_debug(BINDER_DEBUG_FREE_BUFFER, diff --git a/drivers/android/binder_alloc.c b/drivers/android/binder_alloc.c index 1d9db2ef26bd..baecb4bf9d9b 100644 --- a/drivers/android/binder_alloc.c +++ b/drivers/android/binder_alloc.c @@ -149,14 +149,12 @@ static struct binder_buffer *binder_alloc_prepare_to_free_locked( else { /* * Guard against user threads attempting to - * free the buffer twice + * free the buffer when in use by kernel or + * after it's already been freed. */ - if (buffer->free_in_progress) { - pr_err("%d:%d FREE_BUFFER u%016llx user freed buffer twice\n", - alloc->pid, current->pid, (u64)user_ptr); - return NULL; - } - buffer->free_in_progress = 1; + if (!buffer->allow_user_free) + return ERR_PTR(-EPERM); + buffer->allow_user_free = 0; return buffer; } } @@ -463,7 +461,7 @@ static struct binder_buffer *binder_alloc_new_buf_locked( rb_erase(best_fit, &alloc->free_buffers); buffer->free = 0; - buffer->free_in_progress = 0; + buffer->allow_user_free = 0; binder_insert_allocated_buffer_locked(alloc, buffer); binder_alloc_debug(BINDER_DEBUG_BUFFER_ALLOC, "%d: binder_alloc_buf size %zd got %pK\n", diff --git a/drivers/android/binder_alloc.h b/drivers/android/binder_alloc.h index 9ef64e563856..fb3238c74c8a 100644 --- a/drivers/android/binder_alloc.h +++ b/drivers/android/binder_alloc.h @@ -50,8 +50,7 @@ struct binder_buffer { unsigned free:1; unsigned allow_user_free:1; unsigned async_transaction:1; - unsigned free_in_progress:1; - unsigned debug_id:28; + unsigned debug_id:29; struct binder_transaction *transaction; diff --git a/drivers/char/adsprpc.c b/drivers/char/adsprpc.c index 24513e5d1e1e..3da8f64444a3 100644 --- a/drivers/char/adsprpc.c +++ b/drivers/char/adsprpc.c @@ -55,6 +55,8 @@ #define TZ_PIL_AUTH_QDSP6_PROC 1 #define ADSP_MMAP_HEAP_ADDR 4 #define ADSP_MMAP_REMOTE_HEAP_ADDR 8 +#define ADSP_MMAP_ADD_PAGES 0x1000 + #define FASTRPC_ENOSUCH 39 #define VMID_SSC_Q6 38 #define VMID_ADSP_Q6 6 @@ -126,6 +128,7 @@ static inline uint64_t buf_num_pages(uint64_t buf, size_t len) static inline uint64_t buf_page_size(uint32_t size) { uint64_t sz = (size + (PAGE_SIZE - 1)) & PAGE_MASK; + return sz > PAGE_SIZE ? sz : PAGE_SIZE; } @@ -145,10 +148,15 @@ struct fastrpc_file; struct fastrpc_buf { struct hlist_node hn; + struct hlist_node hn_rem; struct fastrpc_file *fl; void *virt; uint64_t phys; size_t size; + struct dma_attrs attrs; + uintptr_t raddr; + uint32_t flags; + int remote; }; struct fastrpc_ctx_lst; @@ -292,9 +300,11 @@ struct fastrpc_file { struct hlist_node hn; spinlock_t hlock; struct hlist_head maps; - struct hlist_head bufs; + struct hlist_head cached_bufs; + struct hlist_head remote_bufs; struct fastrpc_ctx_lst clst; struct fastrpc_session_ctx *sctx; + struct fastrpc_buf *init_mem; struct fastrpc_session_ctx *secsctx; uint32_t mode; uint32_t profile; @@ -363,10 +373,17 @@ static void fastrpc_buf_free(struct fastrpc_buf *buf, int cache) return; if (cache) { spin_lock(&fl->hlock); - hlist_add_head(&buf->hn, &fl->bufs); + hlist_add_head(&buf->hn, &fl->cached_bufs); spin_unlock(&fl->hlock); return; } + if (buf->remote) { + spin_lock(&fl->hlock); + hlist_del_init(&buf->hn_rem); + spin_unlock(&fl->hlock); + buf->remote = 0; + buf->raddr = 0; + } if (!IS_ERR_OR_NULL(buf->virt)) { int destVM[1] = {VMID_HLOS}; int destVMperm[1] = {PERM_READ | PERM_WRITE | PERM_EXEC}; @@ -380,21 +397,22 @@ static void fastrpc_buf_free(struct fastrpc_buf *buf, int cache) hyp_assign_phys(buf->phys, buf_page_size(buf->size), srcVM, 2, destVM, destVMperm, 1); } - dma_free_coherent(fl->sctx->smmu.dev, buf->size, buf->virt, - buf->phys); + dma_free_attrs(fl->sctx->smmu.dev, buf->size, buf->virt, + buf->phys, (struct dma_attrs *)&buf->attrs); } kfree(buf); } -static void fastrpc_buf_list_free(struct fastrpc_file *fl) +static void fastrpc_cached_buf_list_free(struct fastrpc_file *fl) { struct fastrpc_buf *buf, *free; + do { struct hlist_node *n; free = NULL; spin_lock(&fl->hlock); - hlist_for_each_entry_safe(buf, n, &fl->bufs, hn) { + hlist_for_each_entry_safe(buf, n, &fl->cached_bufs, hn) { hlist_del_init(&buf->hn); free = buf; break; @@ -405,6 +423,25 @@ static void fastrpc_buf_list_free(struct fastrpc_file *fl) } while (free); } +static void fastrpc_remote_buf_list_free(struct fastrpc_file *fl) +{ + struct fastrpc_buf *buf, *free; + + do { + struct hlist_node *n; + + free = NULL; + spin_lock(&fl->hlock); + hlist_for_each_entry_safe(buf, n, &fl->remote_bufs, hn_rem) { + free = buf; + break; + } + spin_unlock(&fl->hlock); + if (free) + fastrpc_buf_free(free, 0); + } while (free); +} + static void fastrpc_mmap_add(struct fastrpc_mmap *map) { if (map->flags == ADSP_MMAP_HEAP_ADDR || @@ -465,23 +502,21 @@ static int fastrpc_mmap_find(struct fastrpc_file *fl, int fd, uintptr_t va, return -ENOTTY; } -static int dma_alloc_memory(phys_addr_t *region_start, size_t size) +static int dma_alloc_memory(dma_addr_t *region_start, void **vaddr, size_t size, + struct dma_attrs *attrs) { struct fastrpc_apps *me = &gfa; - void *vaddr = NULL; - DEFINE_DMA_ATTRS(attrs); if (me->dev == NULL) { pr_err("device adsprpc-mem is not initialized\n"); return -ENODEV; } - dma_set_attr(DMA_ATTR_SKIP_ZEROING, &attrs); - dma_set_attr(DMA_ATTR_NO_KERNEL_MAPPING, &attrs); - vaddr = dma_alloc_attrs(me->dev, size, region_start, GFP_KERNEL, - &attrs); - if (!vaddr) { - pr_err("ADSPRPC: Failed to allocate %x remote heap memory\n", - (unsigned int)size); + + *vaddr = dma_alloc_attrs(me->dev, size, region_start, + GFP_KERNEL, attrs); + if (IS_ERR_OR_NULL(*vaddr)) { + pr_err("adsprpc: %s: %s: dma_alloc_attrs failed for size 0x%zx, returned %pK\n", + current->comm, __func__, size, (*vaddr)); return -ENOMEM; } return 0; @@ -617,7 +652,8 @@ static int fastrpc_mmap_create(struct fastrpc_file *fl, int fd, unsigned attr, struct fastrpc_channel_ctx *chan = &apps->channel[cid]; struct fastrpc_mmap *map = NULL; struct dma_attrs attrs; - phys_addr_t region_start = 0; + dma_addr_t region_start = 0; + void *region_vaddr = NULL; unsigned long flags; int err = 0, vmid; @@ -635,14 +671,20 @@ static int fastrpc_mmap_create(struct fastrpc_file *fl, int fd, unsigned attr, map->attr = attr; if (mflags == ADSP_MMAP_HEAP_ADDR || mflags == ADSP_MMAP_REMOTE_HEAP_ADDR) { + DEFINE_DMA_ATTRS(rh_attrs); + + dma_set_attr(DMA_ATTR_SKIP_ZEROING, &rh_attrs); + dma_set_attr(DMA_ATTR_NO_KERNEL_MAPPING, &rh_attrs); + map->apps = me; map->fl = NULL; - VERIFY(err, !dma_alloc_memory(®ion_start, len)); + VERIFY(err, !dma_alloc_memory(®ion_start, + ®ion_vaddr, len, &rh_attrs)); if (err) goto bail; map->phys = (uintptr_t)region_start; map->size = len; - map->va = (uintptr_t)map->phys; + map->va = (uintptr_t)region_vaddr; } else { VERIFY(err, !IS_ERR_OR_NULL(map->handle = ion_import_dma_buf(fl->apps->client, fd))); @@ -741,7 +783,8 @@ bail: } static int fastrpc_buf_alloc(struct fastrpc_file *fl, size_t size, - struct fastrpc_buf **obuf) + struct dma_attrs attr, uint32_t rflags, + int remote, struct fastrpc_buf **obuf) { int err = 0, vmid; struct fastrpc_buf *buf = NULL, *fr = NULL; @@ -751,18 +794,20 @@ static int fastrpc_buf_alloc(struct fastrpc_file *fl, size_t size, if (err) goto bail; - /* find the smallest buffer that fits in the cache */ - spin_lock(&fl->hlock); - hlist_for_each_entry_safe(buf, n, &fl->bufs, hn) { - if (buf->size >= size && (!fr || fr->size > buf->size)) - fr = buf; - } - if (fr) - hlist_del_init(&fr->hn); - spin_unlock(&fl->hlock); - if (fr) { - *obuf = fr; - return 0; + if (!remote) { + /* find the smallest buffer that fits in the cache */ + spin_lock(&fl->hlock); + hlist_for_each_entry_safe(buf, n, &fl->cached_bufs, hn) { + if (buf->size >= size && (!fr || fr->size > buf->size)) + fr = buf; + } + if (fr) + hlist_del_init(&fr->hn); + spin_unlock(&fl->hlock); + if (fr) { + *obuf = fr; + return 0; + } } buf = NULL; VERIFY(err, NULL != (buf = kzalloc(sizeof(*buf), GFP_KERNEL))); @@ -773,17 +818,29 @@ static int fastrpc_buf_alloc(struct fastrpc_file *fl, size_t size, buf->virt = NULL; buf->phys = 0; buf->size = size; - buf->virt = dma_alloc_coherent(fl->sctx->smmu.dev, buf->size, - (void *)&buf->phys, GFP_KERNEL); + memcpy(&buf->attrs, &attr, sizeof(struct dma_attrs)); + buf->flags = rflags; + buf->raddr = 0; + buf->remote = 0; + buf->virt = dma_alloc_attrs(fl->sctx->smmu.dev, buf->size, + (dma_addr_t *)&buf->phys, + GFP_KERNEL, + (struct dma_attrs *)&buf->attrs); if (IS_ERR_OR_NULL(buf->virt)) { /* free cache and retry */ - fastrpc_buf_list_free(fl); - buf->virt = dma_alloc_coherent(fl->sctx->smmu.dev, buf->size, - (void *)&buf->phys, GFP_KERNEL); + fastrpc_cached_buf_list_free(fl); + buf->virt = dma_alloc_attrs(fl->sctx->smmu.dev, buf->size, + (dma_addr_t *)&buf->phys, + GFP_KERNEL, + (struct dma_attrs *)&buf->attrs); VERIFY(err, !IS_ERR_OR_NULL(buf->virt)); } - if (err) + if (err) { + err = -ENOMEM; + pr_err("adsprpc: %s: %s: dma_alloc_attrs failed for size 0x%zx\n", + current->comm, __func__, size); goto bail; + } if (fl->sctx->smmu.cb) buf->phys += ((uint64_t)fl->sctx->smmu.cb << 32); vmid = fl->apps->channel[fl->cid].vmid; @@ -799,6 +856,13 @@ static int fastrpc_buf_alloc(struct fastrpc_file *fl, size_t size, goto bail; } + if (remote) { + INIT_HLIST_NODE(&buf->hn_rem); + spin_lock(&fl->hlock); + hlist_add_head(&buf->hn_rem, &fl->remote_bufs); + spin_unlock(&fl->hlock); + buf->remote = remote; + } *obuf = buf; bail: if (err && buf) @@ -806,7 +870,6 @@ static int fastrpc_buf_alloc(struct fastrpc_file *fl, size_t size, return err; } - static int context_restore_interrupted(struct fastrpc_file *fl, struct fastrpc_ioctl_invoke_attrs *inv, struct smq_invoke_ctx **po) @@ -815,6 +878,7 @@ static int context_restore_interrupted(struct fastrpc_file *fl, struct smq_invoke_ctx *ctx = NULL, *ictx = NULL; struct hlist_node *n; struct fastrpc_ioctl_invoke *invoke = &inv->inv; + spin_lock(&fl->hlock); hlist_for_each_entry_safe(ictx, n, &fl->clst.interrupted, hn) { if (ictx->pid == current->pid) { @@ -854,6 +918,7 @@ static int context_build_overlap(struct smq_invoke_ctx *ctx) int outbufs = REMOTE_SCALARS_OUTBUFS(ctx->sc); int nbufs = inbufs + outbufs; struct overlap max; + for (i = 0; i < nbufs; ++i) { ctx->overs[i].start = (uintptr_t)lpra[i].buf.pv; ctx->overs[i].end = ctx->overs[i].start + lpra[i].buf.len; @@ -1003,12 +1068,13 @@ bail: static void context_save_interrupted(struct smq_invoke_ctx *ctx) { struct fastrpc_ctx_lst *clst = &ctx->fl->clst; + spin_lock(&ctx->fl->hlock); hlist_del_init(&ctx->hn); hlist_add_head(&ctx->hn, &clst->interrupted); spin_unlock(&ctx->fl->hlock); /* free the cache on power collapse */ - fastrpc_buf_list_free(ctx->fl); + fastrpc_cached_buf_list_free(ctx->fl); } static void context_free(struct smq_invoke_ctx *ctx) @@ -1044,11 +1110,11 @@ static void context_notify_user(struct smq_invoke_ctx *ctx, int retval) complete(&ctx->work); } - static void fastrpc_notify_users(struct fastrpc_file *me) { struct smq_invoke_ctx *ictx; struct hlist_node *n; + spin_lock(&me->hlock); hlist_for_each_entry_safe(ictx, n, &me->clst.pending, hn) { complete(&ictx->work); @@ -1064,6 +1130,7 @@ static void fastrpc_notify_drivers(struct fastrpc_apps *me, int cid) { struct fastrpc_file *fl; struct hlist_node *n; + spin_lock(&me->hlock); hlist_for_each_entry_safe(fl, n, &me->drivers, hn) { if (fl->cid == cid) @@ -1072,6 +1139,7 @@ static void fastrpc_notify_drivers(struct fastrpc_apps *me, int cid) spin_unlock(&me->hlock); } + static void context_list_ctor(struct fastrpc_ctx_lst *me) { INIT_HLIST_HEAD(&me->interrupted); @@ -1083,6 +1151,7 @@ static void fastrpc_context_list_dtor(struct fastrpc_file *fl) struct fastrpc_ctx_lst *clst = &fl->clst; struct smq_invoke_ctx *ictx = NULL, *ctxfree; struct hlist_node *n; + do { ctxfree = NULL; spin_lock(&fl->hlock); @@ -1110,10 +1179,12 @@ static void fastrpc_context_list_dtor(struct fastrpc_file *fl) } static int fastrpc_file_free(struct fastrpc_file *fl); + static void fastrpc_file_list_dtor(struct fastrpc_apps *me) { struct fastrpc_file *fl, *free; struct hlist_node *n; + do { free = NULL; spin_lock(&me->hlock); @@ -1187,7 +1258,10 @@ static int get_args(uint32_t kernel, struct smq_invoke_ctx *ctx) /* allocate new buffer */ if (copylen) { - VERIFY(err, !fastrpc_buf_alloc(ctx->fl, copylen, &ctx->buf)); + DEFINE_DMA_ATTRS(ctx_attrs); + + err = fastrpc_buf_alloc(ctx->fl, copylen, ctx_attrs, + 0, 0, &ctx->buf); if (err) goto bail; } @@ -1206,6 +1280,7 @@ static int get_args(uint32_t kernel, struct smq_invoke_ctx *ctx) args = (uintptr_t)ctx->buf->virt + metalen; for (i = 0; i < bufs; ++i) { size_t len = lpra[i].buf.len; + list[i].num = 0; list[i].pgidx = 0; if (!len) @@ -1220,6 +1295,7 @@ static int get_args(uint32_t kernel, struct smq_invoke_ctx *ctx) struct fastrpc_mmap *map = ctx->maps[i]; uint64_t buf = ptr_to_uint64(lpra[i].buf.pv); size_t len = lpra[i].buf.len; + rpra[i].buf.pv = 0; rpra[i].buf.len = len; if (!len) @@ -1561,6 +1637,7 @@ static void smd_event_handler(void *priv, unsigned event) static void fastrpc_init(struct fastrpc_apps *me) { int i; + INIT_HLIST_HEAD(&me->drivers); INIT_HLIST_HEAD(&me->maps); spin_lock_init(&me->hlock); @@ -1684,6 +1761,7 @@ static int fastrpc_init_process(struct fastrpc_file *fl, struct fastrpc_ioctl_init *init = &uproc->init; struct smq_phy_page pages[1]; struct fastrpc_mmap *file = NULL, *mem = NULL; + struct fastrpc_buf *imem = NULL; char *proc_name = NULL; int srcVM[1] = {VMID_HLOS}; int destVM[1] = {gcinfo[0].heap_vmid}; @@ -1696,6 +1774,7 @@ static int fastrpc_init_process(struct fastrpc_file *fl, if (init->flags == FASTRPC_INIT_ATTACH) { remote_arg_t ra[1]; int tgid = current->tgid; + ra[0].buf.pv = (void *)&tgid; ra[0].buf.len = sizeof(tgid); ioctl.inv.handle = 1; @@ -1712,6 +1791,8 @@ static int fastrpc_init_process(struct fastrpc_file *fl, remote_arg_t ra[6]; int fds[6]; int mflags = 0; + int memlen; + DEFINE_DMA_ATTRS(imem_dma_attr); struct { int pgid; unsigned int namelen; @@ -1734,14 +1815,27 @@ static int fastrpc_init_process(struct fastrpc_file *fl, if (err) goto bail; } - if (!access_ok(1, (void const __user *)init->mem, - init->memlen)) - goto bail; inbuf.pageslen = 1; - VERIFY(err, !fastrpc_mmap_create(fl, init->memfd, 0, - init->mem, init->memlen, mflags, &mem)); + + VERIFY(err, !init->mem); + if (err) { + err = -EINVAL; + pr_err("adsprpc: %s: %s: ERROR: donated memory allocated in userspace\n", + current->comm, __func__); + goto bail; + } + memlen = ALIGN(max(1024*1024*3, (int)init->filelen * 4), + 1024*1024); + + dma_set_attr(DMA_ATTR_EXEC_MAPPING, &imem_dma_attr); + dma_set_attr(DMA_ATTR_NO_KERNEL_MAPPING, &imem_dma_attr); + dma_set_attr(DMA_ATTR_FORCE_NON_COHERENT, &imem_dma_attr); + + err = fastrpc_buf_alloc(fl, memlen, imem_dma_attr, 0, 0, &imem); if (err) goto bail; + fl->init_mem = imem; + inbuf.pageslen = 1; ra[0].buf.pv = (void *)&inbuf; ra[0].buf.len = sizeof(inbuf); @@ -1755,8 +1849,8 @@ static int fastrpc_init_process(struct fastrpc_file *fl, ra[2].buf.len = inbuf.filelen; fds[2] = init->filefd; - pages[0].addr = mem->phys; - pages[0].size = mem->size; + pages[0].addr = imem->phys; + pages[0].size = imem->size; ra[3].buf.pv = (void *)pages; ra[3].buf.len = 1 * sizeof(*pages); fds[3] = 0; @@ -1896,7 +1990,8 @@ bail: } static int fastrpc_mmap_on_dsp(struct fastrpc_file *fl, uint32_t flags, - struct fastrpc_mmap *map) + uintptr_t va, uint64_t phys, + size_t size, uintptr_t *raddr) { struct fastrpc_ioctl_invoke_attrs ioctl; struct smq_phy_page page; @@ -1913,14 +2008,15 @@ static int fastrpc_mmap_on_dsp(struct fastrpc_file *fl, uint32_t flags, struct { uintptr_t vaddrout; } routargs; + inargs.pid = current->tgid; - inargs.vaddrin = (uintptr_t)map->va; + inargs.vaddrin = (uintptr_t)va; inargs.flags = flags; inargs.num = fl->apps->compat ? num * sizeof(page) : num; ra[0].buf.pv = (void *)&inargs; ra[0].buf.len = sizeof(inargs); - page.addr = map->phys; - page.size = map->size; + page.addr = phys; + page.size = size; ra[1].buf.pv = (void *)&page; ra[1].buf.len = num * sizeof(page); @@ -1937,15 +2033,15 @@ static int fastrpc_mmap_on_dsp(struct fastrpc_file *fl, uint32_t flags, ioctl.attrs = NULL; VERIFY(err, 0 == (err = fastrpc_internal_invoke(fl, FASTRPC_MODE_PARALLEL, 1, &ioctl))); - map->raddr = (uintptr_t)routargs.vaddrout; + *raddr = (uintptr_t)routargs.vaddrout; if (err) goto bail; if (flags == ADSP_MMAP_HEAP_ADDR) { struct scm_desc desc = {0}; desc.args[0] = TZ_PIL_AUTH_QDSP6_PROC; - desc.args[1] = map->phys; - desc.args[2] = map->size; + desc.args[1] = phys; + desc.args[2] = size; desc.arginfo = SCM_ARGS(3); err = scm_call2(SCM_SIP_FNID(SCM_SVC_PIL, TZ_PIL_PROTECT_MEM_SUBSYS_ID), &desc); @@ -1955,7 +2051,7 @@ static int fastrpc_mmap_on_dsp(struct fastrpc_file *fl, uint32_t flags, int destVM[1] = {gcinfo[0].heap_vmid}; int destVMperm[1] = {PERM_READ | PERM_WRITE | PERM_EXEC}; - VERIFY(err, !hyp_assign_phys(map->phys, (uint64_t)map->size, + VERIFY(err, !hyp_assign_phys(phys, (uint64_t)size, srcVM, 1, destVM, destVMperm, 1)); if (err) goto bail; @@ -1964,16 +2060,17 @@ bail: return err; } -static int fastrpc_munmap_on_dsp_rh(struct fastrpc_file *fl, - struct fastrpc_mmap *map) +static int fastrpc_munmap_on_dsp_rh(struct fastrpc_file *fl, uint64_t phys, + size_t size, uint32_t flags) { int err = 0; int srcVM[1] = {gcinfo[0].heap_vmid}; int destVM[1] = {VMID_HLOS}; int destVMperm[1] = {PERM_READ | PERM_WRITE | PERM_EXEC}; - if (map->flags == ADSP_MMAP_HEAP_ADDR) { + if (flags == ADSP_MMAP_HEAP_ADDR) { struct fastrpc_ioctl_invoke_attrs ioctl; + struct scm_desc desc = {0}; remote_arg_t ra[1]; int err = 0; @@ -1997,14 +2094,14 @@ static int fastrpc_munmap_on_dsp_rh(struct fastrpc_file *fl, if (err) goto bail; desc.args[0] = TZ_PIL_AUTH_QDSP6_PROC; - desc.args[1] = map->phys; - desc.args[2] = map->size; + desc.args[1] = phys; + desc.args[2] = size; desc.args[3] = routargs.skey; desc.arginfo = SCM_ARGS(4); err = scm_call2(SCM_SIP_FNID(SCM_SVC_PIL, TZ_PIL_CLEAR_PROTECT_MEM_SUBSYS_ID), &desc); - } else if (map->flags == ADSP_MMAP_REMOTE_HEAP_ADDR) { - VERIFY(err, !hyp_assign_phys(map->phys, (uint64_t)map->size, + } else if (flags == ADSP_MMAP_REMOTE_HEAP_ADDR) { + VERIFY(err, !hyp_assign_phys(phys, (uint64_t)size, srcVM, 1, destVM, destVMperm, 1)); if (err) goto bail; @@ -2014,8 +2111,8 @@ bail: return err; } -static int fastrpc_munmap_on_dsp(struct fastrpc_file *fl, - struct fastrpc_mmap *map) +static int fastrpc_munmap_on_dsp(struct fastrpc_file *fl, uintptr_t raddr, + uint64_t phys, size_t size, uint32_t flags) { struct fastrpc_ioctl_invoke_attrs ioctl; remote_arg_t ra[1]; @@ -2027,8 +2124,8 @@ static int fastrpc_munmap_on_dsp(struct fastrpc_file *fl, } inargs; inargs.pid = current->tgid; - inargs.size = map->size; - inargs.vaddrout = map->raddr; + inargs.size = size; + inargs.vaddrout = raddr; ra[0].buf.pv = (void *)&inargs; ra[0].buf.len = sizeof(inargs); @@ -2044,9 +2141,9 @@ static int fastrpc_munmap_on_dsp(struct fastrpc_file *fl, FASTRPC_MODE_PARALLEL, 1, &ioctl))); if (err) goto bail; - if (map->flags == ADSP_MMAP_HEAP_ADDR || - map->flags == ADSP_MMAP_REMOTE_HEAP_ADDR) { - VERIFY(err, !fastrpc_munmap_on_dsp_rh(fl, map)); + if (flags == ADSP_MMAP_HEAP_ADDR || + flags == ADSP_MMAP_REMOTE_HEAP_ADDR) { + VERIFY(err, !fastrpc_munmap_on_dsp_rh(fl, phys, size, flags)); if (err) goto bail; } @@ -2073,7 +2170,8 @@ static int fastrpc_mmap_remove_ssr(struct fastrpc_file *fl) spin_unlock(&me->hlock); if (match) { - VERIFY(err, !fastrpc_munmap_on_dsp_rh(fl, match)); + VERIFY(err, !fastrpc_munmap_on_dsp_rh(fl, match->phys, + match->size, match->flags)); if (err) goto bail; if (me->channel[0].ramdumpenabled) { @@ -2110,12 +2208,37 @@ static int fastrpc_internal_munmap(struct fastrpc_file *fl, { int err = 0; struct fastrpc_mmap *map = NULL; + struct fastrpc_buf *rbuf = NULL, *free = NULL; + struct hlist_node *n; mutex_lock(&fl->map_mutex); + spin_lock(&fl->hlock); + hlist_for_each_entry_safe(rbuf, n, &fl->remote_bufs, hn_rem) { + if (rbuf->raddr && (rbuf->flags == ADSP_MMAP_ADD_PAGES)) { + if ((rbuf->raddr == ud->vaddrout) && + (rbuf->size == ud->size)) { + free = rbuf; + break; + } + } + } + spin_unlock(&fl->hlock); + + if (free) { + VERIFY(err, !fastrpc_munmap_on_dsp(fl, free->raddr, + free->phys, free->size, free->flags)); + if (err) + goto bail; + fastrpc_buf_free(rbuf, 0); + mutex_unlock(&fl->map_mutex); + return err; + } + VERIFY(err, !fastrpc_mmap_remove(fl, ud->vaddrout, ud->size, &map)); if (err) goto bail; - VERIFY(err, !fastrpc_munmap_on_dsp(fl, map)); + VERIFY(err, !fastrpc_munmap_on_dsp(fl, map->raddr, + map->phys, map->size, map->flags)); if (err) goto bail; fastrpc_mmap_free(map); @@ -2131,22 +2254,55 @@ static int fastrpc_internal_mmap(struct fastrpc_file *fl, { struct fastrpc_mmap *map = NULL; + struct fastrpc_buf *rbuf = NULL; + uintptr_t raddr = 0; int err = 0; mutex_lock(&fl->map_mutex); - if (!fastrpc_mmap_find(fl, ud->fd, (uintptr_t)ud->vaddrin, ud->size, - ud->flags, &map)){ - mutex_unlock(&fl->map_mutex); - return 0; + + if (ud->flags == ADSP_MMAP_ADD_PAGES) { + DEFINE_DMA_ATTRS(dma_attr); + + if (ud->vaddrin) { + err = -EINVAL; + pr_err("adsprpc: %s: %s: ERROR: adding user allocated pages is not supported\n", + current->comm, __func__); + goto bail; + } + dma_set_attr(DMA_ATTR_EXEC_MAPPING, &dma_attr); + dma_set_attr(DMA_ATTR_NO_KERNEL_MAPPING, &dma_attr); + dma_set_attr(DMA_ATTR_FORCE_NON_COHERENT, &dma_attr); + + err = fastrpc_buf_alloc(fl, ud->size, dma_attr, ud->flags, + 1, &rbuf); + if (err) + goto bail; + err = fastrpc_mmap_on_dsp(fl, ud->flags, 0, + rbuf->phys, rbuf->size, &raddr); + if (err) + goto bail; + rbuf->raddr = raddr; + } else { + uintptr_t va_to_dsp; + + VERIFY(err, !fastrpc_mmap_create(fl, ud->fd, 0, + (uintptr_t)ud->vaddrin, ud->size, + ud->flags, &map)); + if (err) + goto bail; + + if (ud->flags == ADSP_MMAP_HEAP_ADDR || + ud->flags == ADSP_MMAP_REMOTE_HEAP_ADDR) + va_to_dsp = 0; + else + va_to_dsp = (uintptr_t)map->va; + VERIFY(err, 0 == fastrpc_mmap_on_dsp(fl, ud->flags, va_to_dsp, + map->phys, map->size, &raddr)); + if (err) + goto bail; + map->raddr = raddr; } - VERIFY(err, !fastrpc_mmap_create(fl, ud->fd, 0, - (uintptr_t)ud->vaddrin, ud->size, ud->flags, &map)); - if (err) - goto bail; - VERIFY(err, 0 == fastrpc_mmap_on_dsp(fl, ud->flags, map)); - if (err) - goto bail; - ud->vaddrout = map->raddr; + ud->vaddrout = raddr; bail: if (err && map) fastrpc_mmap_free(map); @@ -2321,15 +2477,16 @@ static int fastrpc_file_free(struct fastrpc_file *fl) spin_unlock(&fl->apps->hlock); kfree(fl->debug_buf); - if (!fl->sctx) { + if (!fl->sctx) goto bail; - } spin_lock(&fl->hlock); fl->file_close = 1; spin_unlock(&fl->hlock); + if (!IS_ERR_OR_NULL(fl->init_mem)) + fastrpc_buf_free(fl->init_mem, 0); fastrpc_context_list_dtor(fl); - fastrpc_buf_list_free(fl); + fastrpc_cached_buf_list_free(fl); hlist_for_each_entry_safe(map, n, &fl->maps, hn) { fastrpc_mmap_free(map); } @@ -2341,6 +2498,7 @@ static int fastrpc_file_free(struct fastrpc_file *fl) if (fl->secsctx) fastrpc_session_free(&fl->apps->channel[cid], fl->secsctx); bail: + fastrpc_remote_buf_list_free(fl); mutex_destroy(&fl->map_mutex); kfree(fl); return 0; @@ -2480,7 +2638,6 @@ static ssize_t fastrpc_debugfs_read(struct file *filp, char __user *buffer, struct fastrpc_apps *me = &gfa; struct fastrpc_file *fl = filp->private_data; struct hlist_node *n; - struct fastrpc_buf *buf = NULL; struct fastrpc_mmap *map = NULL; struct fastrpc_mmap *gmaps = NULL; struct smq_invoke_ctx *ictx = NULL; @@ -2641,22 +2798,6 @@ static ssize_t fastrpc_debugfs_read(struct file *filp, char __user *buffer, map->secure, map->attr); } len += scnprintf(fileinfo + len, DEBUGFS_SIZE - len, - "\n======%s %s %s======\n", title, - " LIST OF BUFS ", title); - spin_lock(&fl->hlock); - len += scnprintf(fileinfo + len, DEBUGFS_SIZE - len, - "%-19s|%-19s|%-19s\n", - "virt", "phys", "size"); - len += scnprintf(fileinfo + len, DEBUGFS_SIZE - len, - "%s%s%s%s%s\n", single_line, single_line, - single_line, single_line, single_line); - hlist_for_each_entry_safe(buf, n, &fl->bufs, hn) { - len += scnprintf(fileinfo + len, - DEBUGFS_SIZE - len, - "0x%-17p|0x%-17llX|%-19zu\n", - buf->virt, (uint64_t)buf->phys, buf->size); - } - len += scnprintf(fileinfo + len, DEBUGFS_SIZE - len, "\n%s %s %s\n", title, " LIST OF PENDING SMQCONTEXTS ", title); @@ -2800,12 +2941,15 @@ static int fastrpc_device_open(struct inode *inode, struct file *filp) context_list_ctor(&fl->clst); spin_lock_init(&fl->hlock); INIT_HLIST_HEAD(&fl->maps); - INIT_HLIST_HEAD(&fl->bufs); + INIT_HLIST_HEAD(&fl->cached_bufs); + INIT_HLIST_HEAD(&fl->remote_bufs); INIT_HLIST_NODE(&fl->hn); fl->tgid = current->tgid; fl->apps = me; fl->mode = FASTRPC_MODE_SERIAL; fl->cid = -1; + fl->init_mem = NULL; + if (debugfs_file != NULL) fl->debugfs_file = debugfs_file; memset(&fl->perf, 0, sizeof(fl->perf)); @@ -2843,6 +2987,30 @@ bail: return err; } +static int fastrpc_internal_control(struct fastrpc_file *fl, + struct fastrpc_ioctl_control *cp) +{ + int err = 0; + + VERIFY(err, !IS_ERR_OR_NULL(fl) && !IS_ERR_OR_NULL(fl->apps)); + if (err) + goto bail; + VERIFY(err, !IS_ERR_OR_NULL(cp)); + if (err) + goto bail; + + switch (cp->req) { + case FASTRPC_CONTROL_KALLOC: + cp->kalloc.kalloc_support = 1; + break; + default: + err = -ENOTTY; + break; + } +bail: + return err; +} + static long fastrpc_device_ioctl(struct file *file, unsigned int ioctl_num, unsigned long ioctl_param) { @@ -2852,6 +3020,7 @@ static long fastrpc_device_ioctl(struct file *file, unsigned int ioctl_num, struct fastrpc_ioctl_munmap munmap; struct fastrpc_ioctl_init_attrs init; struct fastrpc_ioctl_perf perf; + struct fastrpc_ioctl_control cp; } p; void *param = (char *)ioctl_param; struct fastrpc_file *fl = (struct fastrpc_file *)file->private_data; @@ -2967,8 +3136,22 @@ static long fastrpc_device_ioctl(struct file *file, unsigned int ioctl_num, if (err) goto bail; break; + case FASTRPC_IOCTL_CONTROL: + K_COPY_FROM_USER(err, 0, &p.cp, param, + sizeof(p.cp)); + if (err) + goto bail; + VERIFY(err, 0 == (err = fastrpc_internal_control(fl, &p.cp))); + if (err) + goto bail; + if (p.cp.req == FASTRPC_CONTROL_KALLOC) { + K_COPY_TO_USER(err, 0, param, &p.cp, sizeof(p.cp)); + if (err) + goto bail; + } + break; case FASTRPC_IOCTL_GETINFO: - K_COPY_FROM_USER(err, 0, &info, param, sizeof(info)); + K_COPY_FROM_USER(err, 0, &info, param, sizeof(info)); if (err) goto bail; VERIFY(err, 0 == (err = fastrpc_get_info(fl, &info))); @@ -3283,6 +3466,7 @@ static void fastrpc_deinit(void) } for (j = 0; j < NUM_SESSIONS; j++) { struct fastrpc_session_ctx *sess = &chan->session[j]; + if (sess->smmu.dev) { arm_iommu_detach_device(sess->smmu.dev); sess->smmu.dev = NULL; diff --git a/drivers/char/adsprpc_compat.c b/drivers/char/adsprpc_compat.c index e1e061748f22..d44ae93d9751 100644 --- a/drivers/char/adsprpc_compat.c +++ b/drivers/char/adsprpc_compat.c @@ -36,6 +36,8 @@ _IOWR('R', 9, struct compat_fastrpc_ioctl_perf) #define COMPAT_FASTRPC_IOCTL_INIT_ATTRS \ _IOWR('R', 10, struct compat_fastrpc_ioctl_init_attrs) +#define COMPAT_FASTRPC_IOCTL_CONTROL \ + _IOWR('R', 12, struct compat_fastrpc_ioctl_control) #define COMPAT_FASTRPC_IOCTL_MMAP_64 \ _IOWR('R', 14, struct compat_fastrpc_ioctl_mmap_64) #define COMPAT_FASTRPC_IOCTL_MUNMAP_64 \ @@ -117,6 +119,31 @@ struct compat_fastrpc_ioctl_perf { /* kernel performance data */ compat_uptr_t keys; }; +#define FASTRPC_CONTROL_LATENCY (1) +struct compat_fastrpc_ctrl_latency { + compat_uint_t enable; + compat_uint_t level; +}; + +#define FASTRPC_CONTROL_SMMU (2) +struct compat_fastrpc_ctrl_smmu { + compat_uint_t sharedcb; +}; + +#define FASTRPC_CONTROL_KALLOC (3) +struct compat_fastrpc_ctrl_kalloc { + compat_uint_t kalloc_support; /* Remote memory allocation from kernel */ +}; + +struct compat_fastrpc_ioctl_control { + compat_uint_t req; + union { + struct compat_fastrpc_ctrl_latency lp; + struct compat_fastrpc_ctrl_smmu smmu; + struct compat_fastrpc_ctrl_kalloc kalloc; + }; +}; + static int compat_get_fastrpc_ioctl_invoke( struct compat_fastrpc_ioctl_invoke_attrs __user *inv32, struct fastrpc_ioctl_invoke_attrs __user **inva, @@ -322,6 +349,19 @@ static int compat_get_fastrpc_ioctl_perf( return err; } +static int compat_get_fastrpc_ioctl_control( + struct compat_fastrpc_ioctl_control __user *ctrl32, + struct fastrpc_ioctl_control __user *ctrl) +{ + compat_uptr_t p; + int err; + + err = get_user(p, &ctrl32->req); + err |= put_user(p, &ctrl->req); + + return err; +} + static int compat_get_fastrpc_ioctl_init( struct compat_fastrpc_ioctl_init_attrs __user *init32, struct fastrpc_ioctl_init_attrs __user *init, @@ -513,6 +553,34 @@ long compat_fastrpc_device_ioctl(struct file *filp, unsigned int cmd, case FASTRPC_IOCTL_SETMODE: return filp->f_op->unlocked_ioctl(filp, cmd, (unsigned long)compat_ptr(arg)); + case COMPAT_FASTRPC_IOCTL_CONTROL: + { + struct compat_fastrpc_ioctl_control __user *ctrl32; + struct fastrpc_ioctl_control __user *ctrl; + compat_uptr_t p; + + ctrl32 = compat_ptr(arg); + VERIFY(err, NULL != (ctrl = compat_alloc_user_space( + sizeof(*ctrl)))); + if (err) + return -EFAULT; + VERIFY(err, 0 == compat_get_fastrpc_ioctl_control(ctrl32, + ctrl)); + if (err) + return err; + err = filp->f_op->unlocked_ioctl(filp, FASTRPC_IOCTL_CONTROL, + (unsigned long)ctrl); + if (err) + return err; + err = get_user(p, &ctrl32->req); + if (err) + return err; + if (p == FASTRPC_CONTROL_KALLOC) { + err = get_user(p, &ctrl->kalloc.kalloc_support); + err |= put_user(p, &ctrl32->kalloc.kalloc_support); + } + return err; + } case COMPAT_FASTRPC_IOCTL_GETPERF: { struct compat_fastrpc_ioctl_perf __user *perf32; diff --git a/drivers/char/adsprpc_shared.h b/drivers/char/adsprpc_shared.h index a88c668440c7..4371bf6a2ae7 100644 --- a/drivers/char/adsprpc_shared.h +++ b/drivers/char/adsprpc_shared.h @@ -29,6 +29,7 @@ #define FASTRPC_IOCTL_GETINFO _IOWR('R', 8, uint32_t) #define FASTRPC_IOCTL_GETPERF _IOWR('R', 9, struct fastrpc_ioctl_perf) #define FASTRPC_IOCTL_INIT_ATTRS _IOWR('R', 10, struct fastrpc_ioctl_init_attrs) +#define FASTRPC_IOCTL_CONTROL _IOWR('R', 12, struct fastrpc_ioctl_control) #define FASTRPC_GLINK_GUID "fastrpcglink-apps-dsp" #define FASTRPC_SMD_GUID "fastrpcsmd-apps-dsp" @@ -188,7 +189,7 @@ struct fastrpc_ioctl_mmap { struct fastrpc_ioctl_mmap_64 { - int fd; /* ion fd */ + int fd; /* ion fd */ uint32_t flags; /* flags for dsp to map with */ uint64_t vaddrin; /* optional virtual address */ size_t size; /* size */ @@ -201,6 +202,31 @@ struct fastrpc_ioctl_perf { /* kernel performance data */ uintptr_t keys; }; +#define FASTRPC_CONTROL_LATENCY (1) +struct fastrpc_ctrl_latency { + uint32_t enable; /* latency control enable */ + uint32_t level; /* level of control */ +}; + +#define FASTRPC_CONTROL_SMMU (2) +struct fastrpc_ctrl_smmu { + uint32_t sharedcb; +}; + +#define FASTRPC_CONTROL_KALLOC (3) +struct fastrpc_ctrl_kalloc { + uint32_t kalloc_support; /* Remote memory allocation from kernel */ +}; + +struct fastrpc_ioctl_control { + uint32_t req; + union { + struct fastrpc_ctrl_latency lp; + struct fastrpc_ctrl_smmu smmu; + struct fastrpc_ctrl_kalloc kalloc; + }; +}; + struct smq_null_invoke { uint64_t ctx; /* invoke caller context */ uint32_t handle; /* handle to invoke */ @@ -245,6 +271,7 @@ static inline struct smq_phy_page *smq_phy_page_start(uint32_t sc, struct smq_invoke_buf *buf) { uint64_t nTotal = REMOTE_SCALARS_INBUFS(sc)+REMOTE_SCALARS_OUTBUFS(sc); + return (struct smq_phy_page *)(&buf[nTotal]); } diff --git a/drivers/cpufreq/imx6q-cpufreq.c b/drivers/cpufreq/imx6q-cpufreq.c index ef1fa8145419..fa86946d12aa 100644 --- a/drivers/cpufreq/imx6q-cpufreq.c +++ b/drivers/cpufreq/imx6q-cpufreq.c @@ -130,8 +130,13 @@ static int imx6q_set_target(struct cpufreq_policy *policy, unsigned int index) /* Ensure the arm clock divider is what we expect */ ret = clk_set_rate(arm_clk, new_freq * 1000); if (ret) { + int ret1; + dev_err(cpu_dev, "failed to set clock rate: %d\n", ret); - regulator_set_voltage_tol(arm_reg, volt_old, 0); + ret1 = regulator_set_voltage_tol(arm_reg, volt_old, 0); + if (ret1) + dev_warn(cpu_dev, + "failed to restore vddarm voltage: %d\n", ret1); return ret; } diff --git a/drivers/dma/at_hdmac.c b/drivers/dma/at_hdmac.c index be26f625bb3e..941ace052130 100644 --- a/drivers/dma/at_hdmac.c +++ b/drivers/dma/at_hdmac.c @@ -1781,6 +1781,12 @@ static void atc_free_chan_resources(struct dma_chan *chan) atchan->descs_allocated = 0; atchan->status = 0; + /* + * Free atslave allocated in at_dma_xlate() + */ + kfree(chan->private); + chan->private = NULL; + dev_vdbg(chan2dev(chan), "free_chan_resources: done\n"); } @@ -1815,7 +1821,7 @@ static struct dma_chan *at_dma_xlate(struct of_phandle_args *dma_spec, dma_cap_zero(mask); dma_cap_set(DMA_SLAVE, mask); - atslave = devm_kzalloc(&dmac_pdev->dev, sizeof(*atslave), GFP_KERNEL); + atslave = kzalloc(sizeof(*atslave), GFP_KERNEL); if (!atslave) return NULL; @@ -2146,6 +2152,8 @@ static int at_dma_remove(struct platform_device *pdev) struct resource *io; at_dma_off(atdma); + if (pdev->dev.of_node) + of_dma_controller_free(pdev->dev.of_node); dma_async_device_unregister(&atdma->dma_common); dma_pool_destroy(atdma->memset_pool); diff --git a/drivers/gpu/drm/ast/ast_drv.c b/drivers/gpu/drm/ast/ast_drv.c index 9a32d9dfdd26..011700262824 100644 --- a/drivers/gpu/drm/ast/ast_drv.c +++ b/drivers/gpu/drm/ast/ast_drv.c @@ -60,8 +60,29 @@ static const struct pci_device_id pciidlist[] = { MODULE_DEVICE_TABLE(pci, pciidlist); +static void ast_kick_out_firmware_fb(struct pci_dev *pdev) +{ + struct apertures_struct *ap; + bool primary = false; + + ap = alloc_apertures(1); + if (!ap) + return; + + ap->ranges[0].base = pci_resource_start(pdev, 0); + ap->ranges[0].size = pci_resource_len(pdev, 0); + +#ifdef CONFIG_X86 + primary = pdev->resource[PCI_ROM_RESOURCE].flags & IORESOURCE_ROM_SHADOW; +#endif + remove_conflicting_framebuffers(ap, "astdrmfb", primary); + kfree(ap); +} + static int ast_pci_probe(struct pci_dev *pdev, const struct pci_device_id *ent) { + ast_kick_out_firmware_fb(pdev); + return drm_get_pci_dev(pdev, ent, &driver); } diff --git a/drivers/gpu/drm/ast/ast_main.c b/drivers/gpu/drm/ast/ast_main.c index 498a94069e6b..1acebd64fded 100644 --- a/drivers/gpu/drm/ast/ast_main.c +++ b/drivers/gpu/drm/ast/ast_main.c @@ -557,7 +557,8 @@ int ast_driver_unload(struct drm_device *dev) drm_mode_config_cleanup(dev); ast_mm_fini(ast); - pci_iounmap(dev->pdev, ast->ioregs); + if (ast->ioregs != ast->regs + AST_IO_MM_OFFSET) + pci_iounmap(dev->pdev, ast->ioregs); pci_iounmap(dev->pdev, ast->regs); kfree(ast); return 0; diff --git a/drivers/gpu/drm/ast/ast_mode.c b/drivers/gpu/drm/ast/ast_mode.c index 69d19f3304a5..21085f669e21 100644 --- a/drivers/gpu/drm/ast/ast_mode.c +++ b/drivers/gpu/drm/ast/ast_mode.c @@ -552,6 +552,7 @@ static int ast_crtc_do_set_base(struct drm_crtc *crtc, } ast_bo_unreserve(bo); + ast_set_offset_reg(crtc); ast_set_start_address_crt1(crtc, (u32)gpu_addr); return 0; @@ -1249,7 +1250,7 @@ static int ast_cursor_move(struct drm_crtc *crtc, ast_set_index_reg(ast, AST_IO_CRTC_PORT, 0xc7, ((y >> 8) & 0x07)); /* dummy write to fire HWC */ - ast_set_index_reg_mask(ast, AST_IO_CRTC_PORT, 0xCB, 0xFF, 0x00); + ast_show_cursor(crtc); return 0; } diff --git a/drivers/gpu/drm/gma500/mdfld_intel_display.c b/drivers/gpu/drm/gma500/mdfld_intel_display.c index acd38344b302..764094dd30dd 100644 --- a/drivers/gpu/drm/gma500/mdfld_intel_display.c +++ b/drivers/gpu/drm/gma500/mdfld_intel_display.c @@ -99,7 +99,7 @@ void mdfldWaitForPipeEnable(struct drm_device *dev, int pipe) /* Wait for for the pipe enable to take effect. */ for (count = 0; count < COUNT_MAX; count++) { temp = REG_READ(map->conf); - if ((temp & PIPEACONF_PIPE_STATE) == 1) + if (temp & PIPEACONF_PIPE_STATE) break; } } diff --git a/drivers/gpu/drm/msm/sde/sde_connector.c b/drivers/gpu/drm/msm/sde/sde_connector.c index 5f6b93931c35..1bc3d0a926eb 100644 --- a/drivers/gpu/drm/msm/sde/sde_connector.c +++ b/drivers/gpu/drm/msm/sde/sde_connector.c @@ -17,10 +17,6 @@ #include "sde_connector.h" #include "sde_backlight.h" #include "sde_splash.h" -#include <linux/workqueue.h> -#include <linux/atomic.h> -#include <linux/cpu.h> -#include <linux/device.h> #define SDE_DEBUG_CONN(c, fmt, ...) SDE_DEBUG("conn%d " fmt,\ (c) ? (c)->base.base.id : -1, ##__VA_ARGS__) @@ -55,8 +51,6 @@ static const struct drm_prop_enum_list hpd_clock_state[] = { {SDE_MODE_HPD_OFF, "OFF"}, }; -static struct work_struct cpu_up_work; - int sde_connector_get_info(struct drm_connector *connector, struct msm_display_info *info) { @@ -574,25 +568,11 @@ void sde_connector_prepare_fence(struct drm_connector *connector) sde_fence_prepare(&to_sde_connector(connector)->retire_fence); } -static void wake_up_cpu(struct work_struct *work) -{ - struct device *cpu_dev = NULL; - - cpu_dev = get_cpu_device(1); - if (!cpu_dev) { - pr_err("Could not get cpu1 device\n"); - return; - } - if (!device_online(cpu_dev)) - pr_info("cpu1 is online\n"); -} - void sde_connector_complete_commit(struct drm_connector *connector) { struct drm_device *dev; struct msm_drm_private *priv; struct sde_connector *c_conn; - static atomic_t cpu_up_scheduled = ATOMIC_INIT(0); if (!connector) { SDE_ERROR("invalid connector\n"); @@ -607,8 +587,7 @@ void sde_connector_complete_commit(struct drm_connector *connector) /* * After LK totally exits, LK's early splash resource - * should be released, cpu1 is hot-plugged in case LK's - * early domain has reserved it. + * should be released. */ if (sde_splash_get_lk_complete_status(priv->kms)) { c_conn = to_sde_connector(connector); @@ -616,11 +595,8 @@ void sde_connector_complete_commit(struct drm_connector *connector) sde_splash_free_resource(priv->kms, &priv->phandle, c_conn->connector_type, c_conn->display); - if (atomic_add_unless(&cpu_up_scheduled, 1, 1)) { - INIT_WORK(&cpu_up_work, wake_up_cpu); - schedule_work(&cpu_up_work); - } } + } static int sde_connector_dpms(struct drm_connector *connector, diff --git a/drivers/gpu/drm/msm/sde/sde_crtc.c b/drivers/gpu/drm/msm/sde/sde_crtc.c index 01da32ae5958..86d260e7ca5f 100644 --- a/drivers/gpu/drm/msm/sde/sde_crtc.c +++ b/drivers/gpu/drm/msm/sde/sde_crtc.c @@ -1649,7 +1649,7 @@ static void sde_crtc_install_properties(struct drm_crtc *crtc, */ if (sde_kms->splash_info.handoff) sde_kms_info_add_keyint(info, "max_blendstages", - catalog->max_mixer_blendstages - 1); + catalog->max_mixer_blendstages - 2); else sde_kms_info_add_keyint(info, "max_blendstages", catalog->max_mixer_blendstages); @@ -1995,6 +1995,26 @@ static void _sde_crtc_init_debugfs(struct sde_crtc *sde_crtc, } #endif +void sde_crtc_update_blob_property(struct drm_crtc *crtc, + const char *key, + int32_t value) +{ + struct sde_crtc *sde_crtc; + char *kms_info_str = NULL; + size_t len; + + sde_crtc = to_sde_crtc(crtc); + + kms_info_str = (char *)msm_property_get_blob(&sde_crtc->property_info, + &sde_crtc->blob_info, &len, CRTC_PROP_INFO); + if (!kms_info_str) { + SDE_ERROR("get crtc property_info failed"); + return; + } + + sde_kms_info_update_keystr(kms_info_str, key, value); +} + /* initialize crtc */ struct drm_crtc *sde_crtc_init(struct drm_device *dev, struct drm_plane *plane) diff --git a/drivers/gpu/drm/msm/sde/sde_crtc.h b/drivers/gpu/drm/msm/sde/sde_crtc.h index 200073995d43..a1042390b1a9 100644 --- a/drivers/gpu/drm/msm/sde/sde_crtc.h +++ b/drivers/gpu/drm/msm/sde/sde_crtc.h @@ -292,4 +292,13 @@ static inline bool sde_crtc_is_enabled(struct drm_crtc *crtc) return crtc ? crtc->enabled : false; } +/** + * sde_crtc_update_blob_property - update blob property of a given crtc + * @crtc: Pointer to crtc + * @key: Pointer to key string + * @value: Signed 32 bit integer value + */ +void sde_crtc_update_blob_property(struct drm_crtc *crtc, + const char *key, + int32_t value); #endif /* _SDE_CRTC_H_ */ diff --git a/drivers/gpu/drm/msm/sde/sde_kms.h b/drivers/gpu/drm/msm/sde/sde_kms.h index dee16d119d47..c7355f5bd891 100644 --- a/drivers/gpu/drm/msm/sde/sde_kms.h +++ b/drivers/gpu/drm/msm/sde/sde_kms.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015-2017, The Linux Foundation. All rights reserved. + * Copyright (c) 2015-2018, The Linux Foundation. All rights reserved. * Copyright (C) 2013 Red Hat * Author: Rob Clark <robdclark@gmail.com> * @@ -306,6 +306,16 @@ void sde_kms_info_add_keyint(struct sde_kms_info *info, int32_t value); /** + * sde_kms_info_update_keystr - update the special string's value. + * @info_str: Pointer to source blob str + * @key: Pointer to key string + * @value: Signed 32-bit integer value + */ +void sde_kms_info_update_keystr(char *info_str, + const char *key, + int32_t value); + +/** * sde_kms_info_add_keystr - add string value to 'sde_kms_info' * @info: Pointer to sde_kms_info structure * @key: Pointer to key string diff --git a/drivers/gpu/drm/msm/sde/sde_kms_utils.c b/drivers/gpu/drm/msm/sde/sde_kms_utils.c index 30e12c969538..90fd3912eb59 100644 --- a/drivers/gpu/drm/msm/sde/sde_kms_utils.c +++ b/drivers/gpu/drm/msm/sde/sde_kms_utils.c @@ -1,4 +1,4 @@ -/* Copyright (c) 2015-2017, The Linux Foundation. All rights reserved. +/* Copyright (c) 2015-2018, The Linux Foundation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 and @@ -41,6 +41,64 @@ void sde_kms_info_add_keyint(struct sde_kms_info *info, } } +void sde_kms_info_update_keystr(char *info_str, + const char *key, + int32_t value) +{ + char *str, *temp, *append_str; + uint32_t dst_len = 0, prefix_len = 0; + char c; + int32_t size = 0; + + if (info_str && key) { + str = strnstr(info_str, key, strlen(info_str)); + if (str) { + temp = str + strlen(key); + c = *temp; + while (c != '\n') { + dst_len++; + c = *(++temp); + } + /* + * If input key string to update is exactly the last + * string in source string, no need to allocate one + * memory to store the string after string key. Just + * replace the value of the last string. + * + * If it is not, allocate one new memory to save + * the string after string key+"\n". This new allocated + * string will be appended to the whole source string + * after key value is updated. + */ + size = strlen(str) - strlen(key) - dst_len - 1; + if (size > 0) { + append_str = kzalloc(size + 1, GFP_KERNEL); + if (!append_str) { + SDE_ERROR("failed to alloc memory\n"); + return; + } + memcpy(append_str, + str + strlen(key) + dst_len + 1, size); + } + + prefix_len = strlen(info_str) - strlen(str); + /* Update string with new value for the string key. */ + snprintf(info_str + prefix_len, + SDE_KMS_INFO_MAX_SIZE - prefix_len, + "%s%d\n", key, value); + + /* Append the string save aboved. */ + if (size > 0 && append_str) { + size = prefix_len + strlen(key) + dst_len + 1; + snprintf(info_str + size, + SDE_KMS_INFO_MAX_SIZE - size, + "%s", append_str); + kfree(append_str); + } + } + } +} + void sde_kms_info_add_keystr(struct sde_kms_info *info, const char *key, const char *value) diff --git a/drivers/gpu/drm/msm/sde/sde_plane.c b/drivers/gpu/drm/msm/sde/sde_plane.c index e50577e3eb4b..a35428c93867 100644 --- a/drivers/gpu/drm/msm/sde/sde_plane.c +++ b/drivers/gpu/drm/msm/sde/sde_plane.c @@ -2732,6 +2732,24 @@ end: return rc; } +void sde_plane_update_blob_property(struct drm_plane *plane, + const char *key, + int32_t value) +{ + char *kms_info_str = NULL; + struct sde_plane *sde_plane = to_sde_plane(plane); + size_t len; + + kms_info_str = (char *)msm_property_get_blob(&sde_plane->property_info, + &sde_plane->blob_info, &len, 0); + if (!kms_info_str) { + SDE_ERROR("get plane property_info failed\n"); + return; + } + + sde_kms_info_update_keystr(kms_info_str, key, value); +} + /* initialize plane */ struct drm_plane *sde_plane_init(struct drm_device *dev, uint32_t pipe, bool primary_plane, diff --git a/drivers/gpu/drm/msm/sde/sde_plane.h b/drivers/gpu/drm/msm/sde/sde_plane.h index 8ac582643926..c1414e7db74e 100644 --- a/drivers/gpu/drm/msm/sde/sde_plane.h +++ b/drivers/gpu/drm/msm/sde/sde_plane.h @@ -102,4 +102,13 @@ int sde_plane_wait_input_fence(struct drm_plane *plane, uint32_t wait_ms); int sde_plane_color_fill(struct drm_plane *plane, uint32_t color, uint32_t alpha); +/** + * sde_plane_update_blob_property - update plane blob property + * @plane: Pointer to DRM plane object + * @key: Pointer to key string + * @value: Signed 32 bit integer value + */ +void sde_plane_update_blob_property(struct drm_plane *plane, + const char *key, + int32_t value); #endif /* _SDE_PLANE_H_ */ diff --git a/drivers/gpu/drm/msm/sde/sde_splash.c b/drivers/gpu/drm/msm/sde/sde_splash.c index 16f9248b7abe..ebb02dba6d5d 100644 --- a/drivers/gpu/drm/msm/sde/sde_splash.c +++ b/drivers/gpu/drm/msm/sde/sde_splash.c @@ -14,7 +14,7 @@ #include <linux/of_address.h> #include <linux/debugfs.h> #include <linux/memblock.h> - +#include <soc/qcom/early_domain.h> #include "msm_drv.h" #include "msm_mmu.h" #include "sde_kms.h" @@ -26,6 +26,7 @@ #include "dsi_display.h" #include "sde_hdmi.h" #include "sde_crtc.h" +#include "sde_plane.h" #define MDP_SSPP_TOP0_OFF 0x1000 #define DISP_INTF_SEL 0x004 @@ -65,49 +66,6 @@ static void _sde_splash_free_bootup_memory_to_system(phys_addr_t phys, free_reserved_page(pfn_to_page(pfn_idx)); } -static int _sde_splash_parse_dt_get_lk_pool_node(struct drm_device *dev, - struct sde_splash_info *sinfo) -{ - struct device_node *parent, *node; - struct resource r; - int ret = 0; - - if (!sinfo) - return -EINVAL; - - parent = of_find_node_by_path("/reserved-memory"); - if (!parent) - return -EINVAL; - - node = of_find_node_by_name(parent, "lk_pool"); - if (!node) { - SDE_ERROR("mem reservation for lk_pool is not presented\n"); - ret = -EINVAL; - goto parent_node_err; - } - - /* find the mode */ - if (of_address_to_resource(node, 0, &r)) { - ret = -EINVAL; - goto child_node_err; - } - - sinfo->lk_pool_paddr = (dma_addr_t)r.start; - sinfo->lk_pool_size = r.end - r.start; - - DRM_INFO("lk_pool: addr:%pK, size:%pK\n", - (void *)sinfo->lk_pool_paddr, - (void *)sinfo->lk_pool_size); - -child_node_err: - of_node_put(node); - -parent_node_err: - of_node_put(parent); - - return ret; -} - static int _sde_splash_parse_dt_get_display_node(struct drm_device *dev, struct sde_splash_info *sinfo) { @@ -182,10 +140,9 @@ error: return -ENOMEM; } -static bool _sde_splash_lk_check(struct sde_hw_intr *intr) +static bool _sde_splash_lk_check(void) { - return (SDE_LK_RUNNING_VALUE == SDE_REG_READ(&intr->hw, - SCRATCH_REGISTER_1)) ? true : false; + return get_early_service_status(EARLY_DISPLAY); } /** @@ -193,10 +150,9 @@ static bool _sde_splash_lk_check(struct sde_hw_intr *intr) * * Function to stop early splash in LK. */ -static inline void _sde_splash_notify_lk_stop_splash(struct sde_hw_intr *intr) +static inline void _sde_splash_notify_lk_stop_splash(void) { - /* write splash stop signal to scratch register*/ - SDE_REG_WRITE(&intr->hw, SCRATCH_REGISTER_1, SDE_LK_STOP_SPLASH_VALUE); + request_early_service_shutdown(EARLY_DISPLAY); } static int _sde_splash_gem_new(struct drm_device *dev, @@ -391,6 +347,28 @@ static bool _sde_splash_validate_commit(struct sde_kms *sde_kms, return false; } +static void _sde_splash_update_property(struct sde_kms *sde_kms) +{ + struct drm_device *dev = sde_kms->dev; + struct drm_crtc *crtc; + struct drm_plane *plane; + struct sde_mdss_cfg *catalog = sde_kms->catalog; + + /* + * Update plane availability property + * after splash handoff is done. + */ + drm_for_each_plane(plane, dev) { + sde_plane_update_blob_property(plane, + "plane_unavailability=", 0); + } + + /* update crtc blend stage property */ + drm_for_each_crtc(crtc, dev) + sde_crtc_update_blob_property(crtc, "max_blendstages=", + catalog->max_mixer_blendstages); +} + __ref int sde_splash_init(struct sde_power_handle *phandle, struct msm_kms *kms) { struct sde_kms *sde_kms; @@ -479,12 +457,6 @@ int sde_splash_parse_memory_dt(struct drm_device *dev) SDE_ERROR("get display node failed\n"); return -EINVAL; } - - if (_sde_splash_parse_dt_get_lk_pool_node(dev, sinfo)) { - SDE_ERROR("get LK pool node failed\n"); - return -EINVAL; - } - return 0; } @@ -758,9 +730,8 @@ bool sde_splash_get_lk_complete_status(struct msm_kms *kms) if (sde_kms->splash_info.handoff && !sde_kms->splash_info.display_splash_enabled && - SDE_LK_EXIT_VALUE == SDE_REG_READ(&intr->hw, - SCRATCH_REGISTER_1)) { - SDE_DEBUG("LK totoally exits\n"); + !_sde_splash_lk_check()) { + SDE_DEBUG("LK totally exits\n"); return true; } @@ -818,10 +789,6 @@ int sde_splash_free_resource(struct msm_kms *kms, _sde_splash_destroy_splash_node(sinfo); - /* free lk_pool heap memory */ - _sde_splash_free_bootup_memory_to_system(sinfo->lk_pool_paddr, - sinfo->lk_pool_size); - /* withdraw data bus vote */ sde_power_data_bus_bandwidth_ctrl(phandle, sde_kms->core_client, false); @@ -834,6 +801,9 @@ int sde_splash_free_resource(struct msm_kms *kms, sde_power_resource_enable(phandle, sde_kms->core_client, false); + /* update impacted crtc and plane property by splash */ + _sde_splash_update_property(sde_kms); + /* send uevent to notify user to recycle resource */ _sde_splash_sent_pipe_update_uevent(sde_kms); @@ -948,8 +918,8 @@ int sde_splash_lk_stop_splash(struct msm_kms *kms, mutex_lock(&sde_splash_lock); if (_sde_splash_validate_commit(sde_kms, state) && sinfo->display_splash_enabled) { - if (_sde_splash_lk_check(sde_kms->hw_intr)) - _sde_splash_notify_lk_stop_splash(sde_kms->hw_intr); + if (_sde_splash_lk_check()) + _sde_splash_notify_lk_stop_splash(); sinfo->display_splash_enabled = false; diff --git a/drivers/gpu/drm/msm/sde/sde_splash.h b/drivers/gpu/drm/msm/sde/sde_splash.h index c4bb7b08f817..ee94c348e25b 100644 --- a/drivers/gpu/drm/msm/sde/sde_splash.h +++ b/drivers/gpu/drm/msm/sde/sde_splash.h @@ -68,12 +68,6 @@ struct sde_splash_info { /* constructed gem objects for smmu mapping */ struct drm_gem_object **obj; - /* physical address of lk pool */ - phys_addr_t lk_pool_paddr; - - /* memory size of lk pool */ - size_t lk_pool_size; - /* enabled statue of displays*/ uint32_t intf_sel_status; diff --git a/drivers/infiniband/ulp/iser/iser_verbs.c b/drivers/infiniband/ulp/iser/iser_verbs.c index 0cbc7ceb9a55..1610accfed0b 100644 --- a/drivers/infiniband/ulp/iser/iser_verbs.c +++ b/drivers/infiniband/ulp/iser/iser_verbs.c @@ -1289,7 +1289,9 @@ u8 iser_check_task_pi_status(struct iscsi_iser_task *iser_task, IB_MR_CHECK_SIG_STATUS, &mr_status); if (ret) { pr_err("ib_check_mr_status failed, ret %d\n", ret); - goto err; + /* Not a lot we can do, return ambiguous guard error */ + *sector = 0; + return 0x1; } if (mr_status.fail_status & IB_MR_CHECK_SIG_STATUS) { @@ -1317,7 +1319,4 @@ u8 iser_check_task_pi_status(struct iscsi_iser_task *iser_task, } return 0; -err: - /* Not alot we can do here, return ambiguous guard error */ - return 0x1; } diff --git a/drivers/input/joystick/xpad.c b/drivers/input/joystick/xpad.c index 3258baf3282e..f55dcdf99bc5 100644 --- a/drivers/input/joystick/xpad.c +++ b/drivers/input/joystick/xpad.c @@ -76,18 +76,23 @@ */ #include <linux/kernel.h> +#include <linux/input.h> +#include <linux/rcupdate.h> #include <linux/slab.h> #include <linux/stat.h> #include <linux/module.h> #include <linux/usb/input.h> +#include <linux/usb/quirks.h> #define DRIVER_AUTHOR "Marko Friedemann <mfr@bmx-chemnitz.de>" #define DRIVER_DESC "X-Box pad driver" -#define XPAD_PKT_LEN 32 +#define XPAD_PKT_LEN 64 -/* xbox d-pads should map to buttons, as is required for DDR pads - but we map them to axes when possible to simplify things */ +/* + * xbox d-pads should map to buttons, as is required for DDR pads + * but we map them to axes when possible to simplify things + */ #define MAP_DPAD_TO_BUTTONS (1 << 0) #define MAP_TRIGGERS_TO_BUTTONS (1 << 1) #define MAP_STICKS_TO_NULL (1 << 2) @@ -112,6 +117,10 @@ static bool sticks_to_null; module_param(sticks_to_null, bool, S_IRUGO); MODULE_PARM_DESC(sticks_to_null, "Do not map sticks at all for unknown pads"); +static bool auto_poweroff = true; +module_param(auto_poweroff, bool, S_IWUSR | S_IRUGO); +MODULE_PARM_DESC(auto_poweroff, "Power off wireless controllers on suspend"); + static const struct xpad_device { u16 idVendor; u16 idProduct; @@ -119,43 +128,77 @@ static const struct xpad_device { u8 mapping; u8 xtype; } xpad_device[] = { + { 0x0079, 0x18d4, "GPD Win 2 X-Box Controller", 0, XTYPE_XBOX360 }, + { 0x044f, 0x0f00, "Thrustmaster Wheel", 0, XTYPE_XBOX }, + { 0x044f, 0x0f03, "Thrustmaster Wheel", 0, XTYPE_XBOX }, + { 0x044f, 0x0f07, "Thrustmaster, Inc. Controller", 0, XTYPE_XBOX }, + { 0x044f, 0x0f10, "Thrustmaster Modena GT Wheel", 0, XTYPE_XBOX }, + { 0x044f, 0xb326, "Thrustmaster Gamepad GP XID", 0, XTYPE_XBOX360 }, { 0x045e, 0x0202, "Microsoft X-Box pad v1 (US)", 0, XTYPE_XBOX }, { 0x045e, 0x0285, "Microsoft X-Box pad (Japan)", 0, XTYPE_XBOX }, { 0x045e, 0x0287, "Microsoft Xbox Controller S", 0, XTYPE_XBOX }, + { 0x045e, 0x0288, "Microsoft Xbox Controller S v2", 0, XTYPE_XBOX }, { 0x045e, 0x0289, "Microsoft X-Box pad v2 (US)", 0, XTYPE_XBOX }, { 0x045e, 0x028e, "Microsoft X-Box 360 pad", 0, XTYPE_XBOX360 }, - { 0x045e, 0x02d1, "Microsoft X-Box One pad", 0, XTYPE_XBOXONE }, - { 0x045e, 0x02dd, "Microsoft X-Box One pad (Covert Forces)", 0, XTYPE_XBOXONE }, + { 0x045e, 0x028f, "Microsoft X-Box 360 pad v2", 0, XTYPE_XBOX360 }, { 0x045e, 0x0291, "Xbox 360 Wireless Receiver (XBOX)", MAP_DPAD_TO_BUTTONS, XTYPE_XBOX360W }, + { 0x045e, 0x02d1, "Microsoft X-Box One pad", 0, XTYPE_XBOXONE }, + { 0x045e, 0x02dd, "Microsoft X-Box One pad (Firmware 2015)", 0, XTYPE_XBOXONE }, + { 0x045e, 0x02e3, "Microsoft X-Box One Elite pad", 0, XTYPE_XBOXONE }, + { 0x045e, 0x02ea, "Microsoft X-Box One S pad", 0, XTYPE_XBOXONE }, { 0x045e, 0x0719, "Xbox 360 Wireless Receiver", MAP_DPAD_TO_BUTTONS, XTYPE_XBOX360W }, - { 0x044f, 0x0f07, "Thrustmaster, Inc. Controller", 0, XTYPE_XBOX }, - { 0x044f, 0xb326, "Thrustmaster Gamepad GP XID", 0, XTYPE_XBOX360 }, { 0x046d, 0xc21d, "Logitech Gamepad F310", 0, XTYPE_XBOX360 }, { 0x046d, 0xc21e, "Logitech Gamepad F510", 0, XTYPE_XBOX360 }, { 0x046d, 0xc21f, "Logitech Gamepad F710", 0, XTYPE_XBOX360 }, { 0x046d, 0xc242, "Logitech Chillstream Controller", 0, XTYPE_XBOX360 }, { 0x046d, 0xca84, "Logitech Xbox Cordless Controller", 0, XTYPE_XBOX }, { 0x046d, 0xca88, "Logitech Compact Controller for Xbox", 0, XTYPE_XBOX }, + { 0x046d, 0xca8a, "Logitech Precision Vibration Feedback Wheel", 0, XTYPE_XBOX }, + { 0x046d, 0xcaa3, "Logitech DriveFx Racing Wheel", 0, XTYPE_XBOX360 }, + { 0x056e, 0x2004, "Elecom JC-U3613M", 0, XTYPE_XBOX360 }, { 0x05fd, 0x1007, "Mad Catz Controller (unverified)", 0, XTYPE_XBOX }, { 0x05fd, 0x107a, "InterAct 'PowerPad Pro' X-Box pad (Germany)", 0, XTYPE_XBOX }, + { 0x05fe, 0x3030, "Chic Controller", 0, XTYPE_XBOX }, + { 0x05fe, 0x3031, "Chic Controller", 0, XTYPE_XBOX }, + { 0x062a, 0x0020, "Logic3 Xbox GamePad", 0, XTYPE_XBOX }, + { 0x062a, 0x0033, "Competition Pro Steering Wheel", 0, XTYPE_XBOX }, + { 0x06a3, 0x0200, "Saitek Racing Wheel", 0, XTYPE_XBOX }, + { 0x06a3, 0x0201, "Saitek Adrenalin", 0, XTYPE_XBOX }, + { 0x06a3, 0xf51a, "Saitek P3600", 0, XTYPE_XBOX360 }, + { 0x0738, 0x4506, "Mad Catz 4506 Wireless Controller", 0, XTYPE_XBOX }, { 0x0738, 0x4516, "Mad Catz Control Pad", 0, XTYPE_XBOX }, + { 0x0738, 0x4520, "Mad Catz Control Pad Pro", 0, XTYPE_XBOX }, { 0x0738, 0x4522, "Mad Catz LumiCON", 0, XTYPE_XBOX }, { 0x0738, 0x4526, "Mad Catz Control Pad Pro", 0, XTYPE_XBOX }, + { 0x0738, 0x4530, "Mad Catz Universal MC2 Racing Wheel and Pedals", 0, XTYPE_XBOX }, { 0x0738, 0x4536, "Mad Catz MicroCON", 0, XTYPE_XBOX }, { 0x0738, 0x4540, "Mad Catz Beat Pad", MAP_DPAD_TO_BUTTONS, XTYPE_XBOX }, { 0x0738, 0x4556, "Mad Catz Lynx Wireless Controller", 0, XTYPE_XBOX }, + { 0x0738, 0x4586, "Mad Catz MicroCon Wireless Controller", 0, XTYPE_XBOX }, + { 0x0738, 0x4588, "Mad Catz Blaster", 0, XTYPE_XBOX }, + { 0x0738, 0x45ff, "Mad Catz Beat Pad (w/ Handle)", MAP_DPAD_TO_BUTTONS, XTYPE_XBOX }, { 0x0738, 0x4716, "Mad Catz Wired Xbox 360 Controller", 0, XTYPE_XBOX360 }, { 0x0738, 0x4718, "Mad Catz Street Fighter IV FightStick SE", 0, XTYPE_XBOX360 }, { 0x0738, 0x4726, "Mad Catz Xbox 360 Controller", 0, XTYPE_XBOX360 }, { 0x0738, 0x4728, "Mad Catz Street Fighter IV FightPad", MAP_TRIGGERS_TO_BUTTONS, XTYPE_XBOX360 }, + { 0x0738, 0x4736, "Mad Catz MicroCon Gamepad", 0, XTYPE_XBOX360 }, { 0x0738, 0x4738, "Mad Catz Wired Xbox 360 Controller (SFIV)", MAP_TRIGGERS_TO_BUTTONS, XTYPE_XBOX360 }, { 0x0738, 0x4740, "Mad Catz Beat Pad", 0, XTYPE_XBOX360 }, + { 0x0738, 0x4743, "Mad Catz Beat Pad Pro", MAP_DPAD_TO_BUTTONS, XTYPE_XBOX }, + { 0x0738, 0x4758, "Mad Catz Arcade Game Stick", MAP_TRIGGERS_TO_BUTTONS, XTYPE_XBOX360 }, + { 0x0738, 0x4a01, "Mad Catz FightStick TE 2", MAP_TRIGGERS_TO_BUTTONS, XTYPE_XBOXONE }, { 0x0738, 0x6040, "Mad Catz Beat Pad Pro", MAP_DPAD_TO_BUTTONS, XTYPE_XBOX }, + { 0x0738, 0x9871, "Mad Catz Portable Drum", 0, XTYPE_XBOX360 }, { 0x0738, 0xb726, "Mad Catz Xbox controller - MW2", 0, XTYPE_XBOX360 }, + { 0x0738, 0xb738, "Mad Catz MVC2TE Stick 2", MAP_TRIGGERS_TO_BUTTONS, XTYPE_XBOX360 }, { 0x0738, 0xbeef, "Mad Catz JOYTECH NEO SE Advanced GamePad", XTYPE_XBOX360 }, { 0x0738, 0xcb02, "Saitek Cyborg Rumble Pad - PC/Xbox 360", 0, XTYPE_XBOX360 }, { 0x0738, 0xcb03, "Saitek P3200 Rumble Pad - PC/Xbox 360", 0, XTYPE_XBOX360 }, + { 0x0738, 0xcb29, "Saitek Aviator Stick AV8R02", 0, XTYPE_XBOX360 }, { 0x0738, 0xf738, "Super SFIV FightStick TE S", 0, XTYPE_XBOX360 }, + { 0x07ff, 0xffff, "Mad Catz GamePad", 0, XTYPE_XBOX360 }, + { 0x0c12, 0x0005, "Intec wireless", 0, XTYPE_XBOX }, + { 0x0c12, 0x8801, "Nyko Xbox Controller", 0, XTYPE_XBOX }, { 0x0c12, 0x8802, "Zeroplus Xbox Controller", 0, XTYPE_XBOX }, { 0x0c12, 0x8809, "RedOctane Xbox Dance Pad", DANCEPAD_MAP_CONFIG, XTYPE_XBOX }, { 0x0c12, 0x880a, "Pelican Eclipse PL-2023", 0, XTYPE_XBOX }, @@ -163,32 +206,66 @@ static const struct xpad_device { { 0x0c12, 0x9902, "HAMA VibraX - *FAULTY HARDWARE*", 0, XTYPE_XBOX }, { 0x0d2f, 0x0002, "Andamiro Pump It Up pad", MAP_DPAD_TO_BUTTONS, XTYPE_XBOX }, { 0x0e4c, 0x1097, "Radica Gamester Controller", 0, XTYPE_XBOX }, + { 0x0e4c, 0x1103, "Radica Gamester Reflex", MAP_TRIGGERS_TO_BUTTONS, XTYPE_XBOX }, { 0x0e4c, 0x2390, "Radica Games Jtech Controller", 0, XTYPE_XBOX }, + { 0x0e4c, 0x3510, "Radica Gamester", 0, XTYPE_XBOX }, { 0x0e6f, 0x0003, "Logic3 Freebird wireless Controller", 0, XTYPE_XBOX }, { 0x0e6f, 0x0005, "Eclipse wireless Controller", 0, XTYPE_XBOX }, { 0x0e6f, 0x0006, "Edge wireless Controller", 0, XTYPE_XBOX }, + { 0x0e6f, 0x0008, "After Glow Pro Controller", 0, XTYPE_XBOX }, { 0x0e6f, 0x0105, "HSM3 Xbox360 dancepad", MAP_DPAD_TO_BUTTONS, XTYPE_XBOX360 }, { 0x0e6f, 0x0113, "Afterglow AX.1 Gamepad for Xbox 360", 0, XTYPE_XBOX360 }, + { 0x0e6f, 0x011f, "Rock Candy Gamepad Wired Controller", 0, XTYPE_XBOX360 }, + { 0x0e6f, 0x0131, "PDP EA Sports Controller", 0, XTYPE_XBOX360 }, + { 0x0e6f, 0x0133, "Xbox 360 Wired Controller", 0, XTYPE_XBOX360 }, + { 0x0e6f, 0x0139, "Afterglow Prismatic Wired Controller", 0, XTYPE_XBOXONE }, + { 0x0e6f, 0x013a, "PDP Xbox One Controller", 0, XTYPE_XBOXONE }, + { 0x0e6f, 0x0146, "Rock Candy Wired Controller for Xbox One", 0, XTYPE_XBOXONE }, + { 0x0e6f, 0x0147, "PDP Marvel Xbox One Controller", 0, XTYPE_XBOXONE }, + { 0x0e6f, 0x015c, "PDP Xbox One Arcade Stick", MAP_TRIGGERS_TO_BUTTONS, XTYPE_XBOXONE }, + { 0x0e6f, 0x0161, "PDP Xbox One Controller", 0, XTYPE_XBOXONE }, + { 0x0e6f, 0x0162, "PDP Xbox One Controller", 0, XTYPE_XBOXONE }, + { 0x0e6f, 0x0163, "PDP Xbox One Controller", 0, XTYPE_XBOXONE }, + { 0x0e6f, 0x0164, "PDP Battlefield One", 0, XTYPE_XBOXONE }, + { 0x0e6f, 0x0165, "PDP Titanfall 2", 0, XTYPE_XBOXONE }, { 0x0e6f, 0x0201, "Pelican PL-3601 'TSZ' Wired Xbox 360 Controller", 0, XTYPE_XBOX360 }, { 0x0e6f, 0x0213, "Afterglow Gamepad for Xbox 360", 0, XTYPE_XBOX360 }, { 0x0e6f, 0x021f, "Rock Candy Gamepad for Xbox 360", 0, XTYPE_XBOX360 }, + { 0x0e6f, 0x0246, "Rock Candy Gamepad for Xbox One 2015", 0, XTYPE_XBOXONE }, + { 0x0e6f, 0x02ab, "PDP Controller for Xbox One", 0, XTYPE_XBOXONE }, + { 0x0e6f, 0x02a4, "PDP Wired Controller for Xbox One - Stealth Series", 0, XTYPE_XBOXONE }, + { 0x0e6f, 0x02a6, "PDP Wired Controller for Xbox One - Camo Series", 0, XTYPE_XBOXONE }, { 0x0e6f, 0x0301, "Logic3 Controller", 0, XTYPE_XBOX360 }, + { 0x0e6f, 0x0346, "Rock Candy Gamepad for Xbox One 2016", 0, XTYPE_XBOXONE }, { 0x0e6f, 0x0401, "Logic3 Controller", 0, XTYPE_XBOX360 }, + { 0x0e6f, 0x0413, "Afterglow AX.1 Gamepad for Xbox 360", 0, XTYPE_XBOX360 }, + { 0x0e6f, 0x0501, "PDP Xbox 360 Controller", 0, XTYPE_XBOX360 }, + { 0x0e6f, 0xf900, "PDP Afterglow AX.1", 0, XTYPE_XBOX360 }, { 0x0e8f, 0x0201, "SmartJoy Frag Xpad/PS2 adaptor", 0, XTYPE_XBOX }, { 0x0e8f, 0x3008, "Generic xbox control (dealextreme)", 0, XTYPE_XBOX }, { 0x0f0d, 0x000a, "Hori Co. DOA4 FightStick", 0, XTYPE_XBOX360 }, + { 0x0f0d, 0x000c, "Hori PadEX Turbo", 0, XTYPE_XBOX360 }, { 0x0f0d, 0x000d, "Hori Fighting Stick EX2", MAP_TRIGGERS_TO_BUTTONS, XTYPE_XBOX360 }, { 0x0f0d, 0x0016, "Hori Real Arcade Pro.EX", MAP_TRIGGERS_TO_BUTTONS, XTYPE_XBOX360 }, + { 0x0f0d, 0x001b, "Hori Real Arcade Pro VX", MAP_TRIGGERS_TO_BUTTONS, XTYPE_XBOX360 }, + { 0x0f0d, 0x0063, "Hori Real Arcade Pro Hayabusa (USA) Xbox One", MAP_TRIGGERS_TO_BUTTONS, XTYPE_XBOXONE }, + { 0x0f0d, 0x0067, "HORIPAD ONE", 0, XTYPE_XBOXONE }, + { 0x0f0d, 0x0078, "Hori Real Arcade Pro V Kai Xbox One", MAP_TRIGGERS_TO_BUTTONS, XTYPE_XBOXONE }, + { 0x0f30, 0x010b, "Philips Recoil", 0, XTYPE_XBOX }, { 0x0f30, 0x0202, "Joytech Advanced Controller", 0, XTYPE_XBOX }, { 0x0f30, 0x8888, "BigBen XBMiniPad Controller", 0, XTYPE_XBOX }, { 0x102c, 0xff0c, "Joytech Wireless Advanced Controller", 0, XTYPE_XBOX }, + { 0x11c9, 0x55f0, "Nacon GC-100XF", 0, XTYPE_XBOX360 }, { 0x12ab, 0x0004, "Honey Bee Xbox360 dancepad", MAP_DPAD_TO_BUTTONS, XTYPE_XBOX360 }, { 0x12ab, 0x0301, "PDP AFTERGLOW AX.1", 0, XTYPE_XBOX360 }, + { 0x12ab, 0x0303, "Mortal Kombat Klassic FightStick", MAP_TRIGGERS_TO_BUTTONS, XTYPE_XBOX360 }, { 0x12ab, 0x8809, "Xbox DDR dancepad", MAP_DPAD_TO_BUTTONS, XTYPE_XBOX }, { 0x1430, 0x4748, "RedOctane Guitar Hero X-plorer", 0, XTYPE_XBOX360 }, { 0x1430, 0x8888, "TX6500+ Dance Pad (first generation)", MAP_DPAD_TO_BUTTONS, XTYPE_XBOX }, + { 0x1430, 0xf801, "RedOctane Controller", 0, XTYPE_XBOX360 }, { 0x146b, 0x0601, "BigBen Interactive XBOX 360 Controller", 0, XTYPE_XBOX360 }, { 0x1532, 0x0037, "Razer Sabertooth", 0, XTYPE_XBOX360 }, + { 0x1532, 0x0a00, "Razer Atrox Arcade Stick", MAP_TRIGGERS_TO_BUTTONS, XTYPE_XBOXONE }, { 0x1532, 0x0a03, "Razer Wildcat", 0, XTYPE_XBOXONE }, { 0x15e4, 0x3f00, "Power A Mini Pro Elite", 0, XTYPE_XBOX360 }, { 0x15e4, 0x3f0a, "Xbox Airflo wired controller", 0, XTYPE_XBOX360 }, @@ -196,24 +273,67 @@ static const struct xpad_device { { 0x162e, 0xbeef, "Joytech Neo-Se Take2", 0, XTYPE_XBOX360 }, { 0x1689, 0xfd00, "Razer Onza Tournament Edition", 0, XTYPE_XBOX360 }, { 0x1689, 0xfd01, "Razer Onza Classic Edition", 0, XTYPE_XBOX360 }, - { 0x24c6, 0x5d04, "Razer Sabertooth", 0, XTYPE_XBOX360 }, + { 0x1689, 0xfe00, "Razer Sabertooth", 0, XTYPE_XBOX360 }, { 0x1bad, 0x0002, "Harmonix Rock Band Guitar", 0, XTYPE_XBOX360 }, { 0x1bad, 0x0003, "Harmonix Rock Band Drumkit", MAP_DPAD_TO_BUTTONS, XTYPE_XBOX360 }, + { 0x1bad, 0x0130, "Ion Drum Rocker", MAP_DPAD_TO_BUTTONS, XTYPE_XBOX360 }, { 0x1bad, 0xf016, "Mad Catz Xbox 360 Controller", 0, XTYPE_XBOX360 }, + { 0x1bad, 0xf018, "Mad Catz Street Fighter IV SE Fighting Stick", MAP_TRIGGERS_TO_BUTTONS, XTYPE_XBOX360 }, + { 0x1bad, 0xf019, "Mad Catz Brawlstick for Xbox 360", MAP_TRIGGERS_TO_BUTTONS, XTYPE_XBOX360 }, + { 0x1bad, 0xf021, "Mad Cats Ghost Recon FS GamePad", 0, XTYPE_XBOX360 }, { 0x1bad, 0xf023, "MLG Pro Circuit Controller (Xbox)", 0, XTYPE_XBOX360 }, + { 0x1bad, 0xf025, "Mad Catz Call Of Duty", 0, XTYPE_XBOX360 }, + { 0x1bad, 0xf027, "Mad Catz FPS Pro", 0, XTYPE_XBOX360 }, { 0x1bad, 0xf028, "Street Fighter IV FightPad", 0, XTYPE_XBOX360 }, + { 0x1bad, 0xf02e, "Mad Catz Fightpad", MAP_TRIGGERS_TO_BUTTONS, XTYPE_XBOX360 }, + { 0x1bad, 0xf030, "Mad Catz Xbox 360 MC2 MicroCon Racing Wheel", 0, XTYPE_XBOX360 }, + { 0x1bad, 0xf036, "Mad Catz MicroCon GamePad Pro", 0, XTYPE_XBOX360 }, { 0x1bad, 0xf038, "Street Fighter IV FightStick TE", 0, XTYPE_XBOX360 }, + { 0x1bad, 0xf039, "Mad Catz MvC2 TE", MAP_TRIGGERS_TO_BUTTONS, XTYPE_XBOX360 }, + { 0x1bad, 0xf03a, "Mad Catz SFxT Fightstick Pro", MAP_TRIGGERS_TO_BUTTONS, XTYPE_XBOX360 }, + { 0x1bad, 0xf03d, "Street Fighter IV Arcade Stick TE - Chun Li", MAP_TRIGGERS_TO_BUTTONS, XTYPE_XBOX360 }, + { 0x1bad, 0xf03e, "Mad Catz MLG FightStick TE", MAP_TRIGGERS_TO_BUTTONS, XTYPE_XBOX360 }, + { 0x1bad, 0xf03f, "Mad Catz FightStick SoulCaliber", MAP_TRIGGERS_TO_BUTTONS, XTYPE_XBOX360 }, + { 0x1bad, 0xf042, "Mad Catz FightStick TES+", MAP_TRIGGERS_TO_BUTTONS, XTYPE_XBOX360 }, + { 0x1bad, 0xf080, "Mad Catz FightStick TE2", MAP_TRIGGERS_TO_BUTTONS, XTYPE_XBOX360 }, + { 0x1bad, 0xf501, "HoriPad EX2 Turbo", 0, XTYPE_XBOX360 }, + { 0x1bad, 0xf502, "Hori Real Arcade Pro.VX SA", MAP_TRIGGERS_TO_BUTTONS, XTYPE_XBOX360 }, + { 0x1bad, 0xf503, "Hori Fighting Stick VX", MAP_TRIGGERS_TO_BUTTONS, XTYPE_XBOX360 }, + { 0x1bad, 0xf504, "Hori Real Arcade Pro. EX", MAP_TRIGGERS_TO_BUTTONS, XTYPE_XBOX360 }, + { 0x1bad, 0xf505, "Hori Fighting Stick EX2B", MAP_TRIGGERS_TO_BUTTONS, XTYPE_XBOX360 }, + { 0x1bad, 0xf506, "Hori Real Arcade Pro.EX Premium VLX", 0, XTYPE_XBOX360 }, { 0x1bad, 0xf900, "Harmonix Xbox 360 Controller", 0, XTYPE_XBOX360 }, { 0x1bad, 0xf901, "Gamestop Xbox 360 Controller", 0, XTYPE_XBOX360 }, { 0x1bad, 0xf903, "Tron Xbox 360 controller", 0, XTYPE_XBOX360 }, + { 0x1bad, 0xf904, "PDP Versus Fighting Pad", 0, XTYPE_XBOX360 }, + { 0x1bad, 0xf906, "MortalKombat FightStick", MAP_TRIGGERS_TO_BUTTONS, XTYPE_XBOX360 }, + { 0x1bad, 0xfa01, "MadCatz GamePad", 0, XTYPE_XBOX360 }, + { 0x1bad, 0xfd00, "Razer Onza TE", 0, XTYPE_XBOX360 }, + { 0x1bad, 0xfd01, "Razer Onza", 0, XTYPE_XBOX360 }, { 0x24c6, 0x5000, "Razer Atrox Arcade Stick", MAP_TRIGGERS_TO_BUTTONS, XTYPE_XBOX360 }, { 0x24c6, 0x5300, "PowerA MINI PROEX Controller", 0, XTYPE_XBOX360 }, { 0x24c6, 0x5303, "Xbox Airflo wired controller", 0, XTYPE_XBOX360 }, + { 0x24c6, 0x530a, "Xbox 360 Pro EX Controller", 0, XTYPE_XBOX360 }, + { 0x24c6, 0x531a, "PowerA Pro Ex", 0, XTYPE_XBOX360 }, + { 0x24c6, 0x5397, "FUS1ON Tournament Controller", 0, XTYPE_XBOX360 }, + { 0x24c6, 0x541a, "PowerA Xbox One Mini Wired Controller", 0, XTYPE_XBOXONE }, + { 0x24c6, 0x542a, "Xbox ONE spectra", 0, XTYPE_XBOXONE }, + { 0x24c6, 0x543a, "PowerA Xbox One wired controller", 0, XTYPE_XBOXONE }, { 0x24c6, 0x5500, "Hori XBOX 360 EX 2 with Turbo", 0, XTYPE_XBOX360 }, { 0x24c6, 0x5501, "Hori Real Arcade Pro VX-SA", 0, XTYPE_XBOX360 }, + { 0x24c6, 0x5502, "Hori Fighting Stick VX Alt", MAP_TRIGGERS_TO_BUTTONS, XTYPE_XBOX360 }, + { 0x24c6, 0x5503, "Hori Fighting Edge", MAP_TRIGGERS_TO_BUTTONS, XTYPE_XBOX360 }, { 0x24c6, 0x5506, "Hori SOULCALIBUR V Stick", 0, XTYPE_XBOX360 }, + { 0x24c6, 0x550d, "Hori GEM Xbox controller", 0, XTYPE_XBOX360 }, + { 0x24c6, 0x550e, "Hori Real Arcade Pro V Kai 360", MAP_TRIGGERS_TO_BUTTONS, XTYPE_XBOX360 }, + { 0x24c6, 0x551a, "PowerA FUSION Pro Controller", 0, XTYPE_XBOXONE }, + { 0x24c6, 0x561a, "PowerA FUSION Controller", 0, XTYPE_XBOXONE }, + { 0x24c6, 0x5b00, "ThrustMaster Ferrari 458 Racing Wheel", 0, XTYPE_XBOX360 }, { 0x24c6, 0x5b02, "Thrustmaster, Inc. GPX Controller", 0, XTYPE_XBOX360 }, { 0x24c6, 0x5b03, "Thrustmaster Ferrari 458 Racing Wheel", 0, XTYPE_XBOX360 }, + { 0x24c6, 0x5d04, "Razer Sabertooth", 0, XTYPE_XBOX360 }, + { 0x24c6, 0xfafe, "Rock Candy Gamepad for Xbox 360", 0, XTYPE_XBOX360 }, + { 0x3767, 0x0101, "Fanatec Speedster 3 Forceshock Wheel", 0, XTYPE_XBOX }, { 0xffff, 0xffff, "Chinese-made Xbox Controller", 0, XTYPE_XBOX }, { 0x0000, 0x0000, "Generic X-Box pad", 0, XTYPE_UNKNOWN } }; @@ -274,15 +394,15 @@ static const signed short xpad_abs_triggers[] = { * match against vendor id as well. Wired Xbox 360 devices have protocol 1, * wireless controllers have protocol 129. */ -#define XPAD_XBOX360_VENDOR_PROTOCOL(vend,pr) \ +#define XPAD_XBOX360_VENDOR_PROTOCOL(vend, pr) \ .match_flags = USB_DEVICE_ID_MATCH_VENDOR | USB_DEVICE_ID_MATCH_INT_INFO, \ .idVendor = (vend), \ .bInterfaceClass = USB_CLASS_VENDOR_SPEC, \ .bInterfaceSubClass = 93, \ .bInterfaceProtocol = (pr) #define XPAD_XBOX360_VENDOR(vend) \ - { XPAD_XBOX360_VENDOR_PROTOCOL(vend,1) }, \ - { XPAD_XBOX360_VENDOR_PROTOCOL(vend,129) } + { XPAD_XBOX360_VENDOR_PROTOCOL((vend), 1) }, \ + { XPAD_XBOX360_VENDOR_PROTOCOL((vend), 129) } /* The Xbox One controller uses subclass 71 and protocol 208. */ #define XPAD_XBOXONE_VENDOR_PROTOCOL(vend, pr) \ @@ -292,33 +412,134 @@ static const signed short xpad_abs_triggers[] = { .bInterfaceSubClass = 71, \ .bInterfaceProtocol = (pr) #define XPAD_XBOXONE_VENDOR(vend) \ - { XPAD_XBOXONE_VENDOR_PROTOCOL(vend, 208) } + { XPAD_XBOXONE_VENDOR_PROTOCOL((vend), 208) } -static struct usb_device_id xpad_table[] = { +static const struct usb_device_id xpad_table[] = { { USB_INTERFACE_INFO('X', 'B', 0) }, /* X-Box USB-IF not approved class */ + XPAD_XBOX360_VENDOR(0x0079), /* GPD Win 2 Controller */ XPAD_XBOX360_VENDOR(0x044f), /* Thrustmaster X-Box 360 controllers */ XPAD_XBOX360_VENDOR(0x045e), /* Microsoft X-Box 360 controllers */ XPAD_XBOXONE_VENDOR(0x045e), /* Microsoft X-Box One controllers */ XPAD_XBOX360_VENDOR(0x046d), /* Logitech X-Box 360 style controllers */ + XPAD_XBOX360_VENDOR(0x056e), /* Elecom JC-U3613M */ + XPAD_XBOX360_VENDOR(0x06a3), /* Saitek P3600 */ XPAD_XBOX360_VENDOR(0x0738), /* Mad Catz X-Box 360 controllers */ { USB_DEVICE(0x0738, 0x4540) }, /* Mad Catz Beat Pad */ + XPAD_XBOXONE_VENDOR(0x0738), /* Mad Catz FightStick TE 2 */ + XPAD_XBOX360_VENDOR(0x07ff), /* Mad Catz GamePad */ XPAD_XBOX360_VENDOR(0x0e6f), /* 0x0e6f X-Box 360 controllers */ + XPAD_XBOXONE_VENDOR(0x0e6f), /* 0x0e6f X-Box One controllers */ + XPAD_XBOX360_VENDOR(0x0f0d), /* Hori Controllers */ + XPAD_XBOXONE_VENDOR(0x0f0d), /* Hori Controllers */ + XPAD_XBOX360_VENDOR(0x11c9), /* Nacon GC100XF */ XPAD_XBOX360_VENDOR(0x12ab), /* X-Box 360 dance pads */ XPAD_XBOX360_VENDOR(0x1430), /* RedOctane X-Box 360 controllers */ XPAD_XBOX360_VENDOR(0x146b), /* BigBen Interactive Controllers */ - XPAD_XBOX360_VENDOR(0x1bad), /* Harminix Rock Band Guitar and Drums */ - XPAD_XBOX360_VENDOR(0x0f0d), /* Hori Controllers */ - XPAD_XBOX360_VENDOR(0x1689), /* Razer Onza */ - XPAD_XBOX360_VENDOR(0x24c6), /* PowerA Controllers */ XPAD_XBOX360_VENDOR(0x1532), /* Razer Sabertooth */ XPAD_XBOXONE_VENDOR(0x1532), /* Razer Wildcat */ XPAD_XBOX360_VENDOR(0x15e4), /* Numark X-Box 360 controllers */ XPAD_XBOX360_VENDOR(0x162e), /* Joytech X-Box 360 controllers */ + XPAD_XBOX360_VENDOR(0x1689), /* Razer Onza */ + XPAD_XBOX360_VENDOR(0x1bad), /* Harminix Rock Band Guitar and Drums */ + XPAD_XBOX360_VENDOR(0x24c6), /* PowerA Controllers */ + XPAD_XBOXONE_VENDOR(0x24c6), /* PowerA Controllers */ { } }; MODULE_DEVICE_TABLE(usb, xpad_table); +struct xboxone_init_packet { + u16 idVendor; + u16 idProduct; + const u8 *data; + u8 len; +}; + +#define XBOXONE_INIT_PKT(_vid, _pid, _data) \ + { \ + .idVendor = (_vid), \ + .idProduct = (_pid), \ + .data = (_data), \ + .len = ARRAY_SIZE(_data), \ + } + + +/* + * This packet is required for all Xbox One pads with 2015 + * or later firmware installed (or present from the factory). + */ +static const u8 xboxone_fw2015_init[] = { + 0x05, 0x20, 0x00, 0x01, 0x00 +}; + +/* + * This packet is required for the Titanfall 2 Xbox One pads + * (0x0e6f:0x0165) to finish initialization and for Hori pads + * (0x0f0d:0x0067) to make the analog sticks work. + */ +static const u8 xboxone_hori_init[] = { + 0x01, 0x20, 0x00, 0x09, 0x00, 0x04, 0x20, 0x3a, + 0x00, 0x00, 0x00, 0x80, 0x00 +}; + +/* + * This packet is required for most (all?) of the PDP pads to start + * sending input reports. These pads include: (0x0e6f:0x02ab), + * (0x0e6f:0x02a4), (0x0e6f:0x02a6). + */ +static const u8 xboxone_pdp_init1[] = { + 0x0a, 0x20, 0x00, 0x03, 0x00, 0x01, 0x14 +}; + +/* + * This packet is required for most (all?) of the PDP pads to start + * sending input reports. These pads include: (0x0e6f:0x02ab), + * (0x0e6f:0x02a4), (0x0e6f:0x02a6). + */ +static const u8 xboxone_pdp_init2[] = { + 0x06, 0x20, 0x00, 0x02, 0x01, 0x00 +}; + +/* + * A specific rumble packet is required for some PowerA pads to start + * sending input reports. One of those pads is (0x24c6:0x543a). + */ +static const u8 xboxone_rumblebegin_init[] = { + 0x09, 0x00, 0x00, 0x09, 0x00, 0x0F, 0x00, 0x00, + 0x1D, 0x1D, 0xFF, 0x00, 0x00 +}; + +/* + * A rumble packet with zero FF intensity will immediately + * terminate the rumbling required to init PowerA pads. + * This should happen fast enough that the motors don't + * spin up to enough speed to actually vibrate the gamepad. + */ +static const u8 xboxone_rumbleend_init[] = { + 0x09, 0x00, 0x00, 0x09, 0x00, 0x0F, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00 +}; + +/* + * This specifies the selection of init packets that a gamepad + * will be sent on init *and* the order in which they will be + * sent. The correct sequence number will be added when the + * packet is going to be sent. + */ +static const struct xboxone_init_packet xboxone_init_packets[] = { + XBOXONE_INIT_PKT(0x0e6f, 0x0165, xboxone_hori_init), + XBOXONE_INIT_PKT(0x0f0d, 0x0067, xboxone_hori_init), + XBOXONE_INIT_PKT(0x0000, 0x0000, xboxone_fw2015_init), + XBOXONE_INIT_PKT(0x0e6f, 0x0000, xboxone_pdp_init1), + XBOXONE_INIT_PKT(0x0e6f, 0x0000, xboxone_pdp_init2), + XBOXONE_INIT_PKT(0x24c6, 0x541a, xboxone_rumblebegin_init), + XBOXONE_INIT_PKT(0x24c6, 0x542a, xboxone_rumblebegin_init), + XBOXONE_INIT_PKT(0x24c6, 0x543a, xboxone_rumblebegin_init), + XBOXONE_INIT_PKT(0x24c6, 0x541a, xboxone_rumbleend_init), + XBOXONE_INIT_PKT(0x24c6, 0x542a, xboxone_rumbleend_init), + XBOXONE_INIT_PKT(0x24c6, 0x543a, xboxone_rumbleend_init), +}; + struct xpad_output_packet { u8 data[XPAD_PKT_LEN]; u8 len; @@ -334,23 +555,28 @@ struct xpad_output_packet { struct usb_xpad { struct input_dev *dev; /* input device interface */ + struct input_dev __rcu *x360w_dev; struct usb_device *udev; /* usb device */ struct usb_interface *intf; /* usb interface */ - int pad_present; + bool pad_present; + bool input_created; struct urb *irq_in; /* urb for interrupt in report */ unsigned char *idata; /* input data */ dma_addr_t idata_dma; struct urb *irq_out; /* urb for interrupt out report */ + struct usb_anchor irq_out_anchor; bool irq_out_active; /* we must not use an active URB */ + u8 odata_serial; /* serial number for xbox one protocol */ unsigned char *odata; /* output data */ dma_addr_t odata_dma; spinlock_t odata_lock; struct xpad_output_packet out_packets[XPAD_NUM_OUT_PACKETS]; int last_out_packet; + int init_seq; #if defined(CONFIG_JOYSTICK_XPAD_LEDS) struct xpad_led *led; @@ -362,8 +588,13 @@ struct usb_xpad { int xtype; /* type of xbox device */ int pad_nr; /* the order x360 pads were attached */ const char *name; /* name of the device */ + struct work_struct work; /* init/remove device from callback */ }; +static int xpad_init_input(struct usb_xpad *xpad); +static void xpad_deinit_input(struct usb_xpad *xpad); +static void xpadone_ack_mode_report(struct usb_xpad *xpad, u8 seq_num); + /* * xpad_process_packet * @@ -443,10 +674,12 @@ static void xpad_process_packet(struct usb_xpad *xpad, u16 cmd, unsigned char *d * http://www.free60.org/wiki/Gamepad */ -static void xpad360_process_packet(struct usb_xpad *xpad, +static void xpad360_process_packet(struct usb_xpad *xpad, struct input_dev *dev, u16 cmd, unsigned char *data) { - struct input_dev *dev = xpad->dev; + /* valid pad data */ + if (data[0] != 0x00) + return; /* digital pad */ if (xpad->mapping & MAP_DPAD_TO_BUTTONS) { @@ -514,7 +747,30 @@ static void xpad360_process_packet(struct usb_xpad *xpad, input_sync(dev); } -static void xpad_identify_controller(struct usb_xpad *xpad); +static void xpad_presence_work(struct work_struct *work) +{ + struct usb_xpad *xpad = container_of(work, struct usb_xpad, work); + int error; + + if (xpad->pad_present) { + error = xpad_init_input(xpad); + if (error) { + /* complain only, not much else we can do here */ + dev_err(&xpad->dev->dev, + "unable to init device: %d\n", error); + } else { + rcu_assign_pointer(xpad->x360w_dev, xpad->dev); + } + } else { + RCU_INIT_POINTER(xpad->x360w_dev, NULL); + synchronize_rcu(); + /* + * Now that we are sure xpad360w_process_packet is not + * using input device we can get rid of it. + */ + xpad_deinit_input(xpad); + } +} /* * xpad360w_process_packet @@ -532,35 +788,61 @@ static void xpad_identify_controller(struct usb_xpad *xpad); */ static void xpad360w_process_packet(struct usb_xpad *xpad, u16 cmd, unsigned char *data) { + struct input_dev *dev; + bool present; + /* Presence change */ if (data[0] & 0x08) { - if (data[1] & 0x80) { - xpad->pad_present = 1; - /* - * Light up the segment corresponding to - * controller number. - */ - xpad_identify_controller(xpad); - } else - xpad->pad_present = 0; + present = (data[1] & 0x80) != 0; + + if (xpad->pad_present != present) { + xpad->pad_present = present; + schedule_work(&xpad->work); + } } /* Valid pad data */ - if (!(data[1] & 0x1)) + if (data[1] != 0x1) return; - xpad360_process_packet(xpad, cmd, &data[4]); + rcu_read_lock(); + dev = rcu_dereference(xpad->x360w_dev); + if (dev) + xpad360_process_packet(xpad, dev, cmd, &data[4]); + rcu_read_unlock(); } /* - * xpadone_process_buttons + * xpadone_process_packet * - * Process a button update packet from an Xbox one controller. + * Completes a request by converting the data into events for the + * input subsystem. This version is for the Xbox One controller. + * + * The report format was gleaned from + * https://github.com/kylelemons/xbox/blob/master/xbox.go */ -static void xpadone_process_buttons(struct usb_xpad *xpad, - struct input_dev *dev, - unsigned char *data) +static void xpadone_process_packet(struct usb_xpad *xpad, u16 cmd, unsigned char *data) { + struct input_dev *dev = xpad->dev; + + /* the xbox button has its own special report */ + if (data[0] == 0X07) { + /* + * The Xbox One S controller requires these reports to be + * acked otherwise it continues sending them forever and + * won't report further mode button events. + */ + if (data[1] == 0x30) + xpadone_ack_mode_report(xpad, data[2]); + + input_report_key(dev, BTN_MODE, data[4] & 0x01); + input_sync(dev); + return; + } + /* check invalid packet */ + else if (data[0] != 0X20) + return; + /* menu/view buttons */ input_report_key(dev, BTN_START, data[4] & 0x04); input_report_key(dev, BTN_SELECT, data[4] & 0x08); @@ -623,34 +905,6 @@ static void xpadone_process_buttons(struct usb_xpad *xpad, input_sync(dev); } -/* - * xpadone_process_packet - * - * Completes a request by converting the data into events for the - * input subsystem. This version is for the Xbox One controller. - * - * The report format was gleaned from - * https://github.com/kylelemons/xbox/blob/master/xbox.go - */ - -static void xpadone_process_packet(struct usb_xpad *xpad, - u16 cmd, unsigned char *data) -{ - struct input_dev *dev = xpad->dev; - - switch (data[0]) { - case 0x20: - xpadone_process_buttons(xpad, dev, data); - break; - - case 0x07: - /* the xbox button has its own special report */ - input_report_key(dev, BTN_MODE, data[4] & 0x01); - input_sync(dev); - break; - } -} - static void xpad_irq_in(struct urb *urb) { struct usb_xpad *xpad = urb->context; @@ -678,7 +932,7 @@ static void xpad_irq_in(struct urb *urb) switch (xpad->xtype) { case XTYPE_XBOX360: - xpad360_process_packet(xpad, 0, xpad->idata); + xpad360_process_packet(xpad, xpad->dev, 0, xpad->idata); break; case XTYPE_XBOX360W: xpad360w_process_packet(xpad, 0, xpad->idata); @@ -698,11 +952,47 @@ exit: } /* Callers must hold xpad->odata_lock spinlock */ +static bool xpad_prepare_next_init_packet(struct usb_xpad *xpad) +{ + const struct xboxone_init_packet *init_packet; + + if (xpad->xtype != XTYPE_XBOXONE) + return false; + + /* Perform initialization sequence for Xbox One pads that require it */ + while (xpad->init_seq < ARRAY_SIZE(xboxone_init_packets)) { + init_packet = &xboxone_init_packets[xpad->init_seq++]; + + if (init_packet->idVendor != 0 && + init_packet->idVendor != xpad->dev->id.vendor) + continue; + + if (init_packet->idProduct != 0 && + init_packet->idProduct != xpad->dev->id.product) + continue; + + /* This packet applies to our device, so prepare to send it */ + memcpy(xpad->odata, init_packet->data, init_packet->len); + xpad->irq_out->transfer_buffer_length = init_packet->len; + + /* Update packet with current sequence number */ + xpad->odata[2] = xpad->odata_serial++; + return true; + } + + return false; +} + +/* Callers must hold xpad->odata_lock spinlock */ static bool xpad_prepare_next_out_packet(struct usb_xpad *xpad) { struct xpad_output_packet *pkt, *packet = NULL; int i; + /* We may have init packets to send before we can send user commands */ + if (xpad_prepare_next_init_packet(xpad)) + return true; + for (i = 0; i < XPAD_NUM_OUT_PACKETS; i++) { if (++xpad->last_out_packet >= XPAD_NUM_OUT_PACKETS) xpad->last_out_packet = 0; @@ -733,11 +1023,13 @@ static int xpad_try_sending_next_out_packet(struct usb_xpad *xpad) int error; if (!xpad->irq_out_active && xpad_prepare_next_out_packet(xpad)) { + usb_anchor_urb(xpad->irq_out, &xpad->irq_out_anchor); error = usb_submit_urb(xpad->irq_out, GFP_ATOMIC); if (error) { dev_err(&xpad->intf->dev, "%s - usb_submit_urb failed with result %d\n", __func__, error); + usb_unanchor_urb(xpad->irq_out); return -EIO; } @@ -779,11 +1071,13 @@ static void xpad_irq_out(struct urb *urb) } if (xpad->irq_out_active) { + usb_anchor_urb(urb, &xpad->irq_out_anchor); error = usb_submit_urb(urb, GFP_ATOMIC); if (error) { dev_err(dev, "%s - usb_submit_urb failed with result %d\n", __func__, error); + usb_unanchor_urb(urb); xpad->irq_out_active = false; } } @@ -791,34 +1085,29 @@ static void xpad_irq_out(struct urb *urb) spin_unlock_irqrestore(&xpad->odata_lock, flags); } -static int xpad_init_output(struct usb_interface *intf, struct usb_xpad *xpad) +static int xpad_init_output(struct usb_interface *intf, struct usb_xpad *xpad, + struct usb_endpoint_descriptor *ep_irq_out) { - struct usb_endpoint_descriptor *ep_irq_out; - int ep_irq_out_idx; int error; if (xpad->xtype == XTYPE_UNKNOWN) return 0; + init_usb_anchor(&xpad->irq_out_anchor); + xpad->odata = usb_alloc_coherent(xpad->udev, XPAD_PKT_LEN, GFP_KERNEL, &xpad->odata_dma); - if (!xpad->odata) { - error = -ENOMEM; - goto fail1; - } + if (!xpad->odata) + return -ENOMEM; spin_lock_init(&xpad->odata_lock); xpad->irq_out = usb_alloc_urb(0, GFP_KERNEL); if (!xpad->irq_out) { error = -ENOMEM; - goto fail2; + goto err_free_coherent; } - /* Xbox One controller has in/out endpoints swapped. */ - ep_irq_out_idx = xpad->xtype == XTYPE_XBOXONE ? 0 : 1; - ep_irq_out = &intf->cur_altsetting->endpoint[ep_irq_out_idx].desc; - usb_fill_int_urb(xpad->irq_out, xpad->udev, usb_sndintpipe(xpad->udev, ep_irq_out->bEndpointAddress), xpad->odata, XPAD_PKT_LEN, @@ -828,14 +1117,21 @@ static int xpad_init_output(struct usb_interface *intf, struct usb_xpad *xpad) return 0; - fail2: usb_free_coherent(xpad->udev, XPAD_PKT_LEN, xpad->odata, xpad->odata_dma); - fail1: return error; +err_free_coherent: + usb_free_coherent(xpad->udev, XPAD_PKT_LEN, xpad->odata, xpad->odata_dma); + return error; } static void xpad_stop_output(struct usb_xpad *xpad) { - if (xpad->xtype != XTYPE_UNKNOWN) - usb_kill_urb(xpad->irq_out); + if (xpad->xtype != XTYPE_UNKNOWN) { + if (!usb_wait_anchor_empty_timeout(&xpad->irq_out_anchor, + 5000)) { + dev_warn(&xpad->intf->dev, + "timed out waiting for output URB to complete, killing\n"); + usb_kill_anchored_urbs(&xpad->irq_out_anchor); + } + } } static void xpad_deinit_output(struct usb_xpad *xpad) @@ -882,21 +1178,17 @@ static int xpad_inquiry_pad_presence(struct usb_xpad *xpad) static int xpad_start_xbox_one(struct usb_xpad *xpad) { - struct xpad_output_packet *packet = - &xpad->out_packets[XPAD_OUT_CMD_IDX]; unsigned long flags; int retval; spin_lock_irqsave(&xpad->odata_lock, flags); - /* Xbox one controller needs to be initialized. */ - packet->data[0] = 0x05; - packet->data[1] = 0x20; - packet->len = 2; - packet->pending = true; - - /* Reset the sequence so we send out start packet first */ - xpad->last_out_packet = -1; + /* + * Begin the init sequence by attempting to send a packet. + * We will cycle through the init packet sequence before + * sending any packets from the output ring. + */ + xpad->init_seq = 0; retval = xpad_try_sending_next_out_packet(xpad); spin_unlock_irqrestore(&xpad->odata_lock, flags); @@ -904,6 +1196,30 @@ static int xpad_start_xbox_one(struct usb_xpad *xpad) return retval; } +static void xpadone_ack_mode_report(struct usb_xpad *xpad, u8 seq_num) +{ + unsigned long flags; + struct xpad_output_packet *packet = + &xpad->out_packets[XPAD_OUT_CMD_IDX]; + static const u8 mode_report_ack[] = { + 0x01, 0x20, 0x00, 0x09, 0x00, 0x07, 0x20, 0x02, + 0x00, 0x00, 0x00, 0x00, 0x00 + }; + + spin_lock_irqsave(&xpad->odata_lock, flags); + + packet->len = sizeof(mode_report_ack); + memcpy(packet->data, mode_report_ack, packet->len); + packet->data[2] = seq_num; + packet->pending = true; + + /* Reset the sequence so we send out the ack now */ + xpad->last_out_packet = -1; + xpad_try_sending_next_out_packet(xpad); + + spin_unlock_irqrestore(&xpad->odata_lock, flags); +} + #ifdef CONFIG_JOYSTICK_XPAD_FF static int xpad_play_effect(struct input_dev *dev, void *data, struct ff_effect *effect) { @@ -966,18 +1282,19 @@ static int xpad_play_effect(struct input_dev *dev, void *data, struct ff_effect case XTYPE_XBOXONE: packet->data[0] = 0x09; /* activate rumble */ - packet->data[1] = 0x08; - packet->data[2] = 0x00; - packet->data[3] = 0x08; /* continuous effect */ - packet->data[4] = 0x00; /* simple rumble mode */ - packet->data[5] = 0x03; /* L and R actuator only */ - packet->data[6] = 0x00; /* TODO: LT actuator */ - packet->data[7] = 0x00; /* TODO: RT actuator */ - packet->data[8] = strong / 256; /* left actuator */ - packet->data[9] = weak / 256; /* right actuator */ - packet->data[10] = 0x80; /* length of pulse */ - packet->data[11] = 0x00; /* stop period of pulse */ - packet->len = 12; + packet->data[1] = 0x00; + packet->data[2] = xpad->odata_serial++; + packet->data[3] = 0x09; + packet->data[4] = 0x00; + packet->data[5] = 0x0F; + packet->data[6] = 0x00; + packet->data[7] = 0x00; + packet->data[8] = strong / 512; /* left actuator */ + packet->data[9] = weak / 512; /* right actuator */ + packet->data[10] = 0xFF; /* on period */ + packet->data[11] = 0x00; /* off period */ + packet->data[12] = 0xFF; /* repeat count */ + packet->len = 13; packet->pending = true; break; @@ -1090,7 +1407,7 @@ static void xpad_send_led_command(struct usb_xpad *xpad, int command) */ static void xpad_identify_controller(struct usb_xpad *xpad) { - xpad_send_led_command(xpad, (xpad->pad_nr % 4) + 2); + led_set_brightness(&xpad->led->led_cdev, (xpad->pad_nr % 4) + 2); } static void xpad_led_set(struct led_classdev *led_cdev, @@ -1127,19 +1444,13 @@ static int xpad_led_probe(struct usb_xpad *xpad) led_cdev = &led->led_cdev; led_cdev->name = led->name; led_cdev->brightness_set = xpad_led_set; + led_cdev->flags = LED_CORE_SUSPENDRESUME; error = led_classdev_register(&xpad->udev->dev, led_cdev); if (error) goto err_free_id; - if (xpad->xtype == XTYPE_XBOX360) { - /* - * Light up the segment corresponding to controller - * number on wired devices. On wireless we'll do that - * when they respond to "presence" packet. - */ - xpad_identify_controller(xpad); - } + xpad_identify_controller(xpad); return 0; @@ -1164,41 +1475,110 @@ static void xpad_led_disconnect(struct usb_xpad *xpad) #else static int xpad_led_probe(struct usb_xpad *xpad) { return 0; } static void xpad_led_disconnect(struct usb_xpad *xpad) { } -static void xpad_identify_controller(struct usb_xpad *xpad) { } #endif -static int xpad_open(struct input_dev *dev) +static int xpad_start_input(struct usb_xpad *xpad) { - struct usb_xpad *xpad = input_get_drvdata(dev); - - /* URB was submitted in probe */ - if (xpad->xtype == XTYPE_XBOX360W) - return 0; + int error; - xpad->irq_in->dev = xpad->udev; if (usb_submit_urb(xpad->irq_in, GFP_KERNEL)) return -EIO; - if (xpad->xtype == XTYPE_XBOXONE) - return xpad_start_xbox_one(xpad); + if (xpad->xtype == XTYPE_XBOXONE) { + error = xpad_start_xbox_one(xpad); + if (error) { + usb_kill_urb(xpad->irq_in); + return error; + } + } return 0; } -static void xpad_close(struct input_dev *dev) +static void xpad_stop_input(struct usb_xpad *xpad) { - struct usb_xpad *xpad = input_get_drvdata(dev); + usb_kill_urb(xpad->irq_in); +} - if (xpad->xtype != XTYPE_XBOX360W) +static void xpad360w_poweroff_controller(struct usb_xpad *xpad) +{ + unsigned long flags; + struct xpad_output_packet *packet = + &xpad->out_packets[XPAD_OUT_CMD_IDX]; + + spin_lock_irqsave(&xpad->odata_lock, flags); + + packet->data[0] = 0x00; + packet->data[1] = 0x00; + packet->data[2] = 0x08; + packet->data[3] = 0xC0; + packet->data[4] = 0x00; + packet->data[5] = 0x00; + packet->data[6] = 0x00; + packet->data[7] = 0x00; + packet->data[8] = 0x00; + packet->data[9] = 0x00; + packet->data[10] = 0x00; + packet->data[11] = 0x00; + packet->len = 12; + packet->pending = true; + + /* Reset the sequence so we send out poweroff now */ + xpad->last_out_packet = -1; + xpad_try_sending_next_out_packet(xpad); + + spin_unlock_irqrestore(&xpad->odata_lock, flags); +} + +static int xpad360w_start_input(struct usb_xpad *xpad) +{ + int error; + + error = usb_submit_urb(xpad->irq_in, GFP_KERNEL); + if (error) + return -EIO; + + /* + * Send presence packet. + * This will force the controller to resend connection packets. + * This is useful in the case we activate the module after the + * adapter has been plugged in, as it won't automatically + * send us info about the controllers. + */ + error = xpad_inquiry_pad_presence(xpad); + if (error) { usb_kill_urb(xpad->irq_in); + return error; + } - xpad_stop_output(xpad); + return 0; +} + +static void xpad360w_stop_input(struct usb_xpad *xpad) +{ + usb_kill_urb(xpad->irq_in); + + /* Make sure we are done with presence work if it was scheduled */ + flush_work(&xpad->work); +} + +static int xpad_open(struct input_dev *dev) +{ + struct usb_xpad *xpad = input_get_drvdata(dev); + + return xpad_start_input(xpad); +} + +static void xpad_close(struct input_dev *dev) +{ + struct usb_xpad *xpad = input_get_drvdata(dev); + + xpad_stop_input(xpad); } static void xpad_set_up_abs(struct input_dev *input_dev, signed short abs) { struct usb_xpad *xpad = input_get_drvdata(input_dev); - set_bit(abs, input_dev->absbit); switch (abs) { case ABS_X: @@ -1218,13 +1598,19 @@ static void xpad_set_up_abs(struct input_dev *input_dev, signed short abs) case ABS_HAT0Y: /* the d-pad (only if dpad is mapped to axes */ input_set_abs_params(input_dev, abs, -1, 1, 0, 0); break; + default: + input_set_abs_params(input_dev, abs, 0, 0, 0, 0); + break; } } static void xpad_deinit_input(struct usb_xpad *xpad) { - xpad_led_disconnect(xpad); - input_unregister_device(xpad->dev); + if (xpad->input_created) { + xpad->input_created = false; + xpad_led_disconnect(xpad); + input_unregister_device(xpad->dev); + } } static int xpad_init_input(struct usb_xpad *xpad) @@ -1250,13 +1636,12 @@ static int xpad_init_input(struct usb_xpad *xpad) input_set_drvdata(input_dev, xpad); - input_dev->open = xpad_open; - input_dev->close = xpad_close; - - __set_bit(EV_KEY, input_dev->evbit); + if (xpad->xtype != XTYPE_XBOX360W) { + input_dev->open = xpad_open; + input_dev->close = xpad_close; + } if (!(xpad->mapping & MAP_STICKS_TO_NULL)) { - __set_bit(EV_ABS, input_dev->evbit); /* set up axes */ for (i = 0; xpad_abs[i] >= 0; i++) xpad_set_up_abs(input_dev, xpad_abs[i]); @@ -1264,21 +1649,22 @@ static int xpad_init_input(struct usb_xpad *xpad) /* set up standard buttons */ for (i = 0; xpad_common_btn[i] >= 0; i++) - __set_bit(xpad_common_btn[i], input_dev->keybit); + input_set_capability(input_dev, EV_KEY, xpad_common_btn[i]); /* set up model-specific ones */ if (xpad->xtype == XTYPE_XBOX360 || xpad->xtype == XTYPE_XBOX360W || xpad->xtype == XTYPE_XBOXONE) { for (i = 0; xpad360_btn[i] >= 0; i++) - __set_bit(xpad360_btn[i], input_dev->keybit); + input_set_capability(input_dev, EV_KEY, xpad360_btn[i]); } else { for (i = 0; xpad_btn[i] >= 0; i++) - __set_bit(xpad_btn[i], input_dev->keybit); + input_set_capability(input_dev, EV_KEY, xpad_btn[i]); } if (xpad->mapping & MAP_DPAD_TO_BUTTONS) { for (i = 0; xpad_btn_pad[i] >= 0; i++) - __set_bit(xpad_btn_pad[i], input_dev->keybit); + input_set_capability(input_dev, EV_KEY, + xpad_btn_pad[i]); } /* @@ -1295,7 +1681,8 @@ static int xpad_init_input(struct usb_xpad *xpad) if (xpad->mapping & MAP_TRIGGERS_TO_BUTTONS) { for (i = 0; xpad_btn_triggers[i] >= 0; i++) - __set_bit(xpad_btn_triggers[i], input_dev->keybit); + input_set_capability(input_dev, EV_KEY, + xpad_btn_triggers[i]); } else { for (i = 0; xpad_abs_triggers[i] >= 0; i++) xpad_set_up_abs(input_dev, xpad_abs_triggers[i]); @@ -1313,6 +1700,7 @@ static int xpad_init_input(struct usb_xpad *xpad) if (error) goto err_disconnect_led; + xpad->input_created = true; return 0; err_disconnect_led: @@ -1328,8 +1716,7 @@ static int xpad_probe(struct usb_interface *intf, const struct usb_device_id *id { struct usb_device *udev = interface_to_usbdev(intf); struct usb_xpad *xpad; - struct usb_endpoint_descriptor *ep_irq_in; - int ep_irq_in_idx; + struct usb_endpoint_descriptor *ep_irq_in, *ep_irq_out; int i, error; if (intf->cur_altsetting->desc.bNumEndpoints != 2) @@ -1366,6 +1753,7 @@ static int xpad_probe(struct usb_interface *intf, const struct usb_device_id *id xpad->mapping = xpad_device[i].mapping; xpad->xtype = xpad_device[i].xtype; xpad->name = xpad_device[i].name; + INIT_WORK(&xpad->work, xpad_presence_work); if (xpad->xtype == XTYPE_UNKNOWN) { if (intf->cur_altsetting->desc.bInterfaceClass == USB_CLASS_VENDOR_SPEC) { @@ -1398,13 +1786,28 @@ static int xpad_probe(struct usb_interface *intf, const struct usb_device_id *id goto err_free_in_urb; } - error = xpad_init_output(intf, xpad); - if (error) + ep_irq_in = ep_irq_out = NULL; + + for (i = 0; i < 2; i++) { + struct usb_endpoint_descriptor *ep = + &intf->cur_altsetting->endpoint[i].desc; + + if (usb_endpoint_xfer_int(ep)) { + if (usb_endpoint_dir_in(ep)) + ep_irq_in = ep; + else + ep_irq_out = ep; + } + } + + if (!ep_irq_in || !ep_irq_out) { + error = -ENODEV; goto err_free_in_urb; + } - /* Xbox One controller has in/out endpoints swapped. */ - ep_irq_in_idx = xpad->xtype == XTYPE_XBOXONE ? 1 : 0; - ep_irq_in = &intf->cur_altsetting->endpoint[ep_irq_in_idx].desc; + error = xpad_init_output(intf, xpad, ep_irq_out); + if (error) + goto err_free_in_urb; usb_fill_int_urb(xpad->irq_in, udev, usb_rcvintpipe(udev, ep_irq_in->bEndpointAddress), @@ -1415,10 +1818,6 @@ static int xpad_probe(struct usb_interface *intf, const struct usb_device_id *id usb_set_intfdata(intf, xpad); - error = xpad_init_input(xpad); - if (error) - goto err_deinit_output; - if (xpad->xtype == XTYPE_XBOX360W) { /* * Submit the int URB immediately rather than waiting for open @@ -1427,28 +1826,24 @@ static int xpad_probe(struct usb_interface *intf, const struct usb_device_id *id * exactly the message that a controller has arrived that * we're waiting for. */ - xpad->irq_in->dev = xpad->udev; - error = usb_submit_urb(xpad->irq_in, GFP_KERNEL); + error = xpad360w_start_input(xpad); if (error) - goto err_deinit_input; - + goto err_deinit_output; /* - * Send presence packet. - * This will force the controller to resend connection packets. - * This is useful in the case we activate the module after the - * adapter has been plugged in, as it won't automatically - * send us info about the controllers. + * Wireless controllers require RESET_RESUME to work properly + * after suspend. Ideally this quirk should be in usb core + * quirk list, but we have too many vendors producing these + * controllers and we'd need to maintain 2 identical lists + * here in this driver and in usb core. */ - error = xpad_inquiry_pad_presence(xpad); + udev->quirks |= USB_QUIRK_RESET_RESUME; + } else { + error = xpad_init_input(xpad); if (error) - goto err_kill_in_urb; + goto err_deinit_output; } return 0; -err_kill_in_urb: - usb_kill_urb(xpad->irq_in); -err_deinit_input: - xpad_deinit_input(xpad); err_deinit_output: xpad_deinit_output(xpad); err_free_in_urb: @@ -1458,19 +1853,24 @@ err_free_idata: err_free_mem: kfree(xpad); return error; - } static void xpad_disconnect(struct usb_interface *intf) { - struct usb_xpad *xpad = usb_get_intfdata (intf); + struct usb_xpad *xpad = usb_get_intfdata(intf); + + if (xpad->xtype == XTYPE_XBOX360W) + xpad360w_stop_input(xpad); xpad_deinit_input(xpad); - xpad_deinit_output(xpad); - if (xpad->xtype == XTYPE_XBOX360W) { - usb_kill_urb(xpad->irq_in); - } + /* + * Now that both input device and LED device are gone we can + * stop output URB. + */ + xpad_stop_output(xpad); + + xpad_deinit_output(xpad); usb_free_urb(xpad->irq_in); usb_free_coherent(xpad->udev, XPAD_PKT_LEN, @@ -1481,10 +1881,72 @@ static void xpad_disconnect(struct usb_interface *intf) usb_set_intfdata(intf, NULL); } +static int xpad_suspend(struct usb_interface *intf, pm_message_t message) +{ + struct usb_xpad *xpad = usb_get_intfdata(intf); + struct input_dev *input = xpad->dev; + + if (xpad->xtype == XTYPE_XBOX360W) { + /* + * Wireless controllers always listen to input so + * they are notified when controller shows up + * or goes away. + */ + xpad360w_stop_input(xpad); + + /* + * The wireless adapter is going off now, so the + * gamepads are going to become disconnected. + * Unless explicitly disabled, power them down + * so they don't just sit there flashing. + */ + if (auto_poweroff && xpad->pad_present) + xpad360w_poweroff_controller(xpad); + } else { + mutex_lock(&input->mutex); + if (input->users) + xpad_stop_input(xpad); + mutex_unlock(&input->mutex); + } + + xpad_stop_output(xpad); + + return 0; +} + +static int xpad_resume(struct usb_interface *intf) +{ + struct usb_xpad *xpad = usb_get_intfdata(intf); + struct input_dev *input = xpad->dev; + int retval = 0; + + if (xpad->xtype == XTYPE_XBOX360W) { + retval = xpad360w_start_input(xpad); + } else { + mutex_lock(&input->mutex); + if (input->users) { + retval = xpad_start_input(xpad); + } else if (xpad->xtype == XTYPE_XBOXONE) { + /* + * Even if there are no users, we'll send Xbox One pads + * the startup sequence so they don't sit there and + * blink until somebody opens the input device again. + */ + retval = xpad_start_xbox_one(xpad); + } + mutex_unlock(&input->mutex); + } + + return retval; +} + static struct usb_driver xpad_driver = { .name = "xpad", .probe = xpad_probe, .disconnect = xpad_disconnect, + .suspend = xpad_suspend, + .resume = xpad_resume, + .reset_resume = xpad_resume, .id_table = xpad_table, }; diff --git a/drivers/input/keyboard/matrix_keypad.c b/drivers/input/keyboard/matrix_keypad.c index 795fa353de7c..c64d87442a62 100644 --- a/drivers/input/keyboard/matrix_keypad.c +++ b/drivers/input/keyboard/matrix_keypad.c @@ -405,7 +405,7 @@ matrix_keypad_parse_dt(struct device *dev) struct matrix_keypad_platform_data *pdata; struct device_node *np = dev->of_node; unsigned int *gpios; - int i, nrow, ncol; + int ret, i, nrow, ncol; if (!np) { dev_err(dev, "device lacks DT data\n"); @@ -447,12 +447,19 @@ matrix_keypad_parse_dt(struct device *dev) return ERR_PTR(-ENOMEM); } - for (i = 0; i < pdata->num_row_gpios; i++) - gpios[i] = of_get_named_gpio(np, "row-gpios", i); + for (i = 0; i < nrow; i++) { + ret = of_get_named_gpio(np, "row-gpios", i); + if (ret < 0) + return ERR_PTR(ret); + gpios[i] = ret; + } - for (i = 0; i < pdata->num_col_gpios; i++) - gpios[pdata->num_row_gpios + i] = - of_get_named_gpio(np, "col-gpios", i); + for (i = 0; i < ncol; i++) { + ret = of_get_named_gpio(np, "col-gpios", i); + if (ret < 0) + return ERR_PTR(ret); + gpios[nrow + i] = ret; + } pdata->row_gpios = gpios; pdata->col_gpios = &gpios[pdata->num_row_gpios]; @@ -479,10 +486,8 @@ static int matrix_keypad_probe(struct platform_device *pdev) pdata = dev_get_platdata(&pdev->dev); if (!pdata) { pdata = matrix_keypad_parse_dt(&pdev->dev); - if (IS_ERR(pdata)) { - dev_err(&pdev->dev, "no platform data defined\n"); + if (IS_ERR(pdata)) return PTR_ERR(pdata); - } } else if (!pdata->keymap_data) { dev_err(&pdev->dev, "no keymap data defined\n"); return -EINVAL; diff --git a/drivers/input/mouse/elan_i2c_core.c b/drivers/input/mouse/elan_i2c_core.c index b3119589a444..471984ec2db0 100644 --- a/drivers/input/mouse/elan_i2c_core.c +++ b/drivers/input/mouse/elan_i2c_core.c @@ -1253,6 +1253,9 @@ static const struct acpi_device_id elan_acpi_id[] = { { "ELAN0618", 0 }, { "ELAN061C", 0 }, { "ELAN061D", 0 }, + { "ELAN061E", 0 }, + { "ELAN0620", 0 }, + { "ELAN0621", 0 }, { "ELAN0622", 0 }, { "ELAN1000", 0 }, { } diff --git a/drivers/iommu/intel-iommu.c b/drivers/iommu/intel-iommu.c index 49b266433f4c..7feaa82f8c7c 100644 --- a/drivers/iommu/intel-iommu.c +++ b/drivers/iommu/intel-iommu.c @@ -2977,7 +2977,7 @@ static int copy_context_table(struct intel_iommu *iommu, } if (old_ce) - iounmap(old_ce); + memunmap(old_ce); ret = 0; if (devfn < 0x80) diff --git a/drivers/iommu/intel-svm.c b/drivers/iommu/intel-svm.c index 10068a481e22..cbde03e509c1 100644 --- a/drivers/iommu/intel-svm.c +++ b/drivers/iommu/intel-svm.c @@ -558,7 +558,7 @@ static irqreturn_t prq_event_thread(int irq, void *d) pr_err("%s: Page request without PASID: %08llx %08llx\n", iommu->name, ((unsigned long long *)req)[0], ((unsigned long long *)req)[1]); - goto bad_req; + goto no_pasid; } if (!svm || svm->pasid != req->pasid) { diff --git a/drivers/iommu/ipmmu-vmsa.c b/drivers/iommu/ipmmu-vmsa.c index 624e7ff76166..9101be1a6b59 100644 --- a/drivers/iommu/ipmmu-vmsa.c +++ b/drivers/iommu/ipmmu-vmsa.c @@ -372,6 +372,9 @@ static int ipmmu_domain_init_context(struct ipmmu_vmsa_domain *domain) static void ipmmu_domain_destroy_context(struct ipmmu_vmsa_domain *domain) { + if (!domain->mmu) + return; + /* * Disable the context. Flush the TLB as required when modifying the * context registers. diff --git a/drivers/leds/led-class.c b/drivers/leds/led-class.c index ba20b8e42fbd..cdb9018c3f02 100644 --- a/drivers/leds/led-class.c +++ b/drivers/leds/led-class.c @@ -265,12 +265,13 @@ void led_classdev_unregister(struct led_classdev *led_cdev) up_write(&led_cdev->trigger_lock); #endif - cancel_work_sync(&led_cdev->set_brightness_work); - /* Stop blinking */ led_stop_software_blink(led_cdev); + led_set_brightness(led_cdev, LED_OFF); + flush_work(&led_cdev->set_brightness_work); + device_unregister(led_cdev->dev); down_write(&leds_list_lock); diff --git a/drivers/leds/leds-gpio.c b/drivers/leds/leds-gpio.c index 5db4515a4fd7..df186b38da78 100644 --- a/drivers/leds/leds-gpio.c +++ b/drivers/leds/leds-gpio.c @@ -118,8 +118,8 @@ static int create_gpio_led(const struct gpio_led *template, return ret; led_dat->gpiod = gpio_to_desc(template->gpio); - if (IS_ERR(led_dat->gpiod)) - return PTR_ERR(led_dat->gpiod); + if (!led_dat->gpiod) + return -EINVAL; } led_dat->cdev.name = template->name; diff --git a/drivers/leds/leds-pwm.c b/drivers/leds/leds-pwm.c index 1d07e3e83d29..3149dbece146 100644 --- a/drivers/leds/leds-pwm.c +++ b/drivers/leds/leds-pwm.c @@ -132,6 +132,7 @@ static int led_pwm_add(struct device *dev, struct led_pwm_priv *priv, ret = led_classdev_register(dev, &led_data->cdev); if (ret == 0) { priv->num_leds++; + led_pwm_set(&led_data->cdev, led_data->cdev.brightness); } else { dev_err(dev, "failed to register PWM led for %s: %d\n", led->name, ret); diff --git a/drivers/media/platform/msm/ais/isp/msm_isp_util.c b/drivers/media/platform/msm/ais/isp/msm_isp_util.c index 83b3dfe68932..8753592d3dbf 100644 --- a/drivers/media/platform/msm/ais/isp/msm_isp_util.c +++ b/drivers/media/platform/msm/ais/isp/msm_isp_util.c @@ -24,6 +24,7 @@ #define CREATE_TRACE_POINTS #include "trace/events/msm_cam.h" #include "sensor/cci/msm_early_cam.h" +#include <soc/qcom/early_domain.h> #define MAX_ISP_V4l2_EVENTS 100 #define MAX_ISP_REG_LIST 100 @@ -2292,6 +2293,8 @@ int msm_isp_open_node(struct v4l2_subdev *sd, struct v4l2_subdev_fh *fh) vfe_dev->isp_raw2_debug = 0; /* Postpone hardware changes until early camera is complete */ + /* Signal LK early camera that Kernel started running AIS */ + request_early_service_shutdown(EARLY_CAMERA); msm_early_camera_wait(); if (vfe_dev->hw_info->vfe_ops.core_ops.init_hw(vfe_dev) < 0) { diff --git a/drivers/media/platform/msm/ais/sensor/cci/msm_early_cam.c b/drivers/media/platform/msm/ais/sensor/cci/msm_early_cam.c index 1329511440c4..7329dd9ddb27 100644 --- a/drivers/media/platform/msm/ais/sensor/cci/msm_early_cam.c +++ b/drivers/media/platform/msm/ais/sensor/cci/msm_early_cam.c @@ -17,7 +17,7 @@ #include <linux/of.h> #include <linux/of_gpio.h> #include <linux/of_platform.h> -#include <linux/iopoll.h> +#include <soc/qcom/early_domain.h> #include "msm_sd.h" #include "msm_early_cam.h" #include "msm_cam_cci_hwreg.h" @@ -39,12 +39,6 @@ static struct platform_driver msm_early_camera_driver; static struct early_cam_device *new_early_cam_dev; -#define MMSS_A_VFE_0_BASE 0x00A10000 -#define MMSS_A_VFE_0_SIZE 0x1000 -#define EARLY_CAMERA_SIGNAL_DONE 0xa5a5a5a5 -#define EARLY_CAMERA_SIGNAL_DISABLED 0 -#define MMSS_A_VFE_0_SPARE 0xC84 - int msm_early_cam_disable_clocks(void) { int rc = 0; @@ -263,14 +257,11 @@ int msm_ais_disable_clocks(void) void msm_early_camera_wait(void) { - u32 val = 0; - void __iomem *base; - - base = ioremap(MMSS_A_VFE_0_BASE, MMSS_A_VFE_0_SIZE); - readl_poll_timeout(base + MMSS_A_VFE_0_SPARE, val, - ((val == EARLY_CAMERA_SIGNAL_DONE) - || (val == EARLY_CAMERA_SIGNAL_DISABLED)), 0, 0); - iounmap(base); + while (get_early_service_status(EARLY_CAMERA)) { + CDBG("%s: wait for signal of early camera from LK", + __func__); + msleep(500); + } } static int msm_early_cam_probe(struct platform_device *pdev) diff --git a/drivers/media/platform/msm/camera_v2/sensor/laser_led/msm_laser_led.c b/drivers/media/platform/msm/camera_v2/sensor/laser_led/msm_laser_led.c index c368f081f97b..68d3c71601eb 100644 --- a/drivers/media/platform/msm/camera_v2/sensor/laser_led/msm_laser_led.c +++ b/drivers/media/platform/msm/camera_v2/sensor/laser_led/msm_laser_led.c @@ -1,4 +1,4 @@ -/* Copyright (c) 2017, The Linux Foundation. All rights reserved. +/* Copyright (c) 2017-2018, The Linux Foundation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 and @@ -70,18 +70,15 @@ static struct msm_camera_i2c_fn_t msm_sensor_cci_func_tbl = { .i2c_util = msm_sensor_cci_i2c_util, .i2c_poll = msm_camera_cci_i2c_poll, }; -#ifdef CONFIG_COMPAT -static int32_t msm_laser_led_init( - struct msm_laser_led_ctrl_t *laser_led_ctrl, - struct msm_laser_led_cfg_data_t32 __user *laser_led_data) -#else + static int32_t msm_laser_led_init( struct msm_laser_led_ctrl_t *laser_led_ctrl, - struct msm_laser_led_cfg_data_t __user *laser_led_data) -#endif + void __user *argp) { int32_t rc = -EFAULT; struct msm_camera_cci_client *cci_client = NULL; + struct msm_laser_led_cfg_data_t __user *laser_led_data = + (struct msm_laser_led_cfg_data_t __user *) argp; CDBG("Enter\n"); @@ -263,6 +260,53 @@ static int32_t msm_laser_led_control32( return rc; } + +static int32_t msm_laser_led_init32( + struct msm_laser_led_ctrl_t *laser_led_ctrl, + void __user *argp) +{ + int32_t rc = -EFAULT; + struct msm_laser_led_cfg_data_t32 __user *laser_led_data = + (struct msm_laser_led_cfg_data_t32 __user *) argp; + struct msm_camera_cci_client *cci_client = NULL; + + CDBG("Enter\n"); + + if (laser_led_ctrl->laser_led_state == MSM_CAMERA_LASER_LED_INIT) { + pr_err("Invalid laser_led state = %d\n", + laser_led_ctrl->laser_led_state); + return 0; + } + + rc = laser_led_ctrl->i2c_client.i2c_func_tbl->i2c_util( + &laser_led_ctrl->i2c_client, MSM_CCI_INIT); + if (rc < 0) + pr_err("cci_init failed\n"); + + cci_client = laser_led_ctrl->i2c_client.cci_client; + + if (copy_from_user(&(cci_client->sid), + &(laser_led_data->i2c_addr), + sizeof(uint16_t))) { + pr_err("%s:%d failed\n", __func__, __LINE__); + return -EFAULT; + } + cci_client->sid = cci_client->sid >> 1; + cci_client->retries = 3; + cci_client->id_map = 0; + + if (copy_from_user(&(cci_client->i2c_freq_mode), + &(laser_led_data->i2c_freq_mode), + sizeof(enum i2c_freq_mode_t))) { + pr_err("%s:%d failed\n", __func__, __LINE__); + return -EFAULT; + } + + laser_led_ctrl->laser_led_state = MSM_CAMERA_LASER_LED_INIT; + + CDBG("Exit\n"); + return 0; +} #endif static int32_t msm_laser_led_control( @@ -381,7 +425,12 @@ static int32_t msm_laser_led_config(struct msm_laser_led_ctrl_t *laser_led_ctrl, switch (cfg_type) { case CFG_LASER_LED_INIT: - rc = msm_laser_led_init(laser_led_ctrl, laser_led_data); +#ifdef CONFIG_COMPAT + if (is_compat_task()) + rc = msm_laser_led_init32(laser_led_ctrl, argp); + else +#endif + rc = msm_laser_led_init(laser_led_ctrl, argp); break; case CFG_LASER_LED_CONTROL: #ifdef CONFIG_COMPAT diff --git a/drivers/media/usb/em28xx/em28xx-dvb.c b/drivers/media/usb/em28xx/em28xx-dvb.c index 357be76c7a55..5502a0fb94fd 100644 --- a/drivers/media/usb/em28xx/em28xx-dvb.c +++ b/drivers/media/usb/em28xx/em28xx-dvb.c @@ -1806,6 +1806,8 @@ static int em28xx_dvb_fini(struct em28xx *dev) } } + em28xx_unregister_dvb(dvb); + /* remove I2C SEC */ client = dvb->i2c_client_sec; if (client) { @@ -1827,7 +1829,6 @@ static int em28xx_dvb_fini(struct em28xx *dev) i2c_unregister_device(client); } - em28xx_unregister_dvb(dvb); kfree(dvb); dev->dvb = NULL; kref_put(&dev->ref, em28xx_free_device); diff --git a/drivers/misc/mic/scif/scif_rma.c b/drivers/misc/mic/scif/scif_rma.c index 6a451bd65bf3..8bd63128d536 100644 --- a/drivers/misc/mic/scif/scif_rma.c +++ b/drivers/misc/mic/scif/scif_rma.c @@ -414,7 +414,7 @@ static int scif_create_remote_lookup(struct scif_dev *remote_dev, if (err) goto error_window; err = scif_map_page(&window->num_pages_lookup.lookup[j], - vmalloc_dma_phys ? + vmalloc_num_pages ? vmalloc_to_page(&window->num_pages[i]) : virt_to_page(&window->num_pages[i]), remote_dev); diff --git a/drivers/net/can/dev.c b/drivers/net/can/dev.c index eab132778e67..1dbee1cb3df9 100644 --- a/drivers/net/can/dev.c +++ b/drivers/net/can/dev.c @@ -423,6 +423,34 @@ void can_put_echo_skb(struct sk_buff *skb, struct net_device *dev, } EXPORT_SYMBOL_GPL(can_put_echo_skb); +struct sk_buff *__can_get_echo_skb(struct net_device *dev, unsigned int idx, u8 *len_ptr) +{ + struct can_priv *priv = netdev_priv(dev); + struct sk_buff *skb = priv->echo_skb[idx]; + struct canfd_frame *cf; + + if (idx >= priv->echo_skb_max) { + netdev_err(dev, "%s: BUG! Trying to access can_priv::echo_skb out of bounds (%u/max %u)\n", + __func__, idx, priv->echo_skb_max); + return NULL; + } + + if (!skb) { + netdev_err(dev, "%s: BUG! Trying to echo non existing skb: can_priv::echo_skb[%u]\n", + __func__, idx); + return NULL; + } + + /* Using "struct canfd_frame::len" for the frame + * length is supported on both CAN and CANFD frames. + */ + cf = (struct canfd_frame *)skb->data; + *len_ptr = cf->len; + priv->echo_skb[idx] = NULL; + + return skb; +} + /* * Get the skb from the stack and loop it back locally * @@ -432,22 +460,16 @@ EXPORT_SYMBOL_GPL(can_put_echo_skb); */ unsigned int can_get_echo_skb(struct net_device *dev, unsigned int idx) { - struct can_priv *priv = netdev_priv(dev); - - BUG_ON(idx >= priv->echo_skb_max); - - if (priv->echo_skb[idx]) { - struct sk_buff *skb = priv->echo_skb[idx]; - struct can_frame *cf = (struct can_frame *)skb->data; - u8 dlc = cf->can_dlc; + struct sk_buff *skb; + u8 len; - netif_rx(priv->echo_skb[idx]); - priv->echo_skb[idx] = NULL; + skb = __can_get_echo_skb(dev, idx, &len); + if (!skb) + return 0; - return dlc; - } + netif_rx(skb); - return 0; + return len; } EXPORT_SYMBOL_GPL(can_get_echo_skb); diff --git a/drivers/net/can/rcar_can.c b/drivers/net/can/rcar_can.c index bc46be39549d..9d93492ddfcc 100644 --- a/drivers/net/can/rcar_can.c +++ b/drivers/net/can/rcar_can.c @@ -24,6 +24,9 @@ #define RCAR_CAN_DRV_NAME "rcar_can" +#define RCAR_SUPPORTED_CLOCKS (BIT(CLKR_CLKP1) | BIT(CLKR_CLKP2) | \ + BIT(CLKR_CLKEXT)) + /* Mailbox configuration: * mailbox 60 - 63 - Rx FIFO mailboxes * mailbox 56 - 59 - Tx FIFO mailboxes @@ -789,7 +792,7 @@ static int rcar_can_probe(struct platform_device *pdev) goto fail_clk; } - if (clock_select >= ARRAY_SIZE(clock_names)) { + if (!(BIT(clock_select) & RCAR_SUPPORTED_CLOCKS)) { err = -EINVAL; dev_err(&pdev->dev, "invalid CAN clock selected\n"); goto fail_clk; diff --git a/drivers/net/ethernet/amd/sunlance.c b/drivers/net/ethernet/amd/sunlance.c index 7847638bdd22..8914170fccff 100644 --- a/drivers/net/ethernet/amd/sunlance.c +++ b/drivers/net/ethernet/amd/sunlance.c @@ -1419,7 +1419,7 @@ static int sparc_lance_probe_one(struct platform_device *op, prop = of_get_property(nd, "tpe-link-test?", NULL); if (!prop) - goto no_link_test; + goto node_put; if (strcmp(prop, "true")) { printk(KERN_NOTICE "SunLance: warning: overriding option " @@ -1428,6 +1428,8 @@ static int sparc_lance_probe_one(struct platform_device *op, "to ecd@skynet.be\n"); auxio_set_lte(AUXIO_LTE_ON); } +node_put: + of_node_put(nd); no_link_test: lp->auto_select = 1; lp->tpe = 0; diff --git a/drivers/net/ethernet/broadcom/bnx2x/bnx2x.h b/drivers/net/ethernet/broadcom/bnx2x/bnx2x.h index 1ea068815419..2491cdc2535c 100644 --- a/drivers/net/ethernet/broadcom/bnx2x/bnx2x.h +++ b/drivers/net/ethernet/broadcom/bnx2x/bnx2x.h @@ -2291,6 +2291,13 @@ void bnx2x_igu_clear_sb_gen(struct bnx2x *bp, u8 func, u8 idu_sb_id, #define PMF_DMAE_C(bp) (BP_PORT(bp) * MAX_DMAE_C_PER_PORT + \ E1HVN_MAX) +/* Following is the DMAE channel number allocation for the clients. + * MFW: OCBB/OCSD implementations use DMAE channels 14/15 respectively. + * Driver: 0-3 and 8-11 (for PF dmae operations) + * 4 and 12 (for stats requests) + */ +#define BNX2X_FW_DMAE_C 13 /* Channel for FW DMAE operations */ + /* PCIE link and speed */ #define PCICFG_LINK_WIDTH 0x1f00000 #define PCICFG_LINK_WIDTH_SHIFT 20 diff --git a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_sp.c b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_sp.c index ff702a707a91..343e3366d751 100644 --- a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_sp.c +++ b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_sp.c @@ -5931,6 +5931,7 @@ static inline int bnx2x_func_send_start(struct bnx2x *bp, rdata->sd_vlan_tag = cpu_to_le16(start_params->sd_vlan_tag); rdata->path_id = BP_PATH(bp); rdata->network_cos_mode = start_params->network_cos_mode; + rdata->dmae_cmd_id = BNX2X_FW_DMAE_C; rdata->vxlan_dst_port = cpu_to_le16(start_params->vxlan_dst_port); rdata->geneve_dst_port = cpu_to_le16(start_params->geneve_dst_port); diff --git a/drivers/net/ethernet/broadcom/genet/bcmmii.c b/drivers/net/ethernet/broadcom/genet/bcmmii.c index 4c73feca4842..0565efad6e6e 100644 --- a/drivers/net/ethernet/broadcom/genet/bcmmii.c +++ b/drivers/net/ethernet/broadcom/genet/bcmmii.c @@ -491,7 +491,7 @@ static int bcmgenet_mii_of_init(struct bcmgenet_priv *priv) if (!compat) return -ENOMEM; - priv->mdio_dn = of_find_compatible_node(dn, NULL, compat); + priv->mdio_dn = of_get_compatible_child(dn, compat); kfree(compat); if (!priv->mdio_dn) { dev_err(kdev, "unable to find MDIO bus node\n"); diff --git a/drivers/net/ethernet/faraday/ftmac100.c b/drivers/net/ethernet/faraday/ftmac100.c index dce5f7b7f772..05e1f923f49e 100644 --- a/drivers/net/ethernet/faraday/ftmac100.c +++ b/drivers/net/ethernet/faraday/ftmac100.c @@ -865,11 +865,10 @@ static irqreturn_t ftmac100_interrupt(int irq, void *dev_id) struct net_device *netdev = dev_id; struct ftmac100 *priv = netdev_priv(netdev); - if (likely(netif_running(netdev))) { - /* Disable interrupts for polling */ - ftmac100_disable_all_int(priv); + /* Disable interrupts for polling */ + ftmac100_disable_all_int(priv); + if (likely(netif_running(netdev))) napi_schedule(&priv->napi); - } return IRQ_HANDLED; } diff --git a/drivers/net/ethernet/mellanox/mlx4/alloc.c b/drivers/net/ethernet/mellanox/mlx4/alloc.c index 0c51c69f802f..a4912b11e54f 100644 --- a/drivers/net/ethernet/mellanox/mlx4/alloc.c +++ b/drivers/net/ethernet/mellanox/mlx4/alloc.c @@ -339,7 +339,7 @@ void mlx4_zone_allocator_destroy(struct mlx4_zone_allocator *zone_alloc) static u32 __mlx4_alloc_from_zone(struct mlx4_zone_entry *zone, int count, int align, u32 skip_mask, u32 *puid) { - u32 uid; + u32 uid = 0; u32 res; struct mlx4_zone_allocator *zone_alloc = zone->allocator; struct mlx4_zone_entry *curr_node; diff --git a/drivers/net/ethernet/mellanox/mlx4/mlx4.h b/drivers/net/ethernet/mellanox/mlx4/mlx4.h index f5fdbd53d052..db40387ffaf6 100644 --- a/drivers/net/ethernet/mellanox/mlx4/mlx4.h +++ b/drivers/net/ethernet/mellanox/mlx4/mlx4.h @@ -537,8 +537,8 @@ struct slave_list { struct resource_allocator { spinlock_t alloc_lock; /* protect quotas */ union { - int res_reserved; - int res_port_rsvd[MLX4_MAX_PORTS]; + unsigned int res_reserved; + unsigned int res_port_rsvd[MLX4_MAX_PORTS]; }; union { int res_free; diff --git a/drivers/net/ethernet/mellanox/mlx4/mr.c b/drivers/net/ethernet/mellanox/mlx4/mr.c index 93195191f45b..53833c06696f 100644 --- a/drivers/net/ethernet/mellanox/mlx4/mr.c +++ b/drivers/net/ethernet/mellanox/mlx4/mr.c @@ -366,6 +366,7 @@ int mlx4_mr_hw_write_mpt(struct mlx4_dev *dev, struct mlx4_mr *mmr, container_of((void *)mpt_entry, struct mlx4_cmd_mailbox, buf); + (*mpt_entry)->lkey = 0; err = mlx4_SW2HW_MPT(dev, mailbox, key); } diff --git a/drivers/net/ethernet/qlogic/qed/qed_int.c b/drivers/net/ethernet/qlogic/qed/qed_int.c index 9cc9d62c1fec..8b15a018d625 100644 --- a/drivers/net/ethernet/qlogic/qed/qed_int.c +++ b/drivers/net/ethernet/qlogic/qed/qed_int.c @@ -177,6 +177,8 @@ static int qed_int_attentions(struct qed_hwfn *p_hwfn) */ do { index = p_sb_attn->sb_index; + /* finish reading index before the loop condition */ + dma_rmb(); attn_bits = le32_to_cpu(p_sb_attn->atten_bits); attn_acks = le32_to_cpu(p_sb_attn->atten_ack); } while (index != p_sb_attn->sb_index); diff --git a/drivers/net/ethernet/qlogic/qed/qed_main.c b/drivers/net/ethernet/qlogic/qed/qed_main.c index 35e1468d8196..b8ae6ed5c7ba 100644 --- a/drivers/net/ethernet/qlogic/qed/qed_main.c +++ b/drivers/net/ethernet/qlogic/qed/qed_main.c @@ -1124,9 +1124,9 @@ static int qed_drain(struct qed_dev *cdev) return -EBUSY; } rc = qed_mcp_drain(hwfn, ptt); + qed_ptt_release(hwfn, ptt); if (rc) return rc; - qed_ptt_release(hwfn, ptt); } return 0; diff --git a/drivers/net/rionet.c b/drivers/net/rionet.c index e7034c55e796..6ef9188384ce 100644 --- a/drivers/net/rionet.c +++ b/drivers/net/rionet.c @@ -215,9 +215,9 @@ static int rionet_start_xmit(struct sk_buff *skb, struct net_device *ndev) * it just report sending a packet to the target * (without actual packet transfer). */ - dev_kfree_skb_any(skb); ndev->stats.tx_packets++; ndev->stats.tx_bytes += skb->len; + dev_kfree_skb_any(skb); } } diff --git a/drivers/net/usb/ipheth.c b/drivers/net/usb/ipheth.c index 76465b117b72..f1f8227e7342 100644 --- a/drivers/net/usb/ipheth.c +++ b/drivers/net/usb/ipheth.c @@ -140,7 +140,6 @@ struct ipheth_device { struct usb_device *udev; struct usb_interface *intf; struct net_device *net; - struct sk_buff *tx_skb; struct urb *tx_urb; struct urb *rx_urb; unsigned char *tx_buf; @@ -229,6 +228,7 @@ static void ipheth_rcvbulk_callback(struct urb *urb) case -ENOENT: case -ECONNRESET: case -ESHUTDOWN: + case -EPROTO: return; case 0: break; @@ -280,7 +280,6 @@ static void ipheth_sndbulk_callback(struct urb *urb) dev_err(&dev->intf->dev, "%s: urb status: %d\n", __func__, status); - dev_kfree_skb_irq(dev->tx_skb); netif_wake_queue(dev->net); } @@ -410,7 +409,7 @@ static int ipheth_tx(struct sk_buff *skb, struct net_device *net) if (skb->len > IPHETH_BUF_SIZE) { WARN(1, "%s: skb too large: %d bytes\n", __func__, skb->len); dev->net->stats.tx_dropped++; - dev_kfree_skb_irq(skb); + dev_kfree_skb_any(skb); return NETDEV_TX_OK; } @@ -430,12 +429,11 @@ static int ipheth_tx(struct sk_buff *skb, struct net_device *net) dev_err(&dev->intf->dev, "%s: usb_submit_urb: %d\n", __func__, retval); dev->net->stats.tx_errors++; - dev_kfree_skb_irq(skb); + dev_kfree_skb_any(skb); } else { - dev->tx_skb = skb; - dev->net->stats.tx_packets++; dev->net->stats.tx_bytes += skb->len; + dev_consume_skb_any(skb); netif_stop_queue(net); } diff --git a/drivers/net/wireless/Kconfig b/drivers/net/wireless/Kconfig index 7945b1cd6244..b4c7b36117bd 100644 --- a/drivers/net/wireless/Kconfig +++ b/drivers/net/wireless/Kconfig @@ -256,6 +256,13 @@ config MAC80211_HWSIM To compile this driver as a module, choose M here: the module will be called mac80211_hwsim. If unsure, say N. +config VIRT_WIFI + tristate "Wifi wrapper for ethernet drivers" + depends on CFG80211 + ---help--- + This option adds support for ethernet connections to appear as if they + are wifi connections through a special rtnetlink device. + config MWL8K tristate "Marvell 88W8xxx PCI/PCIe Wireless support" depends on MAC80211 && PCI diff --git a/drivers/net/wireless/Makefile b/drivers/net/wireless/Makefile index f23a2fbc3afa..51f02058adf2 100644 --- a/drivers/net/wireless/Makefile +++ b/drivers/net/wireless/Makefile @@ -51,6 +51,8 @@ obj-$(CONFIG_ATH_CARDS) += ath/ obj-$(CONFIG_MAC80211_HWSIM) += mac80211_hwsim.o +obj-$(CONFIG_VIRT_WIFI) += virt_wifi.o + obj-$(CONFIG_WL_TI) += ti/ obj-$(CONFIG_MWIFIEX) += mwifiex/ diff --git a/drivers/net/wireless/ath/ath10k/mac.c b/drivers/net/wireless/ath/ath10k/mac.c index db0476c44b41..79c1a09a6965 100644 --- a/drivers/net/wireless/ath/ath10k/mac.c +++ b/drivers/net/wireless/ath/ath10k/mac.c @@ -5021,7 +5021,9 @@ static int ath10k_add_interface(struct ieee80211_hw *hw, } ar->free_vdev_map &= ~(1LL << arvif->vdev_id); + spin_lock_bh(&ar->data_lock); list_add(&arvif->list, &ar->arvifs); + spin_unlock_bh(&ar->data_lock); /* It makes no sense to have firmware do keepalives. mac80211 already * takes care of this with idle connection polling. @@ -5172,7 +5174,9 @@ err_peer_delete: err_vdev_delete: ath10k_wmi_vdev_delete(ar, arvif->vdev_id); ar->free_vdev_map |= 1LL << arvif->vdev_id; + spin_lock_bh(&ar->data_lock); list_del(&arvif->list); + spin_unlock_bh(&ar->data_lock); err: if (arvif->beacon_buf) { @@ -5219,7 +5223,9 @@ static void ath10k_remove_interface(struct ieee80211_hw *hw, arvif->vdev_id, ret); ar->free_vdev_map |= 1LL << arvif->vdev_id; + spin_lock_bh(&ar->data_lock); list_del(&arvif->list); + spin_unlock_bh(&ar->data_lock); if (arvif->vdev_type == WMI_VDEV_TYPE_AP || arvif->vdev_type == WMI_VDEV_TYPE_IBSS) { diff --git a/drivers/net/wireless/cw1200/wsm.c b/drivers/net/wireless/cw1200/wsm.c index 3dd46c78c1cc..5a595f9f47ff 100644 --- a/drivers/net/wireless/cw1200/wsm.c +++ b/drivers/net/wireless/cw1200/wsm.c @@ -1805,16 +1805,18 @@ static int wsm_buf_reserve(struct wsm_buf *buf, size_t extra_size) { size_t pos = buf->data - buf->begin; size_t size = pos + extra_size; + u8 *tmp; size = round_up(size, FWLOAD_BLOCK_SIZE); - buf->begin = krealloc(buf->begin, size, GFP_KERNEL | GFP_DMA); - if (buf->begin) { - buf->data = &buf->begin[pos]; - buf->end = &buf->begin[size]; - return 0; - } else { - buf->end = buf->data = buf->begin; + tmp = krealloc(buf->begin, size, GFP_KERNEL | GFP_DMA); + if (!tmp) { + wsm_buf_deinit(buf); return -ENOMEM; } + + buf->begin = tmp; + buf->data = &buf->begin[pos]; + buf->end = &buf->begin[size]; + return 0; } diff --git a/drivers/net/wireless/iwlwifi/mvm/mac80211.c b/drivers/net/wireless/iwlwifi/mvm/mac80211.c index 984cd2f05c4a..7b2a7d848a56 100644 --- a/drivers/net/wireless/iwlwifi/mvm/mac80211.c +++ b/drivers/net/wireless/iwlwifi/mvm/mac80211.c @@ -322,8 +322,12 @@ struct ieee80211_regdomain *iwl_mvm_get_regdomain(struct wiphy *wiphy, goto out; } - if (changed) - *changed = (resp->status == MCC_RESP_NEW_CHAN_PROFILE); + if (changed) { + u32 status = le32_to_cpu(resp->status); + + *changed = (status == MCC_RESP_NEW_CHAN_PROFILE || + status == MCC_RESP_ILLEGAL); + } regd = iwl_parse_nvm_mcc_info(mvm->trans->dev, mvm->cfg, __le32_to_cpu(resp->n_channels), @@ -4050,10 +4054,6 @@ static void iwl_mvm_mac_sta_statistics(struct ieee80211_hw *hw, struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif); struct iwl_mvm_sta *mvmsta = iwl_mvm_sta_from_mac80211(sta); - if (!fw_has_capa(&mvm->fw->ucode_capa, - IWL_UCODE_TLV_CAPA_RADIO_BEACON_STATS)) - return; - /* if beacon filtering isn't on mac80211 does it anyway */ if (!(vif->driver_flags & IEEE80211_VIF_BEACON_FILTER)) return; diff --git a/drivers/net/wireless/iwlwifi/mvm/nvm.c b/drivers/net/wireless/iwlwifi/mvm/nvm.c index 2ee0f6fe56a1..5509c5024352 100644 --- a/drivers/net/wireless/iwlwifi/mvm/nvm.c +++ b/drivers/net/wireless/iwlwifi/mvm/nvm.c @@ -667,9 +667,8 @@ iwl_mvm_update_mcc(struct iwl_mvm *mvm, const char *alpha2, n_channels = __le32_to_cpu(mcc_resp->n_channels); IWL_DEBUG_LAR(mvm, - "MCC response status: 0x%x. new MCC: 0x%x ('%c%c') change: %d n_chans: %d\n", - status, mcc, mcc >> 8, mcc & 0xff, - !!(status == MCC_RESP_NEW_CHAN_PROFILE), n_channels); + "MCC response status: 0x%x. new MCC: 0x%x ('%c%c') n_chans: %d\n", + status, mcc, mcc >> 8, mcc & 0xff, n_channels); resp_len = sizeof(*mcc_resp) + n_channels * sizeof(__le32); resp_cp = kmemdup(mcc_resp, resp_len, GFP_KERNEL); diff --git a/drivers/net/wireless/mac80211_hwsim.c b/drivers/net/wireless/mac80211_hwsim.c index 05413176a5d6..ab480ea6d95a 100644 --- a/drivers/net/wireless/mac80211_hwsim.c +++ b/drivers/net/wireless/mac80211_hwsim.c @@ -2515,6 +2515,10 @@ static int mac80211_hwsim_new_radio(struct genl_info *info, if (param->no_vif) ieee80211_hw_set(hw, NO_AUTO_VIF); + tasklet_hrtimer_init(&data->beacon_timer, + mac80211_hwsim_beacon, + CLOCK_MONOTONIC, HRTIMER_MODE_ABS); + err = ieee80211_register_hw(hw); if (err < 0) { printk(KERN_DEBUG "mac80211_hwsim: ieee80211_register_hw failed (%d)\n", @@ -2539,10 +2543,6 @@ static int mac80211_hwsim_new_radio(struct genl_info *info, data->debugfs, data, &hwsim_simulate_radar); - tasklet_hrtimer_init(&data->beacon_timer, - mac80211_hwsim_beacon, - CLOCK_MONOTONIC, HRTIMER_MODE_ABS); - spin_lock_bh(&hwsim_radio_lock); list_add_tail(&data->list, &hwsim_radios); spin_unlock_bh(&hwsim_radio_lock); diff --git a/drivers/net/wireless/mwifiex/cfg80211.c b/drivers/net/wireless/mwifiex/cfg80211.c index 9a8982f581c5..1e074eaf613d 100644 --- a/drivers/net/wireless/mwifiex/cfg80211.c +++ b/drivers/net/wireless/mwifiex/cfg80211.c @@ -1150,6 +1150,12 @@ mwifiex_cfg80211_change_virtual_intf(struct wiphy *wiphy, priv->adapter->curr_iface_comb.p2p_intf--; priv->adapter->curr_iface_comb.sta_intf++; dev->ieee80211_ptr->iftype = type; + if (mwifiex_deinit_priv_params(priv)) + return -1; + if (mwifiex_init_new_priv_params(priv, dev, type)) + return -1; + if (mwifiex_sta_init_cmd(priv, false, false)) + return -1; break; case NL80211_IFTYPE_ADHOC: if (mwifiex_cfg80211_deinit_p2p(priv)) @@ -2839,8 +2845,10 @@ int mwifiex_del_virtual_intf(struct wiphy *wiphy, struct wireless_dev *wdev) mwifiex_stop_net_dev_queue(priv->netdev, adapter); - skb_queue_walk_safe(&priv->bypass_txq, skb, tmp) + skb_queue_walk_safe(&priv->bypass_txq, skb, tmp) { + skb_unlink(skb, &priv->bypass_txq); mwifiex_write_data_complete(priv->adapter, skb, 0, -1); + } if (netif_carrier_ok(priv->netdev)) netif_carrier_off(priv->netdev); diff --git a/drivers/net/wireless/mwifiex/wmm.c b/drivers/net/wireless/mwifiex/wmm.c index acccd6734e3b..ed8b69d1d65c 100644 --- a/drivers/net/wireless/mwifiex/wmm.c +++ b/drivers/net/wireless/mwifiex/wmm.c @@ -501,8 +501,10 @@ mwifiex_wmm_del_pkts_in_ralist_node(struct mwifiex_private *priv, struct mwifiex_adapter *adapter = priv->adapter; struct sk_buff *skb, *tmp; - skb_queue_walk_safe(&ra_list->skb_head, skb, tmp) + skb_queue_walk_safe(&ra_list->skb_head, skb, tmp) { + skb_unlink(skb, &ra_list->skb_head); mwifiex_write_data_complete(adapter, skb, 0, -1); + } } /* @@ -598,11 +600,15 @@ mwifiex_clean_txrx(struct mwifiex_private *priv) priv->adapter->if_ops.clean_pcie_ring(priv->adapter); spin_unlock_irqrestore(&priv->wmm.ra_list_spinlock, flags); - skb_queue_walk_safe(&priv->tdls_txq, skb, tmp) + skb_queue_walk_safe(&priv->tdls_txq, skb, tmp) { + skb_unlink(skb, &priv->tdls_txq); mwifiex_write_data_complete(priv->adapter, skb, 0, -1); + } - skb_queue_walk_safe(&priv->bypass_txq, skb, tmp) + skb_queue_walk_safe(&priv->bypass_txq, skb, tmp) { + skb_unlink(skb, &priv->bypass_txq); mwifiex_write_data_complete(priv->adapter, skb, 0, -1); + } atomic_set(&priv->adapter->bypass_tx_pending, 0); idr_for_each(&priv->ack_status_frames, mwifiex_free_ack_frame, NULL); diff --git a/drivers/net/wireless/ti/wlcore/cmd.c b/drivers/net/wireless/ti/wlcore/cmd.c index 15dc7a398b90..f01d24baff7c 100644 --- a/drivers/net/wireless/ti/wlcore/cmd.c +++ b/drivers/net/wireless/ti/wlcore/cmd.c @@ -35,7 +35,6 @@ #include "wl12xx_80211.h" #include "cmd.h" #include "event.h" -#include "ps.h" #include "tx.h" #include "hw_ops.h" @@ -192,10 +191,6 @@ int wlcore_cmd_wait_for_event_or_timeout(struct wl1271 *wl, timeout_time = jiffies + msecs_to_jiffies(WL1271_EVENT_TIMEOUT); - ret = wl1271_ps_elp_wakeup(wl); - if (ret < 0) - return ret; - do { if (time_after(jiffies, timeout_time)) { wl1271_debug(DEBUG_CMD, "timeout waiting for event %d", @@ -227,7 +222,6 @@ int wlcore_cmd_wait_for_event_or_timeout(struct wl1271 *wl, } while (!event); out: - wl1271_ps_elp_sleep(wl); kfree(events_vector); return ret; } diff --git a/drivers/net/wireless/virt_wifi.c b/drivers/net/wireless/virt_wifi.c new file mode 100644 index 000000000000..90ecb7e8834f --- /dev/null +++ b/drivers/net/wireless/virt_wifi.c @@ -0,0 +1,629 @@ +// SPDX-License-Identifier: GPL-2.0 +/* drivers/net/wireless/virt_wifi.c + * + * A fake implementation of cfg80211_ops that can be tacked on to an ethernet + * net_device to make it appear as a wireless connection. + * + * Copyright (C) 2018 Google, Inc. + * + * Author: schuffelen@google.com + */ + +#include <net/cfg80211.h> +#include <net/rtnetlink.h> +#include <linux/etherdevice.h> +#include <linux/module.h> + +#include <net/cfg80211.h> +#include <net/rtnetlink.h> +#include <linux/etherdevice.h> +#include <linux/module.h> + +static struct wiphy *common_wiphy; + +struct virt_wifi_wiphy_priv { + struct delayed_work scan_result; + struct cfg80211_scan_request *scan_request; + bool being_deleted; +}; + +static struct ieee80211_channel channel_2ghz = { + .band = IEEE80211_BAND_2GHZ, + .center_freq = 2432, + .hw_value = 2432, + .max_power = 20, +}; + +static struct ieee80211_rate bitrates_2ghz[] = { + { .bitrate = 10 }, + { .bitrate = 20 }, + { .bitrate = 55 }, + { .bitrate = 110 }, + { .bitrate = 60 }, + { .bitrate = 120 }, + { .bitrate = 240 }, +}; + +static struct ieee80211_supported_band band_2ghz = { + .channels = &channel_2ghz, + .bitrates = bitrates_2ghz, + .band = IEEE80211_BAND_2GHZ, + .n_channels = 1, + .n_bitrates = ARRAY_SIZE(bitrates_2ghz), + .ht_cap = { + .ht_supported = true, + .cap = IEEE80211_HT_CAP_SUP_WIDTH_20_40 | + IEEE80211_HT_CAP_GRN_FLD | + IEEE80211_HT_CAP_SGI_20 | + IEEE80211_HT_CAP_SGI_40 | + IEEE80211_HT_CAP_DSSSCCK40, + .ampdu_factor = 0x3, + .ampdu_density = 0x6, + .mcs = { + .rx_mask = {0xff, 0xff}, + .tx_params = IEEE80211_HT_MCS_TX_DEFINED, + }, + }, +}; + +static struct ieee80211_channel channel_5ghz = { + .band = IEEE80211_BAND_5GHZ, + .center_freq = 5240, + .hw_value = 5240, + .max_power = 20, +}; + +static struct ieee80211_rate bitrates_5ghz[] = { + { .bitrate = 60 }, + { .bitrate = 120 }, + { .bitrate = 240 }, +}; + +#define RX_MCS_MAP (IEEE80211_VHT_MCS_SUPPORT_0_9 << 0 | \ + IEEE80211_VHT_MCS_SUPPORT_0_9 << 2 | \ + IEEE80211_VHT_MCS_SUPPORT_0_9 << 4 | \ + IEEE80211_VHT_MCS_SUPPORT_0_9 << 6 | \ + IEEE80211_VHT_MCS_SUPPORT_0_9 << 8 | \ + IEEE80211_VHT_MCS_SUPPORT_0_9 << 10 | \ + IEEE80211_VHT_MCS_SUPPORT_0_9 << 12 | \ + IEEE80211_VHT_MCS_SUPPORT_0_9 << 14) + +#define TX_MCS_MAP (IEEE80211_VHT_MCS_SUPPORT_0_9 << 0 | \ + IEEE80211_VHT_MCS_SUPPORT_0_9 << 2 | \ + IEEE80211_VHT_MCS_SUPPORT_0_9 << 4 | \ + IEEE80211_VHT_MCS_SUPPORT_0_9 << 6 | \ + IEEE80211_VHT_MCS_SUPPORT_0_9 << 8 | \ + IEEE80211_VHT_MCS_SUPPORT_0_9 << 10 | \ + IEEE80211_VHT_MCS_SUPPORT_0_9 << 12 | \ + IEEE80211_VHT_MCS_SUPPORT_0_9 << 14) + +static struct ieee80211_supported_band band_5ghz = { + .channels = &channel_5ghz, + .bitrates = bitrates_5ghz, + .band = IEEE80211_BAND_5GHZ, + .n_channels = 1, + .n_bitrates = ARRAY_SIZE(bitrates_5ghz), + .ht_cap = { + .ht_supported = true, + .cap = IEEE80211_HT_CAP_SUP_WIDTH_20_40 | + IEEE80211_HT_CAP_GRN_FLD | + IEEE80211_HT_CAP_SGI_20 | + IEEE80211_HT_CAP_SGI_40 | + IEEE80211_HT_CAP_DSSSCCK40, + .ampdu_factor = 0x3, + .ampdu_density = 0x6, + .mcs = { + .rx_mask = {0xff, 0xff}, + .tx_params = IEEE80211_HT_MCS_TX_DEFINED, + }, + }, + .vht_cap = { + .vht_supported = true, + .cap = IEEE80211_VHT_CAP_MAX_MPDU_LENGTH_11454 | + IEEE80211_VHT_CAP_SUPP_CHAN_WIDTH_160_80PLUS80MHZ | + IEEE80211_VHT_CAP_RXLDPC | + IEEE80211_VHT_CAP_SHORT_GI_80 | + IEEE80211_VHT_CAP_SHORT_GI_160 | + IEEE80211_VHT_CAP_TXSTBC | + IEEE80211_VHT_CAP_RXSTBC_1 | + IEEE80211_VHT_CAP_RXSTBC_2 | + IEEE80211_VHT_CAP_RXSTBC_3 | + IEEE80211_VHT_CAP_RXSTBC_4 | + IEEE80211_VHT_CAP_MAX_A_MPDU_LENGTH_EXPONENT_MASK, + .vht_mcs = { + .rx_mcs_map = cpu_to_le16(RX_MCS_MAP), + .tx_mcs_map = cpu_to_le16(TX_MCS_MAP), + } + }, +}; + +/* Assigned at module init. Guaranteed locally-administered and unicast. */ +static u8 fake_router_bssid[ETH_ALEN] __ro_after_init = {}; + +/* Called with the rtnl lock held. */ +static int virt_wifi_scan(struct wiphy *wiphy, + struct cfg80211_scan_request *request) +{ + struct virt_wifi_wiphy_priv *priv = wiphy_priv(wiphy); + + wiphy_debug(wiphy, "scan\n"); + + if (priv->scan_request || priv->being_deleted) + return -EBUSY; + + priv->scan_request = request; + schedule_delayed_work(&priv->scan_result, HZ * 2); + + return 0; +} + +/* Acquires and releases the rdev BSS lock. */ +static void virt_wifi_scan_result(struct work_struct *work) +{ + struct { + u8 tag; + u8 len; + u8 ssid[8]; + } __packed ssid = { + .tag = WLAN_EID_SSID, .len = 8, .ssid = "VirtWifi", + }; + struct cfg80211_bss *informed_bss; + struct virt_wifi_wiphy_priv *priv = + container_of(work, struct virt_wifi_wiphy_priv, + scan_result.work); + struct wiphy *wiphy = priv_to_wiphy(priv); + + informed_bss = cfg80211_inform_bss(wiphy, &channel_5ghz, + CFG80211_BSS_FTYPE_PRESP, + fake_router_bssid, + ktime_get_boot_ns(), + WLAN_CAPABILITY_ESS, 0, + (void *)&ssid, sizeof(ssid), + DBM_TO_MBM(-50), GFP_KERNEL); + cfg80211_put_bss(wiphy, informed_bss); + + /* Schedules work which acquires and releases the rtnl lock. */ + cfg80211_scan_done(priv->scan_request, false); + priv->scan_request = NULL; +} + +/* May acquire and release the rdev BSS lock. */ +static void virt_wifi_cancel_scan(struct wiphy *wiphy) +{ + struct virt_wifi_wiphy_priv *priv = wiphy_priv(wiphy); + + cancel_delayed_work_sync(&priv->scan_result); + /* Clean up dangling callbacks if necessary. */ + if (priv->scan_request) { + /* Schedules work which acquires and releases the rtnl lock. */ + cfg80211_scan_done(priv->scan_request, true); + priv->scan_request = NULL; + } +} + +struct virt_wifi_netdev_priv { + struct delayed_work connect; + struct net_device *lowerdev; + struct net_device *upperdev; + u32 tx_packets; + u32 tx_failed; + u8 connect_requested_bss[ETH_ALEN]; + bool is_up; + bool is_connected; + bool being_deleted; +}; + +/* Called with the rtnl lock held. */ +static int virt_wifi_connect(struct wiphy *wiphy, struct net_device *netdev, + struct cfg80211_connect_params *sme) +{ + struct virt_wifi_netdev_priv *priv = netdev_priv(netdev); + bool could_schedule; + + if (priv->being_deleted || !priv->is_up) + return -EBUSY; + + could_schedule = schedule_delayed_work(&priv->connect, HZ * 2); + if (!could_schedule) + return -EBUSY; + + if (sme->bssid) + ether_addr_copy(priv->connect_requested_bss, sme->bssid); + else + eth_zero_addr(priv->connect_requested_bss); + + wiphy_debug(wiphy, "connect\n"); + + return 0; +} + +/* Acquires and releases the rdev event lock. */ +static void virt_wifi_connect_complete(struct work_struct *work) +{ + struct virt_wifi_netdev_priv *priv = + container_of(work, struct virt_wifi_netdev_priv, connect.work); + u8 *requested_bss = priv->connect_requested_bss; + bool has_addr = !is_zero_ether_addr(requested_bss); + bool right_addr = ether_addr_equal(requested_bss, fake_router_bssid); + u16 status = WLAN_STATUS_SUCCESS; + + if (!priv->is_up || (has_addr && !right_addr)) + status = WLAN_STATUS_UNSPECIFIED_FAILURE; + else + priv->is_connected = true; + + /* Schedules an event that acquires the rtnl lock. */ + cfg80211_connect_result(priv->upperdev, requested_bss, NULL, 0, NULL, 0, + status, GFP_KERNEL); + netif_carrier_on(priv->upperdev); +} + +/* May acquire and release the rdev event lock. */ +static void virt_wifi_cancel_connect(struct net_device *netdev) +{ + struct virt_wifi_netdev_priv *priv = netdev_priv(netdev); + + /* If there is work pending, clean up dangling callbacks. */ + if (cancel_delayed_work_sync(&priv->connect)) { + /* Schedules an event that acquires the rtnl lock. */ + cfg80211_connect_result(priv->upperdev, + priv->connect_requested_bss, NULL, 0, + NULL, 0, + WLAN_STATUS_UNSPECIFIED_FAILURE, + GFP_KERNEL); + } +} + +/* Called with the rtnl lock held. Acquires the rdev event lock. */ +static int virt_wifi_disconnect(struct wiphy *wiphy, struct net_device *netdev, + u16 reason_code) +{ + struct virt_wifi_netdev_priv *priv = netdev_priv(netdev); + + if (priv->being_deleted) + return -EBUSY; + + wiphy_debug(wiphy, "disconnect\n"); + virt_wifi_cancel_connect(netdev); + + cfg80211_disconnected(netdev, reason_code, NULL, 0, true, GFP_KERNEL); + priv->is_connected = false; + netif_carrier_off(netdev); + + return 0; +} + +/* Called with the rtnl lock held. */ +static int virt_wifi_get_station(struct wiphy *wiphy, struct net_device *dev, + const u8 *mac, struct station_info *sinfo) +{ + struct virt_wifi_netdev_priv *priv = netdev_priv(dev); + + wiphy_debug(wiphy, "get_station\n"); + + if (!priv->is_connected || !ether_addr_equal(mac, fake_router_bssid)) + return -ENOENT; + + sinfo->filled = BIT_ULL(NL80211_STA_INFO_TX_PACKETS) | + BIT_ULL(NL80211_STA_INFO_TX_FAILED) | + BIT_ULL(NL80211_STA_INFO_SIGNAL) | + BIT_ULL(NL80211_STA_INFO_TX_BITRATE); + sinfo->tx_packets = priv->tx_packets; + sinfo->tx_failed = priv->tx_failed; + /* For CFG80211_SIGNAL_TYPE_MBM, value is expressed in _dBm_ */ + sinfo->signal = -50; + sinfo->txrate = (struct rate_info) { + .legacy = 10, /* units are 100kbit/s */ + }; + return 0; +} + +/* Called with the rtnl lock held. */ +static int virt_wifi_dump_station(struct wiphy *wiphy, struct net_device *dev, + int idx, u8 *mac, struct station_info *sinfo) +{ + struct virt_wifi_netdev_priv *priv = netdev_priv(dev); + + wiphy_debug(wiphy, "dump_station\n"); + + if (idx != 0 || !priv->is_connected) + return -ENOENT; + + ether_addr_copy(mac, fake_router_bssid); + return virt_wifi_get_station(wiphy, dev, fake_router_bssid, sinfo); +} + +static const struct cfg80211_ops virt_wifi_cfg80211_ops = { + .scan = virt_wifi_scan, + + .connect = virt_wifi_connect, + .disconnect = virt_wifi_disconnect, + + .get_station = virt_wifi_get_station, + .dump_station = virt_wifi_dump_station, +}; + +/* Acquires and releases the rtnl lock. */ +static struct wiphy *virt_wifi_make_wiphy(void) +{ + struct wiphy *wiphy; + struct virt_wifi_wiphy_priv *priv; + int err; + + wiphy = wiphy_new(&virt_wifi_cfg80211_ops, sizeof(*priv)); + + if (!wiphy) + return NULL; + + wiphy->max_scan_ssids = 4; + wiphy->max_scan_ie_len = 1000; + wiphy->signal_type = CFG80211_SIGNAL_TYPE_MBM; + + wiphy->bands[IEEE80211_BAND_2GHZ] = &band_2ghz; + wiphy->bands[IEEE80211_BAND_5GHZ] = &band_5ghz; + wiphy->bands[IEEE80211_BAND_60GHZ] = NULL; + + wiphy->regulatory_flags = REGULATORY_WIPHY_SELF_MANAGED; + wiphy->interface_modes = BIT(NL80211_IFTYPE_STATION); + + priv = wiphy_priv(wiphy); + priv->being_deleted = false; + priv->scan_request = NULL; + INIT_DELAYED_WORK(&priv->scan_result, virt_wifi_scan_result); + + err = wiphy_register(wiphy); + if (err < 0) { + wiphy_free(wiphy); + return NULL; + } + + return wiphy; +} + +/* Acquires and releases the rtnl lock. */ +static void virt_wifi_destroy_wiphy(struct wiphy *wiphy) +{ + struct virt_wifi_wiphy_priv *priv; + + WARN(!wiphy, "%s called with null wiphy", __func__); + if (!wiphy) + return; + + priv = wiphy_priv(wiphy); + priv->being_deleted = true; + virt_wifi_cancel_scan(wiphy); + + if (wiphy->registered) + wiphy_unregister(wiphy); + wiphy_free(wiphy); +} + +/* Enters and exits a RCU-bh critical section. */ +static netdev_tx_t virt_wifi_start_xmit(struct sk_buff *skb, + struct net_device *dev) +{ + struct virt_wifi_netdev_priv *priv = netdev_priv(dev); + + priv->tx_packets++; + if (!priv->is_connected) { + priv->tx_failed++; + return NET_XMIT_DROP; + } + + skb->dev = priv->lowerdev; + return dev_queue_xmit(skb); +} + +/* Called with rtnl lock held. */ +static int virt_wifi_net_device_open(struct net_device *dev) +{ + struct virt_wifi_netdev_priv *priv = netdev_priv(dev); + + priv->is_up = true; + return 0; +} + +/* Called with rtnl lock held. */ +static int virt_wifi_net_device_stop(struct net_device *dev) +{ + struct virt_wifi_netdev_priv *n_priv = netdev_priv(dev); + struct virt_wifi_wiphy_priv *w_priv; + + n_priv->is_up = false; + + if (!dev->ieee80211_ptr) + return 0; + w_priv = wiphy_priv(dev->ieee80211_ptr->wiphy); + + virt_wifi_cancel_scan(dev->ieee80211_ptr->wiphy); + virt_wifi_cancel_connect(dev); + netif_carrier_off(dev); + + return 0; +} + +static const struct net_device_ops virt_wifi_ops = { + .ndo_start_xmit = virt_wifi_start_xmit, + .ndo_open = virt_wifi_net_device_open, + .ndo_stop = virt_wifi_net_device_stop, +}; + +/* Invoked as part of rtnl lock release. */ +static void virt_wifi_net_device_destructor(struct net_device *dev) +{ + /* Delayed past dellink to allow nl80211 to react to the device being + * deleted. + */ + kfree(dev->ieee80211_ptr); + dev->ieee80211_ptr = NULL; + free_netdev(dev); +} + +/* No lock interaction. */ +static void virt_wifi_setup(struct net_device *dev) +{ + ether_setup(dev); + dev->netdev_ops = &virt_wifi_ops; + dev->destructor = virt_wifi_net_device_destructor; +} + +/* Called in a RCU read critical section from netif_receive_skb */ +static rx_handler_result_t virt_wifi_rx_handler(struct sk_buff **pskb) +{ + struct sk_buff *skb = *pskb; + struct virt_wifi_netdev_priv *priv = + rcu_dereference(skb->dev->rx_handler_data); + + if (!priv->is_connected) + return RX_HANDLER_PASS; + + /* GFP_ATOMIC because this is a packet interrupt handler. */ + skb = skb_share_check(skb, GFP_ATOMIC); + if (!skb) { + dev_err(&priv->upperdev->dev, "can't skb_share_check\n"); + return RX_HANDLER_CONSUMED; + } + + *pskb = skb; + skb->dev = priv->upperdev; + skb->pkt_type = PACKET_HOST; + return RX_HANDLER_ANOTHER; +} + +/* Called with rtnl lock held. */ +static int virt_wifi_newlink(struct net *src_net, struct net_device *dev, + struct nlattr *tb[], struct nlattr *data[]) +{ + struct virt_wifi_netdev_priv *priv = netdev_priv(dev); + int err; + + if (!tb[IFLA_LINK]) + return -EINVAL; + + netif_carrier_off(dev); + + priv->upperdev = dev; + priv->lowerdev = __dev_get_by_index(src_net, + nla_get_u32(tb[IFLA_LINK])); + + if (!priv->lowerdev) + return -ENODEV; + if (!tb[IFLA_MTU]) + dev->mtu = priv->lowerdev->mtu; + else if (dev->mtu > priv->lowerdev->mtu) + return -EINVAL; + + err = netdev_rx_handler_register(priv->lowerdev, virt_wifi_rx_handler, + priv); + if (err) { + dev_err(&priv->lowerdev->dev, + "can't netdev_rx_handler_register: %d\n", err); + return err; + } + + eth_hw_addr_inherit(dev, priv->lowerdev); + netif_stacked_transfer_operstate(priv->lowerdev, dev); + + SET_NETDEV_DEV(dev, &priv->lowerdev->dev); + dev->ieee80211_ptr = kzalloc(sizeof(*dev->ieee80211_ptr), GFP_KERNEL); + + if (!dev->ieee80211_ptr) + goto remove_handler; + + dev->ieee80211_ptr->iftype = NL80211_IFTYPE_STATION; + dev->ieee80211_ptr->wiphy = common_wiphy; + + err = register_netdevice(dev); + if (err) { + dev_err(&priv->lowerdev->dev, "can't register_netdevice: %d\n", + err); + goto free_wireless_dev; + } + + err = netdev_upper_dev_link(priv->lowerdev, dev); + if (err) { + dev_err(&priv->lowerdev->dev, "can't netdev_upper_dev_link: %d\n", + err); + goto unregister_netdev; + } + + priv->being_deleted = false; + priv->is_connected = false; + priv->is_up = false; + INIT_DELAYED_WORK(&priv->connect, virt_wifi_connect_complete); + + return 0; +unregister_netdev: + unregister_netdevice(dev); +free_wireless_dev: + kfree(dev->ieee80211_ptr); + dev->ieee80211_ptr = NULL; +remove_handler: + netdev_rx_handler_unregister(priv->lowerdev); + + return err; +} + +/* Called with rtnl lock held. */ +static void virt_wifi_dellink(struct net_device *dev, + struct list_head *head) +{ + struct virt_wifi_netdev_priv *priv = netdev_priv(dev); + + if (dev->ieee80211_ptr) + virt_wifi_cancel_scan(dev->ieee80211_ptr->wiphy); + + priv->being_deleted = true; + virt_wifi_cancel_connect(dev); + netif_carrier_off(dev); + + netdev_rx_handler_unregister(priv->lowerdev); + netdev_upper_dev_unlink(priv->lowerdev, dev); + + unregister_netdevice_queue(dev, head); + + /* Deleting the wiphy is handled in the module destructor. */ +} + +static struct rtnl_link_ops virt_wifi_link_ops = { + .kind = "virt_wifi", + .setup = virt_wifi_setup, + .newlink = virt_wifi_newlink, + .dellink = virt_wifi_dellink, + .priv_size = sizeof(struct virt_wifi_netdev_priv), +}; + +/* Acquires and releases the rtnl lock. */ +static int __init virt_wifi_init_module(void) +{ + int err; + + /* Guaranteed to be locallly-administered and not multicast. */ + eth_random_addr(fake_router_bssid); + + common_wiphy = virt_wifi_make_wiphy(); + if (!common_wiphy) + return -ENOMEM; + + err = rtnl_link_register(&virt_wifi_link_ops); + if (err) + virt_wifi_destroy_wiphy(common_wiphy); + + return err; +} + +/* Acquires and releases the rtnl lock. */ +static void __exit virt_wifi_cleanup_module(void) +{ + /* Will delete any devices that depend on the wiphy. */ + rtnl_link_unregister(&virt_wifi_link_ops); + virt_wifi_destroy_wiphy(common_wiphy); +} + +module_init(virt_wifi_init_module); +module_exit(virt_wifi_cleanup_module); + +MODULE_LICENSE("GPL v2"); +MODULE_AUTHOR("Cody Schuffelen <schuffelen@google.com>"); +MODULE_DESCRIPTION("Driver for a wireless wrapper of ethernet devices"); +MODULE_ALIAS_RTNL_LINK("virt_wifi"); diff --git a/drivers/nfc/nfcmrvl/uart.c b/drivers/nfc/nfcmrvl/uart.c index 6c0c301611c4..1b11ded79c4f 100644 --- a/drivers/nfc/nfcmrvl/uart.c +++ b/drivers/nfc/nfcmrvl/uart.c @@ -73,10 +73,9 @@ static int nfcmrvl_uart_parse_dt(struct device_node *node, struct device_node *matched_node; int ret; - matched_node = of_find_compatible_node(node, NULL, "marvell,nfc-uart"); + matched_node = of_get_compatible_child(node, "marvell,nfc-uart"); if (!matched_node) { - matched_node = of_find_compatible_node(node, NULL, - "mrvl,nfc-uart"); + matched_node = of_get_compatible_child(node, "mrvl,nfc-uart"); if (!matched_node) return -ENODEV; } diff --git a/drivers/of/base.c b/drivers/of/base.c index 31341290cd91..c6e019208d17 100644 --- a/drivers/of/base.c +++ b/drivers/of/base.c @@ -713,6 +713,31 @@ struct device_node *of_get_next_available_child(const struct device_node *node, EXPORT_SYMBOL(of_get_next_available_child); /** + * of_get_compatible_child - Find compatible child node + * @parent: parent node + * @compatible: compatible string + * + * Lookup child node whose compatible property contains the given compatible + * string. + * + * Returns a node pointer with refcount incremented, use of_node_put() on it + * when done; or NULL if not found. + */ +struct device_node *of_get_compatible_child(const struct device_node *parent, + const char *compatible) +{ + struct device_node *child; + + for_each_child_of_node(parent, child) { + if (of_device_is_compatible(child, compatible)) + break; + } + + return child; +} +EXPORT_SYMBOL(of_get_compatible_child); + +/** * of_get_child_by_name - Find the child node by name for a given parent * @node: parent node * @name: child name to look for. diff --git a/drivers/pinctrl/qcom/pinctrl-spmi-gpio.c b/drivers/pinctrl/qcom/pinctrl-spmi-gpio.c index 069d167ab410..1a3727aa28a8 100644 --- a/drivers/pinctrl/qcom/pinctrl-spmi-gpio.c +++ b/drivers/pinctrl/qcom/pinctrl-spmi-gpio.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012-2014, 2016 The Linux Foundation. All rights reserved. + * Copyright (c) 2012-2014, 2016, 2018 The Linux Foundation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 and @@ -538,7 +538,7 @@ static int pmic_gpio_config_set(struct pinctrl_dev *pctldev, unsigned int pin, pad->pullup = arg; break; case PMIC_GPIO_CONF_STRENGTH: - if (arg > PMIC_GPIO_STRENGTH_LOW) + if (arg > PMIC_GPIO_STRENGTH_HIGH) return -EINVAL; pad->strength = arg; break; diff --git a/drivers/pinctrl/qcom/pinctrl-ssbi-gpio.c b/drivers/pinctrl/qcom/pinctrl-ssbi-gpio.c index ae351167d849..5645b38d6132 100644 --- a/drivers/pinctrl/qcom/pinctrl-ssbi-gpio.c +++ b/drivers/pinctrl/qcom/pinctrl-ssbi-gpio.c @@ -1,6 +1,6 @@ /* * Copyright (c) 2015, Sony Mobile Communications AB. - * Copyright (c) 2013, The Linux Foundation. All rights reserved. + * Copyright (c) 2013, 2018 The Linux Foundation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 and @@ -379,7 +379,7 @@ static int pm8xxx_pin_config_set(struct pinctrl_dev *pctldev, banks |= BIT(0); break; case PM8XXX_QCOM_DRIVE_STRENGH: - if (arg > PMIC_GPIO_STRENGTH_LOW) { + if (arg > PM8921_GPIO_STRENGTH_LOW) { dev_err(pctrl->dev, "invalid drive strength\n"); return -EINVAL; } diff --git a/drivers/s390/net/qeth_core_main.c b/drivers/s390/net/qeth_core_main.c index 09ac56317f1b..533bd2467910 100644 --- a/drivers/s390/net/qeth_core_main.c +++ b/drivers/s390/net/qeth_core_main.c @@ -4519,8 +4519,8 @@ static int qeth_snmp_command_cb(struct qeth_card *card, { struct qeth_ipa_cmd *cmd; struct qeth_arp_query_info *qinfo; - struct qeth_snmp_cmd *snmp; unsigned char *data; + void *snmp_data; __u16 data_len; QETH_CARD_TEXT(card, 3, "snpcmdcb"); @@ -4528,7 +4528,6 @@ static int qeth_snmp_command_cb(struct qeth_card *card, cmd = (struct qeth_ipa_cmd *) sdata; data = (unsigned char *)((char *)cmd - reply->offset); qinfo = (struct qeth_arp_query_info *) reply->param; - snmp = &cmd->data.setadapterparms.data.snmp; if (cmd->hdr.return_code) { QETH_CARD_TEXT_(card, 4, "scer1%x", cmd->hdr.return_code); @@ -4541,10 +4540,15 @@ static int qeth_snmp_command_cb(struct qeth_card *card, return 0; } data_len = *((__u16 *)QETH_IPA_PDU_LEN_PDU1(data)); - if (cmd->data.setadapterparms.hdr.seq_no == 1) - data_len -= (__u16)((char *)&snmp->data - (char *)cmd); - else - data_len -= (__u16)((char *)&snmp->request - (char *)cmd); + if (cmd->data.setadapterparms.hdr.seq_no == 1) { + snmp_data = &cmd->data.setadapterparms.data.snmp; + data_len -= offsetof(struct qeth_ipa_cmd, + data.setadapterparms.data.snmp); + } else { + snmp_data = &cmd->data.setadapterparms.data.snmp.request; + data_len -= offsetof(struct qeth_ipa_cmd, + data.setadapterparms.data.snmp.request); + } /* check if there is enough room in userspace */ if ((qinfo->udata_len - qinfo->udata_offset) < data_len) { @@ -4557,16 +4561,9 @@ static int qeth_snmp_command_cb(struct qeth_card *card, QETH_CARD_TEXT_(card, 4, "sseqn%i", cmd->data.setadapterparms.hdr.seq_no); /*copy entries to user buffer*/ - if (cmd->data.setadapterparms.hdr.seq_no == 1) { - memcpy(qinfo->udata + qinfo->udata_offset, - (char *)snmp, - data_len + offsetof(struct qeth_snmp_cmd, data)); - qinfo->udata_offset += offsetof(struct qeth_snmp_cmd, data); - } else { - memcpy(qinfo->udata + qinfo->udata_offset, - (char *)&snmp->request, data_len); - } + memcpy(qinfo->udata + qinfo->udata_offset, snmp_data, data_len); qinfo->udata_offset += data_len; + /* check if all replies received ... */ QETH_CARD_TEXT_(card, 4, "srtot%i", cmd->data.setadapterparms.hdr.used_total); diff --git a/drivers/s390/virtio/virtio_ccw.c b/drivers/s390/virtio/virtio_ccw.c index 1b831598df7c..ff06bdfd2b20 100644 --- a/drivers/s390/virtio/virtio_ccw.c +++ b/drivers/s390/virtio/virtio_ccw.c @@ -59,6 +59,7 @@ struct virtio_ccw_device { unsigned int revision; /* Transport revision */ wait_queue_head_t wait_q; spinlock_t lock; + struct mutex io_lock; /* Serializes I/O requests */ struct list_head virtqueues; unsigned long indicators; unsigned long indicators2; @@ -307,6 +308,7 @@ static int ccw_io_helper(struct virtio_ccw_device *vcdev, unsigned long flags; int flag = intparm & VIRTIO_CCW_INTPARM_MASK; + mutex_lock(&vcdev->io_lock); do { spin_lock_irqsave(get_ccwdev_lock(vcdev->cdev), flags); ret = ccw_device_start(vcdev->cdev, ccw, intparm, 0, 0); @@ -319,7 +321,9 @@ static int ccw_io_helper(struct virtio_ccw_device *vcdev, cpu_relax(); } while (ret == -EBUSY); wait_event(vcdev->wait_q, doing_io(vcdev, flag) == 0); - return ret ? ret : vcdev->err; + ret = ret ? ret : vcdev->err; + mutex_unlock(&vcdev->io_lock); + return ret; } static void virtio_ccw_drop_indicator(struct virtio_ccw_device *vcdev, @@ -833,6 +837,7 @@ static void virtio_ccw_get_config(struct virtio_device *vdev, int ret; struct ccw1 *ccw; void *config_area; + unsigned long flags; ccw = kzalloc(sizeof(*ccw), GFP_DMA | GFP_KERNEL); if (!ccw) @@ -851,11 +856,13 @@ static void virtio_ccw_get_config(struct virtio_device *vdev, if (ret) goto out_free; + spin_lock_irqsave(&vcdev->lock, flags); memcpy(vcdev->config, config_area, offset + len); - if (buf) - memcpy(buf, &vcdev->config[offset], len); if (vcdev->config_ready < offset + len) vcdev->config_ready = offset + len; + spin_unlock_irqrestore(&vcdev->lock, flags); + if (buf) + memcpy(buf, config_area + offset, len); out_free: kfree(config_area); @@ -869,6 +876,7 @@ static void virtio_ccw_set_config(struct virtio_device *vdev, struct virtio_ccw_device *vcdev = to_vc_device(vdev); struct ccw1 *ccw; void *config_area; + unsigned long flags; ccw = kzalloc(sizeof(*ccw), GFP_DMA | GFP_KERNEL); if (!ccw) @@ -881,9 +889,11 @@ static void virtio_ccw_set_config(struct virtio_device *vdev, /* Make sure we don't overwrite fields. */ if (vcdev->config_ready < offset) virtio_ccw_get_config(vdev, 0, NULL, offset); + spin_lock_irqsave(&vcdev->lock, flags); memcpy(&vcdev->config[offset], buf, len); /* Write the config area to the host. */ memcpy(config_area, vcdev->config, sizeof(vcdev->config)); + spin_unlock_irqrestore(&vcdev->lock, flags); ccw->cmd_code = CCW_CMD_WRITE_CONF; ccw->flags = 0; ccw->count = offset + len; @@ -1230,6 +1240,7 @@ static int virtio_ccw_online(struct ccw_device *cdev) init_waitqueue_head(&vcdev->wait_q); INIT_LIST_HEAD(&vcdev->virtqueues); spin_lock_init(&vcdev->lock); + mutex_init(&vcdev->io_lock); spin_lock_irqsave(get_ccwdev_lock(cdev), flags); dev_set_drvdata(&cdev->dev, vcdev); diff --git a/drivers/scsi/bfa/bfa_fcbuild.c b/drivers/scsi/bfa/bfa_fcbuild.c index dce787f6cca2..daade591409a 100644 --- a/drivers/scsi/bfa/bfa_fcbuild.c +++ b/drivers/scsi/bfa/bfa_fcbuild.c @@ -1249,8 +1249,8 @@ fc_rspnid_build(struct fchs_s *fchs, void *pyld, u32 s_id, u16 ox_id, memset(rspnid, 0, sizeof(struct fcgs_rspnid_req_s)); rspnid->dap = s_id; - rspnid->spn_len = (u8) strlen((char *)name); - strncpy((char *)rspnid->spn, (char *)name, rspnid->spn_len); + strlcpy(rspnid->spn, name, sizeof(rspnid->spn)); + rspnid->spn_len = (u8) strlen(rspnid->spn); return sizeof(struct fcgs_rspnid_req_s) + sizeof(struct ct_hdr_s); } @@ -1270,8 +1270,8 @@ fc_rsnn_nn_build(struct fchs_s *fchs, void *pyld, u32 s_id, memset(rsnn_nn, 0, sizeof(struct fcgs_rsnn_nn_req_s)); rsnn_nn->node_name = node_name; - rsnn_nn->snn_len = (u8) strlen((char *)name); - strncpy((char *)rsnn_nn->snn, (char *)name, rsnn_nn->snn_len); + strlcpy(rsnn_nn->snn, name, sizeof(rsnn_nn->snn)); + rsnn_nn->snn_len = (u8) strlen(rsnn_nn->snn); return sizeof(struct fcgs_rsnn_nn_req_s) + sizeof(struct ct_hdr_s); } diff --git a/drivers/scsi/bfa/bfa_fcs.c b/drivers/scsi/bfa/bfa_fcs.c index 0f19455951ec..475470efb7c6 100644 --- a/drivers/scsi/bfa/bfa_fcs.c +++ b/drivers/scsi/bfa/bfa_fcs.c @@ -831,23 +831,23 @@ bfa_fcs_fabric_psymb_init(struct bfa_fcs_fabric_s *fabric) bfa_ioc_get_adapter_model(&fabric->fcs->bfa->ioc, model); /* Model name/number */ - strncpy((char *)&port_cfg->sym_name, model, - BFA_FCS_PORT_SYMBNAME_MODEL_SZ); - strncat((char *)&port_cfg->sym_name, BFA_FCS_PORT_SYMBNAME_SEPARATOR, - sizeof(BFA_FCS_PORT_SYMBNAME_SEPARATOR)); + strlcpy(port_cfg->sym_name.symname, model, + BFA_SYMNAME_MAXLEN); + strlcat(port_cfg->sym_name.symname, BFA_FCS_PORT_SYMBNAME_SEPARATOR, + BFA_SYMNAME_MAXLEN); /* Driver Version */ - strncat((char *)&port_cfg->sym_name, (char *)driver_info->version, - BFA_FCS_PORT_SYMBNAME_VERSION_SZ); - strncat((char *)&port_cfg->sym_name, BFA_FCS_PORT_SYMBNAME_SEPARATOR, - sizeof(BFA_FCS_PORT_SYMBNAME_SEPARATOR)); + strlcat(port_cfg->sym_name.symname, driver_info->version, + BFA_SYMNAME_MAXLEN); + strlcat(port_cfg->sym_name.symname, BFA_FCS_PORT_SYMBNAME_SEPARATOR, + BFA_SYMNAME_MAXLEN); /* Host machine name */ - strncat((char *)&port_cfg->sym_name, - (char *)driver_info->host_machine_name, - BFA_FCS_PORT_SYMBNAME_MACHINENAME_SZ); - strncat((char *)&port_cfg->sym_name, BFA_FCS_PORT_SYMBNAME_SEPARATOR, - sizeof(BFA_FCS_PORT_SYMBNAME_SEPARATOR)); + strlcat(port_cfg->sym_name.symname, + driver_info->host_machine_name, + BFA_SYMNAME_MAXLEN); + strlcat(port_cfg->sym_name.symname, BFA_FCS_PORT_SYMBNAME_SEPARATOR, + BFA_SYMNAME_MAXLEN); /* * Host OS Info : @@ -855,24 +855,24 @@ bfa_fcs_fabric_psymb_init(struct bfa_fcs_fabric_s *fabric) * OS name string and instead copy the entire OS info string (64 bytes). */ if (driver_info->host_os_patch[0] == '\0') { - strncat((char *)&port_cfg->sym_name, - (char *)driver_info->host_os_name, - BFA_FCS_OS_STR_LEN); - strncat((char *)&port_cfg->sym_name, + strlcat(port_cfg->sym_name.symname, + driver_info->host_os_name, + BFA_SYMNAME_MAXLEN); + strlcat(port_cfg->sym_name.symname, BFA_FCS_PORT_SYMBNAME_SEPARATOR, - sizeof(BFA_FCS_PORT_SYMBNAME_SEPARATOR)); + BFA_SYMNAME_MAXLEN); } else { - strncat((char *)&port_cfg->sym_name, - (char *)driver_info->host_os_name, - BFA_FCS_PORT_SYMBNAME_OSINFO_SZ); - strncat((char *)&port_cfg->sym_name, + strlcat(port_cfg->sym_name.symname, + driver_info->host_os_name, + BFA_SYMNAME_MAXLEN); + strlcat(port_cfg->sym_name.symname, BFA_FCS_PORT_SYMBNAME_SEPARATOR, - sizeof(BFA_FCS_PORT_SYMBNAME_SEPARATOR)); + BFA_SYMNAME_MAXLEN); /* Append host OS Patch Info */ - strncat((char *)&port_cfg->sym_name, - (char *)driver_info->host_os_patch, - BFA_FCS_PORT_SYMBNAME_OSPATCH_SZ); + strlcat(port_cfg->sym_name.symname, + driver_info->host_os_patch, + BFA_SYMNAME_MAXLEN); } /* null terminate */ @@ -892,26 +892,26 @@ bfa_fcs_fabric_nsymb_init(struct bfa_fcs_fabric_s *fabric) bfa_ioc_get_adapter_model(&fabric->fcs->bfa->ioc, model); /* Model name/number */ - strncpy((char *)&port_cfg->node_sym_name, model, - BFA_FCS_PORT_SYMBNAME_MODEL_SZ); - strncat((char *)&port_cfg->node_sym_name, + strlcpy(port_cfg->node_sym_name.symname, model, + BFA_SYMNAME_MAXLEN); + strlcat(port_cfg->node_sym_name.symname, BFA_FCS_PORT_SYMBNAME_SEPARATOR, - sizeof(BFA_FCS_PORT_SYMBNAME_SEPARATOR)); + BFA_SYMNAME_MAXLEN); /* Driver Version */ - strncat((char *)&port_cfg->node_sym_name, (char *)driver_info->version, - BFA_FCS_PORT_SYMBNAME_VERSION_SZ); - strncat((char *)&port_cfg->node_sym_name, + strlcat(port_cfg->node_sym_name.symname, (char *)driver_info->version, + BFA_SYMNAME_MAXLEN); + strlcat(port_cfg->node_sym_name.symname, BFA_FCS_PORT_SYMBNAME_SEPARATOR, - sizeof(BFA_FCS_PORT_SYMBNAME_SEPARATOR)); + BFA_SYMNAME_MAXLEN); /* Host machine name */ - strncat((char *)&port_cfg->node_sym_name, - (char *)driver_info->host_machine_name, - BFA_FCS_PORT_SYMBNAME_MACHINENAME_SZ); - strncat((char *)&port_cfg->node_sym_name, + strlcat(port_cfg->node_sym_name.symname, + driver_info->host_machine_name, + BFA_SYMNAME_MAXLEN); + strlcat(port_cfg->node_sym_name.symname, BFA_FCS_PORT_SYMBNAME_SEPARATOR, - sizeof(BFA_FCS_PORT_SYMBNAME_SEPARATOR)); + BFA_SYMNAME_MAXLEN); /* null terminate */ port_cfg->node_sym_name.symname[BFA_SYMNAME_MAXLEN - 1] = 0; diff --git a/drivers/scsi/bfa/bfa_fcs_lport.c b/drivers/scsi/bfa/bfa_fcs_lport.c index ff75ef891755..aa96f31ebc43 100644 --- a/drivers/scsi/bfa/bfa_fcs_lport.c +++ b/drivers/scsi/bfa/bfa_fcs_lport.c @@ -2630,10 +2630,10 @@ bfa_fcs_fdmi_get_hbaattr(struct bfa_fcs_lport_fdmi_s *fdmi, bfa_ioc_get_adapter_fw_ver(&port->fcs->bfa->ioc, hba_attr->fw_version); - strncpy(hba_attr->driver_version, (char *)driver_info->version, + strlcpy(hba_attr->driver_version, (char *)driver_info->version, sizeof(hba_attr->driver_version)); - strncpy(hba_attr->os_name, driver_info->host_os_name, + strlcpy(hba_attr->os_name, driver_info->host_os_name, sizeof(hba_attr->os_name)); /* @@ -2641,23 +2641,23 @@ bfa_fcs_fdmi_get_hbaattr(struct bfa_fcs_lport_fdmi_s *fdmi, * to the os name along with a separator */ if (driver_info->host_os_patch[0] != '\0') { - strncat(hba_attr->os_name, BFA_FCS_PORT_SYMBNAME_SEPARATOR, - sizeof(BFA_FCS_PORT_SYMBNAME_SEPARATOR)); - strncat(hba_attr->os_name, driver_info->host_os_patch, - sizeof(driver_info->host_os_patch)); + strlcat(hba_attr->os_name, BFA_FCS_PORT_SYMBNAME_SEPARATOR, + sizeof(hba_attr->os_name)); + strlcat(hba_attr->os_name, driver_info->host_os_patch, + sizeof(hba_attr->os_name)); } /* Retrieve the max frame size from the port attr */ bfa_fcs_fdmi_get_portattr(fdmi, &fcs_port_attr); hba_attr->max_ct_pyld = fcs_port_attr.max_frm_size; - strncpy(hba_attr->node_sym_name.symname, + strlcpy(hba_attr->node_sym_name.symname, port->port_cfg.node_sym_name.symname, BFA_SYMNAME_MAXLEN); strcpy(hba_attr->vendor_info, "BROCADE"); hba_attr->num_ports = cpu_to_be32(bfa_ioc_get_nports(&port->fcs->bfa->ioc)); hba_attr->fabric_name = port->fabric->lps->pr_nwwn; - strncpy(hba_attr->bios_ver, hba_attr->option_rom_ver, BFA_VERSION_LEN); + strlcpy(hba_attr->bios_ver, hba_attr->option_rom_ver, BFA_VERSION_LEN); } @@ -2724,20 +2724,20 @@ bfa_fcs_fdmi_get_portattr(struct bfa_fcs_lport_fdmi_s *fdmi, /* * OS device Name */ - strncpy(port_attr->os_device_name, (char *)driver_info->os_device_name, + strlcpy(port_attr->os_device_name, driver_info->os_device_name, sizeof(port_attr->os_device_name)); /* * Host name */ - strncpy(port_attr->host_name, (char *)driver_info->host_machine_name, + strlcpy(port_attr->host_name, driver_info->host_machine_name, sizeof(port_attr->host_name)); port_attr->node_name = bfa_fcs_lport_get_nwwn(port); port_attr->port_name = bfa_fcs_lport_get_pwwn(port); - strncpy(port_attr->port_sym_name.symname, - (char *)&bfa_fcs_lport_get_psym_name(port), BFA_SYMNAME_MAXLEN); + strlcpy(port_attr->port_sym_name.symname, + bfa_fcs_lport_get_psym_name(port).symname, BFA_SYMNAME_MAXLEN); bfa_fcs_lport_get_attr(port, &lport_attr); port_attr->port_type = cpu_to_be32(lport_attr.port_type); port_attr->scos = pport_attr.cos_supported; @@ -3217,7 +3217,7 @@ bfa_fcs_lport_ms_gmal_response(void *fcsarg, struct bfa_fcxp_s *fcxp, rsp_str[gmal_entry->len-1] = 0; /* copy IP Address to fabric */ - strncpy(bfa_fcs_lport_get_fabric_ipaddr(port), + strlcpy(bfa_fcs_lport_get_fabric_ipaddr(port), gmal_entry->ip_addr, BFA_FCS_FABRIC_IPADDR_SZ); break; @@ -4655,21 +4655,13 @@ bfa_fcs_lport_ns_send_rspn_id(void *ns_cbarg, struct bfa_fcxp_s *fcxp_alloced) * to that of the base port. */ - strncpy((char *)psymbl, - (char *) & - (bfa_fcs_lport_get_psym_name + strlcpy(symbl, + (char *)&(bfa_fcs_lport_get_psym_name (bfa_fcs_get_base_port(port->fcs))), - strlen((char *) & - bfa_fcs_lport_get_psym_name(bfa_fcs_get_base_port - (port->fcs)))); - - /* Ensure we have a null terminating string. */ - ((char *)psymbl)[strlen((char *) & - bfa_fcs_lport_get_psym_name(bfa_fcs_get_base_port - (port->fcs)))] = 0; - strncat((char *)psymbl, - (char *) &(bfa_fcs_lport_get_psym_name(port)), - strlen((char *) &bfa_fcs_lport_get_psym_name(port))); + sizeof(symbl)); + + strlcat(symbl, (char *)&(bfa_fcs_lport_get_psym_name(port)), + sizeof(symbl)); } else { psymbl = (u8 *) &(bfa_fcs_lport_get_psym_name(port)); } @@ -5161,7 +5153,6 @@ bfa_fcs_lport_ns_util_send_rspn_id(void *cbarg, struct bfa_fcxp_s *fcxp_alloced) struct fchs_s fchs; struct bfa_fcxp_s *fcxp; u8 symbl[256]; - u8 *psymbl = &symbl[0]; int len; /* Avoid sending RSPN in the following states. */ @@ -5191,22 +5182,17 @@ bfa_fcs_lport_ns_util_send_rspn_id(void *cbarg, struct bfa_fcxp_s *fcxp_alloced) * For Vports, we append the vport's port symbolic name * to that of the base port. */ - strncpy((char *)psymbl, (char *)&(bfa_fcs_lport_get_psym_name + strlcpy(symbl, (char *)&(bfa_fcs_lport_get_psym_name (bfa_fcs_get_base_port(port->fcs))), - strlen((char *)&bfa_fcs_lport_get_psym_name( - bfa_fcs_get_base_port(port->fcs)))); - - /* Ensure we have a null terminating string. */ - ((char *)psymbl)[strlen((char *)&bfa_fcs_lport_get_psym_name( - bfa_fcs_get_base_port(port->fcs)))] = 0; + sizeof(symbl)); - strncat((char *)psymbl, + strlcat(symbl, (char *)&(bfa_fcs_lport_get_psym_name(port)), - strlen((char *)&bfa_fcs_lport_get_psym_name(port))); + sizeof(symbl)); } len = fc_rspnid_build(&fchs, bfa_fcxp_get_reqbuf(fcxp), - bfa_fcs_lport_get_fcid(port), 0, psymbl); + bfa_fcs_lport_get_fcid(port), 0, symbl); bfa_fcxp_send(fcxp, NULL, port->fabric->vf_id, port->lp_tag, BFA_FALSE, FC_CLASS_3, len, &fchs, NULL, NULL, FC_MAX_PDUSZ, 0); diff --git a/drivers/scsi/bfa/bfa_ioc.c b/drivers/scsi/bfa/bfa_ioc.c index 98f7e8cca52d..e533474748a5 100644 --- a/drivers/scsi/bfa/bfa_ioc.c +++ b/drivers/scsi/bfa/bfa_ioc.c @@ -2802,7 +2802,7 @@ void bfa_ioc_get_adapter_manufacturer(struct bfa_ioc_s *ioc, char *manufacturer) { memset((void *)manufacturer, 0, BFA_ADAPTER_MFG_NAME_LEN); - memcpy(manufacturer, BFA_MFG_NAME, BFA_ADAPTER_MFG_NAME_LEN); + strlcpy(manufacturer, BFA_MFG_NAME, BFA_ADAPTER_MFG_NAME_LEN); } void diff --git a/drivers/scsi/bfa/bfa_svc.c b/drivers/scsi/bfa/bfa_svc.c index 625225f31081..15d02eb09476 100644 --- a/drivers/scsi/bfa/bfa_svc.c +++ b/drivers/scsi/bfa/bfa_svc.c @@ -365,8 +365,8 @@ bfa_plog_str(struct bfa_plog_s *plog, enum bfa_plog_mid mid, lp.eid = event; lp.log_type = BFA_PL_LOG_TYPE_STRING; lp.misc = misc; - strncpy(lp.log_entry.string_log, log_str, - BFA_PL_STRING_LOG_SZ - 1); + strlcpy(lp.log_entry.string_log, log_str, + BFA_PL_STRING_LOG_SZ); lp.log_entry.string_log[BFA_PL_STRING_LOG_SZ - 1] = '\0'; bfa_plog_add(plog, &lp); } diff --git a/drivers/scsi/bfa/bfad.c b/drivers/scsi/bfa/bfad.c index cc3b9d3d6d40..bfefa2bfde0e 100644 --- a/drivers/scsi/bfa/bfad.c +++ b/drivers/scsi/bfa/bfad.c @@ -987,20 +987,20 @@ bfad_start_ops(struct bfad_s *bfad) { /* Fill the driver_info info to fcs*/ memset(&driver_info, 0, sizeof(driver_info)); - strncpy(driver_info.version, BFAD_DRIVER_VERSION, - sizeof(driver_info.version) - 1); + strlcpy(driver_info.version, BFAD_DRIVER_VERSION, + sizeof(driver_info.version)); if (host_name) - strncpy(driver_info.host_machine_name, host_name, - sizeof(driver_info.host_machine_name) - 1); + strlcpy(driver_info.host_machine_name, host_name, + sizeof(driver_info.host_machine_name)); if (os_name) - strncpy(driver_info.host_os_name, os_name, - sizeof(driver_info.host_os_name) - 1); + strlcpy(driver_info.host_os_name, os_name, + sizeof(driver_info.host_os_name)); if (os_patch) - strncpy(driver_info.host_os_patch, os_patch, - sizeof(driver_info.host_os_patch) - 1); + strlcpy(driver_info.host_os_patch, os_patch, + sizeof(driver_info.host_os_patch)); - strncpy(driver_info.os_device_name, bfad->pci_name, - sizeof(driver_info.os_device_name) - 1); + strlcpy(driver_info.os_device_name, bfad->pci_name, + sizeof(driver_info.os_device_name)); /* FCS driver info init */ spin_lock_irqsave(&bfad->bfad_lock, flags); diff --git a/drivers/scsi/bfa/bfad_attr.c b/drivers/scsi/bfa/bfad_attr.c index 40be670a1cbc..6d21bc6a7713 100644 --- a/drivers/scsi/bfa/bfad_attr.c +++ b/drivers/scsi/bfa/bfad_attr.c @@ -842,7 +842,7 @@ bfad_im_symbolic_name_show(struct device *dev, struct device_attribute *attr, char symname[BFA_SYMNAME_MAXLEN]; bfa_fcs_lport_get_attr(&bfad->bfa_fcs.fabric.bport, &port_attr); - strncpy(symname, port_attr.port_cfg.sym_name.symname, + strlcpy(symname, port_attr.port_cfg.sym_name.symname, BFA_SYMNAME_MAXLEN); return snprintf(buf, PAGE_SIZE, "%s\n", symname); } diff --git a/drivers/scsi/bfa/bfad_bsg.c b/drivers/scsi/bfa/bfad_bsg.c index 023b9d42ad9a..be2de04179d0 100644 --- a/drivers/scsi/bfa/bfad_bsg.c +++ b/drivers/scsi/bfa/bfad_bsg.c @@ -126,7 +126,7 @@ bfad_iocmd_ioc_get_attr(struct bfad_s *bfad, void *cmd) /* fill in driver attr info */ strcpy(iocmd->ioc_attr.driver_attr.driver, BFAD_DRIVER_NAME); - strncpy(iocmd->ioc_attr.driver_attr.driver_ver, + strlcpy(iocmd->ioc_attr.driver_attr.driver_ver, BFAD_DRIVER_VERSION, BFA_VERSION_LEN); strcpy(iocmd->ioc_attr.driver_attr.fw_ver, iocmd->ioc_attr.adapter_attr.fw_ver); @@ -314,9 +314,9 @@ bfad_iocmd_port_get_attr(struct bfad_s *bfad, void *cmd) iocmd->attr.port_type = port_attr.port_type; iocmd->attr.loopback = port_attr.loopback; iocmd->attr.authfail = port_attr.authfail; - strncpy(iocmd->attr.port_symname.symname, + strlcpy(iocmd->attr.port_symname.symname, port_attr.port_cfg.sym_name.symname, - sizeof(port_attr.port_cfg.sym_name.symname)); + sizeof(iocmd->attr.port_symname.symname)); iocmd->status = BFA_STATUS_OK; return 0; diff --git a/drivers/scsi/csiostor/csio_lnode.c b/drivers/scsi/csiostor/csio_lnode.c index c00b2ff72b55..be5ee2d37815 100644 --- a/drivers/scsi/csiostor/csio_lnode.c +++ b/drivers/scsi/csiostor/csio_lnode.c @@ -238,14 +238,23 @@ csio_osname(uint8_t *buf, size_t buf_len) } static inline void -csio_append_attrib(uint8_t **ptr, uint16_t type, uint8_t *val, uint16_t len) +csio_append_attrib(uint8_t **ptr, uint16_t type, void *val, size_t val_len) { + uint16_t len; struct fc_fdmi_attr_entry *ae = (struct fc_fdmi_attr_entry *)*ptr; + + if (WARN_ON(val_len > U16_MAX)) + return; + + len = val_len; + ae->type = htons(type); len += 4; /* includes attribute type and length */ len = (len + 3) & ~3; /* should be multiple of 4 bytes */ ae->len = htons(len); - memcpy(ae->value, val, len); + memcpy(ae->value, val, val_len); + if (len > val_len) + memset(ae->value + val_len, 0, len - val_len); *ptr += len; } @@ -335,7 +344,7 @@ csio_ln_fdmi_rhba_cbfn(struct csio_hw *hw, struct csio_ioreq *fdmi_req) numattrs++; val = htonl(FC_PORTSPEED_1GBIT | FC_PORTSPEED_10GBIT); csio_append_attrib(&pld, FC_FDMI_PORT_ATTR_SUPPORTEDSPEED, - (uint8_t *)&val, + &val, FC_FDMI_PORT_ATTR_SUPPORTEDSPEED_LEN); numattrs++; @@ -346,23 +355,22 @@ csio_ln_fdmi_rhba_cbfn(struct csio_hw *hw, struct csio_ioreq *fdmi_req) else val = htonl(CSIO_HBA_PORTSPEED_UNKNOWN); csio_append_attrib(&pld, FC_FDMI_PORT_ATTR_CURRENTPORTSPEED, - (uint8_t *)&val, - FC_FDMI_PORT_ATTR_CURRENTPORTSPEED_LEN); + &val, FC_FDMI_PORT_ATTR_CURRENTPORTSPEED_LEN); numattrs++; mfs = ln->ln_sparm.csp.sp_bb_data; csio_append_attrib(&pld, FC_FDMI_PORT_ATTR_MAXFRAMESIZE, - (uint8_t *)&mfs, FC_FDMI_PORT_ATTR_MAXFRAMESIZE_LEN); + &mfs, sizeof(mfs)); numattrs++; strcpy(buf, "csiostor"); csio_append_attrib(&pld, FC_FDMI_PORT_ATTR_OSDEVICENAME, buf, - (uint16_t)strlen(buf)); + strlen(buf)); numattrs++; if (!csio_hostname(buf, sizeof(buf))) { csio_append_attrib(&pld, FC_FDMI_PORT_ATTR_HOSTNAME, - buf, (uint16_t)strlen(buf)); + buf, strlen(buf)); numattrs++; } attrib_blk->numattrs = htonl(numattrs); @@ -444,33 +452,32 @@ csio_ln_fdmi_dprt_cbfn(struct csio_hw *hw, struct csio_ioreq *fdmi_req) strcpy(buf, "Chelsio Communications"); csio_append_attrib(&pld, FC_FDMI_HBA_ATTR_MANUFACTURER, buf, - (uint16_t)strlen(buf)); + strlen(buf)); numattrs++; csio_append_attrib(&pld, FC_FDMI_HBA_ATTR_SERIALNUMBER, - hw->vpd.sn, (uint16_t)sizeof(hw->vpd.sn)); + hw->vpd.sn, sizeof(hw->vpd.sn)); numattrs++; csio_append_attrib(&pld, FC_FDMI_HBA_ATTR_MODEL, hw->vpd.id, - (uint16_t)sizeof(hw->vpd.id)); + sizeof(hw->vpd.id)); numattrs++; csio_append_attrib(&pld, FC_FDMI_HBA_ATTR_MODELDESCRIPTION, - hw->model_desc, (uint16_t)strlen(hw->model_desc)); + hw->model_desc, strlen(hw->model_desc)); numattrs++; csio_append_attrib(&pld, FC_FDMI_HBA_ATTR_HARDWAREVERSION, - hw->hw_ver, (uint16_t)sizeof(hw->hw_ver)); + hw->hw_ver, sizeof(hw->hw_ver)); numattrs++; csio_append_attrib(&pld, FC_FDMI_HBA_ATTR_FIRMWAREVERSION, - hw->fwrev_str, (uint16_t)strlen(hw->fwrev_str)); + hw->fwrev_str, strlen(hw->fwrev_str)); numattrs++; if (!csio_osname(buf, sizeof(buf))) { csio_append_attrib(&pld, FC_FDMI_HBA_ATTR_OSNAMEVERSION, - buf, (uint16_t)strlen(buf)); + buf, strlen(buf)); numattrs++; } csio_append_attrib(&pld, FC_FDMI_HBA_ATTR_MAXCTPAYLOAD, - (uint8_t *)&maxpayload, - FC_FDMI_HBA_ATTR_MAXCTPAYLOAD_LEN); + &maxpayload, FC_FDMI_HBA_ATTR_MAXCTPAYLOAD_LEN); len = (uint32_t)(pld - (uint8_t *)cmd); numattrs++; attrib_blk->numattrs = htonl(numattrs); @@ -1794,6 +1801,8 @@ csio_ln_mgmt_submit_req(struct csio_ioreq *io_req, struct csio_mgmtm *mgmtm = csio_hw_to_mgmtm(hw); int rv; + BUG_ON(pld_len > pld->len); + io_req->io_cbfn = io_cbfn; /* Upper layer callback handler */ io_req->fw_handle = (uintptr_t) (io_req); io_req->eq_idx = mgmtm->eq_idx; diff --git a/drivers/scsi/qla2xxx/qla_os.c b/drivers/scsi/qla2xxx/qla_os.c index 18b19744398a..ff5df33fc740 100644 --- a/drivers/scsi/qla2xxx/qla_os.c +++ b/drivers/scsi/qla2xxx/qla_os.c @@ -685,6 +685,11 @@ qla2xxx_queuecommand(struct Scsi_Host *host, struct scsi_cmnd *cmd) srb_t *sp; int rval; + if (unlikely(test_bit(UNLOADING, &base_vha->dpc_flags))) { + cmd->result = DID_NO_CONNECT << 16; + goto qc24_fail_command; + } + if (ha->flags.eeh_busy) { if (ha->flags.pci_channel_io_perm_failure) { ql_dbg(ql_dbg_aer, vha, 0x9010, diff --git a/drivers/scsi/scsi_devinfo.c b/drivers/scsi/scsi_devinfo.c index 6b61b09b3226..75f2179860a7 100644 --- a/drivers/scsi/scsi_devinfo.c +++ b/drivers/scsi/scsi_devinfo.c @@ -33,7 +33,6 @@ struct scsi_dev_info_list_table { }; -static const char spaces[] = " "; /* 16 of them */ static unsigned scsi_default_dev_flags; static LIST_HEAD(scsi_dev_info_list); static char scsi_dev_flags[256]; @@ -291,20 +290,13 @@ static void scsi_strcpy_devinfo(char *name, char *to, size_t to_length, size_t from_length; from_length = strlen(from); - strncpy(to, from, min(to_length, from_length)); - if (from_length < to_length) { - if (compatible) { - /* - * NUL terminate the string if it is short. - */ - to[from_length] = '\0'; - } else { - /* - * space pad the string if it is short. - */ - strncpy(&to[from_length], spaces, - to_length - from_length); - } + /* this zero-pads the destination */ + strncpy(to, from, to_length); + if (from_length < to_length && !compatible) { + /* + * space pad the string if it is short. + */ + memset(&to[from_length], ' ', to_length - from_length); } if (from_length > to_length) printk(KERN_WARNING "%s: %s string '%s' is too long\n", diff --git a/drivers/soc/qcom/memshare/msm_memshare.c b/drivers/soc/qcom/memshare/msm_memshare.c index 6dd4b06bf377..94b535111f24 100644 --- a/drivers/soc/qcom/memshare/msm_memshare.c +++ b/drivers/soc/qcom/memshare/msm_memshare.c @@ -1,4 +1,4 @@ -/* Copyright (c) 2013-2017, The Linux Foundation. All rights reserved. +/* Copyright (c) 2013-2018, The Linux Foundation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 and @@ -375,6 +375,7 @@ static int modem_notifier_cb(struct notifier_block *this, unsigned long code, if (memblock[i].peripheral == DHMS_MEM_PROC_MPSS_V01 && !memblock[i].guarantee && + !memblock[i].client_request && memblock[i].alloted) { pr_debug("memshare: Freeing memory for client id: %d\n", memblock[i].client_id); @@ -630,12 +631,10 @@ static int handle_free_generic_req(void *req_h, void *req, void *conn_h) __func__); flag = 1; } else if (!memblock[client_id].guarantee && + memblock[client_id].client_request && memblock[client_id].alloted) { - pr_debug("In %s: pblk->virtual_addr :%lx, pblk->phy_addr: %lx\n,size: %d", - __func__, - (unsigned long int) - memblock[client_id].virtual_addr, - (unsigned long int)memblock[client_id].phy_addr, + pr_debug("memshare: %s: client_id:%d, size: %d", + __func__, client_id, memblock[client_id].size); dma_free_attrs(memsh_drv->dev, memblock[client_id].size, memblock[client_id].virtual_addr, @@ -643,8 +642,8 @@ static int handle_free_generic_req(void *req_h, void *req, void *conn_h) &attrs); free_client(client_id); } else { - pr_err("In %s, Request came for a guaranteed client cannot free up the memory\n", - __func__); + pr_err("In %s, Request came for a guaranteed client(client_id: %d) cannot free up the memory\n", + __func__, client_id); } if (flag) { @@ -947,6 +946,10 @@ static int memshare_child_probe(struct platform_device *pdev) pdev->dev.of_node, "qcom,allocate-boot-time"); + memblock[num_clients].client_request = of_property_read_bool( + pdev->dev.of_node, + "qcom,allocate-on-request"); + rc = of_property_read_string(pdev->dev.of_node, "label", &name); if (rc) { diff --git a/drivers/soc/qcom/memshare/msm_memshare.h b/drivers/soc/qcom/memshare/msm_memshare.h index c7123fb1314b..8a8657674fcf 100644 --- a/drivers/soc/qcom/memshare/msm_memshare.h +++ b/drivers/soc/qcom/memshare/msm_memshare.h @@ -1,4 +1,4 @@ -/* Copyright (c) 2013-2017, The Linux Foundation. All rights reserved. +/* Copyright (c) 2013-2018, The Linux Foundation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 and @@ -39,6 +39,8 @@ struct mem_blocks { uint32_t guarantee; /* Memory alloted or not */ uint32_t alloted; + /* Allocation on request from a client*/ + uint32_t client_request; /* Size required for client */ uint32_t size; /* diff --git a/drivers/staging/lustre/lustre/lmv/lmv_obd.c b/drivers/staging/lustre/lustre/lmv/lmv_obd.c index 635a93cc94de..eed7603db5ec 100644 --- a/drivers/staging/lustre/lustre/lmv/lmv_obd.c +++ b/drivers/staging/lustre/lustre/lmv/lmv_obd.c @@ -700,7 +700,7 @@ repeat_fid2path: memmove(ptr + strlen(gf->gf_path) + 1, ptr, strlen(ori_gf->gf_path)); - strncpy(ptr, gf->gf_path, strlen(gf->gf_path)); + strcpy(ptr, gf->gf_path); ptr += strlen(gf->gf_path); *ptr = '/'; } diff --git a/drivers/staging/rts5208/sd.c b/drivers/staging/rts5208/sd.c index 9a876ce92dbd..dc91cd29f1d2 100644 --- a/drivers/staging/rts5208/sd.c +++ b/drivers/staging/rts5208/sd.c @@ -4165,12 +4165,6 @@ RTY_SEND_CMD: rtsx_trace(chip); return STATUS_FAIL; } - - } else if (rsp_type == SD_RSP_TYPE_R0) { - if ((ptr[3] & 0x1E) != 0x03) { - rtsx_trace(chip); - return STATUS_FAIL; - } } } } diff --git a/drivers/tty/n_tty.c b/drivers/tty/n_tty.c index b1ec202099b2..b74de014cef1 100644 --- a/drivers/tty/n_tty.c +++ b/drivers/tty/n_tty.c @@ -165,15 +165,29 @@ static inline int tty_put_user(struct tty_struct *tty, unsigned char x, return put_user(x, ptr); } +/* If we are not echoing the data, perhaps this is a secret so erase it */ +static inline void zero_buffer(struct tty_struct *tty, u8 *buffer, int size) +{ + bool icanon = !!L_ICANON(tty); + bool no_echo = !L_ECHO(tty); + + if (icanon && no_echo) + memset(buffer, 0x00, size); +} + static inline int tty_copy_to_user(struct tty_struct *tty, void __user *to, - const void *from, + void *from, unsigned long n) { struct n_tty_data *ldata = tty->disc_data; + int retval; tty_audit_add_data(tty, from, n, ldata->icanon); - return copy_to_user(to, from, n); + retval = copy_to_user(to, from, n); + if (!retval) + zero_buffer(tty, from, n); + return retval; } /** @@ -2005,6 +2019,7 @@ static int copy_from_read_buf(struct tty_struct *tty, is_eof = n == 1 && read_buf(ldata, tail) == EOF_CHAR(tty); tty_audit_add_data(tty, read_buf_addr(ldata, tail), n, ldata->icanon); + zero_buffer(tty, read_buf_addr(ldata, tail), n); smp_store_release(&ldata->read_tail, ldata->read_tail + n); /* Turn single EOF into zero-length read */ if (L_EXTPROC(tty) && ldata->icanon && is_eof && diff --git a/drivers/tty/serial/8250/8250_mtk.c b/drivers/tty/serial/8250/8250_mtk.c index 78883ca64ddd..035810bbcd02 100644 --- a/drivers/tty/serial/8250/8250_mtk.c +++ b/drivers/tty/serial/8250/8250_mtk.c @@ -231,17 +231,17 @@ static int mtk8250_probe(struct platform_device *pdev) platform_set_drvdata(pdev, data); - pm_runtime_enable(&pdev->dev); - if (!pm_runtime_enabled(&pdev->dev)) { - err = mtk8250_runtime_resume(&pdev->dev); - if (err) - return err; - } + err = mtk8250_runtime_resume(&pdev->dev); + if (err) + return err; data->line = serial8250_register_8250_port(&uart); if (data->line < 0) return data->line; + pm_runtime_set_active(&pdev->dev); + pm_runtime_enable(&pdev->dev); + return 0; } @@ -252,13 +252,11 @@ static int mtk8250_remove(struct platform_device *pdev) pm_runtime_get_sync(&pdev->dev); serial8250_unregister_port(data->line); + mtk8250_runtime_suspend(&pdev->dev); pm_runtime_disable(&pdev->dev); pm_runtime_put_noidle(&pdev->dev); - if (!pm_runtime_status_suspended(&pdev->dev)) - mtk8250_runtime_suspend(&pdev->dev); - return 0; } diff --git a/drivers/tty/serial/kgdboc.c b/drivers/tty/serial/kgdboc.c index 2db68dfe497d..f2b0d8cee8ef 100644 --- a/drivers/tty/serial/kgdboc.c +++ b/drivers/tty/serial/kgdboc.c @@ -131,24 +131,6 @@ static void kgdboc_unregister_kbd(void) #define kgdboc_restore_input() #endif /* ! CONFIG_KDB_KEYBOARD */ -static int kgdboc_option_setup(char *opt) -{ - if (!opt) { - pr_err("kgdboc: config string not provided\n"); - return -EINVAL; - } - - if (strlen(opt) >= MAX_CONFIG_LEN) { - printk(KERN_ERR "kgdboc: config string too long\n"); - return -ENOSPC; - } - strcpy(config, opt); - - return 0; -} - -__setup("kgdboc=", kgdboc_option_setup); - static void cleanup_kgdboc(void) { if (kgdb_unregister_nmi_console()) @@ -162,15 +144,13 @@ static int configure_kgdboc(void) { struct tty_driver *p; int tty_line = 0; - int err; + int err = -ENODEV; char *cptr = config; struct console *cons; - err = kgdboc_option_setup(config); - if (err || !strlen(config) || isspace(config[0])) + if (!strlen(config) || isspace(config[0])) goto noconfig; - err = -ENODEV; kgdboc_io_ops.is_console = 0; kgdb_tty_driver = NULL; @@ -252,7 +232,7 @@ static void kgdboc_put_char(u8 chr) static int param_set_kgdboc_var(const char *kmessage, struct kernel_param *kp) { - int len = strlen(kmessage); + size_t len = strlen(kmessage); if (len >= MAX_CONFIG_LEN) { printk(KERN_ERR "kgdboc: config string too long\n"); @@ -274,7 +254,7 @@ static int param_set_kgdboc_var(const char *kmessage, struct kernel_param *kp) strcpy(config, kmessage); /* Chop out \n char as a result of echo */ - if (config[len - 1] == '\n') + if (len && config[len - 1] == '\n') config[len - 1] = '\0'; if (configured == 1) @@ -318,6 +298,25 @@ static struct kgdb_io kgdboc_io_ops = { }; #ifdef CONFIG_KGDB_SERIAL_CONSOLE +static int kgdboc_option_setup(char *opt) +{ + if (!opt) { + pr_err("config string not provided\n"); + return -EINVAL; + } + + if (strlen(opt) >= MAX_CONFIG_LEN) { + pr_err("config string too long\n"); + return -ENOSPC; + } + strcpy(config, opt); + + return 0; +} + +__setup("kgdboc=", kgdboc_option_setup); + + /* This is only available if kgdboc is a built in for early debugging */ static int __init kgdboc_early_init(char *opt) { diff --git a/drivers/tty/tty_buffer.c b/drivers/tty/tty_buffer.c index 8f3566cde3eb..355e9cad680d 100644 --- a/drivers/tty/tty_buffer.c +++ b/drivers/tty/tty_buffer.c @@ -454,6 +454,8 @@ receive_buf(struct tty_struct *tty, struct tty_buffer *head, int count) if (count && disc->ops->receive_buf) disc->ops->receive_buf(tty, p, f, count); } + if (count > 0) + memset(p, 0, count); return count; } diff --git a/drivers/usb/core/hub.c b/drivers/usb/core/hub.c index 1e25aa251c05..ab58cb3a9b6a 100644 --- a/drivers/usb/core/hub.c +++ b/drivers/usb/core/hub.c @@ -2222,7 +2222,7 @@ static int usb_enumerate_device_otg(struct usb_device *udev) /* descriptor may appear anywhere in config */ err = __usb_get_extra_descriptor(udev->rawdescriptors[0], le16_to_cpu(udev->config[0].desc.wTotalLength), - USB_DT_OTG, (void **) &desc); + USB_DT_OTG, (void **) &desc, sizeof(*desc)); if (err || !(desc->bmAttributes & USB_OTG_HNP)) return 0; @@ -2768,7 +2768,9 @@ static int hub_port_reset(struct usb_hub *hub, int port1, USB_PORT_FEAT_C_BH_PORT_RESET); usb_clear_port_feature(hub->hdev, port1, USB_PORT_FEAT_C_PORT_LINK_STATE); - usb_clear_port_feature(hub->hdev, port1, + + if (udev) + usb_clear_port_feature(hub->hdev, port1, USB_PORT_FEAT_C_CONNECTION); /* diff --git a/drivers/usb/core/quirks.c b/drivers/usb/core/quirks.c index 1e8f68960014..cf378b1ed373 100644 --- a/drivers/usb/core/quirks.c +++ b/drivers/usb/core/quirks.c @@ -64,6 +64,9 @@ static const struct usb_device_id usb_quirk_list[] = { /* Microsoft LifeCam-VX700 v2.0 */ { USB_DEVICE(0x045e, 0x0770), .driver_info = USB_QUIRK_RESET_RESUME }, + /* Cherry Stream G230 2.0 (G85-231) and 3.0 (G85-232) */ + { USB_DEVICE(0x046a, 0x0023), .driver_info = USB_QUIRK_RESET_RESUME }, + /* Logitech HD Pro Webcams C920, C920-C, C925e and C930e */ { USB_DEVICE(0x046d, 0x082d), .driver_info = USB_QUIRK_DELAY_INIT }, { USB_DEVICE(0x046d, 0x0841), .driver_info = USB_QUIRK_DELAY_INIT }, @@ -185,6 +188,10 @@ static const struct usb_device_id usb_quirk_list[] = { /* Midiman M-Audio Keystation 88es */ { USB_DEVICE(0x0763, 0x0192), .driver_info = USB_QUIRK_RESET_RESUME }, + /* SanDisk Ultra Fit and Ultra Flair */ + { USB_DEVICE(0x0781, 0x5583), .driver_info = USB_QUIRK_NO_LPM }, + { USB_DEVICE(0x0781, 0x5591), .driver_info = USB_QUIRK_NO_LPM }, + /* M-Systems Flash Disk Pioneers */ { USB_DEVICE(0x08ec, 0x1000), .driver_info = USB_QUIRK_RESET_RESUME }, diff --git a/drivers/usb/core/usb.c b/drivers/usb/core/usb.c index 74087b265317..d96ed8fe6442 100644 --- a/drivers/usb/core/usb.c +++ b/drivers/usb/core/usb.c @@ -726,14 +726,14 @@ EXPORT_SYMBOL(usb_get_xfer_ring_dma_addr); */ int __usb_get_extra_descriptor(char *buffer, unsigned size, - unsigned char type, void **ptr) + unsigned char type, void **ptr, size_t minsize) { struct usb_descriptor_header *header; while (size >= sizeof(struct usb_descriptor_header)) { header = (struct usb_descriptor_header *)buffer; - if (header->bLength < 2) { + if (header->bLength < 2 || header->bLength > size) { printk(KERN_ERR "%s: bogus descriptor, type %d length %d\n", usbcore_name, @@ -742,7 +742,7 @@ int __usb_get_extra_descriptor(char *buffer, unsigned size, return -1; } - if (header->bDescriptorType == type) { + if (header->bDescriptorType == type && header->bLength >= minsize) { *ptr = header; return 0; } diff --git a/drivers/usb/gadget/udc/dummy_hcd.c b/drivers/usb/gadget/udc/dummy_hcd.c index eb876ed96861..85f1f282c1d5 100644 --- a/drivers/usb/gadget/udc/dummy_hcd.c +++ b/drivers/usb/gadget/udc/dummy_hcd.c @@ -379,11 +379,10 @@ static void set_link_state_by_speed(struct dummy_hcd *dum_hcd) USB_PORT_STAT_CONNECTION) == 0) dum_hcd->port_status |= (USB_PORT_STAT_C_CONNECTION << 16); - if ((dum_hcd->port_status & - USB_PORT_STAT_ENABLE) == 1 && - (dum_hcd->port_status & - USB_SS_PORT_LS_U0) == 1 && - dum_hcd->rh_state != DUMMY_RH_SUSPENDED) + if ((dum_hcd->port_status & USB_PORT_STAT_ENABLE) && + (dum_hcd->port_status & + USB_PORT_STAT_LINK_STATE) == USB_SS_PORT_LS_U0 && + dum_hcd->rh_state != DUMMY_RH_SUSPENDED) dum_hcd->active = 1; } } else { diff --git a/drivers/usb/host/hwa-hc.c b/drivers/usb/host/hwa-hc.c index 1db0626c8bf4..97750f162f01 100644 --- a/drivers/usb/host/hwa-hc.c +++ b/drivers/usb/host/hwa-hc.c @@ -654,7 +654,7 @@ static int hwahc_security_create(struct hwahc *hwahc) top = itr + itr_size; result = __usb_get_extra_descriptor(usb_dev->rawdescriptors[index], le16_to_cpu(usb_dev->actconfig->desc.wTotalLength), - USB_DT_SECURITY, (void **) &secd); + USB_DT_SECURITY, (void **) &secd, sizeof(*secd)); if (result == -1) { dev_warn(dev, "BUG? WUSB host has no security descriptors\n"); return 0; diff --git a/drivers/usb/host/xhci-hub.c b/drivers/usb/host/xhci-hub.c index ca3517d462da..61da1a22b98a 100644 --- a/drivers/usb/host/xhci-hub.c +++ b/drivers/usb/host/xhci-hub.c @@ -747,7 +747,7 @@ static u32 xhci_get_port_status(struct usb_hcd *hcd, status |= USB_PORT_STAT_SUSPEND; } if ((raw_port_status & PORT_PLS_MASK) == XDEV_RESUME && - !DEV_SUPERSPEED_ANY(raw_port_status)) { + !DEV_SUPERSPEED_ANY(raw_port_status) && hcd->speed < HCD_USB3) { if ((raw_port_status & PORT_RESET) || !(raw_port_status & PORT_PE)) return 0xffffffff; @@ -793,7 +793,7 @@ static u32 xhci_get_port_status(struct usb_hcd *hcd, time_left = wait_for_completion_timeout( &bus_state->rexit_done[wIndex], msecs_to_jiffies( - XHCI_MAX_REXIT_TIMEOUT)); + XHCI_MAX_REXIT_TIMEOUT_MS)); spin_lock_irqsave(&xhci->lock, flags); if (time_left) { @@ -807,7 +807,7 @@ static u32 xhci_get_port_status(struct usb_hcd *hcd, } else { int port_status = readl(port_array[wIndex]); xhci_warn(xhci, "Port resume took longer than %i msec, port status = 0x%x\n", - XHCI_MAX_REXIT_TIMEOUT, + XHCI_MAX_REXIT_TIMEOUT_MS, port_status); status |= USB_PORT_STAT_SUSPEND; clear_bit(wIndex, &bus_state->rexit_ports); @@ -1473,13 +1473,16 @@ int xhci_bus_suspend(struct usb_hcd *hcd) __le32 __iomem **port_array; struct xhci_bus_state *bus_state; unsigned long flags; + u32 portsc_buf[USB_MAXCHILDREN]; + bool wake_enabled; max_ports = xhci_get_ports(hcd, &port_array); bus_state = &xhci->bus_state[hcd_index(hcd)]; + wake_enabled = hcd->self.root_hub->do_remote_wakeup; spin_lock_irqsave(&xhci->lock, flags); - if (hcd->self.root_hub->do_remote_wakeup) { + if (wake_enabled) { if (bus_state->resuming_ports || /* USB2 */ bus_state->port_remote_wakeup) { /* USB3 */ spin_unlock_irqrestore(&xhci->lock, flags); @@ -1487,26 +1490,36 @@ int xhci_bus_suspend(struct usb_hcd *hcd) return -EBUSY; } } - - port_index = max_ports; + /* + * Prepare ports for suspend, but don't write anything before all ports + * are checked and we know bus suspend can proceed + */ bus_state->bus_suspended = 0; + port_index = max_ports; while (port_index--) { - /* suspend the port if the port is not suspended */ u32 t1, t2; - int slot_id; t1 = readl(port_array[port_index]); t2 = xhci_port_state_to_neutral(t1); + portsc_buf[port_index] = 0; - if ((t1 & PORT_PE) && !(t1 & PORT_PLS_MASK)) { - xhci_dbg(xhci, "port %d not suspended\n", port_index); - slot_id = xhci_find_slot_id_by_port(hcd, xhci, - port_index + 1); - if (slot_id) { + /* Bail out if a USB3 port has a new device in link training */ + if ((t1 & PORT_PLS_MASK) == XDEV_POLLING) { + bus_state->bus_suspended = 0; + spin_unlock_irqrestore(&xhci->lock, flags); + xhci_dbg(xhci, "Bus suspend bailout, port in polling\n"); + return -EBUSY; + } + + /* suspend ports in U0, or bail out for new connect changes */ + if ((t1 & PORT_PE) && (t1 & PORT_PLS_MASK) == XDEV_U0) { + if ((t1 & PORT_CSC) && wake_enabled) { + bus_state->bus_suspended = 0; spin_unlock_irqrestore(&xhci->lock, flags); - xhci_stop_device(xhci, slot_id, 1); - spin_lock_irqsave(&xhci->lock, flags); + xhci_dbg(xhci, "Bus suspend bailout, port connect change\n"); + return -EBUSY; } + xhci_dbg(xhci, "port %d not suspended\n", port_index); t2 &= ~PORT_PLS_MASK; t2 |= PORT_LINK_STROBE | XDEV_U3; set_bit(port_index, &bus_state->bus_suspended); @@ -1515,7 +1528,7 @@ int xhci_bus_suspend(struct usb_hcd *hcd) * including the USB 3.0 roothub, but only if CONFIG_PM * is enabled, so also enable remote wake here. */ - if (hcd->self.root_hub->do_remote_wakeup) { + if (wake_enabled) { if (t1 & PORT_CONNECT) { t2 |= PORT_WKOC_E | PORT_WKDISC_E; t2 &= ~PORT_WKCONN_E; @@ -1528,7 +1541,26 @@ int xhci_bus_suspend(struct usb_hcd *hcd) t1 = xhci_port_state_to_neutral(t1); if (t1 != t2) - writel(t2, port_array[port_index]); + portsc_buf[port_index] = t2; + } + + /* write port settings, stopping and suspending ports if needed */ + port_index = max_ports; + while (port_index--) { + if (!portsc_buf[port_index]) + continue; + if (test_bit(port_index, &bus_state->bus_suspended)) { + int slot_id; + + slot_id = xhci_find_slot_id_by_port(hcd, xhci, + port_index + 1); + if (slot_id) { + spin_unlock_irqrestore(&xhci->lock, flags); + xhci_stop_device(xhci, slot_id, 1); + spin_lock_irqsave(&xhci->lock, flags); + } + } + writel(portsc_buf[port_index], port_array[port_index]); } hcd->state = HC_STATE_SUSPENDED; bus_state->next_statechange = jiffies + msecs_to_jiffies(10); diff --git a/drivers/usb/host/xhci-ring.c b/drivers/usb/host/xhci-ring.c index 5bfe47816ac3..e6d366d4e80b 100644 --- a/drivers/usb/host/xhci-ring.c +++ b/drivers/usb/host/xhci-ring.c @@ -1673,7 +1673,7 @@ static void handle_port_status(struct xhci_hcd *xhci, * RExit to a disconnect state). If so, let the the driver know it's * out of the RExit state. */ - if (!DEV_SUPERSPEED_ANY(temp) && + if (!DEV_SUPERSPEED_ANY(temp) && hcd->speed < HCD_USB3 && test_and_clear_bit(faked_port_index, &bus_state->rexit_ports)) { complete(&bus_state->rexit_done[faked_port_index]); diff --git a/drivers/usb/host/xhci.c b/drivers/usb/host/xhci.c index abe6d3c17047..3e11317db602 100644 --- a/drivers/usb/host/xhci.c +++ b/drivers/usb/host/xhci.c @@ -4442,6 +4442,14 @@ static u16 xhci_calculate_u1_timeout(struct xhci_hcd *xhci, { unsigned long long timeout_ns; + /* Prevent U1 if service interval is shorter than U1 exit latency */ + if (usb_endpoint_xfer_int(desc) || usb_endpoint_xfer_isoc(desc)) { + if (xhci_service_interval_to_ns(desc) <= udev->u1_params.mel) { + dev_dbg(&udev->dev, "Disable U1, ESIT shorter than exit latency\n"); + return USB3_LPM_DISABLED; + } + } + if (xhci->quirks & XHCI_INTEL_HOST) timeout_ns = xhci_calculate_intel_u1_timeout(udev, desc); else @@ -4498,6 +4506,14 @@ static u16 xhci_calculate_u2_timeout(struct xhci_hcd *xhci, { unsigned long long timeout_ns; + /* Prevent U2 if service interval is shorter than U2 exit latency */ + if (usb_endpoint_xfer_int(desc) || usb_endpoint_xfer_isoc(desc)) { + if (xhci_service_interval_to_ns(desc) <= udev->u2_params.mel) { + dev_dbg(&udev->dev, "Disable U2, ESIT shorter than exit latency\n"); + return USB3_LPM_DISABLED; + } + } + if (xhci->quirks & XHCI_INTEL_HOST) timeout_ns = xhci_calculate_intel_u2_timeout(udev, desc); else diff --git a/drivers/usb/host/xhci.h b/drivers/usb/host/xhci.h index 72beaa47c15b..b3454c06bb0c 100644 --- a/drivers/usb/host/xhci.h +++ b/drivers/usb/host/xhci.h @@ -1490,7 +1490,7 @@ struct xhci_bus_state { * It can take up to 20 ms to transition from RExit to U0 on the * Intel Lynx Point LP xHCI host. */ -#define XHCI_MAX_REXIT_TIMEOUT (20 * 1000) +#define XHCI_MAX_REXIT_TIMEOUT_MS 20 static inline unsigned int hcd_index(struct usb_hcd *hcd) { diff --git a/drivers/usb/misc/appledisplay.c b/drivers/usb/misc/appledisplay.c index b15842c6f916..993f4da065c3 100644 --- a/drivers/usb/misc/appledisplay.c +++ b/drivers/usb/misc/appledisplay.c @@ -64,6 +64,7 @@ static const struct usb_device_id appledisplay_table[] = { { APPLEDISPLAY_DEVICE(0x921c) }, { APPLEDISPLAY_DEVICE(0x921d) }, { APPLEDISPLAY_DEVICE(0x9222) }, + { APPLEDISPLAY_DEVICE(0x9226) }, { APPLEDISPLAY_DEVICE(0x9236) }, /* Terminating entry */ diff --git a/drivers/usb/misc/diag_ipc_bridge.c b/drivers/usb/misc/diag_ipc_bridge.c index 2ff3aa021bf8..cb3aa9375ca3 100644 --- a/drivers/usb/misc/diag_ipc_bridge.c +++ b/drivers/usb/misc/diag_ipc_bridge.c @@ -732,6 +732,8 @@ static const struct usb_device_id diag_bridge_ids[] = { .driver_info = DEV_ID(0), }, { USB_DEVICE_INTERFACE_NUMBER(0x5c6, 0x901D, 0), .driver_info = DEV_ID(0), }, + { USB_DEVICE_INTERFACE_NUMBER(0x5c6, 0x901F, 0), + .driver_info = DEV_ID(0), }, { USB_DEVICE_INTERFACE_NUMBER(0x5c6, 0x9034, 0), .driver_info = DEV_ID(0), }, { USB_DEVICE_INTERFACE_NUMBER(0x5c6, 0x9048, 0), diff --git a/drivers/usb/misc/ks_bridge.c b/drivers/usb/misc/ks_bridge.c index 4004ba0437d5..3497880dea09 100644 --- a/drivers/usb/misc/ks_bridge.c +++ b/drivers/usb/misc/ks_bridge.c @@ -462,6 +462,7 @@ static const struct usb_device_id ksb_usb_ids[] = { { USB_DEVICE_INTERFACE_NUMBER(0x5c6, 0x9025, 0), }, { USB_DEVICE_INTERFACE_NUMBER(0x5c6, 0x9091, 0), }, { USB_DEVICE_INTERFACE_NUMBER(0x5c6, 0x901D, 0), }, + { USB_DEVICE_INTERFACE_NUMBER(0x5c6, 0x901F, 0), }, { USB_DEVICE_INTERFACE_NUMBER(0x5c6, 0x900E, 0), }, { USB_DEVICE_INTERFACE_NUMBER(0x5c6, 0x9900, 0), }, { USB_DEVICE_INTERFACE_NUMBER(0x5c6, 0x9901, 0), }, diff --git a/drivers/usb/storage/unusual_realtek.h b/drivers/usb/storage/unusual_realtek.h index e41f50c95ed4..f5fc3271e19c 100644 --- a/drivers/usb/storage/unusual_realtek.h +++ b/drivers/usb/storage/unusual_realtek.h @@ -38,4 +38,14 @@ UNUSUAL_DEV(0x0bda, 0x0159, 0x0000, 0x9999, "USB Card Reader", USB_SC_DEVICE, USB_PR_DEVICE, init_realtek_cr, 0), +UNUSUAL_DEV(0x0bda, 0x0177, 0x0000, 0x9999, + "Realtek", + "USB Card Reader", + USB_SC_DEVICE, USB_PR_DEVICE, init_realtek_cr, 0), + +UNUSUAL_DEV(0x0bda, 0x0184, 0x0000, 0x9999, + "Realtek", + "USB Card Reader", + USB_SC_DEVICE, USB_PR_DEVICE, init_realtek_cr, 0), + #endif /* defined(CONFIG_USB_STORAGE_REALTEK) || ... */ diff --git a/fs/9p/vfs_dir.c b/fs/9p/vfs_dir.c index 5cc00e56206e..7d889f56b8e7 100644 --- a/fs/9p/vfs_dir.c +++ b/fs/9p/vfs_dir.c @@ -76,15 +76,6 @@ static inline int dt_type(struct p9_wstat *mistat) return rettype; } -static void p9stat_init(struct p9_wstat *stbuf) -{ - stbuf->name = NULL; - stbuf->uid = NULL; - stbuf->gid = NULL; - stbuf->muid = NULL; - stbuf->extension = NULL; -} - /** * v9fs_alloc_rdir_buf - Allocate buffer used for read and readdir * @filp: opened file structure @@ -145,12 +136,10 @@ static int v9fs_dir_readdir(struct file *file, struct dir_context *ctx) rdir->tail = n; } while (rdir->head < rdir->tail) { - p9stat_init(&st); err = p9stat_read(fid->clnt, rdir->buf + rdir->head, rdir->tail - rdir->head, &st); if (err) { p9_debug(P9_DEBUG_VFS, "returned %d\n", err); - p9stat_free(&st); return -EIO; } reclen = st.size+2; diff --git a/fs/bfs/inode.c b/fs/bfs/inode.c index fdcb4d69f430..4714c55c1ae5 100644 --- a/fs/bfs/inode.c +++ b/fs/bfs/inode.c @@ -350,7 +350,8 @@ static int bfs_fill_super(struct super_block *s, void *data, int silent) s->s_magic = BFS_MAGIC; - if (le32_to_cpu(bfs_sb->s_start) > le32_to_cpu(bfs_sb->s_end)) { + if (le32_to_cpu(bfs_sb->s_start) > le32_to_cpu(bfs_sb->s_end) || + le32_to_cpu(bfs_sb->s_start) < BFS_BSIZE) { printf("Superblock is corrupted\n"); goto out1; } @@ -359,9 +360,11 @@ static int bfs_fill_super(struct super_block *s, void *data, int silent) sizeof(struct bfs_inode) + BFS_ROOT_INO - 1; imap_len = (info->si_lasti / 8) + 1; - info->si_imap = kzalloc(imap_len, GFP_KERNEL); - if (!info->si_imap) + info->si_imap = kzalloc(imap_len, GFP_KERNEL | __GFP_NOWARN); + if (!info->si_imap) { + printf("Cannot allocate %u bytes\n", imap_len); goto out1; + } for (i = 0; i < BFS_ROOT_INO; i++) set_bit(i, info->si_imap); diff --git a/fs/btrfs/disk-io.c b/fs/btrfs/disk-io.c index b0875ef48522..1f21c6c33228 100644 --- a/fs/btrfs/disk-io.c +++ b/fs/btrfs/disk-io.c @@ -445,9 +445,9 @@ static int btree_read_extent_buffer_pages(struct btrfs_root *root, int mirror_num = 0; int failed_mirror = 0; - clear_bit(EXTENT_BUFFER_CORRUPT, &eb->bflags); io_tree = &BTRFS_I(root->fs_info->btree_inode)->io_tree; while (1) { + clear_bit(EXTENT_BUFFER_CORRUPT, &eb->bflags); ret = read_extent_buffer_pages(io_tree, eb, start, WAIT_COMPLETE, btree_get_extent, mirror_num); @@ -459,14 +459,6 @@ static int btree_read_extent_buffer_pages(struct btrfs_root *root, ret = -EIO; } - /* - * This buffer's crc is fine, but its contents are corrupted, so - * there is no reason to read the other copies, they won't be - * any less wrong. - */ - if (test_bit(EXTENT_BUFFER_CORRUPT, &eb->bflags)) - break; - num_copies = btrfs_num_copies(root->fs_info, eb->start, eb->len); if (num_copies == 1) diff --git a/fs/btrfs/extent-tree.c b/fs/btrfs/extent-tree.c index 80cd28456f08..13ff0fdae03e 100644 --- a/fs/btrfs/extent-tree.c +++ b/fs/btrfs/extent-tree.c @@ -10708,17 +10708,9 @@ int btrfs_trim_fs(struct btrfs_root *root, struct fstrim_range *range) u64 start; u64 end; u64 trimmed = 0; - u64 total_bytes = btrfs_super_total_bytes(fs_info->super_copy); int ret = 0; - /* - * try to trim all FS space, our block group may start from non-zero. - */ - if (range->len == total_bytes) - cache = btrfs_lookup_first_block_group(fs_info, range->start); - else - cache = btrfs_lookup_block_group(fs_info, range->start); - + cache = btrfs_lookup_first_block_group(fs_info, range->start); while (cache) { if (cache->key.objectid >= (range->start + range->len)) { btrfs_put_block_group(cache); diff --git a/fs/btrfs/free-space-cache.c b/fs/btrfs/free-space-cache.c index 1aa897dd9ce3..6c0161284a9e 100644 --- a/fs/btrfs/free-space-cache.c +++ b/fs/btrfs/free-space-cache.c @@ -2469,6 +2469,7 @@ void btrfs_dump_free_space(struct btrfs_block_group_cache *block_group, struct rb_node *n; int count = 0; + spin_lock(&ctl->tree_lock); for (n = rb_first(&ctl->free_space_offset); n; n = rb_next(n)) { info = rb_entry(n, struct btrfs_free_space, offset_index); if (info->bytes >= bytes && !block_group->ro) @@ -2478,6 +2479,7 @@ void btrfs_dump_free_space(struct btrfs_block_group_cache *block_group, info->offset, info->bytes, (info->bitmap) ? "yes" : "no"); } + spin_unlock(&ctl->tree_lock); btrfs_info(block_group->fs_info, "block group has cluster?: %s", list_empty(&block_group->cluster_list) ? "no" : "yes"); btrfs_info(block_group->fs_info, diff --git a/fs/btrfs/ioctl.c b/fs/btrfs/ioctl.c index 150d3c891815..3379490ce54d 100644 --- a/fs/btrfs/ioctl.c +++ b/fs/btrfs/ioctl.c @@ -378,7 +378,6 @@ static noinline int btrfs_ioctl_fitrim(struct file *file, void __user *arg) struct fstrim_range range; u64 minlen = ULLONG_MAX; u64 num_devices = 0; - u64 total_bytes = btrfs_super_total_bytes(fs_info->super_copy); int ret; if (!capable(CAP_SYS_ADMIN)) @@ -402,11 +401,15 @@ static noinline int btrfs_ioctl_fitrim(struct file *file, void __user *arg) return -EOPNOTSUPP; if (copy_from_user(&range, arg, sizeof(range))) return -EFAULT; - if (range.start > total_bytes || - range.len < fs_info->sb->s_blocksize) + + /* + * NOTE: Don't truncate the range using super->total_bytes. Bytenr of + * block group is in the logical address space, which can be any + * sectorsize aligned bytenr in the range [0, U64_MAX]. + */ + if (range.len < fs_info->sb->s_blocksize) return -EINVAL; - range.len = min(range.len, total_bytes - range.start); range.minlen = max(range.minlen, minlen); ret = btrfs_trim_fs(fs_info->tree_root, &range); if (ret < 0) diff --git a/fs/btrfs/super.c b/fs/btrfs/super.c index 3bd2233737ac..0f99336c37eb 100644 --- a/fs/btrfs/super.c +++ b/fs/btrfs/super.c @@ -2104,6 +2104,7 @@ static long btrfs_control_ioctl(struct file *file, unsigned int cmd, vol = memdup_user((void __user *)arg, sizeof(*vol)); if (IS_ERR(vol)) return PTR_ERR(vol); + vol->name[BTRFS_PATH_NAME_MAX] = '\0'; switch (cmd) { case BTRFS_IOC_SCAN_DEV: diff --git a/fs/btrfs/transaction.c b/fs/btrfs/transaction.c index be8eae80ff65..098016338f98 100644 --- a/fs/btrfs/transaction.c +++ b/fs/btrfs/transaction.c @@ -1821,6 +1821,9 @@ int btrfs_commit_transaction(struct btrfs_trans_handle *trans, return ret; } + btrfs_trans_release_metadata(trans, root); + trans->block_rsv = NULL; + /* make a pass through all the delayed refs we have so far * any runnings procs may add more while we are here */ @@ -1830,9 +1833,6 @@ int btrfs_commit_transaction(struct btrfs_trans_handle *trans, return ret; } - btrfs_trans_release_metadata(trans, root); - trans->block_rsv = NULL; - cur_trans = trans->transaction; /* diff --git a/fs/cifs/dir.c b/fs/cifs/dir.c index 76dacd5307b9..afd317eb9db9 100644 --- a/fs/cifs/dir.c +++ b/fs/cifs/dir.c @@ -163,7 +163,7 @@ cifs_bp_rename_retry: cifs_dbg(FYI, "using cifs_sb prepath <%s>\n", cifs_sb->prepath); memcpy(full_path+dfsplen+1, cifs_sb->prepath, pplen-1); - full_path[dfsplen] = '\\'; + full_path[dfsplen] = dirsep; for (i = 0; i < pplen-1; i++) if (full_path[dfsplen+1+i] == '/') full_path[dfsplen+1+i] = CIFS_DIR_SEP(cifs_sb); diff --git a/fs/exec.c b/fs/exec.c index 0428c34d4773..6bbea71c6d92 100644 --- a/fs/exec.c +++ b/fs/exec.c @@ -1077,15 +1077,14 @@ killed: return -EAGAIN; } -char *get_task_comm(char *buf, struct task_struct *tsk) +char *__get_task_comm(char *buf, size_t buf_size, struct task_struct *tsk) { - /* buf must be at least sizeof(tsk->comm) in size */ task_lock(tsk); - strncpy(buf, tsk->comm, sizeof(tsk->comm)); + strncpy(buf, tsk->comm, buf_size); task_unlock(tsk); return buf; } -EXPORT_SYMBOL_GPL(get_task_comm); +EXPORT_SYMBOL_GPL(__get_task_comm); /* * These functions flushes out all traces of the currently running executable diff --git a/fs/ext2/xattr.c b/fs/ext2/xattr.c index 24736c8b3d51..e66047d6943f 100644 --- a/fs/ext2/xattr.c +++ b/fs/ext2/xattr.c @@ -606,9 +606,9 @@ skip_replace: } cleanup: - brelse(bh); if (!(bh && header == HDR(bh))) kfree(header); + brelse(bh); up_write(&EXT2_I(inode)->xattr_sem); return error; diff --git a/fs/gfs2/ops_fstype.c b/fs/gfs2/ops_fstype.c index ad23a9257418..9e3f3224e54a 100644 --- a/fs/gfs2/ops_fstype.c +++ b/fs/gfs2/ops_fstype.c @@ -71,13 +71,13 @@ static struct gfs2_sbd *init_sbd(struct super_block *sb) if (!sdp) return NULL; - sb->s_fs_info = sdp; sdp->sd_vfs = sb; sdp->sd_lkstats = alloc_percpu(struct gfs2_pcpu_lkstats); if (!sdp->sd_lkstats) { kfree(sdp); return NULL; } + sb->s_fs_info = sdp; set_bit(SDF_NOJOURNALID, &sdp->sd_flags); gfs2_tune_init(&sdp->sd_tune); diff --git a/fs/kernfs/symlink.c b/fs/kernfs/symlink.c index db272528ab5b..b3b293e2c099 100644 --- a/fs/kernfs/symlink.c +++ b/fs/kernfs/symlink.c @@ -88,7 +88,7 @@ static int kernfs_get_target_path(struct kernfs_node *parent, int slen = strlen(kn->name); len -= slen; - strncpy(s + len, kn->name, slen); + memcpy(s + len, kn->name, slen); if (len) s[--len] = '/'; diff --git a/fs/namei.c b/fs/namei.c index ea6050b6134a..57f030641306 100644 --- a/fs/namei.c +++ b/fs/namei.c @@ -884,6 +884,8 @@ static inline void put_link(struct nameidata *nd) int sysctl_protected_symlinks __read_mostly = 0; int sysctl_protected_hardlinks __read_mostly = 0; +int sysctl_protected_fifos __read_mostly; +int sysctl_protected_regular __read_mostly; /** * may_follow_link - Check symlink following for unsafe situations @@ -997,6 +999,45 @@ static int may_linkat(struct path *link) return -EPERM; } +/** + * may_create_in_sticky - Check whether an O_CREAT open in a sticky directory + * should be allowed, or not, on files that already + * exist. + * @dir: the sticky parent directory + * @inode: the inode of the file to open + * + * Block an O_CREAT open of a FIFO (or a regular file) when: + * - sysctl_protected_fifos (or sysctl_protected_regular) is enabled + * - the file already exists + * - we are in a sticky directory + * - we don't own the file + * - the owner of the directory doesn't own the file + * - the directory is world writable + * If the sysctl_protected_fifos (or sysctl_protected_regular) is set to 2 + * the directory doesn't have to be world writable: being group writable will + * be enough. + * + * Returns 0 if the open is allowed, -ve on error. + */ +static int may_create_in_sticky(struct dentry * const dir, + struct inode * const inode) +{ + if ((!sysctl_protected_fifos && S_ISFIFO(inode->i_mode)) || + (!sysctl_protected_regular && S_ISREG(inode->i_mode)) || + likely(!(dir->d_inode->i_mode & S_ISVTX)) || + uid_eq(inode->i_uid, dir->d_inode->i_uid) || + uid_eq(current_fsuid(), inode->i_uid)) + return 0; + + if (likely(dir->d_inode->i_mode & 0002) || + (dir->d_inode->i_mode & 0020 && + ((sysctl_protected_fifos >= 2 && S_ISFIFO(inode->i_mode)) || + (sysctl_protected_regular >= 2 && S_ISREG(inode->i_mode))))) { + return -EACCES; + } + return 0; +} + static __always_inline const char *get_link(struct nameidata *nd) { @@ -3204,9 +3245,15 @@ finish_open: error = -ELOOP; goto out; } - error = -EISDIR; - if ((open_flag & O_CREAT) && d_is_dir(nd->path.dentry)) - goto out; + if (open_flag & O_CREAT) { + error = -EISDIR; + if (d_is_dir(nd->path.dentry)) + goto out; + error = may_create_in_sticky(dir, + d_backing_inode(nd->path.dentry)); + if (unlikely(error)) + goto out; + } error = -ENOTDIR; if ((nd->flags & LOOKUP_DIRECTORY) && !d_can_lookup(nd->path.dentry)) goto out; diff --git a/fs/sdcardfs/derived_perm.c b/fs/sdcardfs/derived_perm.c index 85126ec6533c..1f142fed5a5e 100644 --- a/fs/sdcardfs/derived_perm.c +++ b/fs/sdcardfs/derived_perm.c @@ -62,6 +62,7 @@ void get_derived_permission_new(struct dentry *parent, struct dentry *dentry, int err; struct qstr q_Android = QSTR_LITERAL("Android"); struct qstr q_data = QSTR_LITERAL("data"); + struct qstr q_sandbox = QSTR_LITERAL("sandbox"); struct qstr q_obb = QSTR_LITERAL("obb"); struct qstr q_media = QSTR_LITERAL("media"); struct qstr q_cache = QSTR_LITERAL("cache"); @@ -110,6 +111,9 @@ void get_derived_permission_new(struct dentry *parent, struct dentry *dentry, if (qstr_case_eq(name, &q_data)) { /* App-specific directories inside; let anyone traverse */ info->data->perm = PERM_ANDROID_DATA; + } else if (qstr_case_eq(name, &q_sandbox)) { + /* App-specific directories inside; let anyone traverse */ + info->data->perm = PERM_ANDROID_DATA; } else if (qstr_case_eq(name, &q_obb)) { /* App-specific directories inside; let anyone traverse */ info->data->perm = PERM_ANDROID_OBB; @@ -356,7 +360,8 @@ int need_graft_path(struct dentry *dentry) struct sdcardfs_sb_info *sbi = SDCARDFS_SB(dentry->d_sb); struct qstr obb = QSTR_LITERAL("obb"); - if (parent_info->data->perm == PERM_ANDROID && + if (!sbi->options.unshared_obb && + parent_info->data->perm == PERM_ANDROID && qstr_case_eq(&dentry->d_name, &obb)) { /* /Android/obb is the base obbpath of DERIVED_UNIFIED */ diff --git a/fs/sdcardfs/main.c b/fs/sdcardfs/main.c index 3151ec9cf7e9..6e44903b3d2f 100644 --- a/fs/sdcardfs/main.c +++ b/fs/sdcardfs/main.c @@ -35,6 +35,7 @@ enum { Opt_gid_derivation, Opt_default_normal, Opt_nocache, + Opt_unshared_obb, Opt_err, }; @@ -48,6 +49,7 @@ static const match_table_t sdcardfs_tokens = { {Opt_multiuser, "multiuser"}, {Opt_gid_derivation, "derive_gid"}, {Opt_default_normal, "default_normal"}, + {Opt_unshared_obb, "unshared_obb"}, {Opt_reserved_mb, "reserved_mb=%u"}, {Opt_nocache, "nocache"}, {Opt_err, NULL} @@ -134,6 +136,9 @@ static int parse_options(struct super_block *sb, char *options, int silent, case Opt_nocache: opts->nocache = true; break; + case Opt_unshared_obb: + opts->unshared_obb = true; + break; /* unknown option */ default: if (!silent) @@ -187,13 +192,16 @@ int parse_options_remount(struct super_block *sb, char *options, int silent, return 0; vfsopts->mask = option; break; + case Opt_unshared_obb: case Opt_default_normal: case Opt_multiuser: case Opt_userid: case Opt_fsuid: case Opt_fsgid: case Opt_reserved_mb: - pr_warn("Option \"%s\" can't be changed during remount\n", p); + case Opt_gid_derivation: + if (!silent) + pr_warn("Option \"%s\" can't be changed during remount\n", p); break; /* unknown option */ default: diff --git a/fs/sdcardfs/sdcardfs.h b/fs/sdcardfs/sdcardfs.h index 57be4761d32b..2bee162921ce 100644 --- a/fs/sdcardfs/sdcardfs.h +++ b/fs/sdcardfs/sdcardfs.h @@ -197,6 +197,7 @@ struct sdcardfs_mount_options { bool multiuser; bool gid_derivation; bool default_normal; + bool unshared_obb; unsigned int reserved_mb; bool nocache; }; diff --git a/include/dt-bindings/pinctrl/qcom,pmic-gpio.h b/include/dt-bindings/pinctrl/qcom,pmic-gpio.h index 64e2dc7183f3..7ac6f1631098 100644 --- a/include/dt-bindings/pinctrl/qcom,pmic-gpio.h +++ b/include/dt-bindings/pinctrl/qcom,pmic-gpio.h @@ -11,9 +11,14 @@ #define PMIC_GPIO_PULL_UP_1P5_30 3 #define PMIC_GPIO_STRENGTH_NO 0 -#define PMIC_GPIO_STRENGTH_HIGH 1 +#define PMIC_GPIO_STRENGTH_LOW 1 #define PMIC_GPIO_STRENGTH_MED 2 -#define PMIC_GPIO_STRENGTH_LOW 3 +#define PMIC_GPIO_STRENGTH_HIGH 3 + +#define PM8921_GPIO_STRENGTH_NO 0 +#define PM8921_GPIO_STRENGTH_HIGH 1 +#define PM8921_GPIO_STRENGTH_MED 2 +#define PM8921_GPIO_STRENGTH_LOW 3 /* * Note: PM8018 GPIO3 and GPIO4 are supporting diff --git a/include/linux/can/dev.h b/include/linux/can/dev.h index 5f5270941ba0..f7178f44825b 100644 --- a/include/linux/can/dev.h +++ b/include/linux/can/dev.h @@ -154,6 +154,7 @@ void can_change_state(struct net_device *dev, struct can_frame *cf, void can_put_echo_skb(struct sk_buff *skb, struct net_device *dev, unsigned int idx); +struct sk_buff *__can_get_echo_skb(struct net_device *dev, unsigned int idx, u8 *len_ptr); unsigned int can_get_echo_skb(struct net_device *dev, unsigned int idx); void can_free_echo_skb(struct net_device *dev, unsigned int idx); diff --git a/include/linux/fs.h b/include/linux/fs.h index f5f4e7871865..ffa1033ad1ce 100644 --- a/include/linux/fs.h +++ b/include/linux/fs.h @@ -68,6 +68,8 @@ extern struct inodes_stat_t inodes_stat; extern int leases_enable, lease_break_time; extern int sysctl_protected_symlinks; extern int sysctl_protected_hardlinks; +extern int sysctl_protected_fifos; +extern int sysctl_protected_regular; struct buffer_head; typedef int (get_block_t)(struct inode *inode, sector_t iblock, diff --git a/include/linux/of.h b/include/linux/of.h index dd10626a615f..d9371c9cd88a 100644 --- a/include/linux/of.h +++ b/include/linux/of.h @@ -265,6 +265,8 @@ extern struct device_node *of_get_next_child(const struct device_node *node, extern struct device_node *of_get_next_available_child( const struct device_node *node, struct device_node *prev); +extern struct device_node *of_get_compatible_child(const struct device_node *parent, + const char *compatible); extern struct device_node *of_get_child_by_name(const struct device_node *node, const char *name); @@ -462,6 +464,12 @@ static inline bool of_have_populated_dt(void) return false; } +static inline struct device_node *of_get_compatible_child(const struct device_node *parent, + const char *compatible) +{ + return NULL; +} + static inline struct device_node *of_get_child_by_name( const struct device_node *node, const char *name) diff --git a/include/linux/sched.h b/include/linux/sched.h index 8f6894c6e83c..ded334b5cf8d 100644 --- a/include/linux/sched.h +++ b/include/linux/sched.h @@ -3082,7 +3082,12 @@ static inline void set_task_comm(struct task_struct *tsk, const char *from) { __set_task_comm(tsk, from, false); } -extern char *get_task_comm(char *to, struct task_struct *tsk); + +extern char *__get_task_comm(char *to, size_t len, struct task_struct *tsk); +#define get_task_comm(buf, tsk) ({ \ + BUILD_BUG_ON(sizeof(buf) != TASK_COMM_LEN); \ + __get_task_comm(buf, sizeof(buf), tsk); \ +}) #ifdef CONFIG_SMP void scheduler_ipi(void); diff --git a/include/linux/seccomp.h b/include/linux/seccomp.h index 5a53d34bba26..50c460a956f1 100644 --- a/include/linux/seccomp.h +++ b/include/linux/seccomp.h @@ -29,19 +29,13 @@ struct seccomp { }; #ifdef CONFIG_HAVE_ARCH_SECCOMP_FILTER -extern int __secure_computing(void); -static inline int secure_computing(void) +extern int __secure_computing(const struct seccomp_data *sd); +static inline int secure_computing(const struct seccomp_data *sd) { if (unlikely(test_thread_flag(TIF_SECCOMP))) - return __secure_computing(); + return __secure_computing(sd); return 0; } - -#define SECCOMP_PHASE1_OK 0 -#define SECCOMP_PHASE1_SKIP 1 - -extern u32 seccomp_phase1(struct seccomp_data *sd); -int seccomp_phase2(u32 phase1_result); #else extern void secure_computing_strict(int this_syscall); #endif @@ -62,7 +56,7 @@ struct seccomp { }; struct seccomp_filter { }; #ifdef CONFIG_HAVE_ARCH_SECCOMP_FILTER -static inline int secure_computing(void) { return 0; } +static inline int secure_computing(struct seccomp_data *sd) { return 0; } #else static inline void secure_computing_strict(int this_syscall) { return; } #endif diff --git a/include/linux/usb.h b/include/linux/usb.h index d88c31c8e6a4..e27df29a298e 100644 --- a/include/linux/usb.h +++ b/include/linux/usb.h @@ -336,11 +336,11 @@ struct usb_host_bos { }; int __usb_get_extra_descriptor(char *buffer, unsigned size, - unsigned char type, void **ptr); + unsigned char type, void **ptr, size_t min); #define usb_get_extra_descriptor(ifpoint, type, ptr) \ __usb_get_extra_descriptor((ifpoint)->extra, \ (ifpoint)->extralen, \ - type, (void **)ptr) + type, (void **)ptr, sizeof(**(ptr))) /* ----------------------------------------------------------------------- */ diff --git a/include/sound/apr_audio-v2.h b/include/sound/apr_audio-v2.h index 48fe32252e8d..89e05abfd74b 100644 --- a/include/sound/apr_audio-v2.h +++ b/include/sound/apr_audio-v2.h @@ -1489,11 +1489,35 @@ struct adm_cmd_connect_afe_port_v5 { #define AFE_PORT_ID_PRIMARY_MI2S_RX 0x1000 #define AFE_PORT_ID_PRIMARY_MI2S_TX 0x1001 #define AFE_PORT_ID_SECONDARY_MI2S_RX 0x1002 +#define AFE_PORT_ID_SECONDARY_MI2S_RX_1 0x1040 +#define AFE_PORT_ID_SECONDARY_MI2S_RX_2 0x1042 +#define AFE_PORT_ID_SECONDARY_MI2S_RX_3 0x1044 +#define AFE_PORT_ID_SECONDARY_MI2S_RX_4 0x1046 #define AFE_PORT_ID_SECONDARY_MI2S_TX 0x1003 +#define AFE_PORT_ID_SECONDARY_MI2S_TX_1 0x1041 +#define AFE_PORT_ID_SECONDARY_MI2S_TX_2 0x1043 +#define AFE_PORT_ID_SECONDARY_MI2S_TX_3 0x1045 +#define AFE_PORT_ID_SECONDARY_MI2S_TX_4 0x1047 #define AFE_PORT_ID_TERTIARY_MI2S_RX 0x1004 +#define AFE_PORT_ID_TERTIARY_MI2S_RX_1 0x1048 +#define AFE_PORT_ID_TERTIARY_MI2S_RX_2 0x104A +#define AFE_PORT_ID_TERTIARY_MI2S_RX_3 0x104C +#define AFE_PORT_ID_TERTIARY_MI2S_RX_4 0x104E #define AFE_PORT_ID_TERTIARY_MI2S_TX 0x1005 +#define AFE_PORT_ID_TERTIARY_MI2S_TX_1 0x1049 +#define AFE_PORT_ID_TERTIARY_MI2S_TX_2 0x104B +#define AFE_PORT_ID_TERTIARY_MI2S_TX_3 0x104D +#define AFE_PORT_ID_TERTIARY_MI2S_TX_4 0x104F #define AFE_PORT_ID_QUATERNARY_MI2S_RX 0x1006 +#define AFE_PORT_ID_QUATERNARY_MI2S_RX_1 0x1020 +#define AFE_PORT_ID_QUATERNARY_MI2S_RX_2 0x1022 +#define AFE_PORT_ID_QUATERNARY_MI2S_RX_3 0x1024 +#define AFE_PORT_ID_QUATERNARY_MI2S_RX_4 0x1026 #define AFE_PORT_ID_QUATERNARY_MI2S_TX 0x1007 +#define AFE_PORT_ID_QUATERNARY_MI2S_TX_1 0x1021 +#define AFE_PORT_ID_QUATERNARY_MI2S_TX_2 0x1023 +#define AFE_PORT_ID_QUATERNARY_MI2S_TX_3 0x1025 +#define AFE_PORT_ID_QUATERNARY_MI2S_TX_4 0x1027 #define AUDIO_PORT_ID_I2S_RX 0x1008 #define AFE_PORT_ID_DIGITAL_MIC_TX 0x1009 #define AFE_PORT_ID_PRIMARY_PCM_RX 0x100A @@ -10886,6 +10910,7 @@ struct afe_port_cmd_set_aanc_acdb_table { #define AFE_PARAM_ID_GROUP_DEVICE_CFG 0x00010255 #define AFE_PARAM_ID_GROUP_DEVICE_ENABLE 0x00010256 #define AFE_GROUP_DEVICE_ID_SECONDARY_MI2S_RX 0x1102 +#define AFE_PARAM_ID_GROUP_DEVICE_I2S_CONFIG 0x00010286 /* Payload of the #AFE_PARAM_ID_GROUP_DEVICE_CFG * parameter, which configures max of 8 AFE ports @@ -11069,6 +11094,119 @@ struct afe_param_id_group_device_tdm_cfg { @values 1 to 2^32 -1 */ } __packed; +#define AFE_GROUP_DEVICE_ID_SECONDARY_MI2S_TX \ + (AFE_PORT_ID_SECONDARY_MI2S_TX + 0x100) +#define AFE_GROUP_DEVICE_ID_TERTIARY_MI2S_RX \ + (AFE_PORT_ID_TERTIARY_MI2S_RX + 0x100) +#define AFE_GROUP_DEVICE_ID_TERTIARY_MI2S_TX \ + (AFE_PORT_ID_TERTIARY_MI2S_TX + 0x100) +#define AFE_GROUP_DEVICE_ID_QUATERNARY_MI2S_RX \ + (AFE_PORT_ID_QUATERNARY_MI2S_RX + 0x100) +#define AFE_GROUP_DEVICE_ID_QUATERNARY_MI2S_TX \ + (AFE_PORT_ID_QUATERNARY_MI2S_TX + 0x100) + +#define AFE_API_VERSION_GROUP_DEVICE_I2S_CONFIG 0x1 + +/* Payload of the AFE_PARAM_ID_GROUP_DEVICE_I2S_CONFIG parameter ID +* used by AFE_MODULE_GROUP_DEVICE. +*/ +struct afe_param_id_group_device_i2s_cfg_v1 { + u32 minor_version; + /**< Minor version used to track group device configuration. + * @values #AFE_API_VERSION_GROUP_DEVICE_I2S_CONFIG + */ + + u16 group_id; + /**< ID for the group device. + * @values + * - #AFE_GROUP_DEVICE_ID_SECONDARY_MI2S_RX + * - #AFE_GROUP_DEVICE_ID_SECONDARY_MI2S_TX + * - #AFE_GROUP_DEVICE_ID_TERTIARY_MI2S_RX + * - #AFE_GROUP_DEVICE_ID_TERTIARY_MI2S_TX + * - #AFE_GROUP_DEVICE_ID_QUATERNARY_MI2S_RX + * - #AFE_GROUP_DEVICE_ID_QUATERNARY_MI2S_RX + */ + + u16 channel_mode; + /**< Group line channel mode + * @values + * - #AFE_PORT_I2S_SD0 + * - #AFE_PORT_I2S_SD1 + * - #AFE_PORT_I2S_SD2 + * - #AFE_PORT_I2S_SD3 + * - #AFE_PORT_I2S_QUAD01 + * - #AFE_PORT_I2S_QUAD23 + * - #AFE_PORT_I2S_6CHS + * - #AFE_PORT_I2S_8CHS + */ + + u32 sample_rate; + /**< Sampling rate of the port. + * @values + * - #AFE_PORT_SAMPLE_RATE_8K + * - #AFE_PORT_SAMPLE_RATE_16K + * - #AFE_PORT_SAMPLE_RATE_24K + * - #AFE_PORT_SAMPLE_RATE_32K + */ + + u16 port_id[AFE_GROUP_DEVICE_NUM_PORTS]; + /**< Array of member port IDs of this group. + * @values + * - #AFE_PORT_ID_SECONDARY_MI2S_RX_1 + * - #AFE_PORT_ID_SECONDARY_MI2S_RX_2 + * - #AFE_PORT_ID_SECONDARY_MI2S_RX_3 + * - #AFE_PORT_ID_SECONDARY_MI2S_RX_4 + + * - #AFE_PORT_ID_SECONDARY_MI2S_TX_1 + * - #AFE_PORT_ID_SECONDARY_MI2S_TX_2 + * - #AFE_PORT_ID_SECONDARY_MI2S_TX_3 + * - #AFE_PORT_ID_SECONDARY_MI2S_TX_4 + + * - #AFE_PORT_ID_TERTIARY_MI2S_RX_1 + * - #AFE_PORT_ID_TERTIARY_MI2S_RX_2 + * - #AFE_PORT_ID_TERTIARY_MI2S_RX_3 + * - #AFE_PORT_ID_TERTIARY_MI2S_RX_4 + + * - #AFE_PORT_ID_TERTIARY_MI2S_TX_1 + * - #AFE_PORT_ID_TERTIARY_MI2S_TX_2 + * - #AFE_PORT_ID_TERTIARY_MI2S_TX_3 + * - #AFE_PORT_ID_TERTIARY_MI2S_TX_4 + + * - #AFE_PORT_ID_QUATERNARY_MI2S_RX_1 + * - #AFE_PORT_ID_QUATERNARY_MI2S_RX_2 + * - #AFE_PORT_ID_QUATERNARY_MI2S_RX_3 + * - #AFE_PORT_ID_QUATERNARY_MI2S_RX_4 + + * - #AFE_PORT_ID_QUATERNARY_MI2S_TX_1 + * - #AFE_PORT_ID_QUATERNARY_MI2S_TX_2 + * - #AFE_PORT_ID_QUATERNARY_MI2S_TX_3 + * - #AFE_PORT_ID_QUATERNARY_MI2S_TX_4 + * @tablebulletend + */ + + u16 bit_width; + /**< Bit width of the sample. + * @values 16, 24, (32) + */ + + u16 reserved; +} __packed; + +struct afe_param_id_group_device_enable { + u16 group_id; + u16 enable; +} __packed; + +union afe_port_group_mi2s_config { + struct afe_param_id_group_device_i2s_cfg_v1 i2s_cfg; + struct afe_param_id_group_device_enable group_enable; +} __packed; + +struct afe_i2s_port_config { + struct afe_param_id_i2s_cfg i2s_cfg; + struct afe_param_id_slot_mapping_cfg slot_mapping; +} __packed; + /* Payload of the #AFE_PARAM_ID_GROUP_DEVICE_ENABLE * parameter, which enables or * disables any module. diff --git a/include/sound/pcm_params.h b/include/sound/pcm_params.h index 747c94a9a3d6..91f6abfb2ce0 100644 --- a/include/sound/pcm_params.h +++ b/include/sound/pcm_params.h @@ -251,11 +251,13 @@ static inline int snd_interval_empty(const struct snd_interval *i) static inline int snd_interval_single(const struct snd_interval *i) { return (i->min == i->max || - (i->min + 1 == i->max && i->openmax)); + (i->min + 1 == i->max && (i->openmin || i->openmax))); } static inline int snd_interval_value(const struct snd_interval *i) { + if (i->openmin && !i->openmax) + return i->max; return i->min; } diff --git a/include/sound/q6afe-v2.h b/include/sound/q6afe-v2.h index cdbf97023f66..a6d697d6a8f8 100644 --- a/include/sound/q6afe-v2.h +++ b/include/sound/q6afe-v2.h @@ -208,6 +208,33 @@ enum { IDX_AFE_PORT_ID_INT5_MI2S_TX, IDX_AFE_PORT_ID_INT6_MI2S_RX, IDX_AFE_PORT_ID_INT6_MI2S_TX, + /* IDX 143 -> 150 */ + IDX_AFE_PORT_ID_SECONDARY_MI2S_RX_1, + IDX_AFE_PORT_ID_SECONDARY_MI2S_RX_2, + IDX_AFE_PORT_ID_SECONDARY_MI2S_RX_3, + IDX_AFE_PORT_ID_SECONDARY_MI2S_RX_4, + IDX_AFE_PORT_ID_SECONDARY_MI2S_TX_1, + IDX_AFE_PORT_ID_SECONDARY_MI2S_TX_2, + IDX_AFE_PORT_ID_SECONDARY_MI2S_TX_3, + IDX_AFE_PORT_ID_SECONDARY_MI2S_TX_4, + /* IDX 151 -> 158 */ + IDX_AFE_PORT_ID_TERTIARY_MI2S_RX_1, + IDX_AFE_PORT_ID_TERTIARY_MI2S_RX_2, + IDX_AFE_PORT_ID_TERTIARY_MI2S_RX_3, + IDX_AFE_PORT_ID_TERTIARY_MI2S_RX_4, + IDX_AFE_PORT_ID_TERTIARY_MI2S_TX_1, + IDX_AFE_PORT_ID_TERTIARY_MI2S_TX_2, + IDX_AFE_PORT_ID_TERTIARY_MI2S_TX_3, + IDX_AFE_PORT_ID_TERTIARY_MI2S_TX_4, + /* IDX 159 -> 166 */ + IDX_AFE_PORT_ID_QUATERNARY_MI2S_RX_1, + IDX_AFE_PORT_ID_QUATERNARY_MI2S_RX_2, + IDX_AFE_PORT_ID_QUATERNARY_MI2S_RX_3, + IDX_AFE_PORT_ID_QUATERNARY_MI2S_RX_4, + IDX_AFE_PORT_ID_QUATERNARY_MI2S_TX_1, + IDX_AFE_PORT_ID_QUATERNARY_MI2S_TX_2, + IDX_AFE_PORT_ID_QUATERNARY_MI2S_TX_3, + IDX_AFE_PORT_ID_QUATERNARY_MI2S_TX_4, AFE_MAX_PORTS }; @@ -292,6 +319,44 @@ enum { IDX_GROUP_TDM_MAX, }; +enum { + IDX_SECONDARY_MI2S_RX_1, + IDX_SECONDARY_MI2S_RX_2, + IDX_SECONDARY_MI2S_RX_3, + IDX_SECONDARY_MI2S_RX_4, + IDX_SECONDARY_MI2S_TX_1, + IDX_SECONDARY_MI2S_TX_2, + IDX_SECONDARY_MI2S_TX_3, + IDX_SECONDARY_MI2S_TX_4, + IDX_TERTIARY_MI2S_RX_1, + IDX_TERTIARY_MI2S_RX_2, + IDX_TERTIARY_MI2S_RX_3, + IDX_TERTIARY_MI2S_RX_4, + IDX_TERTIARY_MI2S_TX_1, + IDX_TERTIARY_MI2S_TX_2, + IDX_TERTIARY_MI2S_TX_3, + IDX_TERTIARY_MI2S_TX_4, + IDX_QUATERNARY_MI2S_RX_1, + IDX_QUATERNARY_MI2S_RX_2, + IDX_QUATERNARY_MI2S_RX_3, + IDX_QUATERNARY_MI2S_RX_4, + IDX_QUATERNARY_MI2S_TX_1, + IDX_QUATERNARY_MI2S_TX_2, + IDX_QUATERNARY_MI2S_TX_3, + IDX_QUATERNARY_MI2S_TX_4, + IDX_GROUP_MI2S_PORT_MAX, +}; + +enum { + IDX_GROUP_SECONDARY_MI2S_RX, + IDX_GROUP_SECONDARY_MI2S_TX, + IDX_GROUP_TERTIARY_MI2S_RX, + IDX_GROUP_TERTIARY_MI2S_TX, + IDX_GROUP_QUATERNARY_MI2S_RX, + IDX_GROUP_QUATERNARY_MI2S_TX, + IDX_GROUP_MI2S_MAX, +}; + enum afe_mad_type { MAD_HW_NONE = 0x00, MAD_HW_AUDIO = 0x01, @@ -458,4 +523,9 @@ int afe_request_dma_resources(uint8_t dma_type, uint8_t num_read_dma_channels, int afe_get_dma_idx(bool **ret_rddma_idx, bool **ret_wrdma_idx); int afe_release_all_dma_resources(void); +int afe_i2s_port_start(u16 port_id, struct afe_i2s_port_config *i2s_port, + u32 rate, u16 num_groups); +int afe_port_group_mi2s_enable(u16 group_id, + union afe_port_group_mi2s_config *afe_group_config, + u16 enable); #endif /* __Q6AFE_V2_H__ */ diff --git a/include/sound/q6asm-v2.h b/include/sound/q6asm-v2.h index 8af49bb6a9fa..d2d639ec462f 100644 --- a/include/sound/q6asm-v2.h +++ b/include/sound/q6asm-v2.h @@ -57,6 +57,7 @@ #define FORMAT_GEN_COMPR 0x001f #define FORMAT_TRUEHD 0x0020 #define FORMAT_IEC61937 0x0021 +#define FORMAT_APTXHD 0x0022 #define ENCDEC_SBCBITRATE 0x0001 #define ENCDEC_IMMEDIATE_DECODE 0x0002 diff --git a/include/uapi/sound/compress_params.h b/include/uapi/sound/compress_params.h index f4028e805cc7..6f57d4f60ce0 100644 --- a/include/uapi/sound/compress_params.h +++ b/include/uapi/sound/compress_params.h @@ -105,7 +105,8 @@ #define SND_AUDIOCODEC_DSD ((__u32) 0x00000021) #define SND_AUDIOCODEC_APTX ((__u32) 0x00000022) #define SND_AUDIOCODEC_TRUEHD ((__u32) 0x00000023) -#define SND_AUDIOCODEC_MAX SND_AUDIOCODEC_TRUEHD +#define SND_AUDIOCODEC_APTXHD ((__u32) 0x00000024) +#define SND_AUDIOCODEC_MAX SND_AUDIOCODEC_APTXHD /* * Profile and modes are listed with bit masks. This allows for a * more compact representation of fields that will not evolve diff --git a/kernel/debug/kdb/kdb_io.c b/kernel/debug/kdb/kdb_io.c index 3990c1f73e45..d3c5b15c86c1 100644 --- a/kernel/debug/kdb/kdb_io.c +++ b/kernel/debug/kdb/kdb_io.c @@ -215,7 +215,7 @@ static char *kdb_read(char *buffer, size_t bufsize) int count; int i; int diag, dtab_count; - int key; + int key, buf_size, ret; static int last_crlf; diag = kdbgetintenv("DTABCOUNT", &dtab_count); @@ -343,9 +343,8 @@ poll_again: else p_tmp = tmpbuffer; len = strlen(p_tmp); - count = kallsyms_symbol_complete(p_tmp, - sizeof(tmpbuffer) - - (p_tmp - tmpbuffer)); + buf_size = sizeof(tmpbuffer) - (p_tmp - tmpbuffer); + count = kallsyms_symbol_complete(p_tmp, buf_size); if (tab == 2 && count > 0) { kdb_printf("\n%d symbols are found.", count); if (count > dtab_count) { @@ -357,9 +356,13 @@ poll_again: } kdb_printf("\n"); for (i = 0; i < count; i++) { - if (WARN_ON(!kallsyms_symbol_next(p_tmp, i))) + ret = kallsyms_symbol_next(p_tmp, i, buf_size); + if (WARN_ON(!ret)) break; - kdb_printf("%s ", p_tmp); + if (ret != -E2BIG) + kdb_printf("%s ", p_tmp); + else + kdb_printf("%s... ", p_tmp); *(p_tmp + len) = '\0'; } if (i >= dtab_count) diff --git a/kernel/debug/kdb/kdb_private.h b/kernel/debug/kdb/kdb_private.h index 75014d7f4568..533e04e75a9c 100644 --- a/kernel/debug/kdb/kdb_private.h +++ b/kernel/debug/kdb/kdb_private.h @@ -83,7 +83,7 @@ typedef struct __ksymtab { unsigned long sym_start; unsigned long sym_end; } kdb_symtab_t; -extern int kallsyms_symbol_next(char *prefix_name, int flag); +extern int kallsyms_symbol_next(char *prefix_name, int flag, int buf_size); extern int kallsyms_symbol_complete(char *prefix_name, int max_len); /* Exported Symbols for kernel loadable modules to use. */ diff --git a/kernel/debug/kdb/kdb_support.c b/kernel/debug/kdb/kdb_support.c index d35cc2d3a4cc..61cd704a21c8 100644 --- a/kernel/debug/kdb/kdb_support.c +++ b/kernel/debug/kdb/kdb_support.c @@ -129,13 +129,13 @@ int kdbnearsym(unsigned long addr, kdb_symtab_t *symtab) } if (i >= ARRAY_SIZE(kdb_name_table)) { debug_kfree(kdb_name_table[0]); - memcpy(kdb_name_table, kdb_name_table+1, + memmove(kdb_name_table, kdb_name_table+1, sizeof(kdb_name_table[0]) * (ARRAY_SIZE(kdb_name_table)-1)); } else { debug_kfree(knt1); knt1 = kdb_name_table[i]; - memcpy(kdb_name_table+i, kdb_name_table+i+1, + memmove(kdb_name_table+i, kdb_name_table+i+1, sizeof(kdb_name_table[0]) * (ARRAY_SIZE(kdb_name_table)-i-1)); } @@ -221,11 +221,13 @@ int kallsyms_symbol_complete(char *prefix_name, int max_len) * Parameters: * prefix_name prefix of a symbol name to lookup * flag 0 means search from the head, 1 means continue search. + * buf_size maximum length that can be written to prefix_name + * buffer * Returns: * 1 if a symbol matches the given prefix. * 0 if no string found */ -int kallsyms_symbol_next(char *prefix_name, int flag) +int kallsyms_symbol_next(char *prefix_name, int flag, int buf_size) { int prefix_len = strlen(prefix_name); static loff_t pos; @@ -235,10 +237,8 @@ int kallsyms_symbol_next(char *prefix_name, int flag) pos = 0; while ((name = kdb_walk_kallsyms(&pos))) { - if (strncmp(name, prefix_name, prefix_len) == 0) { - strncpy(prefix_name, name, strlen(name)+1); - return 1; - } + if (!strncmp(name, prefix_name, prefix_len)) + return strscpy(prefix_name, name, buf_size); } return 0; } diff --git a/kernel/events/uprobes.c b/kernel/events/uprobes.c index 7b1b772ab1ce..d8fc54eef51c 100644 --- a/kernel/events/uprobes.c +++ b/kernel/events/uprobes.c @@ -606,7 +606,7 @@ static int prepare_uprobe(struct uprobe *uprobe, struct file *file, BUG_ON((uprobe->offset & ~PAGE_MASK) + UPROBE_SWBP_INSN_SIZE > PAGE_SIZE); - smp_wmb(); /* pairs with rmb() in find_active_uprobe() */ + smp_wmb(); /* pairs with the smp_rmb() in handle_swbp() */ set_bit(UPROBE_COPY_INSN, &uprobe->flags); out: @@ -1891,10 +1891,18 @@ static void handle_swbp(struct pt_regs *regs) * After we hit the bp, _unregister + _register can install the * new and not-yet-analyzed uprobe at the same address, restart. */ - smp_rmb(); /* pairs with wmb() in install_breakpoint() */ if (unlikely(!test_bit(UPROBE_COPY_INSN, &uprobe->flags))) goto out; + /* + * Pairs with the smp_wmb() in prepare_uprobe(). + * + * Guarantees that if we see the UPROBE_COPY_INSN bit set, then + * we must also see the stores to &uprobe->arch performed by the + * prepare_uprobe() call. + */ + smp_rmb(); + /* Tracing handlers use ->utask to communicate with fetch methods */ if (!get_utask()) goto out; diff --git a/kernel/sched/core.c b/kernel/sched/core.c index 6a5671bdb792..6b9021b9bc26 100644 --- a/kernel/sched/core.c +++ b/kernel/sched/core.c @@ -4205,8 +4205,8 @@ static int __sched_setscheduler(struct task_struct *p, int reset_on_fork; int queue_flags = DEQUEUE_SAVE | DEQUEUE_MOVE; - /* may grab non-irq protected spin_locks */ - BUG_ON(in_interrupt()); + /* The pi code expects interrupts enabled */ + BUG_ON(pi && in_interrupt()); recheck: /* double check policy once rq lock held */ if (policy < 0) { diff --git a/kernel/seccomp.c b/kernel/seccomp.c index 9a9203b15cde..a39f81c7e87a 100644 --- a/kernel/seccomp.c +++ b/kernel/seccomp.c @@ -175,7 +175,7 @@ static int seccomp_check_filter(struct sock_filter *filter, unsigned int flen) * * Returns valid seccomp BPF response codes. */ -static u32 seccomp_run_filters(struct seccomp_data *sd) +static u32 seccomp_run_filters(const struct seccomp_data *sd) { struct seccomp_data sd_local; u32 ret = SECCOMP_RET_ALLOW; @@ -579,20 +579,10 @@ void secure_computing_strict(int this_syscall) BUG(); } #else -int __secure_computing(void) -{ - u32 phase1_result = seccomp_phase1(NULL); - - if (likely(phase1_result == SECCOMP_PHASE1_OK)) - return 0; - else if (likely(phase1_result == SECCOMP_PHASE1_SKIP)) - return -1; - else - return seccomp_phase2(phase1_result); -} #ifdef CONFIG_SECCOMP_FILTER -static u32 __seccomp_phase1_filter(int this_syscall, struct seccomp_data *sd) +static int __seccomp_filter(int this_syscall, const struct seccomp_data *sd, + const bool recheck_after_trace) { u32 filter_ret, action; int data; @@ -624,10 +614,50 @@ static u32 __seccomp_phase1_filter(int this_syscall, struct seccomp_data *sd) goto skip; case SECCOMP_RET_TRACE: - return filter_ret; /* Save the rest for phase 2. */ + /* We've been put in this state by the ptracer already. */ + if (recheck_after_trace) + return 0; + + /* ENOSYS these calls if there is no tracer attached. */ + if (!ptrace_event_enabled(current, PTRACE_EVENT_SECCOMP)) { + syscall_set_return_value(current, + task_pt_regs(current), + -ENOSYS, 0); + goto skip; + } + + /* Allow the BPF to provide the event message */ + ptrace_event(PTRACE_EVENT_SECCOMP, data); + /* + * The delivery of a fatal signal during event + * notification may silently skip tracer notification, + * which could leave us with a potentially unmodified + * syscall that the tracer would have liked to have + * changed. Since the process is about to die, we just + * force the syscall to be skipped and let the signal + * kill the process and correctly handle any tracer exit + * notifications. + */ + if (fatal_signal_pending(current)) + goto skip; + /* Check if the tracer forced the syscall to be skipped. */ + this_syscall = syscall_get_nr(current, task_pt_regs(current)); + if (this_syscall < 0) + goto skip; + + /* + * Recheck the syscall, since it may have changed. This + * intentionally uses a NULL struct seccomp_data to force + * a reload of all registers. This does not goto skip since + * a skip would have already been reported. + */ + if (__seccomp_filter(this_syscall, NULL, true)) + return -1; + + return 0; case SECCOMP_RET_ALLOW: - return SECCOMP_PHASE1_OK; + return 0; case SECCOMP_RET_KILL: default: @@ -639,96 +669,38 @@ static u32 __seccomp_phase1_filter(int this_syscall, struct seccomp_data *sd) skip: audit_seccomp(this_syscall, 0, action); - return SECCOMP_PHASE1_SKIP; + return -1; +} +#else +static int __seccomp_filter(int this_syscall, const struct seccomp_data *sd, + const bool recheck_after_trace) +{ + BUG(); } #endif -/** - * seccomp_phase1() - run fast path seccomp checks on the current syscall - * @arg sd: The seccomp_data or NULL - * - * This only reads pt_regs via the syscall_xyz helpers. The only change - * it will make to pt_regs is via syscall_set_return_value, and it will - * only do that if it returns SECCOMP_PHASE1_SKIP. - * - * If sd is provided, it will not read pt_regs at all. - * - * It may also call do_exit or force a signal; these actions must be - * safe. - * - * If it returns SECCOMP_PHASE1_OK, the syscall passes checks and should - * be processed normally. - * - * If it returns SECCOMP_PHASE1_SKIP, then the syscall should not be - * invoked. In this case, seccomp_phase1 will have set the return value - * using syscall_set_return_value. - * - * If it returns anything else, then the return value should be passed - * to seccomp_phase2 from a context in which ptrace hooks are safe. - */ -u32 seccomp_phase1(struct seccomp_data *sd) +int __secure_computing(const struct seccomp_data *sd) { int mode = current->seccomp.mode; - int this_syscall = sd ? sd->nr : - syscall_get_nr(current, task_pt_regs(current)); + int this_syscall; if (config_enabled(CONFIG_CHECKPOINT_RESTORE) && unlikely(current->ptrace & PT_SUSPEND_SECCOMP)) - return SECCOMP_PHASE1_OK; + return 0; + + this_syscall = sd ? sd->nr : + syscall_get_nr(current, task_pt_regs(current)); switch (mode) { case SECCOMP_MODE_STRICT: __secure_computing_strict(this_syscall); /* may call do_exit */ - return SECCOMP_PHASE1_OK; -#ifdef CONFIG_SECCOMP_FILTER + return 0; case SECCOMP_MODE_FILTER: - return __seccomp_phase1_filter(this_syscall, sd); -#endif + return __seccomp_filter(this_syscall, sd, false); default: BUG(); } } - -/** - * seccomp_phase2() - finish slow path seccomp work for the current syscall - * @phase1_result: The return value from seccomp_phase1() - * - * This must be called from a context in which ptrace hooks can be used. - * - * Returns 0 if the syscall should be processed or -1 to skip the syscall. - */ -int seccomp_phase2(u32 phase1_result) -{ - struct pt_regs *regs = task_pt_regs(current); - u32 action = phase1_result & SECCOMP_RET_ACTION; - int data = phase1_result & SECCOMP_RET_DATA; - - BUG_ON(action != SECCOMP_RET_TRACE); - - audit_seccomp(syscall_get_nr(current, regs), 0, action); - - /* Skip these calls if there is no tracer. */ - if (!ptrace_event_enabled(current, PTRACE_EVENT_SECCOMP)) { - syscall_set_return_value(current, regs, - -ENOSYS, 0); - return -1; - } - - /* Allow the BPF to provide the event message */ - ptrace_event(PTRACE_EVENT_SECCOMP, data); - /* - * The delivery of a fatal signal during event - * notification may silently skip tracer notification. - * Terminating the task now avoids executing a system - * call that may not be intended. - */ - if (fatal_signal_pending(current)) - do_exit(SIGSYS); - if (syscall_get_nr(current, regs) < 0) - return -1; /* Explicit request to skip. */ - - return 0; -} #endif /* CONFIG_HAVE_ARCH_SECCOMP_FILTER */ long prctl_get_seccomp(void) diff --git a/kernel/sysctl.c b/kernel/sysctl.c index 14f19af9d79a..ae30e357f554 100644 --- a/kernel/sysctl.c +++ b/kernel/sysctl.c @@ -2045,6 +2045,24 @@ static struct ctl_table fs_table[] = { .extra2 = &one, }, { + .procname = "protected_fifos", + .data = &sysctl_protected_fifos, + .maxlen = sizeof(int), + .mode = 0600, + .proc_handler = proc_dointvec_minmax, + .extra1 = &zero, + .extra2 = &two, + }, + { + .procname = "protected_regular", + .data = &sysctl_protected_regular, + .maxlen = sizeof(int), + .mode = 0600, + .proc_handler = proc_dointvec_minmax, + .extra1 = &zero, + .extra2 = &two, + }, + { .procname = "suid_dumpable", .data = &suid_dumpable, .maxlen = sizeof(int), diff --git a/lib/kobject.c b/lib/kobject.c index 895edb63fba4..35d490b02cdd 100644 --- a/lib/kobject.c +++ b/lib/kobject.c @@ -127,7 +127,7 @@ static void fill_kobj_path(struct kobject *kobj, char *path, int length) int cur = strlen(kobject_name(parent)); /* back up enough to print this name with '/' */ length -= cur; - strncpy(path + length, kobject_name(parent), cur); + memcpy(path + length, kobject_name(parent), cur); *(path + --length) = '/'; } diff --git a/mm/mlock.c b/mm/mlock.c index 206e86b98a03..966dbdcfc322 100644 --- a/mm/mlock.c +++ b/mm/mlock.c @@ -504,6 +504,7 @@ static int mlock_fixup(struct vm_area_struct *vma, struct vm_area_struct **prev, int nr_pages; int ret = 0; int lock = !!(newflags & VM_LOCKED); + vm_flags_t old_flags = vma->vm_flags; if (newflags == vma->vm_flags || (vma->vm_flags & VM_SPECIAL) || is_vm_hugetlb_page(vma) || vma == get_gate_vma(current->mm)) @@ -538,6 +539,8 @@ success: nr_pages = (end - start) >> PAGE_SHIFT; if (!lock) nr_pages = -nr_pages; + else if (old_flags & VM_LOCKED) + nr_pages = 0; mm->locked_vm += nr_pages; /* diff --git a/mm/shmem.c b/mm/shmem.c index 6318fc7883c4..6397dc2e15bc 100644 --- a/mm/shmem.c +++ b/mm/shmem.c @@ -1818,9 +1818,7 @@ static loff_t shmem_file_llseek(struct file *file, loff_t offset, int whence) mutex_lock(&inode->i_mutex); /* We're holding i_mutex so we can access i_size directly */ - if (offset < 0) - offset = -EINVAL; - else if (offset >= inode->i_size) + if (offset < 0 || offset >= inode->i_size) offset = -ENXIO; else { start = offset >> PAGE_CACHE_SHIFT; diff --git a/mm/truncate.c b/mm/truncate.c index 8ca20a98c327..f6fedb876604 100644 --- a/mm/truncate.c +++ b/mm/truncate.c @@ -499,9 +499,13 @@ void truncate_inode_pages_final(struct address_space *mapping) */ spin_lock_irq(&mapping->tree_lock); spin_unlock_irq(&mapping->tree_lock); - - truncate_inode_pages(mapping, 0); } + + /* + * Cleancache needs notification even if there are no pages or shadow + * entries. + */ + truncate_inode_pages(mapping, 0); } EXPORT_SYMBOL(truncate_inode_pages_final); diff --git a/net/batman-adv/fragmentation.c b/net/batman-adv/fragmentation.c index 5d2f9d4879b2..d50c3b003dc9 100644 --- a/net/batman-adv/fragmentation.c +++ b/net/batman-adv/fragmentation.c @@ -266,7 +266,7 @@ batadv_frag_merge_packets(struct hlist_head *chain) kfree(entry); packet = (struct batadv_frag_packet *)skb_out->data; - size = ntohs(packet->total_size); + size = ntohs(packet->total_size) + hdr_size; /* Make room for the rest of the fragments. */ if (pskb_expand_head(skb_out, 0, size - skb_out->len, GFP_ATOMIC) < 0) { diff --git a/net/ipv4/ip_tunnel.c b/net/ipv4/ip_tunnel.c index 9d3176b080a4..91ae061d46ac 100644 --- a/net/ipv4/ip_tunnel.c +++ b/net/ipv4/ip_tunnel.c @@ -261,8 +261,8 @@ static struct net_device *__ip_tunnel_create(struct net *net, } else { if (strlen(ops->kind) > (IFNAMSIZ - 3)) goto failed; - strlcpy(name, ops->kind, IFNAMSIZ); - strncat(name, "%d", 2); + strcpy(name, ops->kind); + strcat(name, "%d"); } ASSERT_RTNL(); diff --git a/net/llc/af_llc.c b/net/llc/af_llc.c index 83e8a295c806..c153fc2883a8 100644 --- a/net/llc/af_llc.c +++ b/net/llc/af_llc.c @@ -726,7 +726,6 @@ static int llc_ui_recvmsg(struct socket *sock, struct msghdr *msg, size_t len, struct sk_buff *skb = NULL; struct sock *sk = sock->sk; struct llc_sock *llc = llc_sk(sk); - unsigned long cpu_flags; size_t copied = 0; u32 peek_seq = 0; u32 *seq, skb_len; @@ -851,9 +850,8 @@ static int llc_ui_recvmsg(struct socket *sock, struct msghdr *msg, size_t len, goto copy_uaddr; if (!(flags & MSG_PEEK)) { - spin_lock_irqsave(&sk->sk_receive_queue.lock, cpu_flags); - sk_eat_skb(sk, skb); - spin_unlock_irqrestore(&sk->sk_receive_queue.lock, cpu_flags); + skb_unlink(skb, &sk->sk_receive_queue); + kfree_skb(skb); *seq = 0; } @@ -874,9 +872,8 @@ copy_uaddr: llc_cmsg_rcv(msg, skb); if (!(flags & MSG_PEEK)) { - spin_lock_irqsave(&sk->sk_receive_queue.lock, cpu_flags); - sk_eat_skb(sk, skb); - spin_unlock_irqrestore(&sk->sk_receive_queue.lock, cpu_flags); + skb_unlink(skb, &sk->sk_receive_queue); + kfree_skb(skb); *seq = 0; } diff --git a/net/mac80211/iface.c b/net/mac80211/iface.c index 00b25114843f..3678f2d5fcfe 100644 --- a/net/mac80211/iface.c +++ b/net/mac80211/iface.c @@ -988,6 +988,8 @@ static void ieee80211_do_stop(struct ieee80211_sub_if_data *sdata, if (local->open_count == 0) ieee80211_clear_tx_pending(local); + sdata->vif.bss_conf.beacon_int = 0; + /* * If the interface goes down while suspended, presumably because * the device was unplugged and that happens before our resume, diff --git a/net/mac80211/rx.c b/net/mac80211/rx.c index aef0d41e9a9c..b02fcb388640 100644 --- a/net/mac80211/rx.c +++ b/net/mac80211/rx.c @@ -1110,6 +1110,7 @@ ieee80211_rx_h_check_dup(struct ieee80211_rx_data *rx) return RX_CONTINUE; if (ieee80211_is_ctl(hdr->frame_control) || + ieee80211_is_nullfunc(hdr->frame_control) || ieee80211_is_qos_nullfunc(hdr->frame_control) || is_multicast_ether_addr(hdr->addr1)) return RX_CONTINUE; diff --git a/net/mac80211/status.c b/net/mac80211/status.c index 2731cf5bf052..d221300e59e5 100644 --- a/net/mac80211/status.c +++ b/net/mac80211/status.c @@ -648,6 +648,8 @@ void ieee80211_tx_status_noskb(struct ieee80211_hw *hw, /* Track when last TDLS packet was ACKed */ if (test_sta_flag(sta, WLAN_STA_TDLS_PEER_AUTH)) sta->status_stats.last_tdls_pkt_time = jiffies; + } else if (test_sta_flag(sta, WLAN_STA_PS_STA)) { + return; } else { ieee80211_lost_packet(sta, info); } diff --git a/net/mac80211/tx.c b/net/mac80211/tx.c index a45248a4967b..674fe547ffee 100644 --- a/net/mac80211/tx.c +++ b/net/mac80211/tx.c @@ -431,8 +431,8 @@ ieee80211_tx_h_multicast_ps_buf(struct ieee80211_tx_data *tx) if (ieee80211_hw_check(&tx->local->hw, QUEUE_CONTROL)) info->hw_queue = tx->sdata->vif.cab_queue; - /* no stations in PS mode */ - if (!atomic_read(&ps->num_sta_ps)) + /* no stations in PS mode and no buffered packets */ + if (!atomic_read(&ps->num_sta_ps) && skb_queue_empty(&ps->bc_buf)) return TX_CONTINUE; info->flags |= IEEE80211_TX_CTL_SEND_AFTER_DTIM; diff --git a/net/netfilter/nf_tables_api.c b/net/netfilter/nf_tables_api.c index 120e9ae04db3..a7967af0da82 100644 --- a/net/netfilter/nf_tables_api.c +++ b/net/netfilter/nf_tables_api.c @@ -3452,6 +3452,7 @@ static int nft_add_set_elem(struct nft_ctx *ctx, struct nft_set *set, dreg = nft_type_to_reg(set->dtype); list_for_each_entry(binding, &set->bindings, list) { struct nft_ctx bind_ctx = { + .net = ctx->net, .afi = ctx->afi, .table = ctx->table, .chain = (struct nft_chain *)binding->chain, diff --git a/net/sctp/associola.c b/net/sctp/associola.c index a40b8b0ef0d5..f085b01b6603 100644 --- a/net/sctp/associola.c +++ b/net/sctp/associola.c @@ -486,8 +486,9 @@ void sctp_assoc_set_primary(struct sctp_association *asoc, void sctp_assoc_rm_peer(struct sctp_association *asoc, struct sctp_transport *peer) { - struct list_head *pos; - struct sctp_transport *transport; + struct sctp_transport *transport; + struct list_head *pos; + struct sctp_chunk *ch; pr_debug("%s: association:%p addr:%pISpc\n", __func__, asoc, &peer->ipaddr.sa); @@ -543,7 +544,6 @@ void sctp_assoc_rm_peer(struct sctp_association *asoc, */ if (!list_empty(&peer->transmitted)) { struct sctp_transport *active = asoc->peer.active_path; - struct sctp_chunk *ch; /* Reset the transport of each chunk on this list */ list_for_each_entry(ch, &peer->transmitted, @@ -565,6 +565,10 @@ void sctp_assoc_rm_peer(struct sctp_association *asoc, sctp_transport_hold(active); } + list_for_each_entry(ch, &asoc->outqueue.out_chunk_list, list) + if (ch->transport == peer) + ch->transport = NULL; + asoc->peer.transport_count--; sctp_transport_free(peer); diff --git a/net/sunrpc/auth_generic.c b/net/sunrpc/auth_generic.c index 41248b1820c7..cc27e38392ea 100644 --- a/net/sunrpc/auth_generic.c +++ b/net/sunrpc/auth_generic.c @@ -272,13 +272,7 @@ static bool generic_key_to_expire(struct rpc_cred *cred) { struct auth_cred *acred = &container_of(cred, struct generic_cred, gc_base)->acred; - bool ret; - - get_rpccred(cred); - ret = test_bit(RPC_CRED_KEY_EXPIRE_SOON, &acred->ac_flags); - put_rpccred(cred); - - return ret; + return test_bit(RPC_CRED_KEY_EXPIRE_SOON, &acred->ac_flags); } static const struct rpc_credops generic_credops = { diff --git a/net/sunrpc/auth_gss/auth_gss.c b/net/sunrpc/auth_gss/auth_gss.c index 1f0687d8e3d7..62fca77bf3c7 100644 --- a/net/sunrpc/auth_gss/auth_gss.c +++ b/net/sunrpc/auth_gss/auth_gss.c @@ -1722,6 +1722,7 @@ priv_release_snd_buf(struct rpc_rqst *rqstp) for (i=0; i < rqstp->rq_enc_pages_num; i++) __free_page(rqstp->rq_enc_pages[i]); kfree(rqstp->rq_enc_pages); + rqstp->rq_release_snd_buf = NULL; } static int @@ -1730,6 +1731,9 @@ alloc_enc_pages(struct rpc_rqst *rqstp) struct xdr_buf *snd_buf = &rqstp->rq_snd_buf; int first, last, i; + if (rqstp->rq_release_snd_buf) + rqstp->rq_release_snd_buf(rqstp); + if (snd_buf->page_len == 0) { rqstp->rq_enc_pages_num = 0; return 0; diff --git a/scripts/Makefile.extrawarn b/scripts/Makefile.extrawarn index abe5f47b1ab0..93e23a73b232 100644 --- a/scripts/Makefile.extrawarn +++ b/scripts/Makefile.extrawarn @@ -10,6 +10,8 @@ # are not supported by all versions of the compiler # ========================================================================== +KBUILD_CFLAGS += $(call cc-disable-warning, packed-not-aligned) + ifeq ("$(origin W)", "command line") export KBUILD_ENABLE_EXTRA_GCC_CHECKS := $(W) endif @@ -25,6 +27,7 @@ warning-1 += -Wold-style-definition warning-1 += $(call cc-option, -Wmissing-include-dirs) warning-1 += $(call cc-option, -Wunused-but-set-variable) warning-1 += $(call cc-option, -Wunused-const-variable) +warning-1 += $(call cc-option, -Wpacked-not-aligned) warning-1 += $(call cc-disable-warning, missing-field-initializers) warning-2 := -Waggregate-return diff --git a/scripts/clang-android.sh b/scripts/clang-android.sh new file mode 100755 index 000000000000..9186c4f48576 --- /dev/null +++ b/scripts/clang-android.sh @@ -0,0 +1,4 @@ +#!/bin/sh +# SPDX-License-Identifier: GPL-2.0 + +$* -dM -E - </dev/null 2>&1 | grep -q __ANDROID__ && echo "y" diff --git a/scripts/unifdef.c b/scripts/unifdef.c index 7493c0ee51cc..db00e3e30a59 100644 --- a/scripts/unifdef.c +++ b/scripts/unifdef.c @@ -395,7 +395,7 @@ usage(void) * When we have processed a group that starts off with a known-false * #if/#elif sequence (which has therefore been deleted) followed by a * #elif that we don't understand and therefore must keep, we edit the - * latter into a #if to keep the nesting correct. We use strncpy() to + * latter into a #if to keep the nesting correct. We use memcpy() to * overwrite the 4 byte token "elif" with "if " without a '\0' byte. * * When we find a true #elif in a group, the following block will @@ -450,7 +450,7 @@ static void Idrop (void) { Fdrop(); ignoreon(); } static void Itrue (void) { Ftrue(); ignoreon(); } static void Ifalse(void) { Ffalse(); ignoreon(); } /* modify this line */ -static void Mpass (void) { strncpy(keyword, "if ", 4); Pelif(); } +static void Mpass (void) { memcpy(keyword, "if ", 4); Pelif(); } static void Mtrue (void) { keywordedit("else"); state(IS_TRUE_MIDDLE); } static void Melif (void) { keywordedit("endif"); state(IS_FALSE_TRAILER); } static void Melse (void) { keywordedit("endif"); state(IS_FALSE_ELSE); } diff --git a/sound/core/control.c b/sound/core/control.c index bd01d492f46a..2be860a446a2 100644 --- a/sound/core/control.c +++ b/sound/core/control.c @@ -346,6 +346,40 @@ static int snd_ctl_find_hole(struct snd_card *card, unsigned int count) return 0; } +/* add a new kcontrol object; call with card->controls_rwsem locked */ +static int __snd_ctl_add(struct snd_card *card, struct snd_kcontrol *kcontrol) +{ + struct snd_ctl_elem_id id; + unsigned int idx; + unsigned int count; + + id = kcontrol->id; + if (id.index > UINT_MAX - kcontrol->count) + return -EINVAL; + + if (snd_ctl_find_id(card, &id)) { + dev_err(card->dev, + "control %i:%i:%i:%s:%i is already present\n", + id.iface, id.device, id.subdevice, id.name, id.index); + return -EBUSY; + } + + if (snd_ctl_find_hole(card, kcontrol->count) < 0) + return -ENOMEM; + + list_add_tail(&kcontrol->list, &card->controls); + card->controls_count += kcontrol->count; + kcontrol->id.numid = card->last_numid + 1; + card->last_numid += kcontrol->count; + + id = kcontrol->id; + count = kcontrol->count; + for (idx = 0; idx < count; idx++, id.index++, id.numid++) + snd_ctl_notify(card, SNDRV_CTL_EVENT_MASK_ADD, &id); + + return 0; +} + /** * snd_ctl_add - add the control instance to the card * @card: the card instance @@ -362,45 +396,18 @@ static int snd_ctl_find_hole(struct snd_card *card, unsigned int count) */ int snd_ctl_add(struct snd_card *card, struct snd_kcontrol *kcontrol) { - struct snd_ctl_elem_id id; - unsigned int idx; - unsigned int count; int err = -EINVAL; if (! kcontrol) return err; if (snd_BUG_ON(!card || !kcontrol->info)) goto error; - id = kcontrol->id; - if (id.index > UINT_MAX - kcontrol->count) - goto error; down_write(&card->controls_rwsem); - if (snd_ctl_find_id(card, &id)) { - up_write(&card->controls_rwsem); - dev_err(card->dev, "control %i:%i:%i:%s:%i is already present\n", - id.iface, - id.device, - id.subdevice, - id.name, - id.index); - err = -EBUSY; - goto error; - } - if (snd_ctl_find_hole(card, kcontrol->count) < 0) { - up_write(&card->controls_rwsem); - err = -ENOMEM; - goto error; - } - list_add_tail(&kcontrol->list, &card->controls); - card->controls_count += kcontrol->count; - kcontrol->id.numid = card->last_numid + 1; - card->last_numid += kcontrol->count; - id = kcontrol->id; - count = kcontrol->count; + err = __snd_ctl_add(card, kcontrol); up_write(&card->controls_rwsem); - for (idx = 0; idx < count; idx++, id.index++, id.numid++) - snd_ctl_notify(card, SNDRV_CTL_EVENT_MASK_ADD, &id); + if (err < 0) + goto error; return 0; error: @@ -1322,9 +1329,12 @@ static int snd_ctl_elem_add(struct snd_ctl_file *file, kctl->tlv.c = snd_ctl_elem_user_tlv; /* This function manage to free the instance on failure. */ - err = snd_ctl_add(card, kctl); - if (err < 0) - return err; + down_write(&card->controls_rwsem); + err = __snd_ctl_add(card, kctl); + if (err < 0) { + snd_ctl_free_one(kctl); + goto unlock; + } offset = snd_ctl_get_ioff(kctl, &info->id); snd_ctl_build_ioff(&info->id, kctl, offset); /* @@ -1335,10 +1345,10 @@ static int snd_ctl_elem_add(struct snd_ctl_file *file, * which locks the element. */ - down_write(&card->controls_rwsem); card->user_ctl_count++; - up_write(&card->controls_rwsem); + unlock: + up_write(&card->controls_rwsem); return 0; } diff --git a/sound/core/pcm_native.c b/sound/core/pcm_native.c index 981b18bf2e63..c4b15dd51c24 100644 --- a/sound/core/pcm_native.c +++ b/sound/core/pcm_native.c @@ -36,6 +36,7 @@ #include <sound/timer.h> #include <sound/minors.h> #include <linux/uio.h> +#include <linux/delay.h> /* * Compatibility @@ -79,12 +80,12 @@ static DECLARE_RWSEM(snd_pcm_link_rwsem); * and this may lead to a deadlock when the code path takes read sem * twice (e.g. one in snd_pcm_action_nonatomic() and another in * snd_pcm_stream_lock()). As a (suboptimal) workaround, let writer to - * spin until it gets the lock. + * sleep until all the readers are completed without blocking by writer. */ -static inline void down_write_nonblock(struct rw_semaphore *lock) +static inline void down_write_nonfifo(struct rw_semaphore *lock) { while (!down_write_trylock(lock)) - cond_resched(); + msleep(1); } /** @@ -1851,7 +1852,7 @@ static int snd_pcm_link(struct snd_pcm_substream *substream, int fd) res = -ENOMEM; goto _nolock; } - down_write_nonblock(&snd_pcm_link_rwsem); + down_write_nonfifo(&snd_pcm_link_rwsem); write_lock_irq(&snd_pcm_link_rwlock); if (substream->runtime->status->state == SNDRV_PCM_STATE_OPEN || substream->runtime->status->state != substream1->runtime->status->state || @@ -1898,7 +1899,7 @@ static int snd_pcm_unlink(struct snd_pcm_substream *substream) struct snd_pcm_substream *s; int res = 0; - down_write_nonblock(&snd_pcm_link_rwsem); + down_write_nonfifo(&snd_pcm_link_rwsem); write_lock_irq(&snd_pcm_link_rwlock); if (!snd_pcm_stream_linked(substream)) { res = -EALREADY; @@ -2251,7 +2252,8 @@ int snd_pcm_hw_constraints_complete(struct snd_pcm_substream *substream) static void pcm_release_private(struct snd_pcm_substream *substream) { - snd_pcm_unlink(substream); + if (snd_pcm_stream_linked(substream)) + snd_pcm_unlink(substream); } void snd_pcm_release_substream(struct snd_pcm_substream *substream) diff --git a/sound/isa/wss/wss_lib.c b/sound/isa/wss/wss_lib.c index 913b731d2236..f40330ddb9b2 100644 --- a/sound/isa/wss/wss_lib.c +++ b/sound/isa/wss/wss_lib.c @@ -1531,7 +1531,6 @@ static int snd_wss_playback_open(struct snd_pcm_substream *substream) if (err < 0) { if (chip->release_dma) chip->release_dma(chip, chip->dma_private_data, chip->dma1); - snd_free_pages(runtime->dma_area, runtime->dma_bytes); return err; } chip->playback_substream = substream; @@ -1572,7 +1571,6 @@ static int snd_wss_capture_open(struct snd_pcm_substream *substream) if (err < 0) { if (chip->release_dma) chip->release_dma(chip, chip->dma_private_data, chip->dma2); - snd_free_pages(runtime->dma_area, runtime->dma_bytes); return err; } chip->capture_substream = substream; diff --git a/sound/pci/ac97/ac97_codec.c b/sound/pci/ac97/ac97_codec.c index 82259ca61e64..c4840fda44b4 100644 --- a/sound/pci/ac97/ac97_codec.c +++ b/sound/pci/ac97/ac97_codec.c @@ -824,7 +824,7 @@ static int snd_ac97_put_spsa(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_ { struct snd_ac97 *ac97 = snd_kcontrol_chip(kcontrol); int reg = kcontrol->private_value & 0xff; - int shift = (kcontrol->private_value >> 8) & 0xff; + int shift = (kcontrol->private_value >> 8) & 0x0f; int mask = (kcontrol->private_value >> 16) & 0xff; // int invert = (kcontrol->private_value >> 24) & 0xff; unsigned short value, old, new; diff --git a/sound/pci/hda/hda_intel.c b/sound/pci/hda/hda_intel.c index ecb07fb036af..f964743b104c 100644 --- a/sound/pci/hda/hda_intel.c +++ b/sound/pci/hda/hda_intel.c @@ -2363,6 +2363,10 @@ static const struct pci_device_id azx_ids[] = { /* AMD Hudson */ { PCI_DEVICE(0x1022, 0x780d), .driver_data = AZX_DRIVER_GENERIC | AZX_DCAPS_PRESET_ATI_SB }, + /* AMD Stoney */ + { PCI_DEVICE(0x1022, 0x157a), + .driver_data = AZX_DRIVER_GENERIC | AZX_DCAPS_PRESET_ATI_SB | + AZX_DCAPS_PM_RUNTIME }, /* AMD Raven */ { PCI_DEVICE(0x1022, 0x15e3), .driver_data = AZX_DRIVER_GENERIC | AZX_DCAPS_PRESET_ATI_SB | diff --git a/sound/pci/trident/trident.c b/sound/pci/trident/trident.c index cedf13b64803..2f18b1cdc2cd 100644 --- a/sound/pci/trident/trident.c +++ b/sound/pci/trident/trident.c @@ -123,7 +123,7 @@ static int snd_trident_probe(struct pci_dev *pci, } else { strcpy(card->shortname, "Trident "); } - strcat(card->shortname, card->driver); + strcat(card->shortname, str); sprintf(card->longname, "%s PCI Audio at 0x%lx, irq %d", card->shortname, trident->port, trident->irq); diff --git a/sound/soc/codecs/msm_sdw/msm_sdw_cdc.c b/sound/soc/codecs/msm_sdw/msm_sdw_cdc.c index 58df020811f1..1c79e632b8f8 100644 --- a/sound/soc/codecs/msm_sdw/msm_sdw_cdc.c +++ b/sound/soc/codecs/msm_sdw/msm_sdw_cdc.c @@ -1,4 +1,4 @@ -/* Copyright (c) 2016-2017, The Linux Foundation. All rights reserved. +/* Copyright (c) 2016-2018, The Linux Foundation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 and @@ -471,9 +471,9 @@ static int msm_sdw_codec_enable_vi_feedback(struct snd_soc_dapm_widget *w, MSM_SDW_TX10_SPKR_PROT_PATH_CTL, 0x20, 0x20); snd_soc_update_bits(codec, - MSM_SDW_TX9_SPKR_PROT_PATH_CTL, 0x0F, 0x04); + MSM_SDW_TX9_SPKR_PROT_PATH_CTL, 0x0F, 0x00); snd_soc_update_bits(codec, - MSM_SDW_TX10_SPKR_PROT_PATH_CTL, 0x0F, 0x04); + MSM_SDW_TX10_SPKR_PROT_PATH_CTL, 0x0F, 0x00); snd_soc_update_bits(codec, MSM_SDW_TX9_SPKR_PROT_PATH_CTL, 0x10, 0x10); snd_soc_update_bits(codec, @@ -496,10 +496,10 @@ static int msm_sdw_codec_enable_vi_feedback(struct snd_soc_dapm_widget *w, 0x20); snd_soc_update_bits(codec, MSM_SDW_TX11_SPKR_PROT_PATH_CTL, 0x0F, - 0x04); + 0x00); snd_soc_update_bits(codec, MSM_SDW_TX12_SPKR_PROT_PATH_CTL, 0x0F, - 0x04); + 0x00); snd_soc_update_bits(codec, MSM_SDW_TX11_SPKR_PROT_PATH_CTL, 0x10, 0x10); diff --git a/sound/soc/msm/apq8096-auto.c b/sound/soc/msm/apq8096-auto.c index e5d99f5fd7d1..69a1fbfa45aa 100644 --- a/sound/soc/msm/apq8096-auto.c +++ b/sound/soc/msm/apq8096-auto.c @@ -160,6 +160,42 @@ static int msm_tert_tdm_slot_num = 8; static int msm_quat_tdm_slot_width = 32; static int msm_quat_tdm_slot_num = 8; +/* Group_MI2S default port channels */ +static int msm_sec_group_mi2s_rx_1_ch = 2; +static int msm_sec_group_mi2s_rx_2_ch = 2; +static int msm_sec_group_mi2s_rx_3_ch = 2; +static int msm_sec_group_mi2s_rx_4_ch = 2; +static int msm_sec_group_mi2s_tx_1_ch = 2; +static int msm_sec_group_mi2s_tx_2_ch = 2; +static int msm_sec_group_mi2s_tx_3_ch = 2; +static int msm_sec_group_mi2s_tx_4_ch = 2; +static int msm_tert_group_mi2s_rx_1_ch = 2; +static int msm_tert_group_mi2s_rx_2_ch = 2; +static int msm_tert_group_mi2s_rx_3_ch = 2; +static int msm_tert_group_mi2s_rx_4_ch = 2; +static int msm_tert_group_mi2s_tx_1_ch = 2; +static int msm_tert_group_mi2s_tx_2_ch = 2; +static int msm_tert_group_mi2s_tx_3_ch = 2; +static int msm_tert_group_mi2s_tx_4_ch = 2; +static int msm_quat_group_mi2s_rx_1_ch = 2; +static int msm_quat_group_mi2s_rx_2_ch = 2; +static int msm_quat_group_mi2s_rx_3_ch = 2; +static int msm_quat_group_mi2s_rx_4_ch = 2; +static int msm_quat_group_mi2s_tx_1_ch = 2; +static int msm_quat_group_mi2s_tx_2_ch = 2; +static int msm_quat_group_mi2s_tx_3_ch = 2; +static int msm_quat_group_mi2s_tx_4_ch = 2; + +/* Group MI2S default sample rate*/ +static int msm_sec_group_mi2s_rate = SAMPLING_RATE_48KHZ; +static int msm_tert_group_mi2s_rate = SAMPLING_RATE_48KHZ; +static int msm_quat_group_mi2s_rate = SAMPLING_RATE_48KHZ; + +/* Group MI2S slot width bit format */ +static int msm_sec_group_mi2s_bit_format = SNDRV_PCM_FORMAT_S24_LE; +static int msm_tert_group_mi2s_bit_format = SNDRV_PCM_FORMAT_S24_LE; +static int msm_quat_group_mi2s_bit_format = SNDRV_PCM_FORMAT_S24_LE; + /* EC Reference default values are set in mixer_paths.xml */ static int msm_ec_ref_ch = 4; static int msm_ec_ref_bit_format = SNDRV_PCM_FORMAT_S16_LE; @@ -172,6 +208,41 @@ static void *adsp_state_notifier; static bool dummy_device_registered; static struct snd_soc_card *sndcard; +#define GROUP_MI2S_SLOT_OFFSET_MAX 8 +static unsigned int group_mi2s_slot_offset + [IDX_GROUP_MI2S_PORT_MAX][GROUP_MI2S_SLOT_OFFSET_MAX] = { + /* GROUP_SEC_MI2S_RX */ + {0, 4, 0xFFFF}, + {0, 4, 0xFFFF}, + {0xFFFF}, + {0xFFFF}, + /* GROUP_SEC_MI2S_TX */ + {0, 4, 0xFFFF}, + {0, 4, 0xFFFF}, + {0xFFFF}, + {0xFFFF}, + /* GROUP_TERT_MI2S_RX */ + {0, 4, 0xFFFF}, + {0, 4, 0xFFFF}, + {0xFFFF}, + {0xFFFF}, + /* GROUP_TERT_MI2S_TX */ + {0, 4, 0xFFFF}, + {0, 4, 0xFFFF}, + {0xFFFF}, + {0xFFFF}, + /* GROUP_QUAT_MI2S_RX */ + {0, 4, 0xFFFF}, + {0, 4, 0xFFFF}, + {0, 4, 0xFFFF}, + {0, 4, 0xFFFF}, + /* GROUP_QUAT_MI2S_TX */ + {0, 4, 0xFFFF}, + {0, 4, 0xFFFF}, + {0, 4, 0xFFFF}, + {0, 4, 0xFFFF}, +}; + enum { QUATERNARY_TDM_RX_0, QUATERNARY_TDM_RX_1, @@ -3307,6 +3378,173 @@ static int msm_mi2s_tx_be_hw_params_fixup(struct snd_soc_pcm_runtime *rtd, return 0; } +static int msm_group_mi2s_be_hw_params_fixup(struct snd_soc_pcm_runtime *rtd, + struct snd_pcm_hw_params *params) +{ + struct snd_soc_dai *cpu_dai = rtd->cpu_dai; + struct snd_interval *rate = + hw_param_interval(params, SNDRV_PCM_HW_PARAM_RATE); + struct snd_interval *channels = + hw_param_interval(params, SNDRV_PCM_HW_PARAM_CHANNELS); + + switch (cpu_dai->id) { + case AFE_PORT_ID_SECONDARY_MI2S_RX_1: + channels->min = channels->max = msm_sec_group_mi2s_rx_1_ch; + rate->min = rate->max = msm_sec_group_mi2s_rate; + param_set_mask(params, SNDRV_PCM_HW_PARAM_FORMAT, + msm_sec_group_mi2s_bit_format); + break; + case AFE_PORT_ID_SECONDARY_MI2S_RX_2: + channels->min = channels->max = msm_sec_group_mi2s_rx_2_ch; + rate->min = rate->max = msm_sec_group_mi2s_rate; + param_set_mask(params, SNDRV_PCM_HW_PARAM_FORMAT, + msm_sec_group_mi2s_bit_format); + break; + case AFE_PORT_ID_SECONDARY_MI2S_RX_3: + channels->min = channels->max = msm_sec_group_mi2s_rx_3_ch; + rate->min = rate->max = msm_sec_group_mi2s_rate; + param_set_mask(params, SNDRV_PCM_HW_PARAM_FORMAT, + msm_sec_group_mi2s_bit_format); + break; + case AFE_PORT_ID_SECONDARY_MI2S_RX_4: + channels->min = channels->max = msm_sec_group_mi2s_rx_4_ch; + rate->min = rate->max = msm_sec_group_mi2s_rate; + param_set_mask(params, SNDRV_PCM_HW_PARAM_FORMAT, + msm_sec_group_mi2s_bit_format); + break; + case AFE_PORT_ID_SECONDARY_MI2S_TX_1: + channels->min = channels->max = msm_sec_group_mi2s_tx_1_ch; + rate->min = rate->max = msm_sec_group_mi2s_rate; + param_set_mask(params, SNDRV_PCM_HW_PARAM_FORMAT, + msm_sec_group_mi2s_bit_format); + break; + case AFE_PORT_ID_SECONDARY_MI2S_TX_2: + channels->min = channels->max = msm_sec_group_mi2s_tx_2_ch; + rate->min = rate->max = msm_sec_group_mi2s_rate; + param_set_mask(params, SNDRV_PCM_HW_PARAM_FORMAT, + msm_sec_group_mi2s_bit_format); + break; + case AFE_PORT_ID_SECONDARY_MI2S_TX_3: + channels->min = channels->max = msm_sec_group_mi2s_tx_3_ch; + rate->min = rate->max = msm_sec_group_mi2s_rate; + param_set_mask(params, SNDRV_PCM_HW_PARAM_FORMAT, + msm_sec_group_mi2s_bit_format); + break; + case AFE_PORT_ID_SECONDARY_MI2S_TX_4: + channels->min = channels->max = msm_sec_group_mi2s_tx_4_ch; + rate->min = rate->max = msm_sec_group_mi2s_rate; + param_set_mask(params, SNDRV_PCM_HW_PARAM_FORMAT, + msm_sec_group_mi2s_bit_format); + break; + case AFE_PORT_ID_TERTIARY_MI2S_RX_1: + channels->min = channels->max = msm_tert_group_mi2s_rx_1_ch; + rate->min = rate->max = msm_tert_group_mi2s_rate; + param_set_mask(params, SNDRV_PCM_HW_PARAM_FORMAT, + msm_tert_group_mi2s_bit_format); + break; + case AFE_PORT_ID_TERTIARY_MI2S_RX_2: + channels->min = channels->max = msm_tert_group_mi2s_rx_2_ch; + rate->min = rate->max = msm_tert_group_mi2s_rate; + param_set_mask(params, SNDRV_PCM_HW_PARAM_FORMAT, + msm_tert_group_mi2s_bit_format); + break; + case AFE_PORT_ID_TERTIARY_MI2S_RX_3: + channels->min = channels->max = msm_tert_group_mi2s_rx_3_ch; + rate->min = rate->max = msm_tert_group_mi2s_rate; + param_set_mask(params, SNDRV_PCM_HW_PARAM_FORMAT, + msm_tert_group_mi2s_bit_format); + break; + case AFE_PORT_ID_TERTIARY_MI2S_RX_4: + channels->min = channels->max = msm_tert_group_mi2s_rx_4_ch; + rate->min = rate->max = msm_tert_group_mi2s_rate; + param_set_mask(params, SNDRV_PCM_HW_PARAM_FORMAT, + msm_tert_group_mi2s_bit_format); + break; + case AFE_PORT_ID_TERTIARY_MI2S_TX_1: + channels->min = channels->max = msm_tert_group_mi2s_tx_1_ch; + rate->min = rate->max = msm_tert_group_mi2s_rate; + param_set_mask(params, SNDRV_PCM_HW_PARAM_FORMAT, + msm_tert_group_mi2s_bit_format); + break; + case AFE_PORT_ID_TERTIARY_MI2S_TX_2: + channels->min = channels->max = msm_tert_group_mi2s_tx_2_ch; + rate->min = rate->max = msm_tert_group_mi2s_rate; + param_set_mask(params, SNDRV_PCM_HW_PARAM_FORMAT, + msm_tert_group_mi2s_bit_format); + break; + case AFE_PORT_ID_TERTIARY_MI2S_TX_3: + channels->min = channels->max = msm_tert_group_mi2s_tx_3_ch; + rate->min = rate->max = msm_tert_group_mi2s_rate; + param_set_mask(params, SNDRV_PCM_HW_PARAM_FORMAT, + msm_tert_group_mi2s_bit_format); + break; + case AFE_PORT_ID_TERTIARY_MI2S_TX_4: + channels->min = channels->max = msm_tert_group_mi2s_tx_4_ch; + rate->min = rate->max = msm_tert_group_mi2s_rate; + param_set_mask(params, SNDRV_PCM_HW_PARAM_FORMAT, + msm_tert_group_mi2s_bit_format); + break; + case AFE_PORT_ID_QUATERNARY_MI2S_RX_1: + channels->min = channels->max = msm_quat_group_mi2s_rx_1_ch; + rate->min = rate->max = msm_quat_group_mi2s_rate; + param_set_mask(params, SNDRV_PCM_HW_PARAM_FORMAT, + msm_quat_group_mi2s_bit_format); + break; + case AFE_PORT_ID_QUATERNARY_MI2S_RX_2: + channels->min = channels->max = msm_quat_group_mi2s_rx_2_ch; + rate->min = rate->max = msm_quat_group_mi2s_rate; + param_set_mask(params, SNDRV_PCM_HW_PARAM_FORMAT, + msm_quat_group_mi2s_bit_format); + break; + case AFE_PORT_ID_QUATERNARY_MI2S_RX_3: + channels->min = channels->max = msm_quat_group_mi2s_rx_3_ch; + rate->min = rate->max = msm_quat_group_mi2s_rate; + param_set_mask(params, SNDRV_PCM_HW_PARAM_FORMAT, + msm_quat_group_mi2s_bit_format); + break; + case AFE_PORT_ID_QUATERNARY_MI2S_RX_4: + channels->min = channels->max = msm_quat_group_mi2s_rx_4_ch; + rate->min = rate->max = msm_quat_group_mi2s_rate; + param_set_mask(params, SNDRV_PCM_HW_PARAM_FORMAT, + msm_quat_group_mi2s_bit_format); + break; + case AFE_PORT_ID_QUATERNARY_MI2S_TX_1: + channels->min = channels->max = msm_quat_group_mi2s_tx_1_ch; + rate->min = rate->max = msm_quat_group_mi2s_rate; + param_set_mask(params, SNDRV_PCM_HW_PARAM_FORMAT, + msm_quat_group_mi2s_bit_format); + break; + case AFE_PORT_ID_QUATERNARY_MI2S_TX_2: + channels->min = channels->max = msm_quat_group_mi2s_tx_2_ch; + rate->min = rate->max = msm_quat_group_mi2s_rate; + param_set_mask(params, SNDRV_PCM_HW_PARAM_FORMAT, + msm_quat_group_mi2s_bit_format); + break; + case AFE_PORT_ID_QUATERNARY_MI2S_TX_3: + channels->min = channels->max = msm_quat_group_mi2s_tx_3_ch; + rate->min = rate->max = msm_quat_group_mi2s_rate; + param_set_mask(params, SNDRV_PCM_HW_PARAM_FORMAT, + msm_quat_group_mi2s_bit_format); + break; + case AFE_PORT_ID_QUATERNARY_MI2S_TX_4: + channels->min = channels->max = msm_quat_group_mi2s_tx_4_ch; + rate->min = rate->max = msm_quat_group_mi2s_rate; + param_set_mask(params, SNDRV_PCM_HW_PARAM_FORMAT, + msm_quat_group_mi2s_bit_format); + break; + default: + pr_err("%s: dai id 0x%x not supported\n", + __func__, cpu_dai->id); + return -EINVAL; + } + + pr_debug("%s: dai id = 0x%x channels = %d rate = %d format = 0x%x\n", + __func__, cpu_dai->id, channels->max, rate->max, + params_format(params)); + + return 0; +} + static int msm_be_hw_params_fixup(struct snd_soc_pcm_runtime *rtd, struct snd_pcm_hw_params *params) { @@ -4085,6 +4323,142 @@ static struct snd_soc_ops apq8096_tdm_be_ops = { .hw_params = apq8096_tdm_snd_hw_params, }; +static int apq8096_group_mi2s_snd_hw_params(struct snd_pcm_substream *substream, + struct snd_pcm_hw_params *params) +{ + struct snd_soc_pcm_runtime *rtd = substream->private_data; + struct snd_soc_dai *cpu_dai = rtd->cpu_dai; + int ret = 0; + int channels, rate; + unsigned int *slot_offset; + int offset_channels = 0; + int i; + + rate = params_rate(params); + channels = params_channels(params); + + switch (cpu_dai->id) { + case AFE_PORT_ID_SECONDARY_MI2S_RX_1: + slot_offset = group_mi2s_slot_offset[IDX_SECONDARY_MI2S_RX_1]; + break; + case AFE_PORT_ID_SECONDARY_MI2S_RX_2: + slot_offset = group_mi2s_slot_offset[IDX_SECONDARY_MI2S_RX_2]; + break; + case AFE_PORT_ID_SECONDARY_MI2S_RX_3: + slot_offset = group_mi2s_slot_offset[IDX_SECONDARY_MI2S_RX_3]; + break; + case AFE_PORT_ID_SECONDARY_MI2S_RX_4: + slot_offset = group_mi2s_slot_offset[IDX_SECONDARY_MI2S_RX_4]; + break; + case AFE_PORT_ID_SECONDARY_MI2S_TX_1: + slot_offset = group_mi2s_slot_offset[IDX_SECONDARY_MI2S_TX_1]; + break; + case AFE_PORT_ID_SECONDARY_MI2S_TX_2: + slot_offset = group_mi2s_slot_offset[IDX_SECONDARY_MI2S_TX_2]; + break; + case AFE_PORT_ID_SECONDARY_MI2S_TX_3: + slot_offset = group_mi2s_slot_offset[IDX_SECONDARY_MI2S_TX_3]; + break; + case AFE_PORT_ID_SECONDARY_MI2S_TX_4: + slot_offset = group_mi2s_slot_offset[IDX_SECONDARY_MI2S_TX_4]; + break; + case AFE_PORT_ID_TERTIARY_MI2S_RX_1: + slot_offset = group_mi2s_slot_offset[IDX_TERTIARY_MI2S_RX_1]; + break; + case AFE_PORT_ID_TERTIARY_MI2S_RX_2: + slot_offset = group_mi2s_slot_offset[IDX_TERTIARY_MI2S_RX_2]; + break; + case AFE_PORT_ID_TERTIARY_MI2S_RX_3: + slot_offset = group_mi2s_slot_offset[IDX_TERTIARY_MI2S_RX_3]; + break; + case AFE_PORT_ID_TERTIARY_MI2S_RX_4: + slot_offset = group_mi2s_slot_offset[IDX_TERTIARY_MI2S_RX_4]; + break; + case AFE_PORT_ID_TERTIARY_MI2S_TX_1: + slot_offset = group_mi2s_slot_offset[IDX_TERTIARY_MI2S_TX_1]; + break; + case AFE_PORT_ID_TERTIARY_MI2S_TX_2: + slot_offset = group_mi2s_slot_offset[IDX_TERTIARY_MI2S_TX_2]; + break; + case AFE_PORT_ID_TERTIARY_MI2S_TX_3: + slot_offset = group_mi2s_slot_offset[IDX_TERTIARY_MI2S_TX_3]; + break; + case AFE_PORT_ID_TERTIARY_MI2S_TX_4: + slot_offset = group_mi2s_slot_offset[IDX_TERTIARY_MI2S_TX_4]; + break; + case AFE_PORT_ID_QUATERNARY_MI2S_RX_1: + slot_offset = group_mi2s_slot_offset[IDX_QUATERNARY_MI2S_RX_1]; + break; + case AFE_PORT_ID_QUATERNARY_MI2S_RX_2: + slot_offset = group_mi2s_slot_offset[IDX_QUATERNARY_MI2S_RX_2]; + break; + case AFE_PORT_ID_QUATERNARY_MI2S_RX_3: + slot_offset = group_mi2s_slot_offset[IDX_QUATERNARY_MI2S_RX_3]; + break; + case AFE_PORT_ID_QUATERNARY_MI2S_RX_4: + slot_offset = group_mi2s_slot_offset[IDX_QUATERNARY_MI2S_RX_4]; + break; + case AFE_PORT_ID_QUATERNARY_MI2S_TX_1: + slot_offset = group_mi2s_slot_offset[IDX_QUATERNARY_MI2S_TX_1]; + break; + case AFE_PORT_ID_QUATERNARY_MI2S_TX_2: + slot_offset = group_mi2s_slot_offset[IDX_QUATERNARY_MI2S_TX_2]; + break; + case AFE_PORT_ID_QUATERNARY_MI2S_TX_3: + slot_offset = group_mi2s_slot_offset[IDX_QUATERNARY_MI2S_TX_3]; + break; + case AFE_PORT_ID_QUATERNARY_MI2S_TX_4: + slot_offset = group_mi2s_slot_offset[IDX_QUATERNARY_MI2S_TX_4]; + break; + default: + pr_err("%s: dai id 0x%x not supported\n", + __func__, cpu_dai->id); + return -EINVAL; + } + + for (i = 0; i < GROUP_MI2S_SLOT_OFFSET_MAX; i++) { + if (slot_offset[i] != AFE_SLOT_MAPPING_OFFSET_INVALID) + offset_channels++; + } + + if (offset_channels == 0) { + pr_err("%s: slot offset not supported, offset_channels %d\n", + __func__, offset_channels); + return -EINVAL; + } + + if (channels > offset_channels) { + pr_err("%s: channels %d and offset_channels %d not match\n", + __func__, channels, offset_channels); + return -EINVAL; + } + + if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) { + ret = snd_soc_dai_set_channel_map(cpu_dai, 0, NULL, + channels, slot_offset); + if (ret < 0) { + pr_err("%s: failed to set channel map, err:%d\n", + __func__, ret); + goto end; + } + } else { + ret = snd_soc_dai_set_channel_map(cpu_dai, + channels, slot_offset, + 0, NULL); + if (ret < 0) { + pr_err("%s: failed to set channel map, err:%d\n", + __func__, ret); + goto end; + } + } +end: + return ret; +} + +static struct snd_soc_ops apq8096_group_mi2s_be_ops = { + .hw_params = apq8096_group_mi2s_snd_hw_params, +}; + static const struct soc_enum msm_snd_enum[] = { SOC_ENUM_SINGLE_EXT(2, auxpcm_rate_text), SOC_ENUM_SINGLE_EXT(7, hdmi_rx_ch_text), @@ -6546,6 +6920,342 @@ static struct snd_soc_dai_link apq8096_auto_be_dai_links[] = { .be_hw_params_fixup = msm_tdm_be_hw_params_fixup, .ops = &apq8096_tdm_be_ops, .ignore_suspend = 1, + }, + { + .name = LPASS_BE_SEC_MI2S_TX_1, + .stream_name = "Secondary MI2S1 Capture", + .cpu_dai_name = "msm-dai-q6-mi2s.4161", + .platform_name = "msm-pcm-routing", + .codec_name = "msm-stub-codec.1", + .codec_dai_name = "msm-stub-tx", + .no_pcm = 1, + .dpcm_capture = 1, + .be_id = MSM_BACKEND_DAI_SECONDARY_MI2S_TX_1, + .be_hw_params_fixup = msm_group_mi2s_be_hw_params_fixup, + .ops = &apq8096_group_mi2s_be_ops, + .ignore_suspend = 1, + }, + { + .name = LPASS_BE_SEC_MI2S_TX_2, + .stream_name = "Secondary MI2S2 Capture", + .cpu_dai_name = "msm-dai-q6-mi2s.4163", + .platform_name = "msm-pcm-routing", + .codec_name = "msm-stub-codec.1", + .codec_dai_name = "msm-stub-tx", + .no_pcm = 1, + .dpcm_capture = 1, + .be_id = MSM_BACKEND_DAI_SECONDARY_MI2S_TX_2, + .be_hw_params_fixup = msm_group_mi2s_be_hw_params_fixup, + .ops = &apq8096_group_mi2s_be_ops, + .ignore_suspend = 1, + }, + { + .name = LPASS_BE_SEC_MI2S_TX_3, + .stream_name = "Secondary MI2S3 Capture", + .cpu_dai_name = "msm-dai-q6-mi2s.4165", + .platform_name = "msm-pcm-routing", + .codec_name = "msm-stub-codec.1", + .codec_dai_name = "msm-stub-tx", + .no_pcm = 1, + .dpcm_capture = 1, + .be_id = MSM_BACKEND_DAI_SECONDARY_MI2S_TX_3, + .be_hw_params_fixup = msm_group_mi2s_be_hw_params_fixup, + .ops = &apq8096_group_mi2s_be_ops, + .ignore_suspend = 1, + }, + { + .name = LPASS_BE_SEC_MI2S_TX_4, + .stream_name = "Secondary MI2S4 Capture", + .cpu_dai_name = "msm-dai-q6-mi2s.4167", + .platform_name = "msm-pcm-routing", + .codec_name = "msm-stub-codec.1", + .codec_dai_name = "msm-stub-tx", + .no_pcm = 1, + .dpcm_capture = 1, + .be_id = MSM_BACKEND_DAI_SECONDARY_MI2S_TX_4, + .be_hw_params_fixup = msm_group_mi2s_be_hw_params_fixup, + .ops = &apq8096_group_mi2s_be_ops, + .ignore_suspend = 1, + }, + { + .name = LPASS_BE_TERT_MI2S_TX_1, + .stream_name = "Tertiary MI2S1 Capture", + .cpu_dai_name = "msm-dai-q6-mi2s.4169", + .platform_name = "msm-pcm-routing", + .codec_name = "msm-stub-codec.1", + .codec_dai_name = "msm-stub-tx", + .no_pcm = 1, + .dpcm_capture = 1, + .be_id = MSM_BACKEND_DAI_TERTIARY_MI2S_TX_1, + .be_hw_params_fixup = msm_group_mi2s_be_hw_params_fixup, + .ops = &apq8096_group_mi2s_be_ops, + .ignore_suspend = 1, + }, + { + .name = LPASS_BE_TERT_MI2S_TX_2, + .stream_name = "Tertiary MI2S2 Capture", + .cpu_dai_name = "msm-dai-q6-mi2s.4171", + .platform_name = "msm-pcm-routing", + .codec_name = "msm-stub-codec.1", + .codec_dai_name = "msm-stub-tx", + .no_pcm = 1, + .dpcm_capture = 1, + .be_id = MSM_BACKEND_DAI_TERTIARY_MI2S_TX_2, + .be_hw_params_fixup = msm_group_mi2s_be_hw_params_fixup, + .ops = &apq8096_group_mi2s_be_ops, + .ignore_suspend = 1, + }, + { + .name = LPASS_BE_TERT_MI2S_TX_3, + .stream_name = "Tertiary MI2S3 Capture", + .cpu_dai_name = "msm-dai-q6-mi2s.4173", + .platform_name = "msm-pcm-routing", + .codec_name = "msm-stub-codec.1", + .codec_dai_name = "msm-stub-tx", + .no_pcm = 1, + .dpcm_capture = 1, + .be_id = MSM_BACKEND_DAI_TERTIARY_MI2S_TX_3, + .be_hw_params_fixup = msm_group_mi2s_be_hw_params_fixup, + .ops = &apq8096_group_mi2s_be_ops, + .ignore_suspend = 1, + }, + { + .name = LPASS_BE_TERT_MI2S_TX_4, + .stream_name = "Tertiary MI2S4 Capture", + .cpu_dai_name = "msm-dai-q6-mi2s.4175", + .platform_name = "msm-pcm-routing", + .codec_name = "msm-stub-codec.1", + .codec_dai_name = "msm-stub-tx", + .no_pcm = 1, + .dpcm_capture = 1, + .be_id = MSM_BACKEND_DAI_TERTIARY_MI2S_TX_4, + .be_hw_params_fixup = msm_group_mi2s_be_hw_params_fixup, + .ops = &apq8096_group_mi2s_be_ops, + .ignore_suspend = 1, + }, + { + .name = LPASS_BE_QUAT_MI2S_TX_1, + .stream_name = "Quaternary MI2S1 Capture", + .cpu_dai_name = "msm-dai-q6-mi2s.4129", + .platform_name = "msm-pcm-routing", + .codec_name = "msm-stub-codec.1", + .codec_dai_name = "msm-stub-tx", + .no_pcm = 1, + .dpcm_capture = 1, + .be_id = MSM_BACKEND_DAI_QUATERNARY_MI2S_TX_1, + .be_hw_params_fixup = msm_group_mi2s_be_hw_params_fixup, + .ops = &apq8096_group_mi2s_be_ops, + .ignore_suspend = 1, + }, + { + .name = LPASS_BE_QUAT_MI2S_TX_2, + .stream_name = "Quaternary MI2S2 Capture", + .cpu_dai_name = "msm-dai-q6-mi2s.4131", + .platform_name = "msm-pcm-routing", + .codec_name = "msm-stub-codec.1", + .codec_dai_name = "msm-stub-tx", + .no_pcm = 1, + .dpcm_capture = 1, + .be_id = MSM_BACKEND_DAI_QUATERNARY_MI2S_TX_2, + .be_hw_params_fixup = msm_group_mi2s_be_hw_params_fixup, + .ops = &apq8096_group_mi2s_be_ops, + .ignore_suspend = 1, + }, + { + .name = LPASS_BE_QUAT_MI2S_TX_3, + .stream_name = "Quaternary MI2S3 Capture", + .cpu_dai_name = "msm-dai-q6-mi2s.4133", + .platform_name = "msm-pcm-routing", + .codec_name = "msm-stub-codec.1", + .codec_dai_name = "msm-stub-tx", + .no_pcm = 1, + .dpcm_capture = 1, + .be_id = MSM_BACKEND_DAI_QUATERNARY_MI2S_TX_3, + .be_hw_params_fixup = msm_group_mi2s_be_hw_params_fixup, + .ops = &apq8096_group_mi2s_be_ops, + .ignore_suspend = 1, + }, + { + .name = LPASS_BE_QUAT_MI2S_TX_4, + .stream_name = "Quaternary MI2S4 Capture", + .cpu_dai_name = "msm-dai-q6-mi2s.4135", + .platform_name = "msm-pcm-routing", + .codec_name = "msm-stub-codec.1", + .codec_dai_name = "msm-stub-tx", + .no_pcm = 1, + .dpcm_capture = 1, + .be_id = MSM_BACKEND_DAI_QUATERNARY_MI2S_TX_4, + .be_hw_params_fixup = msm_group_mi2s_be_hw_params_fixup, + .ops = &apq8096_group_mi2s_be_ops, + .ignore_suspend = 1, + }, + { + .name = LPASS_BE_SEC_MI2S_RX_1, + .stream_name = "Secondary MI2S1 Playback", + .cpu_dai_name = "msm-dai-q6-mi2s.4160", + .platform_name = "msm-pcm-routing", + .codec_name = "msm-stub-codec.1", + .codec_dai_name = "msm-stub-rx", + .no_pcm = 1, + .dpcm_playback = 1, + .be_id = MSM_BACKEND_DAI_SECONDARY_MI2S_RX_1, + .be_hw_params_fixup = msm_group_mi2s_be_hw_params_fixup, + .ops = &apq8096_group_mi2s_be_ops, + .ignore_suspend = 1, + }, + { + .name = LPASS_BE_SEC_MI2S_RX_2, + .stream_name = "Secondary MI2S2 Playback", + .cpu_dai_name = "msm-dai-q6-mi2s.4162", + .platform_name = "msm-pcm-routing", + .codec_name = "msm-stub-codec.1", + .codec_dai_name = "msm-stub-rx", + .no_pcm = 1, + .dpcm_playback = 1, + .be_id = MSM_BACKEND_DAI_SECONDARY_MI2S_RX_2, + .be_hw_params_fixup = msm_group_mi2s_be_hw_params_fixup, + .ops = &apq8096_group_mi2s_be_ops, + .ignore_suspend = 1, + }, + { + .name = LPASS_BE_SEC_MI2S_RX_3, + .stream_name = "Secondary MI2S3 Playback", + .cpu_dai_name = "msm-dai-q6-mi2s.4164", + .platform_name = "msm-pcm-routing", + .codec_name = "msm-stub-codec.1", + .codec_dai_name = "msm-stub-rx", + .no_pcm = 1, + .dpcm_playback = 1, + .be_id = MSM_BACKEND_DAI_SECONDARY_MI2S_RX_3, + .be_hw_params_fixup = msm_group_mi2s_be_hw_params_fixup, + .ops = &apq8096_group_mi2s_be_ops, + .ignore_suspend = 1, + }, + { + .name = LPASS_BE_SEC_MI2S_RX_4, + .stream_name = "Secondary MI2S4 Playback", + .cpu_dai_name = "msm-dai-q6-mi2s.4166", + .platform_name = "msm-pcm-routing", + .codec_name = "msm-stub-codec.1", + .codec_dai_name = "msm-stub-rx", + .no_pcm = 1, + .dpcm_playback = 1, + .be_id = MSM_BACKEND_DAI_SECONDARY_MI2S_RX_4, + .be_hw_params_fixup = msm_group_mi2s_be_hw_params_fixup, + .ops = &apq8096_group_mi2s_be_ops, + .ignore_suspend = 1, + }, + { + .name = LPASS_BE_TERT_MI2S_RX_1, + .stream_name = "Tertiary MI2S1 Playback", + .cpu_dai_name = "msm-dai-q6-mi2s.4168", + .platform_name = "msm-pcm-routing", + .codec_name = "msm-stub-codec.1", + .codec_dai_name = "msm-stub-rx", + .no_pcm = 1, + .dpcm_playback = 1, + .be_id = MSM_BACKEND_DAI_TERTIARY_MI2S_RX_1, + .be_hw_params_fixup = msm_group_mi2s_be_hw_params_fixup, + .ops = &apq8096_group_mi2s_be_ops, + .ignore_suspend = 1, + }, + { + .name = LPASS_BE_TERT_MI2S_RX_2, + .stream_name = "Tertiary MI2S2 Playback", + .cpu_dai_name = "msm-dai-q6-mi2s.4170", + .platform_name = "msm-pcm-routing", + .codec_name = "msm-stub-codec.1", + .codec_dai_name = "msm-stub-rx", + .no_pcm = 1, + .dpcm_playback = 1, + .be_id = MSM_BACKEND_DAI_TERTIARY_MI2S_RX_2, + .be_hw_params_fixup = msm_group_mi2s_be_hw_params_fixup, + .ops = &apq8096_group_mi2s_be_ops, + .ignore_suspend = 1, + }, + { + .name = LPASS_BE_TERT_MI2S_RX_3, + .stream_name = "Tertiary MI2S3 Playback", + .cpu_dai_name = "msm-dai-q6-mi2s.4172", + .platform_name = "msm-pcm-routing", + .codec_name = "msm-stub-codec.1", + .codec_dai_name = "msm-stub-rx", + .no_pcm = 1, + .dpcm_playback = 1, + .be_id = MSM_BACKEND_DAI_TERTIARY_MI2S_RX_3, + .be_hw_params_fixup = msm_group_mi2s_be_hw_params_fixup, + .ops = &apq8096_group_mi2s_be_ops, + .ignore_suspend = 1, + }, + { + .name = LPASS_BE_TERT_MI2S_RX_4, + .stream_name = "Tertiary MI2S4 Playback", + .cpu_dai_name = "msm-dai-q6-mi2s.4174", + .platform_name = "msm-pcm-routing", + .codec_name = "msm-stub-codec.1", + .codec_dai_name = "msm-stub-rx", + .no_pcm = 1, + .dpcm_playback = 1, + .be_id = MSM_BACKEND_DAI_TERTIARY_MI2S_RX_4, + .be_hw_params_fixup = msm_group_mi2s_be_hw_params_fixup, + .ops = &apq8096_group_mi2s_be_ops, + .ignore_suspend = 1, + }, + { + .name = LPASS_BE_QUAT_MI2S_RX_1, + .stream_name = "Quaternary MI2S1 Playback", + .cpu_dai_name = "msm-dai-q6-mi2s.4128", + .platform_name = "msm-pcm-routing", + .codec_name = "msm-stub-codec.1", + .codec_dai_name = "msm-stub-rx", + .no_pcm = 1, + .dpcm_playback = 1, + .be_id = MSM_BACKEND_DAI_QUATERNARY_MI2S_RX_1, + .be_hw_params_fixup = msm_group_mi2s_be_hw_params_fixup, + .ops = &apq8096_group_mi2s_be_ops, + .ignore_suspend = 1, + }, + { + .name = LPASS_BE_QUAT_MI2S_RX_2, + .stream_name = "Quaternary MI2S2 Playback", + .cpu_dai_name = "msm-dai-q6-mi2s.4130", + .platform_name = "msm-pcm-routing", + .codec_name = "msm-stub-codec.1", + .codec_dai_name = "msm-stub-rx", + .no_pcm = 1, + .dpcm_playback = 1, + .be_id = MSM_BACKEND_DAI_QUATERNARY_MI2S_RX_2, + .be_hw_params_fixup = msm_group_mi2s_be_hw_params_fixup, + .ops = &apq8096_group_mi2s_be_ops, + .ignore_suspend = 1, + }, + { + .name = LPASS_BE_QUAT_MI2S_RX_3, + .stream_name = "Quaternary MI2S3 Playback", + .cpu_dai_name = "msm-dai-q6-mi2s.4132", + .platform_name = "msm-pcm-routing", + .codec_name = "msm-stub-codec.1", + .codec_dai_name = "msm-stub-rx", + .no_pcm = 1, + .dpcm_playback = 1, + .be_id = MSM_BACKEND_DAI_QUATERNARY_MI2S_RX_3, + .be_hw_params_fixup = msm_group_mi2s_be_hw_params_fixup, + .ops = &apq8096_group_mi2s_be_ops, + .ignore_suspend = 1, + }, + { + .name = LPASS_BE_QUAT_MI2S_RX_4, + .stream_name = "Quaternary MI2S4 Playback", + .cpu_dai_name = "msm-dai-q6-mi2s.4134", + .platform_name = "msm-pcm-routing", + .codec_name = "msm-stub-codec.1", + .codec_dai_name = "msm-stub-rx", + .no_pcm = 1, + .dpcm_playback = 1, + .be_id = MSM_BACKEND_DAI_QUATERNARY_MI2S_RX_4, + .be_hw_params_fixup = msm_group_mi2s_be_hw_params_fixup, + .ops = &apq8096_group_mi2s_be_ops, + .ignore_suspend = 1, } }; diff --git a/sound/soc/msm/qdsp6v2/msm-compress-q6-v2.c b/sound/soc/msm/qdsp6v2/msm-compress-q6-v2.c index b2aa6bd3f504..edbd6b485dac 100644 --- a/sound/soc/msm/qdsp6v2/msm-compress-q6-v2.c +++ b/sound/soc/msm/qdsp6v2/msm-compress-q6-v2.c @@ -946,6 +946,7 @@ static void populate_codec_list(struct msm_compr_audio *prtd) prtd->compr_cap.codecs[14] = SND_AUDIOCODEC_APTX; prtd->compr_cap.codecs[15] = SND_AUDIOCODEC_TRUEHD; prtd->compr_cap.codecs[16] = SND_AUDIOCODEC_IEC61937; + prtd->compr_cap.codecs[17] = SND_AUDIOCODEC_APTXHD; } static int msm_compr_send_media_format_block(struct snd_compr_stream *cstream, @@ -1213,6 +1214,8 @@ static int msm_compr_send_media_format_block(struct snd_compr_stream *cstream, pr_err("%s: CMD IEC61937 Format block failed ret %d\n", __func__, ret); break; + case FORMAT_APTXHD: + pr_debug("SND_AUDIOCODEC_APTXHD\n"); case FORMAT_APTX: pr_debug("SND_AUDIOCODEC_APTX\n"); memset(&aptx_cfg, 0x0, sizeof(struct aptx_dec_bt_addr_cfg)); @@ -2106,6 +2109,12 @@ static int msm_compr_set_params(struct snd_compr_stream *cstream, break; } + case SND_AUDIOCODEC_APTXHD: { + pr_debug("%s: SND_AUDIOCODEC_APTXHD\n", __func__); + prtd->codec = FORMAT_APTXHD; + break; + } + default: pr_err("codec not supported, id =%d\n", params->codec.id); return -EINVAL; @@ -2974,6 +2983,7 @@ static int msm_compr_get_codec_caps(struct snd_compr_stream *cstream, case SND_AUDIOCODEC_TRUEHD: case SND_AUDIOCODEC_IEC61937: case SND_AUDIOCODEC_APTX: + case SND_AUDIOCODEC_APTXHD: break; default: pr_err("%s: Unsupported audio codec %d\n", @@ -3412,6 +3422,7 @@ static int msm_compr_send_dec_params(struct snd_compr_stream *cstream, case FORMAT_TRUEHD: case FORMAT_IEC61937: case FORMAT_APTX: + case FORMAT_APTXHD: pr_debug("%s: no runtime parameters for codec: %d\n", __func__, prtd->codec); break; @@ -3481,6 +3492,7 @@ static int msm_compr_dec_params_put(struct snd_kcontrol *kcontrol, case FORMAT_TRUEHD: case FORMAT_IEC61937: case FORMAT_APTX: + case FORMAT_APTXHD: pr_debug("%s: no runtime parameters for codec: %d\n", __func__, prtd->codec); break; diff --git a/sound/soc/msm/qdsp6v2/msm-dai-q6-v2.c b/sound/soc/msm/qdsp6v2/msm-dai-q6-v2.c index b09f6a1378f0..0c23e1eef483 100644 --- a/sound/soc/msm/qdsp6v2/msm-dai-q6-v2.c +++ b/sound/soc/msm/qdsp6v2/msm-dai-q6-v2.c @@ -124,6 +124,47 @@ struct msm_dai_q6_mi2s_dai_data { struct msm_dai_q6_mi2s_dai_config rx_dai; }; +static DEFINE_MUTEX(group_mi2s_mutex); +static atomic_t group_mi2s_ref[IDX_GROUP_MI2S_MAX]; + +/* cache of mi2s group cfg per parent node */ +static struct afe_param_id_group_device_i2s_cfg_v1 group_mi2s_cfg = { + AFE_API_VERSION_GROUP_DEVICE_I2S_CONFIG, + AFE_GROUP_DEVICE_ID_TERTIARY_MI2S_TX, + AFE_PORT_I2S_QUAD01, + 48000, + { + AFE_PORT_ID_INVALID, + AFE_PORT_ID_TERTIARY_MI2S_TX_1, + AFE_PORT_ID_TERTIARY_MI2S_TX_2, + AFE_PORT_ID_INVALID, + AFE_PORT_ID_INVALID, + AFE_PORT_ID_INVALID, + AFE_PORT_ID_INVALID, + AFE_PORT_ID_INVALID + }, + 32, + 0, +}; + +static struct afe_clk_set group_mi2s_bclk_set = { + AFE_API_VERSION_CLOCK_SET, + Q6AFE_LPASS_CLK_ID_TER_MI2S_IBIT, + Q6AFE_LPASS_IBIT_CLK_3_P072_MHZ, + Q6AFE_LPASS_CLK_ATTRIBUTE_COUPLE_NO, + Q6AFE_LPASS_CLK_ROOT_DEFAULT, + 0, +}; + +static struct afe_clk_set group_mi2s_mclk_set = { + AFE_API_VERSION_CLOCK_SET, + Q6AFE_LPASS_CLK_ID_MCLK_2, + Q6AFE_LPASS_OSR_CLK_3_P072_MHZ, + Q6AFE_LPASS_CLK_ATTRIBUTE_COUPLE_NO, + Q6AFE_LPASS_CLK_ROOT_DEFAULT, + 0, +}; + struct msm_dai_q6_auxpcm_dai_data { /* BITMAP to track Rx and Tx port usage count */ DECLARE_BITMAP(auxpcm_port_status, STATUS_MAX); @@ -147,6 +188,19 @@ struct msm_dai_q6_tdm_dai_data { struct afe_tdm_port_config port_cfg; /* hold tdm config */ }; +struct msm_dai_q6_group_mi2s_dai_data { + DECLARE_BITMAP(status_mask, STATUS_MAX); + u32 rate; + u32 channels; + u32 bit_width; + u32 num_group_ports; + u32 sync_mode; + struct afe_clk_set bclk_set; + struct afe_clk_set mclk_set; + union afe_port_group_mi2s_config group_cfg; + struct afe_i2s_port_config port_cfg; +}; + /* MI2S format field for AFE_PORT_CMD_I2S_CONFIG command * 0: linear PCM * 1: non-linear PCM @@ -455,6 +509,104 @@ int msm_dai_q6_get_port_idx(u16 id) } } +static int msm_dai_q6_get_mi2s_group_idx(u16 id) +{ + switch (id) { + case AFE_GROUP_DEVICE_ID_SECONDARY_MI2S_RX: + case AFE_PORT_ID_SECONDARY_MI2S_RX_1: + case AFE_PORT_ID_SECONDARY_MI2S_RX_2: + case AFE_PORT_ID_SECONDARY_MI2S_RX_3: + case AFE_PORT_ID_SECONDARY_MI2S_RX_4: + return IDX_GROUP_SECONDARY_MI2S_RX; + case AFE_GROUP_DEVICE_ID_SECONDARY_MI2S_TX: + case AFE_PORT_ID_SECONDARY_MI2S_TX_1: + case AFE_PORT_ID_SECONDARY_MI2S_TX_2: + case AFE_PORT_ID_SECONDARY_MI2S_TX_3: + case AFE_PORT_ID_SECONDARY_MI2S_TX_4: + return IDX_GROUP_SECONDARY_MI2S_TX; + case AFE_GROUP_DEVICE_ID_TERTIARY_MI2S_RX: + case AFE_PORT_ID_TERTIARY_MI2S_RX_1: + case AFE_PORT_ID_TERTIARY_MI2S_RX_2: + case AFE_PORT_ID_TERTIARY_MI2S_RX_3: + case AFE_PORT_ID_TERTIARY_MI2S_RX_4: + return IDX_GROUP_TERTIARY_MI2S_RX; + case AFE_GROUP_DEVICE_ID_TERTIARY_MI2S_TX: + case AFE_PORT_ID_TERTIARY_MI2S_TX_1: + case AFE_PORT_ID_TERTIARY_MI2S_TX_2: + case AFE_PORT_ID_TERTIARY_MI2S_TX_3: + case AFE_PORT_ID_TERTIARY_MI2S_TX_4: + return IDX_GROUP_TERTIARY_MI2S_TX; + case AFE_GROUP_DEVICE_ID_QUATERNARY_MI2S_RX: + case AFE_PORT_ID_QUATERNARY_MI2S_RX_1: + case AFE_PORT_ID_QUATERNARY_MI2S_RX_2: + case AFE_PORT_ID_QUATERNARY_MI2S_RX_3: + case AFE_PORT_ID_QUATERNARY_MI2S_RX_4: + return IDX_GROUP_QUATERNARY_MI2S_RX; + case AFE_GROUP_DEVICE_ID_QUATERNARY_MI2S_TX: + case AFE_PORT_ID_QUATERNARY_MI2S_TX_1: + case AFE_PORT_ID_QUATERNARY_MI2S_TX_2: + case AFE_PORT_ID_QUATERNARY_MI2S_TX_3: + case AFE_PORT_ID_QUATERNARY_MI2S_TX_4: + return IDX_GROUP_QUATERNARY_MI2S_TX; + default: return -EINVAL; + } +} + +static int msm_dai_q6_get_mi2s_port_idx(u16 id) +{ + switch (id) { + case AFE_PORT_ID_SECONDARY_MI2S_RX_1: + return IDX_SECONDARY_MI2S_RX_1; + case AFE_PORT_ID_SECONDARY_MI2S_RX_2: + return IDX_SECONDARY_MI2S_RX_2; + case AFE_PORT_ID_SECONDARY_MI2S_RX_3: + return IDX_SECONDARY_MI2S_RX_3; + case AFE_PORT_ID_SECONDARY_MI2S_RX_4: + return IDX_SECONDARY_MI2S_RX_4; + case AFE_PORT_ID_SECONDARY_MI2S_TX_1: + return IDX_SECONDARY_MI2S_TX_1; + case AFE_PORT_ID_SECONDARY_MI2S_TX_2: + return IDX_SECONDARY_MI2S_TX_2; + case AFE_PORT_ID_SECONDARY_MI2S_TX_3: + return IDX_SECONDARY_MI2S_TX_3; + case AFE_PORT_ID_SECONDARY_MI2S_TX_4: + return IDX_SECONDARY_MI2S_TX_4; + case AFE_PORT_ID_TERTIARY_MI2S_RX_1: + return IDX_TERTIARY_MI2S_RX_1; + case AFE_PORT_ID_TERTIARY_MI2S_RX_2: + return IDX_TERTIARY_MI2S_RX_2; + case AFE_PORT_ID_TERTIARY_MI2S_RX_3: + return IDX_TERTIARY_MI2S_RX_3; + case AFE_PORT_ID_TERTIARY_MI2S_RX_4: + return IDX_TERTIARY_MI2S_RX_4; + case AFE_PORT_ID_TERTIARY_MI2S_TX_1: + return IDX_TERTIARY_MI2S_TX_1; + case AFE_PORT_ID_TERTIARY_MI2S_TX_2: + return IDX_TERTIARY_MI2S_TX_2; + case AFE_PORT_ID_TERTIARY_MI2S_TX_3: + return IDX_TERTIARY_MI2S_TX_3; + case AFE_PORT_ID_TERTIARY_MI2S_TX_4: + return IDX_TERTIARY_MI2S_TX_4; + case AFE_PORT_ID_QUATERNARY_MI2S_RX_1: + return IDX_QUATERNARY_MI2S_RX_1; + case AFE_PORT_ID_QUATERNARY_MI2S_RX_2: + return IDX_QUATERNARY_MI2S_RX_2; + case AFE_PORT_ID_QUATERNARY_MI2S_RX_3: + return IDX_QUATERNARY_MI2S_RX_3; + case AFE_PORT_ID_QUATERNARY_MI2S_RX_4: + return IDX_QUATERNARY_MI2S_RX_4; + case AFE_PORT_ID_QUATERNARY_MI2S_TX_1: + return IDX_QUATERNARY_MI2S_TX_1; + case AFE_PORT_ID_QUATERNARY_MI2S_TX_2: + return IDX_QUATERNARY_MI2S_TX_2; + case AFE_PORT_ID_QUATERNARY_MI2S_TX_3: + return IDX_QUATERNARY_MI2S_TX_3; + case AFE_PORT_ID_QUATERNARY_MI2S_TX_4: + return IDX_QUATERNARY_MI2S_TX_4; + default: return -EINVAL; + } +} + static u16 msm_dai_q6_max_num_slot(int frame_rate) { /* Max num of slots is bits per frame divided @@ -531,7 +683,7 @@ static int msm_dai_q6_auxpcm_hw_params( int rc = 0, slot_mapping_copy_len = 0; if (params_channels(params) != 1 || (params_rate(params) != 8000 && - params_rate(params) != 16000)) { + params_rate(params) != 16000)) { dev_err(dai->dev, "%s: invalid param chan %d rate %d\n", __func__, params_channels(params), params_rate(params)); return -EINVAL; @@ -540,7 +692,7 @@ static int msm_dai_q6_auxpcm_hw_params( mutex_lock(&aux_dai_data->rlock); if (test_bit(STATUS_TX_PORT, aux_dai_data->auxpcm_port_status) || - test_bit(STATUS_RX_PORT, aux_dai_data->auxpcm_port_status)) { + test_bit(STATUS_RX_PORT, aux_dai_data->auxpcm_port_status)) { /* AUXPCM DAI in use */ if (dai_data->rate != params_rate(params)) { dev_err(dai->dev, "%s: rate mismatch of running DAI\n", @@ -569,7 +721,7 @@ static int msm_dai_q6_auxpcm_hw_params( dai_data->port_config.pcm.num_channels = dai_data->channels; dai_data->port_config.pcm.bit_width = 16; if (ARRAY_SIZE(dai_data->port_config.pcm.slot_number_mapping) <= - auxpcm_pdata->mode_8k.num_slots) + auxpcm_pdata->mode_8k.num_slots) slot_mapping_copy_len = ARRAY_SIZE( dai_data->port_config.pcm.slot_number_mapping) @@ -580,8 +732,8 @@ static int msm_dai_q6_auxpcm_hw_params( if (auxpcm_pdata->mode_8k.slot_mapping) { memcpy(dai_data->port_config.pcm.slot_number_mapping, - auxpcm_pdata->mode_8k.slot_mapping, - slot_mapping_copy_len); + auxpcm_pdata->mode_8k.slot_mapping, + slot_mapping_copy_len); } else { dev_err(dai->dev, "%s 8khz slot mapping is NULL\n", __func__); @@ -605,7 +757,7 @@ static int msm_dai_q6_auxpcm_hw_params( dai_data->port_config.pcm.num_channels = dai_data->channels; dai_data->port_config.pcm.bit_width = 16; if (ARRAY_SIZE(dai_data->port_config.pcm.slot_number_mapping) <= - auxpcm_pdata->mode_16k.num_slots) + auxpcm_pdata->mode_16k.num_slots) slot_mapping_copy_len = ARRAY_SIZE( dai_data->port_config.pcm.slot_number_mapping) @@ -616,8 +768,8 @@ static int msm_dai_q6_auxpcm_hw_params( if (auxpcm_pdata->mode_16k.slot_mapping) { memcpy(dai_data->port_config.pcm.slot_number_mapping, - auxpcm_pdata->mode_16k.slot_mapping, - slot_mapping_copy_len); + auxpcm_pdata->mode_16k.slot_mapping, + slot_mapping_copy_len); } else { dev_err(dai->dev, "%s 16khz slot mapping is NULL\n", __func__); @@ -4322,6 +4474,908 @@ static struct snd_soc_dai_driver msm_dai_q6_mi2s_dai[] = { }, }; +static int msm_dai_q6_group_mi2s_set_clk_param(u32 group_id, + struct afe_clk_set *mclk_set, + struct afe_clk_set *bclk_set, + u32 sync_mode) +{ + switch (group_id) { + case AFE_GROUP_DEVICE_ID_SECONDARY_MI2S_RX: + case AFE_GROUP_DEVICE_ID_SECONDARY_MI2S_TX: + if (sync_mode) + bclk_set->clk_id = Q6AFE_LPASS_CLK_ID_SEC_MI2S_IBIT; + else + bclk_set->clk_id = Q6AFE_LPASS_CLK_ID_SEC_MI2S_EBIT; + mclk_set->clk_id = Q6AFE_LPASS_CLK_ID_MCLK_1; + break; + case AFE_GROUP_DEVICE_ID_TERTIARY_MI2S_RX: + case AFE_GROUP_DEVICE_ID_TERTIARY_MI2S_TX: + if (sync_mode) + bclk_set->clk_id = Q6AFE_LPASS_CLK_ID_TER_MI2S_IBIT; + else + bclk_set->clk_id = Q6AFE_LPASS_CLK_ID_TER_MI2S_EBIT; + mclk_set->clk_id = Q6AFE_LPASS_CLK_ID_MCLK_2; + break; + case AFE_GROUP_DEVICE_ID_QUATERNARY_MI2S_RX: + case AFE_GROUP_DEVICE_ID_QUATERNARY_MI2S_TX: + if (sync_mode) + bclk_set->clk_id = Q6AFE_LPASS_CLK_ID_QUAD_MI2S_IBIT; + else + bclk_set->clk_id = Q6AFE_LPASS_CLK_ID_QUAD_MI2S_EBIT; + mclk_set->clk_id = Q6AFE_LPASS_CLK_ID_MCLK_3; + break; + default: + return -EINVAL; + } + return 0; +} + +static int msm_dai_q6_group_mi2s_set_clk( + struct msm_dai_q6_group_mi2s_dai_data *dai_data, + u16 port_id, bool enable) +{ + int rc = 0; + + dai_data->bclk_set.enable = enable; + rc = afe_set_lpass_clock_v2(port_id, + &dai_data->bclk_set); + if (rc < 0) + pr_err("%s: afe lpass bclk failed, err: %d\n", + __func__, rc); + + /*non zero mclk freq value means to enable mclk for mi2s intf*/ + if (dai_data->mclk_set.clk_freq_in_hz != 0) { + dai_data->mclk_set.enable = enable; + rc = afe_set_lpass_clock_v2(port_id, + &dai_data->mclk_set); + if (rc < 0) + pr_err("%s: afe lpass mclk failed, err: %d\n", + __func__, rc); + } + return rc; +} + +static int msm_dai_q6_dai_group_mi2s_probe(struct snd_soc_dai *dai) +{ + int rc = 0; + + msm_dai_q6_set_dai_id(dai); + rc = msm_dai_q6_dai_add_route(dai); + return rc; +} + +static int msm_dai_q6_dai_group_mi2s_remove(struct snd_soc_dai *dai) +{ + int rc = 0; + struct msm_dai_q6_group_mi2s_dai_data *dai_data = + dev_get_drvdata(dai->dev); + u16 group_id = dai_data->group_cfg.i2s_cfg.group_id; + int group_idx = 0; + atomic_t *group_ref = NULL; + + dev_dbg(dai->dev, "%s rc %d", __func__, rc); + + group_idx = msm_dai_q6_get_mi2s_group_idx(dai->id); + if (group_idx < 0 || group_idx > IDX_GROUP_MI2S_MAX) { + dev_err(dai->dev, "%s: port id 0x%x not supported\n", + __func__, dai->id); + return -EINVAL; + } + + group_ref = &group_mi2s_ref[group_idx]; + + /* if AFE port is still up, close it */ + if (test_bit(STATUS_PORT_STARTED, dai_data->status_mask)) { + rc = afe_close(dai->id); /* can block */ + if (IS_ERR_VALUE(rc)) { + dev_err(dai->dev, "%s: fail to close Group MI2S port 0x%x\n", + __func__, dai->id); + } + atomic_dec(group_ref); + clear_bit(STATUS_PORT_STARTED, dai_data->status_mask); + + if (atomic_read(group_ref) == 0) { + rc = afe_port_group_mi2s_enable(group_id, NULL, false); + if (IS_ERR_VALUE(rc)) { + dev_err(dai->dev, "%s: fail to disable Group MI2S group 0x%x\n", + __func__, group_id); + } + rc = msm_dai_q6_group_mi2s_set_clk(dai_data, + dai->id, false); + if (IS_ERR_VALUE(rc)) { + dev_err(dai->dev, "%s: fail to disable AFE clk 0x%x\n", + __func__, dai->id); + } + } + } + return 0; +} + +static int msm_dai_q6_group_mi2s_set_channel_map(struct snd_soc_dai *dai, + unsigned int tx_num, unsigned int *tx_slot, + unsigned int rx_num, unsigned int *rx_slot) +{ + int rc = 0; + struct msm_dai_q6_group_mi2s_dai_data *dai_data = + dev_get_drvdata(dai->dev); + int i = 0; + + switch (dai->id) { + case AFE_PORT_ID_SECONDARY_MI2S_RX_1: + case AFE_PORT_ID_SECONDARY_MI2S_RX_2: + case AFE_PORT_ID_SECONDARY_MI2S_RX_3: + case AFE_PORT_ID_SECONDARY_MI2S_RX_4: + case AFE_PORT_ID_TERTIARY_MI2S_RX_1: + case AFE_PORT_ID_TERTIARY_MI2S_RX_2: + case AFE_PORT_ID_TERTIARY_MI2S_RX_3: + case AFE_PORT_ID_TERTIARY_MI2S_RX_4: + case AFE_PORT_ID_QUATERNARY_MI2S_RX_1: + case AFE_PORT_ID_QUATERNARY_MI2S_RX_2: + case AFE_PORT_ID_QUATERNARY_MI2S_RX_3: + case AFE_PORT_ID_QUATERNARY_MI2S_RX_4: + if (!rx_slot) { + dev_err(dai->dev, "%s: rx slot not found\n", + __func__); + return -EINVAL; + } + for (i = 0; i < rx_num; i++) + dai_data->port_cfg.slot_mapping.offset[i] = rx_slot[i]; + for (i = rx_num; i < AFE_PORT_MAX_AUDIO_CHAN_CNT; i++) + dai_data->port_cfg.slot_mapping.offset[i] = + AFE_SLOT_MAPPING_OFFSET_INVALID; + dai_data->port_cfg.slot_mapping.num_channel = rx_num; + break; + case AFE_PORT_ID_SECONDARY_MI2S_TX_1: + case AFE_PORT_ID_SECONDARY_MI2S_TX_2: + case AFE_PORT_ID_SECONDARY_MI2S_TX_3: + case AFE_PORT_ID_SECONDARY_MI2S_TX_4: + case AFE_PORT_ID_TERTIARY_MI2S_TX_1: + case AFE_PORT_ID_TERTIARY_MI2S_TX_2: + case AFE_PORT_ID_TERTIARY_MI2S_TX_3: + case AFE_PORT_ID_TERTIARY_MI2S_TX_4: + case AFE_PORT_ID_QUATERNARY_MI2S_TX_1: + case AFE_PORT_ID_QUATERNARY_MI2S_TX_2: + case AFE_PORT_ID_QUATERNARY_MI2S_TX_3: + case AFE_PORT_ID_QUATERNARY_MI2S_TX_4: + if (!tx_slot) { + dev_err(dai->dev, "%s: tx slot not found\n", + __func__); + return -EINVAL; + } + for (i = 0; i < tx_num; i++) + dai_data->port_cfg.slot_mapping.offset[i] = tx_slot[i]; + for (i = tx_num; i < AFE_PORT_MAX_AUDIO_CHAN_CNT; i++) + dai_data->port_cfg.slot_mapping.offset[i] = + AFE_SLOT_MAPPING_OFFSET_INVALID; + + dai_data->port_cfg.slot_mapping.num_channel = tx_num; + break; + default: + dev_err(dai->dev, "%s: invalid dai id 0x%x\n", + __func__, dai->id); + return -EINVAL; + } + + return rc; +} + +static int msm_dai_q6_group_mi2s_hw_params(struct snd_pcm_substream *substream, + struct snd_pcm_hw_params *params, + struct snd_soc_dai *dai) +{ + struct msm_dai_q6_group_mi2s_dai_data *dai_data = + dev_get_drvdata(dai->dev); + struct afe_param_id_group_device_i2s_cfg_v1 *group_mi2s_cfg = + &dai_data->group_cfg.i2s_cfg; + struct afe_param_id_i2s_cfg *dev_i2s_cfg = + &dai_data->port_cfg.i2s_cfg; + struct afe_param_id_slot_mapping_cfg *slot_mapping = + &dai_data->port_cfg.slot_mapping; + + /* update group_mi2s group config param */ + dai_data->channels = params_channels(params); + dai_data->rate = params_rate(params); + + switch (params_format(params)) { + case SNDRV_PCM_FORMAT_S16_LE: + case SNDRV_PCM_FORMAT_SPECIAL: + dai_data->bit_width = 16; + break; + case SNDRV_PCM_FORMAT_S24_LE: + case SNDRV_PCM_FORMAT_S24_3LE: + dai_data->bit_width = 24; + break; + default: + pr_err("%s: format %d\n", + __func__, params_format(params)); + return -EINVAL; + } + + /* update group_mi2s config param */ + group_mi2s_cfg->sample_rate = dai_data->rate; + group_mi2s_cfg->bit_width = dai_data->bit_width; + pr_debug("%s: Group MI2S GROUP 0x%x:\n" + "channel_mode = %d sample_rate = %d bit_width = %d\n", + __func__, group_mi2s_cfg->group_id, + group_mi2s_cfg->channel_mode, + group_mi2s_cfg->sample_rate, + group_mi2s_cfg->bit_width); + pr_debug("%s: Group MI2S GROUP 0x%x:\n" + "port_id[0]=0x%x port_id[1]=0x%x port_id[2]=0x%x port_id[3]=0x%x\n" + "port_id[4]=0x%x port_id[5]=0x%x port_id[6]=0x%x port_id[7]=0x%x\n", + __func__, group_mi2s_cfg->group_id, + group_mi2s_cfg->port_id[0], + group_mi2s_cfg->port_id[1], + group_mi2s_cfg->port_id[2], + group_mi2s_cfg->port_id[3], + group_mi2s_cfg->port_id[4], + group_mi2s_cfg->port_id[5], + group_mi2s_cfg->port_id[6], + group_mi2s_cfg->port_id[7]); + /*i2s port cfg*/ + dev_i2s_cfg->i2s_cfg_minor_version = + AFE_API_VERSION_I2S_CONFIG; + dev_i2s_cfg->bit_width = group_mi2s_cfg->bit_width; + dev_i2s_cfg->mono_stereo = AFE_PORT_I2S_STEREO; + dev_i2s_cfg->sample_rate = group_mi2s_cfg->sample_rate; + dev_i2s_cfg->data_format = AFE_LINEAR_PCM_DATA; + dev_i2s_cfg->ws_src = dai_data->sync_mode; + pr_debug("%s: MI2S port:\n" + "dai id %d dai_data->channels = %d\n" + "sample_rate = %u i2s_cfg_minor_version = 0x%x\n" + "bit_width = %hu channel_mode = 0x%x mono_stereo = %#x\n" + "ws_src = 0x%x sample_rate = %u data_format = 0x%x\n" + "reserved = %u\n", __func__, dai->id, dai_data->channels, + dai_data->rate, dev_i2s_cfg->i2s_cfg_minor_version, + dev_i2s_cfg->bit_width, dev_i2s_cfg->channel_mode, + dev_i2s_cfg->mono_stereo, dev_i2s_cfg->ws_src, + dev_i2s_cfg->sample_rate, dev_i2s_cfg->data_format, + dev_i2s_cfg->reserved); + + /*slot mapping cfg*/ + slot_mapping->minor_version = + AFE_API_VERSION_SLOT_MAPPING_CONFIG; + slot_mapping->bitwidth = group_mi2s_cfg->bit_width; + slot_mapping->data_align_type = + AFE_SLOT_MAPPING_DATA_ALIGN_MSB; + pr_debug("%s: Group MI2S port 0x%x SLOT MAPPING:\n" + "num_channel=%d bitwidth=%d data_align=0x%x\n", + __func__, dai->id, + slot_mapping->num_channel, + slot_mapping->bitwidth, + slot_mapping->data_align_type); + pr_debug("%s: Group MI2S port 0x%x SLOT MAPPING:\n" + "offset[0]=0x%x offset[1]=0x%x offset[2]=0x%x offset[3]=0x%x\n" + "offset[4]=0x%x offset[5]=0x%x offset[6]=0x%x offset[7]=0x%x\n", + __func__, dai->id, + slot_mapping->offset[0], + slot_mapping->offset[1], + slot_mapping->offset[2], + slot_mapping->offset[3], + slot_mapping->offset[4], + slot_mapping->offset[5], + slot_mapping->offset[6], + slot_mapping->offset[7]); + + return 0; +} + +static int msm_dai_q6_group_mi2s_prepare(struct snd_pcm_substream *substream, + struct snd_soc_dai *dai) +{ + int rc = 0; + struct msm_dai_q6_group_mi2s_dai_data *dai_data = + dev_get_drvdata(dai->dev); + u16 group_id = dai_data->group_cfg.i2s_cfg.group_id; + int group_idx = 0; + atomic_t *group_ref = NULL; + + group_idx = msm_dai_q6_get_mi2s_group_idx(dai->id); + if (group_idx < 0 || group_idx > IDX_GROUP_MI2S_MAX) { + dev_err(dai->dev, "%s port id 0x%x not supported\n", + __func__, dai->id); + return -EINVAL; + } + + mutex_lock(&group_mi2s_mutex); + + group_ref = &group_mi2s_ref[group_idx]; + + if (!test_bit(STATUS_PORT_STARTED, dai_data->status_mask)) { + /* PORT START should be set if prepare called + * in active state. + */ + if (atomic_read(group_ref) == 0) { + /* + * TX and RX share the same clk. + * AFE clk is enabled per group to simplify the logic. + * DSP will monitor the clk count. + */ + rc = msm_dai_q6_group_mi2s_set_clk(dai_data, + dai->id, true); + if (IS_ERR_VALUE(rc)) { + dev_err(dai->dev, "%s: fail to enable AFE clk 0x%x\n", + __func__, dai->id); + goto rtn; + } + + /* + * if only one port, don't do group enable as there + * is no group need for only one port + */ + if (dai_data->num_group_ports > 1) { + rc = afe_port_group_mi2s_enable(group_id, + &dai_data->group_cfg, true); + if (IS_ERR_VALUE(rc)) { + dev_err(dai->dev, + "%s: fail to enable AFE group 0x%x\n", + __func__, group_id); + goto rtn; + } + } + } + + rc = afe_i2s_port_start(dai->id, &dai_data->port_cfg, + dai_data->rate, dai_data->num_group_ports); + if (IS_ERR_VALUE(rc)) { + if (atomic_read(group_ref) == 0) { + afe_port_group_mi2s_enable(group_id, + NULL, false); + msm_dai_q6_group_mi2s_set_clk(dai_data, + dai->id, false); + } + dev_err(dai->dev, "%s: fail to open AFE port 0x%x\n", + __func__, dai->id); + } else { + set_bit(STATUS_PORT_STARTED, + dai_data->status_mask); + atomic_inc(group_ref); + } + } + +rtn: + mutex_unlock(&group_mi2s_mutex); + return rc; +} + +static void msm_dai_q6_group_mi2s_shutdown(struct snd_pcm_substream *substream, + struct snd_soc_dai *dai) +{ + int rc = 0; + struct msm_dai_q6_group_mi2s_dai_data *dai_data = + dev_get_drvdata(dai->dev); + u16 group_id = dai_data->group_cfg.i2s_cfg.group_id; + int group_idx = 0; + atomic_t *group_ref = NULL; + + group_idx = msm_dai_q6_get_mi2s_group_idx(dai->id); + if (group_idx < 0 || group_idx > IDX_GROUP_MI2S_MAX) { + dev_err(dai->dev, "%s port id 0x%x not supported\n", + __func__, dai->id); + return; + } + + mutex_lock(&group_mi2s_mutex); + group_ref = &group_mi2s_ref[group_idx]; + + if (test_bit(STATUS_PORT_STARTED, dai_data->status_mask)) { + rc = afe_close(dai->id); + if (IS_ERR_VALUE(rc)) { + dev_err(dai->dev, "%s: fail to close AFE port 0x%x\n", + __func__, dai->id); + } + atomic_dec(group_ref); + clear_bit(STATUS_PORT_STARTED, + dai_data->status_mask); + + if (atomic_read(group_ref) == 0) { + rc = afe_port_group_mi2s_enable(group_id, + NULL, false); + if (IS_ERR_VALUE(rc)) { + dev_err(dai->dev, "%s: fail to disable AFE group 0x%x\n", + __func__, group_id); + } + rc = msm_dai_q6_group_mi2s_set_clk(dai_data, + dai->id, false); + if (IS_ERR_VALUE(rc)) { + dev_err(dai->dev, "%s: fail to disable AFE clk 0x%x\n", + __func__, dai->id); + } + } + } + + mutex_unlock(&group_mi2s_mutex); +} + +static struct snd_soc_dai_ops msm_dai_q6_group_mi2s_ops = { + .prepare = msm_dai_q6_group_mi2s_prepare, + .hw_params = msm_dai_q6_group_mi2s_hw_params, + .set_channel_map = msm_dai_q6_group_mi2s_set_channel_map, + .shutdown = msm_dai_q6_group_mi2s_shutdown, +}; + +static struct snd_soc_dai_driver msm_dai_q6_group_mi2s_dai[] = { + { + .playback = { + .stream_name = "Secondary MI2S1 Playback", + .aif_name = "SEC_MI2S_RX_1", + .rates = SNDRV_PCM_RATE_8000 | SNDRV_PCM_RATE_11025 | + SNDRV_PCM_RATE_16000 | SNDRV_PCM_RATE_22050 | + SNDRV_PCM_RATE_32000 | SNDRV_PCM_RATE_44100 | + SNDRV_PCM_RATE_48000 | SNDRV_PCM_RATE_96000 | + SNDRV_PCM_RATE_192000, + .formats = SNDRV_PCM_FMTBIT_S16_LE | + SNDRV_PCM_FMTBIT_S24_LE | + SNDRV_PCM_FMTBIT_S24_3LE, + .rate_min = 8000, + .rate_max = 192000, + }, + .ops = &msm_dai_q6_group_mi2s_ops, + .id = AFE_PORT_ID_SECONDARY_MI2S_RX_1, + .probe = msm_dai_q6_dai_group_mi2s_probe, + .remove = msm_dai_q6_dai_group_mi2s_remove, + }, + { + .playback = { + .stream_name = "Secondary MI2S2 Playback", + .aif_name = "SEC_MI2S_RX_2", + .rates = SNDRV_PCM_RATE_8000 | SNDRV_PCM_RATE_11025 | + SNDRV_PCM_RATE_16000 | SNDRV_PCM_RATE_22050 | + SNDRV_PCM_RATE_32000 | SNDRV_PCM_RATE_44100 | + SNDRV_PCM_RATE_48000 | SNDRV_PCM_RATE_96000 | + SNDRV_PCM_RATE_192000, + .formats = SNDRV_PCM_FMTBIT_S16_LE | + SNDRV_PCM_FMTBIT_S24_LE | + SNDRV_PCM_FMTBIT_S24_3LE, + .rate_min = 8000, + .rate_max = 192000, + }, + .ops = &msm_dai_q6_group_mi2s_ops, + .id = AFE_PORT_ID_SECONDARY_MI2S_RX_2, + .probe = msm_dai_q6_dai_group_mi2s_probe, + .remove = msm_dai_q6_dai_group_mi2s_remove, + }, + { + .playback = { + .stream_name = "Secondary MI2S3 Playback", + .aif_name = "SEC_MI2S_RX_3", + .rates = SNDRV_PCM_RATE_8000 | SNDRV_PCM_RATE_11025 | + SNDRV_PCM_RATE_16000 | SNDRV_PCM_RATE_22050 | + SNDRV_PCM_RATE_32000 | SNDRV_PCM_RATE_44100 | + SNDRV_PCM_RATE_48000 | SNDRV_PCM_RATE_96000 | + SNDRV_PCM_RATE_192000, + .formats = SNDRV_PCM_FMTBIT_S16_LE | + SNDRV_PCM_FMTBIT_S24_LE | + SNDRV_PCM_FMTBIT_S24_3LE, + .rate_min = 8000, + .rate_max = 192000, + }, + .ops = &msm_dai_q6_group_mi2s_ops, + .id = AFE_PORT_ID_SECONDARY_MI2S_RX_3, + .probe = msm_dai_q6_dai_group_mi2s_probe, + .remove = msm_dai_q6_dai_group_mi2s_remove, + }, + { + .playback = { + .stream_name = "Secondary MI2S4 Playback", + .aif_name = "SEC_MI2S_RX_4", + .rates = SNDRV_PCM_RATE_8000 | SNDRV_PCM_RATE_11025 | + SNDRV_PCM_RATE_16000 | SNDRV_PCM_RATE_22050 | + SNDRV_PCM_RATE_32000 | SNDRV_PCM_RATE_44100 | + SNDRV_PCM_RATE_48000 | SNDRV_PCM_RATE_96000 | + SNDRV_PCM_RATE_192000, + .formats = SNDRV_PCM_FMTBIT_S16_LE | + SNDRV_PCM_FMTBIT_S24_LE | + SNDRV_PCM_FMTBIT_S24_3LE, + .rate_min = 8000, + .rate_max = 192000, + }, + .ops = &msm_dai_q6_group_mi2s_ops, + .id = AFE_PORT_ID_SECONDARY_MI2S_RX_4, + .probe = msm_dai_q6_dai_group_mi2s_probe, + .remove = msm_dai_q6_dai_group_mi2s_remove, + }, + { + .capture = { + .stream_name = "Secondary MI2S1 Capture", + .aif_name = "SEC_MI2S_TX_1", + .rates = SNDRV_PCM_RATE_8000 | SNDRV_PCM_RATE_11025 | + SNDRV_PCM_RATE_16000 | SNDRV_PCM_RATE_22050 | + SNDRV_PCM_RATE_32000 | SNDRV_PCM_RATE_44100 | + SNDRV_PCM_RATE_48000 | SNDRV_PCM_RATE_96000 | + SNDRV_PCM_RATE_192000, + .formats = SNDRV_PCM_FMTBIT_S16_LE | + SNDRV_PCM_FMTBIT_S24_LE | + SNDRV_PCM_FMTBIT_S24_3LE, + .rate_min = 8000, + .rate_max = 192000, + }, + .ops = &msm_dai_q6_group_mi2s_ops, + .id = AFE_PORT_ID_SECONDARY_MI2S_TX_1, + .probe = msm_dai_q6_dai_group_mi2s_probe, + .remove = msm_dai_q6_dai_group_mi2s_remove, + }, + { + .capture = { + .stream_name = "Secondary MI2S2 Capture", + .aif_name = "SEC_MI2S_TX_2", + .rates = SNDRV_PCM_RATE_8000 | SNDRV_PCM_RATE_11025 | + SNDRV_PCM_RATE_16000 | SNDRV_PCM_RATE_22050 | + SNDRV_PCM_RATE_32000 | SNDRV_PCM_RATE_44100 | + SNDRV_PCM_RATE_48000 | SNDRV_PCM_RATE_96000 | + SNDRV_PCM_RATE_192000, + .formats = SNDRV_PCM_FMTBIT_S16_LE | + SNDRV_PCM_FMTBIT_S24_LE | + SNDRV_PCM_FMTBIT_S24_3LE, + .rate_min = 8000, + .rate_max = 192000, + }, + .ops = &msm_dai_q6_group_mi2s_ops, + .id = AFE_PORT_ID_SECONDARY_MI2S_TX_2, + .probe = msm_dai_q6_dai_group_mi2s_probe, + .remove = msm_dai_q6_dai_group_mi2s_remove, + }, + { + .capture = { + .stream_name = "Secondary MI2S3 Capture", + .aif_name = "SEC_MI2S_TX_3", + .rates = SNDRV_PCM_RATE_8000 | SNDRV_PCM_RATE_11025 | + SNDRV_PCM_RATE_16000 | SNDRV_PCM_RATE_22050 | + SNDRV_PCM_RATE_32000 | SNDRV_PCM_RATE_44100 | + SNDRV_PCM_RATE_48000 | SNDRV_PCM_RATE_96000 | + SNDRV_PCM_RATE_192000, + .formats = SNDRV_PCM_FMTBIT_S16_LE | + SNDRV_PCM_FMTBIT_S24_LE | + SNDRV_PCM_FMTBIT_S24_3LE, + .rate_min = 8000, + .rate_max = 192000, + }, + .ops = &msm_dai_q6_group_mi2s_ops, + .id = AFE_PORT_ID_SECONDARY_MI2S_TX_3, + .probe = msm_dai_q6_dai_group_mi2s_probe, + .remove = msm_dai_q6_dai_group_mi2s_remove, + }, + { + .capture = { + .stream_name = "Secondary MI2S4 Capture", + .aif_name = "SEC_MI2S_TX_4", + .rates = SNDRV_PCM_RATE_8000 | SNDRV_PCM_RATE_11025 | + SNDRV_PCM_RATE_16000 | SNDRV_PCM_RATE_22050 | + SNDRV_PCM_RATE_32000 | SNDRV_PCM_RATE_44100 | + SNDRV_PCM_RATE_48000 | SNDRV_PCM_RATE_96000 | + SNDRV_PCM_RATE_192000, + .formats = SNDRV_PCM_FMTBIT_S16_LE | + SNDRV_PCM_FMTBIT_S24_LE | + SNDRV_PCM_FMTBIT_S24_3LE, + .rate_min = 8000, + .rate_max = 192000, + }, + .ops = &msm_dai_q6_group_mi2s_ops, + .id = AFE_PORT_ID_SECONDARY_MI2S_TX_4, + .probe = msm_dai_q6_dai_group_mi2s_probe, + .remove = msm_dai_q6_dai_group_mi2s_remove, + }, + { + .playback = { + .stream_name = "Tertiary MI2S1 Playback", + .aif_name = "TERT_MI2S_RX_1", + .rates = SNDRV_PCM_RATE_8000 | SNDRV_PCM_RATE_11025 | + SNDRV_PCM_RATE_16000 | SNDRV_PCM_RATE_22050 | + SNDRV_PCM_RATE_32000 | SNDRV_PCM_RATE_44100 | + SNDRV_PCM_RATE_48000 | SNDRV_PCM_RATE_96000 | + SNDRV_PCM_RATE_192000, + .formats = SNDRV_PCM_FMTBIT_S16_LE | + SNDRV_PCM_FMTBIT_S24_LE | + SNDRV_PCM_FMTBIT_S24_3LE, + .rate_min = 8000, + .rate_max = 192000, + }, + .ops = &msm_dai_q6_group_mi2s_ops, + .id = AFE_PORT_ID_TERTIARY_MI2S_RX_1, + .probe = msm_dai_q6_dai_group_mi2s_probe, + .remove = msm_dai_q6_dai_group_mi2s_remove, + }, + { + .playback = { + .stream_name = "Tertiary MI2S2 Playback", + .aif_name = "TERT_MI2S_RX_2", + .rates = SNDRV_PCM_RATE_8000 | SNDRV_PCM_RATE_11025 | + SNDRV_PCM_RATE_16000 | SNDRV_PCM_RATE_22050 | + SNDRV_PCM_RATE_32000 | SNDRV_PCM_RATE_44100 | + SNDRV_PCM_RATE_48000 | SNDRV_PCM_RATE_96000 | + SNDRV_PCM_RATE_192000, + .formats = SNDRV_PCM_FMTBIT_S16_LE | + SNDRV_PCM_FMTBIT_S24_LE | + SNDRV_PCM_FMTBIT_S24_3LE, + .rate_min = 8000, + .rate_max = 192000, + }, + .ops = &msm_dai_q6_group_mi2s_ops, + .id = AFE_PORT_ID_TERTIARY_MI2S_RX_2, + .probe = msm_dai_q6_dai_group_mi2s_probe, + .remove = msm_dai_q6_dai_group_mi2s_remove, + }, + { + .playback = { + .stream_name = "Tertiary MI2S3 Playback", + .aif_name = "TERT_MI2S_RX_3", + .rates = SNDRV_PCM_RATE_8000 | SNDRV_PCM_RATE_11025 | + SNDRV_PCM_RATE_16000 | SNDRV_PCM_RATE_22050 | + SNDRV_PCM_RATE_32000 | SNDRV_PCM_RATE_44100 | + SNDRV_PCM_RATE_48000 | SNDRV_PCM_RATE_96000 | + SNDRV_PCM_RATE_192000, + .formats = SNDRV_PCM_FMTBIT_S16_LE | + SNDRV_PCM_FMTBIT_S24_LE | + SNDRV_PCM_FMTBIT_S24_3LE, + .rate_min = 8000, + .rate_max = 192000, + }, + .ops = &msm_dai_q6_group_mi2s_ops, + .id = AFE_PORT_ID_TERTIARY_MI2S_RX_3, + .probe = msm_dai_q6_dai_group_mi2s_probe, + .remove = msm_dai_q6_dai_group_mi2s_remove, + }, + { + .playback = { + .stream_name = "Tertiary MI2S4 Playback", + .aif_name = "TERT_MI2S_RX_4", + .rates = SNDRV_PCM_RATE_8000 | SNDRV_PCM_RATE_11025 | + SNDRV_PCM_RATE_16000 | SNDRV_PCM_RATE_22050 | + SNDRV_PCM_RATE_32000 | SNDRV_PCM_RATE_44100 | + SNDRV_PCM_RATE_48000 | SNDRV_PCM_RATE_96000 | + SNDRV_PCM_RATE_192000, + .formats = SNDRV_PCM_FMTBIT_S16_LE | + SNDRV_PCM_FMTBIT_S24_LE | + SNDRV_PCM_FMTBIT_S24_3LE, + .rate_min = 8000, + .rate_max = 192000, + }, + .ops = &msm_dai_q6_group_mi2s_ops, + .id = AFE_PORT_ID_TERTIARY_MI2S_RX_4, + .probe = msm_dai_q6_dai_group_mi2s_probe, + .remove = msm_dai_q6_dai_group_mi2s_remove, + }, + { + .capture = { + .stream_name = "Tertiary MI2S1 Capture", + .aif_name = "TERT_MI2S_TX_1", + .rates = SNDRV_PCM_RATE_8000 | SNDRV_PCM_RATE_11025 | + SNDRV_PCM_RATE_16000 | SNDRV_PCM_RATE_22050 | + SNDRV_PCM_RATE_32000 | SNDRV_PCM_RATE_44100 | + SNDRV_PCM_RATE_48000 | SNDRV_PCM_RATE_96000 | + SNDRV_PCM_RATE_192000, + .formats = SNDRV_PCM_FMTBIT_S16_LE | + SNDRV_PCM_FMTBIT_S24_LE | + SNDRV_PCM_FMTBIT_S24_3LE, + .rate_min = 8000, + .rate_max = 192000, + }, + .ops = &msm_dai_q6_group_mi2s_ops, + .id = AFE_PORT_ID_TERTIARY_MI2S_TX_1, + .probe = msm_dai_q6_dai_group_mi2s_probe, + .remove = msm_dai_q6_dai_group_mi2s_remove, + }, + { + .capture = { + .stream_name = "Tertiary MI2S2 Capture", + .aif_name = "TERT_MI2S_TX_2", + .rates = SNDRV_PCM_RATE_8000 | SNDRV_PCM_RATE_11025 | + SNDRV_PCM_RATE_16000 | SNDRV_PCM_RATE_22050 | + SNDRV_PCM_RATE_32000 | SNDRV_PCM_RATE_44100 | + SNDRV_PCM_RATE_48000 | SNDRV_PCM_RATE_96000 | + SNDRV_PCM_RATE_192000, + .formats = SNDRV_PCM_FMTBIT_S16_LE | + SNDRV_PCM_FMTBIT_S24_LE | + SNDRV_PCM_FMTBIT_S24_3LE, + .rate_min = 8000, + .rate_max = 192000, + }, + .ops = &msm_dai_q6_group_mi2s_ops, + .id = AFE_PORT_ID_TERTIARY_MI2S_TX_2, + .probe = msm_dai_q6_dai_group_mi2s_probe, + .remove = msm_dai_q6_dai_group_mi2s_remove, + }, + { + .capture = { + .stream_name = "Tertiary MI2S3 Capture", + .aif_name = "TERT_MI2S_TX_3", + .rates = SNDRV_PCM_RATE_8000 | SNDRV_PCM_RATE_11025 | + SNDRV_PCM_RATE_16000 | SNDRV_PCM_RATE_22050 | + SNDRV_PCM_RATE_32000 | SNDRV_PCM_RATE_44100 | + SNDRV_PCM_RATE_48000 | SNDRV_PCM_RATE_96000 | + SNDRV_PCM_RATE_192000, + .formats = SNDRV_PCM_FMTBIT_S16_LE | + SNDRV_PCM_FMTBIT_S24_LE | + SNDRV_PCM_FMTBIT_S24_3LE, + .rate_min = 8000, + .rate_max = 192000, + }, + .ops = &msm_dai_q6_group_mi2s_ops, + .id = AFE_PORT_ID_TERTIARY_MI2S_TX_3, + .probe = msm_dai_q6_dai_group_mi2s_probe, + .remove = msm_dai_q6_dai_group_mi2s_remove, + }, + { + .capture = { + .stream_name = "Tertiary MI2S4 Capture", + .aif_name = "TERT_MI2S_TX_4", + .rates = SNDRV_PCM_RATE_8000 | SNDRV_PCM_RATE_11025 | + SNDRV_PCM_RATE_16000 | SNDRV_PCM_RATE_22050 | + SNDRV_PCM_RATE_32000 | SNDRV_PCM_RATE_44100 | + SNDRV_PCM_RATE_48000 | SNDRV_PCM_RATE_96000 | + SNDRV_PCM_RATE_192000, + .formats = SNDRV_PCM_FMTBIT_S16_LE | + SNDRV_PCM_FMTBIT_S24_LE | + SNDRV_PCM_FMTBIT_S24_3LE, + .rate_min = 8000, + .rate_max = 192000, + }, + .ops = &msm_dai_q6_group_mi2s_ops, + .id = AFE_PORT_ID_TERTIARY_MI2S_TX_4, + .probe = msm_dai_q6_dai_group_mi2s_probe, + .remove = msm_dai_q6_dai_group_mi2s_remove, + }, + { + .playback = { + .stream_name = "Quaternary MI2S1 Playback", + .aif_name = "QUAT_MI2S_RX_1", + .rates = SNDRV_PCM_RATE_8000 | SNDRV_PCM_RATE_11025 | + SNDRV_PCM_RATE_16000 | SNDRV_PCM_RATE_22050 | + SNDRV_PCM_RATE_32000 | SNDRV_PCM_RATE_44100 | + SNDRV_PCM_RATE_48000 | SNDRV_PCM_RATE_96000 | + SNDRV_PCM_RATE_192000, + .formats = SNDRV_PCM_FMTBIT_S16_LE | + SNDRV_PCM_FMTBIT_S24_LE | + SNDRV_PCM_FMTBIT_S24_3LE, + .rate_min = 8000, + .rate_max = 192000, + }, + .ops = &msm_dai_q6_group_mi2s_ops, + .id = AFE_PORT_ID_QUATERNARY_MI2S_RX_1, + .probe = msm_dai_q6_dai_group_mi2s_probe, + .remove = msm_dai_q6_dai_group_mi2s_remove, + }, + { + .playback = { + .stream_name = "Quaternary MI2S2 Playback", + .aif_name = "QUAT_MI2S_RX_2", + .rates = SNDRV_PCM_RATE_8000 | SNDRV_PCM_RATE_11025 | + SNDRV_PCM_RATE_16000 | SNDRV_PCM_RATE_22050 | + SNDRV_PCM_RATE_32000 | SNDRV_PCM_RATE_44100 | + SNDRV_PCM_RATE_48000 | SNDRV_PCM_RATE_96000 | + SNDRV_PCM_RATE_192000, + .formats = SNDRV_PCM_FMTBIT_S16_LE | + SNDRV_PCM_FMTBIT_S24_LE | + SNDRV_PCM_FMTBIT_S24_3LE, + .rate_min = 8000, + .rate_max = 192000, + }, + .ops = &msm_dai_q6_group_mi2s_ops, + .id = AFE_PORT_ID_QUATERNARY_MI2S_RX_2, + .probe = msm_dai_q6_dai_group_mi2s_probe, + .remove = msm_dai_q6_dai_group_mi2s_remove, + }, + { + .playback = { + .stream_name = "Quaternary MI2S3 Playback", + .aif_name = "QUAT_MI2S_RX_3", + .rates = SNDRV_PCM_RATE_8000 | SNDRV_PCM_RATE_11025 | + SNDRV_PCM_RATE_16000 | SNDRV_PCM_RATE_22050 | + SNDRV_PCM_RATE_32000 | SNDRV_PCM_RATE_44100 | + SNDRV_PCM_RATE_48000 | SNDRV_PCM_RATE_96000 | + SNDRV_PCM_RATE_192000, + .formats = SNDRV_PCM_FMTBIT_S16_LE | + SNDRV_PCM_FMTBIT_S24_LE | + SNDRV_PCM_FMTBIT_S24_3LE, + .rate_min = 8000, + .rate_max = 192000, + }, + .ops = &msm_dai_q6_group_mi2s_ops, + .id = AFE_PORT_ID_QUATERNARY_MI2S_RX_3, + .probe = msm_dai_q6_dai_group_mi2s_probe, + .remove = msm_dai_q6_dai_group_mi2s_remove, + }, + { + .playback = { + .stream_name = "Quaternary MI2S4 Playback", + .aif_name = "QUAT_MI2S_RX_4", + .rates = SNDRV_PCM_RATE_8000 | SNDRV_PCM_RATE_11025 | + SNDRV_PCM_RATE_16000 | SNDRV_PCM_RATE_22050 | + SNDRV_PCM_RATE_32000 | SNDRV_PCM_RATE_44100 | + SNDRV_PCM_RATE_48000 | SNDRV_PCM_RATE_96000 | + SNDRV_PCM_RATE_192000, + .formats = SNDRV_PCM_FMTBIT_S16_LE | + SNDRV_PCM_FMTBIT_S24_LE | + SNDRV_PCM_FMTBIT_S24_3LE, + .rate_min = 8000, + .rate_max = 192000, + }, + .ops = &msm_dai_q6_group_mi2s_ops, + .id = AFE_PORT_ID_QUATERNARY_MI2S_RX_4, + .probe = msm_dai_q6_dai_group_mi2s_probe, + .remove = msm_dai_q6_dai_group_mi2s_remove, + }, + { + .capture = { + .stream_name = "Quaternary MI2S1 Capture", + .aif_name = "QUAT_MI2S_TX_1", + .rates = SNDRV_PCM_RATE_8000 | SNDRV_PCM_RATE_11025 | + SNDRV_PCM_RATE_16000 | SNDRV_PCM_RATE_22050 | + SNDRV_PCM_RATE_32000 | SNDRV_PCM_RATE_44100 | + SNDRV_PCM_RATE_48000 | SNDRV_PCM_RATE_96000 | + SNDRV_PCM_RATE_192000, + .formats = SNDRV_PCM_FMTBIT_S16_LE | + SNDRV_PCM_FMTBIT_S24_LE | + SNDRV_PCM_FMTBIT_S24_3LE, + .rate_min = 8000, + .rate_max = 192000, + }, + .ops = &msm_dai_q6_group_mi2s_ops, + .id = AFE_PORT_ID_QUATERNARY_MI2S_TX_1, + .probe = msm_dai_q6_dai_group_mi2s_probe, + .remove = msm_dai_q6_dai_group_mi2s_remove, + }, + { + .capture = { + .stream_name = "Quaternary MI2S2 Capture", + .aif_name = "QUAT_MI2S_TX_2", + .rates = SNDRV_PCM_RATE_8000 | SNDRV_PCM_RATE_11025 | + SNDRV_PCM_RATE_16000 | SNDRV_PCM_RATE_22050 | + SNDRV_PCM_RATE_32000 | SNDRV_PCM_RATE_44100 | + SNDRV_PCM_RATE_48000 | SNDRV_PCM_RATE_96000 | + SNDRV_PCM_RATE_192000, + .formats = SNDRV_PCM_FMTBIT_S16_LE | + SNDRV_PCM_FMTBIT_S24_LE | + SNDRV_PCM_FMTBIT_S24_3LE, + .rate_min = 8000, + .rate_max = 192000, + }, + .ops = &msm_dai_q6_group_mi2s_ops, + .id = AFE_PORT_ID_QUATERNARY_MI2S_TX_2, + .probe = msm_dai_q6_dai_group_mi2s_probe, + .remove = msm_dai_q6_dai_group_mi2s_remove, + }, + { + .capture = { + .stream_name = "Quaternary MI2S3 Capture", + .aif_name = "QUAT_MI2S_TX_3", + .rates = SNDRV_PCM_RATE_8000 | SNDRV_PCM_RATE_11025 | + SNDRV_PCM_RATE_16000 | SNDRV_PCM_RATE_22050 | + SNDRV_PCM_RATE_32000 | SNDRV_PCM_RATE_44100 | + SNDRV_PCM_RATE_48000 | SNDRV_PCM_RATE_96000 | + SNDRV_PCM_RATE_192000, + .formats = SNDRV_PCM_FMTBIT_S16_LE | + SNDRV_PCM_FMTBIT_S24_LE | + SNDRV_PCM_FMTBIT_S24_3LE, + .rate_min = 8000, + .rate_max = 192000, + }, + .ops = &msm_dai_q6_group_mi2s_ops, + .id = AFE_PORT_ID_QUATERNARY_MI2S_TX_3, + .probe = msm_dai_q6_dai_group_mi2s_probe, + .remove = msm_dai_q6_dai_group_mi2s_remove, + }, + { + .capture = { + .stream_name = "Quaternary MI2S4 Capture", + .aif_name = "QUAT_MI2S_TX_4", + .rates = SNDRV_PCM_RATE_8000 | SNDRV_PCM_RATE_11025 | + SNDRV_PCM_RATE_16000 | SNDRV_PCM_RATE_22050 | + SNDRV_PCM_RATE_32000 | SNDRV_PCM_RATE_44100 | + SNDRV_PCM_RATE_48000 | SNDRV_PCM_RATE_96000 | + SNDRV_PCM_RATE_192000, + .formats = SNDRV_PCM_FMTBIT_S16_LE | + SNDRV_PCM_FMTBIT_S24_LE | + SNDRV_PCM_FMTBIT_S24_3LE, + .rate_min = 8000, + .rate_max = 192000, + }, + .ops = &msm_dai_q6_group_mi2s_ops, + .id = AFE_PORT_ID_QUATERNARY_MI2S_TX_4, + .probe = msm_dai_q6_dai_group_mi2s_probe, + .remove = msm_dai_q6_dai_group_mi2s_remove, + } +}; static int msm_dai_q6_mi2s_get_lineconfig(u16 sd_lines, u16 *config_ptr, unsigned int *ch_cnt) @@ -4923,6 +5977,297 @@ static struct platform_driver msm_dai_q6_mi2s_driver = { }, }; +static int msm_dai_group_mi2s_probe(struct platform_device *pdev) +{ + int rc = 0; + + /* probe child node info */ + rc = of_platform_populate(pdev->dev.of_node, NULL, NULL, &pdev->dev); + if (rc) { + dev_err(&pdev->dev, "%s: failed to add child nodes, rc=%d\n", + __func__, rc); + goto rtn; + } else + dev_dbg(&pdev->dev, "%s: added child node\n", __func__); + +rtn: + return rc; +} + +static int msm_dai_group_mi2s_remove(struct platform_device *pdev) +{ + return 0; +} + +static int msm_dai_q6_group_mi2s_dev_id_validation(u32 dev_id) +{ + switch (dev_id) { + case AFE_PORT_ID_SECONDARY_MI2S_RX_1: + case AFE_PORT_ID_SECONDARY_MI2S_RX_2: + case AFE_PORT_ID_SECONDARY_MI2S_RX_3: + case AFE_PORT_ID_SECONDARY_MI2S_RX_4: + case AFE_PORT_ID_SECONDARY_MI2S_TX_1: + case AFE_PORT_ID_SECONDARY_MI2S_TX_2: + case AFE_PORT_ID_SECONDARY_MI2S_TX_3: + case AFE_PORT_ID_SECONDARY_MI2S_TX_4: + case AFE_PORT_ID_TERTIARY_MI2S_RX_1: + case AFE_PORT_ID_TERTIARY_MI2S_RX_2: + case AFE_PORT_ID_TERTIARY_MI2S_RX_3: + case AFE_PORT_ID_TERTIARY_MI2S_RX_4: + case AFE_PORT_ID_TERTIARY_MI2S_TX_1: + case AFE_PORT_ID_TERTIARY_MI2S_TX_2: + case AFE_PORT_ID_TERTIARY_MI2S_TX_3: + case AFE_PORT_ID_TERTIARY_MI2S_TX_4: + case AFE_PORT_ID_QUATERNARY_MI2S_RX_1: + case AFE_PORT_ID_QUATERNARY_MI2S_RX_2: + case AFE_PORT_ID_QUATERNARY_MI2S_RX_3: + case AFE_PORT_ID_QUATERNARY_MI2S_RX_4: + case AFE_PORT_ID_QUATERNARY_MI2S_TX_1: + case AFE_PORT_ID_QUATERNARY_MI2S_TX_2: + case AFE_PORT_ID_QUATERNARY_MI2S_TX_3: + case AFE_PORT_ID_QUATERNARY_MI2S_TX_4: + return 0; + default: + return -EINVAL; + } +} + +static const struct snd_soc_component_driver msm_q6_group_mi2s_dai_component = { + .name = "msm-dai-q6-mi2s-group", +}; + +static int msm_dai_group_mi2s_dev_probe(struct platform_device *pdev) +{ + int rc = 0; + struct msm_dai_q6_group_mi2s_dai_data *dai_data = NULL; + u32 mi2s_dev_id = 0; + u32 ch_mode = 0; + int port_idx = 0; + struct device_node *mi2s_parent_node = NULL; + u32 num_group_mi2s_ports = 0; + const uint32_t *port_id_array = NULL; + u32 array_length, i = 0; + u32 group_idx = 0; + u32 sync_mode = 0; + + mi2s_parent_node = of_get_parent(pdev->dev.of_node); + /* extract mi2s group info into static */ + rc = of_property_read_u32(mi2s_parent_node, + "qcom,msm-cpudai-mi2s-group-id", + (u32 *)&group_mi2s_cfg.group_id); + if (rc) { + dev_err(&pdev->dev, "%s: Group ID from DT file %s\n", + __func__, "qcom,msm-cpudai-mi2s-group-id"); + goto rtn; + } + + rc = of_property_read_u32(mi2s_parent_node, + "qcom,msm-cpudai-mi2s-group-num-ports", + &num_group_mi2s_ports); + if (rc) { + dev_err(&pdev->dev, "%s: ch_mode from DT file %s\n", + __func__, "qcom,msm-cpudai-mi2s-group-num-ports"); + goto rtn; + } + + if (num_group_mi2s_ports > AFE_GROUP_DEVICE_NUM_PORTS) { + dev_err(&pdev->dev, "%s: Group Num Ports %d greater than Man %d\n", + __func__, num_group_mi2s_ports, + AFE_GROUP_DEVICE_NUM_PORTS); + rc = -EINVAL; + goto rtn; + } + + port_id_array = of_get_property(mi2s_parent_node, + "qcom,msm-cpudai-mi2s-group-port-id", + &array_length); + if (port_id_array == NULL) { + dev_err(&pdev->dev, "%s: prot_id_array is not valid\n", + __func__); + rc = -EINVAL; + goto rtn; + } + if (array_length != sizeof(uint32_t) * num_group_mi2s_ports) { + dev_err(&pdev->dev, "%s array_length is %d, expected is %zd\n", + __func__, array_length, + sizeof(uint32_t) * num_group_mi2s_ports); + rc = -EINVAL; + goto rtn; + } + + for (i = 0; i < num_group_mi2s_ports; i++) + group_mi2s_cfg.port_id[i] = (u16)be32_to_cpu(port_id_array[i]); + /* Unused index should be filled with AFE_PORT_INVALID */ + for (i = num_group_mi2s_ports; i < AFE_GROUP_DEVICE_NUM_PORTS; i++) + group_mi2s_cfg.port_id[i] = AFE_PORT_INVALID; + + /*extract group_mi2s group sd line info into static */ + rc = of_property_read_u32(mi2s_parent_node, + "qcom,msm-cpudai-mi2s-channel-mode", + &ch_mode); + if (rc) { + dev_err(&pdev->dev, "%s: ch_mode from DT file %s\n", + __func__, "qcom,msm-cpudai-mi2s-channel-mode"); + goto rtn; + } + + group_mi2s_cfg.channel_mode = ch_mode; + group_mi2s_cfg.minor_version = AFE_API_VERSION_I2S_CONFIG; + group_idx = msm_dai_q6_get_mi2s_group_idx(group_mi2s_cfg.group_id); + if (group_idx < 0 || group_idx > IDX_GROUP_MI2S_MAX) { + dev_err(&pdev->dev, "%s: group id 0x%x not supported\n", + __func__, group_mi2s_cfg.group_id); + rc = -EINVAL; + goto rtn; + } + atomic_set(&group_mi2s_ref[group_idx], 0); + + rc = of_property_read_u32(mi2s_parent_node, + "qcom,msm-cpudai-mi2s-sync-mode", + &sync_mode); + if (rc) { + dev_err(&pdev->dev, "%s: ch_mode from DT file %s\n", + __func__, "qcom,msm-cpudai-mi2s-sync-mode"); + goto rtn; + } + + rc = of_property_read_u32(mi2s_parent_node, + "qcom,msm-cpudai-mi2s-mclk", + &group_mi2s_mclk_set.clk_freq_in_hz); + if (rc) { + dev_err(&pdev->dev, "%s: mclk from DT file %s\n", + __func__, "qcom,msm-cpudai-mi2s-mclk"); + goto rtn; + } + + rc = of_property_read_u32(mi2s_parent_node, + "qcom,msm-cpudai-mi2s-bclk", + &group_mi2s_bclk_set.clk_freq_in_hz); + if (rc) { + dev_err(&pdev->dev, "%s: bclk from DT file %s\n", + __func__, "qcom,msm-cpudai-mi2s-bclk"); + goto rtn; + } + + /*update default group mi2s clk set for master/slave select*/ + rc = msm_dai_q6_group_mi2s_set_clk_param(group_mi2s_cfg.group_id, + &group_mi2s_mclk_set, + &group_mi2s_bclk_set, + sync_mode); + if (rc) { + dev_err(&pdev->dev, "%s: group id not supported 0x%x\n", + __func__, tdm_group_cfg.group_id); + goto rtn; + } + + /* retrieve device/afe id */ + rc = of_property_read_u32(pdev->dev.of_node, + "qcom,msm-cpudai-mi2s-dev-id", + &mi2s_dev_id); + if (rc) { + dev_err(&pdev->dev, "%s: DeviceID missing in DT file\n", + __func__); + goto rtn; + } + rc = msm_dai_q6_group_mi2s_dev_id_validation(mi2s_dev_id); + if (rc) { + dev_err(&pdev->dev, "%s: Invalid GMI2S device ID %d in DT file\n", + __func__, mi2s_dev_id); + rc = -ENXIO; + goto rtn; + } + + pdev->id = mi2s_dev_id; + rc = of_property_read_u32(pdev->dev.of_node, + "qcom,msm-cpudai-mi2s-dev-channel-mode", + &ch_mode); + if (rc) { + dev_err(&pdev->dev, "%s: TX line from DT file %s\n", + __func__, "qcom,msm-cpudai-mi2s-dev-channel-mode"); + goto rtn; + } + + dai_data = kzalloc(sizeof(*dai_data), + GFP_KERNEL); + if (!dai_data) { + rc = -ENOMEM; + goto rtn; + } + dev_set_drvdata(&pdev->dev, dai_data); + + dai_data->sync_mode = sync_mode; + dai_data->num_group_ports = num_group_mi2s_ports; + dai_data->port_cfg.i2s_cfg.channel_mode = ch_mode; + dai_data->bclk_set = group_mi2s_bclk_set; + dai_data->mclk_set = group_mi2s_mclk_set; + dai_data->group_cfg.i2s_cfg = group_mi2s_cfg; + + port_idx = msm_dai_q6_get_mi2s_port_idx(mi2s_dev_id); + if (port_idx < 0 || port_idx > IDX_GROUP_MI2S_PORT_MAX) { + dev_err(&pdev->dev, "%s: Port id 0x%x not supported\n", + __func__, mi2s_dev_id); + rc = -EINVAL; + goto free_dai_data; + } + + rc = snd_soc_register_component(&pdev->dev, + &msm_q6_group_mi2s_dai_component, + &msm_dai_q6_group_mi2s_dai[port_idx], 1); + if (rc) { + dev_err(&pdev->dev, + "%s: fail to register msm_q6_group_mi2s_dai_component\n", + __func__); + goto free_dai_data; + } + + return 0; + +free_dai_data: + kfree(dai_data); +rtn: + return rc; +} + +static int msm_dai_group_mi2s_dev_remove(struct platform_device *pdev) +{ + snd_soc_unregister_component(&pdev->dev); + return 0; +} + +static const struct of_device_id msm_dai_group_mi2s_dt_match[] = { + { .compatible = "qcom,msm-dai-group-mi2s", }, + { } +}; + +MODULE_DEVICE_TABLE(of, msm_dai_group_mi2s_dt_match); + +static struct platform_driver msm_dai_group_mi2s_driver = { + .probe = msm_dai_group_mi2s_probe, + .remove = msm_dai_group_mi2s_remove, + .driver = { + .name = "msm-dai-group-mi2s", + .owner = THIS_MODULE, + .of_match_table = msm_dai_group_mi2s_dt_match, + }, +}; + +static const struct of_device_id msm_dai_group_mi2s_dev_dt_match[] = { + { .compatible = "qcom,msm-dai-group-mi2s-dev", }, + { } +}; + +MODULE_DEVICE_TABLE(of, msm_dai_group_mi2s_dev_dt_match); + +static struct platform_driver msm_dai_group_mi2s_dev_driver = { + .probe = msm_dai_group_mi2s_dev_probe, + .remove = msm_dai_group_mi2s_dev_remove, + .driver = { + .name = "msm-dai-group-mi2s-dev", + .owner = THIS_MODULE, + .of_match_table = msm_dai_group_mi2s_dev_dt_match, + }, +}; + static int msm_dai_q6_spdif_dev_probe(struct platform_device *pdev) { int rc; @@ -8344,8 +9689,27 @@ static int __init msm_dai_q6_init(void) pr_err("%s: fail to register dai TDM\n", __func__); goto dai_tdm_q6_fail; } + + rc = platform_driver_register(&msm_dai_group_mi2s_dev_driver); + if (rc) { + pr_err("%s: fail to register dai GMI2S dev drv\n", + __func__); + goto dai_q6_group_mi2s_dev_fail; + } + + rc = platform_driver_register(&msm_dai_group_mi2s_driver); + if (rc) { + pr_err("%s: fail to register dai GMI2S\n", + __func__); + goto dai_group_mi2s_fail; + } + return rc; +dai_group_mi2s_fail: + platform_driver_unregister(&msm_dai_group_mi2s_driver); +dai_q6_group_mi2s_dev_fail: + platform_driver_unregister(&msm_dai_group_mi2s_dev_driver); dai_tdm_q6_fail: platform_driver_unregister(&msm_dai_q6_tdm_driver); dai_q6_tdm_drv_fail: @@ -8371,6 +9735,8 @@ static void __exit msm_dai_q6_exit(void) platform_driver_unregister(&msm_dai_q6); platform_driver_unregister(&msm_auxpcm_dev_driver); platform_driver_unregister(&msm_dai_q6_spdif_driver); + platform_driver_unregister(&msm_dai_group_mi2s_driver); + platform_driver_unregister(&msm_dai_group_mi2s_dev_driver); } module_exit(msm_dai_q6_exit); diff --git a/sound/soc/msm/qdsp6v2/msm-pcm-routing-v2.c b/sound/soc/msm/qdsp6v2/msm-pcm-routing-v2.c index b0843bca62bf..ee8c42903c99 100644 --- a/sound/soc/msm/qdsp6v2/msm-pcm-routing-v2.c +++ b/sound/soc/msm/qdsp6v2/msm-pcm-routing-v2.c @@ -546,6 +546,54 @@ struct msm_pcm_routing_bdai_data msm_bedais[MSM_BACKEND_DAI_MAX] = { LPASS_BE_INT6_MI2S_RX}, { AFE_PORT_ID_INT6_MI2S_TX, 0, {0}, {0}, 0, 0, 0, 0, {0}, LPASS_BE_INT6_MI2S_TX}, + { AFE_PORT_ID_SECONDARY_MI2S_RX_1, 0, {0}, {0}, 0, 0, 0, 0, {0}, + LPASS_BE_SEC_MI2S_RX_1}, + { AFE_PORT_ID_SECONDARY_MI2S_RX_2, 0, {0}, {0}, 0, 0, 0, 0, {0}, + LPASS_BE_SEC_MI2S_RX_2}, + { AFE_PORT_ID_SECONDARY_MI2S_RX_3, 0, {0}, {0}, 0, 0, 0, 0, {0}, + LPASS_BE_SEC_MI2S_RX_3}, + { AFE_PORT_ID_SECONDARY_MI2S_RX_4, 0, {0}, {0}, 0, 0, 0, 0, {0}, + LPASS_BE_SEC_MI2S_RX_4}, + { AFE_PORT_ID_SECONDARY_MI2S_TX_1, 0, {0}, {0}, 0, 0, 0, 0, {0}, + LPASS_BE_SEC_MI2S_TX_1}, + { AFE_PORT_ID_SECONDARY_MI2S_TX_2, 0, {0}, {0}, 0, 0, 0, 0, {0}, + LPASS_BE_SEC_MI2S_TX_2}, + { AFE_PORT_ID_SECONDARY_MI2S_TX_3, 0, {0}, {0}, 0, 0, 0, 0, {0}, + LPASS_BE_SEC_MI2S_TX_3}, + { AFE_PORT_ID_SECONDARY_MI2S_TX_4, 0, {0}, {0}, 0, 0, 0, 0, {0}, + LPASS_BE_SEC_MI2S_TX_4}, + { AFE_PORT_ID_TERTIARY_MI2S_RX_1, 0, {0}, {0}, 0, 0, 0, 0, {0}, + LPASS_BE_TERT_MI2S_RX_1}, + { AFE_PORT_ID_TERTIARY_MI2S_RX_2, 0, {0}, {0}, 0, 0, 0, 0, {0}, + LPASS_BE_TERT_MI2S_RX_2}, + { AFE_PORT_ID_TERTIARY_MI2S_RX_3, 0, {0}, {0}, 0, 0, 0, 0, {0}, + LPASS_BE_TERT_MI2S_RX_3}, + { AFE_PORT_ID_TERTIARY_MI2S_RX_4, 0, {0}, {0}, 0, 0, 0, 0, {0}, + LPASS_BE_TERT_MI2S_RX_4}, + { AFE_PORT_ID_TERTIARY_MI2S_TX_1, 0, {0}, {0}, 0, 0, 0, 0, {0}, + LPASS_BE_TERT_MI2S_TX_1}, + { AFE_PORT_ID_TERTIARY_MI2S_TX_2, 0, {0}, {0}, 0, 0, 0, 0, {0}, + LPASS_BE_TERT_MI2S_TX_2}, + { AFE_PORT_ID_TERTIARY_MI2S_TX_3, 0, {0}, {0}, 0, 0, 0, 0, {0}, + LPASS_BE_TERT_MI2S_TX_3}, + { AFE_PORT_ID_TERTIARY_MI2S_TX_4, 0, {0}, {0}, 0, 0, 0, 0, {0}, + LPASS_BE_TERT_MI2S_TX_4}, + { AFE_PORT_ID_QUATERNARY_MI2S_RX_1, 0, {0}, {0}, 0, 0, 0, 0, {0}, + LPASS_BE_QUAT_MI2S_RX_1}, + { AFE_PORT_ID_QUATERNARY_MI2S_RX_2, 0, {0}, {0}, 0, 0, 0, 0, {0}, + LPASS_BE_QUAT_MI2S_RX_2}, + { AFE_PORT_ID_QUATERNARY_MI2S_RX_3, 0, {0}, {0}, 0, 0, 0, 0, {0}, + LPASS_BE_QUAT_MI2S_RX_3}, + { AFE_PORT_ID_QUATERNARY_MI2S_RX_4, 0, {0}, {0}, 0, 0, 0, 0, {0}, + LPASS_BE_QUAT_MI2S_RX_4}, + { AFE_PORT_ID_QUATERNARY_MI2S_TX_1, 0, {0}, {0}, 0, 0, 0, 0, {0}, + LPASS_BE_QUAT_MI2S_TX_1}, + { AFE_PORT_ID_QUATERNARY_MI2S_TX_2, 0, {0}, {0}, 0, 0, 0, 0, {0}, + LPASS_BE_QUAT_MI2S_TX_2}, + { AFE_PORT_ID_QUATERNARY_MI2S_TX_3, 0, {0}, {0}, 0, 0, 0, 0, {0}, + LPASS_BE_QUAT_MI2S_TX_3}, + { AFE_PORT_ID_QUATERNARY_MI2S_TX_4, 0, {0}, {0}, 0, 0, 0, 0, {0}, + LPASS_BE_QUAT_MI2S_TX_4} }; /* Track ASM playback & capture sessions of DAI @@ -4723,6 +4771,834 @@ static const struct snd_kcontrol_new secondary_mi2s_rx2_mixer_controls[] = { msm_routing_put_audio_mixer), }; +static const struct snd_kcontrol_new secondary_mi2s_rx_1_mixer_controls[] = { + SOC_SINGLE_EXT("MultiMedia1", MSM_BACKEND_DAI_SECONDARY_MI2S_RX_1, + MSM_FRONTEND_DAI_MULTIMEDIA1, 1, 0, msm_routing_get_audio_mixer, + msm_routing_put_audio_mixer), + SOC_SINGLE_EXT("MultiMedia2", MSM_BACKEND_DAI_SECONDARY_MI2S_RX_1, + MSM_FRONTEND_DAI_MULTIMEDIA2, 1, 0, msm_routing_get_audio_mixer, + msm_routing_put_audio_mixer), + SOC_SINGLE_EXT("MultiMedia3", MSM_BACKEND_DAI_SECONDARY_MI2S_RX_1, + MSM_FRONTEND_DAI_MULTIMEDIA3, 1, 0, msm_routing_get_audio_mixer, + msm_routing_put_audio_mixer), + SOC_SINGLE_EXT("MultiMedia4", MSM_BACKEND_DAI_SECONDARY_MI2S_RX_1, + MSM_FRONTEND_DAI_MULTIMEDIA4, 1, 0, msm_routing_get_audio_mixer, + msm_routing_put_audio_mixer), + SOC_SINGLE_EXT("MultiMedia5", MSM_BACKEND_DAI_SECONDARY_MI2S_RX_1, + MSM_FRONTEND_DAI_MULTIMEDIA5, 1, 0, msm_routing_get_audio_mixer, + msm_routing_put_audio_mixer), + SOC_SINGLE_EXT("MultiMedia6", MSM_BACKEND_DAI_SECONDARY_MI2S_RX_1, + MSM_FRONTEND_DAI_MULTIMEDIA6, 1, 0, msm_routing_get_audio_mixer, + msm_routing_put_audio_mixer), + SOC_SINGLE_EXT("MultiMedia7", MSM_BACKEND_DAI_SECONDARY_MI2S_RX_1, + MSM_FRONTEND_DAI_MULTIMEDIA7, 1, 0, msm_routing_get_audio_mixer, + msm_routing_put_audio_mixer), + SOC_SINGLE_EXT("MultiMedia8", MSM_BACKEND_DAI_SECONDARY_MI2S_RX_1, + MSM_FRONTEND_DAI_MULTIMEDIA8, 1, 0, msm_routing_get_audio_mixer, + msm_routing_put_audio_mixer), + SOC_SINGLE_EXT("MultiMedia9", MSM_BACKEND_DAI_SECONDARY_MI2S_RX_1, + MSM_FRONTEND_DAI_MULTIMEDIA9, 1, 0, msm_routing_get_audio_mixer, + msm_routing_put_audio_mixer), + SOC_SINGLE_EXT("MultiMedia10", MSM_BACKEND_DAI_SECONDARY_MI2S_RX_1, + MSM_FRONTEND_DAI_MULTIMEDIA10, 1, 0, msm_routing_get_audio_mixer, + msm_routing_put_audio_mixer), + SOC_SINGLE_EXT("MultiMedia11", MSM_BACKEND_DAI_SECONDARY_MI2S_RX_1, + MSM_FRONTEND_DAI_MULTIMEDIA11, 1, 0, msm_routing_get_audio_mixer, + msm_routing_put_audio_mixer), + SOC_SINGLE_EXT("MultiMedia12", MSM_BACKEND_DAI_SECONDARY_MI2S_RX_1, + MSM_FRONTEND_DAI_MULTIMEDIA12, 1, 0, msm_routing_get_audio_mixer, + msm_routing_put_audio_mixer), + SOC_SINGLE_EXT("MultiMedia13", MSM_BACKEND_DAI_SECONDARY_MI2S_RX_1, + MSM_FRONTEND_DAI_MULTIMEDIA13, 1, 0, msm_routing_get_audio_mixer, + msm_routing_put_audio_mixer), + SOC_SINGLE_EXT("MultiMedia14", MSM_BACKEND_DAI_SECONDARY_MI2S_RX_1, + MSM_FRONTEND_DAI_MULTIMEDIA14, 1, 0, msm_routing_get_audio_mixer, + msm_routing_put_audio_mixer), + SOC_SINGLE_EXT("MultiMedia15", MSM_BACKEND_DAI_SECONDARY_MI2S_RX_1, + MSM_FRONTEND_DAI_MULTIMEDIA15, 1, 0, msm_routing_get_audio_mixer, + msm_routing_put_audio_mixer), + SOC_SINGLE_EXT("MultiMedia16", MSM_BACKEND_DAI_SECONDARY_MI2S_RX_1, + MSM_FRONTEND_DAI_MULTIMEDIA16, 1, 0, msm_routing_get_audio_mixer, + msm_routing_put_audio_mixer), + SOC_SINGLE_EXT("MultiMedia17", MSM_BACKEND_DAI_SECONDARY_MI2S_RX_1, + MSM_FRONTEND_DAI_MULTIMEDIA17, 1, 0, msm_routing_get_audio_mixer, + msm_routing_put_audio_mixer), + SOC_SINGLE_EXT("MultiMedia18", MSM_BACKEND_DAI_SECONDARY_MI2S_RX_1, + MSM_FRONTEND_DAI_MULTIMEDIA18, 1, 0, msm_routing_get_audio_mixer, + msm_routing_put_audio_mixer), + SOC_SINGLE_EXT("MultiMedia19", MSM_BACKEND_DAI_SECONDARY_MI2S_RX_1, + MSM_FRONTEND_DAI_MULTIMEDIA19, 1, 0, msm_routing_get_audio_mixer, + msm_routing_put_audio_mixer), + SOC_SINGLE_EXT("MultiMedia26", MSM_BACKEND_DAI_SECONDARY_MI2S_RX_1, + MSM_FRONTEND_DAI_MULTIMEDIA26, 1, 0, msm_routing_get_audio_mixer, + msm_routing_put_audio_mixer), + SOC_SINGLE_EXT("MultiMedia28", MSM_BACKEND_DAI_SECONDARY_MI2S_RX_1, + MSM_FRONTEND_DAI_MULTIMEDIA28, 1, 0, msm_routing_get_audio_mixer, + msm_routing_put_audio_mixer), + SOC_SINGLE_EXT("MultiMedia29", MSM_BACKEND_DAI_SECONDARY_MI2S_RX_1, + MSM_FRONTEND_DAI_MULTIMEDIA29, 1, 0, msm_routing_get_audio_mixer, + msm_routing_put_audio_mixer), +}; + +static const struct snd_kcontrol_new secondary_mi2s_rx_2_mixer_controls[] = { + SOC_SINGLE_EXT("MultiMedia1", MSM_BACKEND_DAI_SECONDARY_MI2S_RX_2, + MSM_FRONTEND_DAI_MULTIMEDIA1, 1, 0, msm_routing_get_audio_mixer, + msm_routing_put_audio_mixer), + SOC_SINGLE_EXT("MultiMedia2", MSM_BACKEND_DAI_SECONDARY_MI2S_RX_2, + MSM_FRONTEND_DAI_MULTIMEDIA2, 1, 0, msm_routing_get_audio_mixer, + msm_routing_put_audio_mixer), + SOC_SINGLE_EXT("MultiMedia3", MSM_BACKEND_DAI_SECONDARY_MI2S_RX_2, + MSM_FRONTEND_DAI_MULTIMEDIA3, 1, 0, msm_routing_get_audio_mixer, + msm_routing_put_audio_mixer), + SOC_SINGLE_EXT("MultiMedia4", MSM_BACKEND_DAI_SECONDARY_MI2S_RX_2, + MSM_FRONTEND_DAI_MULTIMEDIA4, 1, 0, msm_routing_get_audio_mixer, + msm_routing_put_audio_mixer), + SOC_SINGLE_EXT("MultiMedia5", MSM_BACKEND_DAI_SECONDARY_MI2S_RX_2, + MSM_FRONTEND_DAI_MULTIMEDIA5, 1, 0, msm_routing_get_audio_mixer, + msm_routing_put_audio_mixer), + SOC_SINGLE_EXT("MultiMedia6", MSM_BACKEND_DAI_SECONDARY_MI2S_RX_2, + MSM_FRONTEND_DAI_MULTIMEDIA6, 1, 0, msm_routing_get_audio_mixer, + msm_routing_put_audio_mixer), + SOC_SINGLE_EXT("MultiMedia7", MSM_BACKEND_DAI_SECONDARY_MI2S_RX_2, + MSM_FRONTEND_DAI_MULTIMEDIA7, 1, 0, msm_routing_get_audio_mixer, + msm_routing_put_audio_mixer), + SOC_SINGLE_EXT("MultiMedia8", MSM_BACKEND_DAI_SECONDARY_MI2S_RX_2, + MSM_FRONTEND_DAI_MULTIMEDIA8, 1, 0, msm_routing_get_audio_mixer, + msm_routing_put_audio_mixer), + SOC_SINGLE_EXT("MultiMedia9", MSM_BACKEND_DAI_SECONDARY_MI2S_RX_2, + MSM_FRONTEND_DAI_MULTIMEDIA9, 1, 0, msm_routing_get_audio_mixer, + msm_routing_put_audio_mixer), + SOC_SINGLE_EXT("MultiMedia10", MSM_BACKEND_DAI_SECONDARY_MI2S_RX_2, + MSM_FRONTEND_DAI_MULTIMEDIA10, 1, 0, msm_routing_get_audio_mixer, + msm_routing_put_audio_mixer), + SOC_SINGLE_EXT("MultiMedia11", MSM_BACKEND_DAI_SECONDARY_MI2S_RX_2, + MSM_FRONTEND_DAI_MULTIMEDIA11, 1, 0, msm_routing_get_audio_mixer, + msm_routing_put_audio_mixer), + SOC_SINGLE_EXT("MultiMedia12", MSM_BACKEND_DAI_SECONDARY_MI2S_RX_2, + MSM_FRONTEND_DAI_MULTIMEDIA12, 1, 0, msm_routing_get_audio_mixer, + msm_routing_put_audio_mixer), + SOC_SINGLE_EXT("MultiMedia13", MSM_BACKEND_DAI_SECONDARY_MI2S_RX_2, + MSM_FRONTEND_DAI_MULTIMEDIA13, 1, 0, msm_routing_get_audio_mixer, + msm_routing_put_audio_mixer), + SOC_SINGLE_EXT("MultiMedia14", MSM_BACKEND_DAI_SECONDARY_MI2S_RX_2, + MSM_FRONTEND_DAI_MULTIMEDIA14, 1, 0, msm_routing_get_audio_mixer, + msm_routing_put_audio_mixer), + SOC_SINGLE_EXT("MultiMedia15", MSM_BACKEND_DAI_SECONDARY_MI2S_RX_2, + MSM_FRONTEND_DAI_MULTIMEDIA15, 1, 0, msm_routing_get_audio_mixer, + msm_routing_put_audio_mixer), + SOC_SINGLE_EXT("MultiMedia16", MSM_BACKEND_DAI_SECONDARY_MI2S_RX_2, + MSM_FRONTEND_DAI_MULTIMEDIA16, 1, 0, msm_routing_get_audio_mixer, + msm_routing_put_audio_mixer), + SOC_SINGLE_EXT("MultiMedia17", MSM_BACKEND_DAI_SECONDARY_MI2S_RX_2, + MSM_FRONTEND_DAI_MULTIMEDIA17, 1, 0, msm_routing_get_audio_mixer, + msm_routing_put_audio_mixer), + SOC_SINGLE_EXT("MultiMedia18", MSM_BACKEND_DAI_SECONDARY_MI2S_RX_2, + MSM_FRONTEND_DAI_MULTIMEDIA18, 1, 0, msm_routing_get_audio_mixer, + msm_routing_put_audio_mixer), + SOC_SINGLE_EXT("MultiMedia19", MSM_BACKEND_DAI_SECONDARY_MI2S_RX_2, + MSM_FRONTEND_DAI_MULTIMEDIA19, 1, 0, msm_routing_get_audio_mixer, + msm_routing_put_audio_mixer), + SOC_SINGLE_EXT("MultiMedia26", MSM_BACKEND_DAI_SECONDARY_MI2S_RX_2, + MSM_FRONTEND_DAI_MULTIMEDIA26, 1, 0, msm_routing_get_audio_mixer, + msm_routing_put_audio_mixer), + SOC_SINGLE_EXT("MultiMedia28", MSM_BACKEND_DAI_SECONDARY_MI2S_RX_2, + MSM_FRONTEND_DAI_MULTIMEDIA28, 1, 0, msm_routing_get_audio_mixer, + msm_routing_put_audio_mixer), + SOC_SINGLE_EXT("MultiMedia29", MSM_BACKEND_DAI_SECONDARY_MI2S_RX_2, + MSM_FRONTEND_DAI_MULTIMEDIA29, 1, 0, msm_routing_get_audio_mixer, + msm_routing_put_audio_mixer), +}; + +static const struct snd_kcontrol_new secondary_mi2s_rx_3_mixer_controls[] = { + SOC_SINGLE_EXT("MultiMedia1", MSM_BACKEND_DAI_SECONDARY_MI2S_RX_3, + MSM_FRONTEND_DAI_MULTIMEDIA1, 1, 0, msm_routing_get_audio_mixer, + msm_routing_put_audio_mixer), + SOC_SINGLE_EXT("MultiMedia2", MSM_BACKEND_DAI_SECONDARY_MI2S_RX_3, + MSM_FRONTEND_DAI_MULTIMEDIA2, 1, 0, msm_routing_get_audio_mixer, + msm_routing_put_audio_mixer), + SOC_SINGLE_EXT("MultiMedia3", MSM_BACKEND_DAI_SECONDARY_MI2S_RX_3, + MSM_FRONTEND_DAI_MULTIMEDIA3, 1, 0, msm_routing_get_audio_mixer, + msm_routing_put_audio_mixer), + SOC_SINGLE_EXT("MultiMedia4", MSM_BACKEND_DAI_SECONDARY_MI2S_RX_3, + MSM_FRONTEND_DAI_MULTIMEDIA4, 1, 0, msm_routing_get_audio_mixer, + msm_routing_put_audio_mixer), + SOC_SINGLE_EXT("MultiMedia5", MSM_BACKEND_DAI_SECONDARY_MI2S_RX_3, + MSM_FRONTEND_DAI_MULTIMEDIA5, 1, 0, msm_routing_get_audio_mixer, + msm_routing_put_audio_mixer), + SOC_SINGLE_EXT("MultiMedia6", MSM_BACKEND_DAI_SECONDARY_MI2S_RX_3, + MSM_FRONTEND_DAI_MULTIMEDIA6, 1, 0, msm_routing_get_audio_mixer, + msm_routing_put_audio_mixer), + SOC_SINGLE_EXT("MultiMedia7", MSM_BACKEND_DAI_SECONDARY_MI2S_RX_3, + MSM_FRONTEND_DAI_MULTIMEDIA7, 1, 0, msm_routing_get_audio_mixer, + msm_routing_put_audio_mixer), + SOC_SINGLE_EXT("MultiMedia8", MSM_BACKEND_DAI_SECONDARY_MI2S_RX_3, + MSM_FRONTEND_DAI_MULTIMEDIA8, 1, 0, msm_routing_get_audio_mixer, + msm_routing_put_audio_mixer), + SOC_SINGLE_EXT("MultiMedia9", MSM_BACKEND_DAI_SECONDARY_MI2S_RX_3, + MSM_FRONTEND_DAI_MULTIMEDIA9, 1, 0, msm_routing_get_audio_mixer, + msm_routing_put_audio_mixer), + SOC_SINGLE_EXT("MultiMedia10", MSM_BACKEND_DAI_SECONDARY_MI2S_RX_3, + MSM_FRONTEND_DAI_MULTIMEDIA10, 1, 0, msm_routing_get_audio_mixer, + msm_routing_put_audio_mixer), + SOC_SINGLE_EXT("MultiMedia11", MSM_BACKEND_DAI_SECONDARY_MI2S_RX_3, + MSM_FRONTEND_DAI_MULTIMEDIA11, 1, 0, msm_routing_get_audio_mixer, + msm_routing_put_audio_mixer), + SOC_SINGLE_EXT("MultiMedia12", MSM_BACKEND_DAI_SECONDARY_MI2S_RX_3, + MSM_FRONTEND_DAI_MULTIMEDIA12, 1, 0, msm_routing_get_audio_mixer, + msm_routing_put_audio_mixer), + SOC_SINGLE_EXT("MultiMedia13", MSM_BACKEND_DAI_SECONDARY_MI2S_RX_3, + MSM_FRONTEND_DAI_MULTIMEDIA13, 1, 0, msm_routing_get_audio_mixer, + msm_routing_put_audio_mixer), + SOC_SINGLE_EXT("MultiMedia14", MSM_BACKEND_DAI_SECONDARY_MI2S_RX_3, + MSM_FRONTEND_DAI_MULTIMEDIA14, 1, 0, msm_routing_get_audio_mixer, + msm_routing_put_audio_mixer), + SOC_SINGLE_EXT("MultiMedia15", MSM_BACKEND_DAI_SECONDARY_MI2S_RX_3, + MSM_FRONTEND_DAI_MULTIMEDIA15, 1, 0, msm_routing_get_audio_mixer, + msm_routing_put_audio_mixer), + SOC_SINGLE_EXT("MultiMedia16", MSM_BACKEND_DAI_SECONDARY_MI2S_RX_3, + MSM_FRONTEND_DAI_MULTIMEDIA16, 1, 0, msm_routing_get_audio_mixer, + msm_routing_put_audio_mixer), + SOC_SINGLE_EXT("MultiMedia17", MSM_BACKEND_DAI_SECONDARY_MI2S_RX_3, + MSM_FRONTEND_DAI_MULTIMEDIA17, 1, 0, msm_routing_get_audio_mixer, + msm_routing_put_audio_mixer), + SOC_SINGLE_EXT("MultiMedia18", MSM_BACKEND_DAI_SECONDARY_MI2S_RX_3, + MSM_FRONTEND_DAI_MULTIMEDIA18, 1, 0, msm_routing_get_audio_mixer, + msm_routing_put_audio_mixer), + SOC_SINGLE_EXT("MultiMedia19", MSM_BACKEND_DAI_SECONDARY_MI2S_RX_3, + MSM_FRONTEND_DAI_MULTIMEDIA19, 1, 0, msm_routing_get_audio_mixer, + msm_routing_put_audio_mixer), + SOC_SINGLE_EXT("MultiMedia26", MSM_BACKEND_DAI_SECONDARY_MI2S_RX_3, + MSM_FRONTEND_DAI_MULTIMEDIA26, 1, 0, msm_routing_get_audio_mixer, + msm_routing_put_audio_mixer), + SOC_SINGLE_EXT("MultiMedia28", MSM_BACKEND_DAI_SECONDARY_MI2S_RX_3, + MSM_FRONTEND_DAI_MULTIMEDIA28, 1, 0, msm_routing_get_audio_mixer, + msm_routing_put_audio_mixer), + SOC_SINGLE_EXT("MultiMedia29", MSM_BACKEND_DAI_SECONDARY_MI2S_RX_3, + MSM_FRONTEND_DAI_MULTIMEDIA29, 1, 0, msm_routing_get_audio_mixer, + msm_routing_put_audio_mixer), +}; + +static const struct snd_kcontrol_new secondary_mi2s_rx_4_mixer_controls[] = { + SOC_SINGLE_EXT("MultiMedia1", MSM_BACKEND_DAI_SECONDARY_MI2S_RX_4, + MSM_FRONTEND_DAI_MULTIMEDIA1, 1, 0, msm_routing_get_audio_mixer, + msm_routing_put_audio_mixer), + SOC_SINGLE_EXT("MultiMedia2", MSM_BACKEND_DAI_SECONDARY_MI2S_RX_4, + MSM_FRONTEND_DAI_MULTIMEDIA2, 1, 0, msm_routing_get_audio_mixer, + msm_routing_put_audio_mixer), + SOC_SINGLE_EXT("MultiMedia3", MSM_BACKEND_DAI_SECONDARY_MI2S_RX_4, + MSM_FRONTEND_DAI_MULTIMEDIA3, 1, 0, msm_routing_get_audio_mixer, + msm_routing_put_audio_mixer), + SOC_SINGLE_EXT("MultiMedia4", MSM_BACKEND_DAI_SECONDARY_MI2S_RX_4, + MSM_FRONTEND_DAI_MULTIMEDIA4, 1, 0, msm_routing_get_audio_mixer, + msm_routing_put_audio_mixer), + SOC_SINGLE_EXT("MultiMedia5", MSM_BACKEND_DAI_SECONDARY_MI2S_RX_4, + MSM_FRONTEND_DAI_MULTIMEDIA5, 1, 0, msm_routing_get_audio_mixer, + msm_routing_put_audio_mixer), + SOC_SINGLE_EXT("MultiMedia6", MSM_BACKEND_DAI_SECONDARY_MI2S_RX_4, + MSM_FRONTEND_DAI_MULTIMEDIA6, 1, 0, msm_routing_get_audio_mixer, + msm_routing_put_audio_mixer), + SOC_SINGLE_EXT("MultiMedia7", MSM_BACKEND_DAI_SECONDARY_MI2S_RX_4, + MSM_FRONTEND_DAI_MULTIMEDIA7, 1, 0, msm_routing_get_audio_mixer, + msm_routing_put_audio_mixer), + SOC_SINGLE_EXT("MultiMedia8", MSM_BACKEND_DAI_SECONDARY_MI2S_RX_4, + MSM_FRONTEND_DAI_MULTIMEDIA8, 1, 0, msm_routing_get_audio_mixer, + msm_routing_put_audio_mixer), + SOC_SINGLE_EXT("MultiMedia9", MSM_BACKEND_DAI_SECONDARY_MI2S_RX_4, + MSM_FRONTEND_DAI_MULTIMEDIA9, 1, 0, msm_routing_get_audio_mixer, + msm_routing_put_audio_mixer), + SOC_SINGLE_EXT("MultiMedia10", MSM_BACKEND_DAI_SECONDARY_MI2S_RX_4, + MSM_FRONTEND_DAI_MULTIMEDIA10, 1, 0, msm_routing_get_audio_mixer, + msm_routing_put_audio_mixer), + SOC_SINGLE_EXT("MultiMedia11", MSM_BACKEND_DAI_SECONDARY_MI2S_RX_4, + MSM_FRONTEND_DAI_MULTIMEDIA11, 1, 0, msm_routing_get_audio_mixer, + msm_routing_put_audio_mixer), + SOC_SINGLE_EXT("MultiMedia12", MSM_BACKEND_DAI_SECONDARY_MI2S_RX_4, + MSM_FRONTEND_DAI_MULTIMEDIA12, 1, 0, msm_routing_get_audio_mixer, + msm_routing_put_audio_mixer), + SOC_SINGLE_EXT("MultiMedia13", MSM_BACKEND_DAI_SECONDARY_MI2S_RX_4, + MSM_FRONTEND_DAI_MULTIMEDIA13, 1, 0, msm_routing_get_audio_mixer, + msm_routing_put_audio_mixer), + SOC_SINGLE_EXT("MultiMedia14", MSM_BACKEND_DAI_SECONDARY_MI2S_RX_4, + MSM_FRONTEND_DAI_MULTIMEDIA14, 1, 0, msm_routing_get_audio_mixer, + msm_routing_put_audio_mixer), + SOC_SINGLE_EXT("MultiMedia15", MSM_BACKEND_DAI_SECONDARY_MI2S_RX_4, + MSM_FRONTEND_DAI_MULTIMEDIA15, 1, 0, msm_routing_get_audio_mixer, + msm_routing_put_audio_mixer), + SOC_SINGLE_EXT("MultiMedia16", MSM_BACKEND_DAI_SECONDARY_MI2S_RX_4, + MSM_FRONTEND_DAI_MULTIMEDIA16, 1, 0, msm_routing_get_audio_mixer, + msm_routing_put_audio_mixer), + SOC_SINGLE_EXT("MultiMedia17", MSM_BACKEND_DAI_SECONDARY_MI2S_RX_4, + MSM_FRONTEND_DAI_MULTIMEDIA17, 1, 0, msm_routing_get_audio_mixer, + msm_routing_put_audio_mixer), + SOC_SINGLE_EXT("MultiMedia18", MSM_BACKEND_DAI_SECONDARY_MI2S_RX_4, + MSM_FRONTEND_DAI_MULTIMEDIA18, 1, 0, msm_routing_get_audio_mixer, + msm_routing_put_audio_mixer), + SOC_SINGLE_EXT("MultiMedia19", MSM_BACKEND_DAI_SECONDARY_MI2S_RX_4, + MSM_FRONTEND_DAI_MULTIMEDIA19, 1, 0, msm_routing_get_audio_mixer, + msm_routing_put_audio_mixer), + SOC_SINGLE_EXT("MultiMedia26", MSM_BACKEND_DAI_SECONDARY_MI2S_RX_4, + MSM_FRONTEND_DAI_MULTIMEDIA26, 1, 0, msm_routing_get_audio_mixer, + msm_routing_put_audio_mixer), + SOC_SINGLE_EXT("MultiMedia28", MSM_BACKEND_DAI_SECONDARY_MI2S_RX_4, + MSM_FRONTEND_DAI_MULTIMEDIA28, 1, 0, msm_routing_get_audio_mixer, + msm_routing_put_audio_mixer), + SOC_SINGLE_EXT("MultiMedia29", MSM_BACKEND_DAI_SECONDARY_MI2S_RX_4, + MSM_FRONTEND_DAI_MULTIMEDIA29, 1, 0, msm_routing_get_audio_mixer, + msm_routing_put_audio_mixer), +}; + +static const struct snd_kcontrol_new tertiary_mi2s_rx_1_mixer_controls[] = { + SOC_SINGLE_EXT("MultiMedia1", MSM_BACKEND_DAI_TERTIARY_MI2S_RX_1, + MSM_FRONTEND_DAI_MULTIMEDIA1, 1, 0, msm_routing_get_audio_mixer, + msm_routing_put_audio_mixer), + SOC_SINGLE_EXT("MultiMedia2", MSM_BACKEND_DAI_TERTIARY_MI2S_RX_1, + MSM_FRONTEND_DAI_MULTIMEDIA2, 1, 0, msm_routing_get_audio_mixer, + msm_routing_put_audio_mixer), + SOC_SINGLE_EXT("MultiMedia3", MSM_BACKEND_DAI_TERTIARY_MI2S_RX_1, + MSM_FRONTEND_DAI_MULTIMEDIA3, 1, 0, msm_routing_get_audio_mixer, + msm_routing_put_audio_mixer), + SOC_SINGLE_EXT("MultiMedia4", MSM_BACKEND_DAI_TERTIARY_MI2S_RX_1, + MSM_FRONTEND_DAI_MULTIMEDIA4, 1, 0, msm_routing_get_audio_mixer, + msm_routing_put_audio_mixer), + SOC_SINGLE_EXT("MultiMedia5", MSM_BACKEND_DAI_TERTIARY_MI2S_RX_1, + MSM_FRONTEND_DAI_MULTIMEDIA5, 1, 0, msm_routing_get_audio_mixer, + msm_routing_put_audio_mixer), + SOC_SINGLE_EXT("MultiMedia6", MSM_BACKEND_DAI_TERTIARY_MI2S_RX_1, + MSM_FRONTEND_DAI_MULTIMEDIA6, 1, 0, msm_routing_get_audio_mixer, + msm_routing_put_audio_mixer), + SOC_SINGLE_EXT("MultiMedia7", MSM_BACKEND_DAI_TERTIARY_MI2S_RX_1, + MSM_FRONTEND_DAI_MULTIMEDIA7, 1, 0, msm_routing_get_audio_mixer, + msm_routing_put_audio_mixer), + SOC_SINGLE_EXT("MultiMedia8", MSM_BACKEND_DAI_TERTIARY_MI2S_RX_1, + MSM_FRONTEND_DAI_MULTIMEDIA8, 1, 0, msm_routing_get_audio_mixer, + msm_routing_put_audio_mixer), + SOC_SINGLE_EXT("MultiMedia9", MSM_BACKEND_DAI_TERTIARY_MI2S_RX_1, + MSM_FRONTEND_DAI_MULTIMEDIA9, 1, 0, msm_routing_get_audio_mixer, + msm_routing_put_audio_mixer), + SOC_SINGLE_EXT("MultiMedia10", MSM_BACKEND_DAI_TERTIARY_MI2S_RX_1, + MSM_FRONTEND_DAI_MULTIMEDIA10, 1, 0, msm_routing_get_audio_mixer, + msm_routing_put_audio_mixer), + SOC_SINGLE_EXT("MultiMedia11", MSM_BACKEND_DAI_TERTIARY_MI2S_RX_1, + MSM_FRONTEND_DAI_MULTIMEDIA11, 1, 0, msm_routing_get_audio_mixer, + msm_routing_put_audio_mixer), + SOC_SINGLE_EXT("MultiMedia12", MSM_BACKEND_DAI_TERTIARY_MI2S_RX_1, + MSM_FRONTEND_DAI_MULTIMEDIA12, 1, 0, msm_routing_get_audio_mixer, + msm_routing_put_audio_mixer), + SOC_SINGLE_EXT("MultiMedia13", MSM_BACKEND_DAI_TERTIARY_MI2S_RX_1, + MSM_FRONTEND_DAI_MULTIMEDIA13, 1, 0, msm_routing_get_audio_mixer, + msm_routing_put_audio_mixer), + SOC_SINGLE_EXT("MultiMedia14", MSM_BACKEND_DAI_TERTIARY_MI2S_RX_1, + MSM_FRONTEND_DAI_MULTIMEDIA14, 1, 0, msm_routing_get_audio_mixer, + msm_routing_put_audio_mixer), + SOC_SINGLE_EXT("MultiMedia15", MSM_BACKEND_DAI_TERTIARY_MI2S_RX_1, + MSM_FRONTEND_DAI_MULTIMEDIA15, 1, 0, msm_routing_get_audio_mixer, + msm_routing_put_audio_mixer), + SOC_SINGLE_EXT("MultiMedia16", MSM_BACKEND_DAI_TERTIARY_MI2S_RX_1, + MSM_FRONTEND_DAI_MULTIMEDIA16, 1, 0, msm_routing_get_audio_mixer, + msm_routing_put_audio_mixer), + SOC_SINGLE_EXT("MultiMedia17", MSM_BACKEND_DAI_TERTIARY_MI2S_RX_1, + MSM_FRONTEND_DAI_MULTIMEDIA17, 1, 0, msm_routing_get_audio_mixer, + msm_routing_put_audio_mixer), + SOC_SINGLE_EXT("MultiMedia18", MSM_BACKEND_DAI_TERTIARY_MI2S_RX_1, + MSM_FRONTEND_DAI_MULTIMEDIA18, 1, 0, msm_routing_get_audio_mixer, + msm_routing_put_audio_mixer), + SOC_SINGLE_EXT("MultiMedia19", MSM_BACKEND_DAI_TERTIARY_MI2S_RX_1, + MSM_FRONTEND_DAI_MULTIMEDIA19, 1, 0, msm_routing_get_audio_mixer, + msm_routing_put_audio_mixer), + SOC_SINGLE_EXT("MultiMedia26", MSM_BACKEND_DAI_TERTIARY_MI2S_RX_1, + MSM_FRONTEND_DAI_MULTIMEDIA26, 1, 0, msm_routing_get_audio_mixer, + msm_routing_put_audio_mixer), + SOC_SINGLE_EXT("MultiMedia28", MSM_BACKEND_DAI_TERTIARY_MI2S_RX_1, + MSM_FRONTEND_DAI_MULTIMEDIA28, 1, 0, msm_routing_get_audio_mixer, + msm_routing_put_audio_mixer), + SOC_SINGLE_EXT("MultiMedia29", MSM_BACKEND_DAI_TERTIARY_MI2S_RX_1, + MSM_FRONTEND_DAI_MULTIMEDIA29, 1, 0, msm_routing_get_audio_mixer, + msm_routing_put_audio_mixer), +}; + +static const struct snd_kcontrol_new tertiary_mi2s_rx_2_mixer_controls[] = { + SOC_SINGLE_EXT("MultiMedia1", MSM_BACKEND_DAI_TERTIARY_MI2S_RX_2, + MSM_FRONTEND_DAI_MULTIMEDIA1, 1, 0, msm_routing_get_audio_mixer, + msm_routing_put_audio_mixer), + SOC_SINGLE_EXT("MultiMedia2", MSM_BACKEND_DAI_TERTIARY_MI2S_RX_2, + MSM_FRONTEND_DAI_MULTIMEDIA2, 1, 0, msm_routing_get_audio_mixer, + msm_routing_put_audio_mixer), + SOC_SINGLE_EXT("MultiMedia3", MSM_BACKEND_DAI_TERTIARY_MI2S_RX_2, + MSM_FRONTEND_DAI_MULTIMEDIA3, 1, 0, msm_routing_get_audio_mixer, + msm_routing_put_audio_mixer), + SOC_SINGLE_EXT("MultiMedia4", MSM_BACKEND_DAI_TERTIARY_MI2S_RX_2, + MSM_FRONTEND_DAI_MULTIMEDIA4, 1, 0, msm_routing_get_audio_mixer, + msm_routing_put_audio_mixer), + SOC_SINGLE_EXT("MultiMedia5", MSM_BACKEND_DAI_TERTIARY_MI2S_RX_2, + MSM_FRONTEND_DAI_MULTIMEDIA5, 1, 0, msm_routing_get_audio_mixer, + msm_routing_put_audio_mixer), + SOC_SINGLE_EXT("MultiMedia6", MSM_BACKEND_DAI_TERTIARY_MI2S_RX_2, + MSM_FRONTEND_DAI_MULTIMEDIA6, 1, 0, msm_routing_get_audio_mixer, + msm_routing_put_audio_mixer), + SOC_SINGLE_EXT("MultiMedia7", MSM_BACKEND_DAI_TERTIARY_MI2S_RX_2, + MSM_FRONTEND_DAI_MULTIMEDIA7, 1, 0, msm_routing_get_audio_mixer, + msm_routing_put_audio_mixer), + SOC_SINGLE_EXT("MultiMedia8", MSM_BACKEND_DAI_TERTIARY_MI2S_RX_2, + MSM_FRONTEND_DAI_MULTIMEDIA8, 1, 0, msm_routing_get_audio_mixer, + msm_routing_put_audio_mixer), + SOC_SINGLE_EXT("MultiMedia9", MSM_BACKEND_DAI_TERTIARY_MI2S_RX_2, + MSM_FRONTEND_DAI_MULTIMEDIA9, 1, 0, msm_routing_get_audio_mixer, + msm_routing_put_audio_mixer), + SOC_SINGLE_EXT("MultiMedia10", MSM_BACKEND_DAI_TERTIARY_MI2S_RX_2, + MSM_FRONTEND_DAI_MULTIMEDIA10, 1, 0, msm_routing_get_audio_mixer, + msm_routing_put_audio_mixer), + SOC_SINGLE_EXT("MultiMedia11", MSM_BACKEND_DAI_TERTIARY_MI2S_RX_2, + MSM_FRONTEND_DAI_MULTIMEDIA11, 1, 0, msm_routing_get_audio_mixer, + msm_routing_put_audio_mixer), + SOC_SINGLE_EXT("MultiMedia12", MSM_BACKEND_DAI_TERTIARY_MI2S_RX_2, + MSM_FRONTEND_DAI_MULTIMEDIA12, 1, 0, msm_routing_get_audio_mixer, + msm_routing_put_audio_mixer), + SOC_SINGLE_EXT("MultiMedia13", MSM_BACKEND_DAI_TERTIARY_MI2S_RX_2, + MSM_FRONTEND_DAI_MULTIMEDIA13, 1, 0, msm_routing_get_audio_mixer, + msm_routing_put_audio_mixer), + SOC_SINGLE_EXT("MultiMedia14", MSM_BACKEND_DAI_TERTIARY_MI2S_RX_2, + MSM_FRONTEND_DAI_MULTIMEDIA14, 1, 0, msm_routing_get_audio_mixer, + msm_routing_put_audio_mixer), + SOC_SINGLE_EXT("MultiMedia15", MSM_BACKEND_DAI_TERTIARY_MI2S_RX_2, + MSM_FRONTEND_DAI_MULTIMEDIA15, 1, 0, msm_routing_get_audio_mixer, + msm_routing_put_audio_mixer), + SOC_SINGLE_EXT("MultiMedia16", MSM_BACKEND_DAI_TERTIARY_MI2S_RX_2, + MSM_FRONTEND_DAI_MULTIMEDIA16, 1, 0, msm_routing_get_audio_mixer, + msm_routing_put_audio_mixer), + SOC_SINGLE_EXT("MultiMedia17", MSM_BACKEND_DAI_TERTIARY_MI2S_RX_2, + MSM_FRONTEND_DAI_MULTIMEDIA17, 1, 0, msm_routing_get_audio_mixer, + msm_routing_put_audio_mixer), + SOC_SINGLE_EXT("MultiMedia18", MSM_BACKEND_DAI_TERTIARY_MI2S_RX_2, + MSM_FRONTEND_DAI_MULTIMEDIA18, 1, 0, msm_routing_get_audio_mixer, + msm_routing_put_audio_mixer), + SOC_SINGLE_EXT("MultiMedia19", MSM_BACKEND_DAI_TERTIARY_MI2S_RX_2, + MSM_FRONTEND_DAI_MULTIMEDIA19, 1, 0, msm_routing_get_audio_mixer, + msm_routing_put_audio_mixer), + SOC_SINGLE_EXT("MultiMedia26", MSM_BACKEND_DAI_TERTIARY_MI2S_RX_2, + MSM_FRONTEND_DAI_MULTIMEDIA26, 1, 0, msm_routing_get_audio_mixer, + msm_routing_put_audio_mixer), + SOC_SINGLE_EXT("MultiMedia28", MSM_BACKEND_DAI_TERTIARY_MI2S_RX_2, + MSM_FRONTEND_DAI_MULTIMEDIA28, 1, 0, msm_routing_get_audio_mixer, + msm_routing_put_audio_mixer), + SOC_SINGLE_EXT("MultiMedia29", MSM_BACKEND_DAI_TERTIARY_MI2S_RX_2, + MSM_FRONTEND_DAI_MULTIMEDIA29, 1, 0, msm_routing_get_audio_mixer, + msm_routing_put_audio_mixer), +}; + +static const struct snd_kcontrol_new tertiary_mi2s_rx_3_mixer_controls[] = { + SOC_SINGLE_EXT("MultiMedia1", MSM_BACKEND_DAI_TERTIARY_MI2S_RX_3, + MSM_FRONTEND_DAI_MULTIMEDIA1, 1, 0, msm_routing_get_audio_mixer, + msm_routing_put_audio_mixer), + SOC_SINGLE_EXT("MultiMedia2", MSM_BACKEND_DAI_TERTIARY_MI2S_RX_3, + MSM_FRONTEND_DAI_MULTIMEDIA2, 1, 0, msm_routing_get_audio_mixer, + msm_routing_put_audio_mixer), + SOC_SINGLE_EXT("MultiMedia3", MSM_BACKEND_DAI_TERTIARY_MI2S_RX_3, + MSM_FRONTEND_DAI_MULTIMEDIA3, 1, 0, msm_routing_get_audio_mixer, + msm_routing_put_audio_mixer), + SOC_SINGLE_EXT("MultiMedia4", MSM_BACKEND_DAI_TERTIARY_MI2S_RX_3, + MSM_FRONTEND_DAI_MULTIMEDIA4, 1, 0, msm_routing_get_audio_mixer, + msm_routing_put_audio_mixer), + SOC_SINGLE_EXT("MultiMedia5", MSM_BACKEND_DAI_TERTIARY_MI2S_RX_3, + MSM_FRONTEND_DAI_MULTIMEDIA5, 1, 0, msm_routing_get_audio_mixer, + msm_routing_put_audio_mixer), + SOC_SINGLE_EXT("MultiMedia6", MSM_BACKEND_DAI_TERTIARY_MI2S_RX_3, + MSM_FRONTEND_DAI_MULTIMEDIA6, 1, 0, msm_routing_get_audio_mixer, + msm_routing_put_audio_mixer), + SOC_SINGLE_EXT("MultiMedia7", MSM_BACKEND_DAI_TERTIARY_MI2S_RX_3, + MSM_FRONTEND_DAI_MULTIMEDIA7, 1, 0, msm_routing_get_audio_mixer, + msm_routing_put_audio_mixer), + SOC_SINGLE_EXT("MultiMedia8", MSM_BACKEND_DAI_TERTIARY_MI2S_RX_3, + MSM_FRONTEND_DAI_MULTIMEDIA8, 1, 0, msm_routing_get_audio_mixer, + msm_routing_put_audio_mixer), + SOC_SINGLE_EXT("MultiMedia9", MSM_BACKEND_DAI_TERTIARY_MI2S_RX_3, + MSM_FRONTEND_DAI_MULTIMEDIA9, 1, 0, msm_routing_get_audio_mixer, + msm_routing_put_audio_mixer), + SOC_SINGLE_EXT("MultiMedia10", MSM_BACKEND_DAI_TERTIARY_MI2S_RX_3, + MSM_FRONTEND_DAI_MULTIMEDIA10, 1, 0, msm_routing_get_audio_mixer, + msm_routing_put_audio_mixer), + SOC_SINGLE_EXT("MultiMedia11", MSM_BACKEND_DAI_TERTIARY_MI2S_RX_3, + MSM_FRONTEND_DAI_MULTIMEDIA11, 1, 0, msm_routing_get_audio_mixer, + msm_routing_put_audio_mixer), + SOC_SINGLE_EXT("MultiMedia12", MSM_BACKEND_DAI_TERTIARY_MI2S_RX_3, + MSM_FRONTEND_DAI_MULTIMEDIA12, 1, 0, msm_routing_get_audio_mixer, + msm_routing_put_audio_mixer), + SOC_SINGLE_EXT("MultiMedia13", MSM_BACKEND_DAI_TERTIARY_MI2S_RX_3, + MSM_FRONTEND_DAI_MULTIMEDIA13, 1, 0, msm_routing_get_audio_mixer, + msm_routing_put_audio_mixer), + SOC_SINGLE_EXT("MultiMedia14", MSM_BACKEND_DAI_TERTIARY_MI2S_RX_3, + MSM_FRONTEND_DAI_MULTIMEDIA14, 1, 0, msm_routing_get_audio_mixer, + msm_routing_put_audio_mixer), + SOC_SINGLE_EXT("MultiMedia15", MSM_BACKEND_DAI_TERTIARY_MI2S_RX_3, + MSM_FRONTEND_DAI_MULTIMEDIA15, 1, 0, msm_routing_get_audio_mixer, + msm_routing_put_audio_mixer), + SOC_SINGLE_EXT("MultiMedia16", MSM_BACKEND_DAI_TERTIARY_MI2S_RX_3, + MSM_FRONTEND_DAI_MULTIMEDIA16, 1, 0, msm_routing_get_audio_mixer, + msm_routing_put_audio_mixer), + SOC_SINGLE_EXT("MultiMedia17", MSM_BACKEND_DAI_TERTIARY_MI2S_RX_3, + MSM_FRONTEND_DAI_MULTIMEDIA17, 1, 0, msm_routing_get_audio_mixer, + msm_routing_put_audio_mixer), + SOC_SINGLE_EXT("MultiMedia18", MSM_BACKEND_DAI_TERTIARY_MI2S_RX_3, + MSM_FRONTEND_DAI_MULTIMEDIA18, 1, 0, msm_routing_get_audio_mixer, + msm_routing_put_audio_mixer), + SOC_SINGLE_EXT("MultiMedia19", MSM_BACKEND_DAI_TERTIARY_MI2S_RX_3, + MSM_FRONTEND_DAI_MULTIMEDIA19, 1, 0, msm_routing_get_audio_mixer, + msm_routing_put_audio_mixer), + SOC_SINGLE_EXT("MultiMedia26", MSM_BACKEND_DAI_TERTIARY_MI2S_RX_3, + MSM_FRONTEND_DAI_MULTIMEDIA26, 1, 0, msm_routing_get_audio_mixer, + msm_routing_put_audio_mixer), + SOC_SINGLE_EXT("MultiMedia28", MSM_BACKEND_DAI_TERTIARY_MI2S_RX_3, + MSM_FRONTEND_DAI_MULTIMEDIA28, 1, 0, msm_routing_get_audio_mixer, + msm_routing_put_audio_mixer), + SOC_SINGLE_EXT("MultiMedia29", MSM_BACKEND_DAI_TERTIARY_MI2S_RX_3, + MSM_FRONTEND_DAI_MULTIMEDIA29, 1, 0, msm_routing_get_audio_mixer, + msm_routing_put_audio_mixer), +}; + +static const struct snd_kcontrol_new tertiary_mi2s_rx_4_mixer_controls[] = { + SOC_SINGLE_EXT("MultiMedia1", MSM_BACKEND_DAI_TERTIARY_MI2S_RX_4, + MSM_FRONTEND_DAI_MULTIMEDIA1, 1, 0, msm_routing_get_audio_mixer, + msm_routing_put_audio_mixer), + SOC_SINGLE_EXT("MultiMedia2", MSM_BACKEND_DAI_TERTIARY_MI2S_RX_4, + MSM_FRONTEND_DAI_MULTIMEDIA2, 1, 0, msm_routing_get_audio_mixer, + msm_routing_put_audio_mixer), + SOC_SINGLE_EXT("MultiMedia3", MSM_BACKEND_DAI_TERTIARY_MI2S_RX_4, + MSM_FRONTEND_DAI_MULTIMEDIA3, 1, 0, msm_routing_get_audio_mixer, + msm_routing_put_audio_mixer), + SOC_SINGLE_EXT("MultiMedia4", MSM_BACKEND_DAI_TERTIARY_MI2S_RX_4, + MSM_FRONTEND_DAI_MULTIMEDIA4, 1, 0, msm_routing_get_audio_mixer, + msm_routing_put_audio_mixer), + SOC_SINGLE_EXT("MultiMedia5", MSM_BACKEND_DAI_TERTIARY_MI2S_RX_4, + MSM_FRONTEND_DAI_MULTIMEDIA5, 1, 0, msm_routing_get_audio_mixer, + msm_routing_put_audio_mixer), + SOC_SINGLE_EXT("MultiMedia6", MSM_BACKEND_DAI_TERTIARY_MI2S_RX_4, + MSM_FRONTEND_DAI_MULTIMEDIA6, 1, 0, msm_routing_get_audio_mixer, + msm_routing_put_audio_mixer), + SOC_SINGLE_EXT("MultiMedia7", MSM_BACKEND_DAI_TERTIARY_MI2S_RX_4, + MSM_FRONTEND_DAI_MULTIMEDIA7, 1, 0, msm_routing_get_audio_mixer, + msm_routing_put_audio_mixer), + SOC_SINGLE_EXT("MultiMedia8", MSM_BACKEND_DAI_TERTIARY_MI2S_RX_4, + MSM_FRONTEND_DAI_MULTIMEDIA8, 1, 0, msm_routing_get_audio_mixer, + msm_routing_put_audio_mixer), + SOC_SINGLE_EXT("MultiMedia9", MSM_BACKEND_DAI_TERTIARY_MI2S_RX_4, + MSM_FRONTEND_DAI_MULTIMEDIA9, 1, 0, msm_routing_get_audio_mixer, + msm_routing_put_audio_mixer), + SOC_SINGLE_EXT("MultiMedia10", MSM_BACKEND_DAI_TERTIARY_MI2S_RX_4, + MSM_FRONTEND_DAI_MULTIMEDIA10, 1, 0, msm_routing_get_audio_mixer, + msm_routing_put_audio_mixer), + SOC_SINGLE_EXT("MultiMedia11", MSM_BACKEND_DAI_TERTIARY_MI2S_RX_4, + MSM_FRONTEND_DAI_MULTIMEDIA11, 1, 0, msm_routing_get_audio_mixer, + msm_routing_put_audio_mixer), + SOC_SINGLE_EXT("MultiMedia12", MSM_BACKEND_DAI_TERTIARY_MI2S_RX_4, + MSM_FRONTEND_DAI_MULTIMEDIA12, 1, 0, msm_routing_get_audio_mixer, + msm_routing_put_audio_mixer), + SOC_SINGLE_EXT("MultiMedia13", MSM_BACKEND_DAI_TERTIARY_MI2S_RX_4, + MSM_FRONTEND_DAI_MULTIMEDIA13, 1, 0, msm_routing_get_audio_mixer, + msm_routing_put_audio_mixer), + SOC_SINGLE_EXT("MultiMedia14", MSM_BACKEND_DAI_TERTIARY_MI2S_RX_4, + MSM_FRONTEND_DAI_MULTIMEDIA14, 1, 0, msm_routing_get_audio_mixer, + msm_routing_put_audio_mixer), + SOC_SINGLE_EXT("MultiMedia15", MSM_BACKEND_DAI_TERTIARY_MI2S_RX_4, + MSM_FRONTEND_DAI_MULTIMEDIA15, 1, 0, msm_routing_get_audio_mixer, + msm_routing_put_audio_mixer), + SOC_SINGLE_EXT("MultiMedia16", MSM_BACKEND_DAI_TERTIARY_MI2S_RX_4, + MSM_FRONTEND_DAI_MULTIMEDIA16, 1, 0, msm_routing_get_audio_mixer, + msm_routing_put_audio_mixer), + SOC_SINGLE_EXT("MultiMedia17", MSM_BACKEND_DAI_TERTIARY_MI2S_RX_4, + MSM_FRONTEND_DAI_MULTIMEDIA17, 1, 0, msm_routing_get_audio_mixer, + msm_routing_put_audio_mixer), + SOC_SINGLE_EXT("MultiMedia18", MSM_BACKEND_DAI_TERTIARY_MI2S_RX_4, + MSM_FRONTEND_DAI_MULTIMEDIA18, 1, 0, msm_routing_get_audio_mixer, + msm_routing_put_audio_mixer), + SOC_SINGLE_EXT("MultiMedia19", MSM_BACKEND_DAI_TERTIARY_MI2S_RX_4, + MSM_FRONTEND_DAI_MULTIMEDIA19, 1, 0, msm_routing_get_audio_mixer, + msm_routing_put_audio_mixer), + SOC_SINGLE_EXT("MultiMedia26", MSM_BACKEND_DAI_TERTIARY_MI2S_RX_4, + MSM_FRONTEND_DAI_MULTIMEDIA26, 1, 0, msm_routing_get_audio_mixer, + msm_routing_put_audio_mixer), + SOC_SINGLE_EXT("MultiMedia28", MSM_BACKEND_DAI_TERTIARY_MI2S_RX_4, + MSM_FRONTEND_DAI_MULTIMEDIA28, 1, 0, msm_routing_get_audio_mixer, + msm_routing_put_audio_mixer), + SOC_SINGLE_EXT("MultiMedia29", MSM_BACKEND_DAI_TERTIARY_MI2S_RX_4, + MSM_FRONTEND_DAI_MULTIMEDIA29, 1, 0, msm_routing_get_audio_mixer, + msm_routing_put_audio_mixer), +}; + +static const struct snd_kcontrol_new quaternary_mi2s_rx_1_mixer_controls[] = { + SOC_SINGLE_EXT("MultiMedia1", MSM_BACKEND_DAI_QUATERNARY_MI2S_RX_1, + MSM_FRONTEND_DAI_MULTIMEDIA1, 1, 0, msm_routing_get_audio_mixer, + msm_routing_put_audio_mixer), + SOC_SINGLE_EXT("MultiMedia2", MSM_BACKEND_DAI_QUATERNARY_MI2S_RX_1, + MSM_FRONTEND_DAI_MULTIMEDIA2, 1, 0, msm_routing_get_audio_mixer, + msm_routing_put_audio_mixer), + SOC_SINGLE_EXT("MultiMedia3", MSM_BACKEND_DAI_QUATERNARY_MI2S_RX_1, + MSM_FRONTEND_DAI_MULTIMEDIA3, 1, 0, msm_routing_get_audio_mixer, + msm_routing_put_audio_mixer), + SOC_SINGLE_EXT("MultiMedia4", MSM_BACKEND_DAI_QUATERNARY_MI2S_RX_1, + MSM_FRONTEND_DAI_MULTIMEDIA4, 1, 0, msm_routing_get_audio_mixer, + msm_routing_put_audio_mixer), + SOC_SINGLE_EXT("MultiMedia5", MSM_BACKEND_DAI_QUATERNARY_MI2S_RX_1, + MSM_FRONTEND_DAI_MULTIMEDIA5, 1, 0, msm_routing_get_audio_mixer, + msm_routing_put_audio_mixer), + SOC_SINGLE_EXT("MultiMedia6", MSM_BACKEND_DAI_QUATERNARY_MI2S_RX_1, + MSM_FRONTEND_DAI_MULTIMEDIA6, 1, 0, msm_routing_get_audio_mixer, + msm_routing_put_audio_mixer), + SOC_SINGLE_EXT("MultiMedia7", MSM_BACKEND_DAI_QUATERNARY_MI2S_RX_1, + MSM_FRONTEND_DAI_MULTIMEDIA7, 1, 0, msm_routing_get_audio_mixer, + msm_routing_put_audio_mixer), + SOC_SINGLE_EXT("MultiMedia8", MSM_BACKEND_DAI_QUATERNARY_MI2S_RX_1, + MSM_FRONTEND_DAI_MULTIMEDIA8, 1, 0, msm_routing_get_audio_mixer, + msm_routing_put_audio_mixer), + SOC_SINGLE_EXT("MultiMedia9", MSM_BACKEND_DAI_QUATERNARY_MI2S_RX_1, + MSM_FRONTEND_DAI_MULTIMEDIA9, 1, 0, msm_routing_get_audio_mixer, + msm_routing_put_audio_mixer), + SOC_SINGLE_EXT("MultiMedia10", MSM_BACKEND_DAI_QUATERNARY_MI2S_RX_1, + MSM_FRONTEND_DAI_MULTIMEDIA10, 1, 0, msm_routing_get_audio_mixer, + msm_routing_put_audio_mixer), + SOC_SINGLE_EXT("MultiMedia11", MSM_BACKEND_DAI_QUATERNARY_MI2S_RX_1, + MSM_FRONTEND_DAI_MULTIMEDIA11, 1, 0, msm_routing_get_audio_mixer, + msm_routing_put_audio_mixer), + SOC_SINGLE_EXT("MultiMedia12", MSM_BACKEND_DAI_QUATERNARY_MI2S_RX_1, + MSM_FRONTEND_DAI_MULTIMEDIA12, 1, 0, msm_routing_get_audio_mixer, + msm_routing_put_audio_mixer), + SOC_SINGLE_EXT("MultiMedia13", MSM_BACKEND_DAI_QUATERNARY_MI2S_RX_1, + MSM_FRONTEND_DAI_MULTIMEDIA13, 1, 0, msm_routing_get_audio_mixer, + msm_routing_put_audio_mixer), + SOC_SINGLE_EXT("MultiMedia14", MSM_BACKEND_DAI_QUATERNARY_MI2S_RX_1, + MSM_FRONTEND_DAI_MULTIMEDIA14, 1, 0, msm_routing_get_audio_mixer, + msm_routing_put_audio_mixer), + SOC_SINGLE_EXT("MultiMedia15", MSM_BACKEND_DAI_QUATERNARY_MI2S_RX_1, + MSM_FRONTEND_DAI_MULTIMEDIA15, 1, 0, msm_routing_get_audio_mixer, + msm_routing_put_audio_mixer), + SOC_SINGLE_EXT("MultiMedia16", MSM_BACKEND_DAI_QUATERNARY_MI2S_RX_1, + MSM_FRONTEND_DAI_MULTIMEDIA16, 1, 0, msm_routing_get_audio_mixer, + msm_routing_put_audio_mixer), + SOC_SINGLE_EXT("MultiMedia17", MSM_BACKEND_DAI_QUATERNARY_MI2S_RX_1, + MSM_FRONTEND_DAI_MULTIMEDIA17, 1, 0, msm_routing_get_audio_mixer, + msm_routing_put_audio_mixer), + SOC_SINGLE_EXT("MultiMedia18", MSM_BACKEND_DAI_QUATERNARY_MI2S_RX_1, + MSM_FRONTEND_DAI_MULTIMEDIA18, 1, 0, msm_routing_get_audio_mixer, + msm_routing_put_audio_mixer), + SOC_SINGLE_EXT("MultiMedia19", MSM_BACKEND_DAI_QUATERNARY_MI2S_RX_1, + MSM_FRONTEND_DAI_MULTIMEDIA19, 1, 0, msm_routing_get_audio_mixer, + msm_routing_put_audio_mixer), + SOC_SINGLE_EXT("MultiMedia26", MSM_BACKEND_DAI_QUATERNARY_MI2S_RX_1, + MSM_FRONTEND_DAI_MULTIMEDIA26, 1, 0, msm_routing_get_audio_mixer, + msm_routing_put_audio_mixer), + SOC_SINGLE_EXT("MultiMedia28", MSM_BACKEND_DAI_QUATERNARY_MI2S_RX_1, + MSM_FRONTEND_DAI_MULTIMEDIA28, 1, 0, msm_routing_get_audio_mixer, + msm_routing_put_audio_mixer), + SOC_SINGLE_EXT("MultiMedia29", MSM_BACKEND_DAI_QUATERNARY_MI2S_RX_1, + MSM_FRONTEND_DAI_MULTIMEDIA29, 1, 0, msm_routing_get_audio_mixer, + msm_routing_put_audio_mixer), +}; + +static const struct snd_kcontrol_new quaternary_mi2s_rx_2_mixer_controls[] = { + SOC_SINGLE_EXT("MultiMedia1", MSM_BACKEND_DAI_QUATERNARY_MI2S_RX_2, + MSM_FRONTEND_DAI_MULTIMEDIA1, 1, 0, msm_routing_get_audio_mixer, + msm_routing_put_audio_mixer), + SOC_SINGLE_EXT("MultiMedia2", MSM_BACKEND_DAI_QUATERNARY_MI2S_RX_2, + MSM_FRONTEND_DAI_MULTIMEDIA2, 1, 0, msm_routing_get_audio_mixer, + msm_routing_put_audio_mixer), + SOC_SINGLE_EXT("MultiMedia3", MSM_BACKEND_DAI_QUATERNARY_MI2S_RX_2, + MSM_FRONTEND_DAI_MULTIMEDIA3, 1, 0, msm_routing_get_audio_mixer, + msm_routing_put_audio_mixer), + SOC_SINGLE_EXT("MultiMedia4", MSM_BACKEND_DAI_QUATERNARY_MI2S_RX_2, + MSM_FRONTEND_DAI_MULTIMEDIA4, 1, 0, msm_routing_get_audio_mixer, + msm_routing_put_audio_mixer), + SOC_SINGLE_EXT("MultiMedia5", MSM_BACKEND_DAI_QUATERNARY_MI2S_RX_2, + MSM_FRONTEND_DAI_MULTIMEDIA5, 1, 0, msm_routing_get_audio_mixer, + msm_routing_put_audio_mixer), + SOC_SINGLE_EXT("MultiMedia6", MSM_BACKEND_DAI_QUATERNARY_MI2S_RX_2, + MSM_FRONTEND_DAI_MULTIMEDIA6, 1, 0, msm_routing_get_audio_mixer, + msm_routing_put_audio_mixer), + SOC_SINGLE_EXT("MultiMedia7", MSM_BACKEND_DAI_QUATERNARY_MI2S_RX_2, + MSM_FRONTEND_DAI_MULTIMEDIA7, 1, 0, msm_routing_get_audio_mixer, + msm_routing_put_audio_mixer), + SOC_SINGLE_EXT("MultiMedia8", MSM_BACKEND_DAI_QUATERNARY_MI2S_RX_2, + MSM_FRONTEND_DAI_MULTIMEDIA8, 1, 0, msm_routing_get_audio_mixer, + msm_routing_put_audio_mixer), + SOC_SINGLE_EXT("MultiMedia9", MSM_BACKEND_DAI_QUATERNARY_MI2S_RX_2, + MSM_FRONTEND_DAI_MULTIMEDIA9, 1, 0, msm_routing_get_audio_mixer, + msm_routing_put_audio_mixer), + SOC_SINGLE_EXT("MultiMedia10", MSM_BACKEND_DAI_QUATERNARY_MI2S_RX_2, + MSM_FRONTEND_DAI_MULTIMEDIA10, 1, 0, msm_routing_get_audio_mixer, + msm_routing_put_audio_mixer), + SOC_SINGLE_EXT("MultiMedia11", MSM_BACKEND_DAI_QUATERNARY_MI2S_RX_2, + MSM_FRONTEND_DAI_MULTIMEDIA11, 1, 0, msm_routing_get_audio_mixer, + msm_routing_put_audio_mixer), + SOC_SINGLE_EXT("MultiMedia12", MSM_BACKEND_DAI_QUATERNARY_MI2S_RX_2, + MSM_FRONTEND_DAI_MULTIMEDIA12, 1, 0, msm_routing_get_audio_mixer, + msm_routing_put_audio_mixer), + SOC_SINGLE_EXT("MultiMedia13", MSM_BACKEND_DAI_QUATERNARY_MI2S_RX_2, + MSM_FRONTEND_DAI_MULTIMEDIA13, 1, 0, msm_routing_get_audio_mixer, + msm_routing_put_audio_mixer), + SOC_SINGLE_EXT("MultiMedia14", MSM_BACKEND_DAI_QUATERNARY_MI2S_RX_2, + MSM_FRONTEND_DAI_MULTIMEDIA14, 1, 0, msm_routing_get_audio_mixer, + msm_routing_put_audio_mixer), + SOC_SINGLE_EXT("MultiMedia15", MSM_BACKEND_DAI_QUATERNARY_MI2S_RX_2, + MSM_FRONTEND_DAI_MULTIMEDIA15, 1, 0, msm_routing_get_audio_mixer, + msm_routing_put_audio_mixer), + SOC_SINGLE_EXT("MultiMedia16", MSM_BACKEND_DAI_QUATERNARY_MI2S_RX_2, + MSM_FRONTEND_DAI_MULTIMEDIA16, 1, 0, msm_routing_get_audio_mixer, + msm_routing_put_audio_mixer), + SOC_SINGLE_EXT("MultiMedia17", MSM_BACKEND_DAI_QUATERNARY_MI2S_RX_2, + MSM_FRONTEND_DAI_MULTIMEDIA17, 1, 0, msm_routing_get_audio_mixer, + msm_routing_put_audio_mixer), + SOC_SINGLE_EXT("MultiMedia18", MSM_BACKEND_DAI_QUATERNARY_MI2S_RX_2, + MSM_FRONTEND_DAI_MULTIMEDIA18, 1, 0, msm_routing_get_audio_mixer, + msm_routing_put_audio_mixer), + SOC_SINGLE_EXT("MultiMedia19", MSM_BACKEND_DAI_QUATERNARY_MI2S_RX_2, + MSM_FRONTEND_DAI_MULTIMEDIA19, 1, 0, msm_routing_get_audio_mixer, + msm_routing_put_audio_mixer), + SOC_SINGLE_EXT("MultiMedia26", MSM_BACKEND_DAI_QUATERNARY_MI2S_RX_2, + MSM_FRONTEND_DAI_MULTIMEDIA26, 1, 0, msm_routing_get_audio_mixer, + msm_routing_put_audio_mixer), + SOC_SINGLE_EXT("MultiMedia28", MSM_BACKEND_DAI_QUATERNARY_MI2S_RX_2, + MSM_FRONTEND_DAI_MULTIMEDIA28, 1, 0, msm_routing_get_audio_mixer, + msm_routing_put_audio_mixer), + SOC_SINGLE_EXT("MultiMedia29", MSM_BACKEND_DAI_QUATERNARY_MI2S_RX_2, + MSM_FRONTEND_DAI_MULTIMEDIA29, 1, 0, msm_routing_get_audio_mixer, + msm_routing_put_audio_mixer), +}; + +static const struct snd_kcontrol_new quaternary_mi2s_rx_3_mixer_controls[] = { + SOC_SINGLE_EXT("MultiMedia1", MSM_BACKEND_DAI_QUATERNARY_MI2S_RX_3, + MSM_FRONTEND_DAI_MULTIMEDIA1, 1, 0, msm_routing_get_audio_mixer, + msm_routing_put_audio_mixer), + SOC_SINGLE_EXT("MultiMedia2", MSM_BACKEND_DAI_QUATERNARY_MI2S_RX_3, + MSM_FRONTEND_DAI_MULTIMEDIA2, 1, 0, msm_routing_get_audio_mixer, + msm_routing_put_audio_mixer), + SOC_SINGLE_EXT("MultiMedia3", MSM_BACKEND_DAI_QUATERNARY_MI2S_RX_3, + MSM_FRONTEND_DAI_MULTIMEDIA3, 1, 0, msm_routing_get_audio_mixer, + msm_routing_put_audio_mixer), + SOC_SINGLE_EXT("MultiMedia4", MSM_BACKEND_DAI_QUATERNARY_MI2S_RX_3, + MSM_FRONTEND_DAI_MULTIMEDIA4, 1, 0, msm_routing_get_audio_mixer, + msm_routing_put_audio_mixer), + SOC_SINGLE_EXT("MultiMedia5", MSM_BACKEND_DAI_QUATERNARY_MI2S_RX_3, + MSM_FRONTEND_DAI_MULTIMEDIA5, 1, 0, msm_routing_get_audio_mixer, + msm_routing_put_audio_mixer), + SOC_SINGLE_EXT("MultiMedia6", MSM_BACKEND_DAI_QUATERNARY_MI2S_RX_3, + MSM_FRONTEND_DAI_MULTIMEDIA6, 1, 0, msm_routing_get_audio_mixer, + msm_routing_put_audio_mixer), + SOC_SINGLE_EXT("MultiMedia7", MSM_BACKEND_DAI_QUATERNARY_MI2S_RX_3, + MSM_FRONTEND_DAI_MULTIMEDIA7, 1, 0, msm_routing_get_audio_mixer, + msm_routing_put_audio_mixer), + SOC_SINGLE_EXT("MultiMedia8", MSM_BACKEND_DAI_QUATERNARY_MI2S_RX_3, + MSM_FRONTEND_DAI_MULTIMEDIA8, 1, 0, msm_routing_get_audio_mixer, + msm_routing_put_audio_mixer), + SOC_SINGLE_EXT("MultiMedia9", MSM_BACKEND_DAI_QUATERNARY_MI2S_RX_3, + MSM_FRONTEND_DAI_MULTIMEDIA9, 1, 0, msm_routing_get_audio_mixer, + msm_routing_put_audio_mixer), + SOC_SINGLE_EXT("MultiMedia10", MSM_BACKEND_DAI_QUATERNARY_MI2S_RX_3, + MSM_FRONTEND_DAI_MULTIMEDIA10, 1, 0, msm_routing_get_audio_mixer, + msm_routing_put_audio_mixer), + SOC_SINGLE_EXT("MultiMedia11", MSM_BACKEND_DAI_QUATERNARY_MI2S_RX_3, + MSM_FRONTEND_DAI_MULTIMEDIA11, 1, 0, msm_routing_get_audio_mixer, + msm_routing_put_audio_mixer), + SOC_SINGLE_EXT("MultiMedia12", MSM_BACKEND_DAI_QUATERNARY_MI2S_RX_3, + MSM_FRONTEND_DAI_MULTIMEDIA12, 1, 0, msm_routing_get_audio_mixer, + msm_routing_put_audio_mixer), + SOC_SINGLE_EXT("MultiMedia13", MSM_BACKEND_DAI_QUATERNARY_MI2S_RX_3, + MSM_FRONTEND_DAI_MULTIMEDIA13, 1, 0, msm_routing_get_audio_mixer, + msm_routing_put_audio_mixer), + SOC_SINGLE_EXT("MultiMedia14", MSM_BACKEND_DAI_QUATERNARY_MI2S_RX_3, + MSM_FRONTEND_DAI_MULTIMEDIA14, 1, 0, msm_routing_get_audio_mixer, + msm_routing_put_audio_mixer), + SOC_SINGLE_EXT("MultiMedia15", MSM_BACKEND_DAI_QUATERNARY_MI2S_RX_3, + MSM_FRONTEND_DAI_MULTIMEDIA15, 1, 0, msm_routing_get_audio_mixer, + msm_routing_put_audio_mixer), + SOC_SINGLE_EXT("MultiMedia16", MSM_BACKEND_DAI_QUATERNARY_MI2S_RX_3, + MSM_FRONTEND_DAI_MULTIMEDIA16, 1, 0, msm_routing_get_audio_mixer, + msm_routing_put_audio_mixer), + SOC_SINGLE_EXT("MultiMedia17", MSM_BACKEND_DAI_QUATERNARY_MI2S_RX_3, + MSM_FRONTEND_DAI_MULTIMEDIA17, 1, 0, msm_routing_get_audio_mixer, + msm_routing_put_audio_mixer), + SOC_SINGLE_EXT("MultiMedia18", MSM_BACKEND_DAI_QUATERNARY_MI2S_RX_3, + MSM_FRONTEND_DAI_MULTIMEDIA18, 1, 0, msm_routing_get_audio_mixer, + msm_routing_put_audio_mixer), + SOC_SINGLE_EXT("MultiMedia19", MSM_BACKEND_DAI_QUATERNARY_MI2S_RX_3, + MSM_FRONTEND_DAI_MULTIMEDIA19, 1, 0, msm_routing_get_audio_mixer, + msm_routing_put_audio_mixer), + SOC_SINGLE_EXT("MultiMedia26", MSM_BACKEND_DAI_QUATERNARY_MI2S_RX_3, + MSM_FRONTEND_DAI_MULTIMEDIA26, 1, 0, msm_routing_get_audio_mixer, + msm_routing_put_audio_mixer), + SOC_SINGLE_EXT("MultiMedia28", MSM_BACKEND_DAI_QUATERNARY_MI2S_RX_3, + MSM_FRONTEND_DAI_MULTIMEDIA28, 1, 0, msm_routing_get_audio_mixer, + msm_routing_put_audio_mixer), + SOC_SINGLE_EXT("MultiMedia29", MSM_BACKEND_DAI_QUATERNARY_MI2S_RX_3, + MSM_FRONTEND_DAI_MULTIMEDIA29, 1, 0, msm_routing_get_audio_mixer, + msm_routing_put_audio_mixer), +}; + +static const struct snd_kcontrol_new quaternary_mi2s_rx_4_mixer_controls[] = { + SOC_SINGLE_EXT("MultiMedia1", MSM_BACKEND_DAI_QUATERNARY_MI2S_RX_4, + MSM_FRONTEND_DAI_MULTIMEDIA1, 1, 0, msm_routing_get_audio_mixer, + msm_routing_put_audio_mixer), + SOC_SINGLE_EXT("MultiMedia2", MSM_BACKEND_DAI_QUATERNARY_MI2S_RX_4, + MSM_FRONTEND_DAI_MULTIMEDIA2, 1, 0, msm_routing_get_audio_mixer, + msm_routing_put_audio_mixer), + SOC_SINGLE_EXT("MultiMedia3", MSM_BACKEND_DAI_QUATERNARY_MI2S_RX_4, + MSM_FRONTEND_DAI_MULTIMEDIA3, 1, 0, msm_routing_get_audio_mixer, + msm_routing_put_audio_mixer), + SOC_SINGLE_EXT("MultiMedia4", MSM_BACKEND_DAI_QUATERNARY_MI2S_RX_4, + MSM_FRONTEND_DAI_MULTIMEDIA4, 1, 0, msm_routing_get_audio_mixer, + msm_routing_put_audio_mixer), + SOC_SINGLE_EXT("MultiMedia5", MSM_BACKEND_DAI_QUATERNARY_MI2S_RX_4, + MSM_FRONTEND_DAI_MULTIMEDIA5, 1, 0, msm_routing_get_audio_mixer, + msm_routing_put_audio_mixer), + SOC_SINGLE_EXT("MultiMedia6", MSM_BACKEND_DAI_QUATERNARY_MI2S_RX_4, + MSM_FRONTEND_DAI_MULTIMEDIA6, 1, 0, msm_routing_get_audio_mixer, + msm_routing_put_audio_mixer), + SOC_SINGLE_EXT("MultiMedia7", MSM_BACKEND_DAI_QUATERNARY_MI2S_RX_4, + MSM_FRONTEND_DAI_MULTIMEDIA7, 1, 0, msm_routing_get_audio_mixer, + msm_routing_put_audio_mixer), + SOC_SINGLE_EXT("MultiMedia8", MSM_BACKEND_DAI_QUATERNARY_MI2S_RX_4, + MSM_FRONTEND_DAI_MULTIMEDIA8, 1, 0, msm_routing_get_audio_mixer, + msm_routing_put_audio_mixer), + SOC_SINGLE_EXT("MultiMedia9", MSM_BACKEND_DAI_QUATERNARY_MI2S_RX_4, + MSM_FRONTEND_DAI_MULTIMEDIA9, 1, 0, msm_routing_get_audio_mixer, + msm_routing_put_audio_mixer), + SOC_SINGLE_EXT("MultiMedia10", MSM_BACKEND_DAI_QUATERNARY_MI2S_RX_4, + MSM_FRONTEND_DAI_MULTIMEDIA10, 1, 0, msm_routing_get_audio_mixer, + msm_routing_put_audio_mixer), + SOC_SINGLE_EXT("MultiMedia11", MSM_BACKEND_DAI_QUATERNARY_MI2S_RX_4, + MSM_FRONTEND_DAI_MULTIMEDIA11, 1, 0, msm_routing_get_audio_mixer, + msm_routing_put_audio_mixer), + SOC_SINGLE_EXT("MultiMedia12", MSM_BACKEND_DAI_QUATERNARY_MI2S_RX_4, + MSM_FRONTEND_DAI_MULTIMEDIA12, 1, 0, msm_routing_get_audio_mixer, + msm_routing_put_audio_mixer), + SOC_SINGLE_EXT("MultiMedia13", MSM_BACKEND_DAI_QUATERNARY_MI2S_RX_4, + MSM_FRONTEND_DAI_MULTIMEDIA13, 1, 0, msm_routing_get_audio_mixer, + msm_routing_put_audio_mixer), + SOC_SINGLE_EXT("MultiMedia14", MSM_BACKEND_DAI_QUATERNARY_MI2S_RX_4, + MSM_FRONTEND_DAI_MULTIMEDIA14, 1, 0, msm_routing_get_audio_mixer, + msm_routing_put_audio_mixer), + SOC_SINGLE_EXT("MultiMedia15", MSM_BACKEND_DAI_QUATERNARY_MI2S_RX_4, + MSM_FRONTEND_DAI_MULTIMEDIA15, 1, 0, msm_routing_get_audio_mixer, + msm_routing_put_audio_mixer), + SOC_SINGLE_EXT("MultiMedia16", MSM_BACKEND_DAI_QUATERNARY_MI2S_RX_4, + MSM_FRONTEND_DAI_MULTIMEDIA16, 1, 0, msm_routing_get_audio_mixer, + msm_routing_put_audio_mixer), + SOC_SINGLE_EXT("MultiMedia17", MSM_BACKEND_DAI_QUATERNARY_MI2S_RX_4, + MSM_FRONTEND_DAI_MULTIMEDIA17, 1, 0, msm_routing_get_audio_mixer, + msm_routing_put_audio_mixer), + SOC_SINGLE_EXT("MultiMedia18", MSM_BACKEND_DAI_QUATERNARY_MI2S_RX_4, + MSM_FRONTEND_DAI_MULTIMEDIA18, 1, 0, msm_routing_get_audio_mixer, + msm_routing_put_audio_mixer), + SOC_SINGLE_EXT("MultiMedia19", MSM_BACKEND_DAI_QUATERNARY_MI2S_RX_4, + MSM_FRONTEND_DAI_MULTIMEDIA19, 1, 0, msm_routing_get_audio_mixer, + msm_routing_put_audio_mixer), + SOC_SINGLE_EXT("MultiMedia26", MSM_BACKEND_DAI_QUATERNARY_MI2S_RX_4, + MSM_FRONTEND_DAI_MULTIMEDIA26, 1, 0, msm_routing_get_audio_mixer, + msm_routing_put_audio_mixer), + SOC_SINGLE_EXT("MultiMedia28", MSM_BACKEND_DAI_QUATERNARY_MI2S_RX_4, + MSM_FRONTEND_DAI_MULTIMEDIA28, 1, 0, msm_routing_get_audio_mixer, + msm_routing_put_audio_mixer), + SOC_SINGLE_EXT("MultiMedia29", MSM_BACKEND_DAI_QUATERNARY_MI2S_RX_4, + MSM_FRONTEND_DAI_MULTIMEDIA29, 1, 0, msm_routing_get_audio_mixer, + msm_routing_put_audio_mixer), +}; + static const struct snd_kcontrol_new secondary_mi2s_rx_mixer_controls[] = { SOC_SINGLE_EXT("MultiMedia1", MSM_BACKEND_DAI_SECONDARY_MI2S_RX , MSM_FRONTEND_DAI_MULTIMEDIA1, 1, 0, msm_routing_get_audio_mixer, @@ -7215,6 +8091,42 @@ static const struct snd_kcontrol_new mmul1_mixer_controls[] = { SOC_SINGLE_EXT("USB_AUDIO_TX", MSM_BACKEND_DAI_USB_TX, MSM_FRONTEND_DAI_MULTIMEDIA1, 1, 0, msm_routing_get_audio_mixer, msm_routing_put_audio_mixer), + SOC_SINGLE_EXT("SEC_MI2S_TX_1", MSM_BACKEND_DAI_SECONDARY_MI2S_TX_1, + MSM_FRONTEND_DAI_MULTIMEDIA1, 1, 0, msm_routing_get_audio_mixer, + msm_routing_put_audio_mixer), + SOC_SINGLE_EXT("SEC_MI2S_TX_2", MSM_BACKEND_DAI_SECONDARY_MI2S_TX_2, + MSM_FRONTEND_DAI_MULTIMEDIA1, 1, 0, msm_routing_get_audio_mixer, + msm_routing_put_audio_mixer), + SOC_SINGLE_EXT("SEC_MI2S_TX_3", MSM_BACKEND_DAI_SECONDARY_MI2S_TX_3, + MSM_FRONTEND_DAI_MULTIMEDIA1, 1, 0, msm_routing_get_audio_mixer, + msm_routing_put_audio_mixer), + SOC_SINGLE_EXT("SEC_MI2S_TX_4", MSM_BACKEND_DAI_SECONDARY_MI2S_TX_4, + MSM_FRONTEND_DAI_MULTIMEDIA1, 1, 0, msm_routing_get_audio_mixer, + msm_routing_put_audio_mixer), + SOC_SINGLE_EXT("TERT_MI2S_TX_1", MSM_BACKEND_DAI_TERTIARY_MI2S_TX_1, + MSM_FRONTEND_DAI_MULTIMEDIA1, 1, 0, msm_routing_get_audio_mixer, + msm_routing_put_audio_mixer), + SOC_SINGLE_EXT("TERT_MI2S_TX_2", MSM_BACKEND_DAI_TERTIARY_MI2S_TX_2, + MSM_FRONTEND_DAI_MULTIMEDIA1, 1, 0, msm_routing_get_audio_mixer, + msm_routing_put_audio_mixer), + SOC_SINGLE_EXT("TERT_MI2S_TX_3", MSM_BACKEND_DAI_TERTIARY_MI2S_TX_3, + MSM_FRONTEND_DAI_MULTIMEDIA1, 1, 0, msm_routing_get_audio_mixer, + msm_routing_put_audio_mixer), + SOC_SINGLE_EXT("TERT_MI2S_TX_4", MSM_BACKEND_DAI_TERTIARY_MI2S_TX_4, + MSM_FRONTEND_DAI_MULTIMEDIA1, 1, 0, msm_routing_get_audio_mixer, + msm_routing_put_audio_mixer), + SOC_SINGLE_EXT("QUAT_MI2S_TX_1", MSM_BACKEND_DAI_QUATERNARY_MI2S_TX_1, + MSM_FRONTEND_DAI_MULTIMEDIA1, 1, 0, msm_routing_get_audio_mixer, + msm_routing_put_audio_mixer), + SOC_SINGLE_EXT("QUAT_MI2S_TX_2", MSM_BACKEND_DAI_QUATERNARY_MI2S_TX_2, + MSM_FRONTEND_DAI_MULTIMEDIA1, 1, 0, msm_routing_get_audio_mixer, + msm_routing_put_audio_mixer), + SOC_SINGLE_EXT("QUAT_MI2S_TX_3", MSM_BACKEND_DAI_QUATERNARY_MI2S_TX_3, + MSM_FRONTEND_DAI_MULTIMEDIA1, 1, 0, msm_routing_get_audio_mixer, + msm_routing_put_audio_mixer), + SOC_SINGLE_EXT("QUAT_MI2S_TX_4", MSM_BACKEND_DAI_QUATERNARY_MI2S_TX_4, + MSM_FRONTEND_DAI_MULTIMEDIA1, 1, 0, msm_routing_get_audio_mixer, + msm_routing_put_audio_mixer), }; static const struct snd_kcontrol_new mmul2_mixer_controls[] = { @@ -7308,6 +8220,42 @@ static const struct snd_kcontrol_new mmul2_mixer_controls[] = { SOC_SINGLE_EXT("USB_AUDIO_TX", MSM_BACKEND_DAI_USB_TX, MSM_FRONTEND_DAI_MULTIMEDIA2, 1, 0, msm_routing_get_audio_mixer, msm_routing_put_audio_mixer), + SOC_SINGLE_EXT("SEC_MI2S_TX_1", MSM_BACKEND_DAI_SECONDARY_MI2S_TX_1, + MSM_FRONTEND_DAI_MULTIMEDIA2, 1, 0, msm_routing_get_audio_mixer, + msm_routing_put_audio_mixer), + SOC_SINGLE_EXT("SEC_MI2S_TX_2", MSM_BACKEND_DAI_SECONDARY_MI2S_TX_2, + MSM_FRONTEND_DAI_MULTIMEDIA2, 1, 0, msm_routing_get_audio_mixer, + msm_routing_put_audio_mixer), + SOC_SINGLE_EXT("SEC_MI2S_TX_3", MSM_BACKEND_DAI_SECONDARY_MI2S_TX_3, + MSM_FRONTEND_DAI_MULTIMEDIA2, 1, 0, msm_routing_get_audio_mixer, + msm_routing_put_audio_mixer), + SOC_SINGLE_EXT("SEC_MI2S_TX_4", MSM_BACKEND_DAI_SECONDARY_MI2S_TX_4, + MSM_FRONTEND_DAI_MULTIMEDIA2, 1, 0, msm_routing_get_audio_mixer, + msm_routing_put_audio_mixer), + SOC_SINGLE_EXT("TERT_MI2S_TX_1", MSM_BACKEND_DAI_TERTIARY_MI2S_TX_1, + MSM_FRONTEND_DAI_MULTIMEDIA2, 1, 0, msm_routing_get_audio_mixer, + msm_routing_put_audio_mixer), + SOC_SINGLE_EXT("TERT_MI2S_TX_2", MSM_BACKEND_DAI_TERTIARY_MI2S_TX_2, + MSM_FRONTEND_DAI_MULTIMEDIA2, 1, 0, msm_routing_get_audio_mixer, + msm_routing_put_audio_mixer), + SOC_SINGLE_EXT("TERT_MI2S_TX_3", MSM_BACKEND_DAI_TERTIARY_MI2S_TX_3, + MSM_FRONTEND_DAI_MULTIMEDIA2, 1, 0, msm_routing_get_audio_mixer, + msm_routing_put_audio_mixer), + SOC_SINGLE_EXT("TERT_MI2S_TX_4", MSM_BACKEND_DAI_TERTIARY_MI2S_TX_4, + MSM_FRONTEND_DAI_MULTIMEDIA2, 1, 0, msm_routing_get_audio_mixer, + msm_routing_put_audio_mixer), + SOC_SINGLE_EXT("QUAT_MI2S_TX_1", MSM_BACKEND_DAI_QUATERNARY_MI2S_TX_1, + MSM_FRONTEND_DAI_MULTIMEDIA2, 1, 0, msm_routing_get_audio_mixer, + msm_routing_put_audio_mixer), + SOC_SINGLE_EXT("QUAT_MI2S_TX_2", MSM_BACKEND_DAI_QUATERNARY_MI2S_TX_2, + MSM_FRONTEND_DAI_MULTIMEDIA2, 1, 0, msm_routing_get_audio_mixer, + msm_routing_put_audio_mixer), + SOC_SINGLE_EXT("QUAT_MI2S_TX_3", MSM_BACKEND_DAI_QUATERNARY_MI2S_TX_3, + MSM_FRONTEND_DAI_MULTIMEDIA2, 1, 0, msm_routing_get_audio_mixer, + msm_routing_put_audio_mixer), + SOC_SINGLE_EXT("QUAT_MI2S_TX_4", MSM_BACKEND_DAI_QUATERNARY_MI2S_TX_4, + MSM_FRONTEND_DAI_MULTIMEDIA2, 1, 0, msm_routing_get_audio_mixer, + msm_routing_put_audio_mixer), }; static const struct snd_kcontrol_new mmul3_mixer_controls[] = { @@ -7398,6 +8346,42 @@ static const struct snd_kcontrol_new mmul3_mixer_controls[] = { SOC_SINGLE_EXT("QUAT_TDM_TX_3", MSM_BACKEND_DAI_QUAT_TDM_TX_3, MSM_FRONTEND_DAI_MULTIMEDIA3, 1, 0, msm_routing_get_audio_mixer, msm_routing_put_audio_mixer), + SOC_SINGLE_EXT("SEC_MI2S_TX_1", MSM_BACKEND_DAI_SECONDARY_MI2S_TX_1, + MSM_FRONTEND_DAI_MULTIMEDIA3, 1, 0, msm_routing_get_audio_mixer, + msm_routing_put_audio_mixer), + SOC_SINGLE_EXT("SEC_MI2S_TX_2", MSM_BACKEND_DAI_SECONDARY_MI2S_TX_2, + MSM_FRONTEND_DAI_MULTIMEDIA3, 1, 0, msm_routing_get_audio_mixer, + msm_routing_put_audio_mixer), + SOC_SINGLE_EXT("SEC_MI2S_TX_3", MSM_BACKEND_DAI_SECONDARY_MI2S_TX_3, + MSM_FRONTEND_DAI_MULTIMEDIA3, 1, 0, msm_routing_get_audio_mixer, + msm_routing_put_audio_mixer), + SOC_SINGLE_EXT("SEC_MI2S_TX_4", MSM_BACKEND_DAI_SECONDARY_MI2S_TX_4, + MSM_FRONTEND_DAI_MULTIMEDIA3, 1, 0, msm_routing_get_audio_mixer, + msm_routing_put_audio_mixer), + SOC_SINGLE_EXT("TERT_MI2S_TX_1", MSM_BACKEND_DAI_TERTIARY_MI2S_TX_1, + MSM_FRONTEND_DAI_MULTIMEDIA3, 1, 0, msm_routing_get_audio_mixer, + msm_routing_put_audio_mixer), + SOC_SINGLE_EXT("TERT_MI2S_TX_2", MSM_BACKEND_DAI_TERTIARY_MI2S_TX_2, + MSM_FRONTEND_DAI_MULTIMEDIA3, 1, 0, msm_routing_get_audio_mixer, + msm_routing_put_audio_mixer), + SOC_SINGLE_EXT("TERT_MI2S_TX_3", MSM_BACKEND_DAI_TERTIARY_MI2S_TX_3, + MSM_FRONTEND_DAI_MULTIMEDIA3, 1, 0, msm_routing_get_audio_mixer, + msm_routing_put_audio_mixer), + SOC_SINGLE_EXT("TERT_MI2S_TX_4", MSM_BACKEND_DAI_TERTIARY_MI2S_TX_4, + MSM_FRONTEND_DAI_MULTIMEDIA3, 1, 0, msm_routing_get_audio_mixer, + msm_routing_put_audio_mixer), + SOC_SINGLE_EXT("QUAT_MI2S_TX_1", MSM_BACKEND_DAI_QUATERNARY_MI2S_TX_1, + MSM_FRONTEND_DAI_MULTIMEDIA3, 1, 0, msm_routing_get_audio_mixer, + msm_routing_put_audio_mixer), + SOC_SINGLE_EXT("QUAT_MI2S_TX_2", MSM_BACKEND_DAI_QUATERNARY_MI2S_TX_2, + MSM_FRONTEND_DAI_MULTIMEDIA3, 1, 0, msm_routing_get_audio_mixer, + msm_routing_put_audio_mixer), + SOC_SINGLE_EXT("QUAT_MI2S_TX_3", MSM_BACKEND_DAI_QUATERNARY_MI2S_TX_3, + MSM_FRONTEND_DAI_MULTIMEDIA3, 1, 0, msm_routing_get_audio_mixer, + msm_routing_put_audio_mixer), + SOC_SINGLE_EXT("QUAT_MI2S_TX_4", MSM_BACKEND_DAI_QUATERNARY_MI2S_TX_4, + MSM_FRONTEND_DAI_MULTIMEDIA3, 1, 0, msm_routing_get_audio_mixer, + msm_routing_put_audio_mixer), }; static const struct snd_kcontrol_new mmul4_mixer_controls[] = { @@ -7593,6 +8577,42 @@ static const struct snd_kcontrol_new mmul5_mixer_controls[] = { SOC_SINGLE_EXT("USB_AUDIO_TX", MSM_BACKEND_DAI_USB_TX, MSM_FRONTEND_DAI_MULTIMEDIA5, 1, 0, msm_routing_get_audio_mixer, msm_routing_put_audio_mixer), + SOC_SINGLE_EXT("SEC_MI2S_TX_1", MSM_BACKEND_DAI_SECONDARY_MI2S_TX_1, + MSM_FRONTEND_DAI_MULTIMEDIA5, 1, 0, msm_routing_get_audio_mixer, + msm_routing_put_audio_mixer), + SOC_SINGLE_EXT("SEC_MI2S_TX_2", MSM_BACKEND_DAI_SECONDARY_MI2S_TX_2, + MSM_FRONTEND_DAI_MULTIMEDIA5, 1, 0, msm_routing_get_audio_mixer, + msm_routing_put_audio_mixer), + SOC_SINGLE_EXT("SEC_MI2S_TX_3", MSM_BACKEND_DAI_SECONDARY_MI2S_TX_3, + MSM_FRONTEND_DAI_MULTIMEDIA5, 1, 0, msm_routing_get_audio_mixer, + msm_routing_put_audio_mixer), + SOC_SINGLE_EXT("SEC_MI2S_TX_4", MSM_BACKEND_DAI_SECONDARY_MI2S_TX_4, + MSM_FRONTEND_DAI_MULTIMEDIA4, 1, 0, msm_routing_get_audio_mixer, + msm_routing_put_audio_mixer), + SOC_SINGLE_EXT("TERT_MI2S_TX_1", MSM_BACKEND_DAI_TERTIARY_MI2S_TX_1, + MSM_FRONTEND_DAI_MULTIMEDIA5, 1, 0, msm_routing_get_audio_mixer, + msm_routing_put_audio_mixer), + SOC_SINGLE_EXT("TERT_MI2S_TX_2", MSM_BACKEND_DAI_TERTIARY_MI2S_TX_2, + MSM_FRONTEND_DAI_MULTIMEDIA5, 1, 0, msm_routing_get_audio_mixer, + msm_routing_put_audio_mixer), + SOC_SINGLE_EXT("TERT_MI2S_TX_3", MSM_BACKEND_DAI_TERTIARY_MI2S_TX_3, + MSM_FRONTEND_DAI_MULTIMEDIA5, 1, 0, msm_routing_get_audio_mixer, + msm_routing_put_audio_mixer), + SOC_SINGLE_EXT("TERT_MI2S_TX_4", MSM_BACKEND_DAI_TERTIARY_MI2S_TX_4, + MSM_FRONTEND_DAI_MULTIMEDIA5, 1, 0, msm_routing_get_audio_mixer, + msm_routing_put_audio_mixer), + SOC_SINGLE_EXT("QUAT_MI2S_TX_1", MSM_BACKEND_DAI_QUATERNARY_MI2S_TX_1, + MSM_FRONTEND_DAI_MULTIMEDIA5, 1, 0, msm_routing_get_audio_mixer, + msm_routing_put_audio_mixer), + SOC_SINGLE_EXT("QUAT_MI2S_TX_2", MSM_BACKEND_DAI_QUATERNARY_MI2S_TX_2, + MSM_FRONTEND_DAI_MULTIMEDIA5, 1, 0, msm_routing_get_audio_mixer, + msm_routing_put_audio_mixer), + SOC_SINGLE_EXT("QUAT_MI2S_TX_3", MSM_BACKEND_DAI_QUATERNARY_MI2S_TX_3, + MSM_FRONTEND_DAI_MULTIMEDIA5, 1, 0, msm_routing_get_audio_mixer, + msm_routing_put_audio_mixer), + SOC_SINGLE_EXT("QUAT_MI2S_TX_4", MSM_BACKEND_DAI_QUATERNARY_MI2S_TX_4, + MSM_FRONTEND_DAI_MULTIMEDIA5, 1, 0, msm_routing_get_audio_mixer, + msm_routing_put_audio_mixer), }; static const struct snd_kcontrol_new mmul6_mixer_controls[] = { @@ -7938,6 +8958,42 @@ static const struct snd_kcontrol_new mmul9_mixer_controls[] = { SOC_SINGLE_EXT("QUAT_TDM_TX_3", MSM_BACKEND_DAI_QUAT_TDM_TX_3, MSM_FRONTEND_DAI_MULTIMEDIA9, 1, 0, msm_routing_get_audio_mixer, msm_routing_put_audio_mixer), + SOC_SINGLE_EXT("SEC_MI2S_TX_1", MSM_BACKEND_DAI_SECONDARY_MI2S_TX_1, + MSM_FRONTEND_DAI_MULTIMEDIA9, 1, 0, msm_routing_get_audio_mixer, + msm_routing_put_audio_mixer), + SOC_SINGLE_EXT("SEC_MI2S_TX_2", MSM_BACKEND_DAI_SECONDARY_MI2S_TX_2, + MSM_FRONTEND_DAI_MULTIMEDIA9, 1, 0, msm_routing_get_audio_mixer, + msm_routing_put_audio_mixer), + SOC_SINGLE_EXT("SEC_MI2S_TX_3", MSM_BACKEND_DAI_SECONDARY_MI2S_TX_3, + MSM_FRONTEND_DAI_MULTIMEDIA9, 1, 0, msm_routing_get_audio_mixer, + msm_routing_put_audio_mixer), + SOC_SINGLE_EXT("SEC_MI2S_TX_4", MSM_BACKEND_DAI_SECONDARY_MI2S_TX_4, + MSM_FRONTEND_DAI_MULTIMEDIA9, 1, 0, msm_routing_get_audio_mixer, + msm_routing_put_audio_mixer), + SOC_SINGLE_EXT("TERT_MI2S_TX_1", MSM_BACKEND_DAI_TERTIARY_MI2S_TX_1, + MSM_FRONTEND_DAI_MULTIMEDIA9, 1, 0, msm_routing_get_audio_mixer, + msm_routing_put_audio_mixer), + SOC_SINGLE_EXT("TERT_MI2S_TX_2", MSM_BACKEND_DAI_TERTIARY_MI2S_TX_2, + MSM_FRONTEND_DAI_MULTIMEDIA9, 1, 0, msm_routing_get_audio_mixer, + msm_routing_put_audio_mixer), + SOC_SINGLE_EXT("TERT_MI2S_TX_3", MSM_BACKEND_DAI_TERTIARY_MI2S_TX_3, + MSM_FRONTEND_DAI_MULTIMEDIA9, 1, 0, msm_routing_get_audio_mixer, + msm_routing_put_audio_mixer), + SOC_SINGLE_EXT("TERT_MI2S_TX_4", MSM_BACKEND_DAI_TERTIARY_MI2S_TX_4, + MSM_FRONTEND_DAI_MULTIMEDIA9, 1, 0, msm_routing_get_audio_mixer, + msm_routing_put_audio_mixer), + SOC_SINGLE_EXT("QUAT_MI2S_TX_1", MSM_BACKEND_DAI_QUATERNARY_MI2S_TX_1, + MSM_FRONTEND_DAI_MULTIMEDIA9, 1, 0, msm_routing_get_audio_mixer, + msm_routing_put_audio_mixer), + SOC_SINGLE_EXT("QUAT_MI2S_TX_2", MSM_BACKEND_DAI_QUATERNARY_MI2S_TX_2, + MSM_FRONTEND_DAI_MULTIMEDIA9, 1, 0, msm_routing_get_audio_mixer, + msm_routing_put_audio_mixer), + SOC_SINGLE_EXT("QUAT_MI2S_TX_3", MSM_BACKEND_DAI_QUATERNARY_MI2S_TX_3, + MSM_FRONTEND_DAI_MULTIMEDIA9, 1, 0, msm_routing_get_audio_mixer, + msm_routing_put_audio_mixer), + SOC_SINGLE_EXT("QUAT_MI2S_TX_4", MSM_BACKEND_DAI_QUATERNARY_MI2S_TX_4, + MSM_FRONTEND_DAI_MULTIMEDIA9, 1, 0, msm_routing_get_audio_mixer, + msm_routing_put_audio_mixer), }; static const struct snd_kcontrol_new mmul17_mixer_controls[] = { @@ -8091,6 +9147,42 @@ static const struct snd_kcontrol_new mmul20_mixer_controls[] = { SOC_SINGLE_EXT("QUAT_TDM_TX_3", MSM_BACKEND_DAI_QUAT_TDM_TX_3, MSM_FRONTEND_DAI_MULTIMEDIA20, 1, 0, msm_routing_get_audio_mixer, msm_routing_put_audio_mixer), + SOC_SINGLE_EXT("SEC_MI2S_TX_1", MSM_BACKEND_DAI_SECONDARY_MI2S_TX_1, + MSM_FRONTEND_DAI_MULTIMEDIA20, 1, 0, msm_routing_get_audio_mixer, + msm_routing_put_audio_mixer), + SOC_SINGLE_EXT("SEC_MI2S_TX_2", MSM_BACKEND_DAI_SECONDARY_MI2S_TX_2, + MSM_FRONTEND_DAI_MULTIMEDIA20, 1, 0, msm_routing_get_audio_mixer, + msm_routing_put_audio_mixer), + SOC_SINGLE_EXT("SEC_MI2S_TX_3", MSM_BACKEND_DAI_SECONDARY_MI2S_TX_3, + MSM_FRONTEND_DAI_MULTIMEDIA20, 1, 0, msm_routing_get_audio_mixer, + msm_routing_put_audio_mixer), + SOC_SINGLE_EXT("SEC_MI2S_TX_4", MSM_BACKEND_DAI_SECONDARY_MI2S_TX_4, + MSM_FRONTEND_DAI_MULTIMEDIA20, 1, 0, msm_routing_get_audio_mixer, + msm_routing_put_audio_mixer), + SOC_SINGLE_EXT("TERT_MI2S_TX_1", MSM_BACKEND_DAI_TERTIARY_MI2S_TX_1, + MSM_FRONTEND_DAI_MULTIMEDIA20, 1, 0, msm_routing_get_audio_mixer, + msm_routing_put_audio_mixer), + SOC_SINGLE_EXT("TERT_MI2S_TX_2", MSM_BACKEND_DAI_TERTIARY_MI2S_TX_2, + MSM_FRONTEND_DAI_MULTIMEDIA20, 1, 0, msm_routing_get_audio_mixer, + msm_routing_put_audio_mixer), + SOC_SINGLE_EXT("TERT_MI2S_TX_3", MSM_BACKEND_DAI_TERTIARY_MI2S_TX_3, + MSM_FRONTEND_DAI_MULTIMEDIA20, 1, 0, msm_routing_get_audio_mixer, + msm_routing_put_audio_mixer), + SOC_SINGLE_EXT("TERT_MI2S_TX_4", MSM_BACKEND_DAI_TERTIARY_MI2S_TX_4, + MSM_FRONTEND_DAI_MULTIMEDIA20, 1, 0, msm_routing_get_audio_mixer, + msm_routing_put_audio_mixer), + SOC_SINGLE_EXT("QUAT_MI2S_TX_1", MSM_BACKEND_DAI_QUATERNARY_MI2S_TX_1, + MSM_FRONTEND_DAI_MULTIMEDIA20, 1, 0, msm_routing_get_audio_mixer, + msm_routing_put_audio_mixer), + SOC_SINGLE_EXT("QUAT_MI2S_TX_2", MSM_BACKEND_DAI_QUATERNARY_MI2S_TX_2, + MSM_FRONTEND_DAI_MULTIMEDIA20, 1, 0, msm_routing_get_audio_mixer, + msm_routing_put_audio_mixer), + SOC_SINGLE_EXT("QUAT_MI2S_TX_3", MSM_BACKEND_DAI_QUATERNARY_MI2S_TX_3, + MSM_FRONTEND_DAI_MULTIMEDIA20, 1, 0, msm_routing_get_audio_mixer, + msm_routing_put_audio_mixer), + SOC_SINGLE_EXT("QUAT_MI2S_TX_4", MSM_BACKEND_DAI_QUATERNARY_MI2S_TX_4, + MSM_FRONTEND_DAI_MULTIMEDIA20, 1, 0, msm_routing_get_audio_mixer, + msm_routing_put_audio_mixer), }; static const struct snd_kcontrol_new mmul21_mixer_controls[] = { @@ -12773,6 +13865,56 @@ static const struct snd_soc_dapm_widget msm_qdsp6_widgets[] = { 0, 0, 0 , 0), SND_SOC_DAPM_AIF_IN("PCM_TX", "AFE Capture", 0, 0, 0 , 0), + SND_SOC_DAPM_AIF_IN("SEC_MI2S_TX_1", "Secondary MI2S1 Capture", + 0, 0, 0, 0), + SND_SOC_DAPM_AIF_IN("SEC_MI2S_TX_2", "Secondary MI2S2 Capture", + 0, 0, 0, 0), + SND_SOC_DAPM_AIF_IN("SEC_MI2S_TX_3", "Secondary MI2S3 Capture", + 0, 0, 0, 0), + SND_SOC_DAPM_AIF_IN("SEC_MI2S_TX_4", "Secondary MI2S4 Capture", + 0, 0, 0, 0), + SND_SOC_DAPM_AIF_IN("TERT_MI2S_TX_1", "Tertiary MI2S1 Capture", + 0, 0, 0, 0), + SND_SOC_DAPM_AIF_IN("TERT_MI2S_TX_2", "Tertiary MI2S2 Capture", + 0, 0, 0, 0), + SND_SOC_DAPM_AIF_IN("TERT_MI2S_TX_3", "Tertiary MI2S3 Capture", + 0, 0, 0, 0), + SND_SOC_DAPM_AIF_IN("TERT_MI2S_TX_4", "Tertiary MI2S4 Capture", + 0, 0, 0, 0), + SND_SOC_DAPM_AIF_IN("QUAT_MI2S_TX_1", "Quaternary MI2S1 Capture", + 0, 0, 0, 0), + SND_SOC_DAPM_AIF_IN("QUAT_MI2S_TX_2", "Quaternary MI2S2 Capture", + 0, 0, 0, 0), + SND_SOC_DAPM_AIF_IN("QUAT_MI2S_TX_3", "Quaternary MI2S3 Capture", + 0, 0, 0, 0), + SND_SOC_DAPM_AIF_IN("QUAT_MI2S_TX_4", "Quaternary MI2S4 Capture", + 0, 0, 0, 0), + + SND_SOC_DAPM_AIF_OUT("SEC_MI2S_RX_1", "Secondary MI2S1 Playback", + 0, 0, 0, 0), + SND_SOC_DAPM_AIF_OUT("SEC_MI2S_RX_2", "Secondary MI2S2 Playback", + 0, 0, 0, 0), + SND_SOC_DAPM_AIF_OUT("SEC_MI2S_RX_3", "Secondary MI2S3 Playback", + 0, 0, 0, 0), + SND_SOC_DAPM_AIF_OUT("SEC_MI2S_RX_4", "Secondary MI2S4 Playback", + 0, 0, 0, 0), + SND_SOC_DAPM_AIF_OUT("TERT_MI2S_RX_1", "Tertiary MI2S1 Playback", + 0, 0, 0, 0), + SND_SOC_DAPM_AIF_OUT("TERT_MI2S_RX_2", "Tertiary MI2S2 Playback", + 0, 0, 0, 0), + SND_SOC_DAPM_AIF_OUT("TERT_MI2S_RX_3", "Tertiary MI2S3 Playback", + 0, 0, 0, 0), + SND_SOC_DAPM_AIF_OUT("TERT_MI2S_RX_4", "Tertiary MI2S4 Playback", + 0, 0, 0, 0), + SND_SOC_DAPM_AIF_OUT("QUAT_MI2S_RX_1", "Quaternary MI2S1 Playback", + 0, 0, 0, 0), + SND_SOC_DAPM_AIF_OUT("QUAT_MI2S_RX_2", "Quaternary MI2S2 Playback", + 0, 0, 0, 0), + SND_SOC_DAPM_AIF_OUT("QUAT_MI2S_RX_3", "Quaternary MI2S3 Playback", + 0, 0, 0, 0), + SND_SOC_DAPM_AIF_OUT("QUAT_MI2S_RX_4", "Quaternary MI2S4 Playback", + 0, 0, 0, 0), + SND_SOC_DAPM_AIF_OUT("PRI_TDM_RX_0", "Primary TDM0 Playback", 0, 0, 0, 0), SND_SOC_DAPM_AIF_IN("PRI_TDM_TX_0", "Primary TDM0 Capture", @@ -13024,6 +14166,42 @@ static const struct snd_soc_dapm_widget msm_qdsp6_widgets[] = { SND_SOC_DAPM_MIXER("TERT_MI2S_RX Audio Mixer", SND_SOC_NOPM, 0, 0, tertiary_mi2s_rx_mixer_controls, ARRAY_SIZE(tertiary_mi2s_rx_mixer_controls)), + SND_SOC_DAPM_MIXER("SEC_MI2S_RX_1 Audio Mixer", SND_SOC_NOPM, 0, 0, + secondary_mi2s_rx_1_mixer_controls, + ARRAY_SIZE(secondary_mi2s_rx_1_mixer_controls)), + SND_SOC_DAPM_MIXER("SEC_MI2S_RX_2 Audio Mixer", SND_SOC_NOPM, 0, 0, + secondary_mi2s_rx_2_mixer_controls, + ARRAY_SIZE(secondary_mi2s_rx_2_mixer_controls)), + SND_SOC_DAPM_MIXER("SEC_MI2S_RX_3 Audio Mixer", SND_SOC_NOPM, 0, 0, + secondary_mi2s_rx_3_mixer_controls, + ARRAY_SIZE(secondary_mi2s_rx_3_mixer_controls)), + SND_SOC_DAPM_MIXER("SEC_MI2S_RX_4 Audio Mixer", SND_SOC_NOPM, 0, 0, + secondary_mi2s_rx_4_mixer_controls, + ARRAY_SIZE(secondary_mi2s_rx_4_mixer_controls)), + SND_SOC_DAPM_MIXER("TERT_MI2S_RX_1 Audio Mixer", SND_SOC_NOPM, 0, 0, + tertiary_mi2s_rx_1_mixer_controls, + ARRAY_SIZE(tertiary_mi2s_rx_1_mixer_controls)), + SND_SOC_DAPM_MIXER("TERT_MI2S_RX_2 Audio Mixer", SND_SOC_NOPM, 0, 0, + tertiary_mi2s_rx_2_mixer_controls, + ARRAY_SIZE(tertiary_mi2s_rx_2_mixer_controls)), + SND_SOC_DAPM_MIXER("TERT_MI2S_RX_3 Audio Mixer", SND_SOC_NOPM, 0, 0, + tertiary_mi2s_rx_3_mixer_controls, + ARRAY_SIZE(tertiary_mi2s_rx_3_mixer_controls)), + SND_SOC_DAPM_MIXER("TERT_MI2S_RX_4 Audio Mixer", SND_SOC_NOPM, 0, 0, + tertiary_mi2s_rx_4_mixer_controls, + ARRAY_SIZE(tertiary_mi2s_rx_4_mixer_controls)), + SND_SOC_DAPM_MIXER("QUAT_MI2S_RX_1 Audio Mixer", SND_SOC_NOPM, 0, 0, + quaternary_mi2s_rx_1_mixer_controls, + ARRAY_SIZE(quaternary_mi2s_rx_1_mixer_controls)), + SND_SOC_DAPM_MIXER("QUAT_MI2S_RX_2 Audio Mixer", SND_SOC_NOPM, 0, 0, + quaternary_mi2s_rx_2_mixer_controls, + ARRAY_SIZE(quaternary_mi2s_rx_2_mixer_controls)), + SND_SOC_DAPM_MIXER("QUAT_MI2S_RX_3 Audio Mixer", SND_SOC_NOPM, 0, 0, + quaternary_mi2s_rx_3_mixer_controls, + ARRAY_SIZE(quaternary_mi2s_rx_3_mixer_controls)), + SND_SOC_DAPM_MIXER("QUAT_MI2S_RX_4 Audio Mixer", SND_SOC_NOPM, 0, 0, + quaternary_mi2s_rx_4_mixer_controls, + ARRAY_SIZE(quaternary_mi2s_rx_4_mixer_controls)), SND_SOC_DAPM_MIXER("SEC_MI2S_RX Audio Mixer", SND_SOC_NOPM, 0, 0, secondary_mi2s_rx_mixer_controls, ARRAY_SIZE(secondary_mi2s_rx_mixer_controls)), @@ -14346,6 +15524,222 @@ static const struct snd_soc_dapm_route intercon[] = { {"QUAT_TDM_RX_3 Audio Mixer", "MultiMedia26", "MM_DL26"}, {"QUAT_TDM_RX_3", NULL, "QUAT_TDM_RX_3 Audio Mixer"}, + {"SEC_MI2S_RX_1 Audio Mixer", "MultiMedia1", "MM_DL1"}, + {"SEC_MI2S_RX_1 Audio Mixer", "MultiMedia2", "MM_DL2"}, + {"SEC_MI2S_RX_1 Audio Mixer", "MultiMedia3", "MM_DL3"}, + {"SEC_MI2S_RX_1 Audio Mixer", "MultiMedia4", "MM_DL4"}, + {"SEC_MI2S_RX_1 Audio Mixer", "MultiMedia5", "MM_DL5"}, + {"SEC_MI2S_RX_1 Audio Mixer", "MultiMedia6", "MM_DL6"}, + {"SEC_MI2S_RX_1 Audio Mixer", "MultiMedia7", "MM_DL7"}, + {"SEC_MI2S_RX_1 Audio Mixer", "MultiMedia8", "MM_DL8"}, + {"SEC_MI2S_RX_1 Audio Mixer", "MultiMedia10", "MM_DL10"}, + {"SEC_MI2S_RX_1 Audio Mixer", "MultiMedia11", "MM_DL11"}, + {"SEC_MI2S_RX_1 Audio Mixer", "MultiMedia12", "MM_DL12"}, + {"SEC_MI2S_RX_1 Audio Mixer", "MultiMedia13", "MM_DL13"}, + {"SEC_MI2S_RX_1 Audio Mixer", "MultiMedia14", "MM_DL14"}, + {"SEC_MI2S_RX_1 Audio Mixer", "MultiMedia15", "MM_DL15"}, + {"SEC_MI2S_RX_1 Audio Mixer", "MultiMedia16", "MM_DL16"}, + {"SEC_MI2S_RX_1 Audio Mixer", "MultiMedia26", "MM_DL26"}, + {"SEC_MI2S_RX_1", NULL, "SEC_MI2S_RX_1 Audio Mixer"}, + + {"SEC_MI2S_RX_2 Audio Mixer", "MultiMedia1", "MM_DL1"}, + {"SEC_MI2S_RX_2 Audio Mixer", "MultiMedia2", "MM_DL2"}, + {"SEC_MI2S_RX_2 Audio Mixer", "MultiMedia3", "MM_DL3"}, + {"SEC_MI2S_RX_2 Audio Mixer", "MultiMedia4", "MM_DL4"}, + {"SEC_MI2S_RX_2 Audio Mixer", "MultiMedia5", "MM_DL5"}, + {"SEC_MI2S_RX_2 Audio Mixer", "MultiMedia6", "MM_DL6"}, + {"SEC_MI2S_RX_2 Audio Mixer", "MultiMedia7", "MM_DL7"}, + {"SEC_MI2S_RX_2 Audio Mixer", "MultiMedia8", "MM_DL8"}, + {"SEC_MI2S_RX_2 Audio Mixer", "MultiMedia10", "MM_DL10"}, + {"SEC_MI2S_RX_2 Audio Mixer", "MultiMedia11", "MM_DL11"}, + {"SEC_MI2S_RX_2 Audio Mixer", "MultiMedia12", "MM_DL12"}, + {"SEC_MI2S_RX_2 Audio Mixer", "MultiMedia13", "MM_DL13"}, + {"SEC_MI2S_RX_2 Audio Mixer", "MultiMedia14", "MM_DL14"}, + {"SEC_MI2S_RX_2 Audio Mixer", "MultiMedia15", "MM_DL15"}, + {"SEC_MI2S_RX_2 Audio Mixer", "MultiMedia16", "MM_DL16"}, + {"SEC_MI2S_RX_2 Audio Mixer", "MultiMedia26", "MM_DL26"}, + {"SEC_MI2S_RX_2", NULL, "SEC_MI2S_RX_2 Audio Mixer"}, + + {"SEC_MI2S_RX_3 Audio Mixer", "MultiMedia1", "MM_DL1"}, + {"SEC_MI2S_RX_3 Audio Mixer", "MultiMedia2", "MM_DL2"}, + {"SEC_MI2S_RX_3 Audio Mixer", "MultiMedia3", "MM_DL3"}, + {"SEC_MI2S_RX_3 Audio Mixer", "MultiMedia4", "MM_DL4"}, + {"SEC_MI2S_RX_3 Audio Mixer", "MultiMedia5", "MM_DL5"}, + {"SEC_MI2S_RX_3 Audio Mixer", "MultiMedia6", "MM_DL6"}, + {"SEC_MI2S_RX_3 Audio Mixer", "MultiMedia7", "MM_DL7"}, + {"SEC_MI2S_RX_3 Audio Mixer", "MultiMedia8", "MM_DL8"}, + {"SEC_MI2S_RX_3 Audio Mixer", "MultiMedia10", "MM_DL10"}, + {"SEC_MI2S_RX_3 Audio Mixer", "MultiMedia11", "MM_DL11"}, + {"SEC_MI2S_RX_3 Audio Mixer", "MultiMedia12", "MM_DL12"}, + {"SEC_MI2S_RX_3 Audio Mixer", "MultiMedia13", "MM_DL13"}, + {"SEC_MI2S_RX_3 Audio Mixer", "MultiMedia14", "MM_DL14"}, + {"SEC_MI2S_RX_3 Audio Mixer", "MultiMedia15", "MM_DL15"}, + {"SEC_MI2S_RX_3 Audio Mixer", "MultiMedia16", "MM_DL16"}, + {"SEC_MI2S_RX_3 Audio Mixer", "MultiMedia26", "MM_DL26"}, + {"SEC_MI2S_RX_3", NULL, "SEC_MI2S_RX_3 Audio Mixer"}, + + {"SEC_MI2S_RX_4 Audio Mixer", "MultiMedia1", "MM_DL1"}, + {"SEC_MI2S_RX_4 Audio Mixer", "MultiMedia2", "MM_DL2"}, + {"SEC_MI2S_RX_4 Audio Mixer", "MultiMedia3", "MM_DL3"}, + {"SEC_MI2S_RX_4 Audio Mixer", "MultiMedia4", "MM_DL4"}, + {"SEC_MI2S_RX_4 Audio Mixer", "MultiMedia5", "MM_DL5"}, + {"SEC_MI2S_RX_4 Audio Mixer", "MultiMedia6", "MM_DL6"}, + {"SEC_MI2S_RX_4 Audio Mixer", "MultiMedia7", "MM_DL7"}, + {"SEC_MI2S_RX_4 Audio Mixer", "MultiMedia8", "MM_DL8"}, + {"SEC_MI2S_RX_4 Audio Mixer", "MultiMedia10", "MM_DL10"}, + {"SEC_MI2S_RX_4 Audio Mixer", "MultiMedia11", "MM_DL11"}, + {"SEC_MI2S_RX_4 Audio Mixer", "MultiMedia12", "MM_DL12"}, + {"SEC_MI2S_RX_4 Audio Mixer", "MultiMedia13", "MM_DL13"}, + {"SEC_MI2S_RX_4 Audio Mixer", "MultiMedia14", "MM_DL14"}, + {"SEC_MI2S_RX_4 Audio Mixer", "MultiMedia15", "MM_DL15"}, + {"SEC_MI2S_RX_4 Audio Mixer", "MultiMedia16", "MM_DL16"}, + {"SEC_MI2S_RX_4 Audio Mixer", "MultiMedia26", "MM_DL26"}, + {"SEC_MI2S_RX_4", NULL, "SEC_MI2S_RX_4 Audio Mixer"}, + + {"TERT_MI2S_RX_1 Audio Mixer", "MultiMedia1", "MM_DL1"}, + {"TERT_MI2S_RX_1 Audio Mixer", "MultiMedia2", "MM_DL2"}, + {"TERT_MI2S_RX_1 Audio Mixer", "MultiMedia3", "MM_DL3"}, + {"TERT_MI2S_RX_1 Audio Mixer", "MultiMedia4", "MM_DL4"}, + {"TERT_MI2S_RX_1 Audio Mixer", "MultiMedia5", "MM_DL5"}, + {"TERT_MI2S_RX_1 Audio Mixer", "MultiMedia6", "MM_DL6"}, + {"TERT_MI2S_RX_1 Audio Mixer", "MultiMedia7", "MM_DL7"}, + {"TERT_MI2S_RX_1 Audio Mixer", "MultiMedia8", "MM_DL8"}, + {"TERT_MI2S_RX_1 Audio Mixer", "MultiMedia10", "MM_DL10"}, + {"TERT_MI2S_RX_1 Audio Mixer", "MultiMedia11", "MM_DL11"}, + {"TERT_MI2S_RX_1 Audio Mixer", "MultiMedia12", "MM_DL12"}, + {"TERT_MI2S_RX_1 Audio Mixer", "MultiMedia13", "MM_DL13"}, + {"TERT_MI2S_RX_1 Audio Mixer", "MultiMedia14", "MM_DL14"}, + {"TERT_MI2S_RX_1 Audio Mixer", "MultiMedia15", "MM_DL15"}, + {"TERT_MI2S_RX_1 Audio Mixer", "MultiMedia16", "MM_DL16"}, + {"TERT_MI2S_RX_1 Audio Mixer", "MultiMedia26", "MM_DL26"}, + {"TERT_MI2S_RX_1", NULL, "TERT_MI2S_RX_1 Audio Mixer"}, + + {"TERT_MI2S_RX_2 Audio Mixer", "MultiMedia1", "MM_DL1"}, + {"TERT_MI2S_RX_2 Audio Mixer", "MultiMedia2", "MM_DL2"}, + {"TERT_MI2S_RX_2 Audio Mixer", "MultiMedia3", "MM_DL3"}, + {"TERT_MI2S_RX_2 Audio Mixer", "MultiMedia4", "MM_DL4"}, + {"TERT_MI2S_RX_2 Audio Mixer", "MultiMedia5", "MM_DL5"}, + {"TERT_MI2S_RX_2 Audio Mixer", "MultiMedia6", "MM_DL6"}, + {"TERT_MI2S_RX_2 Audio Mixer", "MultiMedia7", "MM_DL7"}, + {"TERT_MI2S_RX_2 Audio Mixer", "MultiMedia8", "MM_DL8"}, + {"TERT_MI2S_RX_2 Audio Mixer", "MultiMedia10", "MM_DL10"}, + {"TERT_MI2S_RX_2 Audio Mixer", "MultiMedia11", "MM_DL11"}, + {"TERT_MI2S_RX_2 Audio Mixer", "MultiMedia12", "MM_DL12"}, + {"TERT_MI2S_RX_2 Audio Mixer", "MultiMedia13", "MM_DL13"}, + {"TERT_MI2S_RX_2 Audio Mixer", "MultiMedia14", "MM_DL14"}, + {"TERT_MI2S_RX_2 Audio Mixer", "MultiMedia15", "MM_DL15"}, + {"TERT_MI2S_RX_2 Audio Mixer", "MultiMedia16", "MM_DL16"}, + {"TERT_MI2S_RX_2 Audio Mixer", "MultiMedia26", "MM_DL26"}, + {"TERT_MI2S_RX_2", NULL, "TERT_MI2S_RX_2 Audio Mixer"}, + + {"TERT_MI2S_RX_3 Audio Mixer", "MultiMedia1", "MM_DL1"}, + {"TERT_MI2S_RX_3 Audio Mixer", "MultiMedia2", "MM_DL2"}, + {"TERT_MI2S_RX_3 Audio Mixer", "MultiMedia3", "MM_DL3"}, + {"TERT_MI2S_RX_3 Audio Mixer", "MultiMedia4", "MM_DL4"}, + {"TERT_MI2S_RX_3 Audio Mixer", "MultiMedia5", "MM_DL5"}, + {"TERT_MI2S_RX_3 Audio Mixer", "MultiMedia6", "MM_DL6"}, + {"TERT_MI2S_RX_3 Audio Mixer", "MultiMedia7", "MM_DL7"}, + {"TERT_MI2S_RX_3 Audio Mixer", "MultiMedia8", "MM_DL8"}, + {"TERT_MI2S_RX_3 Audio Mixer", "MultiMedia10", "MM_DL10"}, + {"TERT_MI2S_RX_3 Audio Mixer", "MultiMedia11", "MM_DL11"}, + {"TERT_MI2S_RX_3 Audio Mixer", "MultiMedia12", "MM_DL12"}, + {"TERT_MI2S_RX_3 Audio Mixer", "MultiMedia13", "MM_DL13"}, + {"TERT_MI2S_RX_3 Audio Mixer", "MultiMedia14", "MM_DL14"}, + {"TERT_MI2S_RX_3 Audio Mixer", "MultiMedia15", "MM_DL15"}, + {"TERT_MI2S_RX_3 Audio Mixer", "MultiMedia16", "MM_DL16"}, + {"TERT_MI2S_RX_3 Audio Mixer", "MultiMedia26", "MM_DL26"}, + {"TERT_MI2S_RX_3", NULL, "TERT_MI2S_RX_3 Audio Mixer"}, + + {"TERT_MI2S_RX_4 Audio Mixer", "MultiMedia1", "MM_DL1"}, + {"TERT_MI2S_RX_4 Audio Mixer", "MultiMedia2", "MM_DL2"}, + {"TERT_MI2S_RX_4 Audio Mixer", "MultiMedia3", "MM_DL3"}, + {"TERT_MI2S_RX_4 Audio Mixer", "MultiMedia4", "MM_DL4"}, + {"TERT_MI2S_RX_4 Audio Mixer", "MultiMedia5", "MM_DL5"}, + {"TERT_MI2S_RX_4 Audio Mixer", "MultiMedia6", "MM_DL6"}, + {"TERT_MI2S_RX_4 Audio Mixer", "MultiMedia7", "MM_DL7"}, + {"TERT_MI2S_RX_4 Audio Mixer", "MultiMedia8", "MM_DL8"}, + {"TERT_MI2S_RX_4 Audio Mixer", "MultiMedia10", "MM_DL10"}, + {"TERT_MI2S_RX_4 Audio Mixer", "MultiMedia11", "MM_DL11"}, + {"TERT_MI2S_RX_4 Audio Mixer", "MultiMedia12", "MM_DL12"}, + {"TERT_MI2S_RX_4 Audio Mixer", "MultiMedia13", "MM_DL13"}, + {"TERT_MI2S_RX_4 Audio Mixer", "MultiMedia14", "MM_DL14"}, + {"TERT_MI2S_RX_4 Audio Mixer", "MultiMedia15", "MM_DL15"}, + {"TERT_MI2S_RX_4 Audio Mixer", "MultiMedia16", "MM_DL16"}, + {"TERT_MI2S_RX_4 Audio Mixer", "MultiMedia26", "MM_DL26"}, + {"TERT_MI2S_RX_4", NULL, "TERT_MI2S_RX_4 Audio Mixer"}, + + {"QUAT_MI2S_RX_1 Audio Mixer", "MultiMedia1", "MM_DL1"}, + {"QUAT_MI2S_RX_1 Audio Mixer", "MultiMedia2", "MM_DL2"}, + {"QUAT_MI2S_RX_1 Audio Mixer", "MultiMedia3", "MM_DL3"}, + {"QUAT_MI2S_RX_1 Audio Mixer", "MultiMedia4", "MM_DL4"}, + {"QUAT_MI2S_RX_1 Audio Mixer", "MultiMedia5", "MM_DL5"}, + {"QUAT_MI2S_RX_1 Audio Mixer", "MultiMedia6", "MM_DL6"}, + {"QUAT_MI2S_RX_1 Audio Mixer", "MultiMedia7", "MM_DL7"}, + {"QUAT_MI2S_RX_1 Audio Mixer", "MultiMedia8", "MM_DL8"}, + {"QUAT_MI2S_RX_1 Audio Mixer", "MultiMedia10", "MM_DL10"}, + {"QUAT_MI2S_RX_1 Audio Mixer", "MultiMedia11", "MM_DL11"}, + {"QUAT_MI2S_RX_1 Audio Mixer", "MultiMedia12", "MM_DL12"}, + {"QUAT_MI2S_RX_1 Audio Mixer", "MultiMedia13", "MM_DL13"}, + {"QUAT_MI2S_RX_1 Audio Mixer", "MultiMedia14", "MM_DL14"}, + {"QUAT_MI2S_RX_1 Audio Mixer", "MultiMedia15", "MM_DL15"}, + {"QUAT_MI2S_RX_1 Audio Mixer", "MultiMedia16", "MM_DL16"}, + {"QUAT_MI2S_RX_1 Audio Mixer", "MultiMedia26", "MM_DL26"}, + {"QUAT_MI2S_RX_1", NULL, "QUAT_MI2S_RX_1 Audio Mixer"}, + + {"QUAT_MI2S_RX_2 Audio Mixer", "MultiMedia1", "MM_DL1"}, + {"QUAT_MI2S_RX_2 Audio Mixer", "MultiMedia2", "MM_DL2"}, + {"QUAT_MI2S_RX_2 Audio Mixer", "MultiMedia3", "MM_DL3"}, + {"QUAT_MI2S_RX_2 Audio Mixer", "MultiMedia4", "MM_DL4"}, + {"QUAT_MI2S_RX_2 Audio Mixer", "MultiMedia5", "MM_DL5"}, + {"QUAT_MI2S_RX_2 Audio Mixer", "MultiMedia6", "MM_DL6"}, + {"QUAT_MI2S_RX_2 Audio Mixer", "MultiMedia7", "MM_DL7"}, + {"QUAT_MI2S_RX_2 Audio Mixer", "MultiMedia8", "MM_DL8"}, + {"QUAT_MI2S_RX_2 Audio Mixer", "MultiMedia10", "MM_DL10"}, + {"QUAT_MI2S_RX_2 Audio Mixer", "MultiMedia11", "MM_DL11"}, + {"QUAT_MI2S_RX_2 Audio Mixer", "MultiMedia12", "MM_DL12"}, + {"QUAT_MI2S_RX_2 Audio Mixer", "MultiMedia13", "MM_DL13"}, + {"QUAT_MI2S_RX_2 Audio Mixer", "MultiMedia14", "MM_DL14"}, + {"QUAT_MI2S_RX_2 Audio Mixer", "MultiMedia15", "MM_DL15"}, + {"QUAT_MI2S_RX_2 Audio Mixer", "MultiMedia16", "MM_DL16"}, + {"QUAT_MI2S_RX_2 Audio Mixer", "MultiMedia26", "MM_DL26"}, + {"QUAT_MI2S_RX_2", NULL, "QUAT_MI2S_RX_2 Audio Mixer"}, + + {"QUAT_MI2S_RX_3 Audio Mixer", "MultiMedia1", "MM_DL1"}, + {"QUAT_MI2S_RX_3 Audio Mixer", "MultiMedia2", "MM_DL2"}, + {"QUAT_MI2S_RX_3 Audio Mixer", "MultiMedia3", "MM_DL3"}, + {"QUAT_MI2S_RX_3 Audio Mixer", "MultiMedia4", "MM_DL4"}, + {"QUAT_MI2S_RX_3 Audio Mixer", "MultiMedia5", "MM_DL5"}, + {"QUAT_MI2S_RX_3 Audio Mixer", "MultiMedia6", "MM_DL6"}, + {"QUAT_MI2S_RX_3 Audio Mixer", "MultiMedia7", "MM_DL7"}, + {"QUAT_MI2S_RX_3 Audio Mixer", "MultiMedia8", "MM_DL8"}, + {"QUAT_MI2S_RX_3 Audio Mixer", "MultiMedia10", "MM_DL10"}, + {"QUAT_MI2S_RX_3 Audio Mixer", "MultiMedia11", "MM_DL11"}, + {"QUAT_MI2S_RX_3 Audio Mixer", "MultiMedia12", "MM_DL12"}, + {"QUAT_MI2S_RX_3 Audio Mixer", "MultiMedia13", "MM_DL13"}, + {"QUAT_MI2S_RX_3 Audio Mixer", "MultiMedia14", "MM_DL14"}, + {"QUAT_MI2S_RX_3 Audio Mixer", "MultiMedia15", "MM_DL15"}, + {"QUAT_MI2S_RX_3 Audio Mixer", "MultiMedia16", "MM_DL16"}, + {"QUAT_MI2S_RX_3 Audio Mixer", "MultiMedia26", "MM_DL26"}, + {"QUAT_MI2S_RX_3", NULL, "QUAT_MI2S_RX_3 Audio Mixer"}, + + {"QUAT_MI2S_RX_4 Audio Mixer", "MultiMedia1", "MM_DL1"}, + {"QUAT_MI2S_RX_4 Audio Mixer", "MultiMedia2", "MM_DL2"}, + {"QUAT_MI2S_RX_4 Audio Mixer", "MultiMedia3", "MM_DL3"}, + {"QUAT_MI2S_RX_4 Audio Mixer", "MultiMedia4", "MM_DL4"}, + {"QUAT_MI2S_RX_4 Audio Mixer", "MultiMedia5", "MM_DL5"}, + {"QUAT_MI2S_RX_4 Audio Mixer", "MultiMedia6", "MM_DL6"}, + {"QUAT_MI2S_RX_4 Audio Mixer", "MultiMedia7", "MM_DL7"}, + {"QUAT_MI2S_RX_4 Audio Mixer", "MultiMedia8", "MM_DL8"}, + {"QUAT_MI2S_RX_4 Audio Mixer", "MultiMedia10", "MM_DL10"}, + {"QUAT_MI2S_RX_4 Audio Mixer", "MultiMedia11", "MM_DL11"}, + {"QUAT_MI2S_RX_4 Audio Mixer", "MultiMedia12", "MM_DL12"}, + {"QUAT_MI2S_RX_4 Audio Mixer", "MultiMedia13", "MM_DL13"}, + {"QUAT_MI2S_RX_4 Audio Mixer", "MultiMedia14", "MM_DL14"}, + {"QUAT_MI2S_RX_4 Audio Mixer", "MultiMedia15", "MM_DL15"}, + {"QUAT_MI2S_RX_4 Audio Mixer", "MultiMedia16", "MM_DL16"}, + {"QUAT_MI2S_RX_4 Audio Mixer", "MultiMedia26", "MM_DL26"}, + {"QUAT_MI2S_RX_4", NULL, "QUAT_MI2S_RX_4 Audio Mixer"}, + {"MultiMedia1 Mixer", "PRI_TX", "PRI_I2S_TX"}, {"MultiMedia1 Mixer", "MI2S_TX", "MI2S_TX"}, {"MultiMedia2 Mixer", "MI2S_TX", "MI2S_TX"}, @@ -14423,6 +15817,19 @@ static const struct snd_soc_dapm_route intercon[] = { {"MultiMedia1 Mixer", "QUAT_TDM_TX_2", "QUAT_TDM_TX_2"}, {"MultiMedia1 Mixer", "QUAT_TDM_TX_3", "QUAT_TDM_TX_3"}, + {"MultiMedia1 Mixer", "SEC_MI2S_TX_1", "SEC_MI2S_TX_1"}, + {"MultiMedia1 Mixer", "SEC_MI2S_TX_2", "SEC_MI2S_TX_2"}, + {"MultiMedia1 Mixer", "SEC_MI2S_TX_3", "SEC_MI2S_TX_3"}, + {"MultiMedia1 Mixer", "SEC_MI2S_TX_4", "SEC_MI2S_TX_4"}, + {"MultiMedia1 Mixer", "TERT_MI2S_TX_1", "TERT_MI2S_TX_1"}, + {"MultiMedia1 Mixer", "TERT_MI2S_TX_2", "TERT_MI2S_TX_2"}, + {"MultiMedia1 Mixer", "TERT_MI2S_TX_3", "TERT_MI2S_TX_3"}, + {"MultiMedia1 Mixer", "TERT_MI2S_TX_4", "TERT_MI2S_TX_4"}, + {"MultiMedia1 Mixer", "QUAT_MI2S_TX_1", "QUAT_MI2S_TX_1"}, + {"MultiMedia1 Mixer", "QUAT_MI2S_TX_2", "QUAT_MI2S_TX_2"}, + {"MultiMedia1 Mixer", "QUAT_MI2S_TX_3", "QUAT_MI2S_TX_3"}, + {"MultiMedia1 Mixer", "QUAT_MI2S_TX_4", "QUAT_MI2S_TX_4"}, + {"MultiMedia2 Mixer", "PRI_TDM_TX_0", "PRI_TDM_TX_0"}, {"MultiMedia2 Mixer", "PRI_TDM_TX_1", "PRI_TDM_TX_1"}, {"MultiMedia2 Mixer", "PRI_TDM_TX_2", "PRI_TDM_TX_2"}, @@ -14439,6 +15846,18 @@ static const struct snd_soc_dapm_route intercon[] = { {"MultiMedia2 Mixer", "QUAT_TDM_TX_1", "QUAT_TDM_TX_1"}, {"MultiMedia2 Mixer", "QUAT_TDM_TX_2", "QUAT_TDM_TX_2"}, {"MultiMedia2 Mixer", "QUAT_TDM_TX_3", "QUAT_TDM_TX_3"}, + {"MultiMedia2 Mixer", "SEC_MI2S_TX_1", "SEC_MI2S_TX_1"}, + {"MultiMedia2 Mixer", "SEC_MI2S_TX_2", "SEC_MI2S_TX_2"}, + {"MultiMedia2 Mixer", "SEC_MI2S_TX_3", "SEC_MI2S_TX_3"}, + {"MultiMedia2 Mixer", "SEC_MI2S_TX_4", "SEC_MI2S_TX_4"}, + {"MultiMedia2 Mixer", "TERT_MI2S_TX_1", "TERT_MI2S_TX_1"}, + {"MultiMedia2 Mixer", "TERT_MI2S_TX_2", "TERT_MI2S_TX_2"}, + {"MultiMedia2 Mixer", "TERT_MI2S_TX_3", "TERT_MI2S_TX_3"}, + {"MultiMedia2 Mixer", "TERT_MI2S_TX_4", "TERT_MI2S_TX_4"}, + {"MultiMedia2 Mixer", "QUAT_MI2S_TX_1", "QUAT_MI2S_TX_1"}, + {"MultiMedia2 Mixer", "QUAT_MI2S_TX_2", "QUAT_MI2S_TX_2"}, + {"MultiMedia2 Mixer", "QUAT_MI2S_TX_3", "QUAT_MI2S_TX_3"}, + {"MultiMedia2 Mixer", "QUAT_MI2S_TX_4", "QUAT_MI2S_TX_4"}, {"MultiMedia3 Mixer", "PRI_TDM_TX_0", "PRI_TDM_TX_0"}, {"MultiMedia3 Mixer", "PRI_TDM_TX_1", "PRI_TDM_TX_1"}, @@ -14456,6 +15875,18 @@ static const struct snd_soc_dapm_route intercon[] = { {"MultiMedia3 Mixer", "QUAT_TDM_TX_1", "QUAT_TDM_TX_1"}, {"MultiMedia3 Mixer", "QUAT_TDM_TX_2", "QUAT_TDM_TX_2"}, {"MultiMedia3 Mixer", "QUAT_TDM_TX_3", "QUAT_TDM_TX_3"}, + {"MultiMedia3 Mixer", "SEC_MI2S_TX_1", "SEC_MI2S_TX_1"}, + {"MultiMedia3 Mixer", "SEC_MI2S_TX_2", "SEC_MI2S_TX_2"}, + {"MultiMedia3 Mixer", "SEC_MI2S_TX_3", "SEC_MI2S_TX_3"}, + {"MultiMedia3 Mixer", "SEC_MI2S_TX_4", "SEC_MI2S_TX_4"}, + {"MultiMedia3 Mixer", "TERT_MI2S_TX_1", "TERT_MI2S_TX_1"}, + {"MultiMedia3 Mixer", "TERT_MI2S_TX_2", "TERT_MI2S_TX_2"}, + {"MultiMedia3 Mixer", "TERT_MI2S_TX_3", "TERT_MI2S_TX_3"}, + {"MultiMedia3 Mixer", "TERT_MI2S_TX_4", "TERT_MI2S_TX_4"}, + {"MultiMedia3 Mixer", "QUAT_MI2S_TX_1", "QUAT_MI2S_TX_1"}, + {"MultiMedia3 Mixer", "QUAT_MI2S_TX_2", "QUAT_MI2S_TX_2"}, + {"MultiMedia3 Mixer", "QUAT_MI2S_TX_3", "QUAT_MI2S_TX_3"}, + {"MultiMedia3 Mixer", "QUAT_MI2S_TX_4", "QUAT_MI2S_TX_4"}, {"MultiMedia4 Mixer", "PRI_TDM_TX_0", "PRI_TDM_TX_0"}, {"MultiMedia4 Mixer", "PRI_TDM_TX_1", "PRI_TDM_TX_1"}, @@ -14490,6 +15921,18 @@ static const struct snd_soc_dapm_route intercon[] = { {"MultiMedia5 Mixer", "QUAT_TDM_TX_1", "QUAT_TDM_TX_1"}, {"MultiMedia5 Mixer", "QUAT_TDM_TX_2", "QUAT_TDM_TX_2"}, {"MultiMedia5 Mixer", "QUAT_TDM_TX_3", "QUAT_TDM_TX_3"}, + {"MultiMedia5 Mixer", "SEC_MI2S_TX_1", "SEC_MI2S_TX_1"}, + {"MultiMedia5 Mixer", "SEC_MI2S_TX_2", "SEC_MI2S_TX_2"}, + {"MultiMedia5 Mixer", "SEC_MI2S_TX_3", "SEC_MI2S_TX_3"}, + {"MultiMedia5 Mixer", "SEC_MI2S_TX_4", "SEC_MI2S_TX_4"}, + {"MultiMedia5 Mixer", "TERT_MI2S_TX_1", "TERT_MI2S_TX_1"}, + {"MultiMedia5 Mixer", "TERT_MI2S_TX_2", "TERT_MI2S_TX_2"}, + {"MultiMedia5 Mixer", "TERT_MI2S_TX_3", "TERT_MI2S_TX_3"}, + {"MultiMedia5 Mixer", "TERT_MI2S_TX_4", "TERT_MI2S_TX_4"}, + {"MultiMedia5 Mixer", "QUAT_MI2S_TX_1", "QUAT_MI2S_TX_1"}, + {"MultiMedia5 Mixer", "QUAT_MI2S_TX_2", "QUAT_MI2S_TX_2"}, + {"MultiMedia5 Mixer", "QUAT_MI2S_TX_3", "QUAT_MI2S_TX_3"}, + {"MultiMedia5 Mixer", "QUAT_MI2S_TX_4", "QUAT_MI2S_TX_4"}, {"MultiMedia6 Mixer", "PRI_TDM_TX_0", "PRI_TDM_TX_0"}, {"MultiMedia6 Mixer", "PRI_TDM_TX_1", "PRI_TDM_TX_1"}, @@ -14533,11 +15976,35 @@ static const struct snd_soc_dapm_route intercon[] = { {"MultiMedia9 Mixer", "QUAT_TDM_TX_1", "QUAT_TDM_TX_1"}, {"MultiMedia9 Mixer", "QUAT_TDM_TX_2", "QUAT_TDM_TX_2"}, {"MultiMedia9 Mixer", "QUAT_TDM_TX_3", "QUAT_TDM_TX_3"}, + {"MultiMedia9 Mixer", "SEC_MI2S_TX_1", "SEC_MI2S_TX_1"}, + {"MultiMedia9 Mixer", "SEC_MI2S_TX_2", "SEC_MI2S_TX_2"}, + {"MultiMedia9 Mixer", "SEC_MI2S_TX_3", "SEC_MI2S_TX_3"}, + {"MultiMedia9 Mixer", "SEC_MI2S_TX_4", "SEC_MI2S_TX_4"}, + {"MultiMedia9 Mixer", "TERT_MI2S_TX_1", "TERT_MI2S_TX_1"}, + {"MultiMedia9 Mixer", "TERT_MI2S_TX_2", "TERT_MI2S_TX_2"}, + {"MultiMedia9 Mixer", "TERT_MI2S_TX_3", "TERT_MI2S_TX_3"}, + {"MultiMedia9 Mixer", "TERT_MI2S_TX_4", "TERT_MI2S_TX_4"}, + {"MultiMedia9 Mixer", "QUAT_MI2S_TX_1", "QUAT_MI2S_TX_1"}, + {"MultiMedia9 Mixer", "QUAT_MI2S_TX_2", "QUAT_MI2S_TX_2"}, + {"MultiMedia9 Mixer", "QUAT_MI2S_TX_3", "QUAT_MI2S_TX_3"}, + {"MultiMedia9 Mixer", "QUAT_MI2S_TX_4", "QUAT_MI2S_TX_4"}, {"MultiMedia20 Mixer", "PRI_MI2S_TX", "PRI_MI2S_TX"}, {"MultiMedia20 Mixer", "SEC_MI2S_TX", "SEC_MI2S_TX"}, {"MultiMedia20 Mixer", "TERT_MI2S_TX", "TERT_MI2S_TX"}, {"MultiMedia20 Mixer", "QUAT_MI2S_TX", "QUAT_MI2S_TX"}, + {"MultiMedia20 Mixer", "SEC_MI2S_TX_1", "SEC_MI2S_TX_1"}, + {"MultiMedia20 Mixer", "SEC_MI2S_TX_2", "SEC_MI2S_TX_2"}, + {"MultiMedia20 Mixer", "SEC_MI2S_TX_3", "SEC_MI2S_TX_3"}, + {"MultiMedia20 Mixer", "SEC_MI2S_TX_4", "SEC_MI2S_TX_4"}, + {"MultiMedia20 Mixer", "TERT_MI2S_TX_1", "TERT_MI2S_TX_1"}, + {"MultiMedia20 Mixer", "TERT_MI2S_TX_2", "TERT_MI2S_TX_2"}, + {"MultiMedia20 Mixer", "TERT_MI2S_TX_3", "TERT_MI2S_TX_3"}, + {"MultiMedia20 Mixer", "TERT_MI2S_TX_4", "TERT_MI2S_TX_4"}, + {"MultiMedia20 Mixer", "QUAT_MI2S_TX_1", "QUAT_MI2S_TX_1"}, + {"MultiMedia20 Mixer", "QUAT_MI2S_TX_2", "QUAT_MI2S_TX_2"}, + {"MultiMedia20 Mixer", "QUAT_MI2S_TX_3", "QUAT_MI2S_TX_3"}, + {"MultiMedia20 Mixer", "QUAT_MI2S_TX_4", "QUAT_MI2S_TX_4"}, {"MultiMedia20 Mixer", "PRI_TDM_TX_0", "PRI_TDM_TX_0"}, {"MultiMedia20 Mixer", "PRI_TDM_TX_1", "PRI_TDM_TX_1"}, {"MultiMedia20 Mixer", "PRI_TDM_TX_2", "PRI_TDM_TX_2"}, @@ -16080,6 +17547,18 @@ static const struct snd_soc_dapm_route intercon[] = { {"BE_OUT", NULL, "QUAT_TDM_RX_1"}, {"BE_OUT", NULL, "QUAT_TDM_RX_2"}, {"BE_OUT", NULL, "QUAT_TDM_RX_3"}, + {"BE_OUT", NULL, "SEC_MI2S_RX_1"}, + {"BE_OUT", NULL, "SEC_MI2S_RX_2"}, + {"BE_OUT", NULL, "SEC_MI2S_RX_3"}, + {"BE_OUT", NULL, "SEC_MI2S_RX_4"}, + {"BE_OUT", NULL, "TERT_MI2S_RX_1"}, + {"BE_OUT", NULL, "TERT_MI2S_RX_2"}, + {"BE_OUT", NULL, "TERT_MI2S_RX_3"}, + {"BE_OUT", NULL, "TERT_MI2S_RX_4"}, + {"BE_OUT", NULL, "QUAT_MI2S_RX_1"}, + {"BE_OUT", NULL, "QUAT_MI2S_RX_2"}, + {"BE_OUT", NULL, "QUAT_MI2S_RX_3"}, + {"BE_OUT", NULL, "QUAT_MI2S_RX_4"}, {"PRI_I2S_TX", NULL, "BE_IN"}, {"MI2S_TX", NULL, "BE_IN"}, @@ -16094,6 +17573,18 @@ static const struct snd_soc_dapm_route intercon[] = { {"INT5_MI2S_TX", NULL, "BE_IN"}, {"SEC_MI2S_TX", NULL, "BE_IN"}, {"SENARY_MI2S_TX", NULL, "BE_IN" }, + {"SEC_MI2S_TX_1", NULL, "BE_IN"}, + {"SEC_MI2S_TX_2", NULL, "BE_IN"}, + {"SEC_MI2S_TX_3", NULL, "BE_IN"}, + {"SEC_MI2S_TX_4", NULL, "BE_IN"}, + {"TERT_MI2S_TX_1", NULL, "BE_IN"}, + {"TERT_MI2S_TX_2", NULL, "BE_IN"}, + {"TERT_MI2S_TX_3", NULL, "BE_IN"}, + {"TERT_MI2S_TX_4", NULL, "BE_IN"}, + {"QUAT_MI2S_TX_1", NULL, "BE_IN"}, + {"QUAT_MI2S_TX_2", NULL, "BE_IN"}, + {"QUAT_MI2S_TX_3", NULL, "BE_IN"}, + {"QUAT_MI2S_TX_4", NULL, "BE_IN"}, {"SLIMBUS_0_TX", NULL, "BE_IN" }, {"SLIMBUS_1_TX", NULL, "BE_IN" }, {"SLIMBUS_3_TX", NULL, "BE_IN" }, diff --git a/sound/soc/msm/qdsp6v2/msm-pcm-routing-v2.h b/sound/soc/msm/qdsp6v2/msm-pcm-routing-v2.h index 531f83d752b0..bfeee4ad3607 100644 --- a/sound/soc/msm/qdsp6v2/msm-pcm-routing-v2.h +++ b/sound/soc/msm/qdsp6v2/msm-pcm-routing-v2.h @@ -167,6 +167,34 @@ #define LPASS_BE_INT5_MI2S_TX "INT5_MI2S_TX" #define LPASS_BE_INT6_MI2S_RX "INT6_MI2S_RX" #define LPASS_BE_INT6_MI2S_TX "INT6_MI2S_TX" + +#define LPASS_BE_SEC_MI2S_RX_1 "SEC_MI2S_RX_1" +#define LPASS_BE_SEC_MI2S_RX_2 "SEC_MI2S_RX_2" +#define LPASS_BE_SEC_MI2S_RX_3 "SEC_MI2S_RX_3" +#define LPASS_BE_SEC_MI2S_RX_4 "SEC_MI2S_RX_4" +#define LPASS_BE_SEC_MI2S_TX_1 "SEC_MI2S_TX_1" +#define LPASS_BE_SEC_MI2S_TX_2 "SEC_MI2S_TX_2" +#define LPASS_BE_SEC_MI2S_TX_3 "SEC_MI2S_TX_3" +#define LPASS_BE_SEC_MI2S_TX_4 "SEC_MI2S_TX_4" + +#define LPASS_BE_TERT_MI2S_RX_1 "TERT_MI2S_RX_1" +#define LPASS_BE_TERT_MI2S_RX_2 "TERT_MI2S_RX_2" +#define LPASS_BE_TERT_MI2S_RX_3 "TERT_MI2S_RX_3" +#define LPASS_BE_TERT_MI2S_RX_4 "TERT_MI2S_RX_4" +#define LPASS_BE_TERT_MI2S_TX_1 "TERT_MI2S_TX_1" +#define LPASS_BE_TERT_MI2S_TX_2 "TERT_MI2S_TX_2" +#define LPASS_BE_TERT_MI2S_TX_3 "TERT_MI2S_TX_3" +#define LPASS_BE_TERT_MI2S_TX_4 "TERT_MI2S_TX_4" + +#define LPASS_BE_QUAT_MI2S_RX_1 "QUAT_MI2S_RX_1" +#define LPASS_BE_QUAT_MI2S_RX_2 "QUAT_MI2S_RX_2" +#define LPASS_BE_QUAT_MI2S_RX_3 "QUAT_MI2S_RX_3" +#define LPASS_BE_QUAT_MI2S_RX_4 "QUAT_MI2S_RX_4" +#define LPASS_BE_QUAT_MI2S_TX_1 "QUAT_MI2S_TX_1" +#define LPASS_BE_QUAT_MI2S_TX_2 "QUAT_MI2S_TX_2" +#define LPASS_BE_QUAT_MI2S_TX_3 "QUAT_MI2S_TX_3" +#define LPASS_BE_QUAT_MI2S_TX_4 "QUAT_MI2S_TX_4" + /* For multimedia front-ends, asm session is allocated dynamically. * Hence, asm session/multimedia front-end mapping has to be maintained. * Due to this reason, additional multimedia front-end must be placed before @@ -373,6 +401,30 @@ enum { MSM_BACKEND_DAI_INT5_MI2S_TX, MSM_BACKEND_DAI_INT6_MI2S_RX, MSM_BACKEND_DAI_INT6_MI2S_TX, + MSM_BACKEND_DAI_SECONDARY_MI2S_RX_1, + MSM_BACKEND_DAI_SECONDARY_MI2S_RX_2, + MSM_BACKEND_DAI_SECONDARY_MI2S_RX_3, + MSM_BACKEND_DAI_SECONDARY_MI2S_RX_4, + MSM_BACKEND_DAI_SECONDARY_MI2S_TX_1, + MSM_BACKEND_DAI_SECONDARY_MI2S_TX_2, + MSM_BACKEND_DAI_SECONDARY_MI2S_TX_3, + MSM_BACKEND_DAI_SECONDARY_MI2S_TX_4, + MSM_BACKEND_DAI_TERTIARY_MI2S_RX_1, + MSM_BACKEND_DAI_TERTIARY_MI2S_RX_2, + MSM_BACKEND_DAI_TERTIARY_MI2S_RX_3, + MSM_BACKEND_DAI_TERTIARY_MI2S_RX_4, + MSM_BACKEND_DAI_TERTIARY_MI2S_TX_1, + MSM_BACKEND_DAI_TERTIARY_MI2S_TX_2, + MSM_BACKEND_DAI_TERTIARY_MI2S_TX_3, + MSM_BACKEND_DAI_TERTIARY_MI2S_TX_4, + MSM_BACKEND_DAI_QUATERNARY_MI2S_RX_1, + MSM_BACKEND_DAI_QUATERNARY_MI2S_RX_2, + MSM_BACKEND_DAI_QUATERNARY_MI2S_RX_3, + MSM_BACKEND_DAI_QUATERNARY_MI2S_RX_4, + MSM_BACKEND_DAI_QUATERNARY_MI2S_TX_1, + MSM_BACKEND_DAI_QUATERNARY_MI2S_TX_2, + MSM_BACKEND_DAI_QUATERNARY_MI2S_TX_3, + MSM_BACKEND_DAI_QUATERNARY_MI2S_TX_4, MSM_BACKEND_DAI_MAX, }; diff --git a/sound/soc/msm/qdsp6v2/q6afe.c b/sound/soc/msm/qdsp6v2/q6afe.c index 0524ca21feba..c7aecd5758d4 100644 --- a/sound/soc/msm/qdsp6v2/q6afe.c +++ b/sound/soc/msm/qdsp6v2/q6afe.c @@ -785,6 +785,18 @@ int afe_get_port_type(u16 port_id) case AFE_PORT_ID_INT4_MI2S_RX: case AFE_PORT_ID_INT5_MI2S_RX: case AFE_PORT_ID_INT6_MI2S_RX: + case AFE_PORT_ID_SECONDARY_MI2S_RX_1: + case AFE_PORT_ID_SECONDARY_MI2S_RX_2: + case AFE_PORT_ID_SECONDARY_MI2S_RX_3: + case AFE_PORT_ID_SECONDARY_MI2S_RX_4: + case AFE_PORT_ID_TERTIARY_MI2S_RX_1: + case AFE_PORT_ID_TERTIARY_MI2S_RX_2: + case AFE_PORT_ID_TERTIARY_MI2S_RX_3: + case AFE_PORT_ID_TERTIARY_MI2S_RX_4: + case AFE_PORT_ID_QUATERNARY_MI2S_RX_1: + case AFE_PORT_ID_QUATERNARY_MI2S_RX_2: + case AFE_PORT_ID_QUATERNARY_MI2S_RX_3: + case AFE_PORT_ID_QUATERNARY_MI2S_RX_4: ret = MSM_AFE_PORT_TYPE_RX; break; @@ -856,6 +868,18 @@ int afe_get_port_type(u16 port_id) case AFE_PORT_ID_INT4_MI2S_TX: case AFE_PORT_ID_INT5_MI2S_TX: case AFE_PORT_ID_INT6_MI2S_TX: + case AFE_PORT_ID_SECONDARY_MI2S_TX_1: + case AFE_PORT_ID_SECONDARY_MI2S_TX_2: + case AFE_PORT_ID_SECONDARY_MI2S_TX_3: + case AFE_PORT_ID_SECONDARY_MI2S_TX_4: + case AFE_PORT_ID_TERTIARY_MI2S_TX_1: + case AFE_PORT_ID_TERTIARY_MI2S_TX_2: + case AFE_PORT_ID_TERTIARY_MI2S_TX_3: + case AFE_PORT_ID_TERTIARY_MI2S_TX_4: + case AFE_PORT_ID_QUATERNARY_MI2S_TX_1: + case AFE_PORT_ID_QUATERNARY_MI2S_TX_2: + case AFE_PORT_ID_QUATERNARY_MI2S_TX_3: + case AFE_PORT_ID_QUATERNARY_MI2S_TX_4: ret = MSM_AFE_PORT_TYPE_TX; break; @@ -2734,6 +2758,118 @@ int afe_send_custom_tdm_header_cfg( return ret; } +int afe_i2s_port_start(u16 port_id, struct afe_i2s_port_config *i2s_port, + u32 rate, u16 num_groups) +{ + struct param_hdr_v3 param_hdr = {0}; + int index = 0; + uint16_t port_index = 0; + enum afe_mad_type mad_type = MAD_HW_NONE; + int ret = 0; + + if (!i2s_port) { + pr_err("%s: Error, no configuration data\n", __func__); + return -EINVAL; + } + + pr_debug("%s: port id: 0x%x\n", __func__, port_id); + + index = q6audio_get_port_index(port_id); + if (index < 0 || index >= AFE_MAX_PORTS) { + pr_err("%s: AFE port index[%d] invalid!\n", + __func__, index); + return -EINVAL; + } + ret = q6audio_validate_port(port_id); + if (ret < 0) { + pr_err("%s: port id: 0x%x ret %d\n", __func__, port_id, ret); + return -EINVAL; + } + + ret = afe_q6_interface_prepare(); + if (ret != 0) { + pr_err("%s: Q6 interface prepare failed %d\n", __func__, ret); + return ret; + } + + if ((index >= 0) && (index < AFE_MAX_PORTS)) { + this_afe.afe_sample_rates[index] = rate; + + if (this_afe.rt_cb) + this_afe.dev_acdb_id[index] = this_afe.rt_cb(port_id); + } + + /* Also send the topology id here if multiple ports: */ + port_index = afe_get_port_index(port_id); + if (!(this_afe.afe_cal_mode[port_index] == AFE_CAL_MODE_NONE) && + num_groups > 1) { + /* One time call: only for first time */ + afe_send_custom_topology(); + afe_send_port_topology_id(port_id); + afe_send_cal(port_id); + afe_send_hw_delay(port_id, rate); + } + + /* Start SW MAD module */ + mad_type = afe_port_get_mad_type(port_id); + pr_debug("%s: port_id 0x%x, mad_type %d\n", __func__, port_id, + mad_type); + if (mad_type != MAD_HW_NONE && mad_type != MAD_SW_AUDIO) { + if (!afe_has_config(AFE_CDC_REGISTERS_CONFIG) || + !afe_has_config(AFE_SLIMBUS_SLAVE_CONFIG)) { + pr_err("%s: AFE isn't configured yet for\n" + "HW MAD try Again\n", __func__); + ret = -EAGAIN; + goto fail_cmd; + } + ret = afe_turn_onoff_hw_mad(mad_type, true); + if (ret) { + pr_err("%s: afe_turn_onoff_hw_mad failed %d\n", + __func__, ret); + goto fail_cmd; + } + } + + param_hdr.module_id = AFE_MODULE_AUDIO_DEV_INTERFACE; + param_hdr.instance_id = INSTANCE_ID_0; + param_hdr.param_id = AFE_PARAM_ID_I2S_CONFIG; + param_hdr.param_size = sizeof(struct afe_param_id_i2s_cfg); + + ret = q6afe_pack_and_set_param_in_band(port_id, + q6audio_get_port_index(port_id), + param_hdr, + (u8 *) &i2s_port->i2s_cfg); + if (ret) { + pr_err("%s: AFE enable for port 0x%x failed ret = %d\n", + __func__, port_id, ret); + goto fail_cmd; + } + + port_index = afe_get_port_index(port_id); + if ((port_index >= 0) && (port_index < AFE_MAX_PORTS)) { + this_afe.afe_sample_rates[port_index] = rate; + } else { + pr_err("%s: Invalid port index %d\n", __func__, port_index); + ret = -EINVAL; + goto fail_cmd; + } + /* slot mapping is not need if there is only one group */ + if (num_groups > 1) { + ret = afe_send_slot_mapping_cfg( + &i2s_port->slot_mapping, + port_id); + if (ret < 0) { + pr_err("%s: afe send failed %d\n", __func__, ret); + goto fail_cmd; + } + } + + ret = afe_send_cmd_port_start(port_id); + +fail_cmd: + return ret; +} + int afe_tdm_port_start(u16 port_id, struct afe_tdm_port_config *tdm_port, u32 rate, u16 num_groups) { @@ -3598,6 +3734,54 @@ int afe_get_port_index(u16 port_id) return IDX_AFE_PORT_ID_INT6_MI2S_RX; case AFE_PORT_ID_INT6_MI2S_TX: return IDX_AFE_PORT_ID_INT6_MI2S_TX; + case AFE_PORT_ID_SECONDARY_MI2S_TX_1: + return IDX_AFE_PORT_ID_SECONDARY_MI2S_TX_1; + case AFE_PORT_ID_SECONDARY_MI2S_TX_2: + return IDX_AFE_PORT_ID_SECONDARY_MI2S_TX_2; + case AFE_PORT_ID_SECONDARY_MI2S_TX_3: + return IDX_AFE_PORT_ID_SECONDARY_MI2S_TX_3; + case AFE_PORT_ID_SECONDARY_MI2S_TX_4: + return IDX_AFE_PORT_ID_SECONDARY_MI2S_TX_4; + case AFE_PORT_ID_TERTIARY_MI2S_TX_1: + return IDX_AFE_PORT_ID_TERTIARY_MI2S_TX_1; + case AFE_PORT_ID_TERTIARY_MI2S_TX_2: + return IDX_AFE_PORT_ID_TERTIARY_MI2S_TX_2; + case AFE_PORT_ID_TERTIARY_MI2S_TX_3: + return IDX_AFE_PORT_ID_TERTIARY_MI2S_TX_3; + case AFE_PORT_ID_TERTIARY_MI2S_TX_4: + return IDX_AFE_PORT_ID_TERTIARY_MI2S_TX_4; + case AFE_PORT_ID_QUATERNARY_MI2S_TX_1: + return IDX_AFE_PORT_ID_QUATERNARY_MI2S_TX_1; + case AFE_PORT_ID_QUATERNARY_MI2S_TX_2: + return IDX_AFE_PORT_ID_QUATERNARY_MI2S_TX_2; + case AFE_PORT_ID_QUATERNARY_MI2S_TX_3: + return IDX_AFE_PORT_ID_QUATERNARY_MI2S_TX_3; + case AFE_PORT_ID_QUATERNARY_MI2S_TX_4: + return IDX_AFE_PORT_ID_QUATERNARY_MI2S_TX_4; + case AFE_PORT_ID_SECONDARY_MI2S_RX_1: + return IDX_AFE_PORT_ID_SECONDARY_MI2S_RX_1; + case AFE_PORT_ID_SECONDARY_MI2S_RX_2: + return IDX_AFE_PORT_ID_SECONDARY_MI2S_RX_2; + case AFE_PORT_ID_SECONDARY_MI2S_RX_3: + return IDX_AFE_PORT_ID_SECONDARY_MI2S_RX_3; + case AFE_PORT_ID_SECONDARY_MI2S_RX_4: + return IDX_AFE_PORT_ID_SECONDARY_MI2S_RX_4; + case AFE_PORT_ID_TERTIARY_MI2S_RX_1: + return IDX_AFE_PORT_ID_TERTIARY_MI2S_RX_1; + case AFE_PORT_ID_TERTIARY_MI2S_RX_2: + return IDX_AFE_PORT_ID_TERTIARY_MI2S_RX_2; + case AFE_PORT_ID_TERTIARY_MI2S_RX_3: + return IDX_AFE_PORT_ID_TERTIARY_MI2S_RX_3; + case AFE_PORT_ID_TERTIARY_MI2S_RX_4: + return IDX_AFE_PORT_ID_TERTIARY_MI2S_RX_4; + case AFE_PORT_ID_QUATERNARY_MI2S_RX_1: + return IDX_AFE_PORT_ID_QUATERNARY_MI2S_RX_1; + case AFE_PORT_ID_QUATERNARY_MI2S_RX_2: + return IDX_AFE_PORT_ID_QUATERNARY_MI2S_RX_2; + case AFE_PORT_ID_QUATERNARY_MI2S_RX_3: + return IDX_AFE_PORT_ID_QUATERNARY_MI2S_RX_3; + case AFE_PORT_ID_QUATERNARY_MI2S_RX_4: + return IDX_AFE_PORT_ID_QUATERNARY_MI2S_RX_4; default: pr_err("%s: port 0x%x\n", __func__, port_id); return -EINVAL; @@ -4022,6 +4206,154 @@ int afe_port_group_set_param(u16 group_id, return ret; } +static int afe_port_group_mi2s_set_param(u16 group_id, + struct afe_param_id_group_device_i2s_cfg_v1 *afe_group_config) +{ + struct param_hdr_v3 param_hdr = {0}; + int cfg_type; + int ret; + + if (!afe_group_config) { + pr_err("%s: Error, no configuration data\n", __func__); + return -EINVAL; + } + + pr_debug("%s: group id: 0x%x\n", __func__, group_id); + + ret = afe_q6_interface_prepare(); + if (ret != 0) { + pr_err("%s: Q6 interface prepare failed %d\n", __func__, ret); + return ret; + } + + switch (group_id) { + case AFE_GROUP_DEVICE_ID_SECONDARY_MI2S_RX: + case AFE_GROUP_DEVICE_ID_SECONDARY_MI2S_TX: + case AFE_GROUP_DEVICE_ID_TERTIARY_MI2S_RX: + case AFE_GROUP_DEVICE_ID_TERTIARY_MI2S_TX: + case AFE_GROUP_DEVICE_ID_QUATERNARY_MI2S_RX: + case AFE_GROUP_DEVICE_ID_QUATERNARY_MI2S_TX: + cfg_type = AFE_PARAM_ID_GROUP_DEVICE_I2S_CONFIG; + break; + default: + pr_err("%s: Invalid group id 0x%x\n", __func__, group_id); + return -EINVAL; + } + + param_hdr.module_id = AFE_MODULE_GROUP_DEVICE; + param_hdr.instance_id = INSTANCE_ID_0; + param_hdr.param_id = cfg_type; + param_hdr.param_size = + sizeof(struct afe_param_id_group_device_i2s_cfg_v1); + + ret = q6afe_svc_pack_and_set_param_in_band(IDX_GLOBAL_CFG, param_hdr, + (u8 *) afe_group_config); + if (ret) + pr_err("%s: AFE_PARAM_ID_GROUP_DEVICE_CFG failed %d\n", + __func__, ret); + + return ret; +} + +static atomic_t mi2s_gp_en_ref[IDX_GROUP_MI2S_MAX]; +static int afe_get_mi2s_group_idx(u16 group_id) +{ + int gp_idx = -1; + + switch (group_id) { + case AFE_GROUP_DEVICE_ID_SECONDARY_MI2S_RX: + gp_idx = IDX_GROUP_SECONDARY_MI2S_RX; + break; + case AFE_GROUP_DEVICE_ID_SECONDARY_MI2S_TX: + gp_idx = IDX_GROUP_SECONDARY_MI2S_TX; + break; + case AFE_GROUP_DEVICE_ID_TERTIARY_MI2S_RX: + gp_idx = IDX_GROUP_TERTIARY_MI2S_RX; + break; + case AFE_GROUP_DEVICE_ID_TERTIARY_MI2S_TX: + gp_idx = IDX_GROUP_TERTIARY_MI2S_TX; + break; + case AFE_GROUP_DEVICE_ID_QUATERNARY_MI2S_RX: + gp_idx = IDX_GROUP_QUATERNARY_MI2S_RX; + break; + case AFE_GROUP_DEVICE_ID_QUATERNARY_MI2S_TX: + gp_idx = IDX_GROUP_QUATERNARY_MI2S_TX; + break; + default: + break; + } + + return gp_idx; +} + +int afe_port_group_mi2s_enable(u16 group_id, + union afe_port_group_mi2s_config *afe_group_config, + u16 enable) +{ + struct afe_param_id_group_device_enable group_enable = {0}; + struct param_hdr_v3 param_hdr = {0}; + int ret = 0; + int gp_idx; + + pr_debug("%s: group id: 0x%x enable: %d\n", __func__, + group_id, enable); + + gp_idx = afe_get_mi2s_group_idx(group_id); + + if ((gp_idx >= 0) && (gp_idx < IDX_GROUP_MI2S_MAX)) { + + atomic_t *gp_ref = &mi2s_gp_en_ref[gp_idx]; + + if (enable) + atomic_inc(gp_ref); + else + atomic_dec(gp_ref); + + if ((enable) && (atomic_read(gp_ref) > 1)) { + pr_err("%s: this TDM group is enabled already %d refs_cnt %d\n", + __func__, group_id, atomic_read(gp_ref)); + goto rtn; + } + + if ((!enable) && (atomic_read(gp_ref) > 0)) { + pr_err("%s: this TDM group will be disabled in last call %d refs_cnt %d\n", + __func__, group_id, atomic_read(gp_ref)); + goto rtn; + } + } + + ret = afe_q6_interface_prepare(); + if (ret != 0) { + pr_err("%s: Q6 interface prepare failed %d\n", __func__, ret); + return ret; + } + + if (enable) { + ret = afe_port_group_mi2s_set_param( + group_id, &afe_group_config->i2s_cfg); + if (ret < 0) { + pr_err("%s: afe send failed %d\n", __func__, ret); + return ret; + } + } + + param_hdr.module_id = AFE_MODULE_GROUP_DEVICE; + param_hdr.instance_id = INSTANCE_ID_0; + param_hdr.param_id = AFE_PARAM_ID_GROUP_DEVICE_ENABLE; + param_hdr.param_size = sizeof(struct afe_group_device_enable); + group_enable.group_id = group_id; + group_enable.enable = enable; + + ret = q6afe_svc_pack_and_set_param_in_band(IDX_GLOBAL_CFG, param_hdr, + (u8 *) &group_enable); + if (ret) + pr_err("%s: AFE_PARAM_ID_GROUP_DEVICE_ENABLE failed %d\n", + __func__, ret); + +rtn: + return ret; +} + int afe_port_group_enable(u16 group_id, union afe_port_group_config *afe_group_config, u16 enable) diff --git a/sound/soc/msm/qdsp6v2/q6asm.c b/sound/soc/msm/qdsp6v2/q6asm.c index b7f85c504f7a..f6194eade877 100644 --- a/sound/soc/msm/qdsp6v2/q6asm.c +++ b/sound/soc/msm/qdsp6v2/q6asm.c @@ -3245,6 +3245,9 @@ static int __q6asm_open_write(struct audio_client *ac, uint32_t format, case FORMAT_APTX: open.dec_fmt_id = ASM_MEDIA_FMT_APTX; break; + case FORMAT_APTXHD: + open.dec_fmt_id = ASM_MEDIA_FMT_APTX_HD; + break; case FORMAT_GEN_COMPR: open.dec_fmt_id = ASM_MEDIA_FMT_GENERIC_COMPRESSED; break; diff --git a/sound/soc/msm/qdsp6v2/q6audio-v2.c b/sound/soc/msm/qdsp6v2/q6audio-v2.c index 0062e4cd6432..94a6b0c42dee 100644 --- a/sound/soc/msm/qdsp6v2/q6audio-v2.c +++ b/sound/soc/msm/qdsp6v2/q6audio-v2.c @@ -95,6 +95,54 @@ int q6audio_get_port_index(u16 port_id) return IDX_AFE_PORT_ID_TERTIARY_MI2S_RX; case AFE_PORT_ID_TERTIARY_MI2S_TX: return IDX_AFE_PORT_ID_TERTIARY_MI2S_TX; + case AFE_PORT_ID_SECONDARY_MI2S_TX_1: + return IDX_AFE_PORT_ID_SECONDARY_MI2S_TX_1; + case AFE_PORT_ID_SECONDARY_MI2S_TX_2: + return IDX_AFE_PORT_ID_SECONDARY_MI2S_TX_2; + case AFE_PORT_ID_SECONDARY_MI2S_TX_3: + return IDX_AFE_PORT_ID_SECONDARY_MI2S_TX_3; + case AFE_PORT_ID_SECONDARY_MI2S_TX_4: + return IDX_AFE_PORT_ID_SECONDARY_MI2S_TX_4; + case AFE_PORT_ID_TERTIARY_MI2S_TX_1: + return IDX_AFE_PORT_ID_TERTIARY_MI2S_TX_1; + case AFE_PORT_ID_TERTIARY_MI2S_TX_2: + return IDX_AFE_PORT_ID_TERTIARY_MI2S_TX_2; + case AFE_PORT_ID_TERTIARY_MI2S_TX_3: + return IDX_AFE_PORT_ID_TERTIARY_MI2S_TX_3; + case AFE_PORT_ID_TERTIARY_MI2S_TX_4: + return IDX_AFE_PORT_ID_TERTIARY_MI2S_TX_4; + case AFE_PORT_ID_QUATERNARY_MI2S_TX_1: + return IDX_AFE_PORT_ID_QUATERNARY_MI2S_TX_1; + case AFE_PORT_ID_QUATERNARY_MI2S_TX_2: + return IDX_AFE_PORT_ID_QUATERNARY_MI2S_TX_2; + case AFE_PORT_ID_QUATERNARY_MI2S_TX_3: + return IDX_AFE_PORT_ID_QUATERNARY_MI2S_TX_3; + case AFE_PORT_ID_QUATERNARY_MI2S_TX_4: + return IDX_AFE_PORT_ID_QUATERNARY_MI2S_TX_4; + case AFE_PORT_ID_SECONDARY_MI2S_RX_1: + return IDX_AFE_PORT_ID_SECONDARY_MI2S_RX_1; + case AFE_PORT_ID_SECONDARY_MI2S_RX_2: + return IDX_AFE_PORT_ID_SECONDARY_MI2S_RX_2; + case AFE_PORT_ID_SECONDARY_MI2S_RX_3: + return IDX_AFE_PORT_ID_SECONDARY_MI2S_RX_3; + case AFE_PORT_ID_SECONDARY_MI2S_RX_4: + return IDX_AFE_PORT_ID_SECONDARY_MI2S_RX_4; + case AFE_PORT_ID_TERTIARY_MI2S_RX_1: + return IDX_AFE_PORT_ID_TERTIARY_MI2S_RX_1; + case AFE_PORT_ID_TERTIARY_MI2S_RX_2: + return IDX_AFE_PORT_ID_TERTIARY_MI2S_RX_2; + case AFE_PORT_ID_TERTIARY_MI2S_RX_3: + return IDX_AFE_PORT_ID_TERTIARY_MI2S_RX_3; + case AFE_PORT_ID_TERTIARY_MI2S_RX_4: + return IDX_AFE_PORT_ID_TERTIARY_MI2S_RX_4; + case AFE_PORT_ID_QUATERNARY_MI2S_RX_1: + return IDX_AFE_PORT_ID_QUATERNARY_MI2S_RX_1; + case AFE_PORT_ID_QUATERNARY_MI2S_RX_2: + return IDX_AFE_PORT_ID_QUATERNARY_MI2S_RX_2; + case AFE_PORT_ID_QUATERNARY_MI2S_RX_3: + return IDX_AFE_PORT_ID_QUATERNARY_MI2S_RX_3; + case AFE_PORT_ID_QUATERNARY_MI2S_RX_4: + return IDX_AFE_PORT_ID_QUATERNARY_MI2S_RX_4; case AUDIO_PORT_ID_I2S_RX: return IDX_AUDIO_PORT_ID_I2S_RX; case AFE_PORT_ID_SECONDARY_MI2S_RX_SD1: @@ -342,6 +390,54 @@ int q6audio_get_port_id(u16 port_id) return AFE_PORT_ID_TERTIARY_MI2S_RX; case AFE_PORT_ID_TERTIARY_MI2S_TX: return AFE_PORT_ID_TERTIARY_MI2S_TX; + case AFE_PORT_ID_SECONDARY_MI2S_TX_1: + return AFE_PORT_ID_SECONDARY_MI2S_TX_1; + case AFE_PORT_ID_SECONDARY_MI2S_TX_2: + return AFE_PORT_ID_SECONDARY_MI2S_TX_2; + case AFE_PORT_ID_SECONDARY_MI2S_TX_3: + return AFE_PORT_ID_SECONDARY_MI2S_TX_3; + case AFE_PORT_ID_SECONDARY_MI2S_TX_4: + return AFE_PORT_ID_SECONDARY_MI2S_TX_4; + case AFE_PORT_ID_TERTIARY_MI2S_TX_1: + return AFE_PORT_ID_TERTIARY_MI2S_TX_1; + case AFE_PORT_ID_TERTIARY_MI2S_TX_2: + return AFE_PORT_ID_TERTIARY_MI2S_TX_2; + case AFE_PORT_ID_TERTIARY_MI2S_TX_3: + return AFE_PORT_ID_TERTIARY_MI2S_TX_3; + case AFE_PORT_ID_TERTIARY_MI2S_TX_4: + return AFE_PORT_ID_TERTIARY_MI2S_TX_4; + case AFE_PORT_ID_QUATERNARY_MI2S_TX_1: + return AFE_PORT_ID_QUATERNARY_MI2S_TX_1; + case AFE_PORT_ID_QUATERNARY_MI2S_TX_2: + return AFE_PORT_ID_QUATERNARY_MI2S_TX_2; + case AFE_PORT_ID_QUATERNARY_MI2S_TX_3: + return AFE_PORT_ID_QUATERNARY_MI2S_TX_3; + case AFE_PORT_ID_QUATERNARY_MI2S_TX_4: + return AFE_PORT_ID_QUATERNARY_MI2S_TX_4; + case AFE_PORT_ID_SECONDARY_MI2S_RX_1: + return AFE_PORT_ID_SECONDARY_MI2S_RX_1; + case AFE_PORT_ID_SECONDARY_MI2S_RX_2: + return AFE_PORT_ID_SECONDARY_MI2S_RX_2; + case AFE_PORT_ID_SECONDARY_MI2S_RX_3: + return AFE_PORT_ID_SECONDARY_MI2S_RX_3; + case AFE_PORT_ID_SECONDARY_MI2S_RX_4: + return AFE_PORT_ID_SECONDARY_MI2S_RX_4; + case AFE_PORT_ID_TERTIARY_MI2S_RX_1: + return AFE_PORT_ID_TERTIARY_MI2S_RX_1; + case AFE_PORT_ID_TERTIARY_MI2S_RX_2: + return AFE_PORT_ID_TERTIARY_MI2S_RX_2; + case AFE_PORT_ID_TERTIARY_MI2S_RX_3: + return AFE_PORT_ID_TERTIARY_MI2S_RX_3; + case AFE_PORT_ID_TERTIARY_MI2S_RX_4: + return AFE_PORT_ID_TERTIARY_MI2S_RX_4; + case AFE_PORT_ID_QUATERNARY_MI2S_RX_1: + return AFE_PORT_ID_QUATERNARY_MI2S_RX_1; + case AFE_PORT_ID_QUATERNARY_MI2S_RX_2: + return AFE_PORT_ID_QUATERNARY_MI2S_RX_2; + case AFE_PORT_ID_QUATERNARY_MI2S_RX_3: + return AFE_PORT_ID_QUATERNARY_MI2S_RX_3; + case AFE_PORT_ID_QUATERNARY_MI2S_RX_4: + return AFE_PORT_ID_QUATERNARY_MI2S_RX_4; case AUDIO_PORT_ID_I2S_RX: return AUDIO_PORT_ID_I2S_RX; case AFE_PORT_ID_SECONDARY_MI2S_RX_SD1: @@ -642,6 +738,30 @@ int q6audio_is_digital_pcm_interface(u16 port_id) case AFE_PORT_ID_INT5_MI2S_TX: case AFE_PORT_ID_INT6_MI2S_RX: case AFE_PORT_ID_INT6_MI2S_TX: + case AFE_PORT_ID_SECONDARY_MI2S_RX_1: + case AFE_PORT_ID_SECONDARY_MI2S_RX_2: + case AFE_PORT_ID_SECONDARY_MI2S_RX_3: + case AFE_PORT_ID_SECONDARY_MI2S_RX_4: + case AFE_PORT_ID_TERTIARY_MI2S_RX_1: + case AFE_PORT_ID_TERTIARY_MI2S_RX_2: + case AFE_PORT_ID_TERTIARY_MI2S_RX_3: + case AFE_PORT_ID_TERTIARY_MI2S_RX_4: + case AFE_PORT_ID_QUATERNARY_MI2S_RX_1: + case AFE_PORT_ID_QUATERNARY_MI2S_RX_2: + case AFE_PORT_ID_QUATERNARY_MI2S_RX_3: + case AFE_PORT_ID_QUATERNARY_MI2S_RX_4: + case AFE_PORT_ID_SECONDARY_MI2S_TX_1: + case AFE_PORT_ID_SECONDARY_MI2S_TX_2: + case AFE_PORT_ID_SECONDARY_MI2S_TX_3: + case AFE_PORT_ID_SECONDARY_MI2S_TX_4: + case AFE_PORT_ID_TERTIARY_MI2S_TX_1: + case AFE_PORT_ID_TERTIARY_MI2S_TX_2: + case AFE_PORT_ID_TERTIARY_MI2S_TX_3: + case AFE_PORT_ID_TERTIARY_MI2S_TX_4: + case AFE_PORT_ID_QUATERNARY_MI2S_TX_1: + case AFE_PORT_ID_QUATERNARY_MI2S_TX_2: + case AFE_PORT_ID_QUATERNARY_MI2S_TX_3: + case AFE_PORT_ID_QUATERNARY_MI2S_TX_4: break; default: ret = -EINVAL; @@ -795,6 +915,30 @@ int q6audio_validate_port(u16 port_id) case AFE_PORT_ID_INT6_MI2S_RX: case AFE_PORT_ID_INT6_MI2S_TX: case AFE_PORT_ID_MULTICHAN_HDMI_RX: + case AFE_PORT_ID_SECONDARY_MI2S_RX_1: + case AFE_PORT_ID_SECONDARY_MI2S_RX_2: + case AFE_PORT_ID_SECONDARY_MI2S_RX_3: + case AFE_PORT_ID_SECONDARY_MI2S_RX_4: + case AFE_PORT_ID_SECONDARY_MI2S_TX_1: + case AFE_PORT_ID_SECONDARY_MI2S_TX_2: + case AFE_PORT_ID_SECONDARY_MI2S_TX_3: + case AFE_PORT_ID_SECONDARY_MI2S_TX_4: + case AFE_PORT_ID_TERTIARY_MI2S_RX_1: + case AFE_PORT_ID_TERTIARY_MI2S_RX_2: + case AFE_PORT_ID_TERTIARY_MI2S_RX_3: + case AFE_PORT_ID_TERTIARY_MI2S_RX_4: + case AFE_PORT_ID_TERTIARY_MI2S_TX_1: + case AFE_PORT_ID_TERTIARY_MI2S_TX_2: + case AFE_PORT_ID_TERTIARY_MI2S_TX_3: + case AFE_PORT_ID_TERTIARY_MI2S_TX_4: + case AFE_PORT_ID_QUATERNARY_MI2S_RX_1: + case AFE_PORT_ID_QUATERNARY_MI2S_RX_2: + case AFE_PORT_ID_QUATERNARY_MI2S_RX_3: + case AFE_PORT_ID_QUATERNARY_MI2S_RX_4: + case AFE_PORT_ID_QUATERNARY_MI2S_TX_1: + case AFE_PORT_ID_QUATERNARY_MI2S_TX_2: + case AFE_PORT_ID_QUATERNARY_MI2S_TX_3: + case AFE_PORT_ID_QUATERNARY_MI2S_TX_4: { ret = 0; break; diff --git a/sound/soc/msm/sdm660-internal.c b/sound/soc/msm/sdm660-internal.c index 4e2a40319b02..072d586da818 100644 --- a/sound/soc/msm/sdm660-internal.c +++ b/sound/soc/msm/sdm660-internal.c @@ -134,7 +134,7 @@ static struct dev_config int_mi2s_cfg[] = { [INT2_MI2S] = {SAMPLING_RATE_48KHZ, SNDRV_PCM_FORMAT_S16_LE, 1}, [INT3_MI2S] = {SAMPLING_RATE_48KHZ, SNDRV_PCM_FORMAT_S16_LE, 1}, [INT4_MI2S] = {SAMPLING_RATE_48KHZ, SNDRV_PCM_FORMAT_S16_LE, 1}, - [INT5_MI2S] = {SAMPLING_RATE_48KHZ, SNDRV_PCM_FORMAT_S16_LE, 2}, + [INT5_MI2S] = {SAMPLING_RATE_8KHZ, SNDRV_PCM_FORMAT_S16_LE, 2}, [INT6_MI2S] = {SAMPLING_RATE_8KHZ, SNDRV_PCM_FORMAT_S16_LE, 2}, }; diff --git a/sound/sparc/cs4231.c b/sound/sparc/cs4231.c index 30bdc971883b..017e241b0ec9 100644 --- a/sound/sparc/cs4231.c +++ b/sound/sparc/cs4231.c @@ -1146,10 +1146,8 @@ static int snd_cs4231_playback_open(struct snd_pcm_substream *substream) runtime->hw = snd_cs4231_playback; err = snd_cs4231_open(chip, CS4231_MODE_PLAY); - if (err < 0) { - snd_free_pages(runtime->dma_area, runtime->dma_bytes); + if (err < 0) return err; - } chip->playback_substream = substream; chip->p_periods_sent = 0; snd_pcm_set_sync(substream); @@ -1167,10 +1165,8 @@ static int snd_cs4231_capture_open(struct snd_pcm_substream *substream) runtime->hw = snd_cs4231_capture; err = snd_cs4231_open(chip, CS4231_MODE_RECORD); - if (err < 0) { - snd_free_pages(runtime->dma_area, runtime->dma_bytes); + if (err < 0) return err; - } chip->capture_substream = substream; chip->c_periods_sent = 0; snd_pcm_set_sync(substream); diff --git a/sound/usb/card.c b/sound/usb/card.c index 86096532dfba..bbbece670eaf 100644 --- a/sound/usb/card.c +++ b/sound/usb/card.c @@ -688,9 +688,12 @@ static int usb_audio_probe(struct usb_interface *intf, __error: if (chip) { + /* chip->active is inside the chip->card object, + * decrement before memory is possibly returned. + */ + atomic_dec(&chip->active); if (!chip->num_interfaces) snd_card_free(chip->card); - atomic_dec(&chip->active); } mutex_unlock(®ister_mutex); return err; |
