diff options
213 files changed, 4386 insertions, 1499 deletions
diff --git a/Documentation/devicetree/bindings/arm/msm/msm.txt b/Documentation/devicetree/bindings/arm/msm/msm.txt index d442cf02a816..41cbb91351bb 100644 --- a/Documentation/devicetree/bindings/arm/msm/msm.txt +++ b/Documentation/devicetree/bindings/arm/msm/msm.txt @@ -86,6 +86,9 @@ SoCs: - MSM8998 compatible = "qcom,msm8998" +- MSM8998_9x55 + compatible = "qcom,msm8998-9x55" + - MSMHAMSTER compatible = "qcom,msmhamster" @@ -270,6 +273,8 @@ compatible = "qcom,msm8998-rumi" compatible = "qcom,msm8998-cdp" compatible = "qcom,msm8998-mtp" compatible = "qcom,msm8998-qrd" +compatible = "qcom,msm8998-9x55-cdp" +compatible = "qcom,msm8998-9x55-mtp" compatible = "qcom,msmhamster-rumi" compatible = "qcom,msmhamster-cdp" compatible = "qcom,msmhamster-mtp" diff --git a/Documentation/devicetree/bindings/arm/msm/rdbg-smp2p.txt b/Documentation/devicetree/bindings/arm/msm/rdbg-smp2p.txt index ce2d8bd54e43..1114308f9436 100644 --- a/Documentation/devicetree/bindings/arm/msm/rdbg-smp2p.txt +++ b/Documentation/devicetree/bindings/arm/msm/rdbg-smp2p.txt @@ -2,12 +2,15 @@ Qualcomm Technologies, Inc. Remote Debugger (RDBG) driver Required properties: -compatible : Should be one of - To communicate with modem + To communicate with adsp qcom,smp2pgpio_client_rdbg_2_in (inbound) qcom,smp2pgpio_client_rdbg_2_out (outbound) To communicate with modem qcom,smp2pgpio_client_rdbg_1_in (inbound) qcom,smp2pgpio_client_rdbg_1_out (outbound) + To communicate with cdsp + qcom,smp2pgpio_client_rdbg_5_in (inbound) + qcom,smp2pgpio_client_rdbg_5_out (outbound) -gpios : the relevant gpio pins of the entry. Example: diff --git a/Documentation/devicetree/bindings/sound/qcom-audio-dev.txt b/Documentation/devicetree/bindings/sound/qcom-audio-dev.txt index 38e056cdc0ee..db21a2b58c2b 100644 --- a/Documentation/devicetree/bindings/sound/qcom-audio-dev.txt +++ b/Documentation/devicetree/bindings/sound/qcom-audio-dev.txt @@ -1311,6 +1311,13 @@ Optional properties: - pinctrl-x: Defines pinctrl state for each pin group. + - qcom,msm-cpudai-tdm-clk-attribute: Clock attribute for tdm. + 0 - Clk invalid attribute + 1 - Clk attribute couple no + 2 - Clk attribute couple dividend + 3 - Clk attribute couple divisor + 4 - Clk attribute invert couple no + Example: qcom,msm-dai-tdm-quat-rx { @@ -1,6 +1,6 @@ VERSION = 4 PATCHLEVEL = 4 -SUBLEVEL = 75 +SUBLEVEL = 76 EXTRAVERSION = NAME = Blurry Fish Butt @@ -637,6 +637,12 @@ endif # Tell gcc to never replace conditional load with a non-conditional one KBUILD_CFLAGS += $(call cc-option,--param=allow-store-data-races=0) +# check for 'asm goto' +ifeq ($(shell $(CONFIG_SHELL) $(srctree)/scripts/gcc-goto.sh $(CC) $(KBUILD_CFLAGS)), y) + KBUILD_CFLAGS += -DCC_HAVE_ASM_GOTO + KBUILD_AFLAGS += -DCC_HAVE_ASM_GOTO +endif + ifdef CONFIG_READABLE_ASM # Disable optimizations that make assembler listings hard to read. # reorder blocks reorders the control in the function @@ -792,12 +798,6 @@ KBUILD_CFLAGS += $(call cc-option,-Werror=date-time) # use the deterministic mode of AR if available KBUILD_ARFLAGS := $(call ar-option,D) -# check for 'asm goto' -ifeq ($(shell $(CONFIG_SHELL) $(srctree)/scripts/gcc-goto.sh $(CC) $(KBUILD_CFLAGS)), y) - KBUILD_CFLAGS += -DCC_HAVE_ASM_GOTO - KBUILD_AFLAGS += -DCC_HAVE_ASM_GOTO -endif - include scripts/Makefile.kasan include scripts/Makefile.extrawarn include scripts/Makefile.ubsan diff --git a/arch/arm/boot/dts/bcm5301x.dtsi b/arch/arm/boot/dts/bcm5301x.dtsi index 6f50f672efbd..de8ac998604d 100644 --- a/arch/arm/boot/dts/bcm5301x.dtsi +++ b/arch/arm/boot/dts/bcm5301x.dtsi @@ -54,14 +54,14 @@ timer@0200 { compatible = "arm,cortex-a9-global-timer"; reg = <0x0200 0x100>; - interrupts = <GIC_PPI 11 IRQ_TYPE_LEVEL_HIGH>; + interrupts = <GIC_PPI 11 IRQ_TYPE_EDGE_RISING>; clocks = <&clk_periph>; }; local-timer@0600 { compatible = "arm,cortex-a9-twd-timer"; reg = <0x0600 0x100>; - interrupts = <GIC_PPI 13 IRQ_TYPE_LEVEL_HIGH>; + interrupts = <GIC_PPI 13 IRQ_TYPE_EDGE_RISING>; clocks = <&clk_periph>; }; diff --git a/arch/arm/boot/dts/qcom/Makefile b/arch/arm/boot/dts/qcom/Makefile index c938988d6634..297d6535382e 100644 --- a/arch/arm/boot/dts/qcom/Makefile +++ b/arch/arm/boot/dts/qcom/Makefile @@ -170,7 +170,10 @@ dtb-$(CONFIG_ARCH_MSM8998) += msm8998-sim.dtb \ apq8098-v2.1-mediabox.dtb \ msm8998-v2.1-interposer-sdm660-cdp.dtb \ msm8998-v2.1-interposer-sdm660-mtp.dtb \ - msm8998-v2.1-interposer-sdm660-qrd.dtb + msm8998-v2.1-interposer-sdm660-qrd.dtb \ + msm8998-9x55-rcm.dtb \ + msm8998-9x55-cdp.dtb \ + msm8998-9x55-mtp.dtb endif dtb-$(CONFIG_ARCH_MSMHAMSTER) += msmhamster-rumi.dtb diff --git a/arch/arm/boot/dts/qcom/msm-pm660l.dtsi b/arch/arm/boot/dts/qcom/msm-pm660l.dtsi index 0f18ba5c94c7..9cd117ce4e0c 100644 --- a/arch/arm/boot/dts/qcom/msm-pm660l.dtsi +++ b/arch/arm/boot/dts/qcom/msm-pm660l.dtsi @@ -250,9 +250,8 @@ <0xd900 0x100>; reg-names = "qpnp-wled-ctrl-base", "qpnp-wled-sink-base"; - interrupts = <0x3 0xd8 0x1 IRQ_TYPE_EDGE_RISING>, - <0x3 0xd8 0x2 IRQ_TYPE_EDGE_RISING>; - interrupt-names = "ovp-irq", "sc-irq"; + interrupts = <0x3 0xd8 0x1 IRQ_TYPE_EDGE_RISING>; + interrupt-names = "ovp-irq"; linux,name = "wled"; linux,default-trigger = "bkl-trigger"; qcom,fdbk-output = "auto"; @@ -268,7 +267,6 @@ qcom,fs-curr-ua = <25000>; qcom,cons-sync-write-delay-us = <1000>; qcom,led-strings-list = [00 01 02]; - qcom,en-ext-pfet-sc-pro; qcom,loop-auto-gm-en; qcom,pmic-revid = <&pm660l_revid>; status = "ok"; diff --git a/arch/arm/boot/dts/qcom/msm8996-agave-adp.dtsi b/arch/arm/boot/dts/qcom/msm8996-agave-adp.dtsi index 3b55215c7e5d..9dbec1e87fda 100644 --- a/arch/arm/boot/dts/qcom/msm8996-agave-adp.dtsi +++ b/arch/arm/boot/dts/qcom/msm8996-agave-adp.dtsi @@ -547,7 +547,7 @@ #include "msm8996-sde-display.dtsi" -&mdss_mdp { +&sde_kms { qcom,mdss-pref-prim-intf = "dsi"; qcom,sde-plane-id-map { qcom,sde-plane-id@0 { @@ -869,6 +869,9 @@ qcom,ntn-rst-delay-msec = <100>; qcom,ntn-rc-num = <1>; + qcom,ntn-bus-num = <1>; + qcom,ntn-mdio-bus-id = <1>; + qcom,ntn-phy-addr = <7>; qcom,msm-bus,name = "ntn"; qcom,msm-bus,num-cases = <2>; @@ -1238,7 +1241,7 @@ qcom,vin-sel = <2>; /* 1.8 */ qcom,out-strength = <1>; qcom,src-sel = <0>; /* GPIO */ - qcom,master-en = <0>; /* Disable GPIO */ + qcom,master-en = <1>; /* Enable GPIO */ status = "okay"; }; diff --git a/arch/arm/boot/dts/qcom/msm8996-auto-cdp.dtsi b/arch/arm/boot/dts/qcom/msm8996-auto-cdp.dtsi index 4fe6f0d67fbe..ad14bfd00cd1 100644 --- a/arch/arm/boot/dts/qcom/msm8996-auto-cdp.dtsi +++ b/arch/arm/boot/dts/qcom/msm8996-auto-cdp.dtsi @@ -333,7 +333,7 @@ }; }; -&mdss_mdp { +&sde_kms { qcom,mdss-pref-prim-intf = "dsi"; qcom,sde-plane-id-map { qcom,sde-plane-id@0 { @@ -635,6 +635,8 @@ qcom,ntn-rst-delay-msec = <100>; qcom,ntn-rc-num = <1>; qcom,ntn-bus-num = <1>; + qcom,ntn-mdio-bus-id = <1>; + qcom,ntn-phy-addr = <7>; qcom,msm-bus,name = "ntn"; qcom,msm-bus,num-cases = <2>; @@ -649,6 +651,7 @@ qcom,ntn-rst-delay-msec = <100>; qcom,ntn-rc-num = <2>; qcom,ntn-bus-num = <1>; + qcom,ntn-mdio-bus-id = <2>; qcom,msm-bus,name = "ntn"; qcom,msm-bus,num-cases = <2>; diff --git a/arch/arm/boot/dts/qcom/msm8996-mtp.dtsi b/arch/arm/boot/dts/qcom/msm8996-mtp.dtsi index ab10a71d1fd7..0bd9b02f3d2e 100644 --- a/arch/arm/boot/dts/qcom/msm8996-mtp.dtsi +++ b/arch/arm/boot/dts/qcom/msm8996-mtp.dtsi @@ -1,4 +1,4 @@ -/* Copyright (c) 2015-2016, The Linux Foundation. All rights reserved. +/* Copyright (c) 2015-2017, The Linux Foundation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 and @@ -343,7 +343,7 @@ qcom,mdss-pref-prim-intf = "dsi"; }; -&mdss_hdmi { +&sde_hdmi { status = "ok"; }; diff --git a/arch/arm/boot/dts/qcom/msm8996-sde-display.dtsi b/arch/arm/boot/dts/qcom/msm8996-sde-display.dtsi index 061301f1c479..1c81bc433374 100644 --- a/arch/arm/boot/dts/qcom/msm8996-sde-display.dtsi +++ b/arch/arm/boot/dts/qcom/msm8996-sde-display.dtsi @@ -94,8 +94,8 @@ label = "dsi_dual_sharp_video"; qcom,display-type = "primary"; - qcom,dsi-ctrl = <&mdss_dsi0 &mdss_dsi1>; - qcom,dsi-phy = <&mdss_dsi_phy0 &mdss_dsi_phy1>; + qcom,dsi-ctrl = <&sde_dsi0 &sde_dsi1>; + qcom,dsi-phy = <&sde_dsi_phy0 &sde_dsi_phy1>; clocks = <&clock_mmss clk_ext_byte0_clk_src>, <&clock_mmss clk_ext_pclk0_clk_src>; clock-names = "src_byte_clk", "src_pixel_clk"; @@ -118,8 +118,8 @@ label = "single_dsi_sim"; qcom,display-type = "primary"; - qcom,dsi-ctrl = <&mdss_dsi0>; - qcom,dsi-phy = <&mdss_dsi_phy0>; + qcom,dsi-ctrl = <&sde_dsi0>; + qcom,dsi-phy = <&sde_dsi_phy0>; clocks = <&clock_mmss clk_ext_byte0_clk_src>, <&clock_mmss clk_ext_pclk0_clk_src>; clock-names = "src_byte_clk", "src_pixel_clk"; @@ -140,8 +140,8 @@ label = "single_dsi_toshiba_720p"; qcom,display-type = "primary"; - qcom,dsi-ctrl = <&mdss_dsi0>; - qcom,dsi-phy = <&mdss_dsi_phy0>; + qcom,dsi-ctrl = <&sde_dsi0>; + qcom,dsi-phy = <&sde_dsi_phy0>; clocks = <&clock_mmss clk_ext_byte0_clk_src>, <&clock_mmss clk_ext_pclk0_clk_src>; clock-names = "src_byte_clk", "src_pixel_clk"; @@ -161,8 +161,8 @@ label = "single_dsi_jdi_1080p"; qcom,display-type = "primary"; - qcom,dsi-ctrl = <&mdss_dsi0>; - qcom,dsi-phy = <&mdss_dsi_phy0>; + qcom,dsi-ctrl = <&sde_dsi0>; + qcom,dsi-phy = <&sde_dsi_phy0>; clocks = <&clock_mmss clk_ext_byte0_clk_src>, <&clock_mmss clk_ext_pclk0_clk_src>; clock-names = "src_byte_clk", "src_pixel_clk"; @@ -180,8 +180,8 @@ label = "single_dsi_sharp_1080p"; qcom,display-type = "primary"; - qcom,dsi-ctrl = <&mdss_dsi0>; - qcom,dsi-phy = <&mdss_dsi_phy0>; + qcom,dsi-ctrl = <&sde_dsi0>; + qcom,dsi-phy = <&sde_dsi_phy0>; clocks = <&clock_mmss clk_ext_byte0_clk_src>, <&clock_mmss clk_ext_pclk0_clk_src>; clock-names = "src_byte_clk", "src_pixel_clk"; @@ -209,8 +209,8 @@ qcom,display-type = "primary"; /* dsi1/dsi0 swapped due to IMGSWAP */ - qcom,dsi-ctrl = <&mdss_dsi1 &mdss_dsi0>; - qcom,dsi-phy = <&mdss_dsi_phy0 &mdss_dsi_phy1>; + qcom,dsi-ctrl = <&sde_dsi1 &sde_dsi0>; + qcom,dsi-phy = <&sde_dsi_phy0 &sde_dsi_phy1>; clocks = <&clock_mmss clk_ext_byte0_clk_src>, <&clock_mmss clk_ext_pclk0_clk_src>; clock-names = "src_byte_clk", "src_pixel_clk"; @@ -231,8 +231,8 @@ label = "dsi_dual_nt35597_video"; qcom,display-type = "primary"; - qcom,dsi-ctrl = <&mdss_dsi0 &mdss_dsi1>; - qcom,dsi-phy = <&mdss_dsi_phy0 &mdss_dsi_phy1>; + qcom,dsi-ctrl = <&sde_dsi0 &sde_dsi1>; + qcom,dsi-phy = <&sde_dsi_phy0 &sde_dsi_phy1>; clocks = <&clock_mmss clk_ext_byte0_clk_src>, <&clock_mmss clk_ext_pclk0_clk_src>; clock-names = "src_byte_clk", "src_pixel_clk"; @@ -253,8 +253,8 @@ label = "dsi_adv_7533_1"; qcom,display-type = "secondary"; - qcom,dsi-ctrl = <&mdss_dsi0>; - qcom,dsi-phy = <&mdss_dsi_phy0>; + qcom,dsi-ctrl = <&sde_dsi0>; + qcom,dsi-phy = <&sde_dsi_phy0>; clocks = <&clock_mmss clk_ext_byte0_clk_src>, <&clock_mmss clk_ext_pclk0_clk_src>; clock-names = "src_byte_clk", "src_pixel_clk"; @@ -269,8 +269,8 @@ label = "dsi_adv_7533_2"; qcom,display-type = "tertiary"; - qcom,dsi-ctrl = <&mdss_dsi1>; - qcom,dsi-phy = <&mdss_dsi_phy1>; + qcom,dsi-ctrl = <&sde_dsi1>; + qcom,dsi-phy = <&sde_dsi_phy1>; clocks = <&clock_mmss clk_ext_byte1_clk_src>, <&clock_mmss clk_ext_pclk1_clk_src>; clock-names = "src_byte_clk", "src_pixel_clk"; @@ -297,8 +297,8 @@ }; }; -&mdss_mdp { - connectors = <&mdss_hdmi &sde_hdmi &dsi_adv_7533_1 &dsi_adv_7533_2>; +&sde_kms { + connectors = <&sde_hdmi_tx &sde_hdmi &dsi_adv_7533_1 &dsi_adv_7533_2>; }; &dsi_dual_sharp_video { diff --git a/arch/arm/boot/dts/qcom/msm8996-sde.dtsi b/arch/arm/boot/dts/qcom/msm8996-sde.dtsi index f0fa5dcb2224..6d0e5c4cb920 100644 --- a/arch/arm/boot/dts/qcom/msm8996-sde.dtsi +++ b/arch/arm/boot/dts/qcom/msm8996-sde.dtsi @@ -11,7 +11,7 @@ */ &soc { - mdss_mdp: qcom,mdss_mdp@900000 { + sde_kms: qcom,sde_kms@900000 { compatible = "qcom,sde-kms"; reg = <0x00900000 0x90000>, <0x009b0000 0x1040>, @@ -180,8 +180,8 @@ }; }; - smmu_mdp_unsec: qcom,smmu_mdp_unsec_cb { - compatible = "qcom,smmu_mdp_unsec"; + smmu_kms_unsec: qcom,smmu_kms_unsec_cb { + compatible = "qcom,smmu_kms_unsec"; iommus = <&mdp_smmu 0>; }; @@ -211,7 +211,7 @@ }; }; - mdss_dsi0: qcom,mdss_dsi_ctrl0@994000 { + sde_dsi0: qcom,sde_dsi_ctrl0@994000 { compatible = "qcom,dsi-ctrl-hw-v1.4"; label = "dsi-ctrl-0"; cell-index = <0>; @@ -246,7 +246,7 @@ <22 512 0 0>, <22 512 0 1000>; - interrupt-parent = <&mdss_mdp>; + interrupt-parent = <&sde_kms>; interrupts = <4 0>; qcom,core-supply-entries { #address-cells = <1>; @@ -287,7 +287,7 @@ }; }; - mdss_dsi1: qcom,mdss_dsi_ctrl1@996000 { + sde_dsi1: qcom,sde_dsi_ctrl1@996000 { compatible = "qcom,dsi-ctrl-hw-v1.4"; label = "dsi-ctrl-1"; cell-index = <1>; @@ -321,7 +321,7 @@ <22 512 0 0>, <22 512 0 1000>; - interrupt-parent = <&mdss_mdp>; + interrupt-parent = <&sde_kms>; interrupts = <5 0>; qcom,core-supply-entries { #address-cells = <1>; @@ -361,7 +361,7 @@ }; }; - mdss_dsi_phy0: qcom,mdss_dsi_phy0@994400 { + sde_dsi_phy0: qcom,sde_dsi_phy0@994400 { compatible = "qcom,dsi-phy-v4.0"; label = "dsi-phy-0"; cell-index = <0>; @@ -420,7 +420,7 @@ }; }; - mdss_dsi_phy1: qcom,mdss_dsi_phy1@996400 { + sde_dsi_phy1: qcom,sde_dsi_phy1@996400 { compatible = "qcom,dsi-phy-v4.0"; label = "dsi-phy-1"; cell-index = <1>; @@ -479,7 +479,7 @@ }; }; - mdss_hdmi: qcom,hdmi_tx@9a0000 { + sde_hdmi_tx: qcom,hdmi_tx_8996@9a0000 { compatible = "qcom,hdmi-tx-8996"; reg = <0x009a0000 0x50c>, @@ -499,7 +499,7 @@ "core_clk", "alt_iface_clk", "extp_clk"; - interrupt-parent = <&mdss_mdp>; + interrupt-parent = <&sde_kms>; interrupts = <8 0>; hpd-gdsc-supply = <&gdsc_mdss>; qcom,hdmi-tx-hpd-gpio = <&pm8994_mpps 4 0>; @@ -511,23 +511,8 @@ &mdss_hdmi_ddc_suspend &mdss_hdmi_cec_suspend>; - hdmi_audio: qcom,msm-hdmi-audio-rx { + sde_hdmi_audio: qcom,sde-hdmi-audio-rx { compatible = "qcom,msm-hdmi-audio-codec-rx"; }; }; }; - -/* dummy nodes for compatibility with 8996 mdss dtsi */ -&soc { - mdss_dsi: qcom,mdss_dsi_dummy { - /* dummy node for backward compatibility */ - }; - - mdss_hdmi_tx: qcom,mdss_hdmi_tx_dummy { - /* dummy node for backward compatibility */ - }; - - mdss_fb2: qcom,mdss_fb2_dummy { - /* dummy node for backward compatibility */ - }; -}; diff --git a/arch/arm/boot/dts/qcom/msm8996-v2.dtsi b/arch/arm/boot/dts/qcom/msm8996-v2.dtsi index 9725bc3ee530..698c0193a164 100644 --- a/arch/arm/boot/dts/qcom/msm8996-v2.dtsi +++ b/arch/arm/boot/dts/qcom/msm8996-v2.dtsi @@ -1,4 +1,4 @@ -/* Copyright (c) 2014-2016, The Linux Foundation. All rights reserved. +/* Copyright (c) 2014-2017, The Linux Foundation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 and @@ -480,7 +480,7 @@ gdsc-venus-supply = <&gdsc_venus>; }; -&mdss_hdmi { +&sde_hdmi_tx { hpd-gdsc-venus-supply = <&gdsc_venus>; }; diff --git a/arch/arm/boot/dts/qcom/msm8996.dtsi b/arch/arm/boot/dts/qcom/msm8996.dtsi index 80b3437beac6..dcd884b4a745 100644 --- a/arch/arm/boot/dts/qcom/msm8996.dtsi +++ b/arch/arm/boot/dts/qcom/msm8996.dtsi @@ -242,6 +242,7 @@ #include "msm8996-ion.dtsi" #include "msm8996-sde.dtsi" +#include "msm8996-mdss.dtsi" #include "msm8996-mdss-pll.dtsi" #include "msm8996-smp2p.dtsi" #include "msm8996-ipcrouter.dtsi" diff --git a/arch/arm/boot/dts/qcom/msm8996v3-auto.dtsi b/arch/arm/boot/dts/qcom/msm8996v3-auto.dtsi index 32adb9a36dd4..355062adf7ef 100644 --- a/arch/arm/boot/dts/qcom/msm8996v3-auto.dtsi +++ b/arch/arm/boot/dts/qcom/msm8996v3-auto.dtsi @@ -1,4 +1,4 @@ -/* Copyright (c) 2016, The Linux Foundation. All rights reserved. +/* Copyright (c) 2016 - 2017, The Linux Foundation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 and @@ -167,3 +167,40 @@ < 560000000 7 >, < 624000000 7 >; }; + +&soc { + ipa_hw: qcom,ipa@680000 { + compatible = "qcom,ipa"; + reg = <0x680000 0x4effc>, + <0x684000 0x26934>; + reg-names = "ipa-base", "bam-base"; + interrupts = <0 333 0>, + <0 432 0>; + interrupt-names = "ipa-irq", "bam-irq"; + qcom,ipa-hw-ver = <5>; /* IPA core version = IPAv2.5 */ + qcom,ipa-hw-mode = <0>; + qcom,ee = <0>; + qcom,use-ipa-tethering-bridge; + qcom,ipa-bam-remote-mode; + qcom,modem-cfg-emb-pipe-flt; + clocks = <&clock_gcc clk_ipa_clk>; + clock-names = "core_clk"; + qcom,use-dma-zone; + qcom,msm-bus,name = "ipa"; + qcom,msm-bus,num-cases = <3>; + qcom,msm-bus,num-paths = <2>; + qcom,msm-bus,vectors-KBps = + <90 512 0 0>, <90 585 0 0>, /* No vote */ + <90 512 80000 640000>, <90 585 80000 640000>, /* SVS */ + <90 512 206000 960000>, <90 585 206000 960000>; /* PERF */ + qcom,bus-vector-names = "MIN", "SVS", "PERF"; + }; + + qcom,rmnet-ipa { + compatible = "qcom,rmnet-ipa"; + qcom,rmnet-ipa-ssr; + qcom,ipa-loaduC; + qcom,ipa-advertise-sg-support; + }; +}; + diff --git a/arch/arm/boot/dts/qcom/msm8998-9x55-cdp.dts b/arch/arm/boot/dts/qcom/msm8998-9x55-cdp.dts new file mode 100644 index 000000000000..cf167897bb89 --- /dev/null +++ b/arch/arm/boot/dts/qcom/msm8998-9x55-cdp.dts @@ -0,0 +1,24 @@ +/* + * Copyright (c) 2017, The Linux Foundation. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 and + * 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 "msm8998-9x55.dtsi" +#include "msm8998-mdss-panels.dtsi" +#include "msm8998-cdp.dtsi" + +/ { + model = "Qualcomm Technologies, Inc. MSM8998-9x55 CDP"; + compatible = "qcom,msm8998-9x55-cdp", "qcom,msm8998-9x55", "qcom,cdp"; + qcom,board-id= <1 2>; +}; diff --git a/arch/arm/boot/dts/qcom/msm8998-9x55-mtp.dts b/arch/arm/boot/dts/qcom/msm8998-9x55-mtp.dts new file mode 100644 index 000000000000..a95e9e4f272f --- /dev/null +++ b/arch/arm/boot/dts/qcom/msm8998-9x55-mtp.dts @@ -0,0 +1,24 @@ +/* + * Copyright (c) 2017, The Linux Foundation. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 and + * 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 "msm8998-9x55.dtsi" +#include "msm8998-mdss-panels.dtsi" +#include "msm8998-mtp.dtsi" + +/ { + model = "Qualcomm Technologies, Inc. MSM8998-9x55 MTP"; + compatible = "qcom,msm8998-9x55-mtp", "qcom,msm8998-9x55", "qcom,mtp"; + qcom,board-id= <8 6>; +}; diff --git a/arch/arm/boot/dts/qcom/msm8998-9x55-rcm.dts b/arch/arm/boot/dts/qcom/msm8998-9x55-rcm.dts new file mode 100644 index 000000000000..094ecbc50061 --- /dev/null +++ b/arch/arm/boot/dts/qcom/msm8998-9x55-rcm.dts @@ -0,0 +1,24 @@ +/* + * Copyright (c) 2017, The Linux Foundation. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 and + * 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 "msm8998-9x55.dtsi" +#include "msm8998-mdss-panels.dtsi" +#include "msm8998-cdp.dtsi" + +/ { + model = "Qualcomm Technologies, Inc. MSM8998-9x55 RCM"; + compatible = "qcom,msm8998-9x55-cdp", "qcom,msm8998-9x55", "qcom,cdp"; + qcom,board-id= <0x21 2>; +}; diff --git a/arch/arm/boot/dts/qcom/msm8998-9x55.dtsi b/arch/arm/boot/dts/qcom/msm8998-9x55.dtsi new file mode 100644 index 000000000000..be947507e398 --- /dev/null +++ b/arch/arm/boot/dts/qcom/msm8998-9x55.dtsi @@ -0,0 +1,25 @@ +/* + * Copyright (c) 2017, The Linux Foundation. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 and + * 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 "skeleton64.dtsi" +#include "msm8998-v2.1.dtsi" + +/ { + model = "Qualcomm Technologies, Inc. MSM8998-9x55"; + compatible = "qcom,msm8998-9x55"; + qcom,msm-id = <292 0x0>; + interrupt-parent = <&intc>; + + soc: soc { }; +}; diff --git a/arch/arm/boot/dts/qcom/sdm630.dtsi b/arch/arm/boot/dts/qcom/sdm630.dtsi index 8ca0b94403cb..cff3aa809488 100644 --- a/arch/arm/boot/dts/qcom/sdm630.dtsi +++ b/arch/arm/boot/dts/qcom/sdm630.dtsi @@ -1689,6 +1689,7 @@ qcom,vdd-1.3-rfa-config = <1200000 1370000>; qcom,vdd-3.3-ch0-config = <3200000 3400000>; qcom,wlan-msa-memory = <0x100000>; + qcom,wlan-msa-fixed-region = <&wlan_msa_mem>; qcom,smmu-s1-bypass; }; diff --git a/arch/arm/boot/dts/qcom/sdm660.dtsi b/arch/arm/boot/dts/qcom/sdm660.dtsi index 8158825264c2..f14c9a32c2f9 100644 --- a/arch/arm/boot/dts/qcom/sdm660.dtsi +++ b/arch/arm/boot/dts/qcom/sdm660.dtsi @@ -1940,6 +1940,7 @@ qcom,vdd-1.3-rfa-config = <1200000 1370000>; qcom,vdd-3.3-ch0-config = <3200000 3400000>; qcom,wlan-msa-memory = <0x100000>; + qcom,wlan-msa-fixed-region = <&wlan_msa_mem>; qcom,smmu-s1-bypass; }; diff --git a/arch/arm/mm/mmu.c b/arch/arm/mm/mmu.c index 221b11bb50e3..f353849d9388 100644 --- a/arch/arm/mm/mmu.c +++ b/arch/arm/mm/mmu.c @@ -1197,15 +1197,15 @@ void __init sanity_check_meminfo(void) high_memory = __va(arm_lowmem_limit - 1) + 1; + if (!memblock_limit) + memblock_limit = arm_lowmem_limit; + /* * Round the memblock limit down to a pmd size. This * helps to ensure that we will allocate memory from the * last full pmd, which should be mapped. */ - if (memblock_limit) - memblock_limit = round_down(memblock_limit, PMD_SIZE); - if (!memblock_limit) - memblock_limit = arm_lowmem_limit; + memblock_limit = round_down(memblock_limit, PMD_SIZE); memblock_set_current_limit(memblock_limit); } diff --git a/arch/arm64/configs/msmcortex-perf_defconfig b/arch/arm64/configs/msmcortex-perf_defconfig index 5692f0dcd65e..894cb466b075 100644 --- a/arch/arm64/configs/msmcortex-perf_defconfig +++ b/arch/arm64/configs/msmcortex-perf_defconfig @@ -16,7 +16,6 @@ CONFIG_RCU_NOCB_CPU_ALL=y CONFIG_IKCONFIG=y CONFIG_IKCONFIG_PROC=y CONFIG_LOG_CPU_MAX_BUF_SHIFT=17 -CONFIG_CGROUP_DEBUG=y CONFIG_CGROUP_FREEZER=y CONFIG_CPUSETS=y CONFIG_CGROUP_CPUACCT=y diff --git a/arch/arm64/include/asm/acpi.h b/arch/arm64/include/asm/acpi.h index aee323b13802..0a11cd502dbc 100644 --- a/arch/arm64/include/asm/acpi.h +++ b/arch/arm64/include/asm/acpi.h @@ -22,9 +22,9 @@ #define ACPI_MADT_GICC_LENGTH \ (acpi_gbl_FADT.header.revision < 6 ? 76 : 80) -#define BAD_MADT_GICC_ENTRY(entry, end) \ - (!(entry) || (unsigned long)(entry) + sizeof(*(entry)) > (end) || \ - (entry)->header.length != ACPI_MADT_GICC_LENGTH) +#define BAD_MADT_GICC_ENTRY(entry, end) \ + (!(entry) || (entry)->header.length != ACPI_MADT_GICC_LENGTH || \ + (unsigned long)(entry) + ACPI_MADT_GICC_LENGTH > (end)) /* Basic configuration for ACPI */ #ifdef CONFIG_ACPI diff --git a/arch/arm64/kernel/perf_trace_counters.c b/arch/arm64/kernel/perf_trace_counters.c index 748ad449fc18..dc92b29ac103 100644 --- a/arch/arm64/kernel/perf_trace_counters.c +++ b/arch/arm64/kernel/perf_trace_counters.c @@ -1,4 +1,4 @@ -/* Copyright (c) 2013-2014, The Linux Foundation. All rights reserved. +/* Copyright (c) 2013-2014, 2017 The Linux Foundation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 and @@ -124,6 +124,7 @@ static ssize_t write_enabled_perftp_file_bool(struct file *file, char buf[32]; size_t buf_size; + buf[0] = 0; buf_size = min(count, (sizeof(buf)-1)); if (copy_from_user(buf, user_buf, buf_size)) return -EFAULT; diff --git a/arch/mips/ath79/common.c b/arch/mips/ath79/common.c index 3cedd1f95e0f..8ae4067a5eda 100644 --- a/arch/mips/ath79/common.c +++ b/arch/mips/ath79/common.c @@ -76,14 +76,14 @@ void ath79_ddr_set_pci_windows(void) { BUG_ON(!ath79_ddr_pci_win_base); - __raw_writel(AR71XX_PCI_WIN0_OFFS, ath79_ddr_pci_win_base + 0); - __raw_writel(AR71XX_PCI_WIN1_OFFS, ath79_ddr_pci_win_base + 1); - __raw_writel(AR71XX_PCI_WIN2_OFFS, ath79_ddr_pci_win_base + 2); - __raw_writel(AR71XX_PCI_WIN3_OFFS, ath79_ddr_pci_win_base + 3); - __raw_writel(AR71XX_PCI_WIN4_OFFS, ath79_ddr_pci_win_base + 4); - __raw_writel(AR71XX_PCI_WIN5_OFFS, ath79_ddr_pci_win_base + 5); - __raw_writel(AR71XX_PCI_WIN6_OFFS, ath79_ddr_pci_win_base + 6); - __raw_writel(AR71XX_PCI_WIN7_OFFS, ath79_ddr_pci_win_base + 7); + __raw_writel(AR71XX_PCI_WIN0_OFFS, ath79_ddr_pci_win_base + 0x0); + __raw_writel(AR71XX_PCI_WIN1_OFFS, ath79_ddr_pci_win_base + 0x4); + __raw_writel(AR71XX_PCI_WIN2_OFFS, ath79_ddr_pci_win_base + 0x8); + __raw_writel(AR71XX_PCI_WIN3_OFFS, ath79_ddr_pci_win_base + 0xc); + __raw_writel(AR71XX_PCI_WIN4_OFFS, ath79_ddr_pci_win_base + 0x10); + __raw_writel(AR71XX_PCI_WIN5_OFFS, ath79_ddr_pci_win_base + 0x14); + __raw_writel(AR71XX_PCI_WIN6_OFFS, ath79_ddr_pci_win_base + 0x18); + __raw_writel(AR71XX_PCI_WIN7_OFFS, ath79_ddr_pci_win_base + 0x1c); } EXPORT_SYMBOL_GPL(ath79_ddr_set_pci_windows); diff --git a/arch/mips/kernel/entry.S b/arch/mips/kernel/entry.S index 7791840cf22c..db07793f7b43 100644 --- a/arch/mips/kernel/entry.S +++ b/arch/mips/kernel/entry.S @@ -11,6 +11,7 @@ #include <asm/asm.h> #include <asm/asmmacro.h> #include <asm/compiler.h> +#include <asm/irqflags.h> #include <asm/regdef.h> #include <asm/mipsregs.h> #include <asm/stackframe.h> @@ -137,6 +138,7 @@ work_pending: andi t0, a2, _TIF_NEED_RESCHED # a2 is preloaded with TI_FLAGS beqz t0, work_notifysig work_resched: + TRACE_IRQS_OFF jal schedule local_irq_disable # make sure need_resched and @@ -173,6 +175,7 @@ syscall_exit_work: beqz t0, work_pending # trace bit set? local_irq_enable # could let syscall_trace_leave() # call schedule() instead + TRACE_IRQS_ON move a0, sp jal syscall_trace_leave b resume_userspace diff --git a/arch/mips/kernel/pm-cps.c b/arch/mips/kernel/pm-cps.c index f63a289977cc..0b3e58a3189f 100644 --- a/arch/mips/kernel/pm-cps.c +++ b/arch/mips/kernel/pm-cps.c @@ -55,7 +55,6 @@ DECLARE_BITMAP(state_support, CPS_PM_STATE_COUNT); * state. Actually per-core rather than per-CPU. */ static DEFINE_PER_CPU_ALIGNED(u32*, ready_count); -static DEFINE_PER_CPU_ALIGNED(void*, ready_count_alloc); /* Indicates online CPUs coupled with the current CPU */ static DEFINE_PER_CPU_ALIGNED(cpumask_t, online_coupled); @@ -625,7 +624,6 @@ static int __init cps_gen_core_entries(unsigned cpu) { enum cps_pm_state state; unsigned core = cpu_data[cpu].core; - unsigned dlinesz = cpu_data[cpu].dcache.linesz; void *entry_fn, *core_rc; for (state = CPS_PM_NC_WAIT; state < CPS_PM_STATE_COUNT; state++) { @@ -645,16 +643,11 @@ static int __init cps_gen_core_entries(unsigned cpu) } if (!per_cpu(ready_count, core)) { - core_rc = kmalloc(dlinesz * 2, GFP_KERNEL); + core_rc = kmalloc(sizeof(u32), GFP_KERNEL); if (!core_rc) { pr_err("Failed allocate core %u ready_count\n", core); return -ENOMEM; } - per_cpu(ready_count_alloc, core) = core_rc; - - /* Ensure ready_count is aligned to a cacheline boundary */ - core_rc += dlinesz - 1; - core_rc = (void *)((unsigned long)core_rc & ~(dlinesz - 1)); per_cpu(ready_count, core) = core_rc; } diff --git a/arch/mips/kernel/traps.c b/arch/mips/kernel/traps.c index 99a402231f4d..31ca2edd7218 100644 --- a/arch/mips/kernel/traps.c +++ b/arch/mips/kernel/traps.c @@ -194,6 +194,8 @@ void show_stack(struct task_struct *task, unsigned long *sp) { struct pt_regs regs; mm_segment_t old_fs = get_fs(); + + regs.cp0_status = KSU_KERNEL; if (sp) { regs.regs[29] = (unsigned long)sp; regs.regs[31] = 0; diff --git a/arch/mips/ralink/mt7620.c b/arch/mips/ralink/mt7620.c index dfb04fcedb04..48d6349fd9d7 100644 --- a/arch/mips/ralink/mt7620.c +++ b/arch/mips/ralink/mt7620.c @@ -107,31 +107,31 @@ static struct rt2880_pmx_group mt7620a_pinmux_data[] = { }; static struct rt2880_pmx_func pwm1_grp_mt7628[] = { - FUNC("sdcx", 3, 19, 1), + FUNC("sdxc d6", 3, 19, 1), FUNC("utif", 2, 19, 1), FUNC("gpio", 1, 19, 1), - FUNC("pwm", 0, 19, 1), + FUNC("pwm1", 0, 19, 1), }; static struct rt2880_pmx_func pwm0_grp_mt7628[] = { - FUNC("sdcx", 3, 18, 1), + FUNC("sdxc d7", 3, 18, 1), FUNC("utif", 2, 18, 1), FUNC("gpio", 1, 18, 1), - FUNC("pwm", 0, 18, 1), + FUNC("pwm0", 0, 18, 1), }; static struct rt2880_pmx_func uart2_grp_mt7628[] = { - FUNC("sdcx", 3, 20, 2), + FUNC("sdxc d5 d4", 3, 20, 2), FUNC("pwm", 2, 20, 2), FUNC("gpio", 1, 20, 2), - FUNC("uart", 0, 20, 2), + FUNC("uart2", 0, 20, 2), }; static struct rt2880_pmx_func uart1_grp_mt7628[] = { - FUNC("sdcx", 3, 45, 2), + FUNC("sw_r", 3, 45, 2), FUNC("pwm", 2, 45, 2), FUNC("gpio", 1, 45, 2), - FUNC("uart", 0, 45, 2), + FUNC("uart1", 0, 45, 2), }; static struct rt2880_pmx_func i2c_grp_mt7628[] = { @@ -143,21 +143,21 @@ static struct rt2880_pmx_func i2c_grp_mt7628[] = { static struct rt2880_pmx_func refclk_grp_mt7628[] = { FUNC("reclk", 0, 36, 1) }; static struct rt2880_pmx_func perst_grp_mt7628[] = { FUNC("perst", 0, 37, 1) }; -static struct rt2880_pmx_func wdt_grp_mt7628[] = { FUNC("wdt", 0, 15, 38) }; +static struct rt2880_pmx_func wdt_grp_mt7628[] = { FUNC("wdt", 0, 38, 1) }; static struct rt2880_pmx_func spi_grp_mt7628[] = { FUNC("spi", 0, 7, 4) }; static struct rt2880_pmx_func sd_mode_grp_mt7628[] = { FUNC("jtag", 3, 22, 8), FUNC("utif", 2, 22, 8), FUNC("gpio", 1, 22, 8), - FUNC("sdcx", 0, 22, 8), + FUNC("sdxc", 0, 22, 8), }; static struct rt2880_pmx_func uart0_grp_mt7628[] = { FUNC("-", 3, 12, 2), FUNC("-", 2, 12, 2), FUNC("gpio", 1, 12, 2), - FUNC("uart", 0, 12, 2), + FUNC("uart0", 0, 12, 2), }; static struct rt2880_pmx_func i2s_grp_mt7628[] = { @@ -171,7 +171,7 @@ static struct rt2880_pmx_func spi_cs1_grp_mt7628[] = { FUNC("-", 3, 6, 1), FUNC("refclk", 2, 6, 1), FUNC("gpio", 1, 6, 1), - FUNC("spi", 0, 6, 1), + FUNC("spi cs1", 0, 6, 1), }; static struct rt2880_pmx_func spis_grp_mt7628[] = { @@ -188,28 +188,44 @@ static struct rt2880_pmx_func gpio_grp_mt7628[] = { FUNC("gpio", 0, 11, 1), }; -#define MT7628_GPIO_MODE_MASK 0x3 - -#define MT7628_GPIO_MODE_PWM1 30 -#define MT7628_GPIO_MODE_PWM0 28 -#define MT7628_GPIO_MODE_UART2 26 -#define MT7628_GPIO_MODE_UART1 24 -#define MT7628_GPIO_MODE_I2C 20 -#define MT7628_GPIO_MODE_REFCLK 18 -#define MT7628_GPIO_MODE_PERST 16 -#define MT7628_GPIO_MODE_WDT 14 -#define MT7628_GPIO_MODE_SPI 12 -#define MT7628_GPIO_MODE_SDMODE 10 -#define MT7628_GPIO_MODE_UART0 8 -#define MT7628_GPIO_MODE_I2S 6 -#define MT7628_GPIO_MODE_CS1 4 -#define MT7628_GPIO_MODE_SPIS 2 -#define MT7628_GPIO_MODE_GPIO 0 +static struct rt2880_pmx_func wled_kn_grp_mt7628[] = { + FUNC("rsvd", 3, 35, 1), + FUNC("rsvd", 2, 35, 1), + FUNC("gpio", 1, 35, 1), + FUNC("wled_kn", 0, 35, 1), +}; + +static struct rt2880_pmx_func wled_an_grp_mt7628[] = { + FUNC("rsvd", 3, 44, 1), + FUNC("rsvd", 2, 44, 1), + FUNC("gpio", 1, 44, 1), + FUNC("wled_an", 0, 44, 1), +}; + +#define MT7628_GPIO_MODE_MASK 0x3 + +#define MT7628_GPIO_MODE_WLED_KN 48 +#define MT7628_GPIO_MODE_WLED_AN 32 +#define MT7628_GPIO_MODE_PWM1 30 +#define MT7628_GPIO_MODE_PWM0 28 +#define MT7628_GPIO_MODE_UART2 26 +#define MT7628_GPIO_MODE_UART1 24 +#define MT7628_GPIO_MODE_I2C 20 +#define MT7628_GPIO_MODE_REFCLK 18 +#define MT7628_GPIO_MODE_PERST 16 +#define MT7628_GPIO_MODE_WDT 14 +#define MT7628_GPIO_MODE_SPI 12 +#define MT7628_GPIO_MODE_SDMODE 10 +#define MT7628_GPIO_MODE_UART0 8 +#define MT7628_GPIO_MODE_I2S 6 +#define MT7628_GPIO_MODE_CS1 4 +#define MT7628_GPIO_MODE_SPIS 2 +#define MT7628_GPIO_MODE_GPIO 0 static struct rt2880_pmx_group mt7628an_pinmux_data[] = { - GRP_G("pmw1", pwm1_grp_mt7628, MT7628_GPIO_MODE_MASK, + GRP_G("pwm1", pwm1_grp_mt7628, MT7628_GPIO_MODE_MASK, 1, MT7628_GPIO_MODE_PWM1), - GRP_G("pmw1", pwm0_grp_mt7628, MT7628_GPIO_MODE_MASK, + GRP_G("pwm0", pwm0_grp_mt7628, MT7628_GPIO_MODE_MASK, 1, MT7628_GPIO_MODE_PWM0), GRP_G("uart2", uart2_grp_mt7628, MT7628_GPIO_MODE_MASK, 1, MT7628_GPIO_MODE_UART2), @@ -233,6 +249,10 @@ static struct rt2880_pmx_group mt7628an_pinmux_data[] = { 1, MT7628_GPIO_MODE_SPIS), GRP_G("gpio", gpio_grp_mt7628, MT7628_GPIO_MODE_MASK, 1, MT7628_GPIO_MODE_GPIO), + GRP_G("wled_an", wled_an_grp_mt7628, MT7628_GPIO_MODE_MASK, + 1, MT7628_GPIO_MODE_WLED_AN), + GRP_G("wled_kn", wled_kn_grp_mt7628, MT7628_GPIO_MODE_MASK, + 1, MT7628_GPIO_MODE_WLED_KN), { 0 } }; @@ -439,7 +459,7 @@ void __init ralink_clk_init(void) ralink_clk_add("10000c00.uartlite", periph_rate); ralink_clk_add("10180000.wmac", xtal_rate); - if (IS_ENABLED(CONFIG_USB) && is_mt76x8()) { + if (IS_ENABLED(CONFIG_USB) && !is_mt76x8()) { /* * When the CPU goes into sleep mode, the BUS clock will be * too low for USB to function properly. Adjust the busses diff --git a/arch/mips/ralink/rt288x.c b/arch/mips/ralink/rt288x.c index 15506a1ff22a..9dd67749c592 100644 --- a/arch/mips/ralink/rt288x.c +++ b/arch/mips/ralink/rt288x.c @@ -109,5 +109,5 @@ void prom_soc_init(struct ralink_soc_info *soc_info) soc_info->mem_size_max = RT2880_MEM_SIZE_MAX; rt2880_pinmux_data = rt2880_pinmux_data_act; - ralink_soc == RT2880_SOC; + ralink_soc = RT2880_SOC; } diff --git a/arch/powerpc/kernel/eeh.c b/arch/powerpc/kernel/eeh.c index 98949b0df00a..6696c1986844 100644 --- a/arch/powerpc/kernel/eeh.c +++ b/arch/powerpc/kernel/eeh.c @@ -304,9 +304,17 @@ void eeh_slot_error_detail(struct eeh_pe *pe, int severity) * * For pHyp, we have to enable IO for log retrieval. Otherwise, * 0xFF's is always returned from PCI config space. + * + * When the @severity is EEH_LOG_PERM, the PE is going to be + * removed. Prior to that, the drivers for devices included in + * the PE will be closed. The drivers rely on working IO path + * to bring the devices to quiet state. Otherwise, PCI traffic + * from those devices after they are removed is like to cause + * another unexpected EEH error. */ if (!(pe->type & EEH_PE_PHB)) { - if (eeh_has_flag(EEH_ENABLE_IO_FOR_LOG)) + if (eeh_has_flag(EEH_ENABLE_IO_FOR_LOG) || + severity == EEH_LOG_PERM) eeh_pci_enable(pe, EEH_OPT_THAW_MMIO); /* diff --git a/arch/s390/include/asm/ctl_reg.h b/arch/s390/include/asm/ctl_reg.h index d7697ab802f6..8e136b88cdf4 100644 --- a/arch/s390/include/asm/ctl_reg.h +++ b/arch/s390/include/asm/ctl_reg.h @@ -15,7 +15,9 @@ BUILD_BUG_ON(sizeof(addrtype) != (high - low + 1) * sizeof(long));\ asm volatile( \ " lctlg %1,%2,%0\n" \ - : : "Q" (*(addrtype *)(&array)), "i" (low), "i" (high));\ + : \ + : "Q" (*(addrtype *)(&array)), "i" (low), "i" (high) \ + : "memory"); \ } #define __ctl_store(array, low, high) { \ diff --git a/arch/x86/include/asm/kvm_emulate.h b/arch/x86/include/asm/kvm_emulate.h index e9cd7befcb76..19d14ac23ef9 100644 --- a/arch/x86/include/asm/kvm_emulate.h +++ b/arch/x86/include/asm/kvm_emulate.h @@ -221,6 +221,9 @@ struct x86_emulate_ops { void (*get_cpuid)(struct x86_emulate_ctxt *ctxt, u32 *eax, u32 *ebx, u32 *ecx, u32 *edx); void (*set_nmi_mask)(struct x86_emulate_ctxt *ctxt, bool masked); + + unsigned (*get_hflags)(struct x86_emulate_ctxt *ctxt); + void (*set_hflags)(struct x86_emulate_ctxt *ctxt, unsigned hflags); }; typedef u32 __attribute__((vector_size(16))) sse128_t; @@ -290,7 +293,6 @@ struct x86_emulate_ctxt { /* interruptibility state, as a result of execution of STI or MOV SS */ int interruptibility; - int emul_flags; bool perm_ok; /* do not check permissions if true */ bool ud; /* inject an #UD if host doesn't support insn */ diff --git a/arch/x86/kvm/emulate.c b/arch/x86/kvm/emulate.c index 1dcea225977d..04b2f3cad7ba 100644 --- a/arch/x86/kvm/emulate.c +++ b/arch/x86/kvm/emulate.c @@ -2531,7 +2531,7 @@ static int em_rsm(struct x86_emulate_ctxt *ctxt) u64 smbase; int ret; - if ((ctxt->emul_flags & X86EMUL_SMM_MASK) == 0) + if ((ctxt->ops->get_hflags(ctxt) & X86EMUL_SMM_MASK) == 0) return emulate_ud(ctxt); /* @@ -2580,11 +2580,11 @@ static int em_rsm(struct x86_emulate_ctxt *ctxt) return X86EMUL_UNHANDLEABLE; } - if ((ctxt->emul_flags & X86EMUL_SMM_INSIDE_NMI_MASK) == 0) + if ((ctxt->ops->get_hflags(ctxt) & X86EMUL_SMM_INSIDE_NMI_MASK) == 0) ctxt->ops->set_nmi_mask(ctxt, false); - ctxt->emul_flags &= ~X86EMUL_SMM_INSIDE_NMI_MASK; - ctxt->emul_flags &= ~X86EMUL_SMM_MASK; + ctxt->ops->set_hflags(ctxt, ctxt->ops->get_hflags(ctxt) & + ~(X86EMUL_SMM_INSIDE_NMI_MASK | X86EMUL_SMM_MASK)); return X86EMUL_CONTINUE; } @@ -5296,6 +5296,7 @@ int x86_emulate_insn(struct x86_emulate_ctxt *ctxt) const struct x86_emulate_ops *ops = ctxt->ops; int rc = X86EMUL_CONTINUE; int saved_dst_type = ctxt->dst.type; + unsigned emul_flags; ctxt->mem_read.pos = 0; @@ -5310,6 +5311,7 @@ int x86_emulate_insn(struct x86_emulate_ctxt *ctxt) goto done; } + emul_flags = ctxt->ops->get_hflags(ctxt); if (unlikely(ctxt->d & (No64|Undefined|Sse|Mmx|Intercept|CheckPerm|Priv|Prot|String))) { if ((ctxt->mode == X86EMUL_MODE_PROT64 && (ctxt->d & No64)) || @@ -5343,7 +5345,7 @@ int x86_emulate_insn(struct x86_emulate_ctxt *ctxt) fetch_possible_mmx_operand(ctxt, &ctxt->dst); } - if (unlikely(ctxt->emul_flags & X86EMUL_GUEST_MASK) && ctxt->intercept) { + if (unlikely(emul_flags & X86EMUL_GUEST_MASK) && ctxt->intercept) { rc = emulator_check_intercept(ctxt, ctxt->intercept, X86_ICPT_PRE_EXCEPT); if (rc != X86EMUL_CONTINUE) @@ -5372,7 +5374,7 @@ int x86_emulate_insn(struct x86_emulate_ctxt *ctxt) goto done; } - if (unlikely(ctxt->emul_flags & X86EMUL_GUEST_MASK) && (ctxt->d & Intercept)) { + if (unlikely(emul_flags & X86EMUL_GUEST_MASK) && (ctxt->d & Intercept)) { rc = emulator_check_intercept(ctxt, ctxt->intercept, X86_ICPT_POST_EXCEPT); if (rc != X86EMUL_CONTINUE) @@ -5426,7 +5428,7 @@ int x86_emulate_insn(struct x86_emulate_ctxt *ctxt) special_insn: - if (unlikely(ctxt->emul_flags & X86EMUL_GUEST_MASK) && (ctxt->d & Intercept)) { + if (unlikely(emul_flags & X86EMUL_GUEST_MASK) && (ctxt->d & Intercept)) { rc = emulator_check_intercept(ctxt, ctxt->intercept, X86_ICPT_POST_MEMACCESS); if (rc != X86EMUL_CONTINUE) diff --git a/arch/x86/kvm/pmu_intel.c b/arch/x86/kvm/pmu_intel.c index ab38af4f4947..23a7c7ba377a 100644 --- a/arch/x86/kvm/pmu_intel.c +++ b/arch/x86/kvm/pmu_intel.c @@ -294,7 +294,7 @@ static void intel_pmu_refresh(struct kvm_vcpu *vcpu) ((u64)1 << edx.split.bit_width_fixed) - 1; } - pmu->global_ctrl = ((1 << pmu->nr_arch_gp_counters) - 1) | + pmu->global_ctrl = ((1ull << pmu->nr_arch_gp_counters) - 1) | (((1ull << pmu->nr_arch_fixed_counters) - 1) << INTEL_PMC_IDX_FIXED); pmu->global_ctrl_mask = ~pmu->global_ctrl; diff --git a/arch/x86/kvm/vmx.c b/arch/x86/kvm/vmx.c index 50ca8f409a7c..bbaa11f4e74b 100644 --- a/arch/x86/kvm/vmx.c +++ b/arch/x86/kvm/vmx.c @@ -2264,7 +2264,7 @@ static int nested_vmx_check_exception(struct kvm_vcpu *vcpu, unsigned nr) if (!(vmcs12->exception_bitmap & (1u << nr))) return 0; - nested_vmx_vmexit(vcpu, to_vmx(vcpu)->exit_reason, + nested_vmx_vmexit(vcpu, EXIT_REASON_EXCEPTION_NMI, vmcs_read32(VM_EXIT_INTR_INFO), vmcs_readl(EXIT_QUALIFICATION)); return 1; diff --git a/arch/x86/kvm/x86.c b/arch/x86/kvm/x86.c index 6c82792487e9..8e526c6fd784 100644 --- a/arch/x86/kvm/x86.c +++ b/arch/x86/kvm/x86.c @@ -4844,6 +4844,8 @@ static bool emulator_get_segment(struct x86_emulate_ctxt *ctxt, u16 *selector, if (var.unusable) { memset(desc, 0, sizeof(*desc)); + if (base3) + *base3 = 0; return false; } @@ -4999,6 +5001,16 @@ static void emulator_set_nmi_mask(struct x86_emulate_ctxt *ctxt, bool masked) kvm_x86_ops->set_nmi_mask(emul_to_vcpu(ctxt), masked); } +static unsigned emulator_get_hflags(struct x86_emulate_ctxt *ctxt) +{ + return emul_to_vcpu(ctxt)->arch.hflags; +} + +static void emulator_set_hflags(struct x86_emulate_ctxt *ctxt, unsigned emul_flags) +{ + kvm_set_hflags(emul_to_vcpu(ctxt), emul_flags); +} + static const struct x86_emulate_ops emulate_ops = { .read_gpr = emulator_read_gpr, .write_gpr = emulator_write_gpr, @@ -5038,6 +5050,8 @@ static const struct x86_emulate_ops emulate_ops = { .intercept = emulator_intercept, .get_cpuid = emulator_get_cpuid, .set_nmi_mask = emulator_set_nmi_mask, + .get_hflags = emulator_get_hflags, + .set_hflags = emulator_set_hflags, }; static void toggle_interruptibility(struct kvm_vcpu *vcpu, u32 mask) @@ -5090,7 +5104,6 @@ static void init_emulate_ctxt(struct kvm_vcpu *vcpu) BUILD_BUG_ON(HF_GUEST_MASK != X86EMUL_GUEST_MASK); BUILD_BUG_ON(HF_SMM_MASK != X86EMUL_SMM_MASK); BUILD_BUG_ON(HF_SMM_INSIDE_NMI_MASK != X86EMUL_SMM_INSIDE_NMI_MASK); - ctxt->emul_flags = vcpu->arch.hflags; init_decode_cache(ctxt); vcpu->arch.emulate_regs_need_sync_from_vcpu = false; @@ -5486,8 +5499,6 @@ restart: unsigned long rflags = kvm_x86_ops->get_rflags(vcpu); toggle_interruptibility(vcpu, ctxt->interruptibility); vcpu->arch.emulate_regs_need_sync_to_vcpu = false; - if (vcpu->arch.hflags != ctxt->emul_flags) - kvm_set_hflags(vcpu, ctxt->emul_flags); kvm_rip_write(vcpu, ctxt->eip); if (r == EMULATE_DONE) kvm_vcpu_check_singlestep(vcpu, rflags, &r); @@ -5974,7 +5985,8 @@ static int emulator_fix_hypercall(struct x86_emulate_ctxt *ctxt) kvm_x86_ops->patch_hypercall(vcpu, instruction); - return emulator_write_emulated(ctxt, rip, instruction, 3, NULL); + return emulator_write_emulated(ctxt, rip, instruction, 3, + &ctxt->exception); } static int dm_request_for_irq_injection(struct kvm_vcpu *vcpu) diff --git a/arch/x86/mm/mpx.c b/arch/x86/mm/mpx.c index ef05755a1900..7ed47b1e6f42 100644 --- a/arch/x86/mm/mpx.c +++ b/arch/x86/mm/mpx.c @@ -293,7 +293,7 @@ siginfo_t *mpx_generate_siginfo(struct pt_regs *regs) * We were not able to extract an address from the instruction, * probably because there was something invalid in it. */ - if (info->si_addr == (void *)-1) { + if (info->si_addr == (void __user *)-1) { err = -EINVAL; goto err_out; } @@ -525,15 +525,7 @@ int mpx_handle_bd_fault(void) if (!kernel_managing_mpx_tables(current->mm)) return -EINVAL; - if (do_mpx_bt_fault()) { - force_sig(SIGSEGV, current); - /* - * The force_sig() is essentially "handling" this - * exception, so we do not pass up the error - * from do_mpx_bt_fault(). - */ - } - return 0; + return do_mpx_bt_fault(); } /* diff --git a/arch/x86/mm/tlb.c b/arch/x86/mm/tlb.c index 5fb6adaaa796..5a760fd66bec 100644 --- a/arch/x86/mm/tlb.c +++ b/arch/x86/mm/tlb.c @@ -134,8 +134,6 @@ void native_flush_tlb_others(const struct cpumask *cpumask, { struct flush_tlb_info info; - if (end == 0) - end = start + PAGE_SIZE; info.flush_mm = mm; info.flush_start = start; info.flush_end = end; @@ -264,7 +262,7 @@ void flush_tlb_page(struct vm_area_struct *vma, unsigned long start) } if (cpumask_any_but(mm_cpumask(mm), smp_processor_id()) < nr_cpu_ids) - flush_tlb_others(mm_cpumask(mm), mm, start, 0UL); + flush_tlb_others(mm_cpumask(mm), mm, start, start + PAGE_SIZE); preempt_enable(); } diff --git a/drivers/char/adsprpc.c b/drivers/char/adsprpc.c index 13016f32b344..a84172106e0f 100644 --- a/drivers/char/adsprpc.c +++ b/drivers/char/adsprpc.c @@ -212,6 +212,7 @@ struct fastrpc_channel_ctx { struct device *dev; struct fastrpc_session_ctx session[NUM_SESSIONS]; struct completion work; + struct completion workport; struct notifier_block nb; struct kref kref; int channel; @@ -1474,6 +1475,7 @@ static void fastrpc_init(struct fastrpc_apps *me) me->channel = &gcinfo[0]; for (i = 0; i < NUM_CHANNELS; i++) { init_completion(&me->channel[i].work); + init_completion(&me->channel[i].workport); me->channel[i].sesscount = 0; } } @@ -2135,7 +2137,7 @@ void fastrpc_glink_notify_state(void *handle, const void *priv, unsigned event) switch (event) { case GLINK_CONNECTED: link->port_state = FASTRPC_LINK_CONNECTED; - complete(&me->channel[cid].work); + complete(&me->channel[cid].workport); break; case GLINK_LOCAL_DISCONNECTED: link->port_state = FASTRPC_LINK_DISCONNECTED; @@ -2285,8 +2287,7 @@ static void fastrpc_glink_close(void *chan, int cid) return; link = &gfa.channel[cid].link; - if (link->port_state == FASTRPC_LINK_CONNECTED || - link->port_state == FASTRPC_LINK_CONNECTING) { + if (link->port_state == FASTRPC_LINK_CONNECTED) { link->port_state = FASTRPC_LINK_DISCONNECTING; glink_close(chan); } @@ -2484,8 +2485,9 @@ static int fastrpc_channel_open(struct fastrpc_file *fl) if (err) goto bail; - VERIFY(err, wait_for_completion_timeout(&me->channel[cid].work, - RPC_TIMEOUT)); + VERIFY(err, + wait_for_completion_timeout(&me->channel[cid].workport, + RPC_TIMEOUT)); if (err) { me->channel[cid].chan = 0; goto bail; diff --git a/drivers/char/diag/diag_masks.c b/drivers/char/diag/diag_masks.c index 20e617ed0770..e37609abf7bf 100644 --- a/drivers/char/diag/diag_masks.c +++ b/drivers/char/diag/diag_masks.c @@ -796,7 +796,9 @@ static int diag_cmd_set_msg_mask(unsigned char *src_buf, int src_len, for (i = 0; i < NUM_PERIPHERALS; i++) { if (!diag_check_update(i)) continue; + mutex_lock(&driver->md_session_lock); diag_send_msg_mask_update(i, req->ssid_first, req->ssid_last); + mutex_unlock(&driver->md_session_lock); } end: return write_len; @@ -856,7 +858,9 @@ static int diag_cmd_set_all_msg_mask(unsigned char *src_buf, int src_len, for (i = 0; i < NUM_PERIPHERALS; i++) { if (!diag_check_update(i)) continue; + mutex_lock(&driver->md_session_lock); diag_send_msg_mask_update(i, ALL_SSID, ALL_SSID); + mutex_unlock(&driver->md_session_lock); } return write_len; @@ -950,7 +954,9 @@ static int diag_cmd_update_event_mask(unsigned char *src_buf, int src_len, for (i = 0; i < NUM_PERIPHERALS; i++) { if (!diag_check_update(i)) continue; + mutex_lock(&driver->md_session_lock); diag_send_event_mask_update(i); + mutex_unlock(&driver->md_session_lock); } return write_len; @@ -997,7 +1003,9 @@ static int diag_cmd_toggle_events(unsigned char *src_buf, int src_len, for (i = 0; i < NUM_PERIPHERALS; i++) { if (!diag_check_update(i)) continue; + mutex_lock(&driver->md_session_lock); diag_send_event_mask_update(i); + mutex_unlock(&driver->md_session_lock); } memcpy(dest_buf, &header, sizeof(header)); write_len += sizeof(header); @@ -1251,7 +1259,9 @@ static int diag_cmd_set_log_mask(unsigned char *src_buf, int src_len, for (i = 0; i < NUM_PERIPHERALS; i++) { if (!diag_check_update(i)) continue; + mutex_lock(&driver->md_session_lock); diag_send_log_mask_update(i, req->equip_id); + mutex_unlock(&driver->md_session_lock); } end: return write_len; @@ -1302,7 +1312,9 @@ static int diag_cmd_disable_log_mask(unsigned char *src_buf, int src_len, for (i = 0; i < NUM_PERIPHERALS; i++) { if (!diag_check_update(i)) continue; + mutex_lock(&driver->md_session_lock); diag_send_log_mask_update(i, ALL_EQUIP_ID); + mutex_unlock(&driver->md_session_lock); } return write_len; @@ -1966,9 +1978,11 @@ void diag_send_updates_peripheral(uint8_t peripheral) diag_send_feature_mask_update(peripheral); if (driver->time_sync_enabled) diag_send_time_sync_update(peripheral); + mutex_lock(&driver->md_session_lock); diag_send_msg_mask_update(peripheral, ALL_SSID, ALL_SSID); diag_send_log_mask_update(peripheral, ALL_EQUIP_ID); diag_send_event_mask_update(peripheral); + mutex_unlock(&driver->md_session_lock); diag_send_real_time_update(peripheral, driver->real_time_mode[DIAG_LOCAL_PROC]); diag_send_peripheral_buffering_mode( diff --git a/drivers/char/diag/diag_memorydevice.c b/drivers/char/diag/diag_memorydevice.c index 06b83f5230bf..a27f12883c8d 100644 --- a/drivers/char/diag/diag_memorydevice.c +++ b/drivers/char/diag/diag_memorydevice.c @@ -129,37 +129,6 @@ void diag_md_close_all() diag_ws_reset(DIAG_WS_MUX); } -static int diag_md_get_peripheral(int ctxt) -{ - int peripheral; - - if (driver->num_pd_session) { - peripheral = GET_PD_CTXT(ctxt); - switch (peripheral) { - case UPD_WLAN: - case UPD_AUDIO: - case UPD_SENSORS: - break; - case DIAG_ID_MPSS: - case DIAG_ID_LPASS: - case DIAG_ID_CDSP: - default: - peripheral = - GET_BUF_PERIPHERAL(ctxt); - if (peripheral > NUM_PERIPHERALS) - peripheral = -EINVAL; - break; - } - } else { - /* Account for Apps data as well */ - peripheral = GET_BUF_PERIPHERAL(ctxt); - if (peripheral > NUM_PERIPHERALS) - peripheral = -EINVAL; - } - - return peripheral; -} - int diag_md_write(int id, unsigned char *buf, int len, int ctx) { int i; diff --git a/drivers/char/diag/diag_mux.c b/drivers/char/diag/diag_mux.c index d6f6ea7af8ea..8cc803eef552 100644 --- a/drivers/char/diag/diag_mux.c +++ b/drivers/char/diag/diag_mux.c @@ -153,12 +153,15 @@ int diag_mux_write(int proc, unsigned char *buf, int len, int ctx) upd = PERIPHERAL_CDSP; break; case UPD_WLAN: - if (!driver->num_pd_session) + if (!driver->pd_logging_mode[0]) upd = PERIPHERAL_MODEM; break; case UPD_AUDIO: + if (!driver->pd_logging_mode[1]) + upd = PERIPHERAL_LPASS; + break; case UPD_SENSORS: - if (!driver->num_pd_session) + if (!driver->pd_logging_mode[2]) upd = PERIPHERAL_LPASS; break; default: diff --git a/drivers/char/diag/diagchar_core.c b/drivers/char/diag/diagchar_core.c index 5ae3e4defd0d..afaedc99a4e7 100644 --- a/drivers/char/diag/diagchar_core.c +++ b/drivers/char/diag/diagchar_core.c @@ -456,6 +456,7 @@ static void diag_close_logging_process(const int pid) { int i, j; int session_mask; + uint32_t p_mask; struct diag_md_session_t *session_info = NULL; struct diag_logging_mode_param_t params; @@ -475,6 +476,9 @@ static void diag_close_logging_process(const int pid) session_mask = session_info->peripheral_mask; diag_md_session_close(session_info); + p_mask = + diag_translate_kernel_to_user_mask(session_mask); + for (i = 0; i < NUM_MD_SESSIONS; i++) if (MD_PERIPHERAL_MASK(i) & session_mask) diag_mux_close_peripheral(DIAG_LOCAL_PROC, i); @@ -482,19 +486,17 @@ static void diag_close_logging_process(const int pid) params.req_mode = USB_MODE; params.mode_param = 0; params.pd_mask = 0; - params.peripheral_mask = - diag_translate_kernel_to_user_mask(session_mask); + params.peripheral_mask = p_mask; if (driver->num_pd_session > 0) { - for (i = UPD_WLAN; ((i < NUM_MD_SESSIONS) && - (session_mask & MD_PERIPHERAL_MASK(i))); - i++) { - j = i - UPD_WLAN; - driver->pd_session_clear[j] = 1; - driver->pd_logging_mode[j] = 0; - driver->num_pd_session -= 1; - params.pd_mask = - diag_translate_kernel_to_user_mask(session_mask); + for (i = UPD_WLAN; (i < NUM_MD_SESSIONS); i++) { + if (session_mask & MD_PERIPHERAL_MASK(i)) { + j = i - UPD_WLAN; + driver->pd_session_clear[j] = 1; + driver->pd_logging_mode[j] = 0; + driver->num_pd_session -= 1; + params.pd_mask = p_mask; + } } } diff --git a/drivers/char/diag/diagfwd_peripheral.c b/drivers/char/diag/diagfwd_peripheral.c index e209039bed5a..9ac1ad62ffe0 100644 --- a/drivers/char/diag/diagfwd_peripheral.c +++ b/drivers/char/diag/diagfwd_peripheral.c @@ -216,6 +216,45 @@ static int check_bufsize_for_encoding(struct diagfwd_buf_t *buf, uint32_t len) return buf->len; } +int diag_md_get_peripheral(int ctxt) +{ + int peripheral; + + if (driver->num_pd_session) { + peripheral = GET_PD_CTXT(ctxt); + switch (peripheral) { + case UPD_WLAN: + if (!driver->pd_logging_mode[0]) + peripheral = PERIPHERAL_MODEM; + break; + case UPD_AUDIO: + if (!driver->pd_logging_mode[1]) + peripheral = PERIPHERAL_LPASS; + break; + case UPD_SENSORS: + if (!driver->pd_logging_mode[2]) + peripheral = PERIPHERAL_LPASS; + break; + case DIAG_ID_MPSS: + case DIAG_ID_LPASS: + case DIAG_ID_CDSP: + default: + peripheral = + GET_BUF_PERIPHERAL(ctxt); + if (peripheral > NUM_PERIPHERALS) + peripheral = -EINVAL; + break; + } + } else { + /* Account for Apps data as well */ + peripheral = GET_BUF_PERIPHERAL(ctxt); + if (peripheral > NUM_PERIPHERALS) + peripheral = -EINVAL; + } + + return peripheral; +} + static void diagfwd_data_process_done(struct diagfwd_info *fwd_info, struct diagfwd_buf_t *buf, int len) { @@ -245,13 +284,15 @@ static void diagfwd_data_process_done(struct diagfwd_info *fwd_info, mutex_lock(&driver->hdlc_disable_mutex); mutex_lock(&fwd_info->data_mutex); - peripheral = GET_PD_CTXT(buf->ctxt); - if (peripheral == DIAG_ID_MPSS) - peripheral = PERIPHERAL_MODEM; - if (peripheral == DIAG_ID_LPASS) - peripheral = PERIPHERAL_LPASS; - if (peripheral == DIAG_ID_CDSP) - peripheral = PERIPHERAL_CDSP; + peripheral = diag_md_get_peripheral(buf->ctxt); + if (peripheral < 0) { + pr_err("diag:%s:%d invalid peripheral = %d\n", + __func__, __LINE__, peripheral); + mutex_unlock(&fwd_info->data_mutex); + mutex_unlock(&driver->hdlc_disable_mutex); + diag_ws_release(); + return; + } session_info = diag_md_session_get_peripheral(peripheral); diff --git a/drivers/char/diag/diagfwd_peripheral.h b/drivers/char/diag/diagfwd_peripheral.h index 037eeebdeb35..eda70dcfdcd9 100644 --- a/drivers/char/diag/diagfwd_peripheral.h +++ b/drivers/char/diag/diagfwd_peripheral.h @@ -105,6 +105,9 @@ void diagfwd_early_open(uint8_t peripheral); void diagfwd_late_open(struct diagfwd_info *fwd_info); void diagfwd_close(uint8_t peripheral, uint8_t type); + +int diag_md_get_peripheral(int ctxt); + int diagfwd_register(uint8_t transport, uint8_t peripheral, uint8_t type, void *ctxt, struct diag_peripheral_ops *ops, struct diagfwd_info **fwd_ctxt); diff --git a/drivers/char/rdbg.c b/drivers/char/rdbg.c index 0823ed78485e..8161d77ca194 100644 --- a/drivers/char/rdbg.c +++ b/drivers/char/rdbg.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2013-2016, The Linux Foundation. All rights reserved. + * Copyright (c) 2013-2017, The Linux Foundation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 and @@ -22,7 +22,7 @@ #include <linux/uaccess.h> #include <linux/interrupt.h> -#define SMP2P_NUM_PROCS 8 +#define SMP2P_NUM_PROCS 16 #define MAX_RETRIES 20 #define SM_VERSION 1 @@ -146,9 +146,17 @@ static struct processor_specific_info proc_info[SMP2P_NUM_PROCS] = { {"rdbg_adsp", SMEM_LC_DEBUGGER, 16*1024}, /*ADSP*/ {0}, /*SMP2P_RESERVED_PROC_1*/ {"rdbg_wcnss", 0, 0}, /*WCNSS*/ - {0}, /*SMP2P_RESERVED_PROC_2*/ - {0}, /*SMP2P_POWER_PROC*/ - {0} /*SMP2P_REMOTE_MOCK_PROC*/ + {"rdbg_cdsp", SMEM_LC_DEBUGGER, 16*1024}, /*CDSP*/ + {NULL}, /*SMP2P_POWER_PROC*/ + {NULL}, /*SMP2P_TZ_PROC*/ + {NULL}, /*EMPTY*/ + {NULL}, /*EMPTY*/ + {NULL}, /*EMPTY*/ + {NULL}, /*EMPTY*/ + {NULL}, /*EMPTY*/ + {NULL}, /*EMPTY*/ + {NULL}, /*EMPTY*/ + {NULL} /*SMP2P_REMOTE_MOCK_PROC*/ }; static int smq_blockmap_get(struct smq_block_map *block_map, diff --git a/drivers/char/virtio_console.c b/drivers/char/virtio_console.c index 31e8ae916ba0..be0b09a0fb44 100644 --- a/drivers/char/virtio_console.c +++ b/drivers/char/virtio_console.c @@ -1864,7 +1864,7 @@ static void config_work_handler(struct work_struct *work) { struct ports_device *portdev; - portdev = container_of(work, struct ports_device, control_work); + portdev = container_of(work, struct ports_device, config_work); if (!use_multiport(portdev)) { struct virtio_device *vdev; struct port *port; diff --git a/drivers/cpufreq/s3c2416-cpufreq.c b/drivers/cpufreq/s3c2416-cpufreq.c index d6d425773fa4..5b2db3c6568f 100644 --- a/drivers/cpufreq/s3c2416-cpufreq.c +++ b/drivers/cpufreq/s3c2416-cpufreq.c @@ -400,7 +400,6 @@ static int s3c2416_cpufreq_driver_init(struct cpufreq_policy *policy) rate = clk_get_rate(s3c_freq->hclk); if (rate < 133 * 1000 * 1000) { pr_err("cpufreq: HCLK not at 133MHz\n"); - clk_put(s3c_freq->hclk); ret = -EINVAL; goto err_armclk; } diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_cs.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_cs.c index 25a3e2485cc2..2bc17a907ecf 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_cs.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_cs.c @@ -124,6 +124,13 @@ int amdgpu_cs_get_ring(struct amdgpu_device *adev, u32 ip_type, } break; } + + if (!(*out_ring && (*out_ring)->adev)) { + DRM_ERROR("Ring %d is not initialized on IP %d\n", + ring, ip_type); + return -EINVAL; + } + return 0; } diff --git a/drivers/gpu/drm/ast/ast_drv.h b/drivers/gpu/drm/ast/ast_drv.h index b92139e9b9d8..b5c64edeb668 100644 --- a/drivers/gpu/drm/ast/ast_drv.h +++ b/drivers/gpu/drm/ast/ast_drv.h @@ -113,7 +113,11 @@ struct ast_private { struct ttm_bo_kmap_obj cache_kmap; int next_cursor; bool support_wide_screen; - bool DisableP2A; + enum { + ast_use_p2a, + ast_use_dt, + ast_use_defaults + } config_mode; enum ast_tx_chip tx_chip_type; u8 dp501_maxclk; diff --git a/drivers/gpu/drm/ast/ast_main.c b/drivers/gpu/drm/ast/ast_main.c index 6c021165ca67..498a94069e6b 100644 --- a/drivers/gpu/drm/ast/ast_main.c +++ b/drivers/gpu/drm/ast/ast_main.c @@ -62,13 +62,84 @@ uint8_t ast_get_index_reg_mask(struct ast_private *ast, return ret; } +static void ast_detect_config_mode(struct drm_device *dev, u32 *scu_rev) +{ + struct device_node *np = dev->pdev->dev.of_node; + struct ast_private *ast = dev->dev_private; + uint32_t data, jregd0, jregd1; + + /* Defaults */ + ast->config_mode = ast_use_defaults; + *scu_rev = 0xffffffff; + + /* Check if we have device-tree properties */ + if (np && !of_property_read_u32(np, "aspeed,scu-revision-id", + scu_rev)) { + /* We do, disable P2A access */ + ast->config_mode = ast_use_dt; + DRM_INFO("Using device-tree for configuration\n"); + return; + } + + /* Not all families have a P2A bridge */ + if (dev->pdev->device != PCI_CHIP_AST2000) + return; + + /* + * The BMC will set SCU 0x40 D[12] to 1 if the P2 bridge + * is disabled. We force using P2A if VGA only mode bit + * is set D[7] + */ + jregd0 = ast_get_index_reg_mask(ast, AST_IO_CRTC_PORT, 0xd0, 0xff); + jregd1 = ast_get_index_reg_mask(ast, AST_IO_CRTC_PORT, 0xd1, 0xff); + if (!(jregd0 & 0x80) || !(jregd1 & 0x10)) { + /* Double check it's actually working */ + data = ast_read32(ast, 0xf004); + if (data != 0xFFFFFFFF) { + /* P2A works, grab silicon revision */ + ast->config_mode = ast_use_p2a; + + DRM_INFO("Using P2A bridge for configuration\n"); + + /* Read SCU7c (silicon revision register) */ + ast_write32(ast, 0xf004, 0x1e6e0000); + ast_write32(ast, 0xf000, 0x1); + *scu_rev = ast_read32(ast, 0x1207c); + return; + } + } + + /* We have a P2A bridge but it's disabled */ + DRM_INFO("P2A bridge disabled, using default configuration\n"); +} static int ast_detect_chip(struct drm_device *dev, bool *need_post) { struct ast_private *ast = dev->dev_private; - uint32_t data, jreg; + uint32_t jreg, scu_rev; + + /* + * If VGA isn't enabled, we need to enable now or subsequent + * access to the scratch registers will fail. We also inform + * our caller that it needs to POST the chip + * (Assumption: VGA not enabled -> need to POST) + */ + if (!ast_is_vga_enabled(dev)) { + ast_enable_vga(dev); + DRM_INFO("VGA not enabled on entry, requesting chip POST\n"); + *need_post = true; + } else + *need_post = false; + + + /* Enable extended register access */ + ast_enable_mmio(dev); ast_open_key(ast); + /* Find out whether P2A works or whether to use device-tree */ + ast_detect_config_mode(dev, &scu_rev); + + /* Identify chipset */ if (dev->pdev->device == PCI_CHIP_AST1180) { ast->chip = AST1100; DRM_INFO("AST 1180 detected\n"); @@ -80,12 +151,7 @@ static int ast_detect_chip(struct drm_device *dev, bool *need_post) ast->chip = AST2300; DRM_INFO("AST 2300 detected\n"); } else if (dev->pdev->revision >= 0x10) { - uint32_t data; - ast_write32(ast, 0xf004, 0x1e6e0000); - ast_write32(ast, 0xf000, 0x1); - - data = ast_read32(ast, 0x1207c); - switch (data & 0x0300) { + switch (scu_rev & 0x0300) { case 0x0200: ast->chip = AST1100; DRM_INFO("AST 1100 detected\n"); @@ -110,26 +176,6 @@ static int ast_detect_chip(struct drm_device *dev, bool *need_post) } } - /* - * If VGA isn't enabled, we need to enable now or subsequent - * access to the scratch registers will fail. We also inform - * our caller that it needs to POST the chip - * (Assumption: VGA not enabled -> need to POST) - */ - if (!ast_is_vga_enabled(dev)) { - ast_enable_vga(dev); - ast_enable_mmio(dev); - DRM_INFO("VGA not enabled on entry, requesting chip POST\n"); - *need_post = true; - } else - *need_post = false; - - /* Check P2A Access */ - ast->DisableP2A = true; - data = ast_read32(ast, 0xf004); - if (data != 0xFFFFFFFF) - ast->DisableP2A = false; - /* Check if we support wide screen */ switch (ast->chip) { case AST1180: @@ -146,17 +192,12 @@ static int ast_detect_chip(struct drm_device *dev, bool *need_post) ast->support_wide_screen = true; else { ast->support_wide_screen = false; - if (ast->DisableP2A == false) { - /* Read SCU7c (silicon revision register) */ - ast_write32(ast, 0xf004, 0x1e6e0000); - ast_write32(ast, 0xf000, 0x1); - data = ast_read32(ast, 0x1207c); - data &= 0x300; - if (ast->chip == AST2300 && data == 0x0) /* ast1300 */ - ast->support_wide_screen = true; - if (ast->chip == AST2400 && data == 0x100) /* ast1400 */ - ast->support_wide_screen = true; - } + if (ast->chip == AST2300 && + (scu_rev & 0x300) == 0x0) /* ast1300 */ + ast->support_wide_screen = true; + if (ast->chip == AST2400 && + (scu_rev & 0x300) == 0x100) /* ast1400 */ + ast->support_wide_screen = true; } break; } @@ -220,85 +261,102 @@ static int ast_detect_chip(struct drm_device *dev, bool *need_post) static int ast_get_dram_info(struct drm_device *dev) { + struct device_node *np = dev->pdev->dev.of_node; struct ast_private *ast = dev->dev_private; - uint32_t data, data2; - uint32_t denum, num, div, ref_pll; + uint32_t mcr_cfg, mcr_scu_mpll, mcr_scu_strap; + uint32_t denum, num, div, ref_pll, dsel; - if (ast->DisableP2A) - { + switch (ast->config_mode) { + case ast_use_dt: + /* + * If some properties are missing, use reasonable + * defaults for AST2400 + */ + if (of_property_read_u32(np, "aspeed,mcr-configuration", + &mcr_cfg)) + mcr_cfg = 0x00000577; + if (of_property_read_u32(np, "aspeed,mcr-scu-mpll", + &mcr_scu_mpll)) + mcr_scu_mpll = 0x000050C0; + if (of_property_read_u32(np, "aspeed,mcr-scu-strap", + &mcr_scu_strap)) + mcr_scu_strap = 0; + break; + case ast_use_p2a: + ast_write32(ast, 0xf004, 0x1e6e0000); + ast_write32(ast, 0xf000, 0x1); + mcr_cfg = ast_read32(ast, 0x10004); + mcr_scu_mpll = ast_read32(ast, 0x10120); + mcr_scu_strap = ast_read32(ast, 0x10170); + break; + case ast_use_defaults: + default: ast->dram_bus_width = 16; ast->dram_type = AST_DRAM_1Gx16; ast->mclk = 396; + return 0; } - else - { - ast_write32(ast, 0xf004, 0x1e6e0000); - ast_write32(ast, 0xf000, 0x1); - data = ast_read32(ast, 0x10004); - - if (data & 0x40) - ast->dram_bus_width = 16; - else - ast->dram_bus_width = 32; - if (ast->chip == AST2300 || ast->chip == AST2400) { - switch (data & 0x03) { - case 0: - ast->dram_type = AST_DRAM_512Mx16; - break; - default: - case 1: - ast->dram_type = AST_DRAM_1Gx16; - break; - case 2: - ast->dram_type = AST_DRAM_2Gx16; - break; - case 3: - ast->dram_type = AST_DRAM_4Gx16; - break; - } - } else { - switch (data & 0x0c) { - case 0: - case 4: - ast->dram_type = AST_DRAM_512Mx16; - break; - case 8: - if (data & 0x40) - ast->dram_type = AST_DRAM_1Gx16; - else - ast->dram_type = AST_DRAM_512Mx32; - break; - case 0xc: - ast->dram_type = AST_DRAM_1Gx32; - break; - } - } + if (mcr_cfg & 0x40) + ast->dram_bus_width = 16; + else + ast->dram_bus_width = 32; - data = ast_read32(ast, 0x10120); - data2 = ast_read32(ast, 0x10170); - if (data2 & 0x2000) - ref_pll = 14318; - else - ref_pll = 12000; - - denum = data & 0x1f; - num = (data & 0x3fe0) >> 5; - data = (data & 0xc000) >> 14; - switch (data) { - case 3: - div = 0x4; + if (ast->chip == AST2300 || ast->chip == AST2400) { + switch (mcr_cfg & 0x03) { + case 0: + ast->dram_type = AST_DRAM_512Mx16; break; - case 2: + default: case 1: - div = 0x2; + ast->dram_type = AST_DRAM_1Gx16; break; - default: - div = 0x1; + case 2: + ast->dram_type = AST_DRAM_2Gx16; + break; + case 3: + ast->dram_type = AST_DRAM_4Gx16; + break; + } + } else { + switch (mcr_cfg & 0x0c) { + case 0: + case 4: + ast->dram_type = AST_DRAM_512Mx16; + break; + case 8: + if (mcr_cfg & 0x40) + ast->dram_type = AST_DRAM_1Gx16; + else + ast->dram_type = AST_DRAM_512Mx32; + break; + case 0xc: + ast->dram_type = AST_DRAM_1Gx32; break; } - ast->mclk = ref_pll * (num + 2) / (denum + 2) * (div * 1000); } + + if (mcr_scu_strap & 0x2000) + ref_pll = 14318; + else + ref_pll = 12000; + + denum = mcr_scu_mpll & 0x1f; + num = (mcr_scu_mpll & 0x3fe0) >> 5; + dsel = (mcr_scu_mpll & 0xc000) >> 14; + switch (dsel) { + case 3: + div = 0x4; + break; + case 2: + case 1: + div = 0x2; + break; + default: + div = 0x1; + break; + } + ast->mclk = ref_pll * (num + 2) / (denum + 2) * (div * 1000); return 0; } diff --git a/drivers/gpu/drm/ast/ast_post.c b/drivers/gpu/drm/ast/ast_post.c index 270e8fb2803f..c7c58becb25d 100644 --- a/drivers/gpu/drm/ast/ast_post.c +++ b/drivers/gpu/drm/ast/ast_post.c @@ -375,17 +375,14 @@ void ast_post_gpu(struct drm_device *dev) ast_enable_mmio(dev); ast_set_def_ext_reg(dev); - if (ast->DisableP2A == false) - { + if (ast->config_mode == ast_use_p2a) { if (ast->chip == AST2300 || ast->chip == AST2400) ast_init_dram_2300(dev); else ast_init_dram_reg(dev); ast_init_3rdtx(dev); - } - else - { + } else { if (ast->tx_chip_type != AST_TX_NONE) ast_set_index_reg_mask(ast, AST_IO_CRTC_PORT, 0xa3, 0xcf, 0x80); /* Enable DVO */ } diff --git a/drivers/gpu/drm/msm/hdmi-staging/sde_hdmi.c b/drivers/gpu/drm/msm/hdmi-staging/sde_hdmi.c index b30e894ebc4d..1b295949122b 100644 --- a/drivers/gpu/drm/msm/hdmi-staging/sde_hdmi.c +++ b/drivers/gpu/drm/msm/hdmi-staging/sde_hdmi.c @@ -556,13 +556,13 @@ static const struct file_operations sde_hdmi_hdcp_state_fops = { .read = _sde_hdmi_hdcp_state_read, }; -static u64 _sde_hdmi_clip_valid_pclk(struct drm_display_mode *mode, u64 pclk_in) +static u64 _sde_hdmi_clip_valid_pclk(struct hdmi *hdmi, u64 pclk_in) { u32 pclk_delta, pclk; u64 pclk_clip = pclk_in; /* as per standard, 0.5% of deviation is allowed */ - pclk = mode->clock * HDMI_KHZ_TO_HZ; + pclk = hdmi->pixclock; pclk_delta = pclk * 5 / 1000; if (pclk_in < (pclk - pclk_delta)) @@ -700,7 +700,6 @@ static void sde_hdmi_tx_hdcp_cb_work(struct work_struct *work) static int _sde_hdmi_update_pll_delta(struct sde_hdmi *display, s32 ppm) { struct hdmi *hdmi = display->ctrl.ctrl; - struct drm_display_mode *current_mode = &display->mode; u64 cur_pclk, dst_pclk; u64 clip_pclk; int rc = 0; @@ -725,7 +724,7 @@ static int _sde_hdmi_update_pll_delta(struct sde_hdmi *display, s32 ppm) dst_pclk = cur_pclk * (1000000000 + ppm); do_div(dst_pclk, 1000000000); - clip_pclk = _sde_hdmi_clip_valid_pclk(current_mode, dst_pclk); + clip_pclk = _sde_hdmi_clip_valid_pclk(hdmi, dst_pclk); /* update pclk */ if (clip_pclk != cur_pclk) { @@ -2126,9 +2125,13 @@ static int sde_hdmi_tx_check_capability(struct sde_hdmi *sde_hdmi) } } - SDE_DEBUG("%s: Features <HDMI:%s, HDCP:%s>\n", __func__, + if (sde_hdmi->hdmi_tx_major_version >= HDMI_TX_VERSION_4) + sde_hdmi->dc_feature_supported = true; + + SDE_DEBUG("%s: Features <HDMI:%s, HDCP:%s, Deep Color:%s>\n", __func__, hdmi_disabled ? "OFF" : "ON", - hdcp_disabled ? "OFF" : "ON"); + hdcp_disabled ? "OFF" : "ON", + sde_hdmi->dc_feature_supported ? "ON" : "OFF"); if (hdmi_disabled) { DEV_ERR("%s: HDMI disabled\n", __func__); diff --git a/drivers/gpu/drm/msm/hdmi-staging/sde_hdmi.h b/drivers/gpu/drm/msm/hdmi-staging/sde_hdmi.h index 6b9bcfec031b..743d34d05e57 100644 --- a/drivers/gpu/drm/msm/hdmi-staging/sde_hdmi.h +++ b/drivers/gpu/drm/msm/hdmi-staging/sde_hdmi.h @@ -33,6 +33,9 @@ #include "sde_hdmi_util.h" #include "sde_hdcp.h" +#ifndef MIN +#define MIN(x, y) (((x) < (y)) ? (x) : (y)) +#endif #ifdef HDMI_DEBUG_ENABLE #define SDE_HDMI_DEBUG(fmt, args...) SDE_ERROR(fmt, ##args) #else @@ -110,6 +113,8 @@ enum hdmi_tx_feature_type { * @client_notify_pending: If there is client notification pending. * @irq_domain: IRQ domain structure. * @pll_update_enable: if it's allowed to update HDMI PLL ppm. + * @dc_enable: If deep color is enabled. Only DC_30 so far. + * @dc_feature_supported: If deep color feature is supported. * @notifier: CEC notifider to convey physical address information. * @root: Debug fs root entry. */ @@ -161,6 +166,8 @@ struct sde_hdmi { struct irq_domain *irq_domain; struct cec_notifier *notifier; bool pll_update_enable; + bool dc_enable; + bool dc_feature_supported; struct delayed_work hdcp_cb_work; struct dss_io_data io[HDMI_TX_MAX_IO]; @@ -188,6 +195,8 @@ enum hdmi_tx_scdc_access_type { #define HDMI_KHZ_TO_HZ 1000 #define HDMI_MHZ_TO_HZ 1000000 +#define HDMI_YUV420_24BPP_PCLK_TMDS_CH_RATE_RATIO 2 +#define HDMI_RGB_24BPP_PCLK_TMDS_CH_RATE_RATIO 1 /* Maximum pixel clock rates for hdmi tx */ #define HDMI_DEFAULT_MAX_PCLK_RATE 148500 diff --git a/drivers/gpu/drm/msm/hdmi-staging/sde_hdmi_bridge.c b/drivers/gpu/drm/msm/hdmi-staging/sde_hdmi_bridge.c index 24d2320683e4..a4c3c2e7ce46 100644 --- a/drivers/gpu/drm/msm/hdmi-staging/sde_hdmi_bridge.c +++ b/drivers/gpu/drm/msm/hdmi-staging/sde_hdmi_bridge.c @@ -345,7 +345,9 @@ static int _sde_hdmi_bridge_setup_scrambler(struct hdmi *hdmi, return 0; } - if (mode->clock > HDMI_TX_SCRAMBLER_THRESHOLD_RATE_KHZ) { + /* use actual clock instead of mode clock */ + if (hdmi->pixclock > + HDMI_TX_SCRAMBLER_THRESHOLD_RATE_KHZ * HDMI_KHZ_TO_HZ) { scrambler_on = true; tmds_clock_ratio = 1; } else { @@ -402,6 +404,38 @@ static int _sde_hdmi_bridge_setup_scrambler(struct hdmi *hdmi, return rc; } +static void _sde_hdmi_bridge_setup_deep_color(struct hdmi *hdmi) +{ + struct drm_connector *connector = hdmi->connector; + struct sde_connector *c_conn = to_sde_connector(connector); + struct sde_hdmi *display = (struct sde_hdmi *)c_conn->display; + u32 hdmi_ctrl_reg, vbi_pkt_reg; + + SDE_DEBUG("Deep Color: %s\n", display->dc_enable ? "On" : "Off"); + + if (display->dc_enable) { + hdmi_ctrl_reg = hdmi_read(hdmi, REG_HDMI_CTRL); + + /* GC CD override */ + hdmi_ctrl_reg |= BIT(27); + + /* enable deep color for RGB888/YUV444/YUV420 30 bits */ + hdmi_ctrl_reg |= BIT(24); + hdmi_write(hdmi, REG_HDMI_CTRL, hdmi_ctrl_reg); + /* Enable GC_CONT and GC_SEND in General Control Packet + * (GCP) register so that deep color data is + * transmitted to the sink on every frame, allowing + * the sink to decode the data correctly. + * + * GC_CONT: 0x1 - Send GCP on every frame + * GC_SEND: 0x1 - Enable GCP Transmission + */ + vbi_pkt_reg = hdmi_read(hdmi, REG_HDMI_VBI_PKT_CTRL); + vbi_pkt_reg |= BIT(5) | BIT(4); + hdmi_write(hdmi, REG_HDMI_VBI_PKT_CTRL, vbi_pkt_reg); + } +} + static void _sde_hdmi_bridge_pre_enable(struct drm_bridge *bridge) { struct sde_hdmi_bridge *sde_hdmi_bridge = to_hdmi_bridge(bridge); @@ -543,6 +577,10 @@ static void _sde_hdmi_bridge_set_avi_infoframe(struct hdmi *hdmi, struct hdmi_avi_infoframe info; drm_hdmi_avi_infoframe_from_display_mode(&info, mode); + + if (mode->private_flags & MSM_MODE_FLAG_COLOR_FORMAT_YCBCR420) + info.colorspace = HDMI_COLORSPACE_YUV420; + hdmi_avi_infoframe_pack(&info, avi_iframe, sizeof(avi_iframe)); checksum = avi_iframe[HDMI_INFOFRAME_HEADER_SIZE - 1]; @@ -660,31 +698,77 @@ static inline void _sde_hdmi_save_mode(struct hdmi *hdmi, drm_mode_copy(&display->mode, mode); } +static u32 _sde_hdmi_choose_best_format(struct hdmi *hdmi, + struct drm_display_mode *mode) +{ + /* + * choose priority: + * 1. DC + RGB + * 2. DC + YUV + * 3. RGB + * 4. YUV + */ + int dc_format; + struct drm_connector *connector = hdmi->connector; + + dc_format = sde_hdmi_sink_dc_support(connector, mode); + if (dc_format & MSM_MODE_FLAG_RGB444_DC_ENABLE) + return (MSM_MODE_FLAG_COLOR_FORMAT_RGB444 + | MSM_MODE_FLAG_RGB444_DC_ENABLE); + else if (dc_format & MSM_MODE_FLAG_YUV420_DC_ENABLE) + return (MSM_MODE_FLAG_COLOR_FORMAT_YCBCR420 + | MSM_MODE_FLAG_YUV420_DC_ENABLE); + else if (mode->flags & DRM_MODE_FLAG_SUPPORTS_RGB) + return MSM_MODE_FLAG_COLOR_FORMAT_RGB444; + else if (mode->flags & DRM_MODE_FLAG_SUPPORTS_YUV) + return MSM_MODE_FLAG_COLOR_FORMAT_YCBCR420; + + SDE_ERROR("Can't get available best display format\n"); + + return MSM_MODE_FLAG_COLOR_FORMAT_RGB444; +} + static void _sde_hdmi_bridge_mode_set(struct drm_bridge *bridge, struct drm_display_mode *mode, struct drm_display_mode *adjusted_mode) { struct sde_hdmi_bridge *sde_hdmi_bridge = to_hdmi_bridge(bridge); struct hdmi *hdmi = sde_hdmi_bridge->hdmi; + struct drm_connector *connector = hdmi->connector; + struct sde_connector *c_conn = to_sde_connector(connector); + struct sde_hdmi *display = (struct sde_hdmi *)c_conn->display; int hstart, hend, vstart, vend; uint32_t frame_ctrl; + u32 div = 0; mode = adjusted_mode; - hdmi->pixclock = mode->clock * 1000; + display->dc_enable = mode->private_flags & + (MSM_MODE_FLAG_RGB444_DC_ENABLE | + MSM_MODE_FLAG_YUV420_DC_ENABLE); + /* compute pixclock as per color format and bit depth */ + hdmi->pixclock = sde_hdmi_calc_pixclk( + mode->clock * HDMI_KHZ_TO_HZ, + mode->private_flags, + display->dc_enable); + SDE_DEBUG("Actual PCLK: %lu, Mode PCLK: %d\n", + hdmi->pixclock, mode->clock); + + if (mode->private_flags & MSM_MODE_FLAG_COLOR_FORMAT_YCBCR420) + div = 1; - hstart = mode->htotal - mode->hsync_start; - hend = mode->htotal - mode->hsync_start + mode->hdisplay; + hstart = (mode->htotal - mode->hsync_start) >> div; + hend = (mode->htotal - mode->hsync_start + mode->hdisplay) >> div; vstart = mode->vtotal - mode->vsync_start - 1; vend = mode->vtotal - mode->vsync_start + mode->vdisplay - 1; - DRM_DEBUG( + SDE_DEBUG( "htotal=%d, vtotal=%d, hstart=%d, hend=%d, vstart=%d, vend=%d", mode->htotal, mode->vtotal, hstart, hend, vstart, vend); hdmi_write(hdmi, REG_HDMI_TOTAL, - SDE_HDMI_TOTAL_H_TOTAL(mode->htotal - 1) | + SDE_HDMI_TOTAL_H_TOTAL((mode->htotal >> div) - 1) | SDE_HDMI_TOTAL_V_TOTAL(mode->vtotal - 1)); hdmi_write(hdmi, REG_HDMI_ACTIVE_HSYNC, @@ -734,6 +818,22 @@ static void _sde_hdmi_bridge_mode_set(struct drm_bridge *bridge, _sde_hdmi_save_mode(hdmi, mode); _sde_hdmi_bridge_setup_scrambler(hdmi, mode); + _sde_hdmi_bridge_setup_deep_color(hdmi); +} + +static bool _sde_hdmi_bridge_mode_fixup(struct drm_bridge *bridge, + const struct drm_display_mode *mode, + struct drm_display_mode *adjusted_mode) +{ + struct sde_hdmi_bridge *sde_hdmi_bridge = to_hdmi_bridge(bridge); + struct hdmi *hdmi = sde_hdmi_bridge->hdmi; + + adjusted_mode->private_flags |= + _sde_hdmi_choose_best_format(hdmi, adjusted_mode); + SDE_DEBUG("Adjusted mode private flags: 0x%x\n", + adjusted_mode->private_flags); + + return true; } static const struct drm_bridge_funcs _sde_hdmi_bridge_funcs = { @@ -742,6 +842,7 @@ static const struct drm_bridge_funcs _sde_hdmi_bridge_funcs = { .disable = _sde_hdmi_bridge_disable, .post_disable = _sde_hdmi_bridge_post_disable, .mode_set = _sde_hdmi_bridge_mode_set, + .mode_fixup = _sde_hdmi_bridge_mode_fixup, }; diff --git a/drivers/gpu/drm/msm/hdmi-staging/sde_hdmi_util.c b/drivers/gpu/drm/msm/hdmi-staging/sde_hdmi_util.c index a7887d2c84b0..ba47b7702efd 100644 --- a/drivers/gpu/drm/msm/hdmi-staging/sde_hdmi_util.c +++ b/drivers/gpu/drm/msm/hdmi-staging/sde_hdmi_util.c @@ -825,3 +825,76 @@ int sde_hdmi_hdcp2p2_read_rxstatus(void *hdmi_display) } return rc; } + +unsigned long sde_hdmi_calc_pixclk(unsigned long pixel_freq, + u32 out_format, bool dc_enable) +{ + u32 rate_ratio = HDMI_RGB_24BPP_PCLK_TMDS_CH_RATE_RATIO; + + if (out_format & MSM_MODE_FLAG_COLOR_FORMAT_YCBCR420) + rate_ratio = HDMI_YUV420_24BPP_PCLK_TMDS_CH_RATE_RATIO; + + pixel_freq /= rate_ratio; + + if (dc_enable) + pixel_freq += pixel_freq >> 2; + + return pixel_freq; + +} + +bool sde_hdmi_validate_pixclk(struct drm_connector *connector, + unsigned long pclk) +{ + struct sde_connector *c_conn = to_sde_connector(connector); + struct sde_hdmi *display = (struct sde_hdmi *)c_conn->display; + unsigned long max_pclk = display->max_pclk_khz * HDMI_KHZ_TO_HZ; + + if (connector->max_tmds_char) + max_pclk = MIN(max_pclk, + connector->max_tmds_char * HDMI_MHZ_TO_HZ); + else if (connector->max_tmds_clock) + max_pclk = MIN(max_pclk, + connector->max_tmds_clock * HDMI_MHZ_TO_HZ); + + SDE_DEBUG("MAX PCLK = %ld, PCLK = %ld\n", max_pclk, pclk); + + return pclk < max_pclk; +} + +static bool sde_hdmi_check_dc_clock(struct drm_connector *connector, + struct drm_display_mode *mode, u32 format) +{ + struct sde_connector *c_conn = to_sde_connector(connector); + struct sde_hdmi *display = (struct sde_hdmi *)c_conn->display; + + u32 tmds_clk_with_dc = sde_hdmi_calc_pixclk( + mode->clock * HDMI_KHZ_TO_HZ, + format, + true); + + return (display->dc_feature_supported && + sde_hdmi_validate_pixclk(connector, tmds_clk_with_dc)); +} + +int sde_hdmi_sink_dc_support(struct drm_connector *connector, + struct drm_display_mode *mode) +{ + int dc_format = 0; + + if ((mode->flags & DRM_MODE_FLAG_SUPPORTS_YUV) && + (connector->display_info.edid_hdmi_dc_modes + & DRM_EDID_YCBCR420_DC_30)) + if (sde_hdmi_check_dc_clock(connector, mode, + MSM_MODE_FLAG_COLOR_FORMAT_YCBCR420)) + dc_format |= MSM_MODE_FLAG_YUV420_DC_ENABLE; + + if ((mode->flags & DRM_MODE_FLAG_SUPPORTS_RGB) && + (connector->display_info.edid_hdmi_dc_modes + & DRM_EDID_HDMI_DC_30)) + if (sde_hdmi_check_dc_clock(connector, mode, + MSM_MODE_FLAG_COLOR_FORMAT_RGB444)) + dc_format |= MSM_MODE_FLAG_RGB444_DC_ENABLE; + + return dc_format; +} diff --git a/drivers/gpu/drm/msm/hdmi-staging/sde_hdmi_util.h b/drivers/gpu/drm/msm/hdmi-staging/sde_hdmi_util.h index 8b69dd31f637..10effed54a14 100644 --- a/drivers/gpu/drm/msm/hdmi-staging/sde_hdmi_util.h +++ b/drivers/gpu/drm/msm/hdmi-staging/sde_hdmi_util.h @@ -164,4 +164,10 @@ int sde_hdmi_hdcp2p2_read_rxstatus(void *hdmi_display); void sde_hdmi_ddc_config(void *hdmi_display); int sde_hdmi_ddc_hdcp2p2_isr(void *hdmi_display); void sde_hdmi_dump_regs(void *hdmi_display); +unsigned long sde_hdmi_calc_pixclk(unsigned long pixel_freq, + u32 out_format, bool dc_enable); +bool sde_hdmi_validate_pixclk(struct drm_connector *connector, + unsigned long pclk); +int sde_hdmi_sink_dc_support(struct drm_connector *connector, + struct drm_display_mode *mode); #endif /* _SDE_HDMI_UTIL_H_ */ diff --git a/drivers/gpu/drm/msm/msm_kms.h b/drivers/gpu/drm/msm/msm_kms.h index 2ab50919f514..ed0ba928f170 100644 --- a/drivers/gpu/drm/msm/msm_kms.h +++ b/drivers/gpu/drm/msm/msm_kms.h @@ -34,6 +34,24 @@ #define MSM_MODE_FLAG_SEAMLESS_DYNAMIC_FPS (1<<0) /* Transition to new mode requires a wait-for-vblank before the modeset */ #define MSM_MODE_FLAG_VBLANK_PRE_MODESET (1<<1) +/* + * We need setting some flags in bridge, and using them in encoder. Add them in + * private_flags would be better for use. DRM_MODE_FLAG_SUPPORTS_RGB/YUV are + * flags that indicating the SINK supported color formats read from EDID. While, + * these flags defined here indicate the best color/bit depth foramt we choosed + * that would be better for display. For example the best mode display like: + * RGB+RGB_DC,YUV+YUV_DC, RGB,YUV. And we could not set RGB and YUV format at + * the same time. And also RGB_DC only set when RGB format is set,the same for + * YUV_DC. + */ +/* Enable RGB444 30 bit deep color */ +#define MSM_MODE_FLAG_RGB444_DC_ENABLE (1<<2) +/* Enable YUV420 30 bit deep color */ +#define MSM_MODE_FLAG_YUV420_DC_ENABLE (1<<3) +/* Choose RGB444 format to display */ +#define MSM_MODE_FLAG_COLOR_FORMAT_RGB444 (1<<4) +/* Choose YUV420 format to display */ +#define MSM_MODE_FLAG_COLOR_FORMAT_YCBCR420 (1<<5) /* As there are different display controller blocks depending on the * snapdragon version, the kms support is split out and the appropriate diff --git a/drivers/gpu/drm/msm/sde/sde_encoder.c b/drivers/gpu/drm/msm/sde/sde_encoder.c index 29444a83cf02..97c9f8baea6d 100644 --- a/drivers/gpu/drm/msm/sde/sde_encoder.c +++ b/drivers/gpu/drm/msm/sde/sde_encoder.c @@ -55,6 +55,33 @@ #define MAX_CHANNELS_PER_ENC 2 +/* rgb to yuv color space conversion matrix */ +static struct sde_csc_cfg sde_csc_10bit_convert[SDE_MAX_CSC] = { + [SDE_CSC_RGB2YUV_601L] = { + { + TO_S15D16(0x0083), TO_S15D16(0x0102), TO_S15D16(0x0032), + TO_S15D16(0xffb4), TO_S15D16(0xff6b), TO_S15D16(0x00e1), + TO_S15D16(0x00e1), TO_S15D16(0xff44), TO_S15D16(0xffdb), + }, + { 0x0, 0x0, 0x0,}, + { 0x0040, 0x0200, 0x0200,}, + { 0x0, 0x3ff, 0x0, 0x3ff, 0x0, 0x3ff,}, + { 0x0040, 0x03ac, 0x0040, 0x03c0, 0x0040, 0x03c0,}, + }, + + [SDE_CSC_RGB2YUV_601FR] = { + { + TO_S15D16(0x0099), TO_S15D16(0x012d), TO_S15D16(0x003a), + TO_S15D16(0xffaa), TO_S15D16(0xff56), TO_S15D16(0x0100), + TO_S15D16(0x0100), TO_S15D16(0xff2a), TO_S15D16(0xffd6), + }, + { 0x0, 0x0, 0x0,}, + { 0x0000, 0x0200, 0x0200,}, + { 0x0, 0x3ff, 0x0, 0x3ff, 0x0, 0x3ff,}, + { 0x0, 0x3ff, 0x0, 0x3ff, 0x0, 0x3ff,}, + }, +}; + /** * struct sde_encoder_virt - virtual encoder. Container of one or more physical * encoders. Virtual encoder manages one "logical" display. Physical @@ -1374,3 +1401,108 @@ enum sde_intf_mode sde_encoder_get_intf_mode(struct drm_encoder *encoder) return INTF_MODE_NONE; } + +/** + * sde_encoder_phys_setup_cdm - setup chroma down block + * @phys_enc: Pointer to physical encoder + * @output_type: HDMI/WB + * @format: Output format + * @roi: Output size + */ +void sde_encoder_phys_setup_cdm(struct sde_encoder_phys *phys_enc, + const struct sde_format *format, u32 output_type, + struct sde_rect *roi) +{ + struct drm_encoder *encoder = phys_enc->parent; + struct sde_encoder_virt *sde_enc = NULL; + struct sde_hw_cdm *hw_cdm = phys_enc->hw_cdm; + struct sde_hw_cdm_cfg *cdm_cfg = &phys_enc->cdm_cfg; + int ret; + u32 csc_type = 0; + + if (!encoder) { + SDE_ERROR("invalid encoder\n"); + return; + } + sde_enc = to_sde_encoder_virt(encoder); + + if (!SDE_FORMAT_IS_YUV(format)) { + SDE_DEBUG_ENC(sde_enc, "[cdm_disable fmt:%x]\n", + format->base.pixel_format); + + if (hw_cdm && hw_cdm->ops.disable) + hw_cdm->ops.disable(hw_cdm); + + return; + } + + memset(cdm_cfg, 0, sizeof(struct sde_hw_cdm_cfg)); + + cdm_cfg->output_width = roi->w; + cdm_cfg->output_height = roi->h; + cdm_cfg->output_fmt = format; + cdm_cfg->output_type = output_type; + cdm_cfg->output_bit_depth = SDE_FORMAT_IS_DX(format) ? + CDM_CDWN_OUTPUT_10BIT : CDM_CDWN_OUTPUT_8BIT; + + /* enable 10 bit logic */ + switch (cdm_cfg->output_fmt->chroma_sample) { + case SDE_CHROMA_RGB: + cdm_cfg->h_cdwn_type = CDM_CDWN_DISABLE; + cdm_cfg->v_cdwn_type = CDM_CDWN_DISABLE; + break; + case SDE_CHROMA_H2V1: + cdm_cfg->h_cdwn_type = CDM_CDWN_COSITE; + cdm_cfg->v_cdwn_type = CDM_CDWN_DISABLE; + break; + case SDE_CHROMA_420: + cdm_cfg->h_cdwn_type = CDM_CDWN_COSITE; + cdm_cfg->v_cdwn_type = CDM_CDWN_OFFSITE; + break; + case SDE_CHROMA_H1V2: + default: + SDE_ERROR("unsupported chroma sampling type\n"); + cdm_cfg->h_cdwn_type = CDM_CDWN_DISABLE; + cdm_cfg->v_cdwn_type = CDM_CDWN_DISABLE; + break; + } + + SDE_DEBUG_ENC(sde_enc, "[cdm_enable:%d,%d,%X,%d,%d,%d,%d]\n", + cdm_cfg->output_width, + cdm_cfg->output_height, + cdm_cfg->output_fmt->base.pixel_format, + cdm_cfg->output_type, + cdm_cfg->output_bit_depth, + cdm_cfg->h_cdwn_type, + cdm_cfg->v_cdwn_type); + + if (output_type == CDM_CDWN_OUTPUT_HDMI) + csc_type = SDE_CSC_RGB2YUV_601FR; + else if (output_type == CDM_CDWN_OUTPUT_WB) + csc_type = SDE_CSC_RGB2YUV_601L; + + if (hw_cdm && hw_cdm->ops.setup_csc_data) { + ret = hw_cdm->ops.setup_csc_data(hw_cdm, + &sde_csc_10bit_convert[csc_type]); + if (ret < 0) { + SDE_ERROR("failed to setup CSC %d\n", ret); + return; + } + } + + if (hw_cdm && hw_cdm->ops.setup_cdwn) { + ret = hw_cdm->ops.setup_cdwn(hw_cdm, cdm_cfg); + if (ret < 0) { + SDE_ERROR("failed to setup CDM %d\n", ret); + return; + } + } + + if (hw_cdm && hw_cdm->ops.enable) { + ret = hw_cdm->ops.enable(hw_cdm, cdm_cfg); + if (ret < 0) { + SDE_ERROR("failed to enable CDM %d\n", ret); + return; + } + } +} diff --git a/drivers/gpu/drm/msm/sde/sde_encoder_phys.h b/drivers/gpu/drm/msm/sde/sde_encoder_phys.h index 2205dd98a927..20f125155de3 100644 --- a/drivers/gpu/drm/msm/sde/sde_encoder_phys.h +++ b/drivers/gpu/drm/msm/sde/sde_encoder_phys.h @@ -349,8 +349,8 @@ struct sde_encoder_phys *sde_encoder_phys_wb_init( #endif void sde_encoder_phys_setup_cdm(struct sde_encoder_phys *phys_enc, - struct drm_framebuffer *fb, const struct sde_format *format, - struct sde_rect *wb_roi); + const struct sde_format *format, u32 output_type, + struct sde_rect *roi); /** * sde_encoder_helper_trigger_start - control start helper function diff --git a/drivers/gpu/drm/msm/sde/sde_encoder_phys_vid.c b/drivers/gpu/drm/msm/sde/sde_encoder_phys_vid.c index 0b6ee302e231..78a8b732b0de 100644 --- a/drivers/gpu/drm/msm/sde/sde_encoder_phys_vid.c +++ b/drivers/gpu/drm/msm/sde/sde_encoder_phys_vid.c @@ -1,4 +1,4 @@ -/* Copyright (c) 2015-2016, The Linux Foundation. All rights reserved. +/* Copyright (c) 2015-2017, The Linux Foundation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 and @@ -242,17 +242,20 @@ static void sde_encoder_phys_vid_setup_timing_engine( SDE_DEBUG_VIDENC(vid_enc, "enabling mode:\n"); drm_mode_debug_printmodeline(&mode); - if (phys_enc->split_role != ENC_ROLE_SOLO) { + if (phys_enc->split_role != ENC_ROLE_SOLO || + (mode.private_flags & MSM_MODE_FLAG_COLOR_FORMAT_YCBCR420)) { mode.hdisplay >>= 1; mode.htotal >>= 1; mode.hsync_start >>= 1; mode.hsync_end >>= 1; + mode.hskew >>= 1; SDE_DEBUG_VIDENC(vid_enc, - "split_role %d, halve horizontal %d %d %d %d\n", + "split_role %d, halve horizontal %d %d %d %d %d\n", phys_enc->split_role, mode.hdisplay, mode.htotal, - mode.hsync_start, mode.hsync_end); + mode.hsync_start, mode.hsync_end, + mode.hskew); } drm_mode_to_intf_timing_params(vid_enc, &mode, &timing_params); @@ -407,6 +410,9 @@ static void sde_encoder_phys_vid_mode_set( return; } + phys_enc->hw_ctl = NULL; + phys_enc->hw_cdm = NULL; + rm = &phys_enc->sde_kms->rm; vid_enc = to_sde_encoder_phys_vid(phys_enc); phys_enc->cached_mode = *adj_mode; @@ -427,6 +433,20 @@ static void sde_encoder_phys_vid_mode_set( phys_enc->hw_ctl = NULL; return; } + + /* CDM is optional */ + sde_rm_init_hw_iter(&iter, phys_enc->parent->base.id, SDE_HW_BLK_CDM); + for (i = 0; i <= instance; i++) { + sde_rm_get_hw(rm, &iter); + if (i == instance) + phys_enc->hw_cdm = (struct sde_hw_cdm *) iter.hw; + } + + if (IS_ERR(phys_enc->hw_cdm)) { + SDE_ERROR("CDM required but not allocated: %ld\n", + PTR_ERR(phys_enc->hw_cdm)); + phys_enc->hw_cdm = NULL; + } } static int sde_encoder_phys_vid_control_vblank_irq( @@ -477,6 +497,9 @@ static void sde_encoder_phys_vid_enable(struct sde_encoder_phys *phys_enc) struct sde_encoder_phys_vid *vid_enc; struct sde_hw_intf *intf; struct sde_hw_ctl *ctl; + struct sde_hw_cdm *hw_cdm = NULL; + struct drm_display_mode mode; + const struct sde_format *fmt = NULL; u32 flush_mask = 0; int ret; @@ -485,7 +508,9 @@ static void sde_encoder_phys_vid_enable(struct sde_encoder_phys *phys_enc) SDE_ERROR("invalid encoder/device\n"); return; } + hw_cdm = phys_enc->hw_cdm; priv = phys_enc->parent->dev->dev_private; + mode = phys_enc->cached_mode; vid_enc = to_sde_encoder_phys_vid(phys_enc); intf = vid_enc->hw_intf; @@ -520,7 +545,21 @@ static void sde_encoder_phys_vid_enable(struct sde_encoder_phys *phys_enc) goto end; } + if (mode.private_flags & MSM_MODE_FLAG_COLOR_FORMAT_YCBCR420) + fmt = sde_get_sde_format(DRM_FORMAT_YUV420); + + if (fmt) { + struct sde_rect hdmi_roi; + + hdmi_roi.w = mode.hdisplay; + hdmi_roi.h = mode.vdisplay; + sde_encoder_phys_setup_cdm(phys_enc, fmt, + CDM_CDWN_OUTPUT_HDMI, &hdmi_roi); + } + ctl->ops.get_bitmask_intf(ctl, &flush_mask, intf->idx); + if (ctl->ops.get_bitmask_cdm && hw_cdm) + ctl->ops.get_bitmask_cdm(ctl, &flush_mask, hw_cdm->idx); ctl->ops.update_pending_flush(ctl, flush_mask); SDE_DEBUG_VIDENC(vid_enc, "update pending flush ctl %d flush_mask %x\n", @@ -569,6 +608,8 @@ static void sde_encoder_phys_vid_get_hw_resources( SDE_DEBUG_VIDENC(vid_enc, "\n"); hw_res->intfs[vid_enc->hw_intf->idx - INTF_0] = INTF_MODE_VIDEO; + hw_res->needs_cdm = true; + SDE_DEBUG_DRIVER("[vid] needs_cdm=%d\n", hw_res->needs_cdm); } static int sde_encoder_phys_vid_wait_for_vblank( @@ -713,6 +754,11 @@ static void sde_encoder_phys_vid_disable(struct sde_encoder_phys *phys_enc) SDE_ERROR_VIDENC(vid_enc, "invalid vblank refcount %d\n", atomic_read(&phys_enc->vblank_refcount)); + if (phys_enc->hw_cdm && phys_enc->hw_cdm->ops.disable) { + SDE_DEBUG_DRIVER("[cdm_disable]\n"); + phys_enc->hw_cdm->ops.disable(phys_enc->hw_cdm); + } + phys_enc->enable_state = SDE_ENC_DISABLED; } diff --git a/drivers/gpu/drm/msm/sde/sde_encoder_phys_wb.c b/drivers/gpu/drm/msm/sde/sde_encoder_phys_wb.c index a48962a2384b..65b16419fcec 100644 --- a/drivers/gpu/drm/msm/sde/sde_encoder_phys_wb.c +++ b/drivers/gpu/drm/msm/sde/sde_encoder_phys_wb.c @@ -28,24 +28,6 @@ #define WBID(wb_enc) ((wb_enc) ? wb_enc->wb_dev->wb_idx : -1) -#define TO_S15D16(_x_) ((_x_) << 7) - -/** - * sde_rgb2yuv_601l - rgb to yuv color space conversion matrix - * - */ -static struct sde_csc_cfg sde_encoder_phys_wb_rgb2yuv_601l = { - { - TO_S15D16(0x0083), TO_S15D16(0x0102), TO_S15D16(0x0032), - TO_S15D16(0x1fb5), TO_S15D16(0x1f6c), TO_S15D16(0x00e1), - TO_S15D16(0x00e1), TO_S15D16(0x1f45), TO_S15D16(0x1fdc) - }, - { 0x00, 0x00, 0x00 }, - { 0x0040, 0x0200, 0x0200 }, - { 0x000, 0x3ff, 0x000, 0x3ff, 0x000, 0x3ff }, - { 0x040, 0x3ac, 0x040, 0x3c0, 0x040, 0x3c0 }, -}; - /** * sde_encoder_phys_wb_is_master - report wb always as master encoder */ @@ -105,96 +87,6 @@ static void sde_encoder_phys_wb_set_traffic_shaper( } /** - * sde_encoder_phys_setup_cdm - setup chroma down block - * @phys_enc: Pointer to physical encoder - * @fb: Pointer to output framebuffer - * @format: Output format - */ -void sde_encoder_phys_setup_cdm(struct sde_encoder_phys *phys_enc, - struct drm_framebuffer *fb, const struct sde_format *format, - struct sde_rect *wb_roi) -{ - struct sde_hw_cdm *hw_cdm = phys_enc->hw_cdm; - struct sde_hw_cdm_cfg *cdm_cfg = &phys_enc->cdm_cfg; - int ret; - - if (!SDE_FORMAT_IS_YUV(format)) { - SDE_DEBUG("[cdm_disable fmt:%x]\n", - format->base.pixel_format); - - if (hw_cdm && hw_cdm->ops.disable) - hw_cdm->ops.disable(hw_cdm); - - return; - } - - memset(cdm_cfg, 0, sizeof(struct sde_hw_cdm_cfg)); - - cdm_cfg->output_width = wb_roi->w; - cdm_cfg->output_height = wb_roi->h; - cdm_cfg->output_fmt = format; - cdm_cfg->output_type = CDM_CDWN_OUTPUT_WB; - cdm_cfg->output_bit_depth = SDE_FORMAT_IS_DX(format) ? - CDM_CDWN_OUTPUT_10BIT : CDM_CDWN_OUTPUT_8BIT; - - /* enable 10 bit logic */ - switch (cdm_cfg->output_fmt->chroma_sample) { - case SDE_CHROMA_RGB: - cdm_cfg->h_cdwn_type = CDM_CDWN_DISABLE; - cdm_cfg->v_cdwn_type = CDM_CDWN_DISABLE; - break; - case SDE_CHROMA_H2V1: - cdm_cfg->h_cdwn_type = CDM_CDWN_COSITE; - cdm_cfg->v_cdwn_type = CDM_CDWN_DISABLE; - break; - case SDE_CHROMA_420: - cdm_cfg->h_cdwn_type = CDM_CDWN_COSITE; - cdm_cfg->v_cdwn_type = CDM_CDWN_OFFSITE; - break; - case SDE_CHROMA_H1V2: - default: - SDE_ERROR("unsupported chroma sampling type\n"); - cdm_cfg->h_cdwn_type = CDM_CDWN_DISABLE; - cdm_cfg->v_cdwn_type = CDM_CDWN_DISABLE; - break; - } - - SDE_DEBUG("[cdm_enable:%d,%d,%X,%d,%d,%d,%d]\n", - cdm_cfg->output_width, - cdm_cfg->output_height, - cdm_cfg->output_fmt->base.pixel_format, - cdm_cfg->output_type, - cdm_cfg->output_bit_depth, - cdm_cfg->h_cdwn_type, - cdm_cfg->v_cdwn_type); - - if (hw_cdm && hw_cdm->ops.setup_csc_data) { - ret = hw_cdm->ops.setup_csc_data(hw_cdm, - &sde_encoder_phys_wb_rgb2yuv_601l); - if (ret < 0) { - SDE_ERROR("failed to setup CSC %d\n", ret); - return; - } - } - - if (hw_cdm && hw_cdm->ops.setup_cdwn) { - ret = hw_cdm->ops.setup_cdwn(hw_cdm, cdm_cfg); - if (ret < 0) { - SDE_ERROR("failed to setup CDM %d\n", ret); - return; - } - } - - if (hw_cdm && hw_cdm->ops.enable) { - ret = hw_cdm->ops.enable(hw_cdm, cdm_cfg); - if (ret < 0) { - SDE_ERROR("failed to enable CDM %d\n", ret); - return; - } - } -} - -/** * sde_encoder_phys_wb_setup_fb - setup output framebuffer * @phys_enc: Pointer to physical encoder * @fb: Pointer to output framebuffer @@ -520,7 +412,8 @@ static void sde_encoder_phys_wb_setup( sde_encoder_phys_wb_set_traffic_shaper(phys_enc); - sde_encoder_phys_setup_cdm(phys_enc, fb, wb_enc->wb_fmt, wb_roi); + sde_encoder_phys_setup_cdm(phys_enc, wb_enc->wb_fmt, + CDM_CDWN_OUTPUT_WB, wb_roi); sde_encoder_phys_wb_setup_fb(phys_enc, fb, wb_roi); diff --git a/drivers/gpu/drm/msm/sde/sde_hw_cdm.c b/drivers/gpu/drm/msm/sde/sde_hw_cdm.c index 188649d946d6..9ec81c227e60 100644 --- a/drivers/gpu/drm/msm/sde/sde_hw_cdm.c +++ b/drivers/gpu/drm/msm/sde/sde_hw_cdm.c @@ -227,7 +227,7 @@ int sde_hw_cdm_enable(struct sde_hw_cdm *ctx, return -EINVAL; if (cdm->output_type == CDM_CDWN_OUTPUT_HDMI) { - if (fmt->chroma_sample != SDE_CHROMA_H1V2) + if (fmt->chroma_sample == SDE_CHROMA_H1V2) return -EINVAL; /*unsupported format */ opmode = BIT(0); opmode |= (fmt->chroma_sample << 1); diff --git a/drivers/gpu/drm/msm/sde/sde_hw_mdss.h b/drivers/gpu/drm/msm/sde/sde_hw_mdss.h index 2592fe26cb38..1edeff6a7aec 100644 --- a/drivers/gpu/drm/msm/sde/sde_hw_mdss.h +++ b/drivers/gpu/drm/msm/sde/sde_hw_mdss.h @@ -63,6 +63,8 @@ enum sde_format_flags { (((X)->fetch_mode == SDE_FETCH_UBWC) && \ test_bit(SDE_FORMAT_FLAG_COMPRESSED_BIT, (X)->flag)) +#define TO_S15D16(_x_) ((_x_) << 7) + #define SDE_BLEND_FG_ALPHA_FG_CONST (0 << 0) #define SDE_BLEND_FG_ALPHA_BG_CONST (1 << 0) #define SDE_BLEND_FG_ALPHA_FG_PIXEL (2 << 0) @@ -339,6 +341,12 @@ enum sde_3d_blend_mode { BLEND_3D_MAX }; +enum sde_csc_type { + SDE_CSC_RGB2YUV_601L, + SDE_CSC_RGB2YUV_601FR, + SDE_MAX_CSC +}; + /** struct sde_format - defines the format configuration which * allows SDE HW to correctly fetch and decode the format * @base: base msm_format struture containing fourcc code diff --git a/drivers/gpu/drm/msm/sde_edid_parser.c b/drivers/gpu/drm/msm/sde_edid_parser.c index ca9229ede251..68246253bb70 100644 --- a/drivers/gpu/drm/msm/sde_edid_parser.c +++ b/drivers/gpu/drm/msm/sde_edid_parser.c @@ -229,10 +229,17 @@ u32 video_format) { u8 cea_mode = 0; struct drm_display_mode *mode; + u32 mode_fmt_flags = 0; /* Need to add Y420 support flag to the modes */ list_for_each_entry(mode, &connector->probed_modes, head) { + /* Cache the format flags before clearing */ + mode_fmt_flags = mode->flags; + /* Clear the RGB/YUV format flags before calling upstream API */ + mode->flags &= ~SDE_DRM_MODE_FLAG_FMT_MASK; cea_mode = drm_match_cea_mode(mode); + /* Restore the format flags */ + mode->flags = mode_fmt_flags; if ((cea_mode != 0) && (cea_mode == video_format)) { SDE_EDID_DEBUG("%s found match for %d ", __func__, video_format); @@ -246,7 +253,7 @@ struct drm_connector *connector, struct sde_edid_ctrl *edid_ctrl, const u8 *db) { u32 offset = 0; - u8 len = 0; + u8 cmdb_len = 0; u8 svd_len = 0; const u8 *svd = NULL; u32 i = 0, j = 0; @@ -262,10 +269,8 @@ const u8 *db) return; } SDE_EDID_DEBUG("%s +\n", __func__); - len = db[0] & 0x1f; + cmdb_len = db[0] & 0x1f; - if (len < 7) - return; /* Byte 3 to L+1 contain SVDs */ offset += 2; @@ -273,20 +278,24 @@ const u8 *db) if (svd) { /*moving to the next byte as vic info begins there*/ - ++svd; svd_len = svd[0] & 0x1f; + ++svd; } for (i = 0; i < svd_len; i++, j++) { - video_format = *svd & 0x7F; - if (db[offset] & (1 << j)) + video_format = *(svd + i) & 0x7F; + if (cmdb_len == 1) { + /* If cmdb_len is 1, it means all SVDs support YUV */ + sde_edid_set_y420_support(connector, video_format); + } else if (db[offset] & (1 << j)) { sde_edid_set_y420_support(connector, video_format); - if (j & 0x80) { - j = j/8; - offset++; - if (offset >= len) - break; + if (j & 0x80) { + j = j/8; + offset++; + if (offset >= cmdb_len) + break; + } } } diff --git a/drivers/gpu/drm/msm/sde_edid_parser.h b/drivers/gpu/drm/msm/sde_edid_parser.h index 1143dc2c7bec..59e3dceca33c 100644 --- a/drivers/gpu/drm/msm/sde_edid_parser.h +++ b/drivers/gpu/drm/msm/sde_edid_parser.h @@ -33,6 +33,8 @@ #define SDE_CEA_EXT 0x02 #define SDE_EXTENDED_TAG 0x07 +#define SDE_DRM_MODE_FLAG_FMT_MASK (0x3 << 20) + enum extended_data_block_types { VIDEO_CAPABILITY_DATA_BLOCK = 0x0, VENDOR_SPECIFIC_VIDEO_DATA_BLOCK = 0x01, diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_cmdbuf_res.c b/drivers/gpu/drm/vmwgfx/vmwgfx_cmdbuf_res.c index 13db8a2851ed..1f013d45c9e9 100644 --- a/drivers/gpu/drm/vmwgfx/vmwgfx_cmdbuf_res.c +++ b/drivers/gpu/drm/vmwgfx/vmwgfx_cmdbuf_res.c @@ -321,6 +321,7 @@ void vmw_cmdbuf_res_man_destroy(struct vmw_cmdbuf_res_manager *man) list_for_each_entry_safe(entry, next, &man->list, head) vmw_cmdbuf_res_free(man, entry); + drm_ht_remove(&man->resources); kfree(man); } diff --git a/drivers/gpu/msm/kgsl.c b/drivers/gpu/msm/kgsl.c index 990c9bca5127..afb489f10172 100644 --- a/drivers/gpu/msm/kgsl.c +++ b/drivers/gpu/msm/kgsl.c @@ -2210,21 +2210,23 @@ static int kgsl_setup_dmabuf_useraddr(struct kgsl_device *device, if (fd != 0) dmabuf = dma_buf_get(fd - 1); } - up_read(¤t->mm->mmap_sem); - if (IS_ERR_OR_NULL(dmabuf)) + if (IS_ERR_OR_NULL(dmabuf)) { + up_read(¤t->mm->mmap_sem); return dmabuf ? PTR_ERR(dmabuf) : -ENODEV; + } ret = kgsl_setup_dma_buf(device, pagetable, entry, dmabuf); if (ret) { dma_buf_put(dmabuf); + up_read(¤t->mm->mmap_sem); return ret; } /* Setup the user addr/cache mode for cache operations */ entry->memdesc.useraddr = hostptr; _setup_cache_mode(entry, vma); - + up_read(¤t->mm->mmap_sem); return 0; } #else diff --git a/drivers/gpu/msm/kgsl_pwrscale.c b/drivers/gpu/msm/kgsl_pwrscale.c index 24a1a42af74e..3e4cc4490792 100644 --- a/drivers/gpu/msm/kgsl_pwrscale.c +++ b/drivers/gpu/msm/kgsl_pwrscale.c @@ -522,7 +522,8 @@ int kgsl_devfreq_target(struct device *dev, unsigned long *freq, u32 flags) struct kgsl_device *device = dev_get_drvdata(dev); struct kgsl_pwrctrl *pwr; struct kgsl_pwrlevel *pwr_level; - int level, i; + int level; + unsigned int i; unsigned long cur_freq; if (device == NULL) @@ -551,10 +552,11 @@ int kgsl_devfreq_target(struct device *dev, unsigned long *freq, u32 flags) if (*freq != cur_freq) { level = pwr->max_pwrlevel; /* - * To avoid infinite loop issue type cast max_pwrlevel to - * signed integer type + * Array index of pwrlevels[] should be within the permitted + * power levels, i.e., from max_pwrlevel to min_pwrlevel. */ - for (i = pwr->min_pwrlevel; i >= (int)pwr->max_pwrlevel; i--) + for (i = pwr->min_pwrlevel; (i >= pwr->max_pwrlevel + && i <= pwr->min_pwrlevel); i--) if (*freq <= pwr->pwrlevels[i].gpu_freq) { if (pwr->thermal_cycle == CYCLE_ACTIVE) level = _thermal_adjust(pwr, i); diff --git a/drivers/hid/i2c-hid/i2c-hid.c b/drivers/hid/i2c-hid/i2c-hid.c index 0b80633bae91..d4d655a10df1 100644 --- a/drivers/hid/i2c-hid/i2c-hid.c +++ b/drivers/hid/i2c-hid/i2c-hid.c @@ -364,6 +364,15 @@ static int i2c_hid_hwreset(struct i2c_client *client) if (ret) return ret; + /* + * The HID over I2C specification states that if a DEVICE needs time + * after the PWR_ON request, it should utilise CLOCK stretching. + * However, it has been observered that the Windows driver provides a + * 1ms sleep between the PWR_ON and RESET requests and that some devices + * rely on this. + */ + usleep_range(1000, 5000); + i2c_hid_dbg(ihid, "resetting...\n"); ret = i2c_hid_command(client, &hid_reset_cmd, NULL, 0); diff --git a/drivers/hwtracing/coresight/coresight-tmc.c b/drivers/hwtracing/coresight/coresight-tmc.c index 316d8b783d94..691c7bb3afac 100644 --- a/drivers/hwtracing/coresight/coresight-tmc.c +++ b/drivers/hwtracing/coresight/coresight-tmc.c @@ -1,4 +1,4 @@ -/* Copyright (c) 2012, 2016-2017 The Linux Foundation. All rights reserved. +/* Copyright (c) 2012, 2016-2017, The Linux Foundation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 and @@ -764,6 +764,16 @@ static int tmc_enable(struct tmc_drvdata *drvdata, enum tmc_mode mode) pm_runtime_get_sync(drvdata->dev); mutex_lock(&drvdata->mem_lock); + + spin_lock_irqsave(&drvdata->spinlock, flags); + if (drvdata->reading) { + spin_unlock_irqrestore(&drvdata->spinlock, flags); + mutex_unlock(&drvdata->mem_lock); + pm_runtime_put(drvdata->dev); + return -EBUSY; + } + spin_unlock_irqrestore(&drvdata->spinlock, flags); + if (drvdata->config_type == TMC_CONFIG_TYPE_ETR && drvdata->out_mode == TMC_ETR_OUT_MODE_MEM) { /* @@ -807,19 +817,8 @@ static int tmc_enable(struct tmc_drvdata *drvdata, enum tmc_mode mode) coresight_cti_map_trigout(drvdata->cti_flush, 1, 0); coresight_cti_map_trigin(drvdata->cti_reset, 2, 0); } - mutex_unlock(&drvdata->mem_lock); spin_lock_irqsave(&drvdata->spinlock, flags); - if (drvdata->reading) { - spin_unlock_irqrestore(&drvdata->spinlock, flags); - - if (drvdata->config_type == TMC_CONFIG_TYPE_ETR - && drvdata->out_mode == TMC_ETR_OUT_MODE_USB) - usb_qdss_close(drvdata->usbch); - pm_runtime_put(drvdata->dev); - - return -EBUSY; - } if (drvdata->config_type == TMC_CONFIG_TYPE_ETB) { tmc_etb_enable_hw(drvdata); @@ -845,6 +844,7 @@ static int tmc_enable(struct tmc_drvdata *drvdata, enum tmc_mode mode) */ drvdata->sticky_enable = true; spin_unlock_irqrestore(&drvdata->spinlock, flags); + mutex_unlock(&drvdata->mem_lock); dev_info(drvdata->dev, "TMC enabled\n"); return 0; @@ -1140,6 +1140,7 @@ static int tmc_read_prepare(struct tmc_drvdata *drvdata) unsigned long flags; enum tmc_mode mode; + mutex_lock(&drvdata->mem_lock); spin_lock_irqsave(&drvdata->spinlock, flags); if (!drvdata->sticky_enable) { dev_err(drvdata->dev, "enable tmc once before reading\n"); @@ -1172,11 +1173,13 @@ static int tmc_read_prepare(struct tmc_drvdata *drvdata) out: drvdata->reading = true; spin_unlock_irqrestore(&drvdata->spinlock, flags); + mutex_unlock(&drvdata->mem_lock); dev_info(drvdata->dev, "TMC read start\n"); return 0; err: spin_unlock_irqrestore(&drvdata->spinlock, flags); + mutex_unlock(&drvdata->mem_lock); return ret; } @@ -1353,7 +1356,11 @@ static ssize_t tmc_read(struct file *file, char __user *data, size_t len, { struct tmc_drvdata *drvdata = container_of(file->private_data, struct tmc_drvdata, miscdev); - char *bufp = drvdata->buf + *ppos; + char *bufp; + + mutex_lock(&drvdata->mem_lock); + + bufp = drvdata->buf + *ppos; if (*ppos + len > drvdata->size) len = drvdata->size - *ppos; @@ -1375,6 +1382,7 @@ static ssize_t tmc_read(struct file *file, char __user *data, size_t len, if (copy_to_user(data, bufp, len)) { dev_dbg(drvdata->dev, "%s: copy_to_user failed\n", __func__); + mutex_unlock(&drvdata->mem_lock); return -EFAULT; } @@ -1382,6 +1390,8 @@ static ssize_t tmc_read(struct file *file, char __user *data, size_t len, dev_dbg(drvdata->dev, "%s: %zu bytes copied, %d bytes left\n", __func__, len, (int)(drvdata->size - *ppos)); + + mutex_unlock(&drvdata->mem_lock); return len; } diff --git a/drivers/iommu/amd_iommu_v2.c b/drivers/iommu/amd_iommu_v2.c index 4831eb910fc7..22160e481794 100644 --- a/drivers/iommu/amd_iommu_v2.c +++ b/drivers/iommu/amd_iommu_v2.c @@ -699,9 +699,9 @@ out_clear_state: out_unregister: mmu_notifier_unregister(&pasid_state->mn, mm); + mmput(mm); out_free: - mmput(mm); free_pasid_state(pasid_state); out: diff --git a/drivers/iommu/intel-iommu.c b/drivers/iommu/intel-iommu.c index b92b8a724efb..f9711aceef54 100644 --- a/drivers/iommu/intel-iommu.c +++ b/drivers/iommu/intel-iommu.c @@ -1137,7 +1137,7 @@ static void dma_pte_free_level(struct dmar_domain *domain, int level, if (!dma_pte_present(pte) || dma_pte_superpage(pte)) goto next; - level_pfn = pfn & level_mask(level - 1); + level_pfn = pfn & level_mask(level); level_pte = phys_to_virt(dma_pte_addr(pte)); if (level > 2) diff --git a/drivers/iommu/iommu.c b/drivers/iommu/iommu.c index 33176a4aa6ef..92e6ae48caf8 100644 --- a/drivers/iommu/iommu.c +++ b/drivers/iommu/iommu.c @@ -394,36 +394,30 @@ int iommu_group_add_device(struct iommu_group *group, struct device *dev) device->dev = dev; ret = sysfs_create_link(&dev->kobj, &group->kobj, "iommu_group"); - if (ret) { - kfree(device); - return ret; - } + if (ret) + goto err_free_device; device->name = kasprintf(GFP_KERNEL, "%s", kobject_name(&dev->kobj)); rename: if (!device->name) { - sysfs_remove_link(&dev->kobj, "iommu_group"); - kfree(device); - return -ENOMEM; + ret = -ENOMEM; + goto err_remove_link; } ret = sysfs_create_link_nowarn(group->devices_kobj, &dev->kobj, device->name); if (ret) { - kfree(device->name); if (ret == -EEXIST && i >= 0) { /* * Account for the slim chance of collision * and append an instance to the name. */ + kfree(device->name); device->name = kasprintf(GFP_KERNEL, "%s.%d", kobject_name(&dev->kobj), i++); goto rename; } - - sysfs_remove_link(&dev->kobj, "iommu_group"); - kfree(device); - return ret; + goto err_free_name; } kobject_get(group->devices_kobj); @@ -435,8 +429,10 @@ rename: mutex_lock(&group->mutex); list_add_tail(&device->list, &group->devices); if (group->domain) - __iommu_attach_device(group->domain, dev); + ret = __iommu_attach_device(group->domain, dev); mutex_unlock(&group->mutex); + if (ret) + goto err_put_group; /* Notify any listeners about change to group. */ blocking_notifier_call_chain(&group->notifier, @@ -447,6 +443,21 @@ rename: pr_info("Adding device %s to group %d\n", dev_name(dev), group->id); return 0; + +err_put_group: + mutex_lock(&group->mutex); + list_del(&device->list); + mutex_unlock(&group->mutex); + dev->iommu_group = NULL; + kobject_put(group->devices_kobj); +err_free_name: + kfree(device->name); +err_remove_link: + sysfs_remove_link(&dev->kobj, "iommu_group"); +err_free_device: + kfree(device); + pr_err("Failed to add device %s to group %d: %d\n", dev_name(dev), group->id, ret); + return ret; } EXPORT_SYMBOL_GPL(iommu_group_add_device); diff --git a/drivers/media/platform/msm/ais/sensor/flash/msm_flash.c b/drivers/media/platform/msm/ais/sensor/flash/msm_flash.c index 6af589e5c230..a2a89b92c9f1 100644 --- a/drivers/media/platform/msm/ais/sensor/flash/msm_flash.c +++ b/drivers/media/platform/msm/ais/sensor/flash/msm_flash.c @@ -1022,13 +1022,13 @@ static long msm_flash_subdev_do_ioctl( sd = vdev_to_v4l2_subdev(vdev); u32 = (struct msm_flash_cfg_data_t32 *)arg; - flash_data.cfg_type = u32->cfg_type; - for (i = 0; i < MAX_LED_TRIGGERS; i++) { - flash_data.flash_current[i] = u32->flash_current[i]; - flash_data.flash_duration[i] = u32->flash_duration[i]; - } switch (cmd) { case VIDIOC_MSM_FLASH_CFG32: + flash_data.cfg_type = u32->cfg_type; + for (i = 0; i < MAX_LED_TRIGGERS; i++) { + flash_data.flash_current[i] = u32->flash_current[i]; + flash_data.flash_duration[i] = u32->flash_duration[i]; + } cmd = VIDIOC_MSM_FLASH_CFG; switch (flash_data.cfg_type) { case CFG_FLASH_OFF: diff --git a/drivers/media/platform/msm/ais/sensor/ois/msm_ois.c b/drivers/media/platform/msm/ais/sensor/ois/msm_ois.c index 28a5402a4359..236660dca3fb 100644 --- a/drivers/media/platform/msm/ais/sensor/ois/msm_ois.c +++ b/drivers/media/platform/msm/ais/sensor/ois/msm_ois.c @@ -781,11 +781,10 @@ static long msm_ois_subdev_do_ioctl( u32 = (struct msm_ois_cfg_data32 *)arg; parg = arg; - ois_data.cfgtype = u32->cfgtype; - switch (cmd) { case VIDIOC_MSM_OIS_CFG32: cmd = VIDIOC_MSM_OIS_CFG; + ois_data.cfgtype = u32->cfgtype; switch (u32->cfgtype) { case CFG_OIS_CONTROL: diff --git a/drivers/media/platform/msm/camera_v2/isp/msm_isp.h b/drivers/media/platform/msm/camera_v2/isp/msm_isp.h index 1f1435fe282e..b2d152bf4ef0 100644 --- a/drivers/media/platform/msm/camera_v2/isp/msm_isp.h +++ b/drivers/media/platform/msm/camera_v2/isp/msm_isp.h @@ -786,6 +786,7 @@ struct vfe_device { size_t num_norm_clk; bool hvx_clk_state; enum cam_ahb_clk_vote ahb_vote; + enum cam_ahb_clk_vote user_requested_ahb_vote; struct cx_ipeak_client *vfe_cx_ipeak; /* Sync variables*/ diff --git a/drivers/media/platform/msm/camera_v2/isp/msm_isp47.c b/drivers/media/platform/msm/camera_v2/isp/msm_isp47.c index 6515e3d6ecbc..24d1c6cba84d 100644 --- a/drivers/media/platform/msm/camera_v2/isp/msm_isp47.c +++ b/drivers/media/platform/msm/camera_v2/isp/msm_isp47.c @@ -274,10 +274,12 @@ int msm_isp47_ahb_clk_cfg(struct vfe_device *vfe_dev, enum cam_ahb_clk_vote src_clk_vote; struct msm_isp_clk_rates clk_rates; - if (ahb_cfg) + if (ahb_cfg) { vote = msm_isp47_get_cam_clk_vote(ahb_cfg->vote); - else - vote = CAM_AHB_SVS_VOTE; + vfe_dev->user_requested_ahb_vote = vote; + } else { + vote = vfe_dev->user_requested_ahb_vote; + } vfe_dev->hw_info->vfe_ops.platform_ops.get_clk_rates(vfe_dev, &clk_rates); @@ -327,6 +329,7 @@ int msm_vfe47_init_hardware(struct vfe_device *vfe_dev) if (rc) goto clk_enable_failed; + vfe_dev->user_requested_ahb_vote = CAM_AHB_SVS_VOTE; rc = cam_config_ahb_clk(NULL, 0, id, CAM_AHB_SVS_VOTE); if (rc < 0) { pr_err("%s: failed to vote for AHB\n", __func__); diff --git a/drivers/media/platform/msm/camera_v2/isp/msm_isp_axi_util.c b/drivers/media/platform/msm/camera_v2/isp/msm_isp_axi_util.c index e6d36a083a36..63f5497e63b8 100644 --- a/drivers/media/platform/msm/camera_v2/isp/msm_isp_axi_util.c +++ b/drivers/media/platform/msm/camera_v2/isp/msm_isp_axi_util.c @@ -776,40 +776,6 @@ void msm_isp_check_for_output_error(struct vfe_device *vfe_dev, } } -static int msm_isp_check_sync_time(struct msm_vfe_src_info *src_info, - struct msm_isp_timestamp *ts, - struct master_slave_resource_info *ms_res) -{ - int i; - struct msm_vfe_src_info *master_src_info = NULL; - uint32_t master_time = 0, current_time; - - if (!ms_res->src_sof_mask) - return 0; - - for (i = 0; i < MAX_VFE * VFE_SRC_MAX; i++) { - if (ms_res->src_info[i] == NULL) - continue; - if (src_info == ms_res->src_info[i] || - ms_res->src_info[i]->active == 0) - continue; - if (ms_res->src_sof_mask & - (1 << ms_res->src_info[i]->dual_hw_ms_info.index)) { - master_src_info = ms_res->src_info[i]; - break; - } - } - if (!master_src_info) - return 0; - master_time = master_src_info-> - dual_hw_ms_info.sof_info.mono_timestamp_ms; - current_time = ts->buf_time.tv_sec * 1000 + - ts->buf_time.tv_usec / 1000; - if ((current_time - master_time) > ms_res->sof_delta_threshold) - return 1; - return 0; -} - static void msm_isp_sync_dual_cam_frame_id( struct vfe_device *vfe_dev, struct master_slave_resource_info *ms_res, @@ -824,24 +790,11 @@ static void msm_isp_sync_dual_cam_frame_id( if (src_info->dual_hw_ms_info.sync_state == ms_res->dual_sync_mode) { - if (msm_isp_check_sync_time(src_info, ts, ms_res) == 0) { - (frame_src == VFE_PIX_0) ? src_info->frame_id += + (frame_src == VFE_PIX_0) ? src_info->frame_id += vfe_dev->axi_data.src_info[frame_src]. sof_counter_step : src_info->frame_id++; - return; - } - ms_res->src_sof_mask = 0; - ms_res->active_src_mask = 0; - for (i = 0; i < MAX_VFE * VFE_SRC_MAX; i++) { - if (ms_res->src_info[i] == NULL) - continue; - if (ms_res->src_info[i]->active == 0) - continue; - ms_res->src_info[i]->dual_hw_ms_info. - sync_state = - MSM_ISP_DUAL_CAM_ASYNC; - } + return; } /* find highest frame id */ diff --git a/drivers/media/platform/msm/camera_v2/sensor/actuator/msm_actuator.c b/drivers/media/platform/msm/camera_v2/sensor/actuator/msm_actuator.c index bc844bb87db5..b1bea12c2cc3 100644 --- a/drivers/media/platform/msm/camera_v2/sensor/actuator/msm_actuator.c +++ b/drivers/media/platform/msm/camera_v2/sensor/actuator/msm_actuator.c @@ -1707,6 +1707,10 @@ static long msm_actuator_subdev_do_ioctl( parg = &actuator_data; break; } + break; + case VIDIOC_MSM_ACTUATOR_CFG: + pr_err("%s: invalid cmd 0x%x received\n", __func__, cmd); + return -EINVAL; } rc = msm_actuator_subdev_ioctl(sd, cmd, parg); diff --git a/drivers/media/platform/msm/camera_v2/sensor/cci/msm_cci.c b/drivers/media/platform/msm/camera_v2/sensor/cci/msm_cci.c index 7dda92510879..3cb6b55ccc8c 100644 --- a/drivers/media/platform/msm/camera_v2/sensor/cci/msm_cci.c +++ b/drivers/media/platform/msm/camera_v2/sensor/cci/msm_cci.c @@ -403,6 +403,10 @@ static int32_t msm_cci_calc_cmd_len(struct cci_device *cci_dev, if (cmd->reg_addr + 1 == (cmd+1)->reg_addr) { len += data_len; + if (len > cci_dev->payload_size) { + len = len - data_len; + break; + } *pack += data_len; } else break; diff --git a/drivers/media/platform/msm/camera_v2/sensor/flash/msm_flash.c b/drivers/media/platform/msm/camera_v2/sensor/flash/msm_flash.c index cf7d1a8aa1f4..223ddf39dce8 100644 --- a/drivers/media/platform/msm/camera_v2/sensor/flash/msm_flash.c +++ b/drivers/media/platform/msm/camera_v2/sensor/flash/msm_flash.c @@ -508,18 +508,42 @@ static int32_t msm_flash_init( return 0; } -#ifdef CONFIG_COMPAT static int32_t msm_flash_init_prepare( struct msm_flash_ctrl_t *flash_ctrl, struct msm_flash_cfg_data_t *flash_data) { +#ifdef CONFIG_COMPAT + struct msm_flash_cfg_data_t flash_data_k; + struct msm_flash_init_info_t flash_init_info; + int32_t i = 0; + + if (!is_compat_task()) { + /*for 64-bit usecase,it need copy the data to local memory*/ + flash_data_k.cfg_type = flash_data->cfg_type; + for (i = 0; i < MAX_LED_TRIGGERS; i++) { + flash_data_k.flash_current[i] = + flash_data->flash_current[i]; + flash_data_k.flash_duration[i] = + flash_data->flash_duration[i]; + } + + flash_data_k.cfg.flash_init_info = &flash_init_info; + if (copy_from_user(&flash_init_info, + (void __user *)(flash_data->cfg.flash_init_info), + sizeof(struct msm_flash_init_info_t))) { + pr_err("%s copy_from_user failed %d\n", + __func__, __LINE__); + return -EFAULT; + } + return msm_flash_init(flash_ctrl, &flash_data_k); + } + /* + * for 32-bit usecase,it already copy the userspace + * data to local memory in msm_flash_subdev_do_ioctl() + * so here do not need copy from user + */ return msm_flash_init(flash_ctrl, flash_data); -} #else -static int32_t msm_flash_init_prepare( - struct msm_flash_ctrl_t *flash_ctrl, - struct msm_flash_cfg_data_t *flash_data) -{ struct msm_flash_cfg_data_t flash_data_k; struct msm_flash_init_info_t flash_init_info; int32_t i = 0; @@ -534,15 +558,15 @@ static int32_t msm_flash_init_prepare( flash_data_k.cfg.flash_init_info = &flash_init_info; if (copy_from_user(&flash_init_info, - (void *)(flash_data->cfg.flash_init_info), + (void __user *)(flash_data->cfg.flash_init_info), sizeof(struct msm_flash_init_info_t))) { pr_err("%s copy_from_user failed %d\n", __func__, __LINE__); return -EFAULT; } return msm_flash_init(flash_ctrl, &flash_data_k); -} #endif +} static int32_t msm_flash_prepare( struct msm_flash_ctrl_t *flash_ctrl) diff --git a/drivers/media/platform/msm/sde/rotator/sde_rotator_r3.c b/drivers/media/platform/msm/sde/rotator/sde_rotator_r3.c index acb697946e18..10f72a2155db 100644 --- a/drivers/media/platform/msm/sde/rotator/sde_rotator_r3.c +++ b/drivers/media/platform/msm/sde/rotator/sde_rotator_r3.c @@ -814,6 +814,9 @@ static void sde_hw_rotator_setup_wbengine(struct sde_hw_rotator_context *ctx, bw /= TRAFFIC_SHAPE_CLKTICK_12MS; if (bw > 0xFF) bw = 0xFF; + else if (bw == 0) + bw = 1; + SDE_REGDMA_WRITE(wrptr, ROT_WB_TRAFFIC_SHAPER_WR_CLIENT, BIT(31) | bw); SDEROT_DBG("Enable ROT_WB Traffic Shaper:%d\n", bw); diff --git a/drivers/media/platform/msm/vidc/msm_vidc.c b/drivers/media/platform/msm/vidc/msm_vidc.c index 7caf61cb6799..2b3070974df8 100644 --- a/drivers/media/platform/msm/vidc/msm_vidc.c +++ b/drivers/media/platform/msm/vidc/msm_vidc.c @@ -550,7 +550,7 @@ static int __map_and_update_binfo(struct msm_vidc_inst *inst, binfo->handle[i] = map_buffer(inst, &b->m.planes[i], get_hal_buffer_type(inst, b)); if (!binfo->handle[i]) - rc = -EINVAL; + return -EINVAL; binfo->mapped[i] = true; binfo->device_addr[i] = binfo->handle[i]->device_addr + @@ -670,13 +670,13 @@ int map_and_register_buf(struct msm_vidc_inst *inst, struct v4l2_buffer *b) rc = __map_and_update_binfo(inst, binfo, b, i); if (rc) - goto exit; + goto map_err; /* We maintain one ref count for all planes*/ if (!i && is_dynamic_output_buffer_mode(b, inst)) { rc = buf_ref_get(inst, binfo); if (rc < 0) - goto exit; + goto map_err; } dprintk(VIDC_DBG, "%s: [MAP] binfo = %pK, handle[%d] = %pK, device_addr = %pa, fd = %d, offset = %d, mapped = %d\n", @@ -690,10 +690,14 @@ int map_and_register_buf(struct msm_vidc_inst *inst, struct v4l2_buffer *b) mutex_unlock(&inst->registeredbufs.lock); return 0; +map_err: + if (binfo->handle[0] && binfo->mapped[0]) + msm_comm_smem_free(inst, binfo->handle[0]); exit: kfree(binfo); return rc; } + int unmap_and_deregister_buf(struct msm_vidc_inst *inst, struct buffer_info *binfo) { diff --git a/drivers/misc/qseecom.c b/drivers/misc/qseecom.c index 7cdcd69cecf4..66f3c9f609f2 100644 --- a/drivers/misc/qseecom.c +++ b/drivers/misc/qseecom.c @@ -281,6 +281,7 @@ struct qseecom_control { wait_queue_head_t app_block_wq; atomic_t qseecom_state; int is_apps_region_protected; + bool smcinvoke_support; }; struct qseecom_sec_buf_fd_info { @@ -578,10 +579,12 @@ static int qseecom_scm_call2(uint32_t svc_id, uint32_t tz_cmd_id, desc.args[1] = req_64bit->sb_ptr; desc.args[2] = req_64bit->sb_len; } + qseecom.smcinvoke_support = true; smc_id = TZ_OS_REGISTER_LISTENER_SMCINVOKE_ID; __qseecom_reentrancy_check_if_no_app_blocked(smc_id); ret = scm_call2(smc_id, &desc); if (ret) { + qseecom.smcinvoke_support = false; smc_id = TZ_OS_REGISTER_LISTENER_ID; __qseecom_reentrancy_check_if_no_app_blocked( smc_id); @@ -1006,10 +1009,14 @@ static int qseecom_scm_call2(uint32_t svc_id, uint32_t tz_cmd_id, struct qseecom_continue_blocked_request_ireq *req = (struct qseecom_continue_blocked_request_ireq *) req_buf; - smc_id = TZ_OS_CONTINUE_BLOCKED_REQUEST_ID; + if (qseecom.smcinvoke_support) + smc_id = + TZ_OS_CONTINUE_BLOCKED_REQUEST_SMCINVOKE_ID; + else + smc_id = TZ_OS_CONTINUE_BLOCKED_REQUEST_ID; desc.arginfo = TZ_OS_CONTINUE_BLOCKED_REQUEST_ID_PARAM_ID; - desc.args[0] = req->app_id; + desc.args[0] = req->app_or_session_id; ret = scm_call2(smc_id, &desc); break; } @@ -1839,7 +1846,7 @@ static int __qseecom_process_incomplete_cmd(struct qseecom_dev_handle *data, return ret; } -int __qseecom_process_reentrancy_blocked_on_listener( +static int __qseecom_process_blocked_on_listener_legacy( struct qseecom_command_scm_resp *resp, struct qseecom_registered_app_list *ptr_app, struct qseecom_dev_handle *data) @@ -1848,9 +1855,8 @@ int __qseecom_process_reentrancy_blocked_on_listener( int ret = 0; struct qseecom_continue_blocked_request_ireq ireq; struct qseecom_command_scm_resp continue_resp; - sigset_t new_sigset, old_sigset; - unsigned long flags; bool found_app = false; + unsigned long flags; if (!resp || !data) { pr_err("invalid resp or data pointer\n"); @@ -1890,32 +1896,30 @@ int __qseecom_process_reentrancy_blocked_on_listener( pr_debug("lsntr %d in_use = %d\n", resp->data, list_ptr->listener_in_use); ptr_app->blocked_on_listener_id = resp->data; + /* sleep until listener is available */ - do { - qseecom.app_block_ref_cnt++; - ptr_app->app_blocked = true; - sigfillset(&new_sigset); - sigprocmask(SIG_SETMASK, &new_sigset, &old_sigset); - mutex_unlock(&app_access_lock); - do { - if (!wait_event_freezable( - list_ptr->listener_block_app_wq, - !list_ptr->listener_in_use)) { - break; - } - } while (1); - mutex_lock(&app_access_lock); - sigprocmask(SIG_SETMASK, &old_sigset, NULL); - ptr_app->app_blocked = false; - qseecom.app_block_ref_cnt--; - } while (list_ptr->listener_in_use == true); + qseecom.app_block_ref_cnt++; + ptr_app->app_blocked = true; + mutex_unlock(&app_access_lock); + if (wait_event_freezable( + list_ptr->listener_block_app_wq, + !list_ptr->listener_in_use)) { + pr_err("Interrupted: listener_id %d, app_id %d\n", + resp->data, ptr_app->app_id); + ret = -ERESTARTSYS; + goto exit; + } + mutex_lock(&app_access_lock); + ptr_app->app_blocked = false; + qseecom.app_block_ref_cnt--; + ptr_app->blocked_on_listener_id = 0; /* notify the blocked app that listener is available */ pr_warn("Lsntr %d is available, unblock app(%d) %s in TZ\n", resp->data, data->client.app_id, data->client.app_name); ireq.qsee_cmd_id = QSEOS_CONTINUE_BLOCKED_REQ_COMMAND; - ireq.app_id = data->client.app_id; + ireq.app_or_session_id = data->client.app_id; ret = qseecom_scm_call(SCM_SVC_TZSCHEDULER, 1, &ireq, sizeof(ireq), &continue_resp, sizeof(continue_resp)); @@ -1934,6 +1938,73 @@ exit: return ret; } +static int __qseecom_process_blocked_on_listener_smcinvoke( + struct qseecom_command_scm_resp *resp) +{ + struct qseecom_registered_listener_list *list_ptr; + int ret = 0; + struct qseecom_continue_blocked_request_ireq ireq; + struct qseecom_command_scm_resp continue_resp; + unsigned int session_id; + + if (!resp) { + pr_err("invalid resp pointer\n"); + ret = -EINVAL; + goto exit; + } + session_id = resp->resp_type; + list_ptr = __qseecom_find_svc(resp->data); + if (!list_ptr) { + pr_err("Invalid listener ID\n"); + ret = -ENODATA; + goto exit; + } + pr_debug("lsntr %d in_use = %d\n", + resp->data, list_ptr->listener_in_use); + /* sleep until listener is available */ + qseecom.app_block_ref_cnt++; + mutex_unlock(&app_access_lock); + if (wait_event_freezable( + list_ptr->listener_block_app_wq, + !list_ptr->listener_in_use)) { + pr_err("Interrupted: listener_id %d, session_id %d\n", + resp->data, session_id); + ret = -ERESTARTSYS; + goto exit; + } + mutex_lock(&app_access_lock); + qseecom.app_block_ref_cnt--; + + /* notify TZ that listener is available */ + pr_warn("Lsntr %d is available, unblock session(%d) in TZ\n", + resp->data, session_id); + ireq.qsee_cmd_id = QSEOS_CONTINUE_BLOCKED_REQ_COMMAND; + ireq.app_or_session_id = session_id; + ret = qseecom_scm_call(SCM_SVC_TZSCHEDULER, 1, + &ireq, sizeof(ireq), + &continue_resp, sizeof(continue_resp)); + if (ret) { + pr_err("scm_call for continue blocked req for session %d failed, ret %d\n", + session_id, ret); + goto exit; + } + resp->result = QSEOS_RESULT_INCOMPLETE; +exit: + return ret; +} + +static int __qseecom_process_reentrancy_blocked_on_listener( + struct qseecom_command_scm_resp *resp, + struct qseecom_registered_app_list *ptr_app, + struct qseecom_dev_handle *data) +{ + if (!qseecom.smcinvoke_support) + return __qseecom_process_blocked_on_listener_legacy( + resp, ptr_app, data); + else + return __qseecom_process_blocked_on_listener_smcinvoke( + resp); +} static int __qseecom_reentrancy_process_incomplete_cmd( struct qseecom_dev_handle *data, struct qseecom_command_scm_resp *resp) @@ -4699,18 +4770,15 @@ int qseecom_process_listener_from_smcinvoke(struct scm_desc *desc) } resp.result = desc->ret[0]; /*req_cmd*/ - resp.resp_type = desc->ret[1]; /*app_id*/ + resp.resp_type = desc->ret[1]; /*incomplete:unused;blocked:session_id*/ resp.data = desc->ret[2]; /*listener_id*/ - dummy_private_data.client.app_id = desc->ret[1]; - dummy_app_entry.app_id = desc->ret[1]; - mutex_lock(&app_access_lock); ret = __qseecom_process_reentrancy(&resp, &dummy_app_entry, &dummy_private_data); mutex_unlock(&app_access_lock); if (ret) - pr_err("Failed to req cmd %d lsnr %d on app %d, ret = %d\n", + pr_err("Failed on cmd %d for lsnr %d session %d, ret = %d\n", (int)desc->ret[0], (int)desc->ret[2], (int)desc->ret[1], ret); desc->ret[0] = resp.result; diff --git a/drivers/mmc/host/sdhci-msm.c b/drivers/mmc/host/sdhci-msm.c index 7aefeb037ef4..8dc93900b16d 100644 --- a/drivers/mmc/host/sdhci-msm.c +++ b/drivers/mmc/host/sdhci-msm.c @@ -1139,6 +1139,7 @@ int sdhci_msm_execute_tuning(struct sdhci_host *host, u32 opcode) bool drv_type_changed = false; struct mmc_card *card = host->mmc->card; int sts_retry; + u8 last_good_phase = 0; /* * Tuning is required for SDR104, HS200 and HS400 cards and @@ -1224,6 +1225,22 @@ retry: mmc_wait_for_req(mmc, &mrq); if (card && (cmd.error || data.error)) { + /* + * Set the dll to last known good phase while sending + * status command to ensure that status command won't + * fail due to bad phase. + */ + if (tuned_phase_cnt) + last_good_phase = + tuned_phases[tuned_phase_cnt-1]; + else if (msm_host->saved_tuning_phase != + INVALID_TUNING_PHASE) + last_good_phase = msm_host->saved_tuning_phase; + + rc = msm_config_cm_dll_phase(host, last_good_phase); + if (rc) + goto kfree; + sts_cmd.opcode = MMC_SEND_STATUS; sts_cmd.arg = card->rca << 16; sts_cmd.flags = MMC_RSP_R1 | MMC_CMD_AC; diff --git a/drivers/mtd/bcm47xxpart.c b/drivers/mtd/bcm47xxpart.c index 5abab8800891..9190057535e6 100644 --- a/drivers/mtd/bcm47xxpart.c +++ b/drivers/mtd/bcm47xxpart.c @@ -66,11 +66,13 @@ static const char *bcm47xxpart_trx_data_part_name(struct mtd_info *master, { uint32_t buf; size_t bytes_read; + int err; - if (mtd_read(master, offset, sizeof(buf), &bytes_read, - (uint8_t *)&buf) < 0) { - pr_err("mtd_read error while parsing (offset: 0x%X)!\n", - offset); + err = mtd_read(master, offset, sizeof(buf), &bytes_read, + (uint8_t *)&buf); + if (err && !mtd_is_bitflip(err)) { + pr_err("mtd_read error while parsing (offset: 0x%X): %d\n", + offset, err); goto out_default; } @@ -95,6 +97,7 @@ static int bcm47xxpart_parse(struct mtd_info *master, int trx_part = -1; int last_trx_part = -1; int possible_nvram_sizes[] = { 0x8000, 0xF000, 0x10000, }; + int err; /* * Some really old flashes (like AT45DB*) had smaller erasesize-s, but @@ -118,8 +121,8 @@ static int bcm47xxpart_parse(struct mtd_info *master, /* Parse block by block looking for magics */ for (offset = 0; offset <= master->size - blocksize; offset += blocksize) { - /* Nothing more in higher memory */ - if (offset >= 0x2000000) + /* Nothing more in higher memory on BCM47XX (MIPS) */ + if (config_enabled(CONFIG_BCM47XX) && offset >= 0x2000000) break; if (curr_part >= BCM47XXPART_MAX_PARTS) { @@ -128,10 +131,11 @@ static int bcm47xxpart_parse(struct mtd_info *master, } /* Read beginning of the block */ - if (mtd_read(master, offset, BCM47XXPART_BYTES_TO_READ, - &bytes_read, (uint8_t *)buf) < 0) { - pr_err("mtd_read error while parsing (offset: 0x%X)!\n", - offset); + err = mtd_read(master, offset, BCM47XXPART_BYTES_TO_READ, + &bytes_read, (uint8_t *)buf); + if (err && !mtd_is_bitflip(err)) { + pr_err("mtd_read error while parsing (offset: 0x%X): %d\n", + offset, err); continue; } @@ -252,10 +256,11 @@ static int bcm47xxpart_parse(struct mtd_info *master, } /* Read middle of the block */ - if (mtd_read(master, offset + 0x8000, 0x4, - &bytes_read, (uint8_t *)buf) < 0) { - pr_err("mtd_read error while parsing (offset: 0x%X)!\n", - offset); + err = mtd_read(master, offset + 0x8000, 0x4, &bytes_read, + (uint8_t *)buf); + if (err && !mtd_is_bitflip(err)) { + pr_err("mtd_read error while parsing (offset: 0x%X): %d\n", + offset, err); continue; } @@ -275,10 +280,11 @@ static int bcm47xxpart_parse(struct mtd_info *master, } offset = master->size - possible_nvram_sizes[i]; - if (mtd_read(master, offset, 0x4, &bytes_read, - (uint8_t *)buf) < 0) { - pr_err("mtd_read error while reading at offset 0x%X!\n", - offset); + err = mtd_read(master, offset, 0x4, &bytes_read, + (uint8_t *)buf); + if (err && !mtd_is_bitflip(err)) { + pr_err("mtd_read error while reading (offset 0x%X): %d\n", + offset, err); continue; } diff --git a/drivers/net/ethernet/amd/xgbe/xgbe-dev.c b/drivers/net/ethernet/amd/xgbe/xgbe-dev.c index 5e6238e0b2bd..75e6e7e6baed 100644 --- a/drivers/net/ethernet/amd/xgbe/xgbe-dev.c +++ b/drivers/net/ethernet/amd/xgbe/xgbe-dev.c @@ -2732,8 +2732,10 @@ static int xgbe_init(struct xgbe_prv_data *pdata) /* Flush Tx queues */ ret = xgbe_flush_tx_queues(pdata); - if (ret) + if (ret) { + netdev_err(pdata->netdev, "error flushing TX queues\n"); return ret; + } /* * Initialize DMA related features diff --git a/drivers/net/ethernet/amd/xgbe/xgbe-drv.c b/drivers/net/ethernet/amd/xgbe/xgbe-drv.c index 865b7e0b133b..64034ff081a0 100644 --- a/drivers/net/ethernet/amd/xgbe/xgbe-drv.c +++ b/drivers/net/ethernet/amd/xgbe/xgbe-drv.c @@ -877,7 +877,9 @@ static int xgbe_start(struct xgbe_prv_data *pdata) DBGPR("-->xgbe_start\n"); - hw_if->init(pdata); + ret = hw_if->init(pdata); + if (ret) + return ret; ret = phy_if->phy_start(pdata); if (ret) diff --git a/drivers/net/ethernet/broadcom/bgmac.c b/drivers/net/ethernet/broadcom/bgmac.c index b56c9c581359..70da30095b89 100644 --- a/drivers/net/ethernet/broadcom/bgmac.c +++ b/drivers/net/ethernet/broadcom/bgmac.c @@ -255,15 +255,16 @@ static void bgmac_dma_tx_free(struct bgmac *bgmac, struct bgmac_dma_ring *ring) while (ring->start != ring->end) { int slot_idx = ring->start % BGMAC_TX_RING_SLOTS; struct bgmac_slot_info *slot = &ring->slots[slot_idx]; - u32 ctl1; + u32 ctl0, ctl1; int len; if (slot_idx == empty_slot) break; + ctl0 = le32_to_cpu(ring->cpu_base[slot_idx].ctl0); ctl1 = le32_to_cpu(ring->cpu_base[slot_idx].ctl1); len = ctl1 & BGMAC_DESC_CTL1_LEN; - if (ctl1 & BGMAC_DESC_CTL0_SOF) + if (ctl0 & BGMAC_DESC_CTL0_SOF) /* Unmap no longer used buffer */ dma_unmap_single(dma_dev, slot->dma_addr, len, DMA_TO_DEVICE); @@ -469,6 +470,11 @@ static int bgmac_dma_rx_read(struct bgmac *bgmac, struct bgmac_dma_ring *ring, len -= ETH_FCS_LEN; skb = build_skb(buf, BGMAC_RX_ALLOC_SIZE); + if (unlikely(!skb)) { + bgmac_err(bgmac, "build_skb failed\n"); + put_page(virt_to_head_page(buf)); + break; + } skb_put(skb, BGMAC_RX_FRAME_OFFSET + BGMAC_RX_BUF_OFFSET + len); skb_pull(skb, BGMAC_RX_FRAME_OFFSET + @@ -1302,7 +1308,8 @@ static int bgmac_open(struct net_device *net_dev) phy_start(bgmac->phy_dev); - netif_carrier_on(net_dev); + netif_start_queue(net_dev); + return 0; } diff --git a/drivers/net/ethernet/emulex/benet/be_cmds.c b/drivers/net/ethernet/emulex/benet/be_cmds.c index 1795c935ff02..7b8638ddb673 100644 --- a/drivers/net/ethernet/emulex/benet/be_cmds.c +++ b/drivers/net/ethernet/emulex/benet/be_cmds.c @@ -1052,7 +1052,7 @@ int be_cmd_pmac_add(struct be_adapter *adapter, u8 *mac_addr, err: spin_unlock_bh(&adapter->mcc_lock); - if (status == MCC_STATUS_UNAUTHORIZED_REQUEST) + if (base_status(status) == MCC_STATUS_UNAUTHORIZED_REQUEST) status = -EPERM; return status; diff --git a/drivers/net/ethernet/freescale/gianfar.c b/drivers/net/ethernet/freescale/gianfar.c index 6a061f17a44f..4cd2a7d0124f 100644 --- a/drivers/net/ethernet/freescale/gianfar.c +++ b/drivers/net/ethernet/freescale/gianfar.c @@ -2939,7 +2939,7 @@ static bool gfar_add_rx_frag(struct gfar_rx_buff *rxb, u32 lstatus, size, GFAR_RXB_TRUESIZE); /* try reuse page */ - if (unlikely(page_count(page) != 1)) + if (unlikely(page_count(page) != 1 || page_is_pfmemalloc(page))) return false; /* change offset to the other half */ diff --git a/drivers/net/ethernet/ibm/ibmveth.c b/drivers/net/ethernet/ibm/ibmveth.c index f9e4988ea30e..2f9b12cf9ee5 100644 --- a/drivers/net/ethernet/ibm/ibmveth.c +++ b/drivers/net/ethernet/ibm/ibmveth.c @@ -1602,8 +1602,11 @@ static int ibmveth_probe(struct vio_dev *dev, const struct vio_device_id *id) netdev->netdev_ops = &ibmveth_netdev_ops; netdev->ethtool_ops = &netdev_ethtool_ops; SET_NETDEV_DEV(netdev, &dev->dev); - netdev->hw_features = NETIF_F_SG | NETIF_F_RXCSUM | - NETIF_F_IP_CSUM | NETIF_F_IPV6_CSUM; + netdev->hw_features = NETIF_F_SG; + if (vio_get_attribute(dev, "ibm,illan-options", NULL) != NULL) { + netdev->hw_features |= NETIF_F_IP_CSUM | NETIF_F_IPV6_CSUM | + NETIF_F_RXCSUM; + } netdev->features |= netdev->hw_features; diff --git a/drivers/net/ethernet/korina.c b/drivers/net/ethernet/korina.c index d74f5f4e5782..07eabf72c480 100644 --- a/drivers/net/ethernet/korina.c +++ b/drivers/net/ethernet/korina.c @@ -900,10 +900,10 @@ static void korina_restart_task(struct work_struct *work) DMA_STAT_DONE | DMA_STAT_HALT | DMA_STAT_ERR, &lp->rx_dma_regs->dmasm); - korina_free_ring(dev); - napi_disable(&lp->napi); + korina_free_ring(dev); + if (korina_init(dev) < 0) { printk(KERN_ERR "%s: cannot restart device\n", dev->name); return; @@ -1064,12 +1064,12 @@ static int korina_close(struct net_device *dev) tmp = tmp | DMA_STAT_DONE | DMA_STAT_HALT | DMA_STAT_ERR; writel(tmp, &lp->rx_dma_regs->dmasm); - korina_free_ring(dev); - napi_disable(&lp->napi); cancel_work_sync(&lp->restart_task); + korina_free_ring(dev); + free_irq(lp->rx_irq, dev); free_irq(lp->tx_irq, dev); free_irq(lp->ovr_irq, dev); diff --git a/drivers/net/ethernet/marvell/mvneta.c b/drivers/net/ethernet/marvell/mvneta.c index 71ec9cb08e06..15056f06754a 100644 --- a/drivers/net/ethernet/marvell/mvneta.c +++ b/drivers/net/ethernet/marvell/mvneta.c @@ -2446,7 +2446,7 @@ static void mvneta_start_dev(struct mvneta_port *pp) mvneta_port_enable(pp); /* Enable polling on the port */ - for_each_present_cpu(cpu) { + for_each_online_cpu(cpu) { struct mvneta_pcpu_port *port = per_cpu_ptr(pp->ports, cpu); napi_enable(&port->napi); @@ -2472,7 +2472,7 @@ static void mvneta_stop_dev(struct mvneta_port *pp) phy_stop(pp->phy_dev); - for_each_present_cpu(cpu) { + for_each_online_cpu(cpu) { struct mvneta_pcpu_port *port = per_cpu_ptr(pp->ports, cpu); napi_disable(&port->napi); @@ -2902,13 +2902,11 @@ err_cleanup_rxqs: static int mvneta_stop(struct net_device *dev) { struct mvneta_port *pp = netdev_priv(dev); - int cpu; mvneta_stop_dev(pp); mvneta_mdio_remove(pp); unregister_cpu_notifier(&pp->cpu_notifier); - for_each_present_cpu(cpu) - smp_call_function_single(cpu, mvneta_percpu_disable, pp, true); + on_each_cpu(mvneta_percpu_disable, pp, true); free_percpu_irq(dev->irq, pp->ports); mvneta_cleanup_rxqs(pp); mvneta_cleanup_txqs(pp); diff --git a/drivers/net/ethernet/mellanox/mlx4/eq.c b/drivers/net/ethernet/mellanox/mlx4/eq.c index 603d1c3d3b2e..ff77b8b608bd 100644 --- a/drivers/net/ethernet/mellanox/mlx4/eq.c +++ b/drivers/net/ethernet/mellanox/mlx4/eq.c @@ -542,8 +542,9 @@ static int mlx4_eq_int(struct mlx4_dev *dev, struct mlx4_eq *eq) break; case MLX4_EVENT_TYPE_SRQ_LIMIT: - mlx4_dbg(dev, "%s: MLX4_EVENT_TYPE_SRQ_LIMIT\n", - __func__); + mlx4_dbg(dev, "%s: MLX4_EVENT_TYPE_SRQ_LIMIT. srq_no=0x%x, eq 0x%x\n", + __func__, be32_to_cpu(eqe->event.srq.srqn), + eq->eqn); case MLX4_EVENT_TYPE_SRQ_CATAS_ERROR: if (mlx4_is_master(dev)) { /* forward only to slave owning the SRQ */ @@ -558,15 +559,19 @@ static int mlx4_eq_int(struct mlx4_dev *dev, struct mlx4_eq *eq) eq->eqn, eq->cons_index, ret); break; } - mlx4_warn(dev, "%s: slave:%d, srq_no:0x%x, event: %02x(%02x)\n", - __func__, slave, - be32_to_cpu(eqe->event.srq.srqn), - eqe->type, eqe->subtype); + if (eqe->type == + MLX4_EVENT_TYPE_SRQ_CATAS_ERROR) + mlx4_warn(dev, "%s: slave:%d, srq_no:0x%x, event: %02x(%02x)\n", + __func__, slave, + be32_to_cpu(eqe->event.srq.srqn), + eqe->type, eqe->subtype); if (!ret && slave != dev->caps.function) { - mlx4_warn(dev, "%s: sending event %02x(%02x) to slave:%d\n", - __func__, eqe->type, - eqe->subtype, slave); + if (eqe->type == + MLX4_EVENT_TYPE_SRQ_CATAS_ERROR) + mlx4_warn(dev, "%s: sending event %02x(%02x) to slave:%d\n", + __func__, eqe->type, + eqe->subtype, slave); mlx4_slave_event(dev, slave, eqe); break; } diff --git a/drivers/net/ethernet/mellanox/mlx5/core/main.c b/drivers/net/ethernet/mellanox/mlx5/core/main.c index 1e611980cf99..f5c1f4acc57b 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/main.c +++ b/drivers/net/ethernet/mellanox/mlx5/core/main.c @@ -153,8 +153,9 @@ static struct mlx5_profile profile[] = { }, }; -#define FW_INIT_TIMEOUT_MILI 2000 -#define FW_INIT_WAIT_MS 2 +#define FW_INIT_TIMEOUT_MILI 2000 +#define FW_INIT_WAIT_MS 2 +#define FW_PRE_INIT_TIMEOUT_MILI 10000 static int wait_fw_init(struct mlx5_core_dev *dev, u32 max_wait_mili) { @@ -934,6 +935,15 @@ static int mlx5_load_one(struct mlx5_core_dev *dev, struct mlx5_priv *priv) */ dev->state = MLX5_DEVICE_STATE_UP; + /* wait for firmware to accept initialization segments configurations + */ + err = wait_fw_init(dev, FW_PRE_INIT_TIMEOUT_MILI); + if (err) { + dev_err(&dev->pdev->dev, "Firmware over %d MS in pre-initializing state, aborting\n", + FW_PRE_INIT_TIMEOUT_MILI); + goto out; + } + err = mlx5_cmd_init(dev); if (err) { dev_err(&pdev->dev, "Failed initializing command interface, aborting\n"); diff --git a/drivers/net/ethernet/renesas/ravb_main.c b/drivers/net/ethernet/renesas/ravb_main.c index 1e61d4da72db..585e90f8341d 100644 --- a/drivers/net/ethernet/renesas/ravb_main.c +++ b/drivers/net/ethernet/renesas/ravb_main.c @@ -221,18 +221,6 @@ static void ravb_ring_free(struct net_device *ndev, int q) int ring_size; int i; - /* Free RX skb ringbuffer */ - if (priv->rx_skb[q]) { - for (i = 0; i < priv->num_rx_ring[q]; i++) - dev_kfree_skb(priv->rx_skb[q][i]); - } - kfree(priv->rx_skb[q]); - priv->rx_skb[q] = NULL; - - /* Free aligned TX buffers */ - kfree(priv->tx_align[q]); - priv->tx_align[q] = NULL; - if (priv->rx_ring[q]) { for (i = 0; i < priv->num_rx_ring[q]; i++) { struct ravb_ex_rx_desc *desc = &priv->rx_ring[q][i]; @@ -261,6 +249,18 @@ static void ravb_ring_free(struct net_device *ndev, int q) priv->tx_ring[q] = NULL; } + /* Free RX skb ringbuffer */ + if (priv->rx_skb[q]) { + for (i = 0; i < priv->num_rx_ring[q]; i++) + dev_kfree_skb(priv->rx_skb[q][i]); + } + kfree(priv->rx_skb[q]); + priv->rx_skb[q] = NULL; + + /* Free aligned TX buffers */ + kfree(priv->tx_align[q]); + priv->tx_align[q] = NULL; + /* Free TX skb ringbuffer. * SKBs are freed by ravb_tx_free() call above. */ diff --git a/drivers/net/ethernet/sfc/falcon.c b/drivers/net/ethernet/sfc/falcon.c index d790cb8d9db3..8e832ba8ab24 100644 --- a/drivers/net/ethernet/sfc/falcon.c +++ b/drivers/net/ethernet/sfc/falcon.c @@ -2796,6 +2796,11 @@ const struct efx_nic_type falcon_a1_nic_type = { .timer_period_max = 1 << FRF_AB_TC_TIMER_VAL_WIDTH, .offload_features = NETIF_F_IP_CSUM, .mcdi_max_ver = -1, +#ifdef CONFIG_SFC_SRIOV + .vswitching_probe = efx_port_dummy_op_int, + .vswitching_restore = efx_port_dummy_op_int, + .vswitching_remove = efx_port_dummy_op_void, +#endif }; const struct efx_nic_type falcon_b0_nic_type = { @@ -2897,4 +2902,9 @@ const struct efx_nic_type falcon_b0_nic_type = { .offload_features = NETIF_F_IP_CSUM | NETIF_F_RXHASH | NETIF_F_NTUPLE, .mcdi_max_ver = -1, .max_rx_ip_filters = FR_BZ_RX_FILTER_TBL0_ROWS, +#ifdef CONFIG_SFC_SRIOV + .vswitching_probe = efx_port_dummy_op_int, + .vswitching_restore = efx_port_dummy_op_int, + .vswitching_remove = efx_port_dummy_op_void, +#endif }; diff --git a/drivers/net/virtio_net.c b/drivers/net/virtio_net.c index 7f7c87762bc6..8dfc75250583 100644 --- a/drivers/net/virtio_net.c +++ b/drivers/net/virtio_net.c @@ -47,8 +47,16 @@ module_param(gso, bool, 0444); */ DECLARE_EWMA(pkt_len, 1, 64) +/* With mergeable buffers we align buffer address and use the low bits to + * encode its true size. Buffer size is up to 1 page so we need to align to + * square root of page size to ensure we reserve enough bits to encode the true + * size. + */ +#define MERGEABLE_BUFFER_MIN_ALIGN_SHIFT ((PAGE_SHIFT + 1) / 2) + /* Minimum alignment for mergeable packet buffers. */ -#define MERGEABLE_BUFFER_ALIGN max(L1_CACHE_BYTES, 256) +#define MERGEABLE_BUFFER_ALIGN max(L1_CACHE_BYTES, \ + 1 << MERGEABLE_BUFFER_MIN_ALIGN_SHIFT) #define VIRTNET_DRIVER_VERSION "1.0.0" diff --git a/drivers/net/vxlan.c b/drivers/net/vxlan.c index 9a986ccd42e5..dab3bf6649e6 100644 --- a/drivers/net/vxlan.c +++ b/drivers/net/vxlan.c @@ -2240,7 +2240,7 @@ static void vxlan_cleanup(unsigned long arg) = container_of(p, struct vxlan_fdb, hlist); unsigned long timeout; - if (f->state & NUD_PERMANENT) + if (f->state & (NUD_PERMANENT | NUD_NOARP)) continue; timeout = f->used + vxlan->cfg.age_interval * HZ; diff --git a/drivers/net/wireless/cnss2/main.c b/drivers/net/wireless/cnss2/main.c index 29bfe1f4d6ed..432960afe09a 100644 --- a/drivers/net/wireless/cnss2/main.c +++ b/drivers/net/wireless/cnss2/main.c @@ -37,6 +37,7 @@ #define FW_READY_TIMEOUT 20000 #define FW_ASSERT_TIMEOUT 5000 #define CNSS_EVENT_PENDING 2989 +#define WAKE_MSI_NAME "WAKE" static struct cnss_plat_data *plat_env; @@ -537,6 +538,24 @@ int cnss_set_fw_log_mode(struct device *dev, u8 fw_log_mode) } EXPORT_SYMBOL(cnss_set_fw_log_mode); +u32 cnss_get_wake_msi(struct cnss_plat_data *plat_priv) +{ + struct cnss_pci_data *pci_priv = plat_priv->bus_priv; + int ret, num_vectors; + u32 user_base_data, base_vector; + + ret = cnss_get_user_msi_assignment(&pci_priv->pci_dev->dev, + WAKE_MSI_NAME, &num_vectors, + &user_base_data, &base_vector); + + if (ret) { + cnss_pr_err("WAKE MSI is not valid\n"); + return 0; + } + + return user_base_data; +} + static int cnss_fw_mem_ready_hdlr(struct cnss_plat_data *plat_priv) { int ret = 0; @@ -573,7 +592,7 @@ static int cnss_driver_call_probe(struct cnss_plat_data *plat_priv) struct cnss_pci_data *pci_priv = plat_priv->bus_priv; if (!plat_priv->driver_ops) { - cnss_pr_err("driver_ops is NULL!"); + cnss_pr_err("driver_ops is NULL\n"); ret = -EINVAL; goto out; } @@ -587,7 +606,7 @@ static int cnss_driver_call_probe(struct cnss_plat_data *plat_priv) goto out; } clear_bit(CNSS_DRIVER_RECOVERY, &plat_priv->driver_state); - } else { + } else if (test_bit(CNSS_DRIVER_LOADING, &plat_priv->driver_state)) { ret = plat_priv->driver_ops->probe(pci_priv->pci_dev, pci_priv->pci_device_id); if (ret) { @@ -605,6 +624,25 @@ out: return ret; } +static int cnss_driver_call_remove(struct cnss_plat_data *plat_priv) +{ + struct cnss_pci_data *pci_priv = plat_priv->bus_priv; + + if (!plat_priv->driver_ops) { + cnss_pr_err("driver_ops is NULL\n"); + return -EINVAL; + } + + if (test_bit(CNSS_DRIVER_RECOVERY, &plat_priv->driver_state)) { + plat_priv->driver_ops->shutdown(pci_priv->pci_dev); + } else if (test_bit(CNSS_DRIVER_UNLOADING, &plat_priv->driver_state)) { + plat_priv->driver_ops->remove(pci_priv->pci_dev); + clear_bit(CNSS_DRIVER_PROBED, &plat_priv->driver_state); + } + + return 0; +} + static int cnss_fw_ready_hdlr(struct cnss_plat_data *plat_priv) { int ret = 0; @@ -626,8 +664,11 @@ static int cnss_fw_ready_hdlr(struct cnss_plat_data *plat_priv) } else if (test_bit(CNSS_COLD_BOOT_CAL, &plat_priv->driver_state)) { ret = cnss_wlfw_wlan_mode_send_sync(plat_priv, QMI_WLFW_CALIBRATION_V01); - } else { + } else if (test_bit(CNSS_DRIVER_LOADING, &plat_priv->driver_state) || + test_bit(CNSS_DRIVER_RECOVERY, &plat_priv->driver_state)) { ret = cnss_driver_call_probe(plat_priv); + } else { + complete(&plat_priv->power_up_complete); } if (ret) @@ -668,6 +709,10 @@ static char *cnss_driver_event_to_str(enum cnss_driver_event_type type) return "RECOVERY"; case CNSS_DRIVER_EVENT_FORCE_FW_ASSERT: return "FORCE_FW_ASSERT"; + case CNSS_DRIVER_EVENT_POWER_UP: + return "POWER_UP"; + case CNSS_DRIVER_EVENT_POWER_DOWN: + return "POWER_DOWN"; case CNSS_DRIVER_EVENT_MAX: return "EVENT_MAX"; } @@ -746,64 +791,57 @@ out: int cnss_power_up(struct device *dev) { int ret = 0; - void *bus_priv = cnss_bus_dev_to_bus_priv(dev); struct cnss_plat_data *plat_priv = cnss_bus_dev_to_plat_priv(dev); + unsigned int timeout; - if (!bus_priv || !plat_priv) + if (!plat_priv) { + cnss_pr_err("plat_priv is NULL\n"); return -ENODEV; - - if (plat_priv->device_id != QCA6174_DEVICE_ID) { - cnss_pr_dbg("Power up is not supported for device ID 0x%lx\n", - plat_priv->device_id); - return 0; } - ret = cnss_power_on_device(plat_priv); - if (ret) { - cnss_pr_err("Failed to power on device, err = %d\n", ret); - goto err_power_on; - } + cnss_pr_dbg("Powering up device\n"); - ret = cnss_resume_pci_link(bus_priv); - if (ret) { - cnss_pr_err("Failed to resume PCI link, err = %d\n", ret); - goto err_resume_link; + ret = cnss_driver_event_post(plat_priv, + CNSS_DRIVER_EVENT_POWER_UP, + true, NULL); + if (ret) + goto out; + + if (plat_priv->device_id == QCA6174_DEVICE_ID) + goto out; + + timeout = cnss_get_qmi_timeout(); + + reinit_completion(&plat_priv->power_up_complete); + ret = wait_for_completion_timeout(&plat_priv->power_up_complete, + msecs_to_jiffies(timeout) << 2); + if (!ret) { + cnss_pr_err("Timeout waiting for power up to complete\n"); + ret = -EAGAIN; + goto out; } return 0; -err_resume_link: - cnss_power_off_device(plat_priv); -err_power_on: + +out: return ret; } EXPORT_SYMBOL(cnss_power_up); int cnss_power_down(struct device *dev) { - int ret = 0; - void *bus_priv = cnss_bus_dev_to_bus_priv(dev); struct cnss_plat_data *plat_priv = cnss_bus_dev_to_plat_priv(dev); - if (!bus_priv || !plat_priv) + if (!plat_priv) { + cnss_pr_err("plat_priv is NULL\n"); return -ENODEV; - - if (plat_priv->device_id != QCA6174_DEVICE_ID) { - cnss_pr_dbg("Power down is not supported for device ID 0x%lx\n", - plat_priv->device_id); - return 0; } - cnss_request_bus_bandwidth(CNSS_BUS_WIDTH_NONE); - cnss_pci_set_monitor_wake_intr(bus_priv, false); - cnss_pci_set_auto_suspended(bus_priv, 0); + cnss_pr_dbg("Powering down device\n"); - ret = cnss_suspend_pci_link(bus_priv); - if (ret) - cnss_pr_err("Failed to suspend PCI link, err = %d\n", ret); - - cnss_power_off_device(plat_priv); - - return 0; + return cnss_driver_event_post(plat_priv, + CNSS_DRIVER_EVENT_POWER_DOWN, + true, NULL); } EXPORT_SYMBOL(cnss_power_down); @@ -1024,14 +1062,11 @@ static int cnss_qca6174_shutdown(struct cnss_plat_data *plat_priv) if (!plat_priv->driver_ops) return -EINVAL; - if (test_bit(CNSS_DRIVER_UNLOADING, &plat_priv->driver_state)) { - cnss_request_bus_bandwidth(CNSS_BUS_WIDTH_NONE); - plat_priv->driver_ops->remove(pci_priv->pci_dev); - cnss_pci_set_monitor_wake_intr(pci_priv, false); - cnss_pci_set_auto_suspended(pci_priv, 0); - } else { - plat_priv->driver_ops->shutdown(pci_priv->pci_dev); - } + cnss_driver_call_remove(plat_priv); + + cnss_request_bus_bandwidth(CNSS_BUS_WIDTH_NONE); + cnss_pci_set_monitor_wake_intr(pci_priv, false); + cnss_pci_set_auto_suspended(pci_priv, 0); ret = cnss_suspend_pci_link(pci_priv); if (ret) @@ -1039,10 +1074,7 @@ static int cnss_qca6174_shutdown(struct cnss_plat_data *plat_priv) cnss_power_off_device(plat_priv); - if (test_bit(CNSS_DRIVER_UNLOADING, &plat_priv->driver_state)) { - clear_bit(CNSS_DRIVER_UNLOADING, &plat_priv->driver_state); - clear_bit(CNSS_DRIVER_PROBED, &plat_priv->driver_state); - } + clear_bit(CNSS_DRIVER_UNLOADING, &plat_priv->driver_state); return ret; } @@ -1134,16 +1166,13 @@ static int cnss_qca6290_shutdown(struct cnss_plat_data *plat_priv) if (!plat_priv->driver_ops) return -EINVAL; - if (test_bit(CNSS_DRIVER_UNLOADING, &plat_priv->driver_state)) { - cnss_request_bus_bandwidth(CNSS_BUS_WIDTH_NONE); - plat_priv->driver_ops->remove(pci_priv->pci_dev); - cnss_pci_set_monitor_wake_intr(pci_priv, false); - cnss_pci_set_auto_suspended(pci_priv, 0); - } else { - plat_priv->driver_ops->shutdown(pci_priv->pci_dev); - } + cnss_driver_call_remove(plat_priv); skip_driver_remove: + cnss_request_bus_bandwidth(CNSS_BUS_WIDTH_NONE); + cnss_pci_set_monitor_wake_intr(pci_priv, false); + cnss_pci_set_auto_suspended(pci_priv, 0); + cnss_pci_stop_mhi(pci_priv); ret = cnss_suspend_pci_link(pci_priv); @@ -1154,11 +1183,7 @@ skip_driver_remove: clear_bit(CNSS_FW_READY, &plat_priv->driver_state); clear_bit(CNSS_FW_MEM_READY, &plat_priv->driver_state); - - if (test_bit(CNSS_DRIVER_UNLOADING, &plat_priv->driver_state)) { - clear_bit(CNSS_DRIVER_UNLOADING, &plat_priv->driver_state); - clear_bit(CNSS_DRIVER_PROBED, &plat_priv->driver_state); - } + clear_bit(CNSS_DRIVER_UNLOADING, &plat_priv->driver_state); return ret; } @@ -1661,6 +1686,22 @@ static int cnss_cold_boot_cal_done_hdlr(struct cnss_plat_data *plat_priv) return 0; } +static int cnss_power_up_hdlr(struct cnss_plat_data *plat_priv) +{ + struct cnss_subsys_info *subsys_info = &plat_priv->subsys_info; + + return cnss_powerup(&subsys_info->subsys_desc); +} + +static int cnss_power_down_hdlr(struct cnss_plat_data *plat_priv) +{ + struct cnss_subsys_info *subsys_info = &plat_priv->subsys_info; + + cnss_shutdown(&subsys_info->subsys_desc, false); + + return 0; +} + static void cnss_driver_event_work(struct work_struct *work) { struct cnss_plat_data *plat_priv = @@ -1728,6 +1769,12 @@ static void cnss_driver_event_work(struct work_struct *work) case CNSS_DRIVER_EVENT_FORCE_FW_ASSERT: ret = cnss_force_fw_assert_hdlr(plat_priv); break; + case CNSS_DRIVER_EVENT_POWER_UP: + ret = cnss_power_up_hdlr(plat_priv); + break; + case CNSS_DRIVER_EVENT_POWER_DOWN: + ret = cnss_power_down_hdlr(plat_priv); + break; default: cnss_pr_err("Invalid driver event type: %d", event->type); @@ -2226,6 +2273,8 @@ static int cnss_probe(struct platform_device *plat_dev) cnss_pr_err("Failed to init platform device wakeup source, err = %d\n", ret); + init_completion(&plat_priv->power_up_complete); + cnss_pr_info("Platform driver probed successfully.\n"); return 0; @@ -2257,6 +2306,7 @@ static int cnss_remove(struct platform_device *plat_dev) { struct cnss_plat_data *plat_priv = platform_get_drvdata(plat_dev); + complete_all(&plat_priv->power_up_complete); device_init_wakeup(&plat_dev->dev, false); unregister_pm_notifier(&cnss_pm_notifier); del_timer(&plat_priv->fw_boot_timer); diff --git a/drivers/net/wireless/cnss2/main.h b/drivers/net/wireless/cnss2/main.h index e3a8d0cccd52..a2d9a02bde20 100644 --- a/drivers/net/wireless/cnss2/main.h +++ b/drivers/net/wireless/cnss2/main.h @@ -126,6 +126,8 @@ enum cnss_driver_event_type { CNSS_DRIVER_EVENT_UNREGISTER_DRIVER, CNSS_DRIVER_EVENT_RECOVERY, CNSS_DRIVER_EVENT_FORCE_FW_ASSERT, + CNSS_DRIVER_EVENT_POWER_UP, + CNSS_DRIVER_EVENT_POWER_DOWN, CNSS_DRIVER_EVENT_MAX, }; @@ -201,6 +203,7 @@ struct cnss_plat_data { struct dentry *root_dentry; atomic_t pm_count; struct timer_list fw_boot_timer; + struct completion power_up_complete; }; void *cnss_bus_dev_to_bus_priv(struct device *dev); @@ -217,5 +220,6 @@ void cnss_unregister_subsys(struct cnss_plat_data *plat_priv); int cnss_register_ramdump(struct cnss_plat_data *plat_priv); void cnss_unregister_ramdump(struct cnss_plat_data *plat_priv); void cnss_set_pin_connect_status(struct cnss_plat_data *plat_priv); +u32 cnss_get_wake_msi(struct cnss_plat_data *plat_priv); #endif /* _CNSS_MAIN_H */ diff --git a/drivers/net/wireless/cnss2/pci.c b/drivers/net/wireless/cnss2/pci.c index f914f4352392..a17b72ce03ba 100644 --- a/drivers/net/wireless/cnss2/pci.c +++ b/drivers/net/wireless/cnss2/pci.c @@ -143,6 +143,12 @@ int cnss_suspend_pci_link(struct cnss_pci_data *pci_priv) if (ret) goto out; + pci_disable_device(pci_priv->pci_dev); + + ret = pci_set_power_state(pci_priv->pci_dev, PCI_D3hot); + if (ret) + cnss_pr_err("Failed to set D3Hot, err = %d\n", ret); + ret = cnss_set_pci_link(pci_priv, PCI_LINK_DOWN); if (ret) goto out; @@ -172,10 +178,18 @@ int cnss_resume_pci_link(struct cnss_pci_data *pci_priv) pci_priv->pci_link_state = PCI_LINK_UP; + ret = pci_enable_device(pci_priv->pci_dev); + if (ret) { + cnss_pr_err("Failed to enable PCI device, err = %d\n", ret); + goto out; + } + ret = cnss_set_pci_config_space(pci_priv, RESTORE_PCI_CONFIG_SPACE); if (ret) goto out; + pci_set_master(pci_priv->pci_dev); + if (pci_priv->pci_link_down_ind) pci_priv->pci_link_down_ind = false; @@ -381,6 +395,12 @@ static int cnss_pci_suspend(struct device *dev) cnss_set_pci_config_space(pci_priv, SAVE_PCI_CONFIG_SPACE); + pci_disable_device(pci_dev); + + ret = pci_set_power_state(pci_dev, PCI_D3hot); + if (ret) + cnss_pr_err("Failed to set D3Hot, err = %d\n", + ret); } } @@ -407,10 +427,18 @@ static int cnss_pci_resume(struct device *dev) driver_ops = plat_priv->driver_ops; if (driver_ops && driver_ops->resume && !pci_priv->pci_link_down_ind) { + ret = pci_enable_device(pci_dev); + if (ret) + cnss_pr_err("Failed to enable PCI device, err = %d\n", + ret); + if (pci_priv->saved_state) cnss_set_pci_config_space(pci_priv, RESTORE_PCI_CONFIG_SPACE); + + pci_set_master(pci_dev); cnss_pci_set_mhi_state(pci_priv, CNSS_MHI_RESUME); + ret = driver_ops->resume(pci_dev); } diff --git a/drivers/net/wireless/cnss2/qmi.c b/drivers/net/wireless/cnss2/qmi.c index db55d3350eb5..99163d51a497 100644 --- a/drivers/net/wireless/cnss2/qmi.c +++ b/drivers/net/wireless/cnss2/qmi.c @@ -140,6 +140,12 @@ static int cnss_wlfw_host_cap_send_sync(struct cnss_plat_data *plat_priv) cnss_pr_dbg("daemon_support is %d\n", req.daemon_support); + req.wake_msi = cnss_get_wake_msi(plat_priv); + if (req.wake_msi) { + cnss_pr_dbg("WAKE MSI base data is %d\n", req.wake_msi); + req.wake_msi_valid = 1; + } + req_desc.max_msg_len = WLFW_HOST_CAP_REQ_MSG_V01_MAX_MSG_LEN; req_desc.msg_id = QMI_WLFW_HOST_CAP_REQ_V01; req_desc.ei_array = wlfw_host_cap_req_msg_v01_ei; diff --git a/drivers/net/wireless/cnss2/wlan_firmware_service_v01.c b/drivers/net/wireless/cnss2/wlan_firmware_service_v01.c index 84a4707e9cc3..7d6a771bc0d5 100644 --- a/drivers/net/wireless/cnss2/wlan_firmware_service_v01.c +++ b/drivers/net/wireless/cnss2/wlan_firmware_service_v01.c @@ -1097,6 +1097,24 @@ struct elem_info wlfw_cal_report_req_msg_v01_ei[] = { meta_data), }, { + .data_type = QMI_OPT_FLAG, + .elem_len = 1, + .elem_size = sizeof(u8), + .is_array = NO_ARRAY, + .tlv_type = 0x10, + .offset = offsetof(struct wlfw_cal_report_req_msg_v01, + xo_cal_data_valid), + }, + { + .data_type = QMI_UNSIGNED_1_BYTE, + .elem_len = 1, + .elem_size = sizeof(u8), + .is_array = NO_ARRAY, + .tlv_type = 0x10, + .offset = offsetof(struct wlfw_cal_report_req_msg_v01, + xo_cal_data), + }, + { .data_type = QMI_EOTI, .is_array = NO_ARRAY, .is_array = QMI_COMMON_TLV_TYPE, @@ -1828,6 +1846,24 @@ struct elem_info wlfw_host_cap_req_msg_v01_ei[] = { daemon_support), }, { + .data_type = QMI_OPT_FLAG, + .elem_len = 1, + .elem_size = sizeof(u8), + .is_array = NO_ARRAY, + .tlv_type = 0x11, + .offset = offsetof(struct wlfw_host_cap_req_msg_v01, + wake_msi_valid), + }, + { + .data_type = QMI_UNSIGNED_4_BYTE, + .elem_len = 1, + .elem_size = sizeof(u32), + .is_array = NO_ARRAY, + .tlv_type = 0x11, + .offset = offsetof(struct wlfw_host_cap_req_msg_v01, + wake_msi), + }, + { .data_type = QMI_EOTI, .is_array = NO_ARRAY, .is_array = QMI_COMMON_TLV_TYPE, @@ -2166,3 +2202,20 @@ struct elem_info wlfw_m3_info_resp_msg_v01_ei[] = { .is_array = QMI_COMMON_TLV_TYPE, }, }; + +struct elem_info wlfw_xo_cal_ind_msg_v01_ei[] = { + { + .data_type = QMI_UNSIGNED_1_BYTE, + .elem_len = 1, + .elem_size = sizeof(u8), + .is_array = NO_ARRAY, + .tlv_type = 0x01, + .offset = offsetof(struct wlfw_xo_cal_ind_msg_v01, + xo_cal_data), + }, + { + .data_type = QMI_EOTI, + .is_array = NO_ARRAY, + .is_array = QMI_COMMON_TLV_TYPE, + }, +}; diff --git a/drivers/net/wireless/cnss2/wlan_firmware_service_v01.h b/drivers/net/wireless/cnss2/wlan_firmware_service_v01.h index cb8225a7c3c3..a3081433cc2b 100644 --- a/drivers/net/wireless/cnss2/wlan_firmware_service_v01.h +++ b/drivers/net/wireless/cnss2/wlan_firmware_service_v01.h @@ -31,6 +31,7 @@ #define QMI_WLFW_M3_INFO_RESP_V01 0x003C #define QMI_WLFW_CAL_UPDATE_RESP_V01 0x0029 #define QMI_WLFW_CAL_DOWNLOAD_RESP_V01 0x0027 +#define QMI_WLFW_XO_CAL_IND_V01 0x003D #define QMI_WLFW_INI_RESP_V01 0x002F #define QMI_WLFW_CAL_REPORT_RESP_V01 0x0026 #define QMI_WLFW_MAC_ADDR_RESP_V01 0x0033 @@ -339,9 +340,11 @@ extern struct elem_info wlfw_bdf_download_resp_msg_v01_ei[]; struct wlfw_cal_report_req_msg_v01 { u32 meta_data_len; enum wlfw_cal_temp_id_enum_v01 meta_data[QMI_WLFW_MAX_NUM_CAL_V01]; + u8 xo_cal_data_valid; + u8 xo_cal_data; }; -#define WLFW_CAL_REPORT_REQ_MSG_V01_MAX_MSG_LEN 24 +#define WLFW_CAL_REPORT_REQ_MSG_V01_MAX_MSG_LEN 28 extern struct elem_info wlfw_cal_report_req_msg_v01_ei[]; struct wlfw_cal_report_resp_msg_v01 { @@ -532,9 +535,11 @@ extern struct elem_info wlfw_mac_addr_resp_msg_v01_ei[]; struct wlfw_host_cap_req_msg_v01 { u8 daemon_support_valid; u8 daemon_support; + u8 wake_msi_valid; + u32 wake_msi; }; -#define WLFW_HOST_CAP_REQ_MSG_V01_MAX_MSG_LEN 4 +#define WLFW_HOST_CAP_REQ_MSG_V01_MAX_MSG_LEN 11 extern struct elem_info wlfw_host_cap_req_msg_v01_ei[]; struct wlfw_host_cap_resp_msg_v01 { @@ -642,4 +647,11 @@ struct wlfw_m3_info_resp_msg_v01 { #define WLFW_M3_INFO_RESP_MSG_V01_MAX_MSG_LEN 7 extern struct elem_info wlfw_m3_info_resp_msg_v01_ei[]; +struct wlfw_xo_cal_ind_msg_v01 { + u8 xo_cal_data; +}; + +#define WLFW_XO_CAL_IND_MSG_V01_MAX_MSG_LEN 4 +extern struct elem_info wlfw_xo_cal_ind_msg_v01_ei[]; + #endif diff --git a/drivers/net/xen-netfront.c b/drivers/net/xen-netfront.c index 888e9cfef51a..34a062ccb11d 100644 --- a/drivers/net/xen-netfront.c +++ b/drivers/net/xen-netfront.c @@ -321,7 +321,7 @@ static void xennet_alloc_rx_buffers(struct netfront_queue *queue) queue->rx.req_prod_pvt = req_prod; /* Not enough requests? Try again later. */ - if (req_prod - queue->rx.rsp_cons < NET_RX_SLOTS_MIN) { + if (req_prod - queue->rx.sring->req_prod < NET_RX_SLOTS_MIN) { mod_timer(&queue->rx_refill_timer, jiffies + (HZ/10)); return; } diff --git a/drivers/platform/msm/Kconfig b/drivers/platform/msm/Kconfig index 66bdc593f811..333d28e64087 100644 --- a/drivers/platform/msm/Kconfig +++ b/drivers/platform/msm/Kconfig @@ -194,7 +194,7 @@ config MSM_11AD tristate "Platform driver for 11ad chip" depends on PCI depends on PCI_MSM - default y + default m ---help--- This module adds required platform support for wireless adapter based on Qualcomm Technologies, Inc. 11ad chip, integrated into MSM platform diff --git a/drivers/platform/msm/ipa/ipa_v2/ipa.c b/drivers/platform/msm/ipa/ipa_v2/ipa.c index 0d17fa58a853..85fa9da50779 100644 --- a/drivers/platform/msm/ipa/ipa_v2/ipa.c +++ b/drivers/platform/msm/ipa/ipa_v2/ipa.c @@ -641,7 +641,7 @@ static long ipa_ioctl(struct file *filp, unsigned int cmd, unsigned long arg) /* add check in case user-space module compromised */ if (unlikely(((struct ipa_ioc_nat_dma_cmd *)param)->entries != pre_entry)) { - IPAERR("current %d pre %d\n", + IPAERR_RL("current %d pre %d\n", ((struct ipa_ioc_nat_dma_cmd *)param)->entries, pre_entry); retval = -EFAULT; @@ -688,7 +688,7 @@ static long ipa_ioctl(struct file *filp, unsigned int cmd, unsigned long arg) /* add check in case user-space module compromised */ if (unlikely(((struct ipa_ioc_add_hdr *)param)->num_hdrs != pre_entry)) { - IPAERR("current %d pre %d\n", + IPAERR_RL("current %d pre %d\n", ((struct ipa_ioc_add_hdr *)param)->num_hdrs, pre_entry); retval = -EFAULT; @@ -727,7 +727,7 @@ static long ipa_ioctl(struct file *filp, unsigned int cmd, unsigned long arg) /* add check in case user-space module compromised */ if (unlikely(((struct ipa_ioc_del_hdr *)param)->num_hdls != pre_entry)) { - IPAERR("current %d pre %d\n", + IPAERR_RL("current %d pre %d\n", ((struct ipa_ioc_del_hdr *)param)->num_hdls, pre_entry); retval = -EFAULT; @@ -767,7 +767,7 @@ static long ipa_ioctl(struct file *filp, unsigned int cmd, unsigned long arg) /* add check in case user-space module compromised */ if (unlikely(((struct ipa_ioc_add_rt_rule *)param)->num_rules != pre_entry)) { - IPAERR("current %d pre %d\n", + IPAERR_RL("current %d pre %d\n", ((struct ipa_ioc_add_rt_rule *)param)-> num_rules, pre_entry); @@ -807,7 +807,7 @@ static long ipa_ioctl(struct file *filp, unsigned int cmd, unsigned long arg) /* add check in case user-space module compromised */ if (unlikely(((struct ipa_ioc_mdfy_rt_rule *)param)->num_rules != pre_entry)) { - IPAERR("current %d pre %d\n", + IPAERR_RL("current %d pre %d\n", ((struct ipa_ioc_mdfy_rt_rule *)param)-> num_rules, pre_entry); @@ -847,7 +847,7 @@ static long ipa_ioctl(struct file *filp, unsigned int cmd, unsigned long arg) /* add check in case user-space module compromised */ if (unlikely(((struct ipa_ioc_del_rt_rule *)param)->num_hdls != pre_entry)) { - IPAERR("current %d pre %d\n", + IPAERR_RL("current %d pre %d\n", ((struct ipa_ioc_del_rt_rule *)param)->num_hdls, pre_entry); retval = -EFAULT; @@ -886,7 +886,7 @@ static long ipa_ioctl(struct file *filp, unsigned int cmd, unsigned long arg) /* add check in case user-space module compromised */ if (unlikely(((struct ipa_ioc_add_flt_rule *)param)->num_rules != pre_entry)) { - IPAERR("current %d pre %d\n", + IPAERR_RL("current %d pre %d\n", ((struct ipa_ioc_add_flt_rule *)param)-> num_rules, pre_entry); @@ -926,7 +926,7 @@ static long ipa_ioctl(struct file *filp, unsigned int cmd, unsigned long arg) /* add check in case user-space module compromised */ if (unlikely(((struct ipa_ioc_del_flt_rule *)param)->num_hdls != pre_entry)) { - IPAERR("current %d pre %d\n", + IPAERR_RL("current %d pre %d\n", ((struct ipa_ioc_del_flt_rule *)param)-> num_hdls, pre_entry); @@ -966,7 +966,7 @@ static long ipa_ioctl(struct file *filp, unsigned int cmd, unsigned long arg) /* add check in case user-space module compromised */ if (unlikely(((struct ipa_ioc_mdfy_flt_rule *)param)->num_rules != pre_entry)) { - IPAERR("current %d pre %d\n", + IPAERR_RL("current %d pre %d\n", ((struct ipa_ioc_mdfy_flt_rule *)param)-> num_rules, pre_entry); @@ -1104,7 +1104,7 @@ static long ipa_ioctl(struct file *filp, unsigned int cmd, unsigned long arg) if (unlikely(((struct ipa_ioc_query_intf_tx_props *) param)->num_tx_props != pre_entry)) { - IPAERR("current %d pre %d\n", + IPAERR_RL("current %d pre %d\n", ((struct ipa_ioc_query_intf_tx_props *) param)->num_tx_props, pre_entry); retval = -EFAULT; @@ -1149,7 +1149,7 @@ static long ipa_ioctl(struct file *filp, unsigned int cmd, unsigned long arg) /* add check in case user-space module compromised */ if (unlikely(((struct ipa_ioc_query_intf_rx_props *) param)->num_rx_props != pre_entry)) { - IPAERR("current %d pre %d\n", + IPAERR_RL("current %d pre %d\n", ((struct ipa_ioc_query_intf_rx_props *) param)->num_rx_props, pre_entry); retval = -EFAULT; @@ -1194,7 +1194,7 @@ static long ipa_ioctl(struct file *filp, unsigned int cmd, unsigned long arg) /* add check in case user-space module compromised */ if (unlikely(((struct ipa_ioc_query_intf_ext_props *) param)->num_ext_props != pre_entry)) { - IPAERR("current %d pre %d\n", + IPAERR_RL("current %d pre %d\n", ((struct ipa_ioc_query_intf_ext_props *) param)->num_ext_props, pre_entry); retval = -EFAULT; @@ -1232,7 +1232,7 @@ static long ipa_ioctl(struct file *filp, unsigned int cmd, unsigned long arg) /* add check in case user-space module compromised */ if (unlikely(((struct ipa_msg_meta *)param)->msg_len != pre_entry)) { - IPAERR("current %d pre %d\n", + IPAERR_RL("current %d pre %d\n", ((struct ipa_msg_meta *)param)->msg_len, pre_entry); retval = -EFAULT; @@ -1372,7 +1372,7 @@ static long ipa_ioctl(struct file *filp, unsigned int cmd, unsigned long arg) /* add check in case user-space module compromised */ if (unlikely(((struct ipa_ioc_add_hdr_proc_ctx *) param)->num_proc_ctxs != pre_entry)) { - IPAERR("current %d pre %d\n", + IPAERR_RL("current %d pre %d\n", ((struct ipa_ioc_add_hdr_proc_ctx *) param)->num_proc_ctxs, pre_entry); retval = -EFAULT; @@ -1411,7 +1411,7 @@ static long ipa_ioctl(struct file *filp, unsigned int cmd, unsigned long arg) /* add check in case user-space module compromised */ if (unlikely(((struct ipa_ioc_del_hdr_proc_ctx *) param)->num_hdls != pre_entry)) { - IPAERR("current %d pre %d\n", + IPAERR_RL("current %d pre %d\n", ((struct ipa_ioc_del_hdr_proc_ctx *)param)-> num_hdls, pre_entry); diff --git a/drivers/platform/msm/ipa/ipa_v2/ipa_flt.c b/drivers/platform/msm/ipa/ipa_v2/ipa_flt.c index 80514f6c738e..72542bf6dd5d 100644 --- a/drivers/platform/msm/ipa/ipa_v2/ipa_flt.c +++ b/drivers/platform/msm/ipa/ipa_v2/ipa_flt.c @@ -1017,25 +1017,25 @@ static int __ipa_add_flt_rule(struct ipa_flt_tbl *tbl, enum ipa_ip_type ip, if (rule->action != IPA_PASS_TO_EXCEPTION) { if (!rule->eq_attrib_type) { if (!rule->rt_tbl_hdl) { - IPAERR("invalid RT tbl\n"); + IPAERR_RL("invalid RT tbl\n"); goto error; } rt_tbl = ipa_id_find(rule->rt_tbl_hdl); if (rt_tbl == NULL) { - IPAERR("RT tbl not found\n"); + IPAERR_RL("RT tbl not found\n"); goto error; } - if (rt_tbl->cookie != IPA_COOKIE) { - IPAERR("RT table cookie is invalid\n"); + if (rt_tbl->cookie != IPA_RT_TBL_COOKIE) { + IPAERR_RL("RT table cookie is invalid\n"); goto error; } } else { if (rule->rt_tbl_idx > ((ip == IPA_IP_v4) ? IPA_MEM_PART(v4_modem_rt_index_hi) : IPA_MEM_PART(v6_modem_rt_index_hi))) { - IPAERR("invalid RT tbl\n"); + IPAERR_RL("invalid RT tbl\n"); goto error; } } @@ -1048,7 +1048,7 @@ static int __ipa_add_flt_rule(struct ipa_flt_tbl *tbl, enum ipa_ip_type ip, } INIT_LIST_HEAD(&entry->link); entry->rule = *rule; - entry->cookie = IPA_COOKIE; + entry->cookie = IPA_FLT_COOKIE; entry->rt_tbl = rt_tbl; entry->tbl = tbl; if (add_rear) { @@ -1067,13 +1067,19 @@ static int __ipa_add_flt_rule(struct ipa_flt_tbl *tbl, enum ipa_ip_type ip, if (id < 0) { IPAERR("failed to add to tree\n"); WARN_ON(1); + goto ipa_insert_failed; } *rule_hdl = id; entry->id = id; IPADBG_LOW("add flt rule rule_cnt=%d\n", tbl->rule_cnt); return 0; - +ipa_insert_failed: + tbl->rule_cnt--; + if (entry->rt_tbl) + entry->rt_tbl->ref_cnt--; + list_del(&entry->link); + kmem_cache_free(ipa_ctx->flt_rule_cache, entry); error: return -EPERM; } @@ -1085,12 +1091,12 @@ static int __ipa_del_flt_rule(u32 rule_hdl) entry = ipa_id_find(rule_hdl); if (entry == NULL) { - IPAERR("lookup failed\n"); + IPAERR_RL("lookup failed\n"); return -EINVAL; } - if (entry->cookie != IPA_COOKIE) { - IPAERR("bad params\n"); + if (entry->cookie != IPA_FLT_COOKIE) { + IPAERR_RL("bad params\n"); return -EINVAL; } id = entry->id; @@ -1117,12 +1123,12 @@ static int __ipa_mdfy_flt_rule(struct ipa_flt_rule_mdfy *frule, entry = ipa_id_find(frule->rule_hdl); if (entry == NULL) { - IPAERR("lookup failed\n"); + IPAERR_RL("lookup failed\n"); goto error; } - if (entry->cookie != IPA_COOKIE) { - IPAERR("bad params\n"); + if (entry->cookie != IPA_FLT_COOKIE) { + IPAERR_RL("bad params\n"); goto error; } @@ -1132,25 +1138,25 @@ static int __ipa_mdfy_flt_rule(struct ipa_flt_rule_mdfy *frule, if (frule->rule.action != IPA_PASS_TO_EXCEPTION) { if (!frule->rule.eq_attrib_type) { if (!frule->rule.rt_tbl_hdl) { - IPAERR("invalid RT tbl\n"); + IPAERR_RL("invalid RT tbl\n"); goto error; } rt_tbl = ipa_id_find(frule->rule.rt_tbl_hdl); if (rt_tbl == NULL) { - IPAERR("RT tbl not found\n"); + IPAERR_RL("RT tbl not found\n"); goto error; } - if (rt_tbl->cookie != IPA_COOKIE) { - IPAERR("RT table cookie is invalid\n"); + if (rt_tbl->cookie != IPA_RT_TBL_COOKIE) { + IPAERR_RL("RT table cookie is invalid\n"); goto error; } } else { if (frule->rule.rt_tbl_idx > ((ip == IPA_IP_v4) ? IPA_MEM_PART(v4_modem_rt_index_hi) : IPA_MEM_PART(v6_modem_rt_index_hi))) { - IPAERR("invalid RT tbl\n"); + IPAERR_RL("invalid RT tbl\n"); goto error; } } @@ -1174,7 +1180,7 @@ static int __ipa_add_global_flt_rule(enum ipa_ip_type ip, struct ipa_flt_tbl *tbl; if (rule == NULL || rule_hdl == NULL) { - IPAERR("bad parms rule=%p rule_hdl=%p\n", rule, rule_hdl); + IPAERR_RL("bad parms rule=%p rule_hdl=%p\n", rule, rule_hdl); return -EINVAL; } @@ -1193,14 +1199,14 @@ static int __ipa_add_ep_flt_rule(enum ipa_ip_type ip, enum ipa_client_type ep, int ipa_ep_idx; if (rule == NULL || rule_hdl == NULL || ep >= IPA_CLIENT_MAX) { - IPAERR("bad parms rule=%p rule_hdl=%p ep=%d\n", rule, + IPAERR_RL("bad parms rule=%p rule_hdl=%p ep=%d\n", rule, rule_hdl, ep); return -EINVAL; } ipa_ep_idx = ipa2_get_ep_mapping(ep); if (ipa_ep_idx == IPA_FLT_TABLE_INDEX_NOT_FOUND) { - IPAERR("ep not valid ep=%d\n", ep); + IPAERR_RL("ep not valid ep=%d\n", ep); return -EINVAL; } if (ipa_ctx->ep[ipa_ep_idx].valid == 0) @@ -1227,7 +1233,7 @@ int ipa2_add_flt_rule(struct ipa_ioc_add_flt_rule *rules) if (rules == NULL || rules->num_rules == 0 || rules->ip >= IPA_IP_MAX) { - IPAERR("bad parm\n"); + IPAERR_RL("bad parm\n"); return -EINVAL; } @@ -1245,7 +1251,7 @@ int ipa2_add_flt_rule(struct ipa_ioc_add_flt_rule *rules) rules->rules[i].at_rear, &rules->rules[i].flt_rule_hdl); if (result) { - IPAERR("failed to add flt rule %d\n", i); + IPAERR_RL("failed to add flt rule %d\n", i); rules->rules[i].status = IPA_FLT_STATUS_OF_ADD_FAILED; } else { rules->rules[i].status = 0; @@ -1278,14 +1284,14 @@ int ipa2_del_flt_rule(struct ipa_ioc_del_flt_rule *hdls) int result; if (hdls == NULL || hdls->num_hdls == 0 || hdls->ip >= IPA_IP_MAX) { - IPAERR("bad parm\n"); + IPAERR_RL("bad parm\n"); return -EINVAL; } mutex_lock(&ipa_ctx->lock); for (i = 0; i < hdls->num_hdls; i++) { if (__ipa_del_flt_rule(hdls->hdl[i].hdl)) { - IPAERR("failed to del rt rule %i\n", i); + IPAERR_RL("failed to del rt rule %i\n", i); hdls->hdl[i].status = IPA_FLT_STATUS_OF_DEL_FAILED; } else { hdls->hdl[i].status = 0; @@ -1318,14 +1324,14 @@ int ipa2_mdfy_flt_rule(struct ipa_ioc_mdfy_flt_rule *hdls) int result; if (hdls == NULL || hdls->num_rules == 0 || hdls->ip >= IPA_IP_MAX) { - IPAERR("bad parm\n"); + IPAERR_RL("bad parm\n"); return -EINVAL; } mutex_lock(&ipa_ctx->lock); for (i = 0; i < hdls->num_rules; i++) { if (__ipa_mdfy_flt_rule(&hdls->rules[i], hdls->ip)) { - IPAERR("failed to mdfy rt rule %i\n", i); + IPAERR_RL("failed to mdfy rt rule %i\n", i); hdls->rules[i].status = IPA_FLT_STATUS_OF_MDFY_FAILED; } else { hdls->rules[i].status = 0; @@ -1359,7 +1365,7 @@ int ipa2_commit_flt(enum ipa_ip_type ip) int result; if (ip >= IPA_IP_MAX) { - IPAERR("bad parm\n"); + IPAERR_RL("bad parm\n"); return -EINVAL; } @@ -1395,7 +1401,7 @@ int ipa2_reset_flt(enum ipa_ip_type ip) int id; if (ip >= IPA_IP_MAX) { - IPAERR("bad parm\n"); + IPAERR_RL("bad parm\n"); return -EINVAL; } diff --git a/drivers/platform/msm/ipa/ipa_v2/ipa_hdr.c b/drivers/platform/msm/ipa/ipa_v2/ipa_hdr.c index 10a49b1e75d8..51806cec1e4d 100644 --- a/drivers/platform/msm/ipa/ipa_v2/ipa_hdr.c +++ b/drivers/platform/msm/ipa/ipa_v2/ipa_hdr.c @@ -547,7 +547,7 @@ static int __ipa_add_hdr_proc_ctx(struct ipa_hdr_proc_ctx_add *proc_ctx, { struct ipa_hdr_entry *hdr_entry; struct ipa_hdr_proc_ctx_entry *entry; - struct ipa_hdr_proc_ctx_offset_entry *offset; + struct ipa_hdr_proc_ctx_offset_entry *offset = NULL; u32 bin; struct ipa_hdr_proc_ctx_tbl *htbl = &ipa_ctx->hdr_proc_ctx_tbl; int id; @@ -558,13 +558,13 @@ static int __ipa_add_hdr_proc_ctx(struct ipa_hdr_proc_ctx_add *proc_ctx, proc_ctx->type, proc_ctx->hdr_hdl); if (!HDR_PROC_TYPE_IS_VALID(proc_ctx->type)) { - IPAERR("invalid processing type %d\n", proc_ctx->type); + IPAERR_RL("invalid processing type %d\n", proc_ctx->type); return -EINVAL; } hdr_entry = ipa_id_find(proc_ctx->hdr_hdl); - if (!hdr_entry || (hdr_entry->cookie != IPA_COOKIE)) { - IPAERR("hdr_hdl is invalid\n"); + if (!hdr_entry || (hdr_entry->cookie != IPA_HDR_COOKIE)) { + IPAERR_RL("hdr_hdl is invalid\n"); return -EINVAL; } @@ -580,7 +580,7 @@ static int __ipa_add_hdr_proc_ctx(struct ipa_hdr_proc_ctx_add *proc_ctx, entry->hdr = hdr_entry; if (add_ref_hdr) hdr_entry->ref_cnt++; - entry->cookie = IPA_COOKIE; + entry->cookie = IPA_PROC_HDR_COOKIE; needed_len = (proc_ctx->type == IPA_HDR_PROC_NONE) ? sizeof(struct ipa_hdr_proc_ctx_add_hdr_seq) : @@ -592,7 +592,7 @@ static int __ipa_add_hdr_proc_ctx(struct ipa_hdr_proc_ctx_add *proc_ctx, ipa_hdr_proc_ctx_bin_sz[IPA_HDR_PROC_CTX_BIN1]) { bin = IPA_HDR_PROC_CTX_BIN1; } else { - IPAERR("unexpected needed len %d\n", needed_len); + IPAERR_RL("unexpected needed len %d\n", needed_len); WARN_ON(1); goto bad_len; } @@ -602,7 +602,7 @@ static int __ipa_add_hdr_proc_ctx(struct ipa_hdr_proc_ctx_add *proc_ctx, IPA_MEM_PART(apps_hdr_proc_ctx_size_ddr); if (list_empty(&htbl->head_free_offset_list[bin])) { if (htbl->end + ipa_hdr_proc_ctx_bin_sz[bin] > mem_size) { - IPAERR("hdr proc ctx table overflow\n"); + IPAERR_RL("hdr proc ctx table overflow\n"); goto bad_len; } @@ -640,6 +640,7 @@ static int __ipa_add_hdr_proc_ctx(struct ipa_hdr_proc_ctx_add *proc_ctx, if (id < 0) { IPAERR("failed to alloc id\n"); WARN_ON(1); + goto ipa_insert_failed; } entry->id = id; proc_ctx->proc_ctx_hdl = id; @@ -647,6 +648,14 @@ static int __ipa_add_hdr_proc_ctx(struct ipa_hdr_proc_ctx_add *proc_ctx, return 0; +ipa_insert_failed: + if (offset) + list_move(&offset->link, + &htbl->head_free_offset_list[offset->bin]); + entry->offset_entry = NULL; + list_del(&entry->link); + htbl->proc_ctx_cnt--; + bad_len: if (add_ref_hdr) hdr_entry->ref_cnt--; @@ -659,7 +668,7 @@ bad_len: static int __ipa_add_hdr(struct ipa_hdr_add *hdr) { struct ipa_hdr_entry *entry; - struct ipa_hdr_offset_entry *offset; + struct ipa_hdr_offset_entry *offset = NULL; u32 bin; struct ipa_hdr_tbl *htbl = &ipa_ctx->hdr_tbl; int id; @@ -667,12 +676,12 @@ static int __ipa_add_hdr(struct ipa_hdr_add *hdr) gfp_t flag = GFP_KERNEL | (ipa_ctx->use_dma_zone ? GFP_DMA : 0); if (hdr->hdr_len == 0 || hdr->hdr_len > IPA_HDR_MAX_SIZE) { - IPAERR("bad parm\n"); + IPAERR_RL("bad parm\n"); goto error; } if (!HDR_TYPE_IS_VALID(hdr->type)) { - IPAERR("invalid hdr type %d\n", hdr->type); + IPAERR_RL("invalid hdr type %d\n", hdr->type); goto error; } @@ -691,7 +700,7 @@ static int __ipa_add_hdr(struct ipa_hdr_add *hdr) entry->type = hdr->type; entry->is_eth2_ofst_valid = hdr->is_eth2_ofst_valid; entry->eth2_ofst = hdr->eth2_ofst; - entry->cookie = IPA_COOKIE; + entry->cookie = IPA_HDR_COOKIE; if (hdr->hdr_len <= ipa_hdr_bin_sz[IPA_HDR_BIN0]) bin = IPA_HDR_BIN0; @@ -704,7 +713,7 @@ static int __ipa_add_hdr(struct ipa_hdr_add *hdr) else if (hdr->hdr_len <= ipa_hdr_bin_sz[IPA_HDR_BIN4]) bin = IPA_HDR_BIN4; else { - IPAERR("unexpected hdr len %d\n", hdr->hdr_len); + IPAERR_RL("unexpected hdr len %d\n", hdr->hdr_len); goto bad_hdr_len; } @@ -780,6 +789,7 @@ static int __ipa_add_hdr(struct ipa_hdr_add *hdr) if (id < 0) { IPAERR("failed to alloc id\n"); WARN_ON(1); + goto ipa_insert_failed; } entry->id = id; hdr->hdr_hdl = id; @@ -804,10 +814,19 @@ fail_add_proc_ctx: entry->ref_cnt--; hdr->hdr_hdl = 0; ipa_id_remove(id); +ipa_insert_failed: + if (entry->is_hdr_proc_ctx) { + dma_unmap_single(ipa_ctx->pdev, entry->phys_base, + entry->hdr_len, DMA_TO_DEVICE); + } else { + if (offset) + list_move(&offset->link, + &htbl->head_free_offset_list[offset->bin]); + entry->offset_entry = NULL; + } htbl->hdr_cnt--; list_del(&entry->link); - dma_unmap_single(ipa_ctx->pdev, entry->phys_base, - entry->hdr_len, DMA_TO_DEVICE); + fail_dma_mapping: entry->is_hdr_proc_ctx = false; bad_hdr_len: @@ -824,8 +843,8 @@ static int __ipa_del_hdr_proc_ctx(u32 proc_ctx_hdl, struct ipa_hdr_proc_ctx_tbl *htbl = &ipa_ctx->hdr_proc_ctx_tbl; entry = ipa_id_find(proc_ctx_hdl); - if (!entry || (entry->cookie != IPA_COOKIE)) { - IPAERR("bad parm\n"); + if (!entry || (entry->cookie != IPA_PROC_HDR_COOKIE)) { + IPAERR_RL("bad parm\n"); return -EINVAL; } @@ -833,7 +852,7 @@ static int __ipa_del_hdr_proc_ctx(u32 proc_ctx_hdl, htbl->proc_ctx_cnt, entry->offset_entry->offset); if (by_user && entry->user_deleted) { - IPAERR("proc_ctx already deleted by user\n"); + IPAERR_RL("proc_ctx already deleted by user\n"); return -EINVAL; } @@ -871,12 +890,12 @@ int __ipa_del_hdr(u32 hdr_hdl, bool by_user) entry = ipa_id_find(hdr_hdl); if (entry == NULL) { - IPAERR("lookup failed\n"); + IPAERR_RL("lookup failed\n"); return -EINVAL; } - if (entry->cookie != IPA_COOKIE) { - IPAERR("bad parm\n"); + if (entry->cookie != IPA_HDR_COOKIE) { + IPAERR_RL("bad parm\n"); return -EINVAL; } @@ -888,7 +907,7 @@ int __ipa_del_hdr(u32 hdr_hdl, bool by_user) htbl->hdr_cnt, entry->offset_entry->offset); if (by_user && entry->user_deleted) { - IPAERR("hdr already deleted by user\n"); + IPAERR_RL("hdr already deleted by user\n"); return -EINVAL; } @@ -937,12 +956,12 @@ int ipa2_add_hdr(struct ipa_ioc_add_hdr *hdrs) int result = -EFAULT; if (unlikely(!ipa_ctx)) { - IPAERR("IPA driver was not initialized\n"); + IPAERR_RL("IPA driver was not initialized\n"); return -EINVAL; } if (hdrs == NULL || hdrs->num_hdrs == 0) { - IPAERR("bad parm\n"); + IPAERR_RL("bad parm\n"); return -EINVAL; } @@ -951,7 +970,7 @@ int ipa2_add_hdr(struct ipa_ioc_add_hdr *hdrs) hdrs->num_hdrs); for (i = 0; i < hdrs->num_hdrs; i++) { if (__ipa_add_hdr(&hdrs->hdr[i])) { - IPAERR("failed to add hdr %d\n", i); + IPAERR_RL("failed to add hdr %d\n", i); hdrs->hdr[i].status = -1; } else { hdrs->hdr[i].status = 0; @@ -992,14 +1011,14 @@ int ipa2_del_hdr_by_user(struct ipa_ioc_del_hdr *hdls, bool by_user) } if (hdls == NULL || hdls->num_hdls == 0) { - IPAERR("bad parm\n"); + IPAERR_RL("bad parm\n"); return -EINVAL; } mutex_lock(&ipa_ctx->lock); for (i = 0; i < hdls->num_hdls; i++) { if (__ipa_del_hdr(hdls->hdl[i].hdl, by_user)) { - IPAERR("failed to del hdr %i\n", i); + IPAERR_RL("failed to del hdr %i\n", i); hdls->hdl[i].status = -1; } else { hdls->hdl[i].status = 0; @@ -1048,13 +1067,13 @@ int ipa2_add_hdr_proc_ctx(struct ipa_ioc_add_hdr_proc_ctx *proc_ctxs) if (ipa_ctx->ipa_hw_type <= IPA_HW_v2_0 || ipa_ctx->ipa_hw_type == IPA_HW_v2_6L) { - IPAERR("Processing context not supported on IPA HW %d\n", + IPAERR_RL("Processing context not supported on IPA HW %d\n", ipa_ctx->ipa_hw_type); return -EFAULT; } if (proc_ctxs == NULL || proc_ctxs->num_proc_ctxs == 0) { - IPAERR("bad parm\n"); + IPAERR_RL("bad parm\n"); return -EINVAL; } @@ -1063,7 +1082,7 @@ int ipa2_add_hdr_proc_ctx(struct ipa_ioc_add_hdr_proc_ctx *proc_ctxs) proc_ctxs->num_proc_ctxs); for (i = 0; i < proc_ctxs->num_proc_ctxs; i++) { if (__ipa_add_hdr_proc_ctx(&proc_ctxs->proc_ctx[i], true)) { - IPAERR("failed to add hdr pric ctx %d\n", i); + IPAERR_RL("failed to add hdr pric ctx %d\n", i); proc_ctxs->proc_ctx[i].status = -1; } else { proc_ctxs->proc_ctx[i].status = 0; @@ -1108,14 +1127,14 @@ int ipa2_del_hdr_proc_ctx_by_user(struct ipa_ioc_del_hdr_proc_ctx *hdls, } if (hdls == NULL || hdls->num_hdls == 0) { - IPAERR("bad parm\n"); + IPAERR_RL("bad parm\n"); return -EINVAL; } mutex_lock(&ipa_ctx->lock); for (i = 0; i < hdls->num_hdls; i++) { if (__ipa_del_hdr_proc_ctx(hdls->hdl[i].hdl, true, by_user)) { - IPAERR("failed to del hdr %i\n", i); + IPAERR_RL("failed to del hdr %i\n", i); hdls->hdl[i].status = -1; } else { hdls->hdl[i].status = 0; @@ -1352,7 +1371,7 @@ int ipa2_get_hdr(struct ipa_ioc_get_hdr *lookup) } if (lookup == NULL) { - IPAERR("bad parm\n"); + IPAERR_RL("bad parm\n"); return -EINVAL; } mutex_lock(&ipa_ctx->lock); @@ -1439,13 +1458,13 @@ int ipa2_put_hdr(u32 hdr_hdl) entry = ipa_id_find(hdr_hdl); if (entry == NULL) { - IPAERR("lookup failed\n"); + IPAERR_RL("lookup failed\n"); result = -EINVAL; goto bail; } - if (entry->cookie != IPA_COOKIE) { - IPAERR("invalid header entry\n"); + if (entry->cookie != IPA_HDR_COOKIE) { + IPAERR_RL("invalid header entry\n"); result = -EINVAL; goto bail; } @@ -1473,7 +1492,7 @@ int ipa2_copy_hdr(struct ipa_ioc_copy_hdr *copy) int result = -EFAULT; if (copy == NULL) { - IPAERR("bad parm\n"); + IPAERR_RL("bad parm\n"); return -EINVAL; } mutex_lock(&ipa_ctx->lock); diff --git a/drivers/platform/msm/ipa/ipa_v2/ipa_i.h b/drivers/platform/msm/ipa/ipa_v2/ipa_i.h index bb11230c960a..bfb1ce56412c 100644 --- a/drivers/platform/msm/ipa/ipa_v2/ipa_i.h +++ b/drivers/platform/msm/ipa/ipa_v2/ipa_i.h @@ -37,7 +37,15 @@ #define DRV_NAME "ipa" #define NAT_DEV_NAME "ipaNatTable" + #define IPA_COOKIE 0x57831603 +#define IPA_RT_RULE_COOKIE 0x57831604 +#define IPA_RT_TBL_COOKIE 0x57831605 +#define IPA_FLT_COOKIE 0x57831606 +#define IPA_HDR_COOKIE 0x57831607 +#define IPA_PROC_HDR_COOKIE 0x57831608 + + #define MTU_BYTE 1500 #define IPA_MAX_NUM_PIPES 0x14 @@ -87,6 +95,18 @@ } \ } while (0) +#define IPAERR_RL(fmt, args...) \ + do { \ + pr_err_ratelimited(DRV_NAME " %s:%d " fmt, __func__, \ + __LINE__, ## args);\ + if (ipa_ctx) { \ + IPA_IPC_LOGGING(ipa_ctx->logbuf, \ + DRV_NAME " %s:%d " fmt, ## args); \ + IPA_IPC_LOGGING(ipa_ctx->logbuf_low, \ + DRV_NAME " %s:%d " fmt, ## args); \ + } \ + } while (0) + #define WLAN_AMPDU_TX_EP 15 #define WLAN_PROD_TX_EP 19 #define WLAN1_CONS_RX_EP 14 @@ -223,8 +243,8 @@ struct ipa_smmu_cb_ctx { */ struct ipa_flt_entry { struct list_head link; - struct ipa_flt_rule rule; u32 cookie; + struct ipa_flt_rule rule; struct ipa_flt_tbl *tbl; struct ipa_rt_tbl *rt_tbl; u32 hw_len; @@ -249,13 +269,13 @@ struct ipa_flt_entry { */ struct ipa_rt_tbl { struct list_head link; + u32 cookie; struct list_head head_rt_rule_list; char name[IPA_RESOURCE_NAME_MAX]; u32 idx; u32 rule_cnt; u32 ref_cnt; struct ipa_rt_tbl_set *set; - u32 cookie; bool in_sys; u32 sz; struct ipa_mem_buffer curr_mem; @@ -286,6 +306,7 @@ struct ipa_rt_tbl { */ struct ipa_hdr_entry { struct list_head link; + u32 cookie; u8 hdr[IPA_HDR_MAX_SIZE]; u32 hdr_len; char name[IPA_RESOURCE_NAME_MAX]; @@ -295,7 +316,6 @@ struct ipa_hdr_entry { dma_addr_t phys_base; struct ipa_hdr_proc_ctx_entry *proc_ctx; struct ipa_hdr_offset_entry *offset_entry; - u32 cookie; u32 ref_cnt; int id; u8 is_eth2_ofst_valid; @@ -368,10 +388,10 @@ struct ipa_hdr_proc_ctx_add_hdr_cmd_seq { */ struct ipa_hdr_proc_ctx_entry { struct list_head link; + u32 cookie; enum ipa_hdr_proc_type type; struct ipa_hdr_proc_ctx_offset_entry *offset_entry; struct ipa_hdr_entry *hdr; - u32 cookie; u32 ref_cnt; int id; bool user_deleted; @@ -427,8 +447,8 @@ struct ipa_flt_tbl { */ struct ipa_rt_entry { struct list_head link; - struct ipa_rt_rule rule; u32 cookie; + struct ipa_rt_rule rule; struct ipa_rt_tbl *tbl; struct ipa_hdr_entry *hdr; struct ipa_hdr_proc_ctx_entry *proc_ctx; diff --git a/drivers/platform/msm/ipa/ipa_v2/ipa_intf.c b/drivers/platform/msm/ipa/ipa_v2/ipa_intf.c index e3f987d47692..9c4fc0ce8cc1 100644 --- a/drivers/platform/msm/ipa/ipa_v2/ipa_intf.c +++ b/drivers/platform/msm/ipa/ipa_v2/ipa_intf.c @@ -274,7 +274,7 @@ int ipa_query_intf_tx_props(struct ipa_ioc_query_intf_tx_props *tx) if (!strncmp(entry->name, tx->name, IPA_RESOURCE_NAME_MAX)) { /* add the entry check */ if (entry->num_tx_props != tx->num_tx_props) { - IPAERR("invalid entry number(%u %u)\n", + IPAERR_RL("invalid entry number(%u %u)\n", entry->num_tx_props, tx->num_tx_props); mutex_unlock(&ipa_ctx->lock); @@ -315,7 +315,7 @@ int ipa_query_intf_rx_props(struct ipa_ioc_query_intf_rx_props *rx) if (!strncmp(entry->name, rx->name, IPA_RESOURCE_NAME_MAX)) { /* add the entry check */ if (entry->num_rx_props != rx->num_rx_props) { - IPAERR("invalid entry number(%u %u)\n", + IPAERR_RL("invalid entry number(%u %u)\n", entry->num_rx_props, rx->num_rx_props); mutex_unlock(&ipa_ctx->lock); @@ -356,7 +356,7 @@ int ipa_query_intf_ext_props(struct ipa_ioc_query_intf_ext_props *ext) if (!strcmp(entry->name, ext->name)) { /* add the entry check */ if (entry->num_ext_props != ext->num_ext_props) { - IPAERR("invalid entry number(%u %u)\n", + IPAERR_RL("invalid entry number(%u %u)\n", entry->num_ext_props, ext->num_ext_props); mutex_unlock(&ipa_ctx->lock); @@ -405,13 +405,13 @@ int ipa2_send_msg(struct ipa_msg_meta *meta, void *buff, if (meta == NULL || (buff == NULL && callback != NULL) || (buff != NULL && callback == NULL)) { - IPAERR("invalid param meta=%p buff=%p, callback=%p\n", + IPAERR_RL("invalid param meta=%p buff=%p, callback=%p\n", meta, buff, callback); return -EINVAL; } if (meta->msg_type >= IPA_EVENT_MAX_NUM) { - IPAERR("unsupported message type %d\n", meta->msg_type); + IPAERR_RL("unsupported message type %d\n", meta->msg_type); return -EINVAL; } @@ -634,7 +634,7 @@ int ipa_pull_msg(struct ipa_msg_meta *meta, char *buff, size_t count) int result = -EINVAL; if (meta == NULL || buff == NULL || !count) { - IPAERR("invalid param name=%p buff=%p count=%zu\n", + IPAERR_RL("invalid param name=%p buff=%p count=%zu\n", meta, buff, count); return result; } diff --git a/drivers/platform/msm/ipa/ipa_v2/ipa_nat.c b/drivers/platform/msm/ipa/ipa_v2/ipa_nat.c index 5dd8b225217d..e7092e9acbc7 100644 --- a/drivers/platform/msm/ipa/ipa_v2/ipa_nat.c +++ b/drivers/platform/msm/ipa/ipa_v2/ipa_nat.c @@ -252,8 +252,8 @@ int ipa2_allocate_nat_device(struct ipa_ioc_nat_alloc_mem *mem) mutex_lock(&nat_ctx->lock); if (strcmp(mem->dev_name, NAT_DEV_NAME)) { - IPAERR("Nat device name mismatch\n"); - IPAERR("Expect: %s Recv: %s\n", NAT_DEV_NAME, mem->dev_name); + IPAERR_RL("Nat device name mismatch\n"); + IPAERR_RL("Expect: %s Recv: %s\n", NAT_DEV_NAME, mem->dev_name); result = -EPERM; goto bail; } @@ -272,7 +272,7 @@ int ipa2_allocate_nat_device(struct ipa_ioc_nat_alloc_mem *mem) if (mem->size <= 0 || nat_ctx->is_dev_init == true) { - IPAERR("Invalid Parameters or device is already init\n"); + IPAERR_RL("Invalid Parameters or device is already init\n"); result = -EPERM; goto bail; } @@ -335,17 +335,17 @@ int ipa2_nat_init_cmd(struct ipa_ioc_v4_nat_init *init) /* check for integer overflow */ if (init->ipv4_rules_offset > - UINT_MAX - (TBL_ENTRY_SIZE * (init->table_entries + 1))) { - IPAERR("Detected overflow\n"); - return -EPERM; + (UINT_MAX - (TBL_ENTRY_SIZE * (init->table_entries + 1)))) { + IPAERR_RL("Detected overflow\n"); + return -EPERM; } /* Check Table Entry offset is not beyond allocated size */ tmp = init->ipv4_rules_offset + (TBL_ENTRY_SIZE * (init->table_entries + 1)); if (tmp > ipa_ctx->nat_mem.size) { - IPAERR("Table rules offset not valid\n"); - IPAERR("offset:%d entrys:%d size:%zu mem_size:%zu\n", + IPAERR_RL("Table rules offset not valid\n"); + IPAERR_RL("offset:%d entrys:%d size:%zu mem_size:%zu\n", init->ipv4_rules_offset, (init->table_entries + 1), tmp, ipa_ctx->nat_mem.size); return -EPERM; @@ -354,16 +354,16 @@ int ipa2_nat_init_cmd(struct ipa_ioc_v4_nat_init *init) /* check for integer overflow */ if (init->expn_rules_offset > UINT_MAX - (TBL_ENTRY_SIZE * init->expn_table_entries)) { - IPAERR("Detected overflow\n"); - return -EPERM; + IPAERR_RL("Detected overflow\n"); + return -EPERM; } /* Check Expn Table Entry offset is not beyond allocated size */ tmp = init->expn_rules_offset + (TBL_ENTRY_SIZE * init->expn_table_entries); if (tmp > ipa_ctx->nat_mem.size) { - IPAERR("Expn Table rules offset not valid\n"); - IPAERR("offset:%d entrys:%d size:%zu mem_size:%zu\n", + IPAERR_RL("Expn Table rules offset not valid\n"); + IPAERR_RL("offset:%d entrys:%d size:%zu mem_size:%zu\n", init->expn_rules_offset, init->expn_table_entries, tmp, ipa_ctx->nat_mem.size); return -EPERM; @@ -372,16 +372,16 @@ int ipa2_nat_init_cmd(struct ipa_ioc_v4_nat_init *init) /* check for integer overflow */ if (init->index_offset > UINT_MAX - (INDX_TBL_ENTRY_SIZE * (init->table_entries + 1))) { - IPAERR("Detected overflow\n"); - return -EPERM; + IPAERR_RL("Detected overflow\n"); + return -EPERM; } /* Check Indx Table Entry offset is not beyond allocated size */ tmp = init->index_offset + (INDX_TBL_ENTRY_SIZE * (init->table_entries + 1)); if (tmp > ipa_ctx->nat_mem.size) { - IPAERR("Indx Table rules offset not valid\n"); - IPAERR("offset:%d entrys:%d size:%zu mem_size:%zu\n", + IPAERR_RL("Indx Table rules offset not valid\n"); + IPAERR_RL("offset:%d entrys:%d size:%zu mem_size:%zu\n", init->index_offset, (init->table_entries + 1), tmp, ipa_ctx->nat_mem.size); return -EPERM; @@ -389,17 +389,17 @@ int ipa2_nat_init_cmd(struct ipa_ioc_v4_nat_init *init) /* check for integer overflow */ if (init->index_expn_offset > - UINT_MAX - (INDX_TBL_ENTRY_SIZE * init->expn_table_entries)) { - IPAERR("Detected overflow\n"); - return -EPERM; + (UINT_MAX - (INDX_TBL_ENTRY_SIZE * init->expn_table_entries))) { + IPAERR_RL("Detected overflow\n"); + return -EPERM; } /* Check Expn Table entry offset is not beyond allocated size */ tmp = init->index_expn_offset + (INDX_TBL_ENTRY_SIZE * init->expn_table_entries); if (tmp > ipa_ctx->nat_mem.size) { - IPAERR("Indx Expn Table rules offset not valid\n"); - IPAERR("offset:%d entrys:%d size:%zu mem_size:%zu\n", + IPAERR_RL("Indx Expn Table rules offset not valid\n"); + IPAERR_RL("offset:%d entrys:%d size:%zu mem_size:%zu\n", init->index_expn_offset, init->expn_table_entries, tmp, ipa_ctx->nat_mem.size); return -EPERM; @@ -444,16 +444,16 @@ int ipa2_nat_init_cmd(struct ipa_ioc_v4_nat_init *init) (init->expn_rules_offset > offset) || (init->index_offset > offset) || (init->index_expn_offset > offset)) { - IPAERR("Failed due to integer overflow\n"); - IPAERR("nat.mem.dma_handle: 0x%pa\n", + IPAERR_RL("Failed due to integer overflow\n"); + IPAERR_RL("nat.mem.dma_handle: 0x%pa\n", &ipa_ctx->nat_mem.dma_handle); - IPAERR("ipv4_rules_offset: 0x%x\n", + IPAERR_RL("ipv4_rules_offset: 0x%x\n", init->ipv4_rules_offset); - IPAERR("expn_rules_offset: 0x%x\n", + IPAERR_RL("expn_rules_offset: 0x%x\n", init->expn_rules_offset); - IPAERR("index_offset: 0x%x\n", + IPAERR_RL("index_offset: 0x%x\n", init->index_offset); - IPAERR("index_expn_offset: 0x%x\n", + IPAERR_RL("index_expn_offset: 0x%x\n", init->index_expn_offset); result = -EPERM; goto free_mem; @@ -509,7 +509,7 @@ int ipa2_nat_init_cmd(struct ipa_ioc_v4_nat_init *init) desc[1].len = size; IPADBG("posting v4 init command\n"); if (ipa_send_cmd(2, desc)) { - IPAERR("Fail to send immediate command\n"); + IPAERR_RL("Fail to send immediate command\n"); result = -EPERM; goto free_mem; } @@ -574,7 +574,7 @@ int ipa2_nat_dma_cmd(struct ipa_ioc_nat_dma_cmd *dma) IPADBG("\n"); if (dma->entries <= 0) { - IPAERR("Invalid number of commands %d\n", + IPAERR_RL("Invalid number of commands %d\n", dma->entries); ret = -EPERM; goto bail; @@ -582,7 +582,7 @@ int ipa2_nat_dma_cmd(struct ipa_ioc_nat_dma_cmd *dma) for (cnt = 0; cnt < dma->entries; cnt++) { if (dma->dma[cnt].table_index >= 1) { - IPAERR("Invalid table index %d\n", + IPAERR_RL("Invalid table index %d\n", dma->dma[cnt].table_index); ret = -EPERM; goto bail; @@ -593,7 +593,7 @@ int ipa2_nat_dma_cmd(struct ipa_ioc_nat_dma_cmd *dma) if (dma->dma[cnt].offset >= (ipa_ctx->nat_mem.size_base_tables + 1) * NAT_TABLE_ENTRY_SIZE_BYTE) { - IPAERR("Invalid offset %d\n", + IPAERR_RL("Invalid offset %d\n", dma->dma[cnt].offset); ret = -EPERM; goto bail; @@ -605,7 +605,7 @@ int ipa2_nat_dma_cmd(struct ipa_ioc_nat_dma_cmd *dma) if (dma->dma[cnt].offset >= ipa_ctx->nat_mem.size_expansion_tables * NAT_TABLE_ENTRY_SIZE_BYTE) { - IPAERR("Invalid offset %d\n", + IPAERR_RL("Invalid offset %d\n", dma->dma[cnt].offset); ret = -EPERM; goto bail; @@ -617,7 +617,7 @@ int ipa2_nat_dma_cmd(struct ipa_ioc_nat_dma_cmd *dma) if (dma->dma[cnt].offset >= (ipa_ctx->nat_mem.size_base_tables + 1) * NAT_INTEX_TABLE_ENTRY_SIZE_BYTE) { - IPAERR("Invalid offset %d\n", + IPAERR_RL("Invalid offset %d\n", dma->dma[cnt].offset); ret = -EPERM; goto bail; @@ -629,7 +629,7 @@ int ipa2_nat_dma_cmd(struct ipa_ioc_nat_dma_cmd *dma) if (dma->dma[cnt].offset >= ipa_ctx->nat_mem.size_expansion_tables * NAT_INTEX_TABLE_ENTRY_SIZE_BYTE) { - IPAERR("Invalid offset %d\n", + IPAERR_RL("Invalid offset %d\n", dma->dma[cnt].offset); ret = -EPERM; goto bail; @@ -638,7 +638,7 @@ int ipa2_nat_dma_cmd(struct ipa_ioc_nat_dma_cmd *dma) break; default: - IPAERR("Invalid base_addr %d\n", + IPAERR_RL("Invalid base_addr %d\n", dma->dma[cnt].base_addr); ret = -EPERM; goto bail; diff --git a/drivers/platform/msm/ipa/ipa_v2/ipa_rt.c b/drivers/platform/msm/ipa/ipa_v2/ipa_rt.c index f2909110d09f..011ca300cc09 100644 --- a/drivers/platform/msm/ipa/ipa_v2/ipa_rt.c +++ b/drivers/platform/msm/ipa/ipa_v2/ipa_rt.c @@ -853,7 +853,7 @@ int ipa2_query_rt_index(struct ipa_ioc_get_rt_tbl_indx *in) struct ipa_rt_tbl *entry; if (in->ip >= IPA_IP_MAX) { - IPAERR("bad parm\n"); + IPAERR_RL("bad parm\n"); return -EINVAL; } @@ -909,7 +909,7 @@ static struct ipa_rt_tbl *__ipa_add_rt_tbl(enum ipa_ip_type ip, INIT_LIST_HEAD(&entry->link); strlcpy(entry->name, name, IPA_RESOURCE_NAME_MAX); entry->set = set; - entry->cookie = IPA_COOKIE; + entry->cookie = IPA_RT_TBL_COOKIE; entry->in_sys = (ip == IPA_IP_v4) ? !ipa_ctx->ip4_rt_tbl_lcl : !ipa_ctx->ip6_rt_tbl_lcl; set->tbl_cnt++; @@ -922,12 +922,16 @@ static struct ipa_rt_tbl *__ipa_add_rt_tbl(enum ipa_ip_type ip, if (id < 0) { IPAERR("failed to add to tree\n"); WARN_ON(1); + goto ipa_insert_failed; } entry->id = id; } return entry; +ipa_insert_failed: + set->tbl_cnt--; + list_del(&entry->link); fail_rt_idx_alloc: entry->cookie = 0; kmem_cache_free(ipa_ctx->rt_tbl_cache, entry); @@ -940,13 +944,13 @@ static int __ipa_del_rt_tbl(struct ipa_rt_tbl *entry) enum ipa_ip_type ip = IPA_IP_MAX; u32 id; - if (entry == NULL || (entry->cookie != IPA_COOKIE)) { - IPAERR("bad parms\n"); + if (entry == NULL || (entry->cookie != IPA_RT_TBL_COOKIE)) { + IPAERR_RL("bad parms\n"); return -EINVAL; } id = entry->id; if (ipa_id_find(id) == NULL) { - IPAERR("lookup failed\n"); + IPAERR_RL("lookup failed\n"); return -EPERM; } @@ -954,8 +958,11 @@ static int __ipa_del_rt_tbl(struct ipa_rt_tbl *entry) ip = IPA_IP_v4; else if (entry->set == &ipa_ctx->rt_tbl_set[IPA_IP_v6]) ip = IPA_IP_v6; - else + else { WARN_ON(1); + return -EPERM; + } + if (!entry->in_sys) { list_del(&entry->link); @@ -994,13 +1001,14 @@ static int __ipa_add_rt_rule(enum ipa_ip_type ip, const char *name, if (rule->hdr_hdl) { hdr = ipa_id_find(rule->hdr_hdl); - if ((hdr == NULL) || (hdr->cookie != IPA_COOKIE)) { + if ((hdr == NULL) || (hdr->cookie != IPA_HDR_COOKIE)) { IPAERR("rt rule does not point to valid hdr\n"); goto error; } } else if (rule->hdr_proc_ctx_hdl) { proc_ctx = ipa_id_find(rule->hdr_proc_ctx_hdl); - if ((proc_ctx == NULL) || (proc_ctx->cookie != IPA_COOKIE)) { + if ((proc_ctx == NULL) || + (proc_ctx->cookie != IPA_PROC_HDR_COOKIE)) { IPAERR("rt rule does not point to valid proc ctx\n"); goto error; } @@ -1008,7 +1016,7 @@ static int __ipa_add_rt_rule(enum ipa_ip_type ip, const char *name, tbl = __ipa_add_rt_tbl(ip, name); - if (tbl == NULL || (tbl->cookie != IPA_COOKIE)) { + if (tbl == NULL || (tbl->cookie != IPA_RT_TBL_COOKIE)) { IPAERR("bad params\n"); goto error; } @@ -1029,7 +1037,7 @@ static int __ipa_add_rt_rule(enum ipa_ip_type ip, const char *name, goto error; } INIT_LIST_HEAD(&entry->link); - entry->cookie = IPA_COOKIE; + entry->cookie = IPA_RT_RULE_COOKIE; entry->rule = *rule; entry->tbl = tbl; entry->hdr = hdr; @@ -1082,7 +1090,7 @@ int ipa2_add_rt_rule(struct ipa_ioc_add_rt_rule *rules) int ret; if (rules == NULL || rules->num_rules == 0 || rules->ip >= IPA_IP_MAX) { - IPAERR("bad parm\n"); + IPAERR_RL("bad parm\n"); return -EINVAL; } @@ -1092,7 +1100,7 @@ int ipa2_add_rt_rule(struct ipa_ioc_add_rt_rule *rules) &rules->rules[i].rule, rules->rules[i].at_rear, &rules->rules[i].rt_rule_hdl)) { - IPAERR("failed to add rt rule %d\n", i); + IPAERR_RL("failed to add rt rule %d\n", i); rules->rules[i].status = IPA_RT_STATUS_OF_ADD_FAILED; } else { rules->rules[i].status = 0; @@ -1119,12 +1127,12 @@ int __ipa_del_rt_rule(u32 rule_hdl) entry = ipa_id_find(rule_hdl); if (entry == NULL) { - IPAERR("lookup failed\n"); + IPAERR_RL("lookup failed\n"); return -EINVAL; } - if (entry->cookie != IPA_COOKIE) { - IPAERR("bad params\n"); + if (entry->cookie != IPA_RT_RULE_COOKIE) { + IPAERR_RL("bad params\n"); return -EINVAL; } @@ -1138,7 +1146,7 @@ int __ipa_del_rt_rule(u32 rule_hdl) entry->tbl->rule_cnt); if (entry->tbl->rule_cnt == 0 && entry->tbl->ref_cnt == 0) { if (__ipa_del_rt_tbl(entry->tbl)) - IPAERR("fail to del RT tbl\n"); + IPAERR_RL("fail to del RT tbl\n"); } entry->cookie = 0; id = entry->id; @@ -1165,14 +1173,14 @@ int ipa2_del_rt_rule(struct ipa_ioc_del_rt_rule *hdls) int ret; if (hdls == NULL || hdls->num_hdls == 0 || hdls->ip >= IPA_IP_MAX) { - IPAERR("bad parm\n"); + IPAERR_RL("bad parm\n"); return -EINVAL; } mutex_lock(&ipa_ctx->lock); for (i = 0; i < hdls->num_hdls; i++) { if (__ipa_del_rt_rule(hdls->hdl[i].hdl)) { - IPAERR("failed to del rt rule %i\n", i); + IPAERR_RL("failed to del rt rule %i\n", i); hdls->hdl[i].status = IPA_RT_STATUS_OF_DEL_FAILED; } else { hdls->hdl[i].status = 0; @@ -1205,7 +1213,7 @@ int ipa2_commit_rt(enum ipa_ip_type ip) int ret; if (ip >= IPA_IP_MAX) { - IPAERR("bad parm\n"); + IPAERR_RL("bad parm\n"); return -EINVAL; } @@ -1249,7 +1257,7 @@ int ipa2_reset_rt(enum ipa_ip_type ip) int id; if (ip >= IPA_IP_MAX) { - IPAERR("bad parm\n"); + IPAERR_RL("bad parm\n"); return -EINVAL; } @@ -1267,7 +1275,7 @@ int ipa2_reset_rt(enum ipa_ip_type ip) * filtering rules point to routing tables */ if (ipa2_reset_flt(ip)) - IPAERR("fail to reset flt ip=%d\n", ip); + IPAERR_RL("fail to reset flt ip=%d\n", ip); set = &ipa_ctx->rt_tbl_set[ip]; rset = &ipa_ctx->reap_rt_tbl_set[ip]; @@ -1353,14 +1361,14 @@ int ipa2_get_rt_tbl(struct ipa_ioc_get_rt_tbl *lookup) int result = -EFAULT; if (lookup == NULL || lookup->ip >= IPA_IP_MAX) { - IPAERR("bad parm\n"); + IPAERR_RL("bad parm\n"); return -EINVAL; } mutex_lock(&ipa_ctx->lock); entry = __ipa_find_rt_tbl(lookup->ip, lookup->name); - if (entry && entry->cookie == IPA_COOKIE) { + if (entry && entry->cookie == IPA_RT_TBL_COOKIE) { if (entry->ref_cnt == U32_MAX) { - IPAERR("fail: ref count crossed limit\n"); + IPAERR_RL("fail: ref count crossed limit\n"); goto ret; } entry->ref_cnt++; @@ -1368,7 +1376,7 @@ int ipa2_get_rt_tbl(struct ipa_ioc_get_rt_tbl *lookup) /* commit for get */ if (ipa_ctx->ctrl->ipa_commit_rt(lookup->ip)) - IPAERR("fail to commit RT tbl\n"); + IPAERR_RL("fail to commit RT tbl\n"); result = 0; } @@ -1396,13 +1404,13 @@ int ipa2_put_rt_tbl(u32 rt_tbl_hdl) mutex_lock(&ipa_ctx->lock); entry = ipa_id_find(rt_tbl_hdl); if (entry == NULL) { - IPAERR("lookup failed\n"); + IPAERR_RL("lookup failed\n"); result = -EINVAL; goto ret; } - if ((entry->cookie != IPA_COOKIE) || entry->ref_cnt == 0) { - IPAERR("bad parms\n"); + if ((entry->cookie != IPA_RT_TBL_COOKIE) || entry->ref_cnt == 0) { + IPAERR_RL("bad parms\n"); result = -EINVAL; goto ret; } @@ -1411,16 +1419,19 @@ int ipa2_put_rt_tbl(u32 rt_tbl_hdl) ip = IPA_IP_v4; else if (entry->set == &ipa_ctx->rt_tbl_set[IPA_IP_v6]) ip = IPA_IP_v6; - else + else { WARN_ON(1); + result = -EINVAL; + goto ret; + } entry->ref_cnt--; if (entry->ref_cnt == 0 && entry->rule_cnt == 0) { if (__ipa_del_rt_tbl(entry)) - IPAERR("fail to del RT tbl\n"); + IPAERR_RL("fail to del RT tbl\n"); /* commit for put */ if (ipa_ctx->ctrl->ipa_commit_rt(ip)) - IPAERR("fail to commit RT tbl\n"); + IPAERR_RL("fail to commit RT tbl\n"); } result = 0; @@ -1439,20 +1450,20 @@ static int __ipa_mdfy_rt_rule(struct ipa_rt_rule_mdfy *rtrule) if (rtrule->rule.hdr_hdl) { hdr = ipa_id_find(rtrule->rule.hdr_hdl); - if ((hdr == NULL) || (hdr->cookie != IPA_COOKIE)) { - IPAERR("rt rule does not point to valid hdr\n"); + if ((hdr == NULL) || (hdr->cookie != IPA_HDR_COOKIE)) { + IPAERR_RL("rt rule does not point to valid hdr\n"); goto error; } } entry = ipa_id_find(rtrule->rt_rule_hdl); if (entry == NULL) { - IPAERR("lookup failed\n"); + IPAERR_RL("lookup failed\n"); goto error; } - if (entry->cookie != IPA_COOKIE) { - IPAERR("bad params\n"); + if (entry->cookie != IPA_RT_RULE_COOKIE) { + IPAERR_RL("bad params\n"); goto error; } @@ -1485,14 +1496,14 @@ int ipa2_mdfy_rt_rule(struct ipa_ioc_mdfy_rt_rule *hdls) int result; if (hdls == NULL || hdls->num_rules == 0 || hdls->ip >= IPA_IP_MAX) { - IPAERR("bad parm\n"); + IPAERR_RL("bad parm\n"); return -EINVAL; } mutex_lock(&ipa_ctx->lock); for (i = 0; i < hdls->num_rules; i++) { if (__ipa_mdfy_rt_rule(&hdls->rules[i])) { - IPAERR("failed to mdfy rt rule %i\n", i); + IPAERR_RL("failed to mdfy rt rule %i\n", i); hdls->rules[i].status = IPA_RT_STATUS_OF_MDFY_FAILED; } else { hdls->rules[i].status = 0; diff --git a/drivers/platform/msm/ipa/ipa_v2/ipa_uc_wdi.c b/drivers/platform/msm/ipa/ipa_v2/ipa_uc_wdi.c index 56b4bf1a2d1e..23f802425cf0 100644 --- a/drivers/platform/msm/ipa/ipa_v2/ipa_uc_wdi.c +++ b/drivers/platform/msm/ipa/ipa_v2/ipa_uc_wdi.c @@ -1672,7 +1672,7 @@ int ipa_write_qmapid_wdi_pipe(u32 clnt_hdl, u8 qmap_id) if (clnt_hdl >= ipa_ctx->ipa_num_pipes || ipa_ctx->ep[clnt_hdl].valid == 0) { - IPAERR("bad parm, %d\n", clnt_hdl); + IPAERR_RL("bad parm, %d\n", clnt_hdl); return -EINVAL; } @@ -1685,7 +1685,7 @@ int ipa_write_qmapid_wdi_pipe(u32 clnt_hdl, u8 qmap_id) ep = &ipa_ctx->ep[clnt_hdl]; if (!(ep->uc_offload_state & IPA_WDI_CONNECTED)) { - IPAERR("WDI channel bad state %d\n", ep->uc_offload_state); + IPAERR_RL("WDI channel bad state %d\n", ep->uc_offload_state); return -EFAULT; } diff --git a/drivers/platform/msm/ipa/ipa_v2/ipa_utils.c b/drivers/platform/msm/ipa/ipa_v2/ipa_utils.c index e0200fe50871..50a8e46d3b12 100644 --- a/drivers/platform/msm/ipa/ipa_v2/ipa_utils.c +++ b/drivers/platform/msm/ipa/ipa_v2/ipa_utils.c @@ -918,7 +918,7 @@ int ipa2_get_ep_mapping(enum ipa_client_type client) } if (client >= IPA_CLIENT_MAX || client < 0) { - IPAERR("Bad client number! client =%d\n", client); + IPAERR_RL("Bad client number! client =%d\n", client); return INVALID_EP_MAPPING_INDEX; } @@ -1769,7 +1769,7 @@ int ipa_generate_flt_eq(enum ipa_ip_type ip, if (attrib->attrib_mask & IPA_FLT_NEXT_HDR || attrib->attrib_mask & IPA_FLT_TC || attrib->attrib_mask & IPA_FLT_FLOW_LABEL) { - IPAERR("v6 attrib's specified for v4 rule\n"); + IPAERR_RL("v6 attrib's specified for v4 rule\n"); return -EPERM; } @@ -1781,7 +1781,7 @@ int ipa_generate_flt_eq(enum ipa_ip_type ip, if (attrib->attrib_mask & IPA_FLT_TOS_MASKED) { if (ipa_ofst_meq32[ofst_meq32] == -1) { - IPAERR("ran out of meq32 eq\n"); + IPAERR_RL("ran out of meq32 eq\n"); return -EPERM; } *en_rule |= ipa_ofst_meq32[ofst_meq32]; @@ -1801,7 +1801,7 @@ int ipa_generate_flt_eq(enum ipa_ip_type ip, if (attrib->attrib_mask & IPA_FLT_SRC_ADDR) { if (ipa_ofst_meq32[ofst_meq32] == -1) { - IPAERR("ran out of meq32 eq\n"); + IPAERR_RL("ran out of meq32 eq\n"); return -EPERM; } *en_rule |= ipa_ofst_meq32[ofst_meq32]; @@ -1815,7 +1815,7 @@ int ipa_generate_flt_eq(enum ipa_ip_type ip, if (attrib->attrib_mask & IPA_FLT_DST_ADDR) { if (ipa_ofst_meq32[ofst_meq32] == -1) { - IPAERR("ran out of meq32 eq\n"); + IPAERR_RL("ran out of meq32 eq\n"); return -EPERM; } *en_rule |= ipa_ofst_meq32[ofst_meq32]; @@ -1829,11 +1829,11 @@ int ipa_generate_flt_eq(enum ipa_ip_type ip, if (attrib->attrib_mask & IPA_FLT_SRC_PORT_RANGE) { if (ipa_ihl_ofst_rng16[ihl_ofst_rng16] == -1) { - IPAERR("ran out of ihl_rng16 eq\n"); + IPAERR_RL("ran out of ihl_rng16 eq\n"); return -EPERM; } if (attrib->src_port_hi < attrib->src_port_lo) { - IPAERR("bad src port range param\n"); + IPAERR_RL("bad src port range param\n"); return -EPERM; } *en_rule |= ipa_ihl_ofst_rng16[ihl_ofst_rng16]; @@ -1847,11 +1847,11 @@ int ipa_generate_flt_eq(enum ipa_ip_type ip, if (attrib->attrib_mask & IPA_FLT_DST_PORT_RANGE) { if (ipa_ihl_ofst_rng16[ihl_ofst_rng16] == -1) { - IPAERR("ran out of ihl_rng16 eq\n"); + IPAERR_RL("ran out of ihl_rng16 eq\n"); return -EPERM; } if (attrib->dst_port_hi < attrib->dst_port_lo) { - IPAERR("bad dst port range param\n"); + IPAERR_RL("bad dst port range param\n"); return -EPERM; } *en_rule |= ipa_ihl_ofst_rng16[ihl_ofst_rng16]; @@ -1865,7 +1865,7 @@ int ipa_generate_flt_eq(enum ipa_ip_type ip, if (attrib->attrib_mask & IPA_FLT_TYPE) { if (ipa_ihl_ofst_meq32[ihl_ofst_meq32] == -1) { - IPAERR("ran out of ihl_meq32 eq\n"); + IPAERR_RL("ran out of ihl_meq32 eq\n"); return -EPERM; } *en_rule |= ipa_ihl_ofst_meq32[ihl_ofst_meq32]; @@ -1878,7 +1878,7 @@ int ipa_generate_flt_eq(enum ipa_ip_type ip, if (attrib->attrib_mask & IPA_FLT_CODE) { if (ipa_ihl_ofst_meq32[ihl_ofst_meq32] == -1) { - IPAERR("ran out of ihl_meq32 eq\n"); + IPAERR_RL("ran out of ihl_meq32 eq\n"); return -EPERM; } *en_rule |= ipa_ihl_ofst_meq32[ihl_ofst_meq32]; @@ -1891,7 +1891,7 @@ int ipa_generate_flt_eq(enum ipa_ip_type ip, if (attrib->attrib_mask & IPA_FLT_SPI) { if (ipa_ihl_ofst_meq32[ihl_ofst_meq32] == -1) { - IPAERR("ran out of ihl_meq32 eq\n"); + IPAERR_RL("ran out of ihl_meq32 eq\n"); return -EPERM; } *en_rule |= ipa_ihl_ofst_meq32[ihl_ofst_meq32]; @@ -1905,7 +1905,7 @@ int ipa_generate_flt_eq(enum ipa_ip_type ip, if (attrib->attrib_mask & IPA_FLT_SRC_PORT) { if (ipa_ihl_ofst_rng16[ihl_ofst_rng16] == -1) { - IPAERR("ran out of ihl_rng16 eq\n"); + IPAERR_RL("ran out of ihl_rng16 eq\n"); return -EPERM; } *en_rule |= ipa_ihl_ofst_rng16[ihl_ofst_rng16]; @@ -1919,7 +1919,7 @@ int ipa_generate_flt_eq(enum ipa_ip_type ip, if (attrib->attrib_mask & IPA_FLT_DST_PORT) { if (ipa_ihl_ofst_rng16[ihl_ofst_rng16] == -1) { - IPAERR("ran out of ihl_rng16 eq\n"); + IPAERR_RL("ran out of ihl_rng16 eq\n"); return -EPERM; } *en_rule |= ipa_ihl_ofst_rng16[ihl_ofst_rng16]; @@ -1946,7 +1946,7 @@ int ipa_generate_flt_eq(enum ipa_ip_type ip, if (attrib->attrib_mask & IPA_FLT_MAC_DST_ADDR_ETHER_II) { if (ipa_ofst_meq128[ofst_meq128] == -1) { - IPAERR("ran out of meq128 eq\n"); + IPAERR_RL("ran out of meq128 eq\n"); return -EPERM; } *en_rule |= ipa_ofst_meq128[ofst_meq128]; @@ -1961,7 +1961,7 @@ int ipa_generate_flt_eq(enum ipa_ip_type ip, if (attrib->attrib_mask & IPA_FLT_MAC_SRC_ADDR_ETHER_II) { if (ipa_ofst_meq128[ofst_meq128] == -1) { - IPAERR("ran out of meq128 eq\n"); + IPAERR_RL("ran out of meq128 eq\n"); return -EPERM; } *en_rule |= ipa_ofst_meq128[ofst_meq128]; @@ -1976,7 +1976,7 @@ int ipa_generate_flt_eq(enum ipa_ip_type ip, if (attrib->attrib_mask & IPA_FLT_MAC_DST_ADDR_802_3) { if (ipa_ofst_meq128[ofst_meq128] == -1) { - IPAERR("ran out of meq128 eq\n"); + IPAERR_RL("ran out of meq128 eq\n"); return -EPERM; } *en_rule |= ipa_ofst_meq128[ofst_meq128]; @@ -1991,7 +1991,7 @@ int ipa_generate_flt_eq(enum ipa_ip_type ip, if (attrib->attrib_mask & IPA_FLT_MAC_SRC_ADDR_802_3) { if (ipa_ofst_meq128[ofst_meq128] == -1) { - IPAERR("ran out of meq128 eq\n"); + IPAERR_RL("ran out of meq128 eq\n"); return -EPERM; } *en_rule |= ipa_ofst_meq128[ofst_meq128]; @@ -2006,7 +2006,7 @@ int ipa_generate_flt_eq(enum ipa_ip_type ip, if (attrib->attrib_mask & IPA_FLT_MAC_ETHER_TYPE) { if (ipa_ofst_meq32[ofst_meq32] == -1) { - IPAERR("ran out of meq128 eq\n"); + IPAERR_RL("ran out of meq128 eq\n"); return -EPERM; } *en_rule |= ipa_ofst_meq32[ofst_meq32]; @@ -2024,7 +2024,7 @@ int ipa_generate_flt_eq(enum ipa_ip_type ip, /* error check */ if (attrib->attrib_mask & IPA_FLT_TOS || attrib->attrib_mask & IPA_FLT_PROTOCOL) { - IPAERR("v4 attrib's specified for v6 rule\n"); + IPAERR_RL("v4 attrib's specified for v6 rule\n"); return -EPERM; } @@ -2036,7 +2036,7 @@ int ipa_generate_flt_eq(enum ipa_ip_type ip, if (attrib->attrib_mask & IPA_FLT_TYPE) { if (ipa_ihl_ofst_meq32[ihl_ofst_meq32] == -1) { - IPAERR("ran out of ihl_meq32 eq\n"); + IPAERR_RL("ran out of ihl_meq32 eq\n"); return -EPERM; } *en_rule |= ipa_ihl_ofst_meq32[ihl_ofst_meq32]; @@ -2049,7 +2049,7 @@ int ipa_generate_flt_eq(enum ipa_ip_type ip, if (attrib->attrib_mask & IPA_FLT_CODE) { if (ipa_ihl_ofst_meq32[ihl_ofst_meq32] == -1) { - IPAERR("ran out of ihl_meq32 eq\n"); + IPAERR_RL("ran out of ihl_meq32 eq\n"); return -EPERM; } *en_rule |= ipa_ihl_ofst_meq32[ihl_ofst_meq32]; @@ -2062,7 +2062,7 @@ int ipa_generate_flt_eq(enum ipa_ip_type ip, if (attrib->attrib_mask & IPA_FLT_SPI) { if (ipa_ihl_ofst_meq32[ihl_ofst_meq32] == -1) { - IPAERR("ran out of ihl_meq32 eq\n"); + IPAERR_RL("ran out of ihl_meq32 eq\n"); return -EPERM; } *en_rule |= ipa_ihl_ofst_meq32[ihl_ofst_meq32]; @@ -2076,7 +2076,7 @@ int ipa_generate_flt_eq(enum ipa_ip_type ip, if (attrib->attrib_mask & IPA_FLT_SRC_PORT) { if (ipa_ihl_ofst_rng16[ihl_ofst_rng16] == -1) { - IPAERR("ran out of ihl_rng16 eq\n"); + IPAERR_RL("ran out of ihl_rng16 eq\n"); return -EPERM; } *en_rule |= ipa_ihl_ofst_rng16[ihl_ofst_rng16]; @@ -2090,7 +2090,7 @@ int ipa_generate_flt_eq(enum ipa_ip_type ip, if (attrib->attrib_mask & IPA_FLT_DST_PORT) { if (ipa_ihl_ofst_rng16[ihl_ofst_rng16] == -1) { - IPAERR("ran out of ihl_rng16 eq\n"); + IPAERR_RL("ran out of ihl_rng16 eq\n"); return -EPERM; } *en_rule |= ipa_ihl_ofst_rng16[ihl_ofst_rng16]; @@ -2104,11 +2104,11 @@ int ipa_generate_flt_eq(enum ipa_ip_type ip, if (attrib->attrib_mask & IPA_FLT_SRC_PORT_RANGE) { if (ipa_ihl_ofst_rng16[ihl_ofst_rng16] == -1) { - IPAERR("ran out of ihl_rng16 eq\n"); + IPAERR_RL("ran out of ihl_rng16 eq\n"); return -EPERM; } if (attrib->src_port_hi < attrib->src_port_lo) { - IPAERR("bad src port range param\n"); + IPAERR_RL("bad src port range param\n"); return -EPERM; } *en_rule |= ipa_ihl_ofst_rng16[ihl_ofst_rng16]; @@ -2122,11 +2122,11 @@ int ipa_generate_flt_eq(enum ipa_ip_type ip, if (attrib->attrib_mask & IPA_FLT_DST_PORT_RANGE) { if (ipa_ihl_ofst_rng16[ihl_ofst_rng16] == -1) { - IPAERR("ran out of ihl_rng16 eq\n"); + IPAERR_RL("ran out of ihl_rng16 eq\n"); return -EPERM; } if (attrib->dst_port_hi < attrib->dst_port_lo) { - IPAERR("bad dst port range param\n"); + IPAERR_RL("bad dst port range param\n"); return -EPERM; } *en_rule |= ipa_ihl_ofst_rng16[ihl_ofst_rng16]; @@ -2140,7 +2140,7 @@ int ipa_generate_flt_eq(enum ipa_ip_type ip, if (attrib->attrib_mask & IPA_FLT_SRC_ADDR) { if (ipa_ofst_meq128[ofst_meq128] == -1) { - IPAERR("ran out of meq128 eq\n"); + IPAERR_RL("ran out of meq128 eq\n"); return -EPERM; } *en_rule |= ipa_ofst_meq128[ofst_meq128]; @@ -2166,7 +2166,7 @@ int ipa_generate_flt_eq(enum ipa_ip_type ip, if (attrib->attrib_mask & IPA_FLT_DST_ADDR) { if (ipa_ofst_meq128[ofst_meq128] == -1) { - IPAERR("ran out of meq128 eq\n"); + IPAERR_RL("ran out of meq128 eq\n"); return -EPERM; } *en_rule |= ipa_ofst_meq128[ofst_meq128]; @@ -2198,7 +2198,7 @@ int ipa_generate_flt_eq(enum ipa_ip_type ip, if (attrib->attrib_mask & IPA_FLT_TOS_MASKED) { if (ipa_ofst_meq128[ofst_meq128] == -1) { - IPAERR("ran out of meq128 eq\n"); + IPAERR_RL("ran out of meq128 eq\n"); return -EPERM; } *en_rule |= ipa_ofst_meq128[ofst_meq128]; @@ -2243,7 +2243,7 @@ int ipa_generate_flt_eq(enum ipa_ip_type ip, if (attrib->attrib_mask & IPA_FLT_MAC_DST_ADDR_ETHER_II) { if (ipa_ofst_meq128[ofst_meq128] == -1) { - IPAERR("ran out of meq128 eq\n"); + IPAERR_RL("ran out of meq128 eq\n"); return -EPERM; } *en_rule |= ipa_ofst_meq128[ofst_meq128]; @@ -2258,7 +2258,7 @@ int ipa_generate_flt_eq(enum ipa_ip_type ip, if (attrib->attrib_mask & IPA_FLT_MAC_SRC_ADDR_ETHER_II) { if (ipa_ofst_meq128[ofst_meq128] == -1) { - IPAERR("ran out of meq128 eq\n"); + IPAERR_RL("ran out of meq128 eq\n"); return -EPERM; } *en_rule |= ipa_ofst_meq128[ofst_meq128]; @@ -2273,7 +2273,7 @@ int ipa_generate_flt_eq(enum ipa_ip_type ip, if (attrib->attrib_mask & IPA_FLT_MAC_DST_ADDR_802_3) { if (ipa_ofst_meq128[ofst_meq128] == -1) { - IPAERR("ran out of meq128 eq\n"); + IPAERR_RL("ran out of meq128 eq\n"); return -EPERM; } *en_rule |= ipa_ofst_meq128[ofst_meq128]; @@ -2288,7 +2288,7 @@ int ipa_generate_flt_eq(enum ipa_ip_type ip, if (attrib->attrib_mask & IPA_FLT_MAC_SRC_ADDR_802_3) { if (ipa_ofst_meq128[ofst_meq128] == -1) { - IPAERR("ran out of meq128 eq\n"); + IPAERR_RL("ran out of meq128 eq\n"); return -EPERM; } *en_rule |= ipa_ofst_meq128[ofst_meq128]; @@ -2303,7 +2303,7 @@ int ipa_generate_flt_eq(enum ipa_ip_type ip, if (attrib->attrib_mask & IPA_FLT_MAC_ETHER_TYPE) { if (ipa_ofst_meq32[ofst_meq32] == -1) { - IPAERR("ran out of meq128 eq\n"); + IPAERR_RL("ran out of meq128 eq\n"); return -EPERM; } *en_rule |= ipa_ofst_meq32[ofst_meq32]; @@ -2316,7 +2316,7 @@ int ipa_generate_flt_eq(enum ipa_ip_type ip, } } else { - IPAERR("unsupported ip %d\n", ip); + IPAERR_RL("unsupported ip %d\n", ip); return -EPERM; } @@ -2326,7 +2326,7 @@ int ipa_generate_flt_eq(enum ipa_ip_type ip, */ if (attrib->attrib_mask == 0) { if (ipa_ofst_meq32[ofst_meq32] == -1) { - IPAERR("ran out of meq32 eq\n"); + IPAERR_RL("ran out of meq32 eq\n"); return -EPERM; } *en_rule |= ipa_ofst_meq32[ofst_meq32]; @@ -3617,19 +3617,19 @@ int ipa2_write_qmap_id(struct ipa_ioc_write_qmapid *param_in) } if (param_in->client >= IPA_CLIENT_MAX) { - IPAERR("bad parm client:%d\n", param_in->client); + IPAERR_RL("bad parm client:%d\n", param_in->client); goto fail; } ipa_ep_idx = ipa2_get_ep_mapping(param_in->client); if (ipa_ep_idx == -1) { - IPAERR("Invalid client.\n"); + IPAERR_RL("Invalid client.\n"); goto fail; } ep = &ipa_ctx->ep[ipa_ep_idx]; if (!ep->valid) { - IPAERR("EP not allocated.\n"); + IPAERR_RL("EP not allocated.\n"); goto fail; } @@ -3642,7 +3642,7 @@ int ipa2_write_qmap_id(struct ipa_ioc_write_qmapid *param_in) ipa_ctx->ep[ipa_ep_idx].cfg.meta = meta; result = ipa_write_qmapid_wdi_pipe(ipa_ep_idx, meta.qmap_id); if (result) - IPAERR("qmap_id %d write failed on ep=%d\n", + IPAERR_RL("qmap_id %d write failed on ep=%d\n", meta.qmap_id, ipa_ep_idx); result = 0; } diff --git a/drivers/platform/msm/ipa/ipa_v3/ipa.c b/drivers/platform/msm/ipa/ipa_v3/ipa.c index a50cd0b807a2..7ed83fb74fcc 100644 --- a/drivers/platform/msm/ipa/ipa_v3/ipa.c +++ b/drivers/platform/msm/ipa/ipa_v3/ipa.c @@ -603,7 +603,7 @@ static int ipa3_send_wan_msg(unsigned long usr_param, uint8_t msg_type) msg_meta.msg_len = sizeof(struct ipa_wan_msg); retval = ipa3_send_msg(&msg_meta, wan_msg, ipa3_wan_msg_free_cb); if (retval) { - IPAERR("ipa3_send_msg failed: %d\n", retval); + IPAERR_RL("ipa3_send_msg failed: %d\n", retval); kfree(wan_msg); return retval; } @@ -695,7 +695,7 @@ static long ipa3_ioctl(struct file *filp, unsigned int cmd, unsigned long arg) /* add check in case user-space module compromised */ if (unlikely(((struct ipa_ioc_nat_dma_cmd *)param)->entries != pre_entry)) { - IPAERR("current %d pre %d\n", + IPAERR_RL("current %d pre %d\n", ((struct ipa_ioc_nat_dma_cmd *)param)->entries, pre_entry); retval = -EFAULT; @@ -742,7 +742,7 @@ static long ipa3_ioctl(struct file *filp, unsigned int cmd, unsigned long arg) /* add check in case user-space module compromised */ if (unlikely(((struct ipa_ioc_add_hdr *)param)->num_hdrs != pre_entry)) { - IPAERR("current %d pre %d\n", + IPAERR_RL("current %d pre %d\n", ((struct ipa_ioc_add_hdr *)param)->num_hdrs, pre_entry); retval = -EFAULT; @@ -781,7 +781,7 @@ static long ipa3_ioctl(struct file *filp, unsigned int cmd, unsigned long arg) /* add check in case user-space module compromised */ if (unlikely(((struct ipa_ioc_del_hdr *)param)->num_hdls != pre_entry)) { - IPAERR("current %d pre %d\n", + IPAERR_RL("current %d pre %d\n", ((struct ipa_ioc_del_hdr *)param)->num_hdls, pre_entry); retval = -EFAULT; @@ -821,7 +821,7 @@ static long ipa3_ioctl(struct file *filp, unsigned int cmd, unsigned long arg) /* add check in case user-space module compromised */ if (unlikely(((struct ipa_ioc_add_rt_rule *)param)->num_rules != pre_entry)) { - IPAERR("current %d pre %d\n", + IPAERR_RL("current %d pre %d\n", ((struct ipa_ioc_add_rt_rule *)param)-> num_rules, pre_entry); @@ -861,7 +861,7 @@ static long ipa3_ioctl(struct file *filp, unsigned int cmd, unsigned long arg) /* add check in case user-space module compromised */ if (unlikely(((struct ipa_ioc_add_rt_rule_after *)param)-> num_rules != pre_entry)) { - IPAERR("current %d pre %d\n", + IPAERR_RL("current %d pre %d\n", ((struct ipa_ioc_add_rt_rule_after *)param)-> num_rules, pre_entry); @@ -903,7 +903,7 @@ static long ipa3_ioctl(struct file *filp, unsigned int cmd, unsigned long arg) /* add check in case user-space module compromised */ if (unlikely(((struct ipa_ioc_mdfy_rt_rule *)param)->num_rules != pre_entry)) { - IPAERR("current %d pre %d\n", + IPAERR_RL("current %d pre %d\n", ((struct ipa_ioc_mdfy_rt_rule *)param)-> num_rules, pre_entry); @@ -943,7 +943,7 @@ static long ipa3_ioctl(struct file *filp, unsigned int cmd, unsigned long arg) /* add check in case user-space module compromised */ if (unlikely(((struct ipa_ioc_del_rt_rule *)param)->num_hdls != pre_entry)) { - IPAERR("current %d pre %d\n", + IPAERR_RL("current %d pre %d\n", ((struct ipa_ioc_del_rt_rule *)param)->num_hdls, pre_entry); retval = -EFAULT; @@ -982,7 +982,7 @@ static long ipa3_ioctl(struct file *filp, unsigned int cmd, unsigned long arg) /* add check in case user-space module compromised */ if (unlikely(((struct ipa_ioc_add_flt_rule *)param)->num_rules != pre_entry)) { - IPAERR("current %d pre %d\n", + IPAERR_RL("current %d pre %d\n", ((struct ipa_ioc_add_flt_rule *)param)-> num_rules, pre_entry); @@ -1024,7 +1024,7 @@ static long ipa3_ioctl(struct file *filp, unsigned int cmd, unsigned long arg) /* add check in case user-space module compromised */ if (unlikely(((struct ipa_ioc_add_flt_rule_after *)param)-> num_rules != pre_entry)) { - IPAERR("current %d pre %d\n", + IPAERR_RL("current %d pre %d\n", ((struct ipa_ioc_add_flt_rule_after *)param)-> num_rules, pre_entry); @@ -1065,7 +1065,7 @@ static long ipa3_ioctl(struct file *filp, unsigned int cmd, unsigned long arg) /* add check in case user-space module compromised */ if (unlikely(((struct ipa_ioc_del_flt_rule *)param)->num_hdls != pre_entry)) { - IPAERR("current %d pre %d\n", + IPAERR_RL("current %d pre %d\n", ((struct ipa_ioc_del_flt_rule *)param)-> num_hdls, pre_entry); @@ -1105,7 +1105,7 @@ static long ipa3_ioctl(struct file *filp, unsigned int cmd, unsigned long arg) /* add check in case user-space module compromised */ if (unlikely(((struct ipa_ioc_mdfy_flt_rule *)param)->num_rules != pre_entry)) { - IPAERR("current %d pre %d\n", + IPAERR_RL("current %d pre %d\n", ((struct ipa_ioc_mdfy_flt_rule *)param)-> num_rules, pre_entry); @@ -1243,7 +1243,7 @@ static long ipa3_ioctl(struct file *filp, unsigned int cmd, unsigned long arg) if (unlikely(((struct ipa_ioc_query_intf_tx_props *) param)->num_tx_props != pre_entry)) { - IPAERR("current %d pre %d\n", + IPAERR_RL("current %d pre %d\n", ((struct ipa_ioc_query_intf_tx_props *) param)->num_tx_props, pre_entry); retval = -EFAULT; @@ -1288,7 +1288,7 @@ static long ipa3_ioctl(struct file *filp, unsigned int cmd, unsigned long arg) /* add check in case user-space module compromised */ if (unlikely(((struct ipa_ioc_query_intf_rx_props *) param)->num_rx_props != pre_entry)) { - IPAERR("current %d pre %d\n", + IPAERR_RL("current %d pre %d\n", ((struct ipa_ioc_query_intf_rx_props *) param)->num_rx_props, pre_entry); retval = -EFAULT; @@ -1333,7 +1333,7 @@ static long ipa3_ioctl(struct file *filp, unsigned int cmd, unsigned long arg) /* add check in case user-space module compromised */ if (unlikely(((struct ipa_ioc_query_intf_ext_props *) param)->num_ext_props != pre_entry)) { - IPAERR("current %d pre %d\n", + IPAERR_RL("current %d pre %d\n", ((struct ipa_ioc_query_intf_ext_props *) param)->num_ext_props, pre_entry); retval = -EFAULT; @@ -1371,7 +1371,7 @@ static long ipa3_ioctl(struct file *filp, unsigned int cmd, unsigned long arg) /* add check in case user-space module compromised */ if (unlikely(((struct ipa_msg_meta *)param)->msg_len != pre_entry)) { - IPAERR("current %d pre %d\n", + IPAERR_RL("current %d pre %d\n", ((struct ipa_msg_meta *)param)->msg_len, pre_entry); retval = -EFAULT; @@ -1511,7 +1511,7 @@ static long ipa3_ioctl(struct file *filp, unsigned int cmd, unsigned long arg) /* add check in case user-space module compromised */ if (unlikely(((struct ipa_ioc_add_hdr_proc_ctx *) param)->num_proc_ctxs != pre_entry)) { - IPAERR("current %d pre %d\n", + IPAERR_RL("current %d pre %d\n", ((struct ipa_ioc_add_hdr_proc_ctx *) param)->num_proc_ctxs, pre_entry); retval = -EFAULT; @@ -1550,7 +1550,7 @@ static long ipa3_ioctl(struct file *filp, unsigned int cmd, unsigned long arg) /* add check in case user-space module compromised */ if (unlikely(((struct ipa_ioc_del_hdr_proc_ctx *) param)->num_hdls != pre_entry)) { - IPAERR("current %d pre %d\n", + IPAERR_RL("current %d pre %d\n", ((struct ipa_ioc_del_hdr_proc_ctx *)param)-> num_hdls, pre_entry); diff --git a/drivers/platform/msm/ipa/ipa_v3/ipa_dp.c b/drivers/platform/msm/ipa/ipa_v3/ipa_dp.c index 6a3a89e2cf8d..5fe425ea7655 100644 --- a/drivers/platform/msm/ipa/ipa_v3/ipa_dp.c +++ b/drivers/platform/msm/ipa/ipa_v3/ipa_dp.c @@ -1188,6 +1188,15 @@ static void ipa3_handle_rx(struct ipa3_sys_context *sys) } else { inactive_cycles = 0; } + + /* + * if pipe is out of buffers there is no point polling for + * completed descs; release the worker so delayed work can + * run in a timely manner + */ + if (sys->len == 0) + break; + } while (inactive_cycles <= POLLING_INACTIVITY_RX); trace_poll_to_intr3(sys->ep->client); diff --git a/drivers/platform/msm/ipa/ipa_v3/ipa_flt.c b/drivers/platform/msm/ipa/ipa_v3/ipa_flt.c index 41b29335d23b..c2fb87ab757b 100644 --- a/drivers/platform/msm/ipa/ipa_v3/ipa_flt.c +++ b/drivers/platform/msm/ipa/ipa_v3/ipa_flt.c @@ -745,7 +745,7 @@ static int __ipa_validate_flt_rule(const struct ipa_flt_rule *rule, goto error; } - if ((*rt_tbl)->cookie != IPA_COOKIE) { + if ((*rt_tbl)->cookie != IPA_RT_TBL_COOKIE) { IPAERR("RT table cookie is invalid\n"); goto error; } @@ -787,7 +787,7 @@ static int __ipa_create_flt_entry(struct ipa3_flt_entry **entry, } INIT_LIST_HEAD(&((*entry)->link)); (*entry)->rule = *rule; - (*entry)->cookie = IPA_COOKIE; + (*entry)->cookie = IPA_FLT_COOKIE; (*entry)->rt_tbl = rt_tbl; (*entry)->tbl = tbl; if (rule->rule_id) { @@ -822,12 +822,18 @@ static int __ipa_finish_flt_rule_add(struct ipa3_flt_tbl *tbl, if (id < 0) { IPAERR("failed to add to tree\n"); WARN_ON(1); + goto ipa_insert_failed; } *rule_hdl = id; entry->id = id; IPADBG_LOW("add flt rule rule_cnt=%d\n", tbl->rule_cnt); return 0; +ipa_insert_failed: + if (entry->rt_tbl) + entry->rt_tbl->ref_cnt--; + tbl->rule_cnt--; + return -EPERM; } static int __ipa_add_flt_rule(struct ipa3_flt_tbl *tbl, enum ipa_ip_type ip, @@ -853,9 +859,16 @@ static int __ipa_add_flt_rule(struct ipa3_flt_tbl *tbl, enum ipa_ip_type ip, list_add(&entry->link, &tbl->head_flt_rule_list); } - __ipa_finish_flt_rule_add(tbl, entry, rule_hdl); + if (__ipa_finish_flt_rule_add(tbl, entry, rule_hdl)) + goto ipa_insert_failed; return 0; +ipa_insert_failed: + list_del(&entry->link); + /* if rule id was allocated from idr, remove it */ + if (!(entry->rule_id & ipahal_get_rule_id_hi_bit())) + idr_remove(&entry->tbl->rule_ids, entry->rule_id); + kmem_cache_free(ipa3_ctx->flt_rule_cache, entry); error: return -EPERM; @@ -874,7 +887,7 @@ static int __ipa_add_flt_rule_after(struct ipa3_flt_tbl *tbl, goto error; if (rule == NULL || rule_hdl == NULL) { - IPAERR("bad parms rule=%p rule_hdl=%p\n", rule, + IPAERR_RL("bad parms rule=%p rule_hdl=%p\n", rule, rule_hdl); goto error; } @@ -887,7 +900,8 @@ static int __ipa_add_flt_rule_after(struct ipa3_flt_tbl *tbl, list_add(&entry->link, &((*add_after_entry)->link)); - __ipa_finish_flt_rule_add(tbl, entry, rule_hdl); + if (__ipa_finish_flt_rule_add(tbl, entry, rule_hdl)) + goto ipa_insert_failed; /* * prepare for next insertion @@ -896,6 +910,13 @@ static int __ipa_add_flt_rule_after(struct ipa3_flt_tbl *tbl, return 0; +ipa_insert_failed: + list_del(&entry->link); + /* if rule id was allocated from idr, remove it */ + if (!(entry->rule_id & ipahal_get_rule_id_hi_bit())) + idr_remove(&entry->tbl->rule_ids, entry->rule_id); + kmem_cache_free(ipa3_ctx->flt_rule_cache, entry); + error: *add_after_entry = NULL; return -EPERM; @@ -908,12 +929,12 @@ static int __ipa_del_flt_rule(u32 rule_hdl) entry = ipa3_id_find(rule_hdl); if (entry == NULL) { - IPAERR("lookup failed\n"); + IPAERR_RL("lookup failed\n"); return -EINVAL; } - if (entry->cookie != IPA_COOKIE) { - IPAERR("bad params\n"); + if (entry->cookie != IPA_FLT_COOKIE) { + IPAERR_RL("bad params\n"); return -EINVAL; } id = entry->id; @@ -945,12 +966,12 @@ static int __ipa_mdfy_flt_rule(struct ipa_flt_rule_mdfy *frule, entry = ipa3_id_find(frule->rule_hdl); if (entry == NULL) { - IPAERR("lookup failed\n"); + IPAERR_RL("lookup failed\n"); goto error; } - if (entry->cookie != IPA_COOKIE) { - IPAERR("bad params\n"); + if (entry->cookie != IPA_FLT_COOKIE) { + IPAERR_RL("bad params\n"); goto error; } @@ -960,25 +981,25 @@ static int __ipa_mdfy_flt_rule(struct ipa_flt_rule_mdfy *frule, if (frule->rule.action != IPA_PASS_TO_EXCEPTION) { if (!frule->rule.eq_attrib_type) { if (!frule->rule.rt_tbl_hdl) { - IPAERR("invalid RT tbl\n"); + IPAERR_RL("invalid RT tbl\n"); goto error; } rt_tbl = ipa3_id_find(frule->rule.rt_tbl_hdl); if (rt_tbl == NULL) { - IPAERR("RT tbl not found\n"); + IPAERR_RL("RT tbl not found\n"); goto error; } - if (rt_tbl->cookie != IPA_COOKIE) { - IPAERR("RT table cookie is invalid\n"); + if (rt_tbl->cookie != IPA_RT_TBL_COOKIE) { + IPAERR_RL("RT table cookie is invalid\n"); goto error; } } else { if (frule->rule.rt_tbl_idx > ((ip == IPA_IP_v4) ? IPA_MEM_PART(v4_modem_rt_index_hi) : IPA_MEM_PART(v6_modem_rt_index_hi))) { - IPAERR("invalid RT tbl\n"); + IPAERR_RL("invalid RT tbl\n"); goto error; } } @@ -1023,7 +1044,7 @@ static int __ipa_add_ep_flt_rule(enum ipa_ip_type ip, enum ipa_client_type ep, int ipa_ep_idx; if (rule == NULL || rule_hdl == NULL || ep >= IPA_CLIENT_MAX) { - IPAERR("bad parms rule=%p rule_hdl=%p ep=%d\n", rule, + IPAERR_RL("bad parms rule=%p rule_hdl=%p ep=%d\n", rule, rule_hdl, ep); return -EINVAL; @@ -1053,7 +1074,7 @@ int ipa3_add_flt_rule(struct ipa_ioc_add_flt_rule *rules) if (rules == NULL || rules->num_rules == 0 || rules->ip >= IPA_IP_MAX) { - IPAERR("bad parm\n"); + IPAERR_RL("bad parm\n"); return -EINVAL; } @@ -1068,7 +1089,7 @@ int ipa3_add_flt_rule(struct ipa_ioc_add_flt_rule *rules) result = -1; if (result) { - IPAERR("failed to add flt rule %d\n", i); + IPAERR_RL("failed to add flt rule %d\n", i); rules->rules[i].status = IPA_FLT_STATUS_OF_ADD_FAILED; } else { rules->rules[i].status = 0; @@ -1076,7 +1097,7 @@ int ipa3_add_flt_rule(struct ipa_ioc_add_flt_rule *rules) } if (rules->global) { - IPAERR("no support for global filter rules\n"); + IPAERR_RL("no support for global filter rules\n"); result = -EPERM; goto bail; } @@ -1111,12 +1132,12 @@ int ipa3_add_flt_rule_after(struct ipa_ioc_add_flt_rule_after *rules) if (rules == NULL || rules->num_rules == 0 || rules->ip >= IPA_IP_MAX) { - IPAERR("bad parm\n"); + IPAERR_RL("bad parm\n"); return -EINVAL; } if (rules->ep >= IPA_CLIENT_MAX) { - IPAERR("bad parms ep=%d\n", rules->ep); + IPAERR_RL("bad parms ep=%d\n", rules->ep); return -EINVAL; } @@ -1131,20 +1152,20 @@ int ipa3_add_flt_rule_after(struct ipa_ioc_add_flt_rule_after *rules) entry = ipa3_id_find(rules->add_after_hdl); if (entry == NULL) { - IPAERR("lookup failed\n"); + IPAERR_RL("lookup failed\n"); result = -EINVAL; goto bail; } if (entry->tbl != tbl) { - IPAERR("given entry does not match the table\n"); + IPAERR_RL("given entry does not match the table\n"); result = -EINVAL; goto bail; } if (tbl->sticky_rear) if (&entry->link == tbl->head_flt_rule_list.prev) { - IPAERR("cannot add rule at end of a sticky table"); + IPAERR_RL("cannot add rule at end of a sticky table"); result = -EINVAL; goto bail; } @@ -1166,7 +1187,7 @@ int ipa3_add_flt_rule_after(struct ipa_ioc_add_flt_rule_after *rules) &entry); if (result) { - IPAERR("failed to add flt rule %d\n", i); + IPAERR_RL("failed to add flt rule %d\n", i); rules->rules[i].status = IPA_FLT_STATUS_OF_ADD_FAILED; } else { rules->rules[i].status = 0; @@ -1200,14 +1221,14 @@ int ipa3_del_flt_rule(struct ipa_ioc_del_flt_rule *hdls) int result; if (hdls == NULL || hdls->num_hdls == 0 || hdls->ip >= IPA_IP_MAX) { - IPAERR("bad parm\n"); + IPAERR_RL("bad parm\n"); return -EINVAL; } mutex_lock(&ipa3_ctx->lock); for (i = 0; i < hdls->num_hdls; i++) { if (__ipa_del_flt_rule(hdls->hdl[i].hdl)) { - IPAERR("failed to del flt rule %i\n", i); + IPAERR_RL("failed to del flt rule %i\n", i); hdls->hdl[i].status = IPA_FLT_STATUS_OF_DEL_FAILED; } else { hdls->hdl[i].status = 0; @@ -1240,14 +1261,14 @@ int ipa3_mdfy_flt_rule(struct ipa_ioc_mdfy_flt_rule *hdls) int result; if (hdls == NULL || hdls->num_rules == 0 || hdls->ip >= IPA_IP_MAX) { - IPAERR("bad parm\n"); + IPAERR_RL("bad parm\n"); return -EINVAL; } mutex_lock(&ipa3_ctx->lock); for (i = 0; i < hdls->num_rules; i++) { if (__ipa_mdfy_flt_rule(&hdls->rules[i], hdls->ip)) { - IPAERR("failed to mdfy flt rule %i\n", i); + IPAERR_RL("failed to mdfy flt rule %i\n", i); hdls->rules[i].status = IPA_FLT_STATUS_OF_MDFY_FAILED; } else { hdls->rules[i].status = 0; @@ -1281,7 +1302,7 @@ int ipa3_commit_flt(enum ipa_ip_type ip) int result; if (ip >= IPA_IP_MAX) { - IPAERR("bad parm\n"); + IPAERR_RL("bad parm\n"); return -EINVAL; } @@ -1317,7 +1338,7 @@ int ipa3_reset_flt(enum ipa_ip_type ip) int id; if (ip >= IPA_IP_MAX) { - IPAERR("bad parm\n"); + IPAERR_RL("bad parm\n"); return -EINVAL; } diff --git a/drivers/platform/msm/ipa/ipa_v3/ipa_hdr.c b/drivers/platform/msm/ipa/ipa_v3/ipa_hdr.c index a5186f1aff35..f8529faf159d 100644 --- a/drivers/platform/msm/ipa/ipa_v3/ipa_hdr.c +++ b/drivers/platform/msm/ipa/ipa_v3/ipa_hdr.c @@ -330,17 +330,17 @@ static int __ipa_add_hdr_proc_ctx(struct ipa_hdr_proc_ctx_add *proc_ctx, proc_ctx->type, proc_ctx->hdr_hdl); if (!HDR_PROC_TYPE_IS_VALID(proc_ctx->type)) { - IPAERR("invalid processing type %d\n", proc_ctx->type); + IPAERR_RL("invalid processing type %d\n", proc_ctx->type); return -EINVAL; } hdr_entry = ipa3_id_find(proc_ctx->hdr_hdl); if (!hdr_entry) { - IPAERR("hdr_hdl is invalid\n"); + IPAERR_RL("hdr_hdl is invalid\n"); return -EINVAL; } - if (hdr_entry->cookie != IPA_COOKIE) { - IPAERR("Invalid header cookie %u\n", hdr_entry->cookie); + if (hdr_entry->cookie != IPA_HDR_COOKIE) { + IPAERR_RL("Invalid header cookie %u\n", hdr_entry->cookie); WARN_ON(1); return -EINVAL; } @@ -359,7 +359,7 @@ static int __ipa_add_hdr_proc_ctx(struct ipa_hdr_proc_ctx_add *proc_ctx, entry->hdr = hdr_entry; if (add_ref_hdr) hdr_entry->ref_cnt++; - entry->cookie = IPA_COOKIE; + entry->cookie = IPA_HDR_COOKIE; needed_len = ipahal_get_proc_ctx_needed_len(proc_ctx->type); @@ -369,7 +369,7 @@ static int __ipa_add_hdr_proc_ctx(struct ipa_hdr_proc_ctx_add *proc_ctx, ipa_hdr_proc_ctx_bin_sz[IPA_HDR_PROC_CTX_BIN1]) { bin = IPA_HDR_PROC_CTX_BIN1; } else { - IPAERR("unexpected needed len %d\n", needed_len); + IPAERR_RL("unexpected needed len %d\n", needed_len); WARN_ON(1); goto bad_len; } @@ -379,7 +379,7 @@ static int __ipa_add_hdr_proc_ctx(struct ipa_hdr_proc_ctx_add *proc_ctx, IPA_MEM_PART(apps_hdr_proc_ctx_size_ddr); if (list_empty(&htbl->head_free_offset_list[bin])) { if (htbl->end + ipa_hdr_proc_ctx_bin_sz[bin] > mem_size) { - IPAERR("hdr proc ctx table overflow\n"); + IPAERR_RL("hdr proc ctx table overflow\n"); goto bad_len; } @@ -417,6 +417,7 @@ static int __ipa_add_hdr_proc_ctx(struct ipa_hdr_proc_ctx_add *proc_ctx, if (id < 0) { IPAERR("failed to alloc id\n"); WARN_ON(1); + goto ipa_insert_failed; } entry->id = id; proc_ctx->proc_ctx_hdl = id; @@ -424,6 +425,14 @@ static int __ipa_add_hdr_proc_ctx(struct ipa_hdr_proc_ctx_add *proc_ctx, return 0; +ipa_insert_failed: + if (offset) + list_move(&offset->link, + &htbl->head_free_offset_list[offset->bin]); + entry->offset_entry = NULL; + list_del(&entry->link); + htbl->proc_ctx_cnt--; + bad_len: if (add_ref_hdr) hdr_entry->ref_cnt--; @@ -436,19 +445,19 @@ bad_len: static int __ipa_add_hdr(struct ipa_hdr_add *hdr) { struct ipa3_hdr_entry *entry; - struct ipa_hdr_offset_entry *offset; + struct ipa_hdr_offset_entry *offset = NULL; u32 bin; struct ipa3_hdr_tbl *htbl = &ipa3_ctx->hdr_tbl; int id; int mem_size; if (hdr->hdr_len == 0 || hdr->hdr_len > IPA_HDR_MAX_SIZE) { - IPAERR("bad parm\n"); + IPAERR_RL("bad parm\n"); goto error; } if (!HDR_TYPE_IS_VALID(hdr->type)) { - IPAERR("invalid hdr type %d\n", hdr->type); + IPAERR_RL("invalid hdr type %d\n", hdr->type); goto error; } @@ -467,7 +476,7 @@ static int __ipa_add_hdr(struct ipa_hdr_add *hdr) entry->type = hdr->type; entry->is_eth2_ofst_valid = hdr->is_eth2_ofst_valid; entry->eth2_ofst = hdr->eth2_ofst; - entry->cookie = IPA_COOKIE; + entry->cookie = IPA_HDR_COOKIE; if (hdr->hdr_len <= ipa_hdr_bin_sz[IPA_HDR_BIN0]) bin = IPA_HDR_BIN0; @@ -480,7 +489,7 @@ static int __ipa_add_hdr(struct ipa_hdr_add *hdr) else if (hdr->hdr_len <= ipa_hdr_bin_sz[IPA_HDR_BIN4]) bin = IPA_HDR_BIN4; else { - IPAERR("unexpected hdr len %d\n", hdr->hdr_len); + IPAERR_RL("unexpected hdr len %d\n", hdr->hdr_len); goto bad_hdr_len; } @@ -546,6 +555,7 @@ static int __ipa_add_hdr(struct ipa_hdr_add *hdr) if (id < 0) { IPAERR("failed to alloc id\n"); WARN_ON(1); + goto ipa_insert_failed; } entry->id = id; hdr->hdr_hdl = id; @@ -570,10 +580,19 @@ fail_add_proc_ctx: entry->ref_cnt--; hdr->hdr_hdl = 0; ipa3_id_remove(id); +ipa_insert_failed: + if (entry->is_hdr_proc_ctx) { + dma_unmap_single(ipa3_ctx->pdev, entry->phys_base, + entry->hdr_len, DMA_TO_DEVICE); + } else { + if (offset) + list_move(&offset->link, + &htbl->head_free_offset_list[offset->bin]); + entry->offset_entry = NULL; + } htbl->hdr_cnt--; list_del(&entry->link); - dma_unmap_single(ipa3_ctx->pdev, entry->phys_base, - entry->hdr_len, DMA_TO_DEVICE); + fail_dma_mapping: entry->is_hdr_proc_ctx = false; @@ -591,8 +610,8 @@ static int __ipa3_del_hdr_proc_ctx(u32 proc_ctx_hdl, struct ipa3_hdr_proc_ctx_tbl *htbl = &ipa3_ctx->hdr_proc_ctx_tbl; entry = ipa3_id_find(proc_ctx_hdl); - if (!entry || (entry->cookie != IPA_COOKIE)) { - IPAERR("bad parm\n"); + if (!entry || (entry->cookie != IPA_HDR_COOKIE)) { + IPAERR_RL("bad parm\n"); return -EINVAL; } @@ -600,7 +619,7 @@ static int __ipa3_del_hdr_proc_ctx(u32 proc_ctx_hdl, htbl->proc_ctx_cnt, entry->offset_entry->offset); if (by_user && entry->user_deleted) { - IPAERR("proc_ctx already deleted by user\n"); + IPAERR_RL("proc_ctx already deleted by user\n"); return -EINVAL; } @@ -638,12 +657,12 @@ int __ipa3_del_hdr(u32 hdr_hdl, bool by_user) entry = ipa3_id_find(hdr_hdl); if (entry == NULL) { - IPAERR("lookup failed\n"); + IPAERR_RL("lookup failed\n"); return -EINVAL; } - if (entry->cookie != IPA_COOKIE) { - IPAERR("bad parm\n"); + if (entry->cookie != IPA_HDR_COOKIE) { + IPAERR_RL("bad parm\n"); return -EINVAL; } @@ -656,7 +675,7 @@ int __ipa3_del_hdr(u32 hdr_hdl, bool by_user) entry->offset_entry->offset); if (by_user && entry->user_deleted) { - IPAERR("proc_ctx already deleted by user\n"); + IPAERR_RL("proc_ctx already deleted by user\n"); return -EINVAL; } @@ -705,7 +724,7 @@ int ipa3_add_hdr(struct ipa_ioc_add_hdr *hdrs) int result = -EFAULT; if (hdrs == NULL || hdrs->num_hdrs == 0) { - IPAERR("bad parm\n"); + IPAERR_RL("bad parm\n"); return -EINVAL; } @@ -714,7 +733,7 @@ int ipa3_add_hdr(struct ipa_ioc_add_hdr *hdrs) hdrs->num_hdrs); for (i = 0; i < hdrs->num_hdrs; i++) { if (__ipa_add_hdr(&hdrs->hdr[i])) { - IPAERR("failed to add hdr %d\n", i); + IPAERR_RL("failed to add hdr %d\n", i); hdrs->hdr[i].status = -1; } else { hdrs->hdr[i].status = 0; @@ -750,14 +769,14 @@ int ipa3_del_hdr_by_user(struct ipa_ioc_del_hdr *hdls, bool by_user) int result = -EFAULT; if (hdls == NULL || hdls->num_hdls == 0) { - IPAERR("bad parm\n"); + IPAERR_RL("bad parm\n"); return -EINVAL; } mutex_lock(&ipa3_ctx->lock); for (i = 0; i < hdls->num_hdls; i++) { if (__ipa3_del_hdr(hdls->hdl[i].hdl, by_user)) { - IPAERR("failed to del hdr %i\n", i); + IPAERR_RL("failed to del hdr %i\n", i); hdls->hdl[i].status = -1; } else { hdls->hdl[i].status = 0; @@ -805,7 +824,7 @@ int ipa3_add_hdr_proc_ctx(struct ipa_ioc_add_hdr_proc_ctx *proc_ctxs) int result = -EFAULT; if (proc_ctxs == NULL || proc_ctxs->num_proc_ctxs == 0) { - IPAERR("bad parm\n"); + IPAERR_RL("bad parm\n"); return -EINVAL; } @@ -814,7 +833,7 @@ int ipa3_add_hdr_proc_ctx(struct ipa_ioc_add_hdr_proc_ctx *proc_ctxs) proc_ctxs->num_proc_ctxs); for (i = 0; i < proc_ctxs->num_proc_ctxs; i++) { if (__ipa_add_hdr_proc_ctx(&proc_ctxs->proc_ctx[i], true)) { - IPAERR("failed to add hdr pric ctx %d\n", i); + IPAERR_RL("failed to add hdr pric ctx %d\n", i); proc_ctxs->proc_ctx[i].status = -1; } else { proc_ctxs->proc_ctx[i].status = 0; @@ -852,14 +871,14 @@ int ipa3_del_hdr_proc_ctx_by_user(struct ipa_ioc_del_hdr_proc_ctx *hdls, int result; if (hdls == NULL || hdls->num_hdls == 0) { - IPAERR("bad parm\n"); + IPAERR_RL("bad parm\n"); return -EINVAL; } mutex_lock(&ipa3_ctx->lock); for (i = 0; i < hdls->num_hdls; i++) { if (__ipa3_del_hdr_proc_ctx(hdls->hdl[i].hdl, true, by_user)) { - IPAERR("failed to del hdr %i\n", i); + IPAERR_RL("failed to del hdr %i\n", i); hdls->hdl[i].status = -1; } else { hdls->hdl[i].status = 0; @@ -1066,7 +1085,7 @@ static struct ipa3_hdr_entry *__ipa_find_hdr(const char *name) struct ipa3_hdr_entry *entry; if (strnlen(name, IPA_RESOURCE_NAME_MAX) == IPA_RESOURCE_NAME_MAX) { - IPAERR("Header name too long: %s\n", name); + IPAERR_RL("Header name too long: %s\n", name); return NULL; } @@ -1096,7 +1115,7 @@ int ipa3_get_hdr(struct ipa_ioc_get_hdr *lookup) int result = -1; if (lookup == NULL) { - IPAERR("bad parm\n"); + IPAERR_RL("bad parm\n"); return -EINVAL; } mutex_lock(&ipa3_ctx->lock); @@ -1183,13 +1202,13 @@ int ipa3_put_hdr(u32 hdr_hdl) entry = ipa3_id_find(hdr_hdl); if (entry == NULL) { - IPAERR("lookup failed\n"); + IPAERR_RL("lookup failed\n"); result = -EINVAL; goto bail; } - if (entry->cookie != IPA_COOKIE) { - IPAERR("invalid header entry\n"); + if (entry->cookie != IPA_HDR_COOKIE) { + IPAERR_RL("invalid header entry\n"); result = -EINVAL; goto bail; } @@ -1217,7 +1236,7 @@ int ipa3_copy_hdr(struct ipa_ioc_copy_hdr *copy) int result = -EFAULT; if (copy == NULL) { - IPAERR("bad parm\n"); + IPAERR_RL("bad parm\n"); return -EINVAL; } mutex_lock(&ipa3_ctx->lock); diff --git a/drivers/platform/msm/ipa/ipa_v3/ipa_i.h b/drivers/platform/msm/ipa/ipa_v3/ipa_i.h index ac7ef6a21952..a890e88a8f61 100644 --- a/drivers/platform/msm/ipa/ipa_v3/ipa_i.h +++ b/drivers/platform/msm/ipa/ipa_v3/ipa_i.h @@ -40,6 +40,12 @@ #define DRV_NAME "ipa" #define NAT_DEV_NAME "ipaNatTable" #define IPA_COOKIE 0x57831603 +#define IPA_RT_RULE_COOKIE 0x57831604 +#define IPA_RT_TBL_COOKIE 0x57831605 +#define IPA_FLT_COOKIE 0x57831606 +#define IPA_HDR_COOKIE 0x57831607 +#define IPA_PROC_HDR_COOKIE 0x57831608 + #define MTU_BYTE 1500 #define IPA_EP_NOT_ALLOCATED (-1) @@ -89,6 +95,18 @@ } \ } while (0) +#define IPAERR_RL(fmt, args...) \ + do { \ + pr_err_ratelimited(DRV_NAME " %s:%d " fmt, __func__,\ + __LINE__, ## args);\ + if (ipa3_ctx) { \ + IPA_IPC_LOGGING(ipa3_ctx->logbuf, \ + DRV_NAME " %s:%d " fmt, ## args); \ + IPA_IPC_LOGGING(ipa3_ctx->logbuf_low, \ + DRV_NAME " %s:%d " fmt, ## args); \ + } \ + } while (0) + #define WLAN_AMPDU_TX_EP 15 #define WLAN_PROD_TX_EP 19 #define WLAN1_CONS_RX_EP 14 @@ -217,8 +235,8 @@ struct ipa_smmu_cb_ctx { */ struct ipa3_flt_entry { struct list_head link; - struct ipa_flt_rule rule; u32 cookie; + struct ipa_flt_rule rule; struct ipa3_flt_tbl *tbl; struct ipa3_rt_tbl *rt_tbl; u32 hw_len; @@ -246,13 +264,13 @@ struct ipa3_flt_entry { */ struct ipa3_rt_tbl { struct list_head link; + u32 cookie; struct list_head head_rt_rule_list; char name[IPA_RESOURCE_NAME_MAX]; u32 idx; u32 rule_cnt; u32 ref_cnt; struct ipa3_rt_tbl_set *set; - u32 cookie; bool in_sys[IPA_RULE_TYPE_MAX]; u32 sz[IPA_RULE_TYPE_MAX]; struct ipa_mem_buffer curr_mem[IPA_RULE_TYPE_MAX]; @@ -284,6 +302,7 @@ struct ipa3_rt_tbl { */ struct ipa3_hdr_entry { struct list_head link; + u32 cookie; u8 hdr[IPA_HDR_MAX_SIZE]; u32 hdr_len; char name[IPA_RESOURCE_NAME_MAX]; @@ -293,7 +312,6 @@ struct ipa3_hdr_entry { dma_addr_t phys_base; struct ipa3_hdr_proc_ctx_entry *proc_ctx; struct ipa_hdr_offset_entry *offset_entry; - u32 cookie; u32 ref_cnt; int id; u8 is_eth2_ofst_valid; @@ -342,10 +360,10 @@ struct ipa3_hdr_proc_ctx_offset_entry { */ struct ipa3_hdr_proc_ctx_entry { struct list_head link; + u32 cookie; enum ipa_hdr_proc_type type; struct ipa3_hdr_proc_ctx_offset_entry *offset_entry; struct ipa3_hdr_entry *hdr; - u32 cookie; u32 ref_cnt; int id; bool user_deleted; @@ -407,8 +425,8 @@ struct ipa3_flt_tbl { */ struct ipa3_rt_entry { struct list_head link; - struct ipa_rt_rule rule; u32 cookie; + struct ipa_rt_rule rule; struct ipa3_rt_tbl *tbl; struct ipa3_hdr_entry *hdr; struct ipa3_hdr_proc_ctx_entry *proc_ctx; diff --git a/drivers/platform/msm/ipa/ipa_v3/ipa_intf.c b/drivers/platform/msm/ipa/ipa_v3/ipa_intf.c index 38e8d4e9d639..76f37162f495 100644 --- a/drivers/platform/msm/ipa/ipa_v3/ipa_intf.c +++ b/drivers/platform/msm/ipa/ipa_v3/ipa_intf.c @@ -227,7 +227,7 @@ int ipa3_query_intf(struct ipa_ioc_query_intf *lookup) if (strnlen(lookup->name, IPA_RESOURCE_NAME_MAX) == IPA_RESOURCE_NAME_MAX) { - IPAERR("Interface name too long. (%s)\n", lookup->name); + IPAERR_RL("Interface name too long. (%s)\n", lookup->name); return result; } @@ -268,7 +268,7 @@ int ipa3_query_intf_tx_props(struct ipa_ioc_query_intf_tx_props *tx) } if (strnlen(tx->name, IPA_RESOURCE_NAME_MAX) == IPA_RESOURCE_NAME_MAX) { - IPAERR("Interface name too long. (%s)\n", tx->name); + IPAERR_RL("Interface name too long. (%s)\n", tx->name); return result; } @@ -277,7 +277,7 @@ int ipa3_query_intf_tx_props(struct ipa_ioc_query_intf_tx_props *tx) if (!strcmp(entry->name, tx->name)) { /* add the entry check */ if (entry->num_tx_props != tx->num_tx_props) { - IPAERR("invalid entry number(%u %u)\n", + IPAERR_RL("invalid entry number(%u %u)\n", entry->num_tx_props, tx->num_tx_props); mutex_unlock(&ipa3_ctx->lock); @@ -315,7 +315,7 @@ int ipa3_query_intf_rx_props(struct ipa_ioc_query_intf_rx_props *rx) } if (strnlen(rx->name, IPA_RESOURCE_NAME_MAX) == IPA_RESOURCE_NAME_MAX) { - IPAERR("Interface name too long. (%s)\n", rx->name); + IPAERR_RL("Interface name too long. (%s)\n", rx->name); return result; } @@ -324,7 +324,7 @@ int ipa3_query_intf_rx_props(struct ipa_ioc_query_intf_rx_props *rx) if (!strcmp(entry->name, rx->name)) { /* add the entry check */ if (entry->num_rx_props != rx->num_rx_props) { - IPAERR("invalid entry number(%u %u)\n", + IPAERR_RL("invalid entry number(%u %u)\n", entry->num_rx_props, rx->num_rx_props); mutex_unlock(&ipa3_ctx->lock); @@ -366,7 +366,7 @@ int ipa3_query_intf_ext_props(struct ipa_ioc_query_intf_ext_props *ext) if (!strcmp(entry->name, ext->name)) { /* add the entry check */ if (entry->num_ext_props != ext->num_ext_props) { - IPAERR("invalid entry number(%u %u)\n", + IPAERR_RL("invalid entry number(%u %u)\n", entry->num_ext_props, ext->num_ext_props); mutex_unlock(&ipa3_ctx->lock); @@ -410,13 +410,13 @@ int ipa3_send_msg(struct ipa_msg_meta *meta, void *buff, if (meta == NULL || (buff == NULL && callback != NULL) || (buff != NULL && callback == NULL)) { - IPAERR("invalid param meta=%p buff=%p, callback=%p\n", + IPAERR_RL("invalid param meta=%p buff=%p, callback=%p\n", meta, buff, callback); return -EINVAL; } if (meta->msg_type >= IPA_EVENT_MAX_NUM) { - IPAERR("unsupported message type %d\n", meta->msg_type); + IPAERR_RL("unsupported message type %d\n", meta->msg_type); return -EINVAL; } @@ -640,7 +640,7 @@ int ipa3_pull_msg(struct ipa_msg_meta *meta, char *buff, size_t count) int result = -EINVAL; if (meta == NULL || buff == NULL || !count) { - IPAERR("invalid param name=%p buff=%p count=%zu\n", + IPAERR_RL("invalid param name=%p buff=%p count=%zu\n", meta, buff, count); return result; } diff --git a/drivers/platform/msm/ipa/ipa_v3/ipa_nat.c b/drivers/platform/msm/ipa/ipa_v3/ipa_nat.c index e7e5cf114242..0256ff89ae24 100644 --- a/drivers/platform/msm/ipa/ipa_v3/ipa_nat.c +++ b/drivers/platform/msm/ipa/ipa_v3/ipa_nat.c @@ -1,4 +1,4 @@ -/* Copyright (c) 2012-2016, The Linux Foundation. All rights reserved. +/* Copyright (c) 2012-2017, The Linux Foundation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 and @@ -254,8 +254,8 @@ int ipa3_allocate_nat_device(struct ipa_ioc_nat_alloc_mem *mem) mutex_lock(&nat_ctx->lock); if (strcmp(mem->dev_name, NAT_DEV_NAME)) { - IPAERR("Nat device name mismatch\n"); - IPAERR("Expect: %s Recv: %s\n", NAT_DEV_NAME, mem->dev_name); + IPAERR_RL("Nat device name mismatch\n"); + IPAERR_RL("Expect: %s Recv: %s\n", NAT_DEV_NAME, mem->dev_name); result = -EPERM; goto bail; } @@ -274,7 +274,7 @@ int ipa3_allocate_nat_device(struct ipa_ioc_nat_alloc_mem *mem) if (mem->size <= 0 || nat_ctx->is_dev_init == true) { - IPAERR("Invalid Parameters or device is already init\n"); + IPAERR_RL("Invalid Parameters or device is already init\n"); result = -EPERM; goto bail; } @@ -337,16 +337,16 @@ int ipa3_nat_init_cmd(struct ipa_ioc_v4_nat_init *init) /* check for integer overflow */ if (init->ipv4_rules_offset > UINT_MAX - (TBL_ENTRY_SIZE * (init->table_entries + 1))) { - IPAERR("Detected overflow\n"); - return -EPERM; + IPAERR_RL("Detected overflow\n"); + return -EPERM; } /* Check Table Entry offset is not beyond allocated size */ tmp = init->ipv4_rules_offset + (TBL_ENTRY_SIZE * (init->table_entries + 1)); if (tmp > ipa3_ctx->nat_mem.size) { - IPAERR("Table rules offset not valid\n"); - IPAERR("offset:%d entrys:%d size:%zu mem_size:%zu\n", + IPAERR_RL("Table rules offset not valid\n"); + IPAERR_RL("offset:%d entrys:%d size:%zu mem_size:%zu\n", init->ipv4_rules_offset, (init->table_entries + 1), tmp, ipa3_ctx->nat_mem.size); return -EPERM; @@ -354,17 +354,17 @@ int ipa3_nat_init_cmd(struct ipa_ioc_v4_nat_init *init) /* check for integer overflow */ if (init->expn_rules_offset > - UINT_MAX - (TBL_ENTRY_SIZE * init->expn_table_entries)) { - IPAERR("Detected overflow\n"); - return -EPERM; + (UINT_MAX - (TBL_ENTRY_SIZE * init->expn_table_entries))) { + IPAERR_RL("Detected overflow\n"); + return -EPERM; } /* Check Expn Table Entry offset is not beyond allocated size */ tmp = init->expn_rules_offset + (TBL_ENTRY_SIZE * init->expn_table_entries); if (tmp > ipa3_ctx->nat_mem.size) { - IPAERR("Expn Table rules offset not valid\n"); - IPAERR("offset:%d entrys:%d size:%zu mem_size:%zu\n", + IPAERR_RL("Expn Table rules offset not valid\n"); + IPAERR_RL("offset:%d entrys:%d size:%zu mem_size:%zu\n", init->expn_rules_offset, init->expn_table_entries, tmp, ipa3_ctx->nat_mem.size); return -EPERM; @@ -373,16 +373,16 @@ int ipa3_nat_init_cmd(struct ipa_ioc_v4_nat_init *init) /* check for integer overflow */ if (init->index_offset > UINT_MAX - (INDX_TBL_ENTRY_SIZE * (init->table_entries + 1))) { - IPAERR("Detected overflow\n"); - return -EPERM; + IPAERR_RL("Detected overflow\n"); + return -EPERM; } /* Check Indx Table Entry offset is not beyond allocated size */ tmp = init->index_offset + (INDX_TBL_ENTRY_SIZE * (init->table_entries + 1)); if (tmp > ipa3_ctx->nat_mem.size) { - IPAERR("Indx Table rules offset not valid\n"); - IPAERR("offset:%d entrys:%d size:%zu mem_size:%zu\n", + IPAERR_RL("Indx Table rules offset not valid\n"); + IPAERR_RL("offset:%d entrys:%d size:%zu mem_size:%zu\n", init->index_offset, (init->table_entries + 1), tmp, ipa3_ctx->nat_mem.size); return -EPERM; @@ -391,16 +391,16 @@ int ipa3_nat_init_cmd(struct ipa_ioc_v4_nat_init *init) /* check for integer overflow */ if (init->index_expn_offset > UINT_MAX - (INDX_TBL_ENTRY_SIZE * init->expn_table_entries)) { - IPAERR("Detected overflow\n"); - return -EPERM; + IPAERR_RL("Detected overflow\n"); + return -EPERM; } /* Check Expn Table entry offset is not beyond allocated size */ tmp = init->index_expn_offset + (INDX_TBL_ENTRY_SIZE * init->expn_table_entries); if (tmp > ipa3_ctx->nat_mem.size) { - IPAERR("Indx Expn Table rules offset not valid\n"); - IPAERR("offset:%d entrys:%d size:%zu mem_size:%zu\n", + IPAERR_RL("Indx Expn Table rules offset not valid\n"); + IPAERR_RL("offset:%d entrys:%d size:%zu mem_size:%zu\n", init->index_expn_offset, init->expn_table_entries, tmp, ipa3_ctx->nat_mem.size); return -EPERM; @@ -437,16 +437,16 @@ int ipa3_nat_init_cmd(struct ipa_ioc_v4_nat_init *init) (init->expn_rules_offset > offset) || (init->index_offset > offset) || (init->index_expn_offset > offset)) { - IPAERR("Failed due to integer overflow\n"); - IPAERR("nat.mem.dma_handle: 0x%pa\n", + IPAERR_RL("Failed due to integer overflow\n"); + IPAERR_RL("nat.mem.dma_handle: 0x%pa\n", &ipa3_ctx->nat_mem.dma_handle); - IPAERR("ipv4_rules_offset: 0x%x\n", + IPAERR_RL("ipv4_rules_offset: 0x%x\n", init->ipv4_rules_offset); - IPAERR("expn_rules_offset: 0x%x\n", + IPAERR_RL("expn_rules_offset: 0x%x\n", init->expn_rules_offset); - IPAERR("index_offset: 0x%x\n", + IPAERR_RL("index_offset: 0x%x\n", init->index_offset); - IPAERR("index_expn_offset: 0x%x\n", + IPAERR_RL("index_expn_offset: 0x%x\n", init->index_expn_offset); result = -EPERM; goto free_nop; @@ -496,7 +496,7 @@ int ipa3_nat_init_cmd(struct ipa_ioc_v4_nat_init *init) cmd_pyld = ipahal_construct_imm_cmd( IPA_IMM_CMD_IP_V4_NAT_INIT, &cmd, false); if (!cmd_pyld) { - IPAERR("Fail to construct ip_v4_nat_init imm cmd\n"); + IPAERR_RL("Fail to construct ip_v4_nat_init imm cmd\n"); result = -EPERM; goto free_nop; } @@ -576,7 +576,7 @@ int ipa3_nat_dma_cmd(struct ipa_ioc_nat_dma_cmd *dma) IPADBG("\n"); if (dma->entries <= 0) { - IPAERR("Invalid number of commands %d\n", + IPAERR_RL("Invalid number of commands %d\n", dma->entries); ret = -EPERM; goto bail; @@ -584,7 +584,7 @@ int ipa3_nat_dma_cmd(struct ipa_ioc_nat_dma_cmd *dma) for (cnt = 0; cnt < dma->entries; cnt++) { if (dma->dma[cnt].table_index >= 1) { - IPAERR("Invalid table index %d\n", + IPAERR_RL("Invalid table index %d\n", dma->dma[cnt].table_index); ret = -EPERM; goto bail; @@ -595,7 +595,7 @@ int ipa3_nat_dma_cmd(struct ipa_ioc_nat_dma_cmd *dma) if (dma->dma[cnt].offset >= (ipa3_ctx->nat_mem.size_base_tables + 1) * NAT_TABLE_ENTRY_SIZE_BYTE) { - IPAERR("Invalid offset %d\n", + IPAERR_RL("Invalid offset %d\n", dma->dma[cnt].offset); ret = -EPERM; goto bail; @@ -607,7 +607,7 @@ int ipa3_nat_dma_cmd(struct ipa_ioc_nat_dma_cmd *dma) if (dma->dma[cnt].offset >= ipa3_ctx->nat_mem.size_expansion_tables * NAT_TABLE_ENTRY_SIZE_BYTE) { - IPAERR("Invalid offset %d\n", + IPAERR_RL("Invalid offset %d\n", dma->dma[cnt].offset); ret = -EPERM; goto bail; @@ -619,7 +619,7 @@ int ipa3_nat_dma_cmd(struct ipa_ioc_nat_dma_cmd *dma) if (dma->dma[cnt].offset >= (ipa3_ctx->nat_mem.size_base_tables + 1) * NAT_INTEX_TABLE_ENTRY_SIZE_BYTE) { - IPAERR("Invalid offset %d\n", + IPAERR_RL("Invalid offset %d\n", dma->dma[cnt].offset); ret = -EPERM; goto bail; @@ -631,7 +631,7 @@ int ipa3_nat_dma_cmd(struct ipa_ioc_nat_dma_cmd *dma) if (dma->dma[cnt].offset >= ipa3_ctx->nat_mem.size_expansion_tables * NAT_INTEX_TABLE_ENTRY_SIZE_BYTE) { - IPAERR("Invalid offset %d\n", + IPAERR_RL("Invalid offset %d\n", dma->dma[cnt].offset); ret = -EPERM; goto bail; @@ -640,7 +640,7 @@ int ipa3_nat_dma_cmd(struct ipa_ioc_nat_dma_cmd *dma) break; default: - IPAERR("Invalid base_addr %d\n", + IPAERR_RL("Invalid base_addr %d\n", dma->dma[cnt].base_addr); ret = -EPERM; goto bail; @@ -679,7 +679,7 @@ int ipa3_nat_dma_cmd(struct ipa_ioc_nat_dma_cmd *dma) cmd_pyld = ipahal_construct_imm_cmd( IPA_IMM_CMD_NAT_DMA, &cmd, false); if (!cmd_pyld) { - IPAERR("Fail to construct nat_dma imm cmd\n"); + IPAERR_RL("Fail to construct nat_dma imm cmd\n"); continue; } desc[1].type = IPA_IMM_CMD_DESC; @@ -796,7 +796,7 @@ int ipa3_nat_del_cmd(struct ipa_ioc_v4_nat_del *del) cmd_pyld = ipahal_construct_imm_cmd( IPA_IMM_CMD_IP_V4_NAT_INIT, &cmd, false); if (!cmd_pyld) { - IPAERR("Fail to construct ip_v4_nat_init imm cmd\n"); + IPAERR_RL("Fail to construct ip_v4_nat_init imm cmd\n"); result = -EPERM; goto destroy_regwrt_imm_cmd; } diff --git a/drivers/platform/msm/ipa/ipa_v3/ipa_rt.c b/drivers/platform/msm/ipa/ipa_v3/ipa_rt.c index 6197c9f64ca5..bc7cc7060545 100644 --- a/drivers/platform/msm/ipa/ipa_v3/ipa_rt.c +++ b/drivers/platform/msm/ipa/ipa_v3/ipa_rt.c @@ -697,7 +697,7 @@ struct ipa3_rt_tbl *__ipa3_find_rt_tbl(enum ipa_ip_type ip, const char *name) struct ipa3_rt_tbl_set *set; if (strnlen(name, IPA_RESOURCE_NAME_MAX) == IPA_RESOURCE_NAME_MAX) { - IPAERR("Name too long: %s\n", name); + IPAERR_RL("Name too long: %s\n", name); return NULL; } @@ -723,7 +723,7 @@ int ipa3_query_rt_index(struct ipa_ioc_get_rt_tbl_indx *in) struct ipa3_rt_tbl *entry; if (in->ip >= IPA_IP_MAX) { - IPAERR("bad parm\n"); + IPAERR_RL("bad parm\n"); return -EINVAL; } @@ -749,7 +749,7 @@ static struct ipa3_rt_tbl *__ipa_add_rt_tbl(enum ipa_ip_type ip, int max_tbl_indx; if (name == NULL) { - IPAERR("no tbl name\n"); + IPAERR_RL("no tbl name\n"); goto error; } @@ -762,7 +762,7 @@ static struct ipa3_rt_tbl *__ipa_add_rt_tbl(enum ipa_ip_type ip, max(IPA_MEM_PART(v6_modem_rt_index_hi), IPA_MEM_PART(v6_apps_rt_index_hi)); } else { - IPAERR("bad ip family type\n"); + IPAERR_RL("bad ip family type\n"); goto error; } @@ -796,7 +796,7 @@ static struct ipa3_rt_tbl *__ipa_add_rt_tbl(enum ipa_ip_type ip, INIT_LIST_HEAD(&entry->link); strlcpy(entry->name, name, IPA_RESOURCE_NAME_MAX); entry->set = set; - entry->cookie = IPA_COOKIE; + entry->cookie = IPA_RT_TBL_COOKIE; entry->in_sys[IPA_RULE_HASHABLE] = (ip == IPA_IP_v4) ? !ipa3_ctx->ip4_rt_tbl_hash_lcl : !ipa3_ctx->ip6_rt_tbl_hash_lcl; @@ -814,12 +814,16 @@ static struct ipa3_rt_tbl *__ipa_add_rt_tbl(enum ipa_ip_type ip, if (id < 0) { IPAERR("failed to add to tree\n"); WARN_ON(1); + goto ipa_insert_failed; } entry->id = id; } return entry; - +ipa_insert_failed: + set->tbl_cnt--; + list_del(&entry->link); + idr_destroy(&entry->rule_ids); fail_rt_idx_alloc: entry->cookie = 0; kmem_cache_free(ipa3_ctx->rt_tbl_cache, entry); @@ -833,13 +837,13 @@ static int __ipa_del_rt_tbl(struct ipa3_rt_tbl *entry) u32 id; struct ipa3_rt_tbl_set *rset; - if (entry == NULL || (entry->cookie != IPA_COOKIE)) { - IPAERR("bad parms\n"); + if (entry == NULL || (entry->cookie != IPA_RT_TBL_COOKIE)) { + IPAERR_RL("bad parms\n"); return -EINVAL; } id = entry->id; if (ipa3_id_find(id) == NULL) { - IPAERR("lookup failed\n"); + IPAERR_RL("lookup failed\n"); return -EPERM; } @@ -847,8 +851,10 @@ static int __ipa_del_rt_tbl(struct ipa3_rt_tbl *entry) ip = IPA_IP_v4; else if (entry->set == &ipa3_ctx->rt_tbl_set[IPA_IP_v6]) ip = IPA_IP_v6; - else + else { WARN_ON(1); + return -EPERM; + } rset = &ipa3_ctx->reap_rt_tbl_set[ip]; @@ -885,14 +891,14 @@ static int __ipa_rt_validate_hndls(const struct ipa_rt_rule *rule, if (rule->hdr_hdl) { *hdr = ipa3_id_find(rule->hdr_hdl); - if ((*hdr == NULL) || ((*hdr)->cookie != IPA_COOKIE)) { + if ((*hdr == NULL) || ((*hdr)->cookie != IPA_HDR_COOKIE)) { IPAERR("rt rule does not point to valid hdr\n"); return -EPERM; } } else if (rule->hdr_proc_ctx_hdl) { *proc_ctx = ipa3_id_find(rule->hdr_proc_ctx_hdl); if ((*proc_ctx == NULL) || - ((*proc_ctx)->cookie != IPA_COOKIE)) { + ((*proc_ctx)->cookie != IPA_PROC_HDR_COOKIE)) { IPAERR("rt rule does not point to valid proc ctx\n"); return -EPERM; @@ -915,7 +921,7 @@ static int __ipa_create_rt_entry(struct ipa3_rt_entry **entry, goto error; } INIT_LIST_HEAD(&(*entry)->link); - (*(entry))->cookie = IPA_COOKIE; + (*(entry))->cookie = IPA_RT_RULE_COOKIE; (*(entry))->rule = *rule; (*(entry))->tbl = tbl; (*(entry))->hdr = hdr; @@ -983,8 +989,8 @@ static int __ipa_add_rt_rule(enum ipa_ip_type ip, const char *name, tbl = __ipa_add_rt_tbl(ip, name); - if (tbl == NULL || (tbl->cookie != IPA_COOKIE)) { - IPAERR("failed adding rt tbl name = %s\n", + if (tbl == NULL || (tbl->cookie != IPA_RT_TBL_COOKIE)) { + IPAERR_RL("failed adding rt tbl name = %s\n", name ? name : ""); goto error; } @@ -994,8 +1000,8 @@ static int __ipa_add_rt_rule(enum ipa_ip_type ip, const char *name, */ if (!strcmp(tbl->name, IPA_DFLT_RT_TBL_NAME) && (tbl->rule_cnt > 0) && (at_rear != 0)) { - IPAERR("cannot add rule at end of tbl rule_cnt=%d at_rear=%d\n", - tbl->rule_cnt, at_rear); + IPAERR_RL("cannot add rule at end of tbl rule_cnt=%d at_rear=%d" + , tbl->rule_cnt, at_rear); goto error; } @@ -1065,7 +1071,7 @@ int ipa3_add_rt_rule(struct ipa_ioc_add_rt_rule *rules) int ret; if (rules == NULL || rules->num_rules == 0 || rules->ip >= IPA_IP_MAX) { - IPAERR("bad parm\n"); + IPAERR_RL("bad parm\n"); return -EINVAL; } @@ -1075,7 +1081,7 @@ int ipa3_add_rt_rule(struct ipa_ioc_add_rt_rule *rules) &rules->rules[i].rule, rules->rules[i].at_rear, &rules->rules[i].rt_rule_hdl)) { - IPAERR("failed to add rt rule %d\n", i); + IPAERR_RL("failed to add rt rule %d\n", i); rules->rules[i].status = IPA_RT_STATUS_OF_ADD_FAILED; } else { rules->rules[i].status = 0; @@ -1111,36 +1117,36 @@ int ipa3_add_rt_rule_after(struct ipa_ioc_add_rt_rule_after *rules) struct ipa3_rt_entry *entry = NULL; if (rules == NULL || rules->num_rules == 0 || rules->ip >= IPA_IP_MAX) { - IPAERR("bad parm\n"); + IPAERR_RL("bad parm\n"); return -EINVAL; } mutex_lock(&ipa3_ctx->lock); tbl = __ipa3_find_rt_tbl(rules->ip, rules->rt_tbl_name); - if (tbl == NULL || (tbl->cookie != IPA_COOKIE)) { - IPAERR("failed finding rt tbl name = %s\n", + if (tbl == NULL || (tbl->cookie != IPA_RT_TBL_COOKIE)) { + IPAERR_RL("failed finding rt tbl name = %s\n", rules->rt_tbl_name ? rules->rt_tbl_name : ""); ret = -EINVAL; goto bail; } if (tbl->rule_cnt <= 0) { - IPAERR("tbl->rule_cnt <= 0"); + IPAERR_RL("tbl->rule_cnt <= 0"); ret = -EINVAL; goto bail; } entry = ipa3_id_find(rules->add_after_hdl); if (!entry) { - IPAERR("failed finding rule %d in rt tbls\n", + IPAERR_RL("failed finding rule %d in rt tbls\n", rules->add_after_hdl); ret = -EINVAL; goto bail; } if (entry->tbl != tbl) { - IPAERR("given rt rule does not match the table\n"); + IPAERR_RL("given rt rule does not match the table\n"); ret = -EINVAL; goto bail; } @@ -1151,7 +1157,7 @@ int ipa3_add_rt_rule_after(struct ipa_ioc_add_rt_rule_after *rules) */ if (!strcmp(tbl->name, IPA_DFLT_RT_TBL_NAME) && (&entry->link == tbl->head_rt_rule_list.prev)) { - IPAERR("cannot add rule at end of tbl rule_cnt=%d\n", + IPAERR_RL("cannot add rule at end of tbl rule_cnt=%d\n", tbl->rule_cnt); ret = -EINVAL; goto bail; @@ -1168,7 +1174,7 @@ int ipa3_add_rt_rule_after(struct ipa_ioc_add_rt_rule_after *rules) &rules->rules[i].rule, &rules->rules[i].rt_rule_hdl, &entry)) { - IPAERR("failed to add rt rule %d\n", i); + IPAERR_RL("failed to add rt rule %d\n", i); rules->rules[i].status = IPA_RT_STATUS_OF_ADD_FAILED; } else { rules->rules[i].status = 0; @@ -1177,7 +1183,7 @@ int ipa3_add_rt_rule_after(struct ipa_ioc_add_rt_rule_after *rules) if (rules->commit) if (ipa3_ctx->ctrl->ipa3_commit_rt(rules->ip)) { - IPAERR("failed to commit\n"); + IPAERR_RL("failed to commit\n"); ret = -EPERM; goto bail; } @@ -1198,12 +1204,12 @@ int __ipa3_del_rt_rule(u32 rule_hdl) entry = ipa3_id_find(rule_hdl); if (entry == NULL) { - IPAERR("lookup failed\n"); + IPAERR_RL("lookup failed\n"); return -EINVAL; } - if (entry->cookie != IPA_COOKIE) { - IPAERR("bad params\n"); + if (entry->cookie != IPA_RT_RULE_COOKIE) { + IPAERR_RL("bad params\n"); return -EINVAL; } @@ -1219,7 +1225,7 @@ int __ipa3_del_rt_rule(u32 rule_hdl) idr_remove(&entry->tbl->rule_ids, entry->rule_id); if (entry->tbl->rule_cnt == 0 && entry->tbl->ref_cnt == 0) { if (__ipa_del_rt_tbl(entry->tbl)) - IPAERR("fail to del RT tbl\n"); + IPAERR_RL("fail to del RT tbl\n"); } entry->cookie = 0; id = entry->id; @@ -1246,14 +1252,14 @@ int ipa3_del_rt_rule(struct ipa_ioc_del_rt_rule *hdls) int ret; if (hdls == NULL || hdls->num_hdls == 0 || hdls->ip >= IPA_IP_MAX) { - IPAERR("bad parm\n"); + IPAERR_RL("bad parm\n"); return -EINVAL; } mutex_lock(&ipa3_ctx->lock); for (i = 0; i < hdls->num_hdls; i++) { if (__ipa3_del_rt_rule(hdls->hdl[i].hdl)) { - IPAERR("failed to del rt rule %i\n", i); + IPAERR_RL("failed to del rt rule %i\n", i); hdls->hdl[i].status = IPA_RT_STATUS_OF_DEL_FAILED; } else { hdls->hdl[i].status = 0; @@ -1286,7 +1292,7 @@ int ipa3_commit_rt(enum ipa_ip_type ip) int ret; if (ip >= IPA_IP_MAX) { - IPAERR("bad parm\n"); + IPAERR_RL("bad parm\n"); return -EINVAL; } @@ -1330,7 +1336,7 @@ int ipa3_reset_rt(enum ipa_ip_type ip) int id; if (ip >= IPA_IP_MAX) { - IPAERR("bad parm\n"); + IPAERR_RL("bad parm\n"); return -EINVAL; } @@ -1346,7 +1352,7 @@ int ipa3_reset_rt(enum ipa_ip_type ip) * filtering rules point to routing tables */ if (ipa3_reset_flt(ip)) - IPAERR("fail to reset flt ip=%d\n", ip); + IPAERR_RL("fail to reset flt ip=%d\n", ip); set = &ipa3_ctx->rt_tbl_set[ip]; rset = &ipa3_ctx->reap_rt_tbl_set[ip]; @@ -1435,14 +1441,14 @@ int ipa3_get_rt_tbl(struct ipa_ioc_get_rt_tbl *lookup) int result = -EFAULT; if (lookup == NULL || lookup->ip >= IPA_IP_MAX) { - IPAERR("bad parm\n"); + IPAERR_RL("bad parm\n"); return -EINVAL; } mutex_lock(&ipa3_ctx->lock); entry = __ipa3_find_rt_tbl(lookup->ip, lookup->name); - if (entry && entry->cookie == IPA_COOKIE) { + if (entry && entry->cookie == IPA_RT_TBL_COOKIE) { if (entry->ref_cnt == U32_MAX) { - IPAERR("fail: ref count crossed limit\n"); + IPAERR_RL("fail: ref count crossed limit\n"); goto ret; } entry->ref_cnt++; @@ -1450,7 +1456,7 @@ int ipa3_get_rt_tbl(struct ipa_ioc_get_rt_tbl *lookup) /* commit for get */ if (ipa3_ctx->ctrl->ipa3_commit_rt(lookup->ip)) - IPAERR("fail to commit RT tbl\n"); + IPAERR_RL("fail to commit RT tbl\n"); result = 0; } @@ -1478,13 +1484,13 @@ int ipa3_put_rt_tbl(u32 rt_tbl_hdl) mutex_lock(&ipa3_ctx->lock); entry = ipa3_id_find(rt_tbl_hdl); if (entry == NULL) { - IPAERR("lookup failed\n"); + IPAERR_RL("lookup failed\n"); result = -EINVAL; goto ret; } - if ((entry->cookie != IPA_COOKIE) || entry->ref_cnt == 0) { - IPAERR("bad parms\n"); + if ((entry->cookie != IPA_RT_TBL_COOKIE) || entry->ref_cnt == 0) { + IPAERR_RL("bad parms\n"); result = -EINVAL; goto ret; } @@ -1493,18 +1499,20 @@ int ipa3_put_rt_tbl(u32 rt_tbl_hdl) ip = IPA_IP_v4; else if (entry->set == &ipa3_ctx->rt_tbl_set[IPA_IP_v6]) ip = IPA_IP_v6; - else + else { WARN_ON(1); + goto ret; + } entry->ref_cnt--; if (entry->ref_cnt == 0 && entry->rule_cnt == 0) { IPADBG("zero ref_cnt, delete rt tbl (idx=%u)\n", entry->idx); if (__ipa_del_rt_tbl(entry)) - IPAERR("fail to del RT tbl\n"); + IPAERR_RL("fail to del RT tbl\n"); /* commit for put */ if (ipa3_ctx->ctrl->ipa3_commit_rt(ip)) - IPAERR("fail to commit RT tbl\n"); + IPAERR_RL("fail to commit RT tbl\n"); } result = 0; @@ -1524,26 +1532,27 @@ static int __ipa_mdfy_rt_rule(struct ipa_rt_rule_mdfy *rtrule) if (rtrule->rule.hdr_hdl) { hdr = ipa3_id_find(rtrule->rule.hdr_hdl); - if ((hdr == NULL) || (hdr->cookie != IPA_COOKIE)) { - IPAERR("rt rule does not point to valid hdr\n"); + if ((hdr == NULL) || (hdr->cookie != IPA_HDR_COOKIE)) { + IPAERR_RL("rt rule does not point to valid hdr\n"); goto error; } } else if (rtrule->rule.hdr_proc_ctx_hdl) { proc_ctx = ipa3_id_find(rtrule->rule.hdr_proc_ctx_hdl); - if ((proc_ctx == NULL) || (proc_ctx->cookie != IPA_COOKIE)) { - IPAERR("rt rule does not point to valid proc ctx\n"); + if ((proc_ctx == NULL) || + (proc_ctx->cookie != IPA_PROC_HDR_COOKIE)) { + IPAERR_RL("rt rule does not point to valid proc ctx\n"); goto error; } } entry = ipa3_id_find(rtrule->rt_rule_hdl); if (entry == NULL) { - IPAERR("lookup failed\n"); + IPAERR_RL("lookup failed\n"); goto error; } - if (entry->cookie != IPA_COOKIE) { - IPAERR("bad params\n"); + if (entry->cookie != IPA_RT_RULE_COOKIE) { + IPAERR_RL("bad params\n"); goto error; } @@ -1584,14 +1593,14 @@ int ipa3_mdfy_rt_rule(struct ipa_ioc_mdfy_rt_rule *hdls) int result; if (hdls == NULL || hdls->num_rules == 0 || hdls->ip >= IPA_IP_MAX) { - IPAERR("bad parm\n"); + IPAERR_RL("bad parm\n"); return -EINVAL; } mutex_lock(&ipa3_ctx->lock); for (i = 0; i < hdls->num_rules; i++) { if (__ipa_mdfy_rt_rule(&hdls->rules[i])) { - IPAERR("failed to mdfy rt rule %i\n", i); + IPAERR_RL("failed to mdfy rt rule %i\n", i); hdls->rules[i].status = IPA_RT_STATUS_OF_MDFY_FAILED; } else { hdls->rules[i].status = 0; diff --git a/drivers/platform/msm/ipa/ipa_v3/ipa_uc_wdi.c b/drivers/platform/msm/ipa/ipa_v3/ipa_uc_wdi.c index e49bdc8c7083..d3837a05fdc2 100644 --- a/drivers/platform/msm/ipa/ipa_v3/ipa_uc_wdi.c +++ b/drivers/platform/msm/ipa/ipa_v3/ipa_uc_wdi.c @@ -1664,7 +1664,7 @@ int ipa3_write_qmapid_wdi_pipe(u32 clnt_hdl, u8 qmap_id) if (clnt_hdl >= ipa3_ctx->ipa_num_pipes || ipa3_ctx->ep[clnt_hdl].valid == 0) { - IPAERR("bad parm, %d\n", clnt_hdl); + IPAERR_RL("bad parm, %d\n", clnt_hdl); return -EINVAL; } @@ -1677,7 +1677,7 @@ int ipa3_write_qmapid_wdi_pipe(u32 clnt_hdl, u8 qmap_id) ep = &ipa3_ctx->ep[clnt_hdl]; if (!(ep->uc_offload_state & IPA_WDI_CONNECTED)) { - IPAERR("WDI channel bad state %d\n", ep->uc_offload_state); + IPAERR_RL("WDI channel bad state %d\n", ep->uc_offload_state); return -EFAULT; } IPA_ACTIVE_CLIENTS_INC_EP(ipa3_get_client_mapping(clnt_hdl)); diff --git a/drivers/platform/msm/ipa/ipa_v3/ipa_utils.c b/drivers/platform/msm/ipa/ipa_v3/ipa_utils.c index 6647f919a577..1fa1196dda63 100644 --- a/drivers/platform/msm/ipa/ipa_v3/ipa_utils.c +++ b/drivers/platform/msm/ipa/ipa_v3/ipa_utils.c @@ -838,7 +838,7 @@ int ipa3_cfg_route(struct ipahal_reg_route *route) */ int ipa3_cfg_filter(u32 disable) { - IPAERR("Filter disable is not supported!\n"); + IPAERR_RL("Filter disable is not supported!\n"); return -EPERM; } @@ -928,7 +928,7 @@ int ipa3_get_ep_mapping(enum ipa_client_type client) int ipa_ep_idx; if (client >= IPA_CLIENT_MAX || client < 0) { - IPAERR("Bad client number! client =%d\n", client); + IPAERR_RL("Bad client number! client =%d\n", client); return IPA_EP_NOT_ALLOCATED; } @@ -2001,19 +2001,19 @@ int ipa3_write_qmap_id(struct ipa_ioc_write_qmapid *param_in) int result = -EINVAL; if (param_in->client >= IPA_CLIENT_MAX) { - IPAERR("bad parm client:%d\n", param_in->client); + IPAERR_RL("bad parm client:%d\n", param_in->client); goto fail; } ipa_ep_idx = ipa3_get_ep_mapping(param_in->client); if (ipa_ep_idx == -1) { - IPAERR("Invalid client.\n"); + IPAERR_RL("Invalid client.\n"); goto fail; } ep = &ipa3_ctx->ep[ipa_ep_idx]; if (!ep->valid) { - IPAERR("EP not allocated.\n"); + IPAERR_RL("EP not allocated.\n"); goto fail; } @@ -2026,7 +2026,7 @@ int ipa3_write_qmap_id(struct ipa_ioc_write_qmapid *param_in) ipa3_ctx->ep[ipa_ep_idx].cfg.meta = meta; result = ipa3_write_qmapid_wdi_pipe(ipa_ep_idx, meta.qmap_id); if (result) - IPAERR("qmap_id %d write failed on ep=%d\n", + IPAERR_RL("qmap_id %d write failed on ep=%d\n", meta.qmap_id, ipa_ep_idx); result = 0; } diff --git a/drivers/platform/x86/ideapad-laptop.c b/drivers/platform/x86/ideapad-laptop.c index be3bc2f4edd4..09cc64b3b695 100644 --- a/drivers/platform/x86/ideapad-laptop.c +++ b/drivers/platform/x86/ideapad-laptop.c @@ -807,6 +807,7 @@ static void ideapad_acpi_notify(acpi_handle handle, u32 event, void *data) case 11: case 7: case 6: + case 1: ideapad_input_report(priv, vpc_bit); break; case 5: diff --git a/drivers/power/qcom/msm-core.c b/drivers/power/qcom/msm-core.c index 43ad33ea234b..825c27e7a4c1 100644 --- a/drivers/power/qcom/msm-core.c +++ b/drivers/power/qcom/msm-core.c @@ -190,10 +190,12 @@ static void core_temp_notify(enum thermal_trip_type type, struct cpu_activity_info *cpu_node = (struct cpu_activity_info *) data; + temp /= scaling_factor; + trace_temp_notification(cpu_node->sensor_id, type, temp, cpu_node->temp); - cpu_node->temp = temp / scaling_factor; + cpu_node->temp = temp; complete(&sampling_completion); } diff --git a/drivers/power/supply/qcom/qpnp-smb2.c b/drivers/power/supply/qcom/qpnp-smb2.c index 0908eea3b186..7b7f991ecba9 100644 --- a/drivers/power/supply/qcom/qpnp-smb2.c +++ b/drivers/power/supply/qcom/qpnp-smb2.c @@ -1847,6 +1847,12 @@ static int smb2_post_init(struct smb2 *chip) struct smb_charger *chg = &chip->chg; int rc; + /* In case the usb path is suspended, we would have missed disabling + * the icl change interrupt because the interrupt could have been + * not requested + */ + rerun_election(chg->usb_icl_votable); + /* configure power role for dual-role */ rc = smblib_masked_write(chg, TYPE_C_INTRPT_ENB_SOFTWARE_CTRL_REG, TYPEC_POWER_ROLE_CMD_MASK, 0); @@ -2196,6 +2202,8 @@ static int smb2_request_interrupts(struct smb2 *chip) return rc; } } + if (chg->irq_info[USBIN_ICL_CHANGE_IRQ].irq) + chg->usb_icl_change_irq_enabled = true; return rc; } diff --git a/drivers/power/supply/qcom/smb-lib.c b/drivers/power/supply/qcom/smb-lib.c index 16db425514c3..64d71727f7e6 100644 --- a/drivers/power/supply/qcom/smb-lib.c +++ b/drivers/power/supply/qcom/smb-lib.c @@ -427,6 +427,14 @@ static int step_charge_soc_update(struct smb_charger *chg, int capacity) int smblib_set_usb_suspend(struct smb_charger *chg, bool suspend) { int rc = 0; + int irq = chg->irq_info[USBIN_ICL_CHANGE_IRQ].irq; + + if (suspend && irq) { + if (chg->usb_icl_change_irq_enabled) { + disable_irq_nosync(irq); + chg->usb_icl_change_irq_enabled = false; + } + } rc = smblib_masked_write(chg, USBIN_CMD_IL_REG, USBIN_SUSPEND_BIT, suspend ? USBIN_SUSPEND_BIT : 0); @@ -434,6 +442,13 @@ int smblib_set_usb_suspend(struct smb_charger *chg, bool suspend) smblib_err(chg, "Couldn't write %s to USBIN_SUSPEND_BIT rc=%d\n", suspend ? "suspend" : "resume", rc); + if (!suspend && irq) { + if (!chg->usb_icl_change_irq_enabled) { + enable_irq(irq); + chg->usb_icl_change_irq_enabled = true; + } + } + return rc; } @@ -885,7 +900,6 @@ int smblib_set_icl_current(struct smb_charger *chg, int icl_ua) if (icl_ua < USBIN_25MA) return smblib_set_usb_suspend(chg, true); - disable_irq_nosync(chg->irq_info[USBIN_ICL_CHANGE_IRQ].irq); if (icl_ua == INT_MAX) goto override_suspend_config; @@ -943,7 +957,6 @@ override_suspend_config: } enable_icl_changed_interrupt: - enable_irq(chg->irq_info[USBIN_ICL_CHANGE_IRQ].irq); return rc; } @@ -1319,68 +1332,110 @@ int smblib_vconn_regulator_is_enabled(struct regulator_dev *rdev) #define MAX_RETRY 15 #define MIN_DELAY_US 2000 #define MAX_DELAY_US 9000 -static int _smblib_vbus_regulator_enable(struct regulator_dev *rdev) +static int otg_current[] = {250000, 500000, 1000000, 1500000}; +static int smblib_enable_otg_wa(struct smb_charger *chg) { - struct smb_charger *chg = rdev_get_drvdata(rdev); - int rc, retry_count = 0, min_delay = MIN_DELAY_US; u8 stat; + int rc, i, retry_count = 0, min_delay = MIN_DELAY_US; - smblib_dbg(chg, PR_OTG, "halt 1 in 8 mode\n"); - rc = smblib_masked_write(chg, OTG_ENG_OTG_CFG_REG, - ENG_BUCKBOOST_HALT1_8_MODE_BIT, - ENG_BUCKBOOST_HALT1_8_MODE_BIT); - if (rc < 0) { - smblib_err(chg, "Couldn't set OTG_ENG_OTG_CFG_REG rc=%d\n", - rc); - return rc; - } + for (i = 0; i < ARRAY_SIZE(otg_current); i++) { + smblib_dbg(chg, PR_OTG, "enabling OTG with %duA\n", + otg_current[i]); + rc = smblib_set_charge_param(chg, &chg->param.otg_cl, + otg_current[i]); + if (rc < 0) { + smblib_err(chg, "Couldn't set otg limit rc=%d\n", rc); + return rc; + } - smblib_dbg(chg, PR_OTG, "enabling OTG\n"); - rc = smblib_write(chg, CMD_OTG_REG, OTG_EN_BIT); - if (rc < 0) { - smblib_err(chg, "Couldn't enable OTG regulator rc=%d\n", rc); - return rc; - } + rc = smblib_write(chg, CMD_OTG_REG, OTG_EN_BIT); + if (rc < 0) { + smblib_err(chg, "Couldn't enable OTG rc=%d\n", rc); + return rc; + } - if (chg->wa_flags & OTG_WA) { - /* check for softstart */ + retry_count = 0; + min_delay = MIN_DELAY_US; do { usleep_range(min_delay, min_delay + 100); rc = smblib_read(chg, OTG_STATUS_REG, &stat); if (rc < 0) { - smblib_err(chg, - "Couldn't read OTG status rc=%d\n", - rc); + smblib_err(chg, "Couldn't read OTG status rc=%d\n", + rc); goto out; } if (stat & BOOST_SOFTSTART_DONE_BIT) { rc = smblib_set_charge_param(chg, &chg->param.otg_cl, chg->otg_cl_ua); - if (rc < 0) - smblib_err(chg, - "Couldn't set otg limit\n"); + if (rc < 0) { + smblib_err(chg, "Couldn't set otg limit rc=%d\n", + rc); + goto out; + } break; } - /* increase the delay for following iterations */ if (retry_count > 5) min_delay = MAX_DELAY_US; + } while (retry_count++ < MAX_RETRY); if (retry_count >= MAX_RETRY) { - smblib_dbg(chg, PR_OTG, "Boost Softstart not done\n"); - goto out; + smblib_dbg(chg, PR_OTG, "OTG enable failed with %duA\n", + otg_current[i]); + rc = smblib_write(chg, CMD_OTG_REG, 0); + if (rc < 0) { + smblib_err(chg, "disable OTG rc=%d\n", rc); + goto out; + } + } else { + smblib_dbg(chg, PR_OTG, "OTG enabled\n"); + return 0; } } + if (i == ARRAY_SIZE(otg_current)) { + rc = -EINVAL; + goto out; + } + return 0; out: - /* disable OTG if softstart failed */ smblib_write(chg, CMD_OTG_REG, 0); return rc; } +static int _smblib_vbus_regulator_enable(struct regulator_dev *rdev) +{ + struct smb_charger *chg = rdev_get_drvdata(rdev); + int rc; + + smblib_dbg(chg, PR_OTG, "halt 1 in 8 mode\n"); + rc = smblib_masked_write(chg, OTG_ENG_OTG_CFG_REG, + ENG_BUCKBOOST_HALT1_8_MODE_BIT, + ENG_BUCKBOOST_HALT1_8_MODE_BIT); + if (rc < 0) { + smblib_err(chg, "Couldn't set OTG_ENG_OTG_CFG_REG rc=%d\n", + rc); + return rc; + } + + smblib_dbg(chg, PR_OTG, "enabling OTG\n"); + + if (chg->wa_flags & OTG_WA) { + rc = smblib_enable_otg_wa(chg); + if (rc < 0) + smblib_err(chg, "Couldn't enable OTG rc=%d\n", rc); + } else { + rc = smblib_write(chg, CMD_OTG_REG, OTG_EN_BIT); + if (rc < 0) + smblib_err(chg, "Couldn't enable OTG rc=%d\n", rc); + } + + return rc; +} + int smblib_vbus_regulator_enable(struct regulator_dev *rdev) { struct smb_charger *chg = rdev_get_drvdata(rdev); diff --git a/drivers/power/supply/qcom/smb-lib.h b/drivers/power/supply/qcom/smb-lib.h index c97b84c34084..18714827b8d2 100644 --- a/drivers/power/supply/qcom/smb-lib.h +++ b/drivers/power/supply/qcom/smb-lib.h @@ -328,6 +328,7 @@ struct smb_charger { int fake_input_current_limited; bool pr_swap_in_progress; int typec_mode; + int usb_icl_change_irq_enabled; /* workaround flag */ u32 wa_flags; diff --git a/drivers/scsi/lpfc/lpfc_els.c b/drivers/scsi/lpfc/lpfc_els.c index 59ced8864b2f..0e6aaef9a038 100644 --- a/drivers/scsi/lpfc/lpfc_els.c +++ b/drivers/scsi/lpfc/lpfc_els.c @@ -3563,12 +3563,14 @@ lpfc_els_free_iocb(struct lpfc_hba *phba, struct lpfc_iocbq *elsiocb) } else { buf_ptr1 = (struct lpfc_dmabuf *) elsiocb->context2; lpfc_els_free_data(phba, buf_ptr1); + elsiocb->context2 = NULL; } } if (elsiocb->context3) { buf_ptr = (struct lpfc_dmabuf *) elsiocb->context3; lpfc_els_free_bpl(phba, buf_ptr); + elsiocb->context3 = NULL; } lpfc_sli_release_iocbq(phba, elsiocb); return 0; diff --git a/drivers/scsi/lpfc/lpfc_sli.c b/drivers/scsi/lpfc/lpfc_sli.c index f5aeda8f014f..38e90d9c2ced 100644 --- a/drivers/scsi/lpfc/lpfc_sli.c +++ b/drivers/scsi/lpfc/lpfc_sli.c @@ -5887,18 +5887,25 @@ lpfc_sli4_alloc_resource_identifiers(struct lpfc_hba *phba) free_vfi_bmask: kfree(phba->sli4_hba.vfi_bmask); + phba->sli4_hba.vfi_bmask = NULL; free_xri_ids: kfree(phba->sli4_hba.xri_ids); + phba->sli4_hba.xri_ids = NULL; free_xri_bmask: kfree(phba->sli4_hba.xri_bmask); + phba->sli4_hba.xri_bmask = NULL; free_vpi_ids: kfree(phba->vpi_ids); + phba->vpi_ids = NULL; free_vpi_bmask: kfree(phba->vpi_bmask); + phba->vpi_bmask = NULL; free_rpi_ids: kfree(phba->sli4_hba.rpi_ids); + phba->sli4_hba.rpi_ids = NULL; free_rpi_bmask: kfree(phba->sli4_hba.rpi_bmask); + phba->sli4_hba.rpi_bmask = NULL; err_exit: return rc; } diff --git a/drivers/scsi/qla2xxx/qla_isr.c b/drivers/scsi/qla2xxx/qla_isr.c index 0e59731f95ad..1f6a3b86965f 100644 --- a/drivers/scsi/qla2xxx/qla_isr.c +++ b/drivers/scsi/qla2xxx/qla_isr.c @@ -2466,6 +2466,10 @@ qla2x00_error_entry(scsi_qla_host_t *vha, struct rsp_que *rsp, sts_entry_t *pkt) if (pkt->entry_status & RF_BUSY) res = DID_BUS_BUSY << 16; + if (pkt->entry_type == NOTIFY_ACK_TYPE && + pkt->handle == QLA_TGT_SKIP_HANDLE) + return; + sp = qla2x00_get_sp_from_handle(vha, func, req, pkt); if (sp) { sp->done(ha, sp, res); diff --git a/drivers/scsi/qla2xxx/qla_target.c b/drivers/scsi/qla2xxx/qla_target.c index f57d96984ae4..e6faa0b050d1 100644 --- a/drivers/scsi/qla2xxx/qla_target.c +++ b/drivers/scsi/qla2xxx/qla_target.c @@ -2865,7 +2865,7 @@ static int __qlt_send_term_imm_notif(struct scsi_qla_host *vha, pkt->entry_type = NOTIFY_ACK_TYPE; pkt->entry_count = 1; - pkt->handle = QLA_TGT_SKIP_HANDLE | CTIO_COMPLETION_HANDLE_MARK; + pkt->handle = QLA_TGT_SKIP_HANDLE; nack = (struct nack_to_isp *)pkt; nack->ox_id = ntfy->ox_id; diff --git a/drivers/scsi/sd.c b/drivers/scsi/sd.c index 9b3af788376c..8aa202faafb5 100644 --- a/drivers/scsi/sd.c +++ b/drivers/scsi/sd.c @@ -2497,7 +2497,8 @@ sd_read_cache_type(struct scsi_disk *sdkp, unsigned char *buffer) if (sdp->broken_fua) { sd_first_printk(KERN_NOTICE, sdkp, "Disabling FUA\n"); sdkp->DPOFUA = 0; - } else if (sdkp->DPOFUA && !sdkp->device->use_10_for_rw) { + } else if (sdkp->DPOFUA && !sdkp->device->use_10_for_rw && + !sdkp->device->use_16_for_rw) { sd_first_printk(KERN_NOTICE, sdkp, "Uses READ/WRITE(6), disabling FUA\n"); sdkp->DPOFUA = 0; diff --git a/drivers/scsi/virtio_scsi.c b/drivers/scsi/virtio_scsi.c index 7dbbb29d24c6..03a2aadf0d3c 100644 --- a/drivers/scsi/virtio_scsi.c +++ b/drivers/scsi/virtio_scsi.c @@ -533,7 +533,9 @@ static int virtscsi_queuecommand(struct virtio_scsi *vscsi, { struct Scsi_Host *shost = virtio_scsi_host(vscsi->vdev); struct virtio_scsi_cmd *cmd = scsi_cmd_priv(sc); + unsigned long flags; int req_size; + int ret; BUG_ON(scsi_sg_count(sc) > shost->sg_tablesize); @@ -561,8 +563,15 @@ static int virtscsi_queuecommand(struct virtio_scsi *vscsi, req_size = sizeof(cmd->req.cmd); } - if (virtscsi_kick_cmd(req_vq, cmd, req_size, sizeof(cmd->resp.cmd)) != 0) + ret = virtscsi_kick_cmd(req_vq, cmd, req_size, sizeof(cmd->resp.cmd)); + if (ret == -EIO) { + cmd->resp.cmd.response = VIRTIO_SCSI_S_BAD_TARGET; + spin_lock_irqsave(&req_vq->vq_lock, flags); + virtscsi_complete_cmd(vscsi, cmd); + spin_unlock_irqrestore(&req_vq->vq_lock, flags); + } else if (ret != 0) { return SCSI_MLQUEUE_HOST_BUSY; + } return 0; } diff --git a/drivers/spi/spi-davinci.c b/drivers/spi/spi-davinci.c index 7d3af3eacf57..1ddba9ae8c0f 100644 --- a/drivers/spi/spi-davinci.c +++ b/drivers/spi/spi-davinci.c @@ -651,7 +651,7 @@ static int davinci_spi_bufs(struct spi_device *spi, struct spi_transfer *t) buf = t->rx_buf; t->rx_dma = dma_map_single(&spi->dev, buf, t->len, DMA_FROM_DEVICE); - if (!t->rx_dma) { + if (dma_mapping_error(&spi->dev, !t->rx_dma)) { ret = -EFAULT; goto err_rx_map; } @@ -665,7 +665,7 @@ static int davinci_spi_bufs(struct spi_device *spi, struct spi_transfer *t) buf = (void *)t->tx_buf; t->tx_dma = dma_map_single(&spi->dev, buf, t->len, DMA_TO_DEVICE); - if (!t->tx_dma) { + if (dma_mapping_error(&spi->dev, t->tx_dma)) { ret = -EFAULT; goto err_tx_map; } diff --git a/drivers/tty/serial/msm_serial_hs.c b/drivers/tty/serial/msm_serial_hs.c index 830ef92ffe80..fc9faaee3170 100644 --- a/drivers/tty/serial/msm_serial_hs.c +++ b/drivers/tty/serial/msm_serial_hs.c @@ -272,7 +272,7 @@ static struct of_device_id msm_hs_match_table[] = { #define UARTDM_TX_BUF_SIZE UART_XMIT_SIZE #define UARTDM_RX_BUF_SIZE 512 #define RETRY_TIMEOUT 5 -#define UARTDM_NR 256 +#define UARTDM_NR 4 #define BAM_PIPE_MIN 0 #define BAM_PIPE_MAX 11 #define BUS_SCALING 1 diff --git a/drivers/usb/dwc3/dwc3-msm.c b/drivers/usb/dwc3/dwc3-msm.c index c2d788bc4bc5..8e8c1a349e6a 100644 --- a/drivers/usb/dwc3/dwc3-msm.c +++ b/drivers/usb/dwc3/dwc3-msm.c @@ -54,6 +54,8 @@ #include "debug.h" #include "xhci.h" +#define SDP_CONNETION_CHECK_TIME 10000 /* in ms */ + /* time out to wait for USB cable status notification (in ms)*/ #define SM_INIT_TIMEOUT 30000 @@ -227,6 +229,7 @@ struct dwc3_msm { int pm_qos_latency; struct pm_qos_request pm_qos_req_dma; struct delayed_work perf_vote_work; + struct delayed_work sdp_check; }; #define USB_HSPHY_3P3_VOL_MIN 3050000 /* uV */ @@ -2625,6 +2628,42 @@ done: return NOTIFY_DONE; } + +static void check_for_sdp_connection(struct work_struct *w) +{ + int ret; + union power_supply_propval pval = {0}; + struct dwc3_msm *mdwc = + container_of(w, struct dwc3_msm, sdp_check.work); + struct dwc3 *dwc = platform_get_drvdata(mdwc->dwc3); + + if (!mdwc->vbus_active) + return; + + /* floating D+/D- lines detected */ + if (dwc->gadget.state < USB_STATE_DEFAULT && + dwc3_gadget_get_link_state(dwc) != DWC3_LINK_STATE_CMPLY) { + if (!mdwc->usb_psy) { + mdwc->usb_psy = power_supply_get_by_name("usb"); + if (!mdwc->usb_psy) { + dev_dbg(mdwc->dev, + "Could not get usb power_supply\n"); + return; + } + } + pval.intval = -ETIMEDOUT; + ret = power_supply_set_property(mdwc->usb_psy, + POWER_SUPPLY_PROP_CURRENT_MAX, &pval); + if (ret) + dev_dbg(mdwc->dev, + "power supply error when setting property\n"); + + mdwc->vbus_active = 0; + dbg_event(0xFF, "Q RW SPD CHK", mdwc->vbus_active); + queue_work(mdwc->dwc3_wq, &mdwc->resume_work); + } +} + static int dwc3_msm_vbus_notifier(struct notifier_block *nb, unsigned long event, void *ptr) { @@ -2833,6 +2872,7 @@ static int dwc3_msm_probe(struct platform_device *pdev) INIT_WORK(&mdwc->vbus_draw_work, dwc3_msm_vbus_draw_work); INIT_DELAYED_WORK(&mdwc->sm_work, dwc3_otg_sm_work); INIT_DELAYED_WORK(&mdwc->perf_vote_work, msm_dwc3_perf_vote_work); + INIT_DELAYED_WORK(&mdwc->sdp_check, check_for_sdp_connection); mdwc->dwc3_wq = alloc_ordered_workqueue("dwc3_wq", 0); if (!mdwc->dwc3_wq) { @@ -3586,28 +3626,38 @@ static int dwc3_otg_start_peripheral(struct dwc3_msm *mdwc, int on) return 0; } -static int dwc3_msm_gadget_vbus_draw(struct dwc3_msm *mdwc, unsigned mA) +int get_psy_type(struct dwc3_msm *mdwc) { union power_supply_propval pval = {0}; - int ret; if (mdwc->charging_disabled) - return 0; - - if (mdwc->max_power == mA) - return 0; + return -EINVAL; if (!mdwc->usb_psy) { mdwc->usb_psy = power_supply_get_by_name("usb"); if (!mdwc->usb_psy) { - dev_warn(mdwc->dev, "Could not get usb power_supply\n"); + dev_err(mdwc->dev, "Could not get usb psy\n"); return -ENODEV; } } - power_supply_get_property(mdwc->usb_psy, - POWER_SUPPLY_PROP_REAL_TYPE, &pval); - if (pval.intval != POWER_SUPPLY_TYPE_USB) + power_supply_get_property(mdwc->usb_psy, POWER_SUPPLY_PROP_REAL_TYPE, + &pval); + + return pval.intval; +} + +static int dwc3_msm_gadget_vbus_draw(struct dwc3_msm *mdwc, unsigned mA) +{ + union power_supply_propval pval = {0}; + int ret, psy_type; + + if (mdwc->max_power == mA) + return 0; + + psy_type = get_psy_type(mdwc); + if (psy_type != POWER_SUPPLY_TYPE_USB && + psy_type != POWER_SUPPLY_TYPE_USB_FLOAT) return 0; dev_info(mdwc->dev, "Avail curr from USB = %u\n", mA); @@ -3684,6 +3734,10 @@ static void dwc3_otg_sm_work(struct work_struct *w) work = 1; } else if (test_bit(B_SESS_VLD, &mdwc->inputs)) { dev_dbg(mdwc->dev, "b_sess_vld\n"); + if (get_psy_type(mdwc) == POWER_SUPPLY_TYPE_USB_FLOAT) + queue_delayed_work(mdwc->dwc3_wq, + &mdwc->sdp_check, + msecs_to_jiffies(SDP_CONNETION_CHECK_TIME)); /* * Increment pm usage count upon cable connect. Count * is decremented in OTG_STATE_B_PERIPHERAL state on @@ -3707,6 +3761,7 @@ static void dwc3_otg_sm_work(struct work_struct *w) !test_bit(ID, &mdwc->inputs)) { dev_dbg(mdwc->dev, "!id || !bsv\n"); mdwc->otg_state = OTG_STATE_B_IDLE; + cancel_delayed_work_sync(&mdwc->sdp_check); dwc3_otg_start_peripheral(mdwc, 0); /* * Decrement pm usage count upon cable disconnect @@ -3739,6 +3794,7 @@ static void dwc3_otg_sm_work(struct work_struct *w) if (!test_bit(B_SESS_VLD, &mdwc->inputs)) { dev_dbg(mdwc->dev, "BSUSP: !bsv\n"); mdwc->otg_state = OTG_STATE_B_IDLE; + cancel_delayed_work_sync(&mdwc->sdp_check); dwc3_otg_start_peripheral(mdwc, 0); } else if (!test_bit(B_SUSPEND, &mdwc->inputs)) { dev_dbg(mdwc->dev, "BSUSP !susp\n"); diff --git a/drivers/usb/pd/policy_engine.c b/drivers/usb/pd/policy_engine.c index 03aeec2e878c..3f1c2b32abb8 100644 --- a/drivers/usb/pd/policy_engine.c +++ b/drivers/usb/pd/policy_engine.c @@ -182,7 +182,7 @@ static void *usbpd_ipc_log; #define PS_HARD_RESET_TIME 25 #define PS_SOURCE_ON 400 #define PS_SOURCE_OFF 750 -#define SWAP_SOURCE_START_TIME 20 +#define FIRST_SOURCE_CAP_TIME 200 #define VDM_BUSY_TIME 50 #define VCONN_ON_TIME 100 @@ -790,17 +790,27 @@ static void usbpd_set_state(struct usbpd *pd, enum usbpd_state next_state) pd->pd_phy_opened = true; } - pd->current_state = PE_SRC_SEND_CAPABILITIES; if (pd->in_pr_swap) { - kick_sm(pd, SWAP_SOURCE_START_TIME); pd->in_pr_swap = false; val.intval = 0; power_supply_set_property(pd->usb_psy, POWER_SUPPLY_PROP_PR_SWAP, &val); - break; } - /* fall-through */ + /* + * A sink might remove its terminations (during some Type-C + * compliance tests or a sink attempting to do Try.SRC) + * at this point just after we enabled VBUS. Sending PD + * messages now would delay detecting the detach beyond the + * required timing. Instead, delay sending out the first + * source capabilities to allow for the other side to + * completely settle CC debounce and allow HW to detect detach + * sooner in the meantime. PD spec allows up to + * tFirstSourceCap (250ms). + */ + pd->current_state = PE_SRC_SEND_CAPABILITIES; + kick_sm(pd, FIRST_SOURCE_CAP_TIME); + break; case PE_SRC_SEND_CAPABILITIES: kick_sm(pd, 0); @@ -910,6 +920,7 @@ static void usbpd_set_state(struct usbpd *pd, enum usbpd_state next_state) if (pd->psy_type == POWER_SUPPLY_TYPE_USB || pd->psy_type == POWER_SUPPLY_TYPE_USB_CDP || + pd->psy_type == POWER_SUPPLY_TYPE_USB_FLOAT || usb_compliance_mode) start_usb_peripheral(pd); } diff --git a/drivers/vfio/vfio_iommu_spapr_tce.c b/drivers/vfio/vfio_iommu_spapr_tce.c index 1a9f18b40be6..34e4b3ad8b92 100644 --- a/drivers/vfio/vfio_iommu_spapr_tce.c +++ b/drivers/vfio/vfio_iommu_spapr_tce.c @@ -1163,6 +1163,10 @@ static int tce_iommu_attach_group(void *iommu_data, /* pr_debug("tce_vfio: Attaching group #%u to iommu %p\n", iommu_group_id(iommu_group), iommu_group); */ table_group = iommu_group_get_iommudata(iommu_group); + if (!table_group) { + ret = -ENODEV; + goto unlock_exit; + } if (tce_groups_attached(container) && (!table_group->ops || !table_group->ops->take_ownership || diff --git a/drivers/video/fbdev/msm/mdss.h b/drivers/video/fbdev/msm/mdss.h index d6e8a213c215..5548f0f09f8a 100644 --- a/drivers/video/fbdev/msm/mdss.h +++ b/drivers/video/fbdev/msm/mdss.h @@ -547,6 +547,7 @@ struct mdss_data_type { u32 sec_session_cnt; wait_queue_head_t secure_waitq; struct cx_ipeak_client *mdss_cx_ipeak; + struct mult_factor bus_throughput_factor; }; extern struct mdss_data_type *mdss_res; diff --git a/drivers/video/fbdev/msm/mdss_mdp.c b/drivers/video/fbdev/msm/mdss_mdp.c index 6936c4c1f3cc..6fb32761a767 100644 --- a/drivers/video/fbdev/msm/mdss_mdp.c +++ b/drivers/video/fbdev/msm/mdss_mdp.c @@ -4527,6 +4527,15 @@ static int mdss_mdp_parse_dt_misc(struct platform_device *pdev) mdss_mdp_parse_dt_fudge_factors(pdev, "qcom,mdss-clk-factor", &mdata->clk_factor); + /* + * Bus throughput factor will be used during high downscale cases. + * The recommended default factor is 1.1. + */ + mdata->bus_throughput_factor.numer = 11; + mdata->bus_throughput_factor.denom = 10; + mdss_mdp_parse_dt_fudge_factors(pdev, "qcom,mdss-bus-througput-factor", + &mdata->bus_throughput_factor); + rc = of_property_read_u32(pdev->dev.of_node, "qcom,max-bandwidth-low-kbps", &mdata->max_bw_low); if (rc) diff --git a/drivers/video/fbdev/msm/mdss_mdp_ctl.c b/drivers/video/fbdev/msm/mdss_mdp_ctl.c index efd681a5d954..0165c48a0467 100644 --- a/drivers/video/fbdev/msm/mdss_mdp_ctl.c +++ b/drivers/video/fbdev/msm/mdss_mdp_ctl.c @@ -31,6 +31,7 @@ #define MDSS_MDP_QSEED3_VER_DOWNSCALE_LIM 2 #define NUM_MIXERCFG_REGS 3 #define MDSS_MDP_WB_OUTPUT_BPP 3 +#define MIN_BUS_THROUGHPUT_SCALE_FACTOR 35 struct mdss_mdp_mixer_cfg { u32 config_masks[NUM_MIXERCFG_REGS]; bool border_enabled; @@ -622,11 +623,21 @@ static u32 __calc_qseed3_mdp_clk_rate(struct mdss_mdp_pipe *pipe, } static inline bool __is_vert_downscaling(u32 src_h, - struct mdss_rect dst){ - + struct mdss_rect dst) +{ return (src_h > dst.h); } +static inline bool __is_bus_throughput_factor_required(u32 src_h, + struct mdss_rect dst) +{ + u32 scale_factor = src_h * 10; + + do_div(scale_factor, dst.h); + return (__is_vert_downscaling(src_h, dst) && + (scale_factor >= MIN_BUS_THROUGHPUT_SCALE_FACTOR)); +} + static u32 get_pipe_mdp_clk_rate(struct mdss_mdp_pipe *pipe, struct mdss_rect src, struct mdss_rect dst, u32 fps, u32 v_total, u32 flags) @@ -673,6 +684,15 @@ static u32 get_pipe_mdp_clk_rate(struct mdss_mdp_pipe *pipe, } } + /* + * If the downscale factor is >= 3.5 for a 32 BPP surface, + * it is recommended to add a 10% bus throughput factor to + * the clock rate. + */ + if ((pipe->src_fmt->bpp == 4) && + __is_bus_throughput_factor_required(src_h, dst)) + rate = apply_fudge_factor(rate, &mdata->bus_throughput_factor); + if (flags & PERF_CALC_PIPE_APPLY_CLK_FUDGE) rate = mdss_mdp_clk_fudge_factor(mixer, rate); diff --git a/drivers/video/fbdev/msm/mdss_mdp_layer.c b/drivers/video/fbdev/msm/mdss_mdp_layer.c index e44edb8fbea7..3ccc09d58480 100644 --- a/drivers/video/fbdev/msm/mdss_mdp_layer.c +++ b/drivers/video/fbdev/msm/mdss_mdp_layer.c @@ -3131,6 +3131,14 @@ int mdss_mdp_layer_pre_commit_wfd(struct msm_fb_data_type *mfd, sync_pt_data = &mfd->mdp_sync_pt_data; mutex_lock(&sync_pt_data->sync_mutex); count = sync_pt_data->acq_fen_cnt; + + if (count >= MDP_MAX_FENCE_FD) { + pr_err("Reached maximum possible value for fence count\n"); + mutex_unlock(&sync_pt_data->sync_mutex); + rc = -EINVAL; + goto input_layer_err; + } + sync_pt_data->acq_fen[count] = fence; sync_pt_data->acq_fen_cnt++; mutex_unlock(&sync_pt_data->sync_mutex); diff --git a/drivers/video/fbdev/msm/mdss_mdp_pp_cache_config.c b/drivers/video/fbdev/msm/mdss_mdp_pp_cache_config.c index 017a2f10dfbc..a5ec7097e0f6 100644 --- a/drivers/video/fbdev/msm/mdss_mdp_pp_cache_config.c +++ b/drivers/video/fbdev/msm/mdss_mdp_pp_cache_config.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2014-2016, The Linux Foundation. All rights reserved. + * Copyright (c) 2014-2017, The Linux Foundation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 and @@ -194,8 +194,12 @@ static int pp_hist_lut_cache_params_pipe_v1_7(struct mdp_hist_lut_data *config, return -EINVAL; } - memcpy(&hist_lut_usr_config, config->cfg_payload, - sizeof(struct mdp_hist_lut_data_v1_7)); + if (copy_from_user(&hist_lut_usr_config, + (void __user *) config->cfg_payload, + sizeof(hist_lut_usr_config))) { + pr_err("failed to copy hist lut config\n"); + return -EFAULT; + } hist_lut_cache_data = pipe->pp_res.hist_lut_cfg_payload; if (!hist_lut_cache_data) { @@ -606,8 +610,12 @@ static int pp_pcc_cache_params_pipe_v1_7(struct mdp_pcc_cfg_data *config, return -EINVAL; } - memcpy(&v17_usr_config, config->cfg_payload, - sizeof(v17_usr_config)); + if (copy_from_user(&v17_usr_config, + (void __user *) config->cfg_payload, + sizeof(v17_usr_config))) { + pr_err("failed to copy pcc config\n"); + return -EFAULT; + } if (!(config->ops & MDP_PP_OPS_WRITE)) { pr_debug("write ops not set value of flag is %d\n", @@ -861,8 +869,12 @@ static int pp_igc_lut_cache_params_pipe_v1_7(struct mdp_igc_lut_data *config, goto igc_config_exit; } - memcpy(&v17_usr_config, config->cfg_payload, - sizeof(v17_usr_config)); + if (copy_from_user(&v17_usr_config, + (void __user *) config->cfg_payload, + sizeof(v17_usr_config))) { + pr_err("failed to copy igc usr config\n"); + return -EFAULT; + } if (!(config->ops & MDP_PP_OPS_WRITE)) { pr_debug("op for gamut %d\n", config->ops); @@ -1272,8 +1284,12 @@ static int pp_pa_cache_params_pipe_v1_7(struct mdp_pa_v2_cfg_data *config, return -EINVAL; } - memcpy(&pa_usr_config, config->cfg_payload, - sizeof(struct mdp_pa_data_v1_7)); + if (copy_from_user(&pa_usr_config, + (void __user *) config->cfg_payload, + sizeof(pa_usr_config))) { + pr_err("failed to copy pa usr config\n"); + return -EFAULT; + } pa_cache_data = pipe->pp_res.pa_cfg_payload; if (!pa_cache_data) { diff --git a/drivers/video/fbdev/msm/msm_mdss_io_8974.c b/drivers/video/fbdev/msm/msm_mdss_io_8974.c index 80dbe83972d7..bb3b4b3fa929 100644 --- a/drivers/video/fbdev/msm/msm_mdss_io_8974.c +++ b/drivers/video/fbdev/msm/msm_mdss_io_8974.c @@ -2587,7 +2587,8 @@ int mdss_dsi_post_clkon_cb(void *priv, } if (clk & MDSS_DSI_LINK_CLK) { /* toggle the resync FIFO everytime clock changes */ - if (ctrl->shared_data->phy_rev == DSI_PHY_REV_30) + if ((ctrl->shared_data->phy_rev == DSI_PHY_REV_30) && + !pdata->panel_info.cont_splash_enabled) mdss_dsi_phy_v3_toggle_resync_fifo(ctrl); if (ctrl->ulps) { diff --git a/drivers/watchdog/bcm_kona_wdt.c b/drivers/watchdog/bcm_kona_wdt.c index e0c98423f2c9..11a72bc2c71b 100644 --- a/drivers/watchdog/bcm_kona_wdt.c +++ b/drivers/watchdog/bcm_kona_wdt.c @@ -304,6 +304,8 @@ static int bcm_kona_wdt_probe(struct platform_device *pdev) if (!wdt) return -ENOMEM; + spin_lock_init(&wdt->lock); + res = platform_get_resource(pdev, IORESOURCE_MEM, 0); wdt->base = devm_ioremap_resource(dev, res); if (IS_ERR(wdt->base)) @@ -316,7 +318,6 @@ static int bcm_kona_wdt_probe(struct platform_device *pdev) return ret; } - spin_lock_init(&wdt->lock); platform_set_drvdata(pdev, wdt); watchdog_set_drvdata(&bcm_kona_wdt_wdd, wdt); bcm_kona_wdt_wdd.parent = &pdev->dev; diff --git a/drivers/xen/swiotlb-xen.c b/drivers/xen/swiotlb-xen.c index 7399782c0998..8a58bbc14de2 100644 --- a/drivers/xen/swiotlb-xen.c +++ b/drivers/xen/swiotlb-xen.c @@ -409,9 +409,9 @@ dma_addr_t xen_swiotlb_map_page(struct device *dev, struct page *page, if (map == SWIOTLB_MAP_ERROR) return DMA_ERROR_CODE; + dev_addr = xen_phys_to_bus(map); xen_dma_map_page(dev, pfn_to_page(map >> PAGE_SHIFT), dev_addr, map & ~PAGE_MASK, size, dir, attrs); - dev_addr = xen_phys_to_bus(map); /* * Ensure that the address returned is DMA'ble @@ -567,13 +567,14 @@ xen_swiotlb_map_sg_attrs(struct device *hwdev, struct scatterlist *sgl, sg_dma_len(sgl) = 0; return 0; } + dev_addr = xen_phys_to_bus(map); xen_dma_map_page(hwdev, pfn_to_page(map >> PAGE_SHIFT), dev_addr, map & ~PAGE_MASK, sg->length, dir, attrs); - sg->dma_address = xen_phys_to_bus(map); + sg->dma_address = dev_addr; } else { /* we are not interested in the dma_addr returned by * xen_dma_map_page, only in the potential cache flushes executed diff --git a/fs/binfmt_elf.c b/fs/binfmt_elf.c index 0c52941dd62c..6c031dd1bc4e 100644 --- a/fs/binfmt_elf.c +++ b/fs/binfmt_elf.c @@ -2295,6 +2295,7 @@ static int elf_core_dump(struct coredump_params *cprm) goto end_coredump; } } + dump_truncate(cprm); if (!elf_core_write_extra_data(cprm)) goto end_coredump; diff --git a/fs/btrfs/inode.c b/fs/btrfs/inode.c index 863fa0f1972b..a61926cb01c0 100644 --- a/fs/btrfs/inode.c +++ b/fs/btrfs/inode.c @@ -4397,8 +4397,19 @@ search_again: if (found_type > min_type) { del_item = 1; } else { - if (item_end < new_size) + if (item_end < new_size) { + /* + * With NO_HOLES mode, for the following mapping + * + * [0-4k][hole][8k-12k] + * + * if truncating isize down to 6k, it ends up + * isize being 8k. + */ + if (btrfs_fs_incompat(root->fs_info, NO_HOLES)) + last_size = new_size; break; + } if (found_key.offset >= new_size) del_item = 1; else diff --git a/fs/coredump.c b/fs/coredump.c index fe0a28da18a6..2ce5ef429c48 100644 --- a/fs/coredump.c +++ b/fs/coredump.c @@ -810,3 +810,21 @@ int dump_align(struct coredump_params *cprm, int align) return mod ? dump_skip(cprm, align - mod) : 1; } EXPORT_SYMBOL(dump_align); + +/* + * Ensures that file size is big enough to contain the current file + * postion. This prevents gdb from complaining about a truncated file + * if the last "write" to the file was dump_skip. + */ +void dump_truncate(struct coredump_params *cprm) +{ + struct file *file = cprm->file; + loff_t offset; + + if (file->f_op->llseek && file->f_op->llseek != no_llseek) { + offset = file->f_op->llseek(file, 0, SEEK_CUR); + if (i_size_read(file->f_mapping->host) < offset) + do_truncate(file->f_path.dentry, offset, 0, file); + } +} +EXPORT_SYMBOL(dump_truncate); diff --git a/fs/nfs/nfs4proc.c b/fs/nfs/nfs4proc.c index 4e3679b25b9b..8e425f2c5ddd 100644 --- a/fs/nfs/nfs4proc.c +++ b/fs/nfs/nfs4proc.c @@ -2188,8 +2188,6 @@ static int nfs4_opendata_access(struct rpc_cred *cred, if ((mask & ~cache.mask & (MAY_READ | MAY_EXEC)) == 0) return 0; - /* even though OPEN succeeded, access is denied. Close the file */ - nfs4_close_state(state, fmode); return -EACCES; } diff --git a/fs/ocfs2/cluster/heartbeat.c b/fs/ocfs2/cluster/heartbeat.c index 709fbbd44c65..acebc350e98d 100644 --- a/fs/ocfs2/cluster/heartbeat.c +++ b/fs/ocfs2/cluster/heartbeat.c @@ -2070,13 +2070,13 @@ unlock: spin_unlock(&o2hb_live_lock); } -static ssize_t o2hb_heartbeat_group_threshold_show(struct config_item *item, +static ssize_t o2hb_heartbeat_group_dead_threshold_show(struct config_item *item, char *page) { return sprintf(page, "%u\n", o2hb_dead_threshold); } -static ssize_t o2hb_heartbeat_group_threshold_store(struct config_item *item, +static ssize_t o2hb_heartbeat_group_dead_threshold_store(struct config_item *item, const char *page, size_t count) { unsigned long tmp; @@ -2125,11 +2125,11 @@ static ssize_t o2hb_heartbeat_group_mode_store(struct config_item *item, } -CONFIGFS_ATTR(o2hb_heartbeat_group_, threshold); +CONFIGFS_ATTR(o2hb_heartbeat_group_, dead_threshold); CONFIGFS_ATTR(o2hb_heartbeat_group_, mode); static struct configfs_attribute *o2hb_heartbeat_group_attrs[] = { - &o2hb_heartbeat_group_attr_threshold, + &o2hb_heartbeat_group_attr_dead_threshold, &o2hb_heartbeat_group_attr_mode, NULL, }; diff --git a/include/linux/coredump.h b/include/linux/coredump.h index d016a121a8c4..28ffa94aed6b 100644 --- a/include/linux/coredump.h +++ b/include/linux/coredump.h @@ -14,6 +14,7 @@ struct coredump_params; extern int dump_skip(struct coredump_params *cprm, size_t nr); extern int dump_emit(struct coredump_params *cprm, const void *addr, int nr); extern int dump_align(struct coredump_params *cprm, int align); +extern void dump_truncate(struct coredump_params *cprm); #ifdef CONFIG_COREDUMP extern void do_coredump(const siginfo_t *siginfo); #else diff --git a/include/net/xfrm.h b/include/net/xfrm.h index d18cbafc3455..c81d806e415f 100644 --- a/include/net/xfrm.h +++ b/include/net/xfrm.h @@ -947,10 +947,6 @@ struct xfrm_dst { struct flow_cache_object flo; struct xfrm_policy *pols[XFRM_POLICY_TYPE_MAX]; int num_pols, num_xfrms; -#ifdef CONFIG_XFRM_SUB_POLICY - struct flowi *origin; - struct xfrm_selector *partner; -#endif u32 xfrm_genid; u32 policy_genid; u32 route_mtu_cached; @@ -966,12 +962,6 @@ static inline void xfrm_dst_destroy(struct xfrm_dst *xdst) dst_release(xdst->route); if (likely(xdst->u.dst.xfrm)) xfrm_state_put(xdst->u.dst.xfrm); -#ifdef CONFIG_XFRM_SUB_POLICY - kfree(xdst->origin); - xdst->origin = NULL; - kfree(xdst->partner); - xdst->partner = NULL; -#endif } #endif diff --git a/include/soc/qcom/qseecomi.h b/include/soc/qcom/qseecomi.h index 6497d962e347..e199978302bf 100644 --- a/include/soc/qcom/qseecomi.h +++ b/include/soc/qcom/qseecomi.h @@ -336,7 +336,7 @@ __packed struct qseecom_client_send_fsm_key_req { __packed struct qseecom_continue_blocked_request_ireq { uint32_t qsee_cmd_id; - uint32_t app_id; + uint32_t app_or_session_id; /*legacy: app_id; smcinvoke: session_id*/ }; @@ -681,6 +681,9 @@ __packed struct qseecom_continue_blocked_request_ireq { #define TZ_OS_CONTINUE_BLOCKED_REQUEST_ID \ TZ_SYSCALL_CREATE_SMC_ID(TZ_OWNER_QSEE_OS, TZ_SVC_LISTENER, 0x04) +#define TZ_OS_CONTINUE_BLOCKED_REQUEST_SMCINVOKE_ID \ + TZ_SYSCALL_CREATE_SMC_ID(TZ_OWNER_QSEE_OS, TZ_SVC_LISTENER, 0x07) + #define TZ_OS_CONTINUE_BLOCKED_REQUEST_ID_PARAM_ID \ TZ_SYSCALL_CREATE_PARAM_ID_1(TZ_SYSCALL_PARAM_TYPE_VAL) diff --git a/include/sound/apr_audio-v2.h b/include/sound/apr_audio-v2.h index 74995a0cdbad..2680a13721c2 100644 --- a/include/sound/apr_audio-v2.h +++ b/include/sound/apr_audio-v2.h @@ -446,6 +446,88 @@ struct adm_param_data_v5 { */ } __packed; + +struct param_data_v6 { + /* Unique ID of the module. */ + u32 module_id; + /* Unique ID of the instance. */ + u16 instance_id; + /* Reserved for future enhancements. + * This field must be set to zero. + */ + u16 reserved; + /* Unique ID of the parameter. */ + u32 param_id; + /* Data size of the param_id/module_id combination. + * This value is a + * multiple of 4 bytes. + */ + u32 param_size; +} __packed; + +/* ADM_CMD_SET_MTMX_STRTR_DEV_PARAMS_V1 command is used to set + * calibration data to the ADSP Matrix Mixer the payload is + * of struct adm_cmd_set_mtmx_params_v1. + * + * ADM_CMD_GET_MTMX_STRTR_DEV_PARAMS_V1 can be used to get + * the calibration data from the ADSP Matrix Mixer and + * ADM_CMDRSP_GET_MTMX_STRTR_DEV_PARAMS_V1 is the response + * ioctl to ADM_CMD_GET_MTMX_STRTR_DEV_PARAMS_V1. + */ +#define ADM_CMD_SET_MTMX_STRTR_DEV_PARAMS_V1 0x00010367 +#define ADM_CMD_GET_MTMX_STRTR_DEV_PARAMS_V1 0x00010368 +#define ADM_CMDRSP_GET_MTMX_STRTR_DEV_PARAMS_V1 0x00010369 + +/* Payload of the #define ADM_CMD_SET_MTMX_STRTR_DEV_PARAMS_V1 command. + * If the data_payload_addr_lsw and data_payload_addr_msw element + * are NULL, a series of struct param_data_v6 structures immediately + * follows, whose total size is payload_size bytes. + */ +struct adm_cmd_set_mtmx_params_v1 { + struct apr_hdr hdr; + /* LSW of parameter data payload address.*/ + u32 payload_addr_lsw; + + /* MSW of parameter data payload address.*/ + u32 payload_addr_msw; + + /* Memory map handle returned by ADM_CMD_SHARED_MEM_MAP_REGIONS + * command. + * If mem_map_handle is zero it implies the message is in + * the payload + */ + u32 mem_map_handle; + + /* Size in bytes of the variable payload accompanying this + * message or in shared memory. This is used for parsing + * the parameter payload. + */ + u32 payload_size; + + /* COPP ID/Device ID */ + u16 copp_id; + + /* For alignment, must be set to 0 */ + u16 reserved; +} __packed; + +struct enable_param_v6 { + /* + * Specifies whether the Audio processing module is enabled. + * This parameter is generic/common parameter to configure or + * determine the state of any audio processing module. + */ + struct param_data_v6 param; + + /* @values 0 : Disable 1: Enable */ + uint32_t enable; +} __packed; + +/* Defined in ADSP as VOICE_MODULE_TX_STREAM_LIMITER but + * used for RX stream limiter on matrix input to ADM. + */ +#define ADM_MTMX_MODULE_STREAM_LIMITER 0x00010F15 + #define ASM_STREAM_CMD_REGISTER_PP_EVENTS 0x00013213 #define ASM_STREAM_PP_EVENT 0x00013214 #define ASM_STREAM_CMD_REGISTER_IEC_61937_FMT_UPDATE 0x13333 @@ -625,6 +707,29 @@ struct audproc_softvolume_params { */ #define AUDPROC_PARAM_ID_MFC_OUTPUT_MEDIA_FORMAT 0x00010913 +/* ID of the Channel Mixer module, which is used to configure + * channel-mixer related parameters. + * This module supports the AUDPROC_CHMIXER_PARAM_ID_COEFF parameter ID. + */ +#define AUDPROC_MODULE_ID_CHMIXER 0x00010341 + +/* ID of the Coefficient parameter used by AUDPROC_MODULE_ID_CHMIXER to + *configure the channel mixer weighting coefficients. + */ +#define AUDPROC_CHMIXER_PARAM_ID_COEFF 0x00010342 + +/* Payload of the per-session, per-device parameter data of the + * #ADM_CMD_SET_PSPD_MTMX_STRTR_PARAMS_V5 command or + * #ADM_CMD_SET_PSPD_MTMX_STRTR_PARAMS_V6 command. + * Immediately following this structure are param_size bytes of parameter + * data. The structure and size depend on the module_id/param_id pair. + */ +struct adm_pspd_param_data_t { + uint32_t module_id; + uint32_t param_id; + uint16_t param_size; + uint16_t reserved; +} __packed; struct audproc_mfc_output_media_fmt { struct adm_cmd_set_pp_params_v5 params; @@ -3902,6 +4007,14 @@ struct asm_softvolume_params { u32 rampingcurve; } __packed; +struct asm_stream_pan_ctrl_params { + uint16_t num_output_channels; + uint16_t num_input_channels; + uint16_t output_channel_map[8]; + uint16_t input_channel_map[8]; + uint16_t gain[64]; +} __packed; + #define ASM_END_POINT_DEVICE_MATRIX 0 #define PCM_CHANNEL_NULL 0 @@ -7802,6 +7915,48 @@ struct asm_volume_ctrl_lr_chan_gain { /*< Linear gain in Q13 format for the right channel.*/ } __packed; +struct audproc_chmixer_param_coeff { + uint32_t index; + uint16_t num_output_channels; + uint16_t num_input_channels; +} __packed; + + +/* ID of the Multichannel Volume Control parameters used by + * AUDPROC_MODULE_ID_VOL_CTRL. + */ +#define AUDPROC_PARAM_ID_MULTICHANNEL_GAIN 0x00010713 + +/* Payload of the AUDPROC_PARAM_ID_MULTICHANNEL_GAIN channel type/gain + * pairs used by the Volume Control module. + * This structure immediately follows the + * audproc_volume_ctrl_multichannel_gain_t structure. + */ +struct audproc_volume_ctrl_channel_type_gain_pair { + uint8_t channel_type; + /* Channel type for which the gain setting is to be applied. */ + + uint8_t reserved1; + uint8_t reserved2; + uint8_t reserved3; + + uint32_t gain; + /* Gain value for this channel in Q28 format. */ +} __packed; + +/* Payload of the AUDPROC_PARAM_ID_MULTICHANNEL_MUTE parameters used by + * the Volume Control module. + */ +struct audproc_volume_ctrl_multichannel_gain { + uint32_t num_channels; + /* Number of channels for which mute configuration is provided. Any + * channels present in the data for which mute configuration is not + * provided are set to unmute. + */ + + struct audproc_volume_ctrl_channel_type_gain_pair *gain_data; + /* Array of channel type/mute setting pairs. */ +} __packed; /* Structure for the mute configuration parameter for a volume control module. */ @@ -9151,7 +9306,6 @@ struct srs_trumedia_params { } __packed; /* SRS TruMedia end */ -#define AUDPROC_PARAM_ID_ENABLE 0x00010904 #define ASM_STREAM_POSTPROC_TOPO_ID_SA_PLUS 0x1000FFFF /* DTS Eagle */ #define AUDPROC_MODULE_ID_DTS_HPX_PREMIX 0x0001077C diff --git a/include/sound/q6adm-v2.h b/include/sound/q6adm-v2.h index e689e9357012..65c42ee18914 100644 --- a/include/sound/q6adm-v2.h +++ b/include/sound/q6adm-v2.h @@ -51,6 +51,13 @@ enum { ADM_CLIENT_ID_MAX, }; +/* ENUM for adm_status & route_status */ +enum adm_status_flags { + ADM_STATUS_CALIBRATION_REQUIRED = 0, + ADM_STATUS_LIMITER, + ADM_STATUS_MAX, +}; + #define MAX_COPPS_PER_PORT 0x8 #define ADM_MAX_CHANNELS 8 @@ -61,6 +68,7 @@ struct route_payload { int app_type[MAX_COPPS_PER_PORT]; int acdb_dev_id[MAX_COPPS_PER_PORT]; int sample_rate[MAX_COPPS_PER_PORT]; + unsigned long route_status[MAX_COPPS_PER_PORT]; unsigned short num_copps; unsigned int session_id; }; @@ -138,9 +146,13 @@ int adm_get_topology_for_port_copp_idx(int port_id, int copp_idx); int adm_get_indexes_from_copp_id(int copp_id, int *port_idx, int *copp_idx); -int adm_set_stereo_to_custom_stereo(int port_id, int copp_idx, - unsigned int session_id, - char *params, uint32_t params_length); +int adm_set_pspd_matrix_params(int port_id, int copp_idx, + unsigned int session_id, + char *params, uint32_t params_length); + +int adm_set_downmix_params(int port_id, int copp_idx, + unsigned int session_id, char *params, + uint32_t params_length); int adm_get_pp_topo_module_list(int port_id, int copp_idx, int32_t param_length, char *params); diff --git a/include/sound/q6asm-v2.h b/include/sound/q6asm-v2.h index d0dffbd15923..177c2f4da32e 100644 --- a/include/sound/q6asm-v2.h +++ b/include/sound/q6asm-v2.h @@ -611,6 +611,14 @@ int q6asm_set_softvolume(struct audio_client *ac, int q6asm_set_softvolume_v2(struct audio_client *ac, struct asm_softvolume_params *param, int instance); +/* Set panning and MFC params */ +int q6asm_set_mfc_panning_params(struct audio_client *ac, + struct asm_stream_pan_ctrl_params *pan_param); + +/* Set vol gain pair */ +int q6asm_set_vol_ctrl_gain_pair(struct audio_client *ac, + struct asm_stream_pan_ctrl_params *pan_param); + /* Send left-right channel gain */ int q6asm_set_lrgain(struct audio_client *ac, int left_gain, int right_gain); diff --git a/include/uapi/linux/msm_ipa.h b/include/uapi/linux/msm_ipa.h index cbd6731aff43..4d0b992d0ba6 100644 --- a/include/uapi/linux/msm_ipa.h +++ b/include/uapi/linux/msm_ipa.h @@ -16,61 +16,82 @@ #define IPA_IOC_MAGIC 0xCF /** + * IPA device full path + */ +#define IPA_DEV_NAME "/dev/ipa" + +/** + * IPA NAT table character device name + */ +#define IPA_NAT_DEV_NAME "ipaNatTable" + +/** + * IPA IPv6CT table character device name + */ +#define IPA_IPV6CT_DEV_NAME "ipaIpv6CTTable" + + /** * name of the default routing tables for v4 and v6 */ #define IPA_DFLT_RT_TBL_NAME "ipa_dflt_rt" /** - * the commands supported by IPA driver - */ -#define IPA_IOCTL_ADD_HDR 0 -#define IPA_IOCTL_DEL_HDR 1 -#define IPA_IOCTL_ADD_RT_RULE 2 -#define IPA_IOCTL_DEL_RT_RULE 3 -#define IPA_IOCTL_ADD_FLT_RULE 4 -#define IPA_IOCTL_DEL_FLT_RULE 5 -#define IPA_IOCTL_COMMIT_HDR 6 -#define IPA_IOCTL_RESET_HDR 7 -#define IPA_IOCTL_COMMIT_RT 8 -#define IPA_IOCTL_RESET_RT 9 -#define IPA_IOCTL_COMMIT_FLT 10 -#define IPA_IOCTL_RESET_FLT 11 -#define IPA_IOCTL_DUMP 12 -#define IPA_IOCTL_GET_RT_TBL 13 -#define IPA_IOCTL_PUT_RT_TBL 14 -#define IPA_IOCTL_COPY_HDR 15 -#define IPA_IOCTL_QUERY_INTF 16 -#define IPA_IOCTL_QUERY_INTF_TX_PROPS 17 -#define IPA_IOCTL_QUERY_INTF_RX_PROPS 18 -#define IPA_IOCTL_GET_HDR 19 -#define IPA_IOCTL_PUT_HDR 20 -#define IPA_IOCTL_SET_FLT 21 -#define IPA_IOCTL_ALLOC_NAT_MEM 22 -#define IPA_IOCTL_V4_INIT_NAT 23 -#define IPA_IOCTL_NAT_DMA 24 -#define IPA_IOCTL_V4_DEL_NAT 26 -#define IPA_IOCTL_PULL_MSG 27 -#define IPA_IOCTL_GET_NAT_OFFSET 28 -#define IPA_IOCTL_RM_ADD_DEPENDENCY 29 -#define IPA_IOCTL_RM_DEL_DEPENDENCY 30 -#define IPA_IOCTL_GENERATE_FLT_EQ 31 -#define IPA_IOCTL_QUERY_INTF_EXT_PROPS 32 -#define IPA_IOCTL_QUERY_EP_MAPPING 33 -#define IPA_IOCTL_QUERY_RT_TBL_INDEX 34 -#define IPA_IOCTL_WRITE_QMAPID 35 -#define IPA_IOCTL_MDFY_FLT_RULE 36 -#define IPA_IOCTL_NOTIFY_WAN_UPSTREAM_ROUTE_ADD 37 -#define IPA_IOCTL_NOTIFY_WAN_UPSTREAM_ROUTE_DEL 38 -#define IPA_IOCTL_NOTIFY_WAN_EMBMS_CONNECTED 39 -#define IPA_IOCTL_ADD_HDR_PROC_CTX 40 -#define IPA_IOCTL_DEL_HDR_PROC_CTX 41 -#define IPA_IOCTL_MDFY_RT_RULE 42 -#define IPA_IOCTL_ADD_RT_RULE_AFTER 43 -#define IPA_IOCTL_ADD_FLT_RULE_AFTER 44 -#define IPA_IOCTL_GET_HW_VERSION 45 -#define IPA_IOCTL_ADD_RT_RULE_EXT 46 -#define IPA_IOCTL_NAT_MODIFY_PDN 47 -#define IPA_IOCTL_MAX 48 + * commands supported by IPA driver + */ +#define IPA_IOCTL_ADD_HDR 0 +#define IPA_IOCTL_DEL_HDR 1 +#define IPA_IOCTL_ADD_RT_RULE 2 +#define IPA_IOCTL_DEL_RT_RULE 3 +#define IPA_IOCTL_ADD_FLT_RULE 4 +#define IPA_IOCTL_DEL_FLT_RULE 5 +#define IPA_IOCTL_COMMIT_HDR 6 +#define IPA_IOCTL_RESET_HDR 7 +#define IPA_IOCTL_COMMIT_RT 8 +#define IPA_IOCTL_RESET_RT 9 +#define IPA_IOCTL_COMMIT_FLT 10 +#define IPA_IOCTL_RESET_FLT 11 +#define IPA_IOCTL_DUMP 12 +#define IPA_IOCTL_GET_RT_TBL 13 +#define IPA_IOCTL_PUT_RT_TBL 14 +#define IPA_IOCTL_COPY_HDR 15 +#define IPA_IOCTL_QUERY_INTF 16 +#define IPA_IOCTL_QUERY_INTF_TX_PROPS 17 +#define IPA_IOCTL_QUERY_INTF_RX_PROPS 18 +#define IPA_IOCTL_GET_HDR 19 +#define IPA_IOCTL_PUT_HDR 20 +#define IPA_IOCTL_SET_FLT 21 +#define IPA_IOCTL_ALLOC_NAT_MEM 22 +#define IPA_IOCTL_V4_INIT_NAT 23 +#define IPA_IOCTL_TABLE_DMA_CMD 24 +#define IPA_IOCTL_NAT_DMA IPA_IOCTL_TABLE_DMA_CMD +#define IPA_IOCTL_INIT_IPV6CT_TABLE 25 +#define IPA_IOCTL_V4_DEL_NAT 26 +#define IPA_IOCTL_PULL_MSG 27 +#define IPA_IOCTL_GET_NAT_OFFSET 28 +#define IPA_IOCTL_RM_ADD_DEPENDENCY 29 +#define IPA_IOCTL_RM_DEL_DEPENDENCY 30 +#define IPA_IOCTL_GENERATE_FLT_EQ 31 +#define IPA_IOCTL_QUERY_INTF_EXT_PROPS 32 +#define IPA_IOCTL_QUERY_EP_MAPPING 33 +#define IPA_IOCTL_QUERY_RT_TBL_INDEX 34 +#define IPA_IOCTL_WRITE_QMAPID 35 +#define IPA_IOCTL_MDFY_FLT_RULE 36 +#define IPA_IOCTL_NOTIFY_WAN_UPSTREAM_ROUTE_ADD 37 +#define IPA_IOCTL_NOTIFY_WAN_UPSTREAM_ROUTE_DEL 38 +#define IPA_IOCTL_NOTIFY_WAN_EMBMS_CONNECTED 39 +#define IPA_IOCTL_ADD_HDR_PROC_CTX 40 +#define IPA_IOCTL_DEL_HDR_PROC_CTX 41 +#define IPA_IOCTL_MDFY_RT_RULE 42 +#define IPA_IOCTL_ADD_RT_RULE_AFTER 43 +#define IPA_IOCTL_ADD_FLT_RULE_AFTER 44 +#define IPA_IOCTL_GET_HW_VERSION 45 +#define IPA_IOCTL_ADD_RT_RULE_EXT 46 +#define IPA_IOCTL_NAT_MODIFY_PDN 47 +#define IPA_IOCTL_ALLOC_NAT_TABLE 48 +#define IPA_IOCTL_ALLOC_IPV6CT_TABLE 49 +#define IPA_IOCTL_DEL_NAT_TABLE 50 +#define IPA_IOCTL_DEL_IPV6CT_TABLE 51 +#define IPA_IOCTL_MAX 52 /** * max size of the header to be inserted @@ -1314,15 +1335,26 @@ struct ipa_ioc_nat_alloc_mem { }; /** - * struct ipa_ioc_v4_nat_init - nat table initialization - * parameters + * struct ipa_ioc_nat_ipv6ct_table_alloc - NAT/IPv6CT table memory allocation + * properties + * @size: input parameter, size of table in bytes + * @offset: output parameter, offset into page in case of system memory + */ +struct ipa_ioc_nat_ipv6ct_table_alloc { + size_t size; + off_t offset; +}; + +/** + * struct ipa_ioc_v4_nat_init - nat table initialization parameters * @tbl_index: input parameter, index of the table * @ipv4_rules_offset: input parameter, ipv4 rules address offset * @expn_rules_offset: input parameter, ipv4 expansion rules address offset * @index_offset: input parameter, index rules offset * @index_expn_offset: input parameter, index expansion rules offset - * @table_entries: input parameter, ipv4 rules table size in entries - * @expn_table_entries: input parameter, ipv4 expansion rules table size + * @table_entries: input parameter, ipv4 rules table number of entries + * @expn_table_entries: input parameter, ipv4 expansion rules table number of + * entries * @ip_addr: input parameter, public ip address */ struct ipa_ioc_v4_nat_init { @@ -1339,6 +1371,23 @@ struct ipa_ioc_v4_nat_init { }; /** + * struct ipa_ioc_ipv6ct_init - IPv6CT table initialization parameters + * @tbl_index: input parameter, index of the table + * @base_table_offset: input parameter, IPv6CT base table address offset + * @expn_table_offset: input parameter, IPv6CT expansion table address offset + * @table_entries: input parameter, IPv6CT table number of entries + * @expn_table_entries: input parameter, IPv6CT expansion table number of + * entries + */ +struct ipa_ioc_ipv6ct_init { + uint8_t tbl_index; + uint32_t base_table_offset; + uint32_t expn_table_offset; + uint16_t table_entries; + uint16_t expn_table_entries; +}; + +/** * struct ipa_ioc_v4_nat_del - nat table delete parameter * @table_index: input parameter, index of the table * @public_ip_addr: input parameter, public ip address @@ -1349,7 +1398,15 @@ struct ipa_ioc_v4_nat_del { }; /** - * struct ipa_ioc_nat_dma_one - nat dma command parameter + * struct ipa_ioc_nat_ipv6ct_table_del - NAT/IPv6CT table delete parameter + * @table_index: input parameter, index of the table + */ +struct ipa_ioc_nat_ipv6ct_table_del { + uint8_t table_index; +}; + +/** + * struct ipa_ioc_nat_dma_one - nat/ipv6ct dma command parameter * @table_index: input parameter, index of the table * @base_addr: type of table, from which the base address of the table * can be inferred @@ -1366,7 +1423,7 @@ struct ipa_ioc_nat_dma_one { }; /** - * struct ipa_ioc_nat_dma_cmd - To hold multiple nat dma commands + * struct ipa_ioc_nat_dma_cmd - To hold multiple nat/ipv6ct dma commands * @entries: number of dma commands in use * @dma: data pointer to the dma commands */ @@ -1377,12 +1434,12 @@ struct ipa_ioc_nat_dma_cmd { }; /** -* struct ipa_ioc_nat_pdn_entry - PDN entry modification data -* @pdn_index: index of the entry in the PDN config table to be changed -* @public_ip: PDN's public ip -* @src_metadata: PDN's source NAT metadata for metadata replacement -* @dst_metadata: PDN's destination NAT metadata for metadata replacement -*/ + * struct ipa_ioc_nat_pdn_entry - PDN entry modification data + * @pdn_index: index of the entry in the PDN config table to be changed + * @public_ip: PDN's public ip + * @src_metadata: PDN's source NAT metadata for metadata replacement + * @dst_metadata: PDN's destination NAT metadata for metadata replacement + */ struct ipa_ioc_nat_pdn_entry { uint8_t pdn_index; uint32_t public_ip; @@ -1600,15 +1657,33 @@ enum ipacm_client_enum { #define IPA_IOC_ALLOC_NAT_MEM _IOWR(IPA_IOC_MAGIC, \ IPA_IOCTL_ALLOC_NAT_MEM, \ struct ipa_ioc_nat_alloc_mem *) +#define IPA_IOC_ALLOC_NAT_TABLE _IOWR(IPA_IOC_MAGIC, \ + IPA_IOCTL_ALLOC_NAT_TABLE, \ + struct ipa_ioc_nat_ipv6ct_table_alloc *) +#define IPA_IOC_ALLOC_IPV6CT_TABLE _IOWR(IPA_IOC_MAGIC, \ + IPA_IOCTL_ALLOC_IPV6CT_TABLE, \ + struct ipa_ioc_nat_ipv6ct_table_alloc *) #define IPA_IOC_V4_INIT_NAT _IOWR(IPA_IOC_MAGIC, \ IPA_IOCTL_V4_INIT_NAT, \ struct ipa_ioc_v4_nat_init *) +#define IPA_IOC_INIT_IPV6CT_TABLE _IOWR(IPA_IOC_MAGIC, \ + IPA_IOCTL_INIT_IPV6CT_TABLE, \ + struct ipa_ioc_ipv6ct_init *) #define IPA_IOC_NAT_DMA _IOWR(IPA_IOC_MAGIC, \ IPA_IOCTL_NAT_DMA, \ struct ipa_ioc_nat_dma_cmd *) +#define IPA_IOC_TABLE_DMA_CMD _IOWR(IPA_IOC_MAGIC, \ + IPA_IOCTL_TABLE_DMA_CMD, \ + struct ipa_ioc_nat_dma_cmd *) #define IPA_IOC_V4_DEL_NAT _IOWR(IPA_IOC_MAGIC, \ IPA_IOCTL_V4_DEL_NAT, \ struct ipa_ioc_v4_nat_del *) +#define IPA_IOC_DEL_NAT_TABLE _IOWR(IPA_IOC_MAGIC, \ + IPA_IOCTL_DEL_NAT_TABLE, \ + struct ipa_ioc_nat_ipv6ct_table_del *) +#define IPA_IOC_DEL_IPV6CT_TABLE _IOWR(IPA_IOC_MAGIC, \ + IPA_IOCTL_DEL_IPV6CT_TABLE, \ + struct ipa_ioc_nat_ipv6ct_table_del *) #define IPA_IOC_GET_NAT_OFFSET _IOWR(IPA_IOC_MAGIC, \ IPA_IOCTL_GET_NAT_OFFSET, \ uint32_t *) diff --git a/include/uapi/sound/devdep_params.h b/include/uapi/sound/devdep_params.h index 5061ec0da356..9e3133b76c68 100644 --- a/include/uapi/sound/devdep_params.h +++ b/include/uapi/sound/devdep_params.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2013-2015, The Linux Foundation. All rights reserved. + * Copyright (c) 2013-2015,2017, The Linux Foundation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 and @@ -66,4 +66,14 @@ struct dts_eagle_param_desc { uint32_t device; } __packed; +#define HWDEP_FE_BASE 3000 /*unique base for FE hw dep nodes*/ +struct snd_pcm_mmap_fd { + int32_t dir; + int32_t fd; + int32_t size; + int32_t actual_size; +}; + +#define SNDRV_PCM_IOCTL_MMAP_DATA_FD _IOWR('U', 0xd2, struct snd_pcm_mmap_fd) + #endif diff --git a/kernel/cpu.c b/kernel/cpu.c index 1a26ef5b7d58..87b88e8c0233 100644 --- a/kernel/cpu.c +++ b/kernel/cpu.c @@ -375,6 +375,21 @@ static int _cpu_down(unsigned int cpu, int tasks_frozen) goto out_release; } + /* + * By now we've cleared cpu_active_mask, wait for all preempt-disabled + * and RCU users of this state to go away such that all new such users + * will observe it. + * + * For CONFIG_PREEMPT we have preemptible RCU and its sync_rcu() might + * not imply sync_sched(), so wait for both. + * + * Do sync before park smpboot threads to take care the rcu boost case. + */ + if (IS_ENABLED(CONFIG_PREEMPT)) + synchronize_rcu_mult(call_rcu, call_rcu_sched); + else + synchronize_rcu(); + smpboot_park_threads(cpu); /* diff --git a/kernel/panic.c b/kernel/panic.c index 982a52352cfc..679254405510 100644 --- a/kernel/panic.c +++ b/kernel/panic.c @@ -172,7 +172,7 @@ void panic(const char *fmt, ...) * Delay timeout seconds before rebooting the machine. * We can't use the "normal" timers since we just panicked. */ - pr_emerg("Rebooting in %d seconds..", panic_timeout); + pr_emerg("Rebooting in %d seconds..\n", panic_timeout); for (i = 0; i < panic_timeout * 1000; i += PANIC_TIMER_STEP) { touch_nmi_watchdog(); diff --git a/kernel/sched/loadavg.c b/kernel/sched/loadavg.c index b0b93fd33af9..f8e8d68ed3fd 100644 --- a/kernel/sched/loadavg.c +++ b/kernel/sched/loadavg.c @@ -201,8 +201,9 @@ void calc_load_exit_idle(void) struct rq *this_rq = this_rq(); /* - * If we're still before the sample window, we're done. + * If we're still before the pending sample window, we're done. */ + this_rq->calc_load_update = calc_load_update; if (time_before(jiffies, this_rq->calc_load_update)) return; @@ -211,7 +212,6 @@ void calc_load_exit_idle(void) * accounted through the nohz accounting, so skip the entire deal and * sync up for the next window. */ - this_rq->calc_load_update = calc_load_update; if (time_before(jiffies, this_rq->calc_load_update + 10)) this_rq->calc_load_update += LOAD_FREQ; } diff --git a/lib/swiotlb.c b/lib/swiotlb.c index 76f29ecba8f4..771234d050c7 100644 --- a/lib/swiotlb.c +++ b/lib/swiotlb.c @@ -452,11 +452,11 @@ phys_addr_t swiotlb_tbl_map_single(struct device *hwdev, : 1UL << (BITS_PER_LONG - IO_TLB_SHIFT); /* - * For mappings greater than a page, we limit the stride (and - * hence alignment) to a page size. + * For mappings greater than or equal to a page, we limit the stride + * (and hence alignment) to a page size. */ nslots = ALIGN(size, 1 << IO_TLB_SHIFT) >> IO_TLB_SHIFT; - if (size > PAGE_SIZE) + if (size >= PAGE_SIZE) stride = (1 << (PAGE_SHIFT - IO_TLB_SHIFT)); else stride = 1; diff --git a/mm/huge_memory.c b/mm/huge_memory.c index 47b469663822..6c6f5ccfcda1 100644 --- a/mm/huge_memory.c +++ b/mm/huge_memory.c @@ -1363,8 +1363,11 @@ int do_huge_pmd_numa_page(struct mm_struct *mm, struct vm_area_struct *vma, */ if (unlikely(pmd_trans_migrating(*pmdp))) { page = pmd_page(*pmdp); + if (!get_page_unless_zero(page)) + goto out_unlock; spin_unlock(ptl); wait_on_page_locked(page); + put_page(page); goto out; } @@ -1396,8 +1399,11 @@ int do_huge_pmd_numa_page(struct mm_struct *mm, struct vm_area_struct *vma, /* Migration could have started since the pmd_trans_migrating check */ if (!page_locked) { + if (!get_page_unless_zero(page)) + goto out_unlock; spin_unlock(ptl); wait_on_page_locked(page); + put_page(page); page_nid = -1; goto out; } diff --git a/mm/swap_cgroup.c b/mm/swap_cgroup.c index 40dd0f9b00d6..09f733b0424a 100644 --- a/mm/swap_cgroup.c +++ b/mm/swap_cgroup.c @@ -205,6 +205,8 @@ void swap_cgroup_swapoff(int type) struct page *page = map[i]; if (page) __free_page(page); + if (!(i % SWAP_CLUSTER_MAX)) + cond_resched(); } vfree(map); } diff --git a/net/8021q/vlan.c b/net/8021q/vlan.c index ad8d6e6b87ca..e20ae2d3c498 100644 --- a/net/8021q/vlan.c +++ b/net/8021q/vlan.c @@ -278,7 +278,8 @@ static int register_vlan_device(struct net_device *real_dev, u16 vlan_id) return 0; out_free_newdev: - free_netdev(new_dev); + if (new_dev->reg_state == NETREG_UNINITIALIZED) + free_netdev(new_dev); return err; } diff --git a/net/caif/cfpkt_skbuff.c b/net/caif/cfpkt_skbuff.c index 59ce1fcc220c..71b6ab240dea 100644 --- a/net/caif/cfpkt_skbuff.c +++ b/net/caif/cfpkt_skbuff.c @@ -81,11 +81,7 @@ static struct cfpkt *cfpkt_create_pfx(u16 len, u16 pfx) { struct sk_buff *skb; - if (likely(in_interrupt())) - skb = alloc_skb(len + pfx, GFP_ATOMIC); - else - skb = alloc_skb(len + pfx, GFP_KERNEL); - + skb = alloc_skb(len + pfx, GFP_ATOMIC); if (unlikely(skb == NULL)) return NULL; diff --git a/net/core/dev.c b/net/core/dev.c index 16467dc215d0..9a3aaba15c5a 100644 --- a/net/core/dev.c +++ b/net/core/dev.c @@ -1248,8 +1248,9 @@ int dev_set_alias(struct net_device *dev, const char *alias, size_t len) if (!new_ifalias) return -ENOMEM; dev->ifalias = new_ifalias; + memcpy(dev->ifalias, alias, len); + dev->ifalias[len] = 0; - strlcpy(dev->ifalias, alias, len+1); return len; } diff --git a/net/core/dst.c b/net/core/dst.c index d7ad628bf64e..e72d706f8d0c 100644 --- a/net/core/dst.c +++ b/net/core/dst.c @@ -462,6 +462,20 @@ static int dst_dev_event(struct notifier_block *this, unsigned long event, spin_lock_bh(&dst_garbage.lock); dst = dst_garbage.list; dst_garbage.list = NULL; + /* The code in dst_ifdown places a hold on the loopback device. + * If the gc entry processing is set to expire after a lengthy + * interval, this hold can cause netdev_wait_allrefs() to hang + * out and wait for a long time -- until the the loopback + * interface is released. If we're really unlucky, it'll emit + * pr_emerg messages to console too. Reset the interval here, + * so dst cleanups occur in a more timely fashion. + */ + if (dst_garbage.timer_inc > DST_GC_INC) { + dst_garbage.timer_inc = DST_GC_INC; + dst_garbage.timer_expires = DST_GC_MIN; + mod_delayed_work(system_wq, &dst_gc_work, + dst_garbage.timer_expires); + } spin_unlock_bh(&dst_garbage.lock); if (last) diff --git a/net/core/rtnetlink.c b/net/core/rtnetlink.c index d43544ce7550..2ec5324a7ff7 100644 --- a/net/core/rtnetlink.c +++ b/net/core/rtnetlink.c @@ -897,6 +897,7 @@ static noinline size_t if_nlmsg_size(const struct net_device *dev, + nla_total_size(1) /* IFLA_LINKMODE */ + nla_total_size(4) /* IFLA_CARRIER_CHANGES */ + nla_total_size(4) /* IFLA_LINK_NETNSID */ + + nla_total_size(4) /* IFLA_GROUP */ + nla_total_size(ext_filter_mask & RTEXT_FILTER_VF ? 4 : 0) /* IFLA_NUM_VF */ + rtnl_vfinfo_size(dev, ext_filter_mask) /* IFLA_VFINFO_LIST */ @@ -1089,6 +1090,8 @@ static noinline_for_stack int rtnl_fill_vfinfo(struct sk_buff *skb, struct ifla_vf_mac vf_mac; struct ifla_vf_info ivi; + memset(&ivi, 0, sizeof(ivi)); + /* Not all SR-IOV capable drivers support the * spoofcheck and "RSS query enable" query. Preset to * -1 so the user space tool can detect that the driver @@ -1097,7 +1100,6 @@ static noinline_for_stack int rtnl_fill_vfinfo(struct sk_buff *skb, ivi.spoofchk = -1; ivi.rss_query_en = -1; ivi.trusted = -1; - memset(ivi.mac, 0, sizeof(ivi.mac)); /* The default value for VF link state is "auto" * IFLA_VF_LINK_STATE_AUTO which equals zero */ @@ -1370,6 +1372,7 @@ static const struct nla_policy ifla_policy[IFLA_MAX+1] = { [IFLA_PHYS_SWITCH_ID] = { .type = NLA_BINARY, .len = MAX_PHYS_ITEM_ID_LEN }, [IFLA_LINK_NETNSID] = { .type = NLA_S32 }, [IFLA_PROTO_DOWN] = { .type = NLA_U8 }, + [IFLA_GROUP] = { .type = NLA_U32 }, }; static const struct nla_policy ifla_info_policy[IFLA_INFO_MAX+1] = { diff --git a/net/decnet/dn_route.c b/net/decnet/dn_route.c index b1dc096d22f8..403593bd2b83 100644 --- a/net/decnet/dn_route.c +++ b/net/decnet/dn_route.c @@ -188,12 +188,6 @@ static inline void dnrt_free(struct dn_route *rt) call_rcu_bh(&rt->dst.rcu_head, dst_rcu_free); } -static inline void dnrt_drop(struct dn_route *rt) -{ - dst_release(&rt->dst); - call_rcu_bh(&rt->dst.rcu_head, dst_rcu_free); -} - static void dn_dst_check_expire(unsigned long dummy) { int i; @@ -248,7 +242,7 @@ static int dn_dst_gc(struct dst_ops *ops) } *rtp = rt->dst.dn_next; rt->dst.dn_next = NULL; - dnrt_drop(rt); + dnrt_free(rt); break; } spin_unlock_bh(&dn_rt_hash_table[i].lock); @@ -350,7 +344,7 @@ static int dn_insert_route(struct dn_route *rt, unsigned int hash, struct dn_rou dst_use(&rth->dst, now); spin_unlock_bh(&dn_rt_hash_table[hash].lock); - dnrt_drop(rt); + dst_free(&rt->dst); *rp = rth; return 0; } @@ -380,7 +374,7 @@ static void dn_run_flush(unsigned long dummy) for(; rt; rt = next) { next = rcu_dereference_raw(rt->dst.dn_next); RCU_INIT_POINTER(rt->dst.dn_next, NULL); - dst_free((struct dst_entry *)rt); + dnrt_free(rt); } nothing_to_declare: @@ -1187,7 +1181,7 @@ make_route: if (dev_out->flags & IFF_LOOPBACK) flags |= RTCF_LOCAL; - rt = dst_alloc(&dn_dst_ops, dev_out, 1, DST_OBSOLETE_NONE, DST_HOST); + rt = dst_alloc(&dn_dst_ops, dev_out, 0, DST_OBSOLETE_NONE, DST_HOST); if (rt == NULL) goto e_nobufs; diff --git a/net/decnet/netfilter/dn_rtmsg.c b/net/decnet/netfilter/dn_rtmsg.c index 85f2fdc360c2..29246bc9a7b4 100644 --- a/net/decnet/netfilter/dn_rtmsg.c +++ b/net/decnet/netfilter/dn_rtmsg.c @@ -102,7 +102,9 @@ static inline void dnrmg_receive_user_skb(struct sk_buff *skb) { struct nlmsghdr *nlh = nlmsg_hdr(skb); - if (nlh->nlmsg_len < sizeof(*nlh) || skb->len < nlh->nlmsg_len) + if (skb->len < sizeof(*nlh) || + nlh->nlmsg_len < sizeof(*nlh) || + skb->len < nlh->nlmsg_len) return; if (!netlink_capable(skb, CAP_NET_ADMIN)) diff --git a/net/dsa/slave.c b/net/dsa/slave.c index 8dfe9fb7ad36..554c2a961ad5 100644 --- a/net/dsa/slave.c +++ b/net/dsa/slave.c @@ -1006,10 +1006,8 @@ static int dsa_slave_phy_connect(struct dsa_slave_priv *p, /* Use already configured phy mode */ if (p->phy_interface == PHY_INTERFACE_MODE_NA) p->phy_interface = p->phy->interface; - phy_connect_direct(slave_dev, p->phy, dsa_slave_adjust_link, - p->phy_interface); - - return 0; + return phy_connect_direct(slave_dev, p->phy, dsa_slave_adjust_link, + p->phy_interface); } static int dsa_slave_phy_setup(struct dsa_slave_priv *p, diff --git a/net/ipv4/igmp.c b/net/ipv4/igmp.c index 17adfdaf5795..3809d523d012 100644 --- a/net/ipv4/igmp.c +++ b/net/ipv4/igmp.c @@ -1102,6 +1102,7 @@ static void igmpv3_add_delrec(struct in_device *in_dev, struct ip_mc_list *im) pmc = kzalloc(sizeof(*pmc), GFP_KERNEL); if (!pmc) return; + spin_lock_init(&pmc->lock); spin_lock_bh(&im->lock); pmc->interface = im->interface; in_dev_hold(in_dev); @@ -2026,21 +2027,26 @@ static int ip_mc_add_src(struct in_device *in_dev, __be32 *pmca, int sfmode, static void ip_mc_clear_src(struct ip_mc_list *pmc) { - struct ip_sf_list *psf, *nextpsf; + struct ip_sf_list *psf, *nextpsf, *tomb, *sources; - for (psf = pmc->tomb; psf; psf = nextpsf) { + spin_lock_bh(&pmc->lock); + tomb = pmc->tomb; + pmc->tomb = NULL; + sources = pmc->sources; + pmc->sources = NULL; + pmc->sfmode = MCAST_EXCLUDE; + pmc->sfcount[MCAST_INCLUDE] = 0; + pmc->sfcount[MCAST_EXCLUDE] = 1; + spin_unlock_bh(&pmc->lock); + + for (psf = tomb; psf; psf = nextpsf) { nextpsf = psf->sf_next; kfree(psf); } - pmc->tomb = NULL; - for (psf = pmc->sources; psf; psf = nextpsf) { + for (psf = sources; psf; psf = nextpsf) { nextpsf = psf->sf_next; kfree(psf); } - pmc->sources = NULL; - pmc->sfmode = MCAST_EXCLUDE; - pmc->sfcount[MCAST_INCLUDE] = 0; - pmc->sfcount[MCAST_EXCLUDE] = 1; } /* Join a multicast group diff --git a/net/ipv6/addrconf.c b/net/ipv6/addrconf.c index 4fe0359d8abf..55e928819846 100644 --- a/net/ipv6/addrconf.c +++ b/net/ipv6/addrconf.c @@ -320,9 +320,9 @@ static void addrconf_mod_rs_timer(struct inet6_dev *idev, static void addrconf_mod_dad_work(struct inet6_ifaddr *ifp, unsigned long delay) { - if (!delayed_work_pending(&ifp->dad_work)) - in6_ifa_hold(ifp); - mod_delayed_work(addrconf_wq, &ifp->dad_work, delay); + in6_ifa_hold(ifp); + if (mod_delayed_work(addrconf_wq, &ifp->dad_work, delay)) + in6_ifa_put(ifp); } static int snmp6_alloc_dev(struct inet6_dev *idev) diff --git a/net/ipv6/datagram.c b/net/ipv6/datagram.c index 27796c33ca05..d7c1ee7cf0e2 100644 --- a/net/ipv6/datagram.c +++ b/net/ipv6/datagram.c @@ -184,6 +184,11 @@ ipv4_connected: err = 0; if (IS_ERR(dst)) { err = PTR_ERR(dst); + /* Reset daddr and dport so that udp_v6_early_demux() + * fails to find this socket + */ + memset(&sk->sk_v6_daddr, 0, sizeof(sk->sk_v6_daddr)); + inet->inet_dport = 0; goto out; } diff --git a/net/ipv6/fib6_rules.c b/net/ipv6/fib6_rules.c index ed33abf57abd..9ac4f0cef27d 100644 --- a/net/ipv6/fib6_rules.c +++ b/net/ipv6/fib6_rules.c @@ -32,7 +32,6 @@ struct fib6_rule { struct dst_entry *fib6_rule_lookup(struct net *net, struct flowi6 *fl6, int flags, pol_lookup_t lookup) { - struct rt6_info *rt; struct fib_lookup_arg arg = { .lookup_ptr = lookup, .flags = FIB_LOOKUP_NOREF, @@ -41,21 +40,11 @@ struct dst_entry *fib6_rule_lookup(struct net *net, struct flowi6 *fl6, fib_rules_lookup(net->ipv6.fib6_rules_ops, flowi6_to_flowi(fl6), flags, &arg); - rt = arg.result; + if (arg.result) + return arg.result; - if (!rt) { - dst_hold(&net->ipv6.ip6_null_entry->dst); - return &net->ipv6.ip6_null_entry->dst; - } - - if (rt->rt6i_flags & RTF_REJECT && - rt->dst.error == -EAGAIN) { - ip6_rt_put(rt); - rt = net->ipv6.ip6_null_entry; - dst_hold(&rt->dst); - } - - return &rt->dst; + dst_hold(&net->ipv6.ip6_null_entry->dst); + return &net->ipv6.ip6_null_entry->dst; } static int fib6_rule_action(struct fib_rule *rule, struct flowi *flp, @@ -116,7 +105,8 @@ static int fib6_rule_action(struct fib_rule *rule, struct flowi *flp, flp6->saddr = saddr; } err = rt->dst.error; - goto out; + if (err != -EAGAIN) + goto out; } again: ip6_rt_put(rt); diff --git a/net/ipv6/ip6_fib.c b/net/ipv6/ip6_fib.c index 85bf86458706..1ac06723f0d7 100644 --- a/net/ipv6/ip6_fib.c +++ b/net/ipv6/ip6_fib.c @@ -290,8 +290,7 @@ struct dst_entry *fib6_rule_lookup(struct net *net, struct flowi6 *fl6, struct rt6_info *rt; rt = lookup(net, net->ipv6.fib6_main_tbl, fl6, flags); - if (rt->rt6i_flags & RTF_REJECT && - rt->dst.error == -EAGAIN) { + if (rt->dst.error == -EAGAIN) { ip6_rt_put(rt); rt = net->ipv6.ip6_null_entry; dst_hold(&rt->dst); diff --git a/net/ipv6/ip6_output.c b/net/ipv6/ip6_output.c index ef745df36fc8..72b53b83a720 100644 --- a/net/ipv6/ip6_output.c +++ b/net/ipv6/ip6_output.c @@ -1004,8 +1004,10 @@ static int ip6_dst_lookup_tail(struct net *net, const struct sock *sk, } #endif if (ipv6_addr_v4mapped(&fl6->saddr) && - !(ipv6_addr_v4mapped(&fl6->daddr) || ipv6_addr_any(&fl6->daddr))) - return -EAFNOSUPPORT; + !(ipv6_addr_v4mapped(&fl6->daddr) || ipv6_addr_any(&fl6->daddr))) { + err = -EAFNOSUPPORT; + goto out_err_release; + } return 0; diff --git a/net/ipv6/udp.c b/net/ipv6/udp.c index 8a07c63ddccd..a8cabc876348 100644 --- a/net/ipv6/udp.c +++ b/net/ipv6/udp.c @@ -45,6 +45,7 @@ #include <net/tcp_states.h> #include <net/ip6_checksum.h> #include <net/xfrm.h> +#include <net/inet_hashtables.h> #include <net/inet6_hashtables.h> #include <net/busy_poll.h> @@ -964,15 +965,22 @@ static struct sock *__udp6_lib_demux_lookup(struct net *net, int dif) { struct sock *sk; + struct hlist_nulls_node *hnode; + unsigned short hnum = ntohs(loc_port); + unsigned int hash2 = udp6_portaddr_hash(net, loc_addr, hnum); + unsigned int slot2 = hash2 & udp_table.mask; + struct udp_hslot *hslot2 = &udp_table.hash2[slot2]; - rcu_read_lock(); - sk = __udp6_lib_lookup(net, rmt_addr, rmt_port, loc_addr, loc_port, - dif, &udp_table); - if (sk && !atomic_inc_not_zero(&sk->sk_refcnt)) - sk = NULL; - rcu_read_unlock(); + const __portpair ports = INET_COMBINED_PORTS(rmt_port, hnum); - return sk; + udp_portaddr_for_each_entry_rcu(sk, hnode, &hslot2->head) { + if (sk->sk_state == TCP_ESTABLISHED && + INET6_MATCH(sk, net, rmt_addr, loc_addr, ports, dif)) + return sk; + /* Only check first socket in chain */ + break; + } + return NULL; } static void udp_v6_early_demux(struct sk_buff *skb) @@ -997,7 +1005,7 @@ static void udp_v6_early_demux(struct sk_buff *skb) else return; - if (!sk) + if (!sk || !atomic_inc_not_zero_hint(&sk->sk_refcnt, 2)) return; skb->sk = sk; diff --git a/net/key/af_key.c b/net/key/af_key.c index f9c9ecb0cdd3..e67c28e614b9 100644 --- a/net/key/af_key.c +++ b/net/key/af_key.c @@ -1135,6 +1135,7 @@ static struct xfrm_state * pfkey_msg2xfrm_state(struct net *net, goto out; } + err = -ENOBUFS; key = ext_hdrs[SADB_EXT_KEY_AUTH - 1]; if (sa->sadb_sa_auth) { int keysize = 0; @@ -1146,8 +1147,10 @@ static struct xfrm_state * pfkey_msg2xfrm_state(struct net *net, if (key) keysize = (key->sadb_key_bits + 7) / 8; x->aalg = kmalloc(sizeof(*x->aalg) + keysize, GFP_KERNEL); - if (!x->aalg) + if (!x->aalg) { + err = -ENOMEM; goto out; + } strcpy(x->aalg->alg_name, a->name); x->aalg->alg_key_len = 0; if (key) { @@ -1166,8 +1169,10 @@ static struct xfrm_state * pfkey_msg2xfrm_state(struct net *net, goto out; } x->calg = kmalloc(sizeof(*x->calg), GFP_KERNEL); - if (!x->calg) + if (!x->calg) { + err = -ENOMEM; goto out; + } strcpy(x->calg->alg_name, a->name); x->props.calgo = sa->sadb_sa_encrypt; } else { @@ -1181,8 +1186,10 @@ static struct xfrm_state * pfkey_msg2xfrm_state(struct net *net, if (key) keysize = (key->sadb_key_bits + 7) / 8; x->ealg = kmalloc(sizeof(*x->ealg) + keysize, GFP_KERNEL); - if (!x->ealg) + if (!x->ealg) { + err = -ENOMEM; goto out; + } strcpy(x->ealg->alg_name, a->name); x->ealg->alg_key_len = 0; if (key) { @@ -1227,8 +1234,10 @@ static struct xfrm_state * pfkey_msg2xfrm_state(struct net *net, struct xfrm_encap_tmpl *natt; x->encap = kmalloc(sizeof(*x->encap), GFP_KERNEL); - if (!x->encap) + if (!x->encap) { + err = -ENOMEM; goto out; + } natt = x->encap; n_type = ext_hdrs[SADB_X_EXT_NAT_T_TYPE-1]; diff --git a/net/mac80211/main.c b/net/mac80211/main.c index 175ffcf7fb06..2ee53dc1ddf7 100644 --- a/net/mac80211/main.c +++ b/net/mac80211/main.c @@ -891,12 +891,17 @@ int ieee80211_register_hw(struct ieee80211_hw *hw) supp_ht = supp_ht || sband->ht_cap.ht_supported; supp_vht = supp_vht || sband->vht_cap.vht_supported; - if (sband->ht_cap.ht_supported) - local->rx_chains = - max(ieee80211_mcs_to_chains(&sband->ht_cap.mcs), - local->rx_chains); + if (!sband->ht_cap.ht_supported) + continue; /* TODO: consider VHT for RX chains, hopefully it's the same */ + local->rx_chains = + max(ieee80211_mcs_to_chains(&sband->ht_cap.mcs), + local->rx_chains); + + /* no need to mask, SM_PS_DISABLED has all bits set */ + sband->ht_cap.cap |= WLAN_HT_CAP_SM_PS_DISABLED << + IEEE80211_HT_CAP_SM_PS_SHIFT; } /* if low-level driver supports AP, we also support VLAN */ diff --git a/net/netfilter/nf_conntrack_netlink.c b/net/netfilter/nf_conntrack_netlink.c index 9f5272968abb..e565b2becb14 100644 --- a/net/netfilter/nf_conntrack_netlink.c +++ b/net/netfilter/nf_conntrack_netlink.c @@ -45,6 +45,8 @@ #include <net/netfilter/nf_conntrack_zones.h> #include <net/netfilter/nf_conntrack_timestamp.h> #include <net/netfilter/nf_conntrack_labels.h> +#include <net/netfilter/nf_conntrack_seqadj.h> +#include <net/netfilter/nf_conntrack_synproxy.h> #ifdef CONFIG_NF_NAT_NEEDED #include <net/netfilter/nf_nat_core.h> #include <net/netfilter/nf_nat_l4proto.h> @@ -1798,6 +1800,8 @@ ctnetlink_create_conntrack(struct net *net, nf_ct_tstamp_ext_add(ct, GFP_ATOMIC); nf_ct_ecache_ext_add(ct, 0, 0, GFP_ATOMIC); nf_ct_labels_ext_add(ct); + nfct_seqadj_ext_add(ct); + nfct_synproxy_ext_add(ct); /* we must add conntrack extensions before confirmation. */ ct->status |= IPS_CONFIRMED; diff --git a/net/netfilter/xt_TCPMSS.c b/net/netfilter/xt_TCPMSS.c index b7c43def0dc6..00f798b20b20 100644 --- a/net/netfilter/xt_TCPMSS.c +++ b/net/netfilter/xt_TCPMSS.c @@ -104,7 +104,7 @@ tcpmss_mangle_packet(struct sk_buff *skb, tcph = (struct tcphdr *)(skb_network_header(skb) + tcphoff); tcp_hdrlen = tcph->doff * 4; - if (len < tcp_hdrlen) + if (len < tcp_hdrlen || tcp_hdrlen < sizeof(struct tcphdr)) return -1; if (info->mss == XT_TCPMSS_CLAMP_PMTU) { @@ -156,6 +156,10 @@ tcpmss_mangle_packet(struct sk_buff *skb, if (len > tcp_hdrlen) return 0; + /* tcph->doff has 4 bits, do not wrap it to 0 */ + if (tcp_hdrlen >= 15 * 4) + return 0; + /* * MSS Option not found ?! add it.. */ diff --git a/net/sctp/socket.c b/net/sctp/socket.c index 956141b71619..3ebf3b652d60 100644 --- a/net/sctp/socket.c +++ b/net/sctp/socket.c @@ -239,7 +239,7 @@ static struct sctp_transport *sctp_addr_id2transport(struct sock *sk, union sctp_addr *laddr = (union sctp_addr *)addr; struct sctp_transport *transport; - if (sctp_verify_addr(sk, laddr, af->sockaddr_len)) + if (!af || sctp_verify_addr(sk, laddr, af->sockaddr_len)) return NULL; addr_asoc = sctp_endpoint_lookup_assoc(sctp_sk(sk)->ep, diff --git a/net/unix/af_unix.c b/net/unix/af_unix.c index 1f5d18d80fba..decd8b8d751f 100644 --- a/net/unix/af_unix.c +++ b/net/unix/af_unix.c @@ -997,7 +997,8 @@ static int unix_bind(struct socket *sock, struct sockaddr *uaddr, int addr_len) struct path path = { NULL, NULL }; err = -EINVAL; - if (sunaddr->sun_family != AF_UNIX) + if (addr_len < offsetofend(struct sockaddr_un, sun_family) || + sunaddr->sun_family != AF_UNIX) goto out; if (addr_len == sizeof(short)) { @@ -1108,6 +1109,10 @@ static int unix_dgram_connect(struct socket *sock, struct sockaddr *addr, unsigned int hash; int err; + err = -EINVAL; + if (alen < offsetofend(struct sockaddr, sa_family)) + goto out; + if (addr->sa_family != AF_UNSPEC) { err = unix_mkname(sunaddr, alen, &hash); if (err < 0) diff --git a/net/xfrm/xfrm_policy.c b/net/xfrm/xfrm_policy.c index d5b4ac7bf0d8..0f45e1a3a7d1 100644 --- a/net/xfrm/xfrm_policy.c +++ b/net/xfrm/xfrm_policy.c @@ -1773,43 +1773,6 @@ free_dst: goto out; } -#ifdef CONFIG_XFRM_SUB_POLICY -static int xfrm_dst_alloc_copy(void **target, const void *src, int size) -{ - if (!*target) { - *target = kmalloc(size, GFP_ATOMIC); - if (!*target) - return -ENOMEM; - } - - memcpy(*target, src, size); - return 0; -} -#endif - -static int xfrm_dst_update_parent(struct dst_entry *dst, - const struct xfrm_selector *sel) -{ -#ifdef CONFIG_XFRM_SUB_POLICY - struct xfrm_dst *xdst = (struct xfrm_dst *)dst; - return xfrm_dst_alloc_copy((void **)&(xdst->partner), - sel, sizeof(*sel)); -#else - return 0; -#endif -} - -static int xfrm_dst_update_origin(struct dst_entry *dst, - const struct flowi *fl) -{ -#ifdef CONFIG_XFRM_SUB_POLICY - struct xfrm_dst *xdst = (struct xfrm_dst *)dst; - return xfrm_dst_alloc_copy((void **)&(xdst->origin), fl, sizeof(*fl)); -#else - return 0; -#endif -} - static int xfrm_expand_policies(const struct flowi *fl, u16 family, struct xfrm_policy **pols, int *num_pols, int *num_xfrms) @@ -1881,16 +1844,6 @@ xfrm_resolve_and_create_bundle(struct xfrm_policy **pols, int num_pols, xdst = (struct xfrm_dst *)dst; xdst->num_xfrms = err; - if (num_pols > 1) - err = xfrm_dst_update_parent(dst, &pols[1]->selector); - else - err = xfrm_dst_update_origin(dst, fl); - if (unlikely(err)) { - dst_free(dst); - XFRM_INC_STATS(net, LINUX_MIB_XFRMOUTBUNDLECHECKERROR); - return ERR_PTR(err); - } - xdst->num_pols = num_pols; memcpy(xdst->pols, pols, sizeof(struct xfrm_policy *) * num_pols); xdst->policy_genid = atomic_read(&pols[0]->genid); diff --git a/security/selinux/hooks.c b/security/selinux/hooks.c index 5ab9d1e3e2b8..d0221769ba52 100644 --- a/security/selinux/hooks.c +++ b/security/selinux/hooks.c @@ -740,6 +740,7 @@ static int selinux_set_mnt_opts(struct super_block *sb, sbsec->flags |= SE_SBPROC | SE_SBGENFS; if (!strcmp(sb->s_type->name, "debugfs") || + !strcmp(sb->s_type->name, "tracefs") || !strcmp(sb->s_type->name, "sysfs") || !strcmp(sb->s_type->name, "pstore")) sbsec->flags |= SE_SBGENFS; diff --git a/sound/pci/hda/hda_codec.h b/sound/pci/hda/hda_codec.h index 373fcad840ea..776dffa88aee 100644 --- a/sound/pci/hda/hda_codec.h +++ b/sound/pci/hda/hda_codec.h @@ -294,6 +294,8 @@ struct hda_codec { #define list_for_each_codec(c, bus) \ list_for_each_entry(c, &(bus)->core.codec_list, core.list) +#define list_for_each_codec_safe(c, n, bus) \ + list_for_each_entry_safe(c, n, &(bus)->core.codec_list, core.list) /* snd_hda_codec_read/write optional flags */ #define HDA_RW_NO_RESPONSE_FALLBACK (1 << 0) diff --git a/sound/pci/hda/hda_controller.c b/sound/pci/hda/hda_controller.c index 5baf8b56b6e7..9c6e10fb479f 100644 --- a/sound/pci/hda/hda_controller.c +++ b/sound/pci/hda/hda_controller.c @@ -1128,8 +1128,12 @@ EXPORT_SYMBOL_GPL(azx_probe_codecs); /* configure each codec instance */ int azx_codec_configure(struct azx *chip) { - struct hda_codec *codec; - list_for_each_codec(codec, &chip->bus) { + struct hda_codec *codec, *next; + + /* use _safe version here since snd_hda_codec_configure() deregisters + * the device upon error and deletes itself from the bus list. + */ + list_for_each_codec_safe(codec, next, &chip->bus) { snd_hda_codec_configure(codec); } return 0; diff --git a/sound/pci/hda/hda_generic.c b/sound/pci/hda/hda_generic.c index dc2fa576d60d..689df78f640a 100644 --- a/sound/pci/hda/hda_generic.c +++ b/sound/pci/hda/hda_generic.c @@ -3190,6 +3190,7 @@ static int check_dyn_adc_switch(struct hda_codec *codec) spec->input_paths[i][nums]); spec->input_paths[i][nums] = spec->input_paths[i][n]; + spec->input_paths[i][n] = 0; } } nums++; diff --git a/sound/soc/codecs/wcd-mbhc-v2.c b/sound/soc/codecs/wcd-mbhc-v2.c index 3d131ed463c9..997a623033fb 100644 --- a/sound/soc/codecs/wcd-mbhc-v2.c +++ b/sound/soc/codecs/wcd-mbhc-v2.c @@ -668,7 +668,8 @@ static void wcd_mbhc_report_plug(struct wcd_mbhc *mbhc, int insertion, jack_type == SND_JACK_LINEOUT) && (mbhc->hph_status && mbhc->hph_status != jack_type)) { - if (mbhc->micbias_enable) { + if (mbhc->micbias_enable && + mbhc->hph_status == SND_JACK_HEADSET) { if (mbhc->mbhc_cb->mbhc_micbias_control) mbhc->mbhc_cb->mbhc_micbias_control( codec, MIC_BIAS_2, diff --git a/sound/soc/codecs/wcd9335.c b/sound/soc/codecs/wcd9335.c index 2ab787f57b31..10883b0939d6 100644 --- a/sound/soc/codecs/wcd9335.c +++ b/sound/soc/codecs/wcd9335.c @@ -12127,8 +12127,10 @@ static int tasha_dig_core_power_collapse(struct tasha_priv *tasha, goto unlock_mutex; if (tasha->power_active_ref < 0) { - dev_dbg(tasha->dev, "%s: power_active_ref is negative\n", + dev_info(tasha->dev, + "%s: power_active_ref is negative, resetting it\n", __func__); + tasha->power_active_ref = 0; goto unlock_mutex; } diff --git a/sound/soc/codecs/wsa881x.c b/sound/soc/codecs/wsa881x.c index fe975a7dbe4e..058f6c5fa676 100644 --- a/sound/soc/codecs/wsa881x.c +++ b/sound/soc/codecs/wsa881x.c @@ -1365,6 +1365,7 @@ static int wsa881x_swr_reset(struct swr_device *pdev) /* Retry after 1 msec delay */ usleep_range(1000, 1100); } + pdev->dev_num = devnum; regcache_mark_dirty(wsa881x->regmap); regcache_sync(wsa881x->regmap); return 0; diff --git a/sound/soc/msm/msm-dai-fe.c b/sound/soc/msm/msm-dai-fe.c index 24dbbedf0be7..cc89408fcb39 100644 --- a/sound/soc/msm/msm-dai-fe.c +++ b/sound/soc/msm/msm-dai-fe.c @@ -2641,6 +2641,101 @@ static struct snd_soc_dai_driver msm_fe_dais[] = { .name = "MultiMedia20", .probe = fe_dai_probe, }, + { + .playback = { + .stream_name = "MultiMedia21 Playback", + .aif_name = "MM_DL21", + .rates = (SNDRV_PCM_RATE_8000_384000 | + SNDRV_PCM_RATE_KNOT), + .formats = (SNDRV_PCM_FMTBIT_S16_LE | + SNDRV_PCM_FMTBIT_S24_LE | + SNDRV_PCM_FMTBIT_S24_3LE | + SNDRV_PCM_FMTBIT_S32_LE), + .channels_min = 1, + .channels_max = 8, + .rate_min = 8000, + .rate_max = 384000, + }, + .ops = &msm_fe_Multimedia_dai_ops, + .name = "MultiMedia21", + .probe = fe_dai_probe, + }, + { + .playback = { + .stream_name = "MultiMedia22 Playback", + .aif_name = "MM_DL22", + .rates = (SNDRV_PCM_RATE_8000_384000 | + SNDRV_PCM_RATE_KNOT), + .formats = (SNDRV_PCM_FMTBIT_S16_LE | + SNDRV_PCM_FMTBIT_S24_LE | + SNDRV_PCM_FMTBIT_S24_3LE | + SNDRV_PCM_FMTBIT_S32_LE), + .channels_min = 1, + .channels_max = 8, + .rate_min = 8000, + .rate_max = 384000, + }, + .ops = &msm_fe_Multimedia_dai_ops, + .name = "MultiMedia22", + .probe = fe_dai_probe, + }, + { + .playback = { + .stream_name = "MultiMedia23 Playback", + .aif_name = "MM_DL23", + .rates = (SNDRV_PCM_RATE_8000_384000 | + SNDRV_PCM_RATE_KNOT), + .formats = (SNDRV_PCM_FMTBIT_S16_LE | + SNDRV_PCM_FMTBIT_S24_LE | + SNDRV_PCM_FMTBIT_S24_3LE | + SNDRV_PCM_FMTBIT_S32_LE), + .channels_min = 1, + .channels_max = 8, + .rate_min = 8000, + .rate_max = 384000, + }, + .ops = &msm_fe_Multimedia_dai_ops, + .name = "MultiMedia23", + .probe = fe_dai_probe, + }, + { + .playback = { + .stream_name = "MultiMedia24 Playback", + .aif_name = "MM_DL24", + .rates = (SNDRV_PCM_RATE_8000_384000 | + SNDRV_PCM_RATE_KNOT), + .formats = (SNDRV_PCM_FMTBIT_S16_LE | + SNDRV_PCM_FMTBIT_S24_LE | + SNDRV_PCM_FMTBIT_S24_3LE | + SNDRV_PCM_FMTBIT_S32_LE), + .channels_min = 1, + .channels_max = 8, + .rate_min = 8000, + .rate_max = 384000, + }, + .ops = &msm_fe_Multimedia_dai_ops, + .name = "MultiMedia24", + .probe = fe_dai_probe, + }, + { + .playback = { + .stream_name = "MultiMedia25 Playback", + .aif_name = "MM_DL25", + .rates = (SNDRV_PCM_RATE_8000_384000 | + SNDRV_PCM_RATE_KNOT), + .formats = (SNDRV_PCM_FMTBIT_S16_LE | + SNDRV_PCM_FMTBIT_S24_LE | + SNDRV_PCM_FMTBIT_S24_3LE | + SNDRV_PCM_FMTBIT_S32_LE), + .channels_min = 1, + .channels_max = 8, + .rate_min = 8000, + .rate_max = 384000, + }, + .ops = &msm_fe_Multimedia_dai_ops, + .name = "MultiMedia25", + .probe = fe_dai_probe, + }, }; static int msm_fe_dai_dev_probe(struct platform_device *pdev) diff --git a/sound/soc/msm/msm8998.c b/sound/soc/msm/msm8998.c index 0b37e7e073aa..e715770d909a 100644 --- a/sound/soc/msm/msm8998.c +++ b/sound/soc/msm/msm8998.c @@ -397,7 +397,9 @@ static struct dev_config aux_pcm_tx_cfg[] = { }; static int msm_vi_feed_tx_ch = 2; -static const char *const slim_rx_ch_text[] = {"One", "Two"}; +static const char *const slim_rx_ch_text[] = {"One", "Two", "Three", "Four", + "Five", "Six", "Seven", + "Eight"}; static const char *const slim_tx_ch_text[] = {"One", "Two", "Three", "Four", "Five", "Six", "Seven", "Eight"}; @@ -5526,6 +5528,91 @@ static struct snd_soc_dai_link msm_common_misc_fe_dai_links[] = { .ignore_pmdown_time = 1, .be_id = MSM_FRONTEND_DAI_MULTIMEDIA18, }, + { + .name = "MultiMedia21", + .stream_name = "MultiMedia21", + .cpu_dai_name = "MultiMedia21", + .platform_name = "msm-pcm-dsp.0", + .dynamic = 1, + .async_ops = ASYNC_DPCM_SND_SOC_PREPARE, + .dpcm_playback = 1, + .codec_dai_name = "snd-soc-dummy-dai", + .codec_name = "snd-soc-dummy", + .trigger = {SND_SOC_DPCM_TRIGGER_POST, + SND_SOC_DPCM_TRIGGER_POST}, + .ignore_suspend = 1, + /* this dainlink has playback support */ + .ignore_pmdown_time = 1, + .be_id = MSM_FRONTEND_DAI_MULTIMEDIA21, + }, + { + .name = "MultiMedia22", + .stream_name = "MultiMedia22", + .cpu_dai_name = "MultiMedia22", + .platform_name = "msm-pcm-dsp.0", + .dynamic = 1, + .async_ops = ASYNC_DPCM_SND_SOC_PREPARE, + .dpcm_playback = 1, + .codec_dai_name = "snd-soc-dummy-dai", + .codec_name = "snd-soc-dummy", + .trigger = {SND_SOC_DPCM_TRIGGER_POST, + SND_SOC_DPCM_TRIGGER_POST}, + .ignore_suspend = 1, + /* this dainlink has playback support */ + .ignore_pmdown_time = 1, + .be_id = MSM_FRONTEND_DAI_MULTIMEDIA22, + }, + { + .name = "MultiMedia23", + .stream_name = "MultiMedia23", + .cpu_dai_name = "MultiMedia23", + .platform_name = "msm-pcm-dsp.0", + .dynamic = 1, + .async_ops = ASYNC_DPCM_SND_SOC_PREPARE, + .dpcm_playback = 1, + .codec_dai_name = "snd-soc-dummy-dai", + .codec_name = "snd-soc-dummy", + .trigger = {SND_SOC_DPCM_TRIGGER_POST, + SND_SOC_DPCM_TRIGGER_POST}, + .ignore_suspend = 1, + /* this dainlink has playback support */ + .ignore_pmdown_time = 1, + .be_id = MSM_FRONTEND_DAI_MULTIMEDIA23, + }, + { + .name = "MultiMedia24", + .stream_name = "MultiMedia24", + .cpu_dai_name = "MultiMedia24", + .platform_name = "msm-pcm-dsp.0", + .dynamic = 1, + .async_ops = ASYNC_DPCM_SND_SOC_PREPARE, + .dpcm_playback = 1, + .codec_dai_name = "snd-soc-dummy-dai", + .codec_name = "snd-soc-dummy", + .trigger = {SND_SOC_DPCM_TRIGGER_POST, + SND_SOC_DPCM_TRIGGER_POST}, + .ignore_suspend = 1, + /* this dainlink has playback support */ + .ignore_pmdown_time = 1, + .be_id = MSM_FRONTEND_DAI_MULTIMEDIA24, + }, + { + .name = "MultiMedia25", + .stream_name = "MultiMedia25", + .cpu_dai_name = "MultiMedia25", + .platform_name = "msm-pcm-dsp.0", + .dynamic = 1, + .async_ops = ASYNC_DPCM_SND_SOC_PREPARE, + .dpcm_playback = 1, + .codec_dai_name = "snd-soc-dummy-dai", + .codec_name = "snd-soc-dummy", + .trigger = {SND_SOC_DPCM_TRIGGER_POST, + SND_SOC_DPCM_TRIGGER_POST}, + .ignore_suspend = 1, + /* this dainlink has playback support */ + .ignore_pmdown_time = 1, + .be_id = MSM_FRONTEND_DAI_MULTIMEDIA25, + }, }; static struct snd_soc_dai_link msm_common_be_dai_links[] = { diff --git a/sound/soc/msm/qdsp6v2/msm-dai-q6-v2.c b/sound/soc/msm/qdsp6v2/msm-dai-q6-v2.c index fa8bdddacef2..3610901addea 100644 --- a/sound/soc/msm/qdsp6v2/msm-dai-q6-v2.c +++ b/sound/soc/msm/qdsp6v2/msm-dai-q6-v2.c @@ -5147,6 +5147,27 @@ static int msm_dai_tdm_q6_probe(struct platform_device *pdev) dev_dbg(&pdev->dev, "%s: Clk Rate from DT file %d\n", __func__, tdm_clk_set.clk_freq_in_hz); + /* initialize static tdm clk attribute to default value */ + tdm_clk_set.clk_attri = Q6AFE_LPASS_CLK_ATTRIBUTE_INVERT_COUPLE_NO; + + /* extract tdm clk attribute into static */ + if (of_find_property(pdev->dev.of_node, + "qcom,msm-cpudai-tdm-clk-attribute", NULL)) { + rc = of_property_read_u16(pdev->dev.of_node, + "qcom,msm-cpudai-tdm-clk-attribute", + &tdm_clk_set.clk_attri); + if (rc) { + dev_err(&pdev->dev, "%s: clk attribute from DT file %s\n", + __func__, "qcom,msm-cpudai-tdm-clk-attribute"); + goto rtn; + } + dev_dbg(&pdev->dev, "%s: clk attribute from DT file %d\n", + __func__, tdm_clk_set.clk_attri); + } else { + dev_dbg(&pdev->dev, "%s: No optional clk attribute found\n", + __func__); + } + /* extract tdm clk src master/slave info into static */ rc = of_property_read_u32(pdev->dev.of_node, "qcom,msm-cpudai-tdm-clk-internal", @@ -6226,6 +6247,41 @@ static int msm_dai_q6_tdm_set_tdm_slot(struct snd_soc_dai *dai, return rc; } +static int msm_dai_q6_tdm_set_sysclk(struct snd_soc_dai *dai, + int clk_id, unsigned int freq, int dir) +{ + struct msm_dai_q6_tdm_dai_data *dai_data = + dev_get_drvdata(dai->dev); + + switch (dai->id) { + case AFE_PORT_ID_PRIMARY_TDM_RX: + case AFE_PORT_ID_PRIMARY_TDM_RX_1: + case AFE_PORT_ID_PRIMARY_TDM_RX_2: + case AFE_PORT_ID_PRIMARY_TDM_RX_3: + case AFE_PORT_ID_PRIMARY_TDM_RX_4: + case AFE_PORT_ID_PRIMARY_TDM_RX_5: + case AFE_PORT_ID_PRIMARY_TDM_RX_6: + case AFE_PORT_ID_PRIMARY_TDM_RX_7: + case AFE_PORT_ID_PRIMARY_TDM_TX: + case AFE_PORT_ID_PRIMARY_TDM_TX_1: + case AFE_PORT_ID_PRIMARY_TDM_TX_2: + case AFE_PORT_ID_PRIMARY_TDM_TX_3: + case AFE_PORT_ID_PRIMARY_TDM_TX_4: + case AFE_PORT_ID_PRIMARY_TDM_TX_5: + case AFE_PORT_ID_PRIMARY_TDM_TX_6: + case AFE_PORT_ID_PRIMARY_TDM_TX_7: + dai_data->clk_set.clk_freq_in_hz = freq; + break; + default: + return 0; + } + + dev_dbg(dai->dev, "%s: dai id = 0x%x group clk_freq %d\n", + __func__, dai->id, freq); + return 0; +} + + static int msm_dai_q6_tdm_set_channel_map(struct snd_soc_dai *dai, unsigned int tx_num, unsigned int *tx_slot, unsigned int rx_num, unsigned int *rx_slot) @@ -6653,6 +6709,7 @@ static struct snd_soc_dai_ops msm_dai_q6_tdm_ops = { .hw_params = msm_dai_q6_tdm_hw_params, .set_tdm_slot = msm_dai_q6_tdm_set_tdm_slot, .set_channel_map = msm_dai_q6_tdm_set_channel_map, + .set_sysclk = msm_dai_q6_tdm_set_sysclk, .shutdown = msm_dai_q6_tdm_shutdown, }; diff --git a/sound/soc/msm/qdsp6v2/msm-pcm-q6-noirq.c b/sound/soc/msm/qdsp6v2/msm-pcm-q6-noirq.c index 6b026bafa276..276270258771 100644 --- a/sound/soc/msm/qdsp6v2/msm-pcm-q6-noirq.c +++ b/sound/soc/msm/qdsp6v2/msm-pcm-q6-noirq.c @@ -30,9 +30,12 @@ #include <sound/control.h> #include <sound/q6audio-v2.h> #include <sound/timer.h> +#include <sound/hwdep.h> + #include <asm/dma.h> #include <sound/tlv.h> #include <sound/pcm_params.h> +#include <sound/devdep_params.h> #include "msm-pcm-q6-v2.h" #include "msm-pcm-routing-v2.h" @@ -421,6 +424,42 @@ static int msm_pcm_trigger(struct snd_pcm_substream *substream, int cmd) return ret; } + +static int msm_pcm_mmap_fd(struct snd_pcm_substream *substream, + struct snd_pcm_mmap_fd *mmap_fd) +{ + struct msm_audio *prtd; + struct audio_port_data *apd; + struct audio_buffer *ab; + int dir = -1; + + if (!substream->runtime) { + pr_err("%s substream runtime not found\n", __func__); + return -EFAULT; + } + + prtd = substream->runtime->private_data; + if (!prtd || !prtd->audio_client || !prtd->mmap_flag) { + pr_err("%s no audio client or not an mmap session\n", __func__); + return -EINVAL; + } + + if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) + dir = IN; + else + dir = OUT; + + apd = prtd->audio_client->port; + ab = &(apd[dir].buf[0]); + mmap_fd->fd = ion_share_dma_buf_fd(ab->client, ab->handle); + if (mmap_fd->fd >= 0) { + mmap_fd->dir = dir; + mmap_fd->actual_size = ab->actual_size; + mmap_fd->size = ab->size; + } + return mmap_fd->fd < 0 ? -EFAULT : 0; +} + static int msm_pcm_ioctl(struct snd_pcm_substream *substream, unsigned int cmd, void *arg) { @@ -445,6 +484,15 @@ static int msm_pcm_ioctl(struct snd_pcm_substream *substream, return snd_pcm_lib_ioctl(substream, cmd, arg); } +#ifdef CONFIG_COMPAT +static int msm_pcm_compat_ioctl(struct snd_pcm_substream *substream, + unsigned int cmd, void *arg) +{ + /* we only handle RESET which is common for both modes */ + return msm_pcm_ioctl(substream, cmd, arg); +} +#endif + static snd_pcm_uframes_t msm_pcm_pointer(struct snd_pcm_substream *substream) { struct snd_pcm_runtime *runtime = substream->runtime; @@ -994,6 +1042,101 @@ static int msm_pcm_add_app_type_controls(struct snd_soc_pcm_runtime *rtd) return 0; } +static int msm_pcm_hwdep_ioctl(struct snd_hwdep *hw, struct file *file, + unsigned int cmd, unsigned long arg) +{ + int ret = 0; + struct snd_pcm *pcm = hw->private_data; + struct snd_pcm_mmap_fd __user *_mmap_fd = NULL; + struct snd_pcm_mmap_fd mmap_fd; + struct snd_pcm_substream *substream = NULL; + int32_t dir = -1; + + switch (cmd) { + case SNDRV_PCM_IOCTL_MMAP_DATA_FD: + _mmap_fd = (struct snd_pcm_mmap_fd __user *)arg; + if (get_user(dir, (int32_t __user *)&(_mmap_fd->dir))) { + pr_err("%s: error copying mmap_fd from user\n", + __func__); + ret = -EFAULT; + break; + } + if (dir != OUT && dir != IN) { + pr_err("%s invalid stream dir\n", __func__); + ret = -EINVAL; + break; + } + substream = pcm->streams[dir].substream; + if (!substream) { + pr_err("%s substream not found\n", __func__); + ret = -ENODEV; + break; + } + pr_debug("%s : %s MMAP Data fd\n", __func__, + dir == 0 ? "P" : "C"); + if (msm_pcm_mmap_fd(substream, &mmap_fd) < 0) { + pr_err("%s: error getting fd\n", + __func__); + ret = -EFAULT; + break; + } + if (put_user(mmap_fd.fd, &_mmap_fd->fd) || + put_user(mmap_fd.size, &_mmap_fd->size) || + put_user(mmap_fd.actual_size, &_mmap_fd->actual_size)) { + pr_err("%s: error copying fd\n", __func__); + return -EFAULT; + } + break; + default: + ret = -EINVAL; + break; + } + return ret; +} + +#ifdef CONFIG_COMPAT +static int msm_pcm_hwdep_compat_ioctl(struct snd_hwdep *hw, + struct file *file, + unsigned int cmd, + unsigned long arg) +{ + /* we only support mmap fd. Handling is common in both modes */ + return msm_pcm_hwdep_ioctl(hw, file, cmd, arg); +} +#else +static int msm_pcm_hwdep_compat_ioctl(struct snd_hwdep *hw, + struct file *file, + unsigned int cmd, + unsigned long arg) +{ + return -EINVAL; +} +#endif + +static int msm_pcm_add_hwdep_dev(struct snd_soc_pcm_runtime *runtime) +{ + struct snd_hwdep *hwdep; + int rc; + char id[] = "NOIRQ_NN"; + + snprintf(id, sizeof(id), "NOIRQ_%d", runtime->pcm->device); + pr_debug("%s: pcm dev %d\n", __func__, runtime->pcm->device); + rc = snd_hwdep_new(runtime->card->snd_card, + &id[0], + HWDEP_FE_BASE + runtime->pcm->device, + &hwdep); + if (!hwdep || rc < 0) { + pr_err("%s: hwdep intf failed to create %s - hwdep\n", __func__, + id); + return rc; + } + + hwdep->iface = SNDRV_HWDEP_IFACE_AUDIO_BE; /* for lack of a FE iface */ + hwdep->private_data = runtime->pcm; /* of type struct snd_pcm */ + hwdep->ops.ioctl = msm_pcm_hwdep_ioctl; + hwdep->ops.ioctl_compat = msm_pcm_hwdep_compat_ioctl; + return 0; +} static int msm_asoc_pcm_new(struct snd_soc_pcm_runtime *rtd) { @@ -1027,7 +1170,9 @@ static int msm_asoc_pcm_new(struct snd_soc_pcm_runtime *rtd) pr_err("%s: Could not add app type controls failed %d\n", __func__, ret); } - + ret = msm_pcm_add_hwdep_dev(rtd); + if (ret) + pr_err("%s: Could not add hw dep node\n", __func__); pcm->nonatomic = true; exit: return ret; @@ -1040,6 +1185,9 @@ static struct snd_pcm_ops msm_pcm_ops = { .copy = msm_pcm_copy, .hw_params = msm_pcm_hw_params, .ioctl = msm_pcm_ioctl, +#ifdef CONFIG_COMPAT + .compat_ioctl = msm_pcm_compat_ioctl, +#endif .trigger = msm_pcm_trigger, .pointer = msm_pcm_pointer, .mmap = msm_pcm_mmap, diff --git a/sound/soc/msm/qdsp6v2/msm-pcm-q6-v2.c b/sound/soc/msm/qdsp6v2/msm-pcm-q6-v2.c index 46a3324d2d6b..de769e8b806c 100644 --- a/sound/soc/msm/qdsp6v2/msm-pcm-q6-v2.c +++ b/sound/soc/msm/qdsp6v2/msm-pcm-q6-v2.c @@ -1603,6 +1603,262 @@ done: return ret; } +static int msm_pcm_playback_pan_scale_ctl_put(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol) +{ + int ret = 0; + int len = 0; + int i = 0; + struct snd_pcm_usr *usr_info = snd_kcontrol_chip(kcontrol); + struct snd_pcm_substream *substream; + struct msm_audio *prtd; + struct asm_stream_pan_ctrl_params pan_param; + + if (!usr_info) { + pr_err("%s: usr_info is null\n", __func__); + ret = -EINVAL; + goto done; + } + + substream = usr_info->pcm->streams[SNDRV_PCM_STREAM_PLAYBACK].substream; + if (!substream) { + pr_err("%s substream not found\n", __func__); + ret = -EINVAL; + goto done; + } + + if (!substream->runtime) { + pr_err("%s substream runtime not found\n", __func__); + ret = -EINVAL; + goto done; + } + prtd = substream->runtime->private_data; + if (!prtd) { + ret = -EINVAL; + goto done; + } + pan_param.num_output_channels = + ucontrol->value.integer.value[len++]; + if (pan_param.num_output_channels > + PCM_FORMAT_MAX_NUM_CHANNEL) { + ret = -EINVAL; + goto done; + } + pan_param.num_input_channels = + ucontrol->value.integer.value[len++]; + if (pan_param.num_input_channels > + PCM_FORMAT_MAX_NUM_CHANNEL) { + ret = -EINVAL; + goto done; + } + + if (ucontrol->value.integer.value[len++]) { + for (i = 0; i < pan_param.num_output_channels; i++) { + pan_param.output_channel_map[i] = + ucontrol->value.integer.value[len++]; + } + } + if (ucontrol->value.integer.value[len++]) { + for (i = 0; i < pan_param.num_input_channels; i++) { + pan_param.input_channel_map[i] = + ucontrol->value.integer.value[len++]; + } + } + if (ucontrol->value.integer.value[len++]) { + for (i = 0; i < pan_param.num_output_channels * + pan_param.num_input_channels; i++) { + pan_param.gain[i] = + !(ucontrol->value.integer.value[len++] > 0) ? + 0 : 2 << 13; + } + } + + ret = q6asm_set_mfc_panning_params(prtd->audio_client, + &pan_param); + len -= pan_param.num_output_channels * + pan_param.num_input_channels; + for (i = 0; i < pan_param.num_output_channels * + pan_param.num_input_channels; i++) { + pan_param.gain[i] = + ucontrol->value.integer.value[len++]; + } + ret = q6asm_set_vol_ctrl_gain_pair(prtd->audio_client, + &pan_param); + +done: + return ret; +} + +static int msm_pcm_playback_pan_scale_ctl_get(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol) +{ + return 0; +} + +static int msm_add_stream_pan_scale_controls(struct snd_soc_pcm_runtime *rtd) +{ + struct snd_pcm *pcm; + struct snd_pcm_usr *pan_ctl_info; + struct snd_kcontrol *kctl; + const char *playback_mixer_ctl_name = "Audio Stream"; + const char *deviceNo = "NN"; + const char *suffix = "Pan Scale Control"; + int ctl_len, ret = 0; + + if (!rtd) { + pr_err("%s: rtd is NULL\n", __func__); + ret = -EINVAL; + goto done; + } + + pcm = rtd->pcm; + ctl_len = strlen(playback_mixer_ctl_name) + 1 + strlen(deviceNo) + 1 + + strlen(suffix) + 1; + + ret = snd_pcm_add_usr_ctls(pcm, SNDRV_PCM_STREAM_PLAYBACK, + NULL, 1, ctl_len, rtd->dai_link->be_id, + &pan_ctl_info); + + if (ret < 0) { + pr_err("%s: failed add ctl %s. err = %d\n", + __func__, suffix, ret); + goto done; + } + kctl = pan_ctl_info->kctl; + snprintf(kctl->id.name, ctl_len, "%s %d %s", playback_mixer_ctl_name, + rtd->pcm->device, suffix); + kctl->put = msm_pcm_playback_pan_scale_ctl_put; + kctl->get = msm_pcm_playback_pan_scale_ctl_get; + pr_debug("%s: Registering new mixer ctl = %s\n", __func__, + kctl->id.name); +done: + return ret; + +} + +static int msm_pcm_playback_dnmix_ctl_get(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol) +{ + return 0; +} + +static int msm_pcm_playback_dnmix_ctl_put(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol) +{ + int ret = 0; + int len = 0; + int i = 0; + struct snd_pcm_usr *usr_info = snd_kcontrol_chip(kcontrol); + struct snd_pcm_substream *substream; + struct msm_audio *prtd; + struct asm_stream_pan_ctrl_params dnmix_param; + + int be_id = ucontrol->value.integer.value[len]; + int stream_id = 0; + + if (!usr_info) { + pr_err("%s usr_info is null\n", __func__); + ret = -EINVAL; + goto done; + } + substream = usr_info->pcm->streams[SNDRV_PCM_STREAM_PLAYBACK].substream; + if (!substream) { + pr_err("%s substream not found\n", __func__); + ret = -EINVAL; + goto done; + } + if (!substream->runtime) { + pr_err("%s substream runtime not found\n", __func__); + ret = -EINVAL; + goto done; + } + prtd = substream->runtime->private_data; + if (!prtd) { + ret = -EINVAL; + goto done; + } + stream_id = prtd->audio_client->session; + dnmix_param.num_output_channels = + ucontrol->value.integer.value[len++]; + if (dnmix_param.num_output_channels > + PCM_FORMAT_MAX_NUM_CHANNEL) { + ret = -EINVAL; + goto done; + } + dnmix_param.num_input_channels = + ucontrol->value.integer.value[len++]; + if (dnmix_param.num_input_channels > + PCM_FORMAT_MAX_NUM_CHANNEL) { + ret = -EINVAL; + goto done; + } + + if (ucontrol->value.integer.value[len++]) { + for (i = 0; i < dnmix_param.num_output_channels; i++) { + dnmix_param.output_channel_map[i] = + ucontrol->value.integer.value[len++]; + } + } + if (ucontrol->value.integer.value[len++]) { + for (i = 0; i < dnmix_param.num_input_channels; i++) { + dnmix_param.input_channel_map[i] = + ucontrol->value.integer.value[len++]; + } + } + if (ucontrol->value.integer.value[len++]) { + for (i = 0; i < dnmix_param.num_output_channels * + dnmix_param.num_input_channels; i++) { + dnmix_param.gain[i] = + ucontrol->value.integer.value[len++]; + } + } + msm_routing_set_downmix_control_data(be_id, + stream_id, + &dnmix_param); + +done: + return ret; +} + +static int msm_add_device_down_mix_controls(struct snd_soc_pcm_runtime *rtd) +{ + struct snd_pcm *pcm; + struct snd_pcm_usr *usr_info; + struct snd_kcontrol *kctl; + const char *playback_mixer_ctl_name = "Audio Device"; + const char *deviceNo = "NN"; + const char *suffix = "Downmix Control"; + int ctl_len, ret = 0; + + if (!rtd) { + pr_err("%s: rtd is NULL\n", __func__); + ret = -EINVAL; + goto done; + } + + pcm = rtd->pcm; + ctl_len = strlen(playback_mixer_ctl_name) + 1 + + strlen(deviceNo) + 1 + strlen(suffix) + 1; + ret = snd_pcm_add_usr_ctls(pcm, SNDRV_PCM_STREAM_PLAYBACK, + NULL, 1, ctl_len, rtd->dai_link->be_id, + &usr_info); + if (ret < 0) { + pr_err("%s: downmix control add failed: %d\n", + __func__, ret); + goto done; + } + + kctl = usr_info->kctl; + snprintf(kctl->id.name, ctl_len, "%s %d %s", + playback_mixer_ctl_name, rtd->pcm->device, suffix); + kctl->put = msm_pcm_playback_dnmix_ctl_put; + kctl->get = msm_pcm_playback_dnmix_ctl_get; + pr_debug("%s: downmix control name = %s\n", + __func__, playback_mixer_ctl_name); +done: + return ret; +} + static int msm_pcm_capture_app_type_cfg_ctl_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) { @@ -1719,6 +1975,14 @@ static int msm_pcm_add_controls(struct snd_soc_pcm_runtime *rtd) if (ret) pr_err("%s: pcm add app type controls failed:%d\n", __func__, ret); + ret = msm_add_stream_pan_scale_controls(rtd); + if (ret) + pr_err("%s: pcm add pan scale controls failed:%d\n", + __func__, ret); + ret = msm_add_device_down_mix_controls(rtd); + if (ret) + pr_err("%s: pcm add dnmix controls failed:%d\n", + __func__, ret); return ret; } diff --git a/sound/soc/msm/qdsp6v2/msm-pcm-routing-v2.c b/sound/soc/msm/qdsp6v2/msm-pcm-routing-v2.c index 974d4a582540..2bf61521ad52 100644 --- a/sound/soc/msm/qdsp6v2/msm-pcm-routing-v2.c +++ b/sound/soc/msm/qdsp6v2/msm-pcm-routing-v2.c @@ -35,6 +35,8 @@ #include <sound/audio_cal_utils.h> #include <sound/audio_effects.h> #include <sound/hwdep.h> +#include <sound/q6adm-v2.h> +#include <sound/apr_audio-v2.h> #include "msm-pcm-routing-v2.h" #include "msm-pcm-routing-devdep.h" @@ -118,17 +120,13 @@ static const char * const lsm_port_text[] = { }; struct msm_pcm_route_bdai_pp_params { - u16 port_id; /* AFE port ID */ unsigned long pp_params_config; bool mute_on; int latency; }; static struct msm_pcm_route_bdai_pp_params - msm_bedais_pp_params[MSM_BACKEND_DAI_PP_PARAMS_REQ_MAX] = { - {HDMI_RX, 0, 0, 0}, - {DISPLAY_PORT_RX, 0, 0, 0}, -}; + msm_bedais_pp_params[MSM_BACKEND_DAI_MAX]; /* * The be_dai_name_table is passed to HAL so that it can specify the @@ -142,6 +140,7 @@ struct msm_pcm_route_bdai_name { }; static struct msm_pcm_route_bdai_name be_dai_name_table[MSM_BACKEND_DAI_MAX]; +static bool msm_pcm_routing_test_pp_param(int be_idx, long param_bit); static int msm_routing_send_device_pp_params(int port_id, int copp_idx, int fe_id); @@ -953,7 +952,7 @@ static void msm_pcm_routing_build_matrix(int fedai_id, int sess_type, uint32_t passthr_mode) { int i, port_type, j, num_copps = 0; - struct route_payload payload; + struct route_payload payload = { {0} }; port_type = ((path_type == ADM_PATH_PLAYBACK || path_type == ADM_PATH_COMPRESSED_RX) ? @@ -983,6 +982,11 @@ static void msm_pcm_routing_build_matrix(int fedai_id, int sess_type, fe_dai_app_type_cfg [fedai_id][sess_type][i] .sample_rate; + if (msm_pcm_routing_test_pp_param(i, + ADM_PP_PARAM_LIMITER_BIT)) + set_bit(ADM_STATUS_LIMITER, + &payload.route_status + [num_copps]); num_copps++; } } @@ -1088,7 +1092,7 @@ int msm_pcm_routing_reg_phy_compr_stream(int fe_id, int perf_mode, port_type = MSM_AFE_PORT_TYPE_RX; } else if (stream_type == SNDRV_PCM_STREAM_CAPTURE) { session_type = SESSION_TYPE_TX; - if (passthr_mode != LEGACY_PCM) + if ((passthr_mode != LEGACY_PCM) && (passthr_mode != LISTEN)) path_type = ADM_PATH_COMPRESSED_TX; else path_type = ADM_PATH_LIVE_REC; @@ -1204,6 +1208,11 @@ int msm_pcm_routing_reg_phy_compr_stream(int fe_id, int perf_mode, fe_dai_app_type_cfg [fe_id][session_type][i] .sample_rate; + if (msm_pcm_routing_test_pp_param(i, + ADM_PP_PARAM_LIMITER_BIT)) + set_bit(ADM_STATUS_LIMITER, + &payload.route_status + [num_copps]); num_copps++; } } @@ -1434,6 +1443,11 @@ int msm_pcm_routing_reg_phy_stream(int fedai_id, int perf_mode, fe_dai_app_type_cfg [fedai_id][session_type] [i].sample_rate; + if (msm_pcm_routing_test_pp_param(i, + ADM_PP_PARAM_LIMITER_BIT)) + set_bit(ADM_STATUS_LIMITER, + &payload.route_status + [num_copps]); num_copps++; } } @@ -4090,6 +4104,21 @@ static const struct snd_kcontrol_new slimbus_rx_mixer_controls[] = { SOC_SINGLE_EXT("MultiMedia19", MSM_BACKEND_DAI_SLIMBUS_0_RX, MSM_FRONTEND_DAI_MULTIMEDIA19, 1, 0, msm_routing_get_audio_mixer, msm_routing_put_audio_mixer), + SOC_SINGLE_EXT("MultiMedia21", MSM_BACKEND_DAI_SLIMBUS_0_RX, + MSM_FRONTEND_DAI_MULTIMEDIA21, 1, 0, msm_routing_get_audio_mixer, + msm_routing_put_audio_mixer), + SOC_SINGLE_EXT("MultiMedia22", MSM_BACKEND_DAI_SLIMBUS_0_RX, + MSM_FRONTEND_DAI_MULTIMEDIA22, 1, 0, msm_routing_get_audio_mixer, + msm_routing_put_audio_mixer), + SOC_SINGLE_EXT("MultiMedia23", MSM_BACKEND_DAI_SLIMBUS_0_RX, + MSM_FRONTEND_DAI_MULTIMEDIA23, 1, 0, msm_routing_get_audio_mixer, + msm_routing_put_audio_mixer), + SOC_SINGLE_EXT("MultiMedia24", MSM_BACKEND_DAI_SLIMBUS_0_RX, + MSM_FRONTEND_DAI_MULTIMEDIA24, 1, 0, msm_routing_get_audio_mixer, + msm_routing_put_audio_mixer), + SOC_SINGLE_EXT("MultiMedia25", MSM_BACKEND_DAI_SLIMBUS_0_RX, + MSM_FRONTEND_DAI_MULTIMEDIA25, 1, 0, msm_routing_get_audio_mixer, + msm_routing_put_audio_mixer), }; static const struct snd_kcontrol_new mi2s_rx_mixer_controls[] = { @@ -4612,6 +4641,21 @@ static const struct snd_kcontrol_new hdmi_mixer_controls[] = { SOC_SINGLE_EXT("MultiMedia19", MSM_BACKEND_DAI_HDMI_RX, MSM_FRONTEND_DAI_MULTIMEDIA19, 1, 0, msm_routing_get_audio_mixer, msm_routing_put_audio_mixer), + SOC_SINGLE_EXT("MultiMedia21", MSM_BACKEND_DAI_HDMI_RX, + MSM_FRONTEND_DAI_MULTIMEDIA21, 1, 0, msm_routing_get_audio_mixer, + msm_routing_put_audio_mixer), + SOC_SINGLE_EXT("MultiMedia22", MSM_BACKEND_DAI_HDMI_RX, + MSM_FRONTEND_DAI_MULTIMEDIA22, 1, 0, msm_routing_get_audio_mixer, + msm_routing_put_audio_mixer), + SOC_SINGLE_EXT("MultiMedia23", MSM_BACKEND_DAI_HDMI_RX, + MSM_FRONTEND_DAI_MULTIMEDIA23, 1, 0, msm_routing_get_audio_mixer, + msm_routing_put_audio_mixer), + SOC_SINGLE_EXT("MultiMedia24", MSM_BACKEND_DAI_HDMI_RX, + MSM_FRONTEND_DAI_MULTIMEDIA24, 1, 0, msm_routing_get_audio_mixer, + msm_routing_put_audio_mixer), + SOC_SINGLE_EXT("MultiMedia25", MSM_BACKEND_DAI_HDMI_RX, + MSM_FRONTEND_DAI_MULTIMEDIA25, 1, 0, msm_routing_get_audio_mixer, + msm_routing_put_audio_mixer), }; static const struct snd_kcontrol_new display_port_mixer_controls[] = { @@ -4760,6 +4804,21 @@ static const struct snd_kcontrol_new slimbus_6_rx_mixer_controls[] = { SOC_SINGLE_EXT("MultiMedia16", MSM_BACKEND_DAI_SLIMBUS_6_RX, MSM_FRONTEND_DAI_MULTIMEDIA16, 1, 0, msm_routing_get_audio_mixer, msm_routing_put_audio_mixer), + SOC_SINGLE_EXT("MultiMedia21", MSM_BACKEND_DAI_SLIMBUS_6_RX, + MSM_FRONTEND_DAI_MULTIMEDIA21, 1, 0, msm_routing_get_audio_mixer, + msm_routing_put_audio_mixer), + SOC_SINGLE_EXT("MultiMedia22", MSM_BACKEND_DAI_SLIMBUS_6_RX, + MSM_FRONTEND_DAI_MULTIMEDIA22, 1, 0, msm_routing_get_audio_mixer, + msm_routing_put_audio_mixer), + SOC_SINGLE_EXT("MultiMedia23", MSM_BACKEND_DAI_SLIMBUS_6_RX, + MSM_FRONTEND_DAI_MULTIMEDIA23, 1, 0, msm_routing_get_audio_mixer, + msm_routing_put_audio_mixer), + SOC_SINGLE_EXT("MultiMedia24", MSM_BACKEND_DAI_SLIMBUS_6_RX, + MSM_FRONTEND_DAI_MULTIMEDIA24, 1, 0, msm_routing_get_audio_mixer, + msm_routing_put_audio_mixer), + SOC_SINGLE_EXT("MultiMedia25", MSM_BACKEND_DAI_SLIMBUS_6_RX, + MSM_FRONTEND_DAI_MULTIMEDIA25, 1, 0, msm_routing_get_audio_mixer, + msm_routing_put_audio_mixer), }; static const struct snd_kcontrol_new slimbus_7_rx_mixer_controls[] = { @@ -4811,6 +4870,21 @@ static const struct snd_kcontrol_new slimbus_7_rx_mixer_controls[] = { SOC_SINGLE_EXT("MultiMedia16", MSM_BACKEND_DAI_SLIMBUS_7_RX, MSM_FRONTEND_DAI_MULTIMEDIA16, 1, 0, msm_routing_get_audio_mixer, msm_routing_put_audio_mixer), + SOC_SINGLE_EXT("MultiMedia21", MSM_BACKEND_DAI_SLIMBUS_7_RX, + MSM_FRONTEND_DAI_MULTIMEDIA21, 1, 0, msm_routing_get_audio_mixer, + msm_routing_put_audio_mixer), + SOC_SINGLE_EXT("MultiMedia22", MSM_BACKEND_DAI_SLIMBUS_7_RX, + MSM_FRONTEND_DAI_MULTIMEDIA22, 1, 0, msm_routing_get_audio_mixer, + msm_routing_put_audio_mixer), + SOC_SINGLE_EXT("MultiMedia23", MSM_BACKEND_DAI_SLIMBUS_7_RX, + MSM_FRONTEND_DAI_MULTIMEDIA23, 1, 0, msm_routing_get_audio_mixer, + msm_routing_put_audio_mixer), + SOC_SINGLE_EXT("MultiMedia24", MSM_BACKEND_DAI_SLIMBUS_7_RX, + MSM_FRONTEND_DAI_MULTIMEDIA24, 1, 0, msm_routing_get_audio_mixer, + msm_routing_put_audio_mixer), + SOC_SINGLE_EXT("MultiMedia25", MSM_BACKEND_DAI_SLIMBUS_7_RX, + MSM_FRONTEND_DAI_MULTIMEDIA25, 1, 0, msm_routing_get_audio_mixer, + msm_routing_put_audio_mixer), }; static const struct snd_kcontrol_new usb_audio_rx_mixer_controls[] = { @@ -9797,6 +9871,22 @@ static const struct snd_kcontrol_new quat_tdm_rx_0_port_mixer_controls[] = { MSM_BACKEND_DAI_SEC_AUXPCM_TX, 1, 0, msm_routing_get_port_mixer, msm_routing_put_port_mixer), + SOC_SINGLE_EXT("PRI_TDM_TX_0", MSM_BACKEND_DAI_QUAT_TDM_RX_0, + MSM_BACKEND_DAI_PRI_TDM_TX_0, 1, 0, + msm_routing_get_port_mixer, + msm_routing_put_port_mixer), + SOC_SINGLE_EXT("PRI_TDM_TX_1", MSM_BACKEND_DAI_QUAT_TDM_RX_0, + MSM_BACKEND_DAI_PRI_TDM_TX_1, 1, 0, + msm_routing_get_port_mixer, + msm_routing_put_port_mixer), + SOC_SINGLE_EXT("PRI_TDM_TX_2", MSM_BACKEND_DAI_QUAT_TDM_RX_0, + MSM_BACKEND_DAI_PRI_TDM_TX_2, 1, 0, + msm_routing_get_port_mixer, + msm_routing_put_port_mixer), + SOC_SINGLE_EXT("PRI_TDM_TX_3", MSM_BACKEND_DAI_QUAT_TDM_RX_0, + MSM_BACKEND_DAI_PRI_TDM_TX_3, 1, 0, + msm_routing_get_port_mixer, + msm_routing_put_port_mixer), SOC_SINGLE_EXT("TERT_TDM_TX_0", MSM_BACKEND_DAI_QUAT_TDM_RX_0, MSM_BACKEND_DAI_TERT_TDM_TX_0, 1, 0, msm_routing_get_port_mixer, @@ -9864,6 +9954,22 @@ static const struct snd_kcontrol_new quat_tdm_rx_1_port_mixer_controls[] = { MSM_BACKEND_DAI_SEC_AUXPCM_TX, 1, 0, msm_routing_get_port_mixer, msm_routing_put_port_mixer), + SOC_SINGLE_EXT("PRI_TDM_TX_0", MSM_BACKEND_DAI_QUAT_TDM_RX_1, + MSM_BACKEND_DAI_PRI_TDM_TX_0, 1, 0, + msm_routing_get_port_mixer, + msm_routing_put_port_mixer), + SOC_SINGLE_EXT("PRI_TDM_TX_1", MSM_BACKEND_DAI_QUAT_TDM_RX_1, + MSM_BACKEND_DAI_PRI_TDM_TX_1, 1, 0, + msm_routing_get_port_mixer, + msm_routing_put_port_mixer), + SOC_SINGLE_EXT("PRI_TDM_TX_2", MSM_BACKEND_DAI_QUAT_TDM_RX_1, + MSM_BACKEND_DAI_PRI_TDM_TX_2, 1, 0, + msm_routing_get_port_mixer, + msm_routing_put_port_mixer), + SOC_SINGLE_EXT("PRI_TDM_TX_3", MSM_BACKEND_DAI_QUAT_TDM_RX_1, + MSM_BACKEND_DAI_PRI_TDM_TX_3, 1, 0, + msm_routing_get_port_mixer, + msm_routing_put_port_mixer), SOC_SINGLE_EXT("TERT_TDM_TX_0", MSM_BACKEND_DAI_QUAT_TDM_RX_1, MSM_BACKEND_DAI_TERT_TDM_TX_0, 1, 0, msm_routing_get_port_mixer, @@ -9931,6 +10037,22 @@ static const struct snd_kcontrol_new quat_tdm_rx_2_port_mixer_controls[] = { MSM_BACKEND_DAI_SEC_AUXPCM_TX, 1, 0, msm_routing_get_port_mixer, msm_routing_put_port_mixer), + SOC_SINGLE_EXT("PRI_TDM_TX_0", MSM_BACKEND_DAI_QUAT_TDM_RX_2, + MSM_BACKEND_DAI_PRI_TDM_TX_0, 1, 0, + msm_routing_get_port_mixer, + msm_routing_put_port_mixer), + SOC_SINGLE_EXT("PRI_TDM_TX_1", MSM_BACKEND_DAI_QUAT_TDM_RX_2, + MSM_BACKEND_DAI_PRI_TDM_TX_1, 1, 0, + msm_routing_get_port_mixer, + msm_routing_put_port_mixer), + SOC_SINGLE_EXT("PRI_TDM_TX_2", MSM_BACKEND_DAI_QUAT_TDM_RX_2, + MSM_BACKEND_DAI_PRI_TDM_TX_2, 1, 0, + msm_routing_get_port_mixer, + msm_routing_put_port_mixer), + SOC_SINGLE_EXT("PRI_TDM_TX_3", MSM_BACKEND_DAI_QUAT_TDM_RX_2, + MSM_BACKEND_DAI_PRI_TDM_TX_3, 1, 0, + msm_routing_get_port_mixer, + msm_routing_put_port_mixer), SOC_SINGLE_EXT("TERT_TDM_TX_0", MSM_BACKEND_DAI_QUAT_TDM_RX_2, MSM_BACKEND_DAI_TERT_TDM_TX_0, 1, 0, msm_routing_get_port_mixer, @@ -9998,6 +10120,22 @@ static const struct snd_kcontrol_new quat_tdm_rx_3_port_mixer_controls[] = { MSM_BACKEND_DAI_SEC_AUXPCM_TX, 1, 0, msm_routing_get_port_mixer, msm_routing_put_port_mixer), + SOC_SINGLE_EXT("PRI_TDM_TX_0", MSM_BACKEND_DAI_QUAT_TDM_RX_3, + MSM_BACKEND_DAI_PRI_TDM_TX_0, 1, 0, + msm_routing_get_port_mixer, + msm_routing_put_port_mixer), + SOC_SINGLE_EXT("PRI_TDM_TX_1", MSM_BACKEND_DAI_QUAT_TDM_RX_3, + MSM_BACKEND_DAI_PRI_TDM_TX_1, 1, 0, + msm_routing_get_port_mixer, + msm_routing_put_port_mixer), + SOC_SINGLE_EXT("PRI_TDM_TX_2", MSM_BACKEND_DAI_QUAT_TDM_RX_3, + MSM_BACKEND_DAI_PRI_TDM_TX_2, 1, 0, + msm_routing_get_port_mixer, + msm_routing_put_port_mixer), + SOC_SINGLE_EXT("PRI_TDM_TX_3", MSM_BACKEND_DAI_QUAT_TDM_RX_3, + MSM_BACKEND_DAI_PRI_TDM_TX_3, 1, 0, + msm_routing_get_port_mixer, + msm_routing_put_port_mixer), SOC_SINGLE_EXT("TERT_TDM_TX_0", MSM_BACKEND_DAI_QUAT_TDM_RX_3, MSM_BACKEND_DAI_TERT_TDM_TX_0, 1, 0, msm_routing_get_port_mixer, @@ -11314,6 +11452,11 @@ static const struct snd_soc_dapm_widget msm_qdsp6_widgets[] = { SND_SOC_DAPM_AIF_IN("MM_DL15", "MultiMedia15 Playback", 0, 0, 0, 0), SND_SOC_DAPM_AIF_IN("MM_DL16", "MultiMedia16 Playback", 0, 0, 0, 0), SND_SOC_DAPM_AIF_IN("MM_DL20", "MultiMedia20 Playback", 0, 0, 0, 0), + SND_SOC_DAPM_AIF_IN("MM_DL21", "MultiMedia21 Playback", 0, 0, 0, 0), + SND_SOC_DAPM_AIF_IN("MM_DL22", "MultiMedia22 Playback", 0, 0, 0, 0), + SND_SOC_DAPM_AIF_IN("MM_DL23", "MultiMedia23 Playback", 0, 0, 0, 0), + SND_SOC_DAPM_AIF_IN("MM_DL24", "MultiMedia24 Playback", 0, 0, 0, 0), + SND_SOC_DAPM_AIF_IN("MM_DL25", "MultiMedia25 Playback", 0, 0, 0, 0), SND_SOC_DAPM_AIF_IN("VOIP_DL", "VoIP Playback", 0, 0, 0, 0), SND_SOC_DAPM_AIF_OUT("MM_UL1", "MultiMedia1 Capture", 0, 0, 0, 0), SND_SOC_DAPM_AIF_OUT("MM_UL2", "MultiMedia2 Capture", 0, 0, 0, 0), @@ -12450,6 +12593,11 @@ static const struct snd_soc_dapm_route intercon[] = { {"SLIMBUS_0_RX Audio Mixer", "MultiMedia14", "MM_DL14"}, {"SLIMBUS_0_RX Audio Mixer", "MultiMedia15", "MM_DL15"}, {"SLIMBUS_0_RX Audio Mixer", "MultiMedia16", "MM_DL16"}, + {"SLIMBUS_0_RX Audio Mixer", "MultiMedia21", "MM_DL21"}, + {"SLIMBUS_0_RX Audio Mixer", "MultiMedia22", "MM_DL22"}, + {"SLIMBUS_0_RX Audio Mixer", "MultiMedia23", "MM_DL23"}, + {"SLIMBUS_0_RX Audio Mixer", "MultiMedia24", "MM_DL24"}, + {"SLIMBUS_0_RX Audio Mixer", "MultiMedia25", "MM_DL25"}, {"SLIMBUS_0_RX", NULL, "SLIMBUS_0_RX Audio Mixer"}, {"SLIMBUS_2_RX Audio Mixer", "MultiMedia1", "MM_DL1"}, @@ -12504,6 +12652,11 @@ static const struct snd_soc_dapm_route intercon[] = { {"HDMI Mixer", "MultiMedia14", "MM_DL14"}, {"HDMI Mixer", "MultiMedia15", "MM_DL15"}, {"HDMI Mixer", "MultiMedia16", "MM_DL16"}, + {"HDMI Mixer", "MultiMedia21", "MM_DL21"}, + {"HDMI Mixer", "MultiMedia22", "MM_DL22"}, + {"HDMI Mixer", "MultiMedia23", "MM_DL23"}, + {"HDMI Mixer", "MultiMedia24", "MM_DL24"}, + {"HDMI Mixer", "MultiMedia25", "MM_DL25"}, {"HDMI", NULL, "HDMI Mixer"}, {"DISPLAY_PORT Mixer", "MultiMedia1", "MM_DL1"}, @@ -12575,6 +12728,11 @@ static const struct snd_soc_dapm_route intercon[] = { {"SLIMBUS_6_RX Audio Mixer", "MultiMedia14", "MM_DL14"}, {"SLIMBUS_6_RX Audio Mixer", "MultiMedia15", "MM_DL15"}, {"SLIMBUS_6_RX Audio Mixer", "MultiMedia16", "MM_DL16"}, + {"SLIMBUS_6_RX Audio Mixer", "MultiMedia21", "MM_DL21"}, + {"SLIMBUS_6_RX Audio Mixer", "MultiMedia22", "MM_DL22"}, + {"SLIMBUS_6_RX Audio Mixer", "MultiMedia23", "MM_DL23"}, + {"SLIMBUS_6_RX Audio Mixer", "MultiMedia24", "MM_DL24"}, + {"SLIMBUS_6_RX Audio Mixer", "MultiMedia25", "MM_DL25"}, {"SLIMBUS_6_RX", NULL, "SLIMBUS_6_RX Audio Mixer"}, {"SLIMBUS_7_RX Audio Mixer", "MultiMedia1", "MM_DL1"}, @@ -12593,6 +12751,11 @@ static const struct snd_soc_dapm_route intercon[] = { {"SLIMBUS_7_RX Audio Mixer", "MultiMedia14", "MM_DL14"}, {"SLIMBUS_7_RX Audio Mixer", "MultiMedia15", "MM_DL15"}, {"SLIMBUS_7_RX Audio Mixer", "MultiMedia16", "MM_DL16"}, + {"SLIMBUS_7_RX Audio Mixer", "MultiMedia21", "MM_DL21"}, + {"SLIMBUS_7_RX Audio Mixer", "MultiMedia22", "MM_DL22"}, + {"SLIMBUS_7_RX Audio Mixer", "MultiMedia23", "MM_DL23"}, + {"SLIMBUS_7_RX Audio Mixer", "MultiMedia24", "MM_DL24"}, + {"SLIMBUS_7_RX Audio Mixer", "MultiMedia25", "MM_DL25"}, {"SLIMBUS_7_RX", NULL, "SLIMBUS_7_RX Audio Mixer"}, {"USB_AUDIO_RX Audio Mixer", "MultiMedia1", "MM_DL1"}, @@ -14460,6 +14623,10 @@ static const struct snd_soc_dapm_route intercon[] = { {"QUAT_TDM_RX_0 Port Mixer", "AFE_PCM_TX", "PCM_TX"}, {"QUAT_TDM_RX_0 Port Mixer", "AUX_PCM_UL_TX", "AUX_PCM_TX"}, {"QUAT_TDM_RX_0 Port Mixer", "SEC_AUX_PCM_UL_TX", "SEC_AUX_PCM_TX"}, + {"QUAT_TDM_RX_0 Port Mixer", "PRI_TDM_TX_0", "PRI_TDM_TX_0"}, + {"QUAT_TDM_RX_0 Port Mixer", "PRI_TDM_TX_1", "PRI_TDM_TX_1"}, + {"QUAT_TDM_RX_0 Port Mixer", "PRI_TDM_TX_2", "PRI_TDM_TX_2"}, + {"QUAT_TDM_RX_0 Port Mixer", "PRI_TDM_TX_3", "PRI_TDM_TX_3"}, {"QUAT_TDM_RX_0 Port Mixer", "TERT_TDM_TX_0", "TERT_TDM_TX_0"}, {"QUAT_TDM_RX_0 Port Mixer", "TERT_TDM_TX_1", "TERT_TDM_TX_1"}, {"QUAT_TDM_RX_0 Port Mixer", "TERT_TDM_TX_2", "TERT_TDM_TX_2"}, @@ -14478,6 +14645,10 @@ static const struct snd_soc_dapm_route intercon[] = { {"QUAT_TDM_RX_1 Port Mixer", "AFE_PCM_TX", "PCM_TX"}, {"QUAT_TDM_RX_1 Port Mixer", "AUX_PCM_UL_TX", "AUX_PCM_TX"}, {"QUAT_TDM_RX_1 Port Mixer", "SEC_AUX_PCM_UL_TX", "SEC_AUX_PCM_TX"}, + {"QUAT_TDM_RX_1 Port Mixer", "PRI_TDM_TX_0", "PRI_TDM_TX_0"}, + {"QUAT_TDM_RX_1 Port Mixer", "PRI_TDM_TX_1", "PRI_TDM_TX_1"}, + {"QUAT_TDM_RX_1 Port Mixer", "PRI_TDM_TX_2", "PRI_TDM_TX_2"}, + {"QUAT_TDM_RX_1 Port Mixer", "PRI_TDM_TX_3", "PRI_TDM_TX_3"}, {"QUAT_TDM_RX_1 Port Mixer", "TERT_TDM_TX_0", "TERT_TDM_TX_0"}, {"QUAT_TDM_RX_1 Port Mixer", "TERT_TDM_TX_1", "TERT_TDM_TX_1"}, {"QUAT_TDM_RX_1 Port Mixer", "TERT_TDM_TX_2", "TERT_TDM_TX_2"}, @@ -14496,6 +14667,10 @@ static const struct snd_soc_dapm_route intercon[] = { {"QUAT_TDM_RX_2 Port Mixer", "AFE_PCM_TX", "PCM_TX"}, {"QUAT_TDM_RX_2 Port Mixer", "AUX_PCM_UL_TX", "AUX_PCM_TX"}, {"QUAT_TDM_RX_2 Port Mixer", "SEC_AUX_PCM_UL_TX", "SEC_AUX_PCM_TX"}, + {"QUAT_TDM_RX_2 Port Mixer", "PRI_TDM_TX_0", "PRI_TDM_TX_0"}, + {"QUAT_TDM_RX_2 Port Mixer", "PRI_TDM_TX_1", "PRI_TDM_TX_1"}, + {"QUAT_TDM_RX_2 Port Mixer", "PRI_TDM_TX_2", "PRI_TDM_TX_2"}, + {"QUAT_TDM_RX_2 Port Mixer", "PRI_TDM_TX_3", "PRI_TDM_TX_3"}, {"QUAT_TDM_RX_2 Port Mixer", "TERT_TDM_TX_0", "TERT_TDM_TX_0"}, {"QUAT_TDM_RX_2 Port Mixer", "TERT_TDM_TX_1", "TERT_TDM_TX_1"}, {"QUAT_TDM_RX_2 Port Mixer", "TERT_TDM_TX_2", "TERT_TDM_TX_2"}, @@ -14514,6 +14689,10 @@ static const struct snd_soc_dapm_route intercon[] = { {"QUAT_TDM_RX_3 Port Mixer", "AFE_PCM_TX", "PCM_TX"}, {"QUAT_TDM_RX_3 Port Mixer", "AUX_PCM_UL_TX", "AUX_PCM_TX"}, {"QUAT_TDM_RX_3 Port Mixer", "SEC_AUX_PCM_UL_TX", "SEC_AUX_PCM_TX"}, + {"QUAT_TDM_RX_3 Port Mixer", "PRI_TDM_TX_0", "PRI_TDM_TX_0"}, + {"QUAT_TDM_RX_3 Port Mixer", "PRI_TDM_TX_1", "PRI_TDM_TX_1"}, + {"QUAT_TDM_RX_3 Port Mixer", "PRI_TDM_TX_2", "PRI_TDM_TX_2"}, + {"QUAT_TDM_RX_3 Port Mixer", "PRI_TDM_TX_3", "PRI_TDM_TX_3"}, {"QUAT_TDM_RX_3 Port Mixer", "TERT_TDM_TX_0", "TERT_TDM_TX_0"}, {"QUAT_TDM_RX_3 Port Mixer", "TERT_TDM_TX_1", "TERT_TDM_TX_1"}, {"QUAT_TDM_RX_3 Port Mixer", "TERT_TDM_TX_2", "TERT_TDM_TX_2"}, @@ -15168,7 +15347,7 @@ done: static int msm_routing_send_device_pp_params(int port_id, int copp_idx, int fe_id) { - int index, topo_id, be_idx; + int topo_id, be_idx; unsigned long pp_config = 0; bool mute_on; int latency; @@ -15192,16 +15371,6 @@ static int msm_routing_send_device_pp_params(int port_id, int copp_idx, return -EINVAL; } - for (index = 0; index < MSM_BACKEND_DAI_PP_PARAMS_REQ_MAX; index++) { - if (msm_bedais_pp_params[index].port_id == port_id) - break; - } - if (index >= MSM_BACKEND_DAI_PP_PARAMS_REQ_MAX) { - pr_err("%s: Invalid backend pp params index %d\n", - __func__, index); - return -EINVAL; - } - topo_id = adm_get_topology_for_port_copp_idx(port_id, copp_idx); if (topo_id != COMPRESSED_PASSTHROUGH_DEFAULT_TOPOLOGY) { pr_err("%s: Invalid passthrough topology 0x%x\n", @@ -15213,11 +15382,11 @@ static int msm_routing_send_device_pp_params(int port_id, int copp_idx, (msm_bedais[be_idx].passthr_mode[fe_id] == LISTEN)) compr_passthr_mode = false; - pp_config = msm_bedais_pp_params[index].pp_params_config; + pp_config = msm_bedais_pp_params[be_idx].pp_params_config; if (test_bit(ADM_PP_PARAM_MUTE_BIT, &pp_config)) { pr_debug("%s: ADM_PP_PARAM_MUTE\n", __func__); clear_bit(ADM_PP_PARAM_MUTE_BIT, &pp_config); - mute_on = msm_bedais_pp_params[index].mute_on; + mute_on = msm_bedais_pp_params[be_idx].mute_on; if ((msm_bedais[be_idx].active) && compr_passthr_mode) adm_send_compressed_device_mute(port_id, copp_idx, @@ -15227,7 +15396,7 @@ static int msm_routing_send_device_pp_params(int port_id, int copp_idx, pr_debug("%s: ADM_PP_PARAM_LATENCY\n", __func__); clear_bit(ADM_PP_PARAM_LATENCY_BIT, &pp_config); - latency = msm_bedais_pp_params[index].latency; + latency = msm_bedais_pp_params[be_idx].latency; if ((msm_bedais[be_idx].active) && compr_passthr_mode) adm_send_compressed_device_latency(port_id, copp_idx, @@ -15236,18 +15405,47 @@ static int msm_routing_send_device_pp_params(int port_id, int copp_idx, return 0; } +static bool msm_pcm_routing_test_pp_param(int be_idx, long param_bit) +{ + return test_bit(param_bit, + &msm_bedais_pp_params[be_idx].pp_params_config); +} + +static void msm_routing_set_pp_param(long param_bit, int value) +{ + int be_idx; + + if (value) { + for (be_idx = 0; be_idx < MSM_BACKEND_DAI_MAX; be_idx++) + set_bit(param_bit, + &msm_bedais_pp_params[be_idx]. + pp_params_config); + } else { + for (be_idx = 0; be_idx < MSM_BACKEND_DAI_MAX; be_idx++) + clear_bit(param_bit, + &msm_bedais_pp_params[be_idx]. + pp_params_config); + } +} + static int msm_routing_put_device_pp_params_mixer(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) { int pp_id = ucontrol->value.integer.value[0]; + int value = ucontrol->value.integer.value[1]; int port_id = 0; - int index, be_idx, i, topo_id, idx; + int be_idx, i, topo_id, idx; bool mute; int latency; bool compr_passthr_mode = true; pr_debug("%s: pp_id: 0x%x\n", __func__, pp_id); + if (pp_id == ADM_PP_PARAM_LIMITER_ID) { + msm_routing_set_pp_param(ADM_PP_PARAM_LIMITER_BIT, value); + goto done; + } + for (be_idx = 0; be_idx < MSM_BACKEND_DAI_MAX; be_idx++) { port_id = msm_bedais[be_idx].port_id; if (port_id == HDMI_RX || port_id == DISPLAY_PORT_RX) @@ -15259,16 +15457,6 @@ static int msm_routing_put_device_pp_params_mixer(struct snd_kcontrol *kcontrol, return -EINVAL; } - for (index = 0; index < MSM_BACKEND_DAI_PP_PARAMS_REQ_MAX; index++) { - if (msm_bedais_pp_params[index].port_id == port_id) - break; - } - if (index >= MSM_BACKEND_DAI_PP_PARAMS_REQ_MAX) { - pr_err("%s: Invalid pp params backend index %d\n", - __func__, index); - return -EINVAL; - } - for_each_set_bit(i, &msm_bedais[be_idx].fe_sessions[0], MSM_FRONTEND_DAI_MM_SIZE) { if ((msm_bedais[be_idx].passthr_mode[i] == LEGACY_PCM) || @@ -15291,22 +15479,20 @@ static int msm_routing_put_device_pp_params_mixer(struct snd_kcontrol *kcontrol, switch (pp_id) { case ADM_PP_PARAM_MUTE_ID: pr_debug("%s: ADM_PP_PARAM_MUTE\n", __func__); - mute = ucontrol->value.integer.value[1] ? true : false; - msm_bedais_pp_params[index].mute_on = mute; + mute = value ? true : false; + msm_bedais_pp_params[be_idx].mute_on = mute; set_bit(ADM_PP_PARAM_MUTE_BIT, - &msm_bedais_pp_params[index].pp_params_config); + &msm_bedais_pp_params[be_idx].pp_params_config); if ((msm_bedais[be_idx].active) && compr_passthr_mode) adm_send_compressed_device_mute(port_id, idx, mute); break; case ADM_PP_PARAM_LATENCY_ID: pr_debug("%s: ADM_PP_PARAM_LATENCY\n", __func__); - msm_bedais_pp_params[index].latency = - ucontrol->value.integer.value[1]; + msm_bedais_pp_params[be_idx].latency = value; set_bit(ADM_PP_PARAM_LATENCY_BIT, - &msm_bedais_pp_params[index].pp_params_config); - latency = msm_bedais_pp_params[index].latency = - ucontrol->value.integer.value[1]; + &msm_bedais_pp_params[be_idx].pp_params_config); + latency = msm_bedais_pp_params[be_idx].latency = value; if ((msm_bedais[be_idx].active) && compr_passthr_mode) adm_send_compressed_device_latency(port_id, idx, latency); @@ -15318,6 +15504,7 @@ static int msm_routing_put_device_pp_params_mixer(struct snd_kcontrol *kcontrol, } } } +done: return 0; } @@ -15486,6 +15673,93 @@ static struct snd_pcm_ops msm_routing_pcm_ops = { .prepare = msm_pcm_routing_prepare, }; +int msm_routing_set_downmix_control_data(int be_id, int session_id, + struct asm_stream_pan_ctrl_params *dnmix_param) +{ + int i, rc = 0; + struct adm_pspd_param_data_t data; + struct audproc_chmixer_param_coeff dnmix_cfg; + uint16_t variable_payload = 0; + char *adm_params = NULL; + int port_id, copp_idx = 0; + uint32_t params_length = 0; + + if (be_id >= MSM_BACKEND_DAI_MAX) { + rc = -EINVAL; + return rc; + } + port_id = msm_bedais[be_id].port_id; + copp_idx = adm_get_default_copp_idx(port_id); + pr_debug("%s: port_id - %d, copp_idx %d session id - %d\n", + __func__, port_id, copp_idx, session_id); + + variable_payload = dnmix_param->num_output_channels * sizeof(uint16_t)+ + dnmix_param->num_input_channels * sizeof(uint16_t) + + dnmix_param->num_output_channels * sizeof(uint16_t) * + dnmix_param->num_input_channels * sizeof(uint16_t); + i = (variable_payload % sizeof(uint32_t)); + variable_payload += (i == 0) ? 0 : sizeof(uint32_t) - i; + + params_length = variable_payload + + sizeof(struct adm_pspd_param_data_t) + + sizeof(struct audproc_chmixer_param_coeff); + adm_params = kzalloc(params_length, GFP_KERNEL); + if (!adm_params) { + rc = -ENOMEM; + goto end; + } + + data.module_id = AUDPROC_MODULE_ID_CHMIXER; + data.param_id = AUDPROC_CHMIXER_PARAM_ID_COEFF; + data.param_size = sizeof(struct audproc_chmixer_param_coeff) + + variable_payload; + data.reserved = 0; + memcpy((u8 *)adm_params, &data, sizeof(struct adm_pspd_param_data_t)); + + dnmix_cfg.index = 0; + dnmix_cfg.num_output_channels = dnmix_param->num_output_channels; + dnmix_cfg.num_input_channels = dnmix_param->num_input_channels; + memcpy(((u8 *)adm_params + + sizeof(struct adm_pspd_param_data_t)), + &dnmix_cfg, sizeof(struct audproc_chmixer_param_coeff)); + + memcpy(((u8 *)adm_params + + sizeof(struct adm_pspd_param_data_t) + + sizeof(struct audproc_chmixer_param_coeff)), + dnmix_param->output_channel_map, + dnmix_param->num_output_channels * sizeof(uint16_t)); + memcpy(((u8 *)adm_params + + sizeof(struct adm_pspd_param_data_t) + + sizeof(struct audproc_chmixer_param_coeff) + + dnmix_param->num_output_channels * sizeof(uint16_t)), + dnmix_param->input_channel_map, + dnmix_param->num_input_channels * sizeof(uint16_t)); + memcpy(((u8 *)adm_params + + sizeof(struct adm_pspd_param_data_t) + + sizeof(struct audproc_chmixer_param_coeff) + + (dnmix_param->num_output_channels * sizeof(uint16_t)) + + (dnmix_param->num_input_channels * sizeof(uint16_t))), + dnmix_param->gain, + (dnmix_param->num_output_channels * sizeof(uint16_t)) * + (dnmix_param->num_input_channels * sizeof(uint16_t))); + + if (params_length) { + rc = adm_set_pspd_matrix_params(port_id, + copp_idx, + session_id, + adm_params, + params_length); + if (rc) { + pr_err("%s: send params failed rc=%d\n", __func__, rc); + rc = -EINVAL; + } + } +end: + kfree(adm_params); + return rc; +} + + /* Not used but frame seems to require it */ static int msm_routing_probe(struct snd_soc_platform *platform) { diff --git a/sound/soc/msm/qdsp6v2/msm-pcm-routing-v2.h b/sound/soc/msm/qdsp6v2/msm-pcm-routing-v2.h index 19e726001d25..a8daff09db58 100644 --- a/sound/soc/msm/qdsp6v2/msm-pcm-routing-v2.h +++ b/sound/soc/msm/qdsp6v2/msm-pcm-routing-v2.h @@ -193,6 +193,11 @@ enum { MSM_FRONTEND_DAI_MULTIMEDIA18, MSM_FRONTEND_DAI_MULTIMEDIA19, MSM_FRONTEND_DAI_MULTIMEDIA20, + MSM_FRONTEND_DAI_MULTIMEDIA21, + MSM_FRONTEND_DAI_MULTIMEDIA22, + MSM_FRONTEND_DAI_MULTIMEDIA23, + MSM_FRONTEND_DAI_MULTIMEDIA24, + MSM_FRONTEND_DAI_MULTIMEDIA25, MSM_FRONTEND_DAI_CS_VOICE, MSM_FRONTEND_DAI_VOIP, MSM_FRONTEND_DAI_AFE_RX, @@ -218,8 +223,8 @@ enum { MSM_FRONTEND_DAI_MAX, }; -#define MSM_FRONTEND_DAI_MM_SIZE (MSM_FRONTEND_DAI_MULTIMEDIA20 + 1) -#define MSM_FRONTEND_DAI_MM_MAX_ID MSM_FRONTEND_DAI_MULTIMEDIA20 +#define MSM_FRONTEND_DAI_MM_SIZE (MSM_FRONTEND_DAI_MULTIMEDIA25 + 1) +#define MSM_FRONTEND_DAI_MM_MAX_ID MSM_FRONTEND_DAI_MULTIMEDIA25 enum { MSM_BACKEND_DAI_PRI_I2S_RX = 0, @@ -392,12 +397,20 @@ enum { #define RELEASE_LOCK 0 #define ACQUIRE_LOCK 1 -#define MSM_BACKEND_DAI_PP_PARAMS_REQ_MAX 2 #define HDMI_RX_ID 0x8001 -#define ADM_PP_PARAM_MUTE_ID 0 -#define ADM_PP_PARAM_MUTE_BIT 1 -#define ADM_PP_PARAM_LATENCY_ID 1 -#define ADM_PP_PARAM_LATENCY_BIT 2 + +enum { + ADM_PP_PARAM_MUTE_ID, + ADM_PP_PARAM_LATENCY_ID, + ADM_PP_PARAM_LIMITER_ID +}; + +enum { + ADM_PP_PARAM_MUTE_BIT = 0x1, + ADM_PP_PARAM_LATENCY_BIT = 0x2, + ADM_PP_PARAM_LIMITER_BIT = 0x4 +}; + #define BE_DAI_PORT_SESSIONS_IDX_MAX 4 #define BE_DAI_FE_SESSIONS_IDX_MAX 2 @@ -483,4 +496,6 @@ int msm_pcm_routing_reg_stream_app_type_cfg( int msm_pcm_routing_get_stream_app_type_cfg( int fedai_id, int session_type, int *be_id, struct msm_pcm_stream_app_type_cfg *cfg_data); +int msm_routing_set_downmix_control_data(int be_id, int session_id, + struct asm_stream_pan_ctrl_params *pan_param); #endif /*_MSM_PCM_H*/ diff --git a/sound/soc/msm/qdsp6v2/msm-qti-pp-config.c b/sound/soc/msm/qdsp6v2/msm-qti-pp-config.c index cac28f43e5ae..65f5167d9dee 100644 --- a/sound/soc/msm/qdsp6v2/msm-qti-pp-config.c +++ b/sound/soc/msm/qdsp6v2/msm-qti-pp-config.c @@ -298,11 +298,11 @@ int msm_qti_pp_send_stereo_to_custom_stereo_cmd(int port_id, int copp_idx, *update_params_value16++ = op_FR_ip_FR_weight; avail_length = avail_length - (4 * sizeof(uint16_t)); if (params_length) { - rc = adm_set_stereo_to_custom_stereo(port_id, - copp_idx, - session_id, - params_value, - params_length); + rc = adm_set_pspd_matrix_params(port_id, + copp_idx, + session_id, + params_value, + params_length); if (rc) { pr_err("%s: send params failed rc=%d\n", __func__, rc); kfree(params_value); diff --git a/sound/soc/msm/qdsp6v2/q6adm.c b/sound/soc/msm/qdsp6v2/q6adm.c index 28aaf2172221..e1bfc950d0e3 100644 --- a/sound/soc/msm/qdsp6v2/q6adm.c +++ b/sound/soc/msm/qdsp6v2/q6adm.c @@ -48,12 +48,6 @@ #define DS2_ADM_COPP_TOPOLOGY_ID 0xFFFFFFFF #endif -/* ENUM for adm_status */ -enum adm_cal_status { - ADM_STATUS_CALIBRATION_REQUIRED = 0, - ADM_STATUS_MAX, -}; - struct adm_copp { atomic_t id[AFE_MAX_PORTS][MAX_COPPS_PER_PORT]; @@ -781,9 +775,9 @@ fail_cmd: return ret; } -int adm_set_stereo_to_custom_stereo(int port_id, int copp_idx, - unsigned int session_id, char *params, - uint32_t params_length) +int adm_set_pspd_matrix_params(int port_id, int copp_idx, + unsigned int session_id, char *params, + uint32_t params_length) { struct adm_cmd_set_pspd_mtmx_strtr_params_v5 *adm_params = NULL; int sz, rc = 0, port_idx; @@ -1413,6 +1407,7 @@ static int32_t adm_callback(struct apr_client_data *data, void *priv) case ADM_CMD_DEVICE_OPEN_V5: case ADM_CMD_DEVICE_CLOSE_V5: case ADM_CMD_DEVICE_OPEN_V6: + case ADM_CMD_SET_MTMX_STRTR_DEV_PARAMS_V1: pr_debug("%s: Basic callback received, wake up.\n", __func__); atomic_set(&this_adm.copp.stat[port_idx] @@ -2695,6 +2690,97 @@ fail_cmd: return; } + +static int adm_set_mtmx_params_v1(int port_idx, int copp_idx, + int params_length, void *params) +{ + struct adm_cmd_set_mtmx_params_v1 *adm_params = NULL; + int rc = 0; + int sz; + + sz = sizeof(*adm_params) + params_length; + adm_params = kzalloc(sz, GFP_KERNEL); + if (!adm_params) + return -ENOMEM; + + memcpy(((u8 *)adm_params + sizeof(*adm_params)), + params, params_length); + adm_params->hdr.hdr_field = APR_HDR_FIELD(APR_MSG_TYPE_SEQ_CMD, + APR_HDR_LEN(APR_HDR_SIZE), APR_PKT_VER); + adm_params->hdr.pkt_size = sz; + adm_params->hdr.src_svc = APR_SVC_ADM; + adm_params->hdr.src_domain = APR_DOMAIN_APPS; + adm_params->hdr.src_port = 0; + adm_params->hdr.dest_svc = APR_SVC_ADM; + adm_params->hdr.dest_domain = APR_DOMAIN_ADSP; + adm_params->hdr.dest_port = + atomic_read(&this_adm.copp.id[port_idx][copp_idx]); + adm_params->hdr.token = port_idx << 16 | copp_idx; + adm_params->hdr.opcode = ADM_CMD_SET_MTMX_STRTR_DEV_PARAMS_V1; + adm_params->payload_addr_lsw = 0; + adm_params->payload_addr_msw = 0; + adm_params->mem_map_handle = 0; + adm_params->payload_size = params_length; + adm_params->copp_id = atomic_read(&this_adm.copp. + id[port_idx][copp_idx]); + + atomic_set(&this_adm.copp.stat[port_idx][copp_idx], -1); + rc = apr_send_pkt(this_adm.apr, (uint32_t *)adm_params); + if (rc < 0) { + pr_err("%s: Set params failed port_idx = 0x%x rc %d\n", + __func__, port_idx, rc); + rc = -EINVAL; + goto send_param_return; + } + /* Wait for the callback */ + rc = wait_event_timeout(this_adm.copp.wait[port_idx][copp_idx], + atomic_read(&this_adm.copp.stat[port_idx][copp_idx]) >= 0, + msecs_to_jiffies(TIMEOUT_MS)); + if (!rc) { + pr_err("%s: Set params timed out port_idx = 0x%x\n", + __func__, port_idx); + rc = -EINVAL; + goto send_param_return; + } else if (atomic_read(&this_adm.copp.stat + [port_idx][copp_idx]) > 0) { + pr_err("%s: DSP returned error[%s]\n", + __func__, adsp_err_get_err_str( + atomic_read(&this_adm.copp.stat + [port_idx][copp_idx]))); + rc = adsp_err_get_lnx_err_code( + atomic_read(&this_adm.copp.stat + [port_idx][copp_idx])); + goto send_param_return; + } + rc = 0; +send_param_return: + kfree(adm_params); + return rc; +} + +static void adm_enable_mtmx_limiter(int port_idx, int copp_idx) +{ + int rc; + struct enable_param_v6 adm_param = { {0} }; + + adm_param.param.module_id = ADM_MTMX_MODULE_STREAM_LIMITER; + adm_param.param.param_id = AUDPROC_PARAM_ID_ENABLE; + adm_param.param.param_size = sizeof(adm_param.enable); + adm_param.enable = 1; + + rc = adm_set_mtmx_params_v1(port_idx, copp_idx, + sizeof(adm_param), &adm_param); + if (rc < 0) { + pr_err("%s: adm_set_mtmx_params_v1 failed port_idx = 0x%x rc %d\n", + __func__, port_idx, rc); + goto done; + } + set_bit(ADM_STATUS_LIMITER, + (void *)&this_adm.copp.adm_status[port_idx][copp_idx]); +done: + return; +} + static void route_set_opcode_matrix_id( struct adm_cmd_matrix_map_routings_v5 **route_addr, int path, uint32_t passthr_mode) @@ -2791,6 +2877,11 @@ int adm_matrix_map(int path, struct route_payload payload_map, int perf_mode, copp_idx = payload_map.copp_idx[i]; copps_list[i] = atomic_read(&this_adm.copp.id[port_idx] [copp_idx]); + if (test_bit(ADM_STATUS_LIMITER, + (void *)&payload_map.route_status) && + ((path == ADM_PATH_PLAYBACK) || + (path == ADM_PATH_COMPRESSED_RX))) + adm_enable_mtmx_limiter(port_idx, copp_idx); } atomic_set(&this_adm.matrix_map_stat, -1); @@ -2991,6 +3082,8 @@ int adm_close(int port_id, int perf_mode, int copp_idx) clear_bit(ADM_STATUS_CALIBRATION_REQUIRED, (void *)&this_adm.copp.adm_status[port_idx][copp_idx]); + clear_bit(ADM_STATUS_LIMITER, + (void *)&this_adm.copp.adm_status[port_idx][copp_idx]); ret = apr_send_pkt(this_adm.apr, (uint32_t *)&close); if (ret < 0) { @@ -4807,8 +4900,7 @@ static int __init adm_init(void) &this_adm.copp.adm_delay_wait[i][j]); atomic_set(&this_adm.copp.topology[i][j], 0); this_adm.copp.adm_delay[i][j] = 0; - this_adm.copp.adm_status[i][j] = - ADM_STATUS_CALIBRATION_REQUIRED; + this_adm.copp.adm_status[i][j] = 0; } } diff --git a/sound/soc/msm/qdsp6v2/q6asm.c b/sound/soc/msm/qdsp6v2/q6asm.c index 44e5b01b1ccb..d3cff9fccf59 100644 --- a/sound/soc/msm/qdsp6v2/q6asm.c +++ b/sound/soc/msm/qdsp6v2/q6asm.c @@ -44,7 +44,7 @@ #define TRUE 0x01 #define FALSE 0x00 #define SESSION_MAX 8 - +#define ASM_MAX_CHANNELS 8 enum { ASM_TOPOLOGY_CAL = 0, ASM_CUSTOM_TOP_CAL, @@ -7419,6 +7419,296 @@ int q6asm_set_softvolume_v2(struct audio_client *ac, return __q6asm_set_softvolume(ac, softvol_param, instance); } +int q6asm_set_vol_ctrl_gain_pair(struct audio_client *ac, + struct asm_stream_pan_ctrl_params *pan_param) +{ + int sz = 0; + int rc = 0; + int i = 0; + int32_t ch = 0; + struct apr_hdr hdr; + struct audproc_volume_ctrl_channel_type_gain_pair + gain_data[ASM_MAX_CHANNELS]; + struct asm_stream_cmd_set_pp_params_v2 payload_params; + struct asm_stream_param_data_v2 data; + uint16_t *asm_params = NULL; + + if (ac == NULL) { + pr_err("%s: ac is NULL\n", __func__); + rc = -EINVAL; + goto fail; + } + if (ac->apr == NULL) { + dev_err(ac->dev, "%s: ac apr handle NULL\n", __func__); + rc = -EINVAL; + goto fail; + } + + sz = sizeof(struct apr_hdr) + + sizeof(struct asm_stream_cmd_set_pp_params_v2) + + sizeof(struct asm_stream_param_data_v2) + + sizeof(uint32_t) + + (sizeof(struct audproc_volume_ctrl_channel_type_gain_pair) * + ASM_MAX_CHANNELS); + asm_params = kzalloc(sz, GFP_KERNEL); + if (!asm_params) { + rc = -ENOMEM; + goto fail; + } + + q6asm_add_hdr_async(ac, &hdr, sz, TRUE); + atomic_set(&ac->cmd_state_pp, -1); + + hdr.opcode = ASM_STREAM_CMD_SET_PP_PARAMS_V2; + memcpy(((u8 *)asm_params), &hdr, sizeof(struct apr_hdr)); + + payload_params.data_payload_addr_lsw = 0; + payload_params.data_payload_addr_msw = 0; + payload_params.mem_map_handle = 0; + payload_params.data_payload_size = + sizeof(struct asm_stream_param_data_v2) + + sizeof(uint32_t) + + (sizeof(struct audproc_volume_ctrl_channel_type_gain_pair) * + ASM_MAX_CHANNELS); + memcpy(((u8 *)asm_params + sizeof(struct apr_hdr)), + &payload_params, + sizeof(struct asm_stream_cmd_set_pp_params_v2)); + + data.module_id = AUDPROC_MODULE_ID_VOL_CTRL; + data.param_id = AUDPROC_PARAM_ID_MULTICHANNEL_GAIN; + data.param_size = sizeof(uint32_t) + + (sizeof(struct audproc_volume_ctrl_channel_type_gain_pair) * + ASM_MAX_CHANNELS); + data.reserved = 0; + memcpy(((u8 *)asm_params + sizeof(struct apr_hdr) + + sizeof(struct asm_stream_cmd_set_pp_params_v2)), + &data, sizeof(struct asm_stream_param_data_v2)); + + ch = pan_param->num_output_channels; + memcpy(((u8 *)asm_params + sizeof(struct apr_hdr) + + sizeof(struct asm_stream_cmd_set_pp_params_v2) + + sizeof(struct asm_stream_param_data_v2)), + &ch, + sizeof(uint32_t)); + + memset(gain_data, 0, + ASM_MAX_CHANNELS * + sizeof(struct audproc_volume_ctrl_channel_type_gain_pair)); + for (i = 0; i < pan_param->num_output_channels; i++) { + gain_data[i].channel_type = + pan_param->output_channel_map[i]; + gain_data[i].gain = pan_param->gain[i]; + } + memcpy(((u8 *)asm_params + sizeof(struct apr_hdr) + + sizeof(struct asm_stream_cmd_set_pp_params_v2) + + sizeof(struct asm_stream_param_data_v2) + + sizeof(uint32_t)), + gain_data, + ASM_MAX_CHANNELS * + sizeof(struct audproc_volume_ctrl_channel_type_gain_pair)); + + rc = apr_send_pkt(ac->apr, (uint32_t *) asm_params); + if (rc < 0) { + pr_err("%s: set-params send failed paramid[0x%x] rc %d\n", + __func__, data.param_id, rc); + goto done; + } + + rc = wait_event_timeout(ac->cmd_wait, + (atomic_read(&ac->cmd_state_pp) >= 0), 5 * HZ); + if (!rc) { + pr_err("%s: timeout, set-params paramid[0x%x]\n", __func__, + data.param_id); + rc = -EINVAL; + goto done; + } + if (atomic_read(&ac->cmd_state_pp) > 0) { + pr_err("%s: DSP returned error[%d], set-params paramid[0x%x]\n", + __func__, atomic_read(&ac->cmd_state_pp), + data.param_id); + rc = -EINVAL; + goto done; + } + rc = 0; +done: + kfree(asm_params); +fail: + return rc; +} + +int q6asm_set_mfc_panning_params(struct audio_client *ac, + struct asm_stream_pan_ctrl_params *pan_param) +{ + int sz, rc, i; + struct audproc_mfc_output_media_fmt mfc_cfg; + struct apr_hdr hdr; + struct asm_stream_cmd_set_pp_params_v2 payload_params; + struct asm_stream_param_data_v2 data; + struct audproc_chmixer_param_coeff pan_cfg; + uint16_t variable_payload = 0; + uint16_t *asm_params = NULL; + + sz = rc = i = 0; + if (ac == NULL) { + pr_err("%s: ac handle NULL\n", __func__); + rc = -EINVAL; + goto fail_cmd1; + } + if (ac->apr == NULL) { + pr_err("%s: ac apr handle NULL\n", __func__); + rc = -EINVAL; + goto fail_cmd1; + } + + sz = sizeof(struct audproc_mfc_output_media_fmt); + q6asm_add_hdr_async(ac, &mfc_cfg.params.hdr, sz, TRUE); + atomic_set(&ac->cmd_state_pp, -1); + mfc_cfg.params.hdr.opcode = ASM_STREAM_CMD_SET_PP_PARAMS_V2; + mfc_cfg.params.payload_addr_lsw = 0; + mfc_cfg.params.payload_addr_msw = 0; + mfc_cfg.params.mem_map_handle = 0; + mfc_cfg.params.payload_size = sizeof(mfc_cfg) - sizeof(mfc_cfg.params); + mfc_cfg.data.module_id = AUDPROC_MODULE_ID_MFC; + mfc_cfg.data.param_id = AUDPROC_PARAM_ID_MFC_OUTPUT_MEDIA_FORMAT; + mfc_cfg.data.param_size = mfc_cfg.params.payload_size - + sizeof(mfc_cfg.data); + mfc_cfg.data.reserved = 0; + mfc_cfg.sampling_rate = 0; + mfc_cfg.bits_per_sample = 0; + mfc_cfg.num_channels = pan_param->num_output_channels; + for (i = 0; i < mfc_cfg.num_channels; i++) + mfc_cfg.channel_type[i] = pan_param->output_channel_map[i]; + + rc = apr_send_pkt(ac->apr, (uint32_t *) &mfc_cfg); + if (rc < 0) { + pr_err("%s: set-params send failed paramid[0x%x] rc %d\n", + __func__, mfc_cfg.data.param_id, rc); + rc = -EINVAL; + goto fail_cmd1; + } + + rc = wait_event_timeout(ac->cmd_wait, + (atomic_read(&ac->cmd_state_pp) >= 0), 5*HZ); + if (!rc) { + pr_err("%s: timeout, set-params paramid[0x%x]\n", __func__, + mfc_cfg.data.param_id); + rc = -ETIMEDOUT; + goto fail_cmd1; + } + if (atomic_read(&ac->cmd_state_pp) > 0) { + pr_err("%s: DSP returned error[%s] set-params paramid[0x%x]\n", + __func__, adsp_err_get_err_str( + atomic_read(&ac->cmd_state_pp)), + mfc_cfg.data.param_id); + rc = adsp_err_get_lnx_err_code( + atomic_read(&ac->cmd_state_pp)); + goto fail_cmd1; + } + + variable_payload = pan_param->num_output_channels * sizeof(uint16_t)+ + pan_param->num_input_channels * sizeof(uint16_t) + + pan_param->num_output_channels * sizeof(uint16_t) * + pan_param->num_input_channels * sizeof(uint16_t); + i = (variable_payload % sizeof(uint32_t)); + variable_payload += (i == 0) ? 0 : sizeof(uint32_t) - i; + sz = sizeof(struct apr_hdr) + + sizeof(struct asm_stream_cmd_set_pp_params_v2) + + sizeof(struct asm_stream_param_data_v2) + + sizeof(struct audproc_chmixer_param_coeff) + + variable_payload; + + asm_params = kzalloc(sz, GFP_KERNEL); + if (!asm_params) { + rc = -ENOMEM; + goto fail_cmd1; + } + + q6asm_add_hdr_async(ac, &hdr, sz, TRUE); + atomic_set(&ac->cmd_state_pp, -1); + hdr.opcode = ASM_STREAM_CMD_SET_PP_PARAMS_V2; + memcpy(((u8 *)asm_params), &hdr, sizeof(struct apr_hdr)); + + payload_params.data_payload_addr_lsw = 0; + payload_params.data_payload_addr_msw = 0; + payload_params.mem_map_handle = 0; + payload_params.data_payload_size = + sizeof(struct audproc_chmixer_param_coeff) + + variable_payload + sizeof(struct asm_stream_param_data_v2); + memcpy(((u8 *)asm_params + sizeof(struct apr_hdr)), + &payload_params, + sizeof(struct asm_stream_cmd_set_pp_params_v2)); + + data.module_id = AUDPROC_MODULE_ID_MFC; + data.param_id = AUDPROC_CHMIXER_PARAM_ID_COEFF; + data.param_size = sizeof(struct audproc_chmixer_param_coeff) + + variable_payload; + data.reserved = 0; + memcpy(((u8 *)asm_params + sizeof(struct apr_hdr) + + sizeof(struct asm_stream_cmd_set_pp_params_v2)), + &data, sizeof(struct asm_stream_param_data_v2)); + + pan_cfg.index = 0; + pan_cfg.num_output_channels = pan_param->num_output_channels; + pan_cfg.num_input_channels = pan_param->num_input_channels; + memcpy(((u8 *)asm_params + sizeof(struct apr_hdr) + + sizeof(struct asm_stream_cmd_set_pp_params_v2) + + sizeof(struct asm_stream_param_data_v2)), + &pan_cfg, sizeof(struct audproc_chmixer_param_coeff)); + memcpy(((u8 *)asm_params + sizeof(struct apr_hdr) + + sizeof(struct asm_stream_cmd_set_pp_params_v2) + + sizeof(struct asm_stream_param_data_v2) + + sizeof(struct audproc_chmixer_param_coeff)), + pan_param->output_channel_map, + pan_param->num_output_channels * sizeof(uint16_t)); + memcpy(((u8 *)asm_params + sizeof(struct apr_hdr) + + sizeof(struct asm_stream_cmd_set_pp_params_v2) + + sizeof(struct asm_stream_param_data_v2) + + sizeof(struct audproc_chmixer_param_coeff) + + pan_param->num_output_channels * sizeof(uint16_t)), + pan_param->input_channel_map, + pan_param->num_input_channels * sizeof(uint16_t)); + memcpy(((u8 *)asm_params + sizeof(struct apr_hdr) + + sizeof(struct asm_stream_cmd_set_pp_params_v2) + + sizeof(struct asm_stream_param_data_v2) + + sizeof(struct audproc_chmixer_param_coeff) + + (pan_param->num_output_channels * sizeof(uint16_t)) + + (pan_param->num_input_channels * sizeof(uint16_t))), + pan_param->gain, + (pan_param->num_output_channels * sizeof(uint16_t)) * + (pan_param->num_input_channels * sizeof(uint16_t))); + + rc = apr_send_pkt(ac->apr, (uint32_t *) asm_params); + if (rc < 0) { + pr_err("%s: set-params send failed paramid[0x%x] rc %d\n", + __func__, data.param_id, rc); + rc = -EINVAL; + goto fail_cmd2; + } + + rc = wait_event_timeout(ac->cmd_wait, + (atomic_read(&ac->cmd_state_pp) >= 0), 5*HZ); + if (!rc) { + pr_err("%s: timeout, set-params paramid[0x%x]\n", __func__, + data.param_id); + rc = -ETIMEDOUT; + goto fail_cmd2; + } + if (atomic_read(&ac->cmd_state_pp) > 0) { + pr_err("%s: DSP returned error[%s] set-params paramid[0x%x]\n", + __func__, adsp_err_get_err_str( + atomic_read(&ac->cmd_state_pp)), + data.param_id); + rc = adsp_err_get_lnx_err_code( + atomic_read(&ac->cmd_state_pp)); + goto fail_cmd2; + } + rc = 0; +fail_cmd2: + kfree(asm_params); +fail_cmd1: + return rc; +} + int q6asm_equalizer(struct audio_client *ac, void *eq_p) { struct asm_eq_params eq; diff --git a/tools/perf/util/probe-finder.c b/tools/perf/util/probe-finder.c index 05012bb178d7..fdd87c7e3e91 100644 --- a/tools/perf/util/probe-finder.c +++ b/tools/perf/util/probe-finder.c @@ -1460,16 +1460,12 @@ int debuginfo__find_probe_point(struct debuginfo *dbg, unsigned long addr, Dwarf_Addr _addr = 0, baseaddr = 0; const char *fname = NULL, *func = NULL, *basefunc = NULL, *tmp; int baseline = 0, lineno = 0, ret = 0; - bool reloc = false; -retry: + /* We always need to relocate the address for aranges */ + if (debuginfo__get_text_offset(dbg, &baseaddr) == 0) + addr += baseaddr; /* Find cu die */ if (!dwarf_addrdie(dbg->dbg, (Dwarf_Addr)addr, &cudie)) { - if (!reloc && debuginfo__get_text_offset(dbg, &baseaddr) == 0) { - addr += baseaddr; - reloc = true; - goto retry; - } pr_warning("Failed to find debug information for address %lx\n", addr); ret = -EINVAL; |
