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