diff options
33 files changed, 1017 insertions, 165 deletions
diff --git a/Documentation/scheduler/sched-hmp.txt b/Documentation/scheduler/sched-hmp.txt index 22449aec5558..b400e053e55d 100644 --- a/Documentation/scheduler/sched-hmp.txt +++ b/Documentation/scheduler/sched-hmp.txt @@ -1220,6 +1220,23 @@ This tunable is a percentage. Configure the minimum demand of big sync waker task. Scheduler places small wakee tasks woken up by big sync waker on the waker's cluster. +*** 7.19 sched_prefer_sync_wakee_to_waker + +Appears at: /proc/sys/kernel/sched_prefer_sync_wakee_to_waker + +Default value: 0 + +The default sync wakee policy has a preference to select an idle CPU in the +waker cluster compared to the waker CPU running only 1 task. By selecting +an idle CPU, it eliminates the chance of waker migrating to a different CPU +after the wakee preempts it. This policy is also not susceptible to the +incorrect "sync" usage i.e the waker does not goto sleep after waking up +the wakee. + +However LPM exit latency associated with an idle CPU outweigh the above +benefits on some targets. When this knob is turned on, the waker CPU is +selected if it has only 1 runnable task. + ========================= 8. HMP SCHEDULER TRACE POINTS ========================= diff --git a/arch/arm/boot/dts/qcom/msm-audio-lpass.dtsi b/arch/arm/boot/dts/qcom/msm-audio-lpass.dtsi index 6360b54b1013..ba27e3912ee6 100644 --- a/arch/arm/boot/dts/qcom/msm-audio-lpass.dtsi +++ b/arch/arm/boot/dts/qcom/msm-audio-lpass.dtsi @@ -370,4 +370,42 @@ compatible = "qcom,adsp-loader"; qcom,adsp-state = <0>; }; + + qcom,msm-dai-tdm-tert-rx { + compatible = "qcom,msm-dai-tdm"; + qcom,msm-cpudai-tdm-group-id = <37152>; + qcom,msm-cpudai-tdm-group-num-ports = <1>; + qcom,msm-cpudai-tdm-group-port-id = <36896>; + qcom,msm-cpudai-tdm-clk-rate = <1536000>; + pinctrl-names = "default", "sleep"; + dai_tert_tdm_rx_0: qcom,msm-dai-q6-tdm-tert-rx-0 { + compatible = "qcom,msm-dai-q6-tdm"; + qcom,msm-cpudai-tdm-dev-id = <36896>; + qcom,msm-cpudai-tdm-sync-mode = <1>; + qcom,msm-cpudai-tdm-sync-src = <1>; + qcom,msm-cpudai-tdm-data-out = <0>; + qcom,msm-cpudai-tdm-invert-sync = <1>; + qcom,msm-cpudai-tdm-data-delay = <1>; + qcom,msm-cpudai-tdm-data-align = <0>; + }; + }; + + qcom,msm-dai-tdm-tert-tx { + compatible = "qcom,msm-dai-tdm"; + qcom,msm-cpudai-tdm-group-id = <37153>; + qcom,msm-cpudai-tdm-group-num-ports = <1>; + qcom,msm-cpudai-tdm-group-port-id = <36897 >; + qcom,msm-cpudai-tdm-clk-rate = <1536000>; + pinctrl-names = "default", "sleep"; + dai_tert_tdm_tx_0: qcom,msm-dai-q6-tdm-tert-tx-0 { + compatible = "qcom,msm-dai-q6-tdm"; + qcom,msm-cpudai-tdm-dev-id = <36897 >; + qcom,msm-cpudai-tdm-sync-mode = <1>; + qcom,msm-cpudai-tdm-sync-src = <1>; + qcom,msm-cpudai-tdm-data-out = <0>; + qcom,msm-cpudai-tdm-invert-sync = <1>; + qcom,msm-cpudai-tdm-data-delay = <1>; + qcom,msm-cpudai-tdm-data-align = <0>; + }; + }; }; diff --git a/arch/arm/boot/dts/qcom/msm-pm2falcon.dtsi b/arch/arm/boot/dts/qcom/msm-pm2falcon.dtsi new file mode 100644 index 000000000000..399892f52b6f --- /dev/null +++ b/arch/arm/boot/dts/qcom/msm-pm2falcon.dtsi @@ -0,0 +1,377 @@ +/* Copyright (c) 2016, The Linux Foundation. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 and + * only version 2 as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + */ + +#include <dt-bindings/interrupt-controller/irq.h> +#include <dt-bindings/spmi/spmi.h> +#include <dt-bindings/msm/power-on.h> + +&spmi_bus { + qcom,pm2falcon@2 { + compatible = "qcom,spmi-pmic"; + reg = <0x2 SPMI_USID>; + #address-cells = <2>; + #size-cells = <0>; + + pm2falcon_revid: qcom,revid@100 { + compatible = "qcom,qpnp-revid"; + reg = <0x100 0x100>; + }; + + qcom,power-on@800 { + compatible = "qcom,qpnp-power-on"; + reg = <0x800 0x100>; + qcom,secondary-pon-reset; + qcom,hard-reset-poweroff-type = + <PON_POWER_OFF_SHUTDOWN>; + }; + + pm2falcon_gpios: gpios { + compatible = "qcom,qpnp-pin"; + gpio-controller; + #gpio-cells = <2>; + #address-cells = <1>; + #size-cells = <1>; + label = "pm2falcon-gpio"; + + gpio@c000 { + reg = <0xc000 0x100>; + qcom,pin-num = <1>; + status = "disabled"; + }; + + gpio@c100 { + reg = <0xc100 0x100>; + qcom,pin-num = <2>; + status = "disabled"; + }; + + gpio@c200 { + reg = <0xc200 0x100>; + qcom,pin-num = <3>; + status = "disabled"; + }; + + gpio@c300 { + reg = <0xc300 0x100>; + qcom,pin-num = <4>; + status = "disabled"; + }; + + gpio@c400 { + reg = <0xc400 0x100>; + qcom,pin-num = <5>; + status = "disabled"; + }; + + gpio@c500 { + reg = <0xc500 0x100>; + qcom,pin-num = <6>; + status = "disabled"; + }; + + gpio@c600 { + reg = <0xc600 0x100>; + qcom,pin-num = <7>; + status = "disabled"; + }; + + gpio@c700 { + reg = <0xc700 0x100>; + qcom,pin-num = <8>; + status = "disabled"; + }; + + gpio@c800 { + reg = <0xc800 0x100>; + qcom,pin-num = <9>; + status = "disabled"; + }; + + gpio@c900 { + reg = <0xc900 0x100>; + qcom,pin-num = <10>; + status = "disabled"; + }; + + gpio@ca00 { + reg = <0xca00 0x100>; + qcom,pin-num = <11>; + status = "disabled"; + }; + + gpio@cb00 { + reg = <0xcb00 0x100>; + qcom,pin-num = <12>; + status = "disabled"; + }; + + }; + }; + + qcom,pm2falcon@3 { + compatible ="qcom,spmi-pmic"; + reg = <0x3 SPMI_USID>; + #address-cells = <2>; + #size-cells = <0>; + + pm2falcon_pwm_1: pwm@b100 { + compatible = "qcom,qpnp-pwm"; + reg = <0xb100 0x100>, + <0xb042 0x7e>; + reg-names = "qpnp-lpg-channel-base", + "qpnp-lpg-lut-base"; + qcom,channel-id = <1>; + qcom,supported-sizes = <6>, <9>; + qcom,ramp-index = <0>; + #pwm-cells = <2>; + status = "disabled"; + }; + + pm2falcon_pwm_2: pwm@b200 { + compatible = "qcom,qpnp-pwm"; + reg = <0xb200 0x100>, + <0xb042 0x7e>; + reg-names = "qpnp-lpg-channel-base", + "qpnp-lpg-lut-base"; + qcom,channel-id = <2>; + qcom,supported-sizes = <6>, <9>; + qcom,ramp-index = <1>; + #pwm-cells = <2>; + status = "disabled"; + }; + + pm2falcon_pwm_3: pwm@b300 { + compatible = "qcom,qpnp-pwm"; + reg = <0xb300 0x100>, + <0xb042 0x7e>; + reg-names = "qpnp-lpg-channel-base", + "qpnp-lpg-lut-base"; + qcom,channel-id = <3>; + qcom,supported-sizes = <6>, <9>; + qcom,ramp-index = <2>; + #pwm-cells = <2>; + status = "disabled"; + }; + + pm2falcon_pwm_4: pwm@b400 { + compatible = "qcom,qpnp-pwm"; + reg = <0xb400 0x100>, + <0xb042 0x7e>; + reg-names = "qpnp-lpg-channel-base", + "qpnp-lpg-lut-base"; + qcom,channel-id = <4>; + qcom,supported-sizes = <6>, <9>; + qcom,ramp-index = <3>; + #pwm-cells = <2>; + status = "disabled"; + }; + + qcom,leds@d000 { + compatible = "qcom,leds-qpnp"; + reg = <0xd000 0x100>; + label = "rgb"; + status = "disabled"; + + red_led: qcom,rgb_0 { + label = "rgb"; + qcom,id = <3>; + qcom,mode = "pwm"; + pwms = <&pm2falcon_pwm_3 0 0>; + qcom,pwm-us = <1000>; + qcom,max-current = <12>; + qcom,default-state = "off"; + linux,name = "red"; + linux,default-trigger = + "battery-charging"; + }; + + green_led: qcom,rgb_1 { + label = "rgb"; + qcom,id = <4>; + qcom,mode = "pwm"; + pwms = <&pm2falcon_pwm_2 0 0>; + qcom,pwm-us = <1000>; + qcom,max-current = <12>; + qcom,default-state = "off"; + linux,name = "green"; + linux,default-trigger = "battery-full"; + }; + + blue_led: qcom,rgb_2 { + label = "rgb"; + qcom,id = <5>; + qcom,mode = "pwm"; + pwms = <&pm2falcon_pwm_1 0 0>; + qcom,pwm-us = <1000>; + qcom,max-current = <12>; + qcom,default-state = "off"; + linux,name = "blue"; + linux,default-trigger = "boot-indication"; + }; + }; + + pm2falcon_wled: qcom,leds@d800 { + compatible = "qcom,qpnp-wled"; + reg = <0xd800 0x100>, + <0xd900 0x100>, + <0xdc00 0x100>, + <0xde00 0x100>; + reg-names = "qpnp-wled-ctrl-base", + "qpnp-wled-sink-base", + "qpnp-wled-ibb-base", + "qpnp-wled-lab-base"; + interrupts = <0x3 0xd8 0x2>; + interrupt-names = "sc-irq"; + linux,name = "wled"; + linux,default-trigger = "bkl-trigger"; + qcom,fdbk-output = "auto"; + qcom,vref-mv = <350>; + qcom,switch-freq-khz = <800>; + qcom,ovp-mv = <29500>; + qcom,ilim-ma = <980>; + qcom,boost-duty-ns = <26>; + qcom,mod-freq-khz = <9600>; + qcom,dim-mode = "hybrid"; + qcom,hyb-thres = <625>; + qcom,sync-dly-us = <800>; + qcom,fs-curr-ua = <25000>; + qcom,cons-sync-write-delay-us = <1000>; + qcom,en-phase-stag; + qcom,led-strings-list = [00 01 02]; + qcom,en-ext-pfet-sc-pro; + status = "ok"; + }; + + flash_led: qcom,leds@d300 { + compatible = "qcom,qpnp-flash-led-v2"; + reg = <0xd300 0x100>; + label = "flash"; + interrupts = <0x3 0xd3 0x0 IRQ_TYPE_EDGE_RISING>, + <0x3 0xd3 0x3 IRQ_TYPE_EDGE_RISING>, + <0x3 0xd3 0x4 IRQ_TYPE_EDGE_RISING>; + interrupt-names = "led-fault-irq", + "all-ramp-down-done-irq", + "all-ramp-up-done-irq"; + qcom,hdrm-auto-mode; + qcom,short-circuit-det; + qcom,open-circuit-det; + qcom,vph-droop-det; + qcom,thermal-derate-en; + qcom,thermal-derate-current = <200 500 1000>; + qcom,isc-delay = <192>; + status = "disabled"; + + pm2falcon_flash0: qcom,flash_0 { + label = "flash"; + qcom,led-name = "led:flash_0"; + qcom,max-current = <1500>; + qcom,default-led-trigger = "flash0_trigger"; + qcom,id = <0>; + qcom,current-ma = <1000>; + qcom,duration-ms = <1280>; + qcom,ires-ua = <12500>; + qcom,hdrm-voltage-mv = <325>; + qcom,hdrm-vol-hi-lo-win-mv = <100>; + }; + + pm2falcon_flash1: qcom,flash_1 { + label = "flash"; + qcom,led-name = "led:flash_1"; + qcom,max-current = <1500>; + qcom,default-led-trigger = "flash1_trigger"; + qcom,id = <1>; + qcom,current-ma = <1000>; + qcom,duration-ms = <1280>; + qcom,ires-ua = <12500>; + qcom,hdrm-voltage-mv = <325>; + qcom,hdrm-vol-hi-lo-win-mv = <100>; + }; + + pm2falcon_flash2: qcom,flash_2 { + label = "flash"; + qcom,led-name = "led:flash_2"; + qcom,max-current = <750>; + qcom,default-led-trigger = "flash2_trigger"; + qcom,id = <2>; + qcom,current-ma = <500>; + qcom,duration-ms = <1280>; + qcom,ires-ua = <12500>; + qcom,hdrm-voltage-mv = <325>; + qcom,hdrm-vol-hi-lo-win-mv = <100>; + pinctrl-names = "led_enable","led_disable"; + pinctrl-0 = <&led_enable>; + pinctrl-1 = <&led_disable>; + }; + + pm2falcon_torch0: qcom,torch_0 { + label = "torch"; + qcom,led-name = "led:torch_0"; + qcom,max-current = <500>; + qcom,default-led-trigger = "torch0_trigger"; + qcom,id = <0>; + qcom,current-ma = <300>; + qcom,ires-ua = <12500>; + qcom,hdrm-voltage-mv = <325>; + qcom,hdrm-vol-hi-lo-win-mv = <100>; + }; + + pm2falcon_torch1: qcom,torch_1 { + label = "torch"; + qcom,led-name = "led:torch_1"; + qcom,max-current = <500>; + qcom,default-led-trigger = "torch1_trigger"; + qcom,id = <1>; + qcom,current-ma = <300>; + qcom,ires-ua = <12500>; + qcom,hdrm-voltage-mv = <325>; + qcom,hdrm-vol-hi-lo-win-mv = <100>; + }; + + pm2falcon_torch2: qcom,torch_2 { + label = "torch"; + qcom,led-name = "led:torch_2"; + qcom,max-current = <500>; + qcom,default-led-trigger = "torch2_trigger"; + qcom,id = <2>; + qcom,current-ma = <300>; + qcom,ires-ua = <12500>; + qcom,hdrm-voltage-mv = <325>; + qcom,hdrm-vol-hi-lo-win-mv = <100>; + pinctrl-names = "led_enable","led_disable"; + pinctrl-0 = <&led_enable>; + pinctrl-1 = <&led_disable>; + }; + + pm2falcon_switch0: qcom,led_switch_0 { + label = "switch"; + qcom,led-name = "led:switch_0"; + qcom,led-mask = <3>; + qcom,default-led-trigger = "switch0_trigger"; + reg0 { + regulator-name = "pmfalcon_bob"; + max-voltage-uv = <3600000>; + }; + }; + + pm2falcon_switch1: qcom,led_switch_1 { + label = "switch"; + qcom,led-name = "led:switch_1"; + qcom,led-mask = <4>; + qcom,default-led-trigger = "switch1_trigger"; + reg0 { + regulator-name = "pmfalcon_bob"; + max-voltage-uv = <3600000>; + }; + }; + }; + }; +}; diff --git a/arch/arm/boot/dts/qcom/msm-pmfalcon.dtsi b/arch/arm/boot/dts/qcom/msm-pmfalcon.dtsi new file mode 100644 index 000000000000..dec37881249c --- /dev/null +++ b/arch/arm/boot/dts/qcom/msm-pmfalcon.dtsi @@ -0,0 +1,169 @@ +/* Copyright (c) 2016, The Linux Foundation. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 and + * only version 2 as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + */ + +#include <dt-bindings/spmi/spmi.h> +#include <dt-bindings/interrupt-controller/irq.h> + +&spmi_bus { + qcom,pmfalcon@0 { + compatible ="qcom,spmi-pmic"; + reg = <0x0 SPMI_USID>; + #address-cells = <2>; + #size-cells = <0>; + + pmfalcon_revid: qcom,revid@100 { + compatible = "qcom,qpnp-revid"; + reg = <0x100 0x100>; + }; + + qcom,power-on@800 { + compatible = "qcom,qpnp-power-on"; + reg = <0x800 0x100>; + interrupts = <0x0 0x8 0x0 IRQ_TYPE_NONE>, + <0x0 0x8 0x1 IRQ_TYPE_NONE>, + <0x0 0x8 0x4 IRQ_TYPE_NONE>, + <0x0 0x8 0x5 IRQ_TYPE_NONE>; + interrupt-names = "kpdpwr", "resin", + "resin-bark", "kpdpwr-resin-bark"; + qcom,pon-dbc-delay = <15625>; + qcom,system-reset; + qcom,store-hard-reset-reason; + + qcom,pon_1 { + qcom,pon-type = <0>; + qcom,pull-up = <1>; + linux,code = <116>; + }; + + qcom,pon_2 { + qcom,pon-type = <1>; + qcom,pull-up = <1>; + linux,code = <114>; + }; + }; + + pmfalcon_gpios: gpios { + compatible = "qcom,qpnp-pin"; + gpio-controller; + #gpio-cells = <2>; + #address-cells = <1>; + #size-cells = <1>; + label = "pmfalcon-gpio"; + + gpio@c000 { + reg = <0xc000 0x100>; + qcom,pin-num = <1>; + status = "disabled"; + }; + + gpio@c100 { + reg = <0xc100 0x100>; + qcom,pin-num = <2>; + status = "disabled"; + }; + + gpio@c200 { + reg = <0xc200 0x100>; + qcom,pin-num = <3>; + status = "disabled"; + }; + + gpio@c300 { + reg = <0xc300 0x100>; + qcom,pin-num = <4>; + status = "disabled"; + }; + + gpio@c400 { + reg = <0xc400 0x100>; + qcom,pin-num = <5>; + status = "disabled"; + }; + + gpio@c500 { + reg = <0xc500 0x100>; + qcom,pin-num = <6>; + status = "disabled"; + }; + + gpio@c600 { + reg = <0xc600 0x100>; + qcom,pin-num = <7>; + status = "disabled"; + }; + + gpio@c700 { + reg = <0xc700 0x100>; + qcom,pin-num = <8>; + status = "disabled"; + }; + + gpio@c800 { + reg = <0xc800 0x100>; + qcom,pin-num = <9>; + status = "disabled"; + }; + + gpio@c900 { + reg = <0xc900 0x100>; + qcom,pin-num = <10>; + status = "disabled"; + }; + + gpio@ca00 { + reg = <0xca00 0x100>; + qcom,pin-num = <11>; + status = "disabled"; + }; + + gpio@cb00 { + reg = <0xcb00 0x100>; + qcom,pin-num = <12>; + status = "disabled"; + }; + + gpio@cc00 { + reg = <0xcc00 0x100>; + qcom,pin-num = <13>; + status = "disabled"; + }; + }; + + pmfalcon_coincell: qcom,coincell@2800 { + compatible = "qcom,qpnp-coincell"; + reg = <0x2800 0x100>; + }; + + pmfalcon_rtc: qcom,pmfalcon_rtc { + compatible = "qcom,qpnp-rtc"; + #address-cells = <1>; + #size-cells = <1>; + qcom,qpnp-rtc-write = <0>; + qcom,qpnp-rtc-alarm-pwrup = <0>; + + qcom,pmfalcon_rtc_rw@6000 { + reg = <0x6000 0x100>; + }; + qcom,pmfalcon_rtc_alarm@6100 { + reg = <0x6100 0x100>; + interrupts = <0x0 0x61 0x1 IRQ_TYPE_NONE>; + }; + }; + }; + + qcom,pmfalcon@1 { + compatible ="qcom,spmi-pmic"; + reg = <0x1 SPMI_USID>; + #address-cells = <2>; + #size-cells = <0>; + }; +}; diff --git a/arch/arm/boot/dts/qcom/msmcobalt-audio.dtsi b/arch/arm/boot/dts/qcom/msmcobalt-audio.dtsi index ee194c37a6c4..445f32df8aa4 100644 --- a/arch/arm/boot/dts/qcom/msmcobalt-audio.dtsi +++ b/arch/arm/boot/dts/qcom/msmcobalt-audio.dtsi @@ -106,7 +106,8 @@ <&incall_record_tx>, <&incall_music_rx>, <&incall_music_2_rx>, <&sb_5_rx>, <&sb_6_rx>, <&sb_7_rx>, <&sb_7_tx>, <&sb_8_tx>, - <&usb_audio_rx>, <&usb_audio_tx>; + <&usb_audio_rx>, <&usb_audio_tx>, + <&dai_tert_tdm_rx_0>, <&dai_tert_tdm_tx_0>; asoc-cpu-names = "msm-dai-q6-hdmi.8", "msm-dai-q6-dp.24608", "msm-dai-q6-mi2s.0", "msm-dai-q6-mi2s.1", "msm-dai-q6-mi2s.2", "msm-dai-q6-mi2s.3", @@ -124,7 +125,8 @@ "msm-dai-q6-dev.32770", "msm-dai-q6-dev.16394", "msm-dai-q6-dev.16396", "msm-dai-q6-dev.16398", "msm-dai-q6-dev.16399", "msm-dai-q6-dev.16401", - "msm-dai-q6-dev.28672", "msm-dai-q6-dev.28673"; + "msm-dai-q6-dev.28672", "msm-dai-q6-dev.28673", + "msm-dai-q6-tdm.36896", "msm-dai-q6-tdm.36897"; asoc-codec = <&stub_codec>, <&ext_disp_audio_codec>; asoc-codec-names = "msm-stub-codec.1", "msm-ext-disp-audio-codec-rx"; @@ -208,7 +210,8 @@ <&incall_record_tx>, <&incall_music_rx>, <&incall_music_2_rx>, <&sb_5_rx>, <&sb_6_rx>, <&sb_7_rx>, <&sb_7_tx>, <&sb_8_tx>, - <&usb_audio_rx>, <&usb_audio_tx>; + <&usb_audio_rx>, <&usb_audio_tx>, + <&dai_tert_tdm_rx_0>, <&dai_tert_tdm_tx_0>; asoc-cpu-names = "msm-dai-q6-hdmi.8", "msm-dai-q6-dp.24608", "msm-dai-q6-mi2s.0", "msm-dai-q6-mi2s.1", "msm-dai-q6-mi2s.2", "msm-dai-q6-mi2s.3", @@ -226,7 +229,8 @@ "msm-dai-q6-dev.32770", "msm-dai-q6-dev.16394", "msm-dai-q6-dev.16396", "msm-dai-q6-dev.16398", "msm-dai-q6-dev.16399", "msm-dai-q6-dev.16401", - "msm-dai-q6-dev.28672", "msm-dai-q6-dev.28673"; + "msm-dai-q6-dev.28672", "msm-dai-q6-dev.28673", + "msm-dai-q6-tdm.36896", "msm-dai-q6-tdm.36897"; asoc-codec = <&stub_codec>, <&ext_disp_audio_codec>; asoc-codec-names = "msm-stub-codec.1", "msm-ext-disp-audio-codec-rx"; diff --git a/arch/arm/boot/dts/qcom/msmcobalt-pinctrl.dtsi b/arch/arm/boot/dts/qcom/msmcobalt-pinctrl.dtsi index f4f47bc461fc..3975bc5d16f5 100644 --- a/arch/arm/boot/dts/qcom/msmcobalt-pinctrl.dtsi +++ b/arch/arm/boot/dts/qcom/msmcobalt-pinctrl.dtsi @@ -1779,6 +1779,66 @@ }; }; + tsif0_signals_active: tsif0_signals_active { + tsif1_clk { + pins = "gpio89"; /* TSIF0 CLK */ + function = "tsif1_clk"; + }; + tsif1_en { + pins = "gpio90"; /* TSIF0 Enable */ + function = "tsif1_en"; + }; + tsif1_data { + pins = "gpio91"; /* TSIF0 DATA */ + function = "tsif1_data"; + }; + signals_cfg { + pins = "gpio89", "gpio90", "gpio91"; + drive_strength = <2>; /* 2 mA */ + bias-pull-down; /* pull down */ + }; + }; + + /* sync signal is only used if configured to mode-2 */ + tsif0_sync_active: tsif0_sync_active { + tsif1_sync { + pins = "gpio9"; /* TSIF0 SYNC */ + function = "tsif1_sync"; + drive_strength = <2>; /* 2 mA */ + bias-pull-down; /* pull down */ + }; + }; + + tsif1_signals_active: tsif1_signals_active { + tsif2_clk { + pins = "gpio93"; /* TSIF1 CLK */ + function = "tsif2_clk"; + }; + tsif2_en { + pins = "gpio94"; /* TSIF1 Enable */ + function = "tsif2_en"; + }; + tsif2_data { + pins = "gpio95"; /* TSIF1 DATA */ + function = "tsif2_data"; + }; + signals_cfg { + pins = "gpio93", "gpio94", "gpio95"; + drive_strength = <2>; /* 2 mA */ + bias-pull-down; /* pull down */ + }; + }; + + /* sync signal is only used if configured to mode-2 */ + tsif1_sync_active: tsif1_sync_active { + tsif2_sync { + pins = "gpio96"; /* TSIF1 SYNC */ + function = "tsif2_sync"; + drive_strength = <2>; /* 2 mA */ + bias-pull-down; /* pull down */ + }; + }; + pri_aux_pcm_clk { pri_aux_pcm_clk_sleep: pri_aux_pcm_clk_sleep { mux { diff --git a/arch/arm/boot/dts/qcom/msmcobalt.dtsi b/arch/arm/boot/dts/qcom/msmcobalt.dtsi index 33830aefcf36..27f9e2ace106 100644 --- a/arch/arm/boot/dts/qcom/msmcobalt.dtsi +++ b/arch/arm/boot/dts/qcom/msmcobalt.dtsi @@ -2886,6 +2886,57 @@ qcom,icnss-adc_tm = <&pmcobalt_adc_tm>; }; + tspp: msm_tspp@0c1e7000 { + compatible = "qcom,msm_tspp"; + reg = <0x0c1e7000 0x200>, /* MSM_TSIF0_PHYS */ + <0x0c1e8000 0x200>, /* MSM_TSIF1_PHYS */ + <0x0c1e9000 0x1000>, /* MSM_TSPP_PHYS */ + <0x0c1c4000 0x23000>; /* MSM_TSPP_BAM_PHYS */ + reg-names = "MSM_TSIF0_PHYS", + "MSM_TSIF1_PHYS", + "MSM_TSPP_PHYS", + "MSM_TSPP_BAM_PHYS"; + interrupts = <0 121 0>, /* TSIF_TSPP_IRQ */ + <0 119 0>, /* TSIF0_IRQ */ + <0 120 0>, /* TSIF1_IRQ */ + <0 122 0>; /* TSIF_BAM_IRQ */ + interrupt-names = "TSIF_TSPP_IRQ", + "TSIF0_IRQ", + "TSIF1_IRQ", + "TSIF_BAM_IRQ"; + + clock-names = "iface_clk", "ref_clk"; + clocks = <&clock_gcc clk_gcc_tsif_ahb_clk>, + <&clock_gcc clk_gcc_tsif_ref_clk>; + + qcom,msm-bus,name = "tsif"; + qcom,msm-bus,num-cases = <2>; + qcom,msm-bus,num-paths = <1>; + qcom,msm-bus,vectors-KBps = + <82 512 0 0>, /* No vote */ + <82 512 12288 24576>; + /* Max. bandwidth, 2xTSIF, each max of 96Mbps */ + + pinctrl-names = "disabled", + "tsif0-mode1", "tsif0-mode2", + "tsif1-mode1", "tsif1-mode2", + "dual-tsif-mode1", "dual-tsif-mode2"; + + pinctrl-0 = <>; /* disabled */ + pinctrl-1 = <&tsif0_signals_active>; /* tsif0-mode1 */ + pinctrl-2 = <&tsif0_signals_active + &tsif0_sync_active>; /* tsif0-mode2 */ + pinctrl-3 = <&tsif1_signals_active>; /* tsif1-mode1 */ + pinctrl-4 = <&tsif1_signals_active + &tsif1_sync_active>; /* tsif1-mode2 */ + pinctrl-5 = <&tsif0_signals_active + &tsif1_signals_active>; /* dual-tsif-mode1 */ + pinctrl-6 = <&tsif0_signals_active + &tsif0_sync_active + &tsif1_signals_active + &tsif1_sync_active>; /* dual-tsif-mode2 */ + }; + wil6210: qcom,wil6210 { compatible = "qcom,wil6210"; qcom,pcie-parent = <&pcie0>; @@ -2933,16 +2984,10 @@ }; &gdsc_usb30 { - clock-names = "core_clk"; - clocks = <&clock_gcc clk_gcc_usb30_master_clk>; status = "ok"; }; &gdsc_pcie_0 { - clock-names = "master_bus_clk", "slave_bus_clk", "core_clk"; - clocks = <&clock_gcc clk_gcc_pcie_0_mstr_axi_clk>, - <&clock_gcc clk_gcc_pcie_0_slv_axi_clk>, - <&clock_gcc clk_gcc_pcie_0_pipe_clk>; status = "ok"; }; @@ -3000,19 +3045,14 @@ }; &gdsc_mdss { - clock-names = "bus_clk", "rot_clk"; - clocks = <&clock_mmss clk_mmss_mdss_axi_clk>, - <&clock_mmss clk_mmss_mdss_rot_clk>; proxy-supply = <&gdsc_mdss>; qcom,proxy-consumer-enable; status = "ok"; }; &gdsc_gpu_gx { - clock-names = "bimc_core_clk", "core_clk", "core_root_clk"; - clocks = <&clock_gcc clk_gcc_gpu_bimc_gfx_clk>, - <&clock_gfx clk_gpucc_gfx3d_clk>, - <&clock_gfx clk_gfx3d_clk_src>; + clock-names = "core_root_clk"; + clocks = <&clock_gfx clk_gfx3d_clk_src>; qcom,force-enable-root-clk; parent-supply = <&gfx_vreg>; status = "ok"; diff --git a/arch/arm/boot/dts/qcom/msmfalcon-pinctrl.dtsi b/arch/arm/boot/dts/qcom/msmfalcon-pinctrl.dtsi index 6a000e4d4fd0..d28d09c2a527 100644 --- a/arch/arm/boot/dts/qcom/msmfalcon-pinctrl.dtsi +++ b/arch/arm/boot/dts/qcom/msmfalcon-pinctrl.dtsi @@ -32,5 +32,21 @@ bias-disable; }; }; + + led_enable: led_enable { + mux { + pins = "gpio40"; + drive_strength = <16>; + output-high; + }; + }; + + led_disable: led_disable { + mux { + pins = "gpio40"; + drive_strength = <2>; + output-low; + }; + }; }; }; diff --git a/arch/arm/boot/dts/qcom/msmfalcon.dtsi b/arch/arm/boot/dts/qcom/msmfalcon.dtsi index 40045b522825..4765a8cb7c79 100644 --- a/arch/arm/boot/dts/qcom/msmfalcon.dtsi +++ b/arch/arm/boot/dts/qcom/msmfalcon.dtsi @@ -231,6 +231,27 @@ clock-frequency = <19200000>; }; + spmi_bus: qcom,spmi@800f000 { + compatible = "qcom,spmi-pmic-arb"; + reg = <0x800f000 0x1000>, + <0x8400000 0x1000000>, + <0x9400000 0x1000000>, + <0xa400000 0x220000>, + <0x800a000 0x3000>; + reg-names = "core", "chnls", "obsrvr", "intr", "cnfg"; + interrupt-names = "periph_irq"; + interrupts = <GIC_SPI 326 IRQ_TYPE_NONE>; + qcom,ee = <0>; + qcom,channel = <0>; + #address-cells = <2>; + #size-cells = <0>; + interrupt-controller; + #interrupt-cells = <4>; + cell-index = <0>; + qcom,not-wakeup; /* Needed until Full-boot-chain enabled */ + status = "ok"; + }; + qcom,sps { compatible = "qcom,msm_sps_4k"; qcom,pipe-attr-ee; @@ -656,3 +677,5 @@ &gdsc_gpu_cx { status = "ok"; }; +#include "msm-pmfalcon.dtsi" +#include "msm-pm2falcon.dtsi" diff --git a/arch/arm64/configs/msmcortex-perf_defconfig b/arch/arm64/configs/msmcortex-perf_defconfig index d50144eed016..50c8848bc6f9 100644 --- a/arch/arm64/configs/msmcortex-perf_defconfig +++ b/arch/arm64/configs/msmcortex-perf_defconfig @@ -273,7 +273,6 @@ 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_RMI_DEV_v21=y CONFIG_TOUCHSCREEN_SYNAPTICS_DSX_FW_UPDATE_v21=y CONFIG_INPUT_MISC=y CONFIG_INPUT_HBTP_INPUT=y diff --git a/arch/arm64/configs/msmcortex_defconfig b/arch/arm64/configs/msmcortex_defconfig index 689255d2f164..3d1a01491c0c 100644 --- a/arch/arm64/configs/msmcortex_defconfig +++ b/arch/arm64/configs/msmcortex_defconfig @@ -274,7 +274,6 @@ CONFIG_KEYBOARD_GPIO=y CONFIG_INPUT_JOYSTICK=y CONFIG_INPUT_TOUCHSCREEN=y CONFIG_TOUCHSCREEN_SYNAPTICS_DSX_CORE_v21=y -CONFIG_TOUCHSCREEN_SYNAPTICS_DSX_RMI_DEV_v21=y CONFIG_TOUCHSCREEN_SYNAPTICS_DSX_FW_UPDATE_v21=y CONFIG_INPUT_MISC=y CONFIG_INPUT_HBTP_INPUT=y diff --git a/block/blk-mq-cpumap.c b/block/blk-mq-cpumap.c index 8764c241e5bb..8cf06af3036e 100644 --- a/block/blk-mq-cpumap.c +++ b/block/blk-mq-cpumap.c @@ -31,8 +31,8 @@ static int get_first_sibling(unsigned int cpu) return cpu; } -int blk_mq_update_queue_map(unsigned int *map, unsigned int nr_queues, - const struct cpumask *online_mask) +static int blk_mq_update_queue_map(unsigned int *map, + unsigned int nr_queues, const struct cpumask *online_mask) { unsigned int i, nr_cpus, nr_uniq_cpus, queue, first_sibling; cpumask_var_t cpus; @@ -52,18 +52,14 @@ int blk_mq_update_queue_map(unsigned int *map, unsigned int nr_queues, queue = 0; for_each_possible_cpu(i) { - if (!cpumask_test_cpu(i, online_mask)) { - map[i] = 0; - continue; - } - /* * Easy case - we have equal or more hardware queues. Or * there are no thread siblings to take into account. Do * 1:1 if enough, or sequential mapping if less. */ - if (nr_queues >= nr_cpus || nr_cpus == nr_uniq_cpus) { - map[i] = cpu_to_queue_index(nr_cpus, nr_queues, queue); + if (nr_queues >= nr_cpu_ids) { + map[i] = cpu_to_queue_index(nr_cpu_ids, nr_queues, + queue); queue++; continue; } @@ -75,7 +71,7 @@ int blk_mq_update_queue_map(unsigned int *map, unsigned int nr_queues, */ first_sibling = get_first_sibling(i); if (first_sibling == i) { - map[i] = cpu_to_queue_index(nr_uniq_cpus, nr_queues, + map[i] = cpu_to_queue_index(nr_cpu_ids, nr_queues, queue); queue++; } else diff --git a/block/blk-mq.c b/block/blk-mq.c index 6d6f8feb48c0..8398e18d4139 100644 --- a/block/blk-mq.c +++ b/block/blk-mq.c @@ -1783,10 +1783,6 @@ static void blk_mq_init_cpu_queues(struct request_queue *q, INIT_LIST_HEAD(&__ctx->rq_list); __ctx->queue = q; - /* If the cpu isn't online, the cpu is mapped to first hctx */ - if (!cpu_online(i)) - continue; - hctx = q->mq_ops->map_queue(q, i); /* @@ -1820,12 +1816,9 @@ static void blk_mq_map_swqueue(struct request_queue *q, * Map software to hardware queues */ queue_for_each_ctx(q, ctx, i) { - /* If the cpu isn't online, the cpu is mapped to first hctx */ - if (!cpumask_test_cpu(i, online_mask)) - continue; - hctx = q->mq_ops->map_queue(q, i); - cpumask_set_cpu(i, hctx->cpumask); + if (cpumask_test_cpu(i, online_mask)) + cpumask_set_cpu(i, hctx->cpumask); ctx->index_hw = hctx->nr_ctx; hctx->ctxs[hctx->nr_ctx++] = ctx; } @@ -1863,17 +1856,22 @@ static void blk_mq_map_swqueue(struct request_queue *q, /* * Initialize batch roundrobin counts + * Set next_cpu for only those hctxs that have an online CPU + * in their cpumask field. For hctxs that belong to few online + * and few offline CPUs, this will always provide one CPU from + * online ones. For hctxs belonging to all offline CPUs, their + * cpumask will be updated in reinit_notify. */ - hctx->next_cpu = cpumask_first(hctx->cpumask); - hctx->next_cpu_batch = BLK_MQ_CPU_WORK_BATCH; + if (cpumask_first(hctx->cpumask) < nr_cpu_ids) { + hctx->next_cpu = cpumask_first(hctx->cpumask); + hctx->next_cpu_batch = BLK_MQ_CPU_WORK_BATCH; + } } queue_for_each_ctx(q, ctx, i) { - if (!cpumask_test_cpu(i, online_mask)) - continue; - hctx = q->mq_ops->map_queue(q, i); - cpumask_set_cpu(i, hctx->tags->cpumask); + if (cpumask_test_cpu(i, online_mask)) + cpumask_set_cpu(i, hctx->tags->cpumask); } } @@ -2101,38 +2099,13 @@ void blk_mq_free_queue(struct request_queue *q) blk_mq_free_hw_queues(q, set); } -/* Basically redo blk_mq_init_queue with queue frozen */ -static void blk_mq_queue_reinit(struct request_queue *q, - const struct cpumask *online_mask) -{ - WARN_ON_ONCE(!atomic_read(&q->mq_freeze_depth)); - - blk_mq_sysfs_unregister(q); - - blk_mq_update_queue_map(q->mq_map, q->nr_hw_queues, online_mask); - - /* - * redo blk_mq_init_cpu_queues and blk_mq_init_hw_queues. FIXME: maybe - * we should change hctx numa_node according to new topology (this - * involves free and re-allocate memory, worthy doing?) - */ - - blk_mq_map_swqueue(q, online_mask); - - blk_mq_sysfs_register(q); -} - static int blk_mq_queue_reinit_notify(struct notifier_block *nb, unsigned long action, void *hcpu) { struct request_queue *q; + struct blk_mq_hw_ctx *hctx; + int i; int cpu = (unsigned long)hcpu; - /* - * New online cpumask which is going to be set in this hotplug event. - * Declare this cpumasks as global as cpu-hotplug operation is invoked - * one-by-one and dynamically allocating this could result in a failure. - */ - static struct cpumask online_new; /* * Before hotadded cpu starts handling requests, new mappings must @@ -2154,44 +2127,31 @@ static int blk_mq_queue_reinit_notify(struct notifier_block *nb, switch (action & ~CPU_TASKS_FROZEN) { case CPU_DEAD: case CPU_UP_CANCELED: - cpumask_copy(&online_new, cpu_online_mask); + mutex_lock(&all_q_mutex); + list_for_each_entry(q, &all_q_list, all_q_node) { + queue_for_each_hw_ctx(q, hctx, i) { + cpumask_clear_cpu(cpu, hctx->cpumask); + cpumask_clear_cpu(cpu, hctx->tags->cpumask); + } + } + mutex_unlock(&all_q_mutex); break; case CPU_UP_PREPARE: - cpumask_copy(&online_new, cpu_online_mask); - cpumask_set_cpu(cpu, &online_new); + /* Update hctx->cpumask for newly onlined CPUs */ + mutex_lock(&all_q_mutex); + list_for_each_entry(q, &all_q_list, all_q_node) { + queue_for_each_hw_ctx(q, hctx, i) { + cpumask_set_cpu(cpu, hctx->cpumask); + hctx->next_cpu_batch = BLK_MQ_CPU_WORK_BATCH; + cpumask_set_cpu(cpu, hctx->tags->cpumask); + } + } + mutex_unlock(&all_q_mutex); break; default: return NOTIFY_OK; } - mutex_lock(&all_q_mutex); - - /* - * We need to freeze and reinit all existing queues. Freezing - * involves synchronous wait for an RCU grace period and doing it - * one by one may take a long time. Start freezing all queues in - * one swoop and then wait for the completions so that freezing can - * take place in parallel. - */ - list_for_each_entry(q, &all_q_list, all_q_node) - blk_mq_freeze_queue_start(q); - list_for_each_entry(q, &all_q_list, all_q_node) { - blk_mq_freeze_queue_wait(q); - - /* - * timeout handler can't touch hw queue during the - * reinitialization - */ - del_timer_sync(&q->timeout); - } - - list_for_each_entry(q, &all_q_list, all_q_node) - blk_mq_queue_reinit(q, &online_new); - - list_for_each_entry(q, &all_q_list, all_q_node) - blk_mq_unfreeze_queue(q); - - mutex_unlock(&all_q_mutex); return NOTIFY_OK; } diff --git a/block/blk-mq.h b/block/blk-mq.h index 713820b47b31..7fd11bcaa409 100644 --- a/block/blk-mq.h +++ b/block/blk-mq.h @@ -48,8 +48,6 @@ void blk_mq_disable_hotplug(void); * CPU -> queue mappings */ extern unsigned int *blk_mq_make_queue_map(struct blk_mq_tag_set *set); -extern int blk_mq_update_queue_map(unsigned int *map, unsigned int nr_queues, - const struct cpumask *online_mask); extern int blk_mq_hw_queue_to_node(unsigned int *map, unsigned int); /* diff --git a/drivers/clk/qcom/clk-rcg.h b/drivers/clk/qcom/clk-rcg.h index b904c335cda4..e3760969848d 100644 --- a/drivers/clk/qcom/clk-rcg.h +++ b/drivers/clk/qcom/clk-rcg.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2013, The Linux Foundation. All rights reserved. + * Copyright (c) 2013, 2016, 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 @@ -158,6 +158,8 @@ extern const struct clk_ops clk_dyn_rcg_ops; * @freq_tbl: frequency table * @current_freq: last cached frequency when using branches with shared RCGs * @clkr: regmap clock handle + * @flags: set if RCG needs to be force enabled/disabled during + * power sequence. * */ struct clk_rcg2 { @@ -168,6 +170,9 @@ struct clk_rcg2 { const struct freq_tbl *freq_tbl; unsigned long current_freq; struct clk_regmap clkr; + +#define FORCE_ENABLE_RCGR BIT(0) + u8 flags; }; #define to_clk_rcg2(_hw) container_of(to_clk_regmap(_hw), struct clk_rcg2, clkr) diff --git a/drivers/clk/qcom/clk-rcg2.c b/drivers/clk/qcom/clk-rcg2.c index a071bba8018c..4d5081c2b6d1 100644 --- a/drivers/clk/qcom/clk-rcg2.c +++ b/drivers/clk/qcom/clk-rcg2.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2013, The Linux Foundation. All rights reserved. + * Copyright (c) 2013, 2016, 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 @@ -60,6 +60,57 @@ static int clk_rcg2_is_enabled(struct clk_hw *hw) return (cmd & CMD_ROOT_OFF) == 0; } +static int clk_rcg_set_force_enable(struct clk_hw *hw) +{ + struct clk_rcg2 *rcg = to_clk_rcg2(hw); + const char *name = clk_hw_get_name(hw); + int ret = 0, count; + + /* force enable RCG */ + ret = regmap_update_bits(rcg->clkr.regmap, rcg->cmd_rcgr + CMD_REG, + CMD_ROOT_EN, CMD_ROOT_EN); + if (ret) + return ret; + + /* wait for RCG to turn ON */ + for (count = 500; count > 0; count--) { + ret = clk_rcg2_is_enabled(hw); + if (ret) { + ret = 0; + break; + } + udelay(1); + } + if (!count) + pr_err("%s: RCG did not turn on after force enable\n", name); + + return ret; +} + +static int clk_rcg2_enable(struct clk_hw *hw) +{ + int ret = 0; + struct clk_rcg2 *rcg = to_clk_rcg2(hw); + + if (rcg->flags & FORCE_ENABLE_RCGR) + ret = clk_rcg_set_force_enable(hw); + + return ret; +} + +static void clk_rcg2_disable(struct clk_hw *hw) +{ + struct clk_rcg2 *rcg = to_clk_rcg2(hw); + + if (rcg->flags & FORCE_ENABLE_RCGR) { + /* force disable RCG - clear CMD_ROOT_EN bit */ + regmap_update_bits(rcg->clkr.regmap, + rcg->cmd_rcgr + CMD_REG, CMD_ROOT_EN, 0); + /* Add a delay to disable the RCG */ + udelay(100); + } +} + static u8 clk_rcg2_get_parent(struct clk_hw *hw) { struct clk_rcg2 *rcg = to_clk_rcg2(hw); @@ -290,6 +341,8 @@ static int clk_rcg2_set_rate_and_parent(struct clk_hw *hw, } const struct clk_ops clk_rcg2_ops = { + .enable = clk_rcg2_enable, + .disable = clk_rcg2_disable, .is_enabled = clk_rcg2_is_enabled, .get_parent = clk_rcg2_get_parent, .set_parent = clk_rcg2_set_parent, @@ -801,6 +854,8 @@ static int clk_gfx3d_set_rate(struct clk_hw *hw, unsigned long rate, } const struct clk_ops clk_gfx3d_ops = { + .enable = clk_rcg2_enable, + .disable = clk_rcg2_disable, .is_enabled = clk_rcg2_is_enabled, .get_parent = clk_rcg2_get_parent, .set_parent = clk_rcg2_set_parent, diff --git a/drivers/hid/hid-apple.c b/drivers/hid/hid-apple.c index 884d82f9190e..37e8b61b5c98 100644 --- a/drivers/hid/hid-apple.c +++ b/drivers/hid/hid-apple.c @@ -440,6 +440,9 @@ static const struct hid_device_id apple_devices[] = { .driver_data = APPLE_HAS_FN }, { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_ALU_ANSI), .driver_data = APPLE_HAS_FN }, + { HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_APPLE, + USB_DEVICE_ID_APPLE_ALU_ANSI), + .driver_data = APPLE_HAS_FN }, { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_ALU_ISO), .driver_data = APPLE_HAS_FN | APPLE_ISO_KEYBOARD }, { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_ALU_JIS), diff --git a/drivers/hid/hid-core.c b/drivers/hid/hid-core.c index ec791e169f8f..9dc9f93f4e36 100644 --- a/drivers/hid/hid-core.c +++ b/drivers/hid/hid-core.c @@ -1754,6 +1754,8 @@ static const struct hid_device_id hid_have_special_driver[] = { { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_ALU_MINI_ISO) }, { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_ALU_MINI_JIS) }, { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_ALU_ANSI) }, + { HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_APPLE, + USB_DEVICE_ID_APPLE_ALU_ANSI) }, { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_ALU_ISO) }, { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_ALU_JIS) }, { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_GEYSER4_HF_ANSI) }, diff --git a/drivers/input/touchscreen/synaptics_dsx/synaptics_dsx_core.c b/drivers/input/touchscreen/synaptics_dsx/synaptics_dsx_core.c index e8229216fcd3..206941708141 100644 --- a/drivers/input/touchscreen/synaptics_dsx/synaptics_dsx_core.c +++ b/drivers/input/touchscreen/synaptics_dsx/synaptics_dsx_core.c @@ -492,33 +492,25 @@ static int synaptics_i2c_change_pipe_owner( static void synaptics_secure_touch_init(struct synaptics_rmi4_data *data) { - int ret = 0; data->st_initialized = 0; init_completion(&data->st_powerdown); init_completion(&data->st_irq_processed); /* Get clocks */ data->core_clk = clk_get(data->pdev->dev.parent, "core_clk"); if (IS_ERR(data->core_clk)) { - ret = PTR_ERR(data->core_clk); - dev_err(data->pdev->dev.parent, - "%s: error on clk_get(core_clk):%d\n", __func__, ret); - return; + data->core_clk = NULL; + dev_warn(data->pdev->dev.parent, + "%s: core_clk is not defined\n", __func__); } data->iface_clk = clk_get(data->pdev->dev.parent, "iface_clk"); if (IS_ERR(data->iface_clk)) { - ret = PTR_ERR(data->iface_clk); - dev_err(data->pdev->dev.parent, - "%s: error on clk_get(iface_clk):%d\n", __func__, ret); - goto err_iface_clk; + data->iface_clk = NULL; + dev_warn(data->pdev->dev.parent, + "%s: iface_clk is not defined\n", __func__); } data->st_initialized = 1; - return; - -err_iface_clk: - clk_put(data->core_clk); - data->core_clk = NULL; } static void synaptics_secure_touch_notify(struct synaptics_rmi4_data *rmi4_data) { diff --git a/drivers/media/platform/msm/vidc/msm_vidc_common.c b/drivers/media/platform/msm/vidc/msm_vidc_common.c index f0a3875a8f28..40643239712f 100644 --- a/drivers/media/platform/msm/vidc/msm_vidc_common.c +++ b/drivers/media/platform/msm/vidc/msm_vidc_common.c @@ -1737,19 +1737,6 @@ static struct vb2_buffer *get_vb_from_device_addr(struct buf_queue *bufq, return vb; } -static void msm_vidc_try_suspend(struct msm_vidc_inst *inst) -{ - bool batch_mode; - - batch_mode = msm_comm_g_ctrl_for_id(inst, V4L2_CID_VIDC_QBUF_MODE) - == V4L2_VIDC_QBUF_BATCHED; - if (batch_mode) { - dprintk(VIDC_DBG, - "Trying to suspend Venus after finishing Batch\n"); - msm_comm_suspend(inst->core->id); - } -} - static void handle_ebd(enum hal_command_response cmd, void *data) { struct msm_vidc_cb_data_done *response = data; @@ -1821,8 +1808,6 @@ static void handle_ebd(enum hal_command_response cmd, void *data) msm_vidc_debugfs_update(inst, MSM_VIDC_DEBUGFS_EVENT_EBD); } - msm_vidc_try_suspend(inst); - put_inst(inst); } @@ -2121,7 +2106,6 @@ static void handle_fbd(enum hal_command_response cmd, void *data) msm_vidc_debugfs_update(inst, MSM_VIDC_DEBUGFS_EVENT_FBD); } - msm_vidc_try_suspend(inst); err_handle_fbd: put_inst(inst); } diff --git a/drivers/soc/qcom/qdsp6v2/apr.c b/drivers/soc/qcom/qdsp6v2/apr.c index 5517f20f310c..ee9b054dcc24 100644 --- a/drivers/soc/qcom/qdsp6v2/apr.c +++ b/drivers/soc/qcom/qdsp6v2/apr.c @@ -304,6 +304,7 @@ int apr_send_pkt(void *handle, uint32_t *buf) uint16_t dest_id; uint16_t client_id; uint16_t w_len; + int rc; unsigned long flags; if (!handle || !buf) { @@ -345,14 +346,23 @@ int apr_send_pkt(void *handle, uint32_t *buf) APR_PKT_INFO("Tx: dest_svc[%d], opcode[0x%X], size[%d]", hdr->dest_svc, hdr->opcode, hdr->pkt_size); - w_len = apr_tal_write(clnt->handle, buf, + rc = apr_tal_write(clnt->handle, buf, (struct apr_pkt_priv *)&svc->pkt_owner, hdr->pkt_size); - if (w_len != hdr->pkt_size) - pr_err("Unable to write APR pkt successfully: %d\n", w_len); + if (rc >= 0) { + w_len = rc; + if (w_len != hdr->pkt_size) { + pr_err("%s: Unable to write whole APR pkt successfully: %d\n", + __func__, rc); + rc = -EINVAL; + } + } else { + pr_err("%s: Write APR pkt failed with error %d\n", + __func__, rc); + } spin_unlock_irqrestore(&svc->w_lock, flags); - return w_len; + return rc; } int apr_pkt_config(void *handle, struct apr_pkt_cfg *cfg) diff --git a/include/linux/sched/sysctl.h b/include/linux/sched/sysctl.h index 1f9c2c734b20..861f715a673d 100644 --- a/include/linux/sched/sysctl.h +++ b/include/linux/sched/sysctl.h @@ -64,6 +64,7 @@ extern unsigned int sysctl_sched_pred_alert_freq; extern unsigned int sysctl_sched_freq_aggregate; extern unsigned int sysctl_sched_enable_thread_grouping; extern unsigned int sysctl_sched_freq_aggregate_threshold_pct; +extern unsigned int sysctl_sched_prefer_sync_wakee_to_waker; #else /* CONFIG_SCHED_HMP */ diff --git a/include/sound/apr_audio-v2.h b/include/sound/apr_audio-v2.h index e1bdca690cc9..1a58a146c3b0 100644 --- a/include/sound/apr_audio-v2.h +++ b/include/sound/apr_audio-v2.h @@ -2943,7 +2943,7 @@ struct asm_aac_enc_cfg_v2_t { * number of channels at the input. * The number of channels must not change during encoding. */ - uint32_t channel_cfg; + uint16_t channel_cfg; /* * Number of samples per second. diff --git a/include/sound/q6asm-v2.h b/include/sound/q6asm-v2.h index 8525f2e7f738..00129eb08888 100644 --- a/include/sound/q6asm-v2.h +++ b/include/sound/q6asm-v2.h @@ -339,6 +339,8 @@ int q6asm_stream_cmd_nowait(struct audio_client *ac, int cmd, void *q6asm_is_cpu_buf_avail(int dir, struct audio_client *ac, uint32_t *size, uint32_t *idx); +int q6asm_cpu_buf_release(int dir, struct audio_client *ac); + void *q6asm_is_cpu_buf_avail_nolock(int dir, struct audio_client *ac, uint32_t *size, uint32_t *idx); diff --git a/kernel/sched/core.c b/kernel/sched/core.c index b146739f8d55..612cda15a8b0 100644 --- a/kernel/sched/core.c +++ b/kernel/sched/core.c @@ -7855,9 +7855,7 @@ void __init sched_init(void) BUG_ON(num_possible_cpus() > BITS_PER_LONG); -#ifdef CONFIG_SCHED_HMP init_clusters(); -#endif #ifdef CONFIG_FAIR_GROUP_SCHED alloc_size += 2 * nr_cpu_ids * sizeof(void **); diff --git a/kernel/sched/fair.c b/kernel/sched/fair.c index 14b8977d1be4..4489bec5d68a 100644 --- a/kernel/sched/fair.c +++ b/kernel/sched/fair.c @@ -2590,6 +2590,7 @@ static u32 __compute_runnable_contrib(u64 n) #define SBC_FLAG_COST_CSTATE_PREV_CPU_TIE_BREAKER 0x80 #define SBC_FLAG_CSTATE_LOAD 0x100 #define SBC_FLAG_BEST_SIBLING 0x200 +#define SBC_FLAG_WAKER_CPU 0x400 /* Cluster selection flag */ #define SBC_FLAG_COLOC_CLUSTER 0x10000 @@ -3060,6 +3061,15 @@ wake_to_waker_cluster(struct cpu_select_env *env) task_load(env->p) < sched_small_wakee_task_load; } +static inline bool +bias_to_waker_cpu(struct task_struct *p, int cpu) +{ + return sysctl_sched_prefer_sync_wakee_to_waker && + cpu_rq(cpu)->nr_running == 1 && + cpumask_test_cpu(cpu, tsk_cpus_allowed(p)) && + cpu_active(cpu) && !cpu_isolated(cpu); +} + static inline int cluster_allowed(struct task_struct *p, struct sched_cluster *cluster) { @@ -3080,6 +3090,7 @@ static int select_best_cpu(struct task_struct *p, int target, int reason, struct cluster_cpu_stats stats; struct related_thread_group *grp; unsigned int sbc_flag = 0; + int cpu = raw_smp_processor_id(); struct cpu_select_env env = { .p = p, @@ -3111,14 +3122,20 @@ static int select_best_cpu(struct task_struct *p, int target, int reason, else env.rtg = grp; } else { - cluster = cpu_rq(smp_processor_id())->cluster; - if (wake_to_waker_cluster(&env) && - cluster_allowed(p, cluster)) { - env.need_waker_cluster = 1; - bitmap_zero(env.candidate_list, NR_CPUS); - __set_bit(cluster->id, env.candidate_list); - env.sbc_best_cluster_flag = SBC_FLAG_WAKER_CLUSTER; - + cluster = cpu_rq(cpu)->cluster; + if (wake_to_waker_cluster(&env)) { + if (bias_to_waker_cpu(p, cpu)) { + target = cpu; + sbc_flag = SBC_FLAG_WAKER_CLUSTER | + SBC_FLAG_WAKER_CPU; + goto out; + } else if (cluster_allowed(p, cluster)) { + env.need_waker_cluster = 1; + bitmap_zero(env.candidate_list, NR_CPUS); + __set_bit(cluster->id, env.candidate_list); + env.sbc_best_cluster_flag = + SBC_FLAG_WAKER_CLUSTER; + } } else if (bias_to_prev_cpu(&env, &stats)) { sbc_flag = SBC_FLAG_PREV_CPU; goto out; diff --git a/kernel/sched/hmp.c b/kernel/sched/hmp.c index 3bbf3ee46cf9..61e352aeec00 100644 --- a/kernel/sched/hmp.c +++ b/kernel/sched/hmp.c @@ -897,6 +897,13 @@ unsigned int __read_mostly sched_spill_load; unsigned int __read_mostly sysctl_sched_spill_load_pct = 100; /* + * Prefer the waker CPU for sync wakee task, if the CPU has only 1 runnable + * task. This eliminates the LPM exit latency associated with the idle + * CPUs in the waker cluster. + */ +unsigned int __read_mostly sysctl_sched_prefer_sync_wakee_to_waker; + +/* * Tasks whose bandwidth consumption on a cpu is more than * sched_upmigrate are considered "big" tasks. Big tasks will be * considered for "up" migration, i.e migrating to a cpu with better diff --git a/kernel/sched/sched.h b/kernel/sched/sched.h index 038d79dda2f2..1b641e60233e 100644 --- a/kernel/sched/sched.h +++ b/kernel/sched/sched.h @@ -1426,6 +1426,7 @@ static inline void clear_hmp_request(int cpu) { } static inline void mark_task_starting(struct task_struct *p) { } static inline void set_window_start(struct rq *rq) { } static inline void migrate_sync_cpu(int cpu, int new_cpu) {} +static inline void init_clusters(void) {} static inline void update_cluster_topology(void) { } static inline void set_task_last_wake(struct task_struct *p, u64 wallclock) { } static inline void set_task_last_switch_out(struct task_struct *p, diff --git a/kernel/sysctl.c b/kernel/sysctl.c index dad3324e7372..cdce7d0f5a0e 100644 --- a/kernel/sysctl.c +++ b/kernel/sysctl.c @@ -422,6 +422,15 @@ static struct ctl_table kern_table[] = { .extra2 = &one_hundred, }, { + .procname = "sched_prefer_sync_wakee_to_waker", + .data = &sysctl_sched_prefer_sync_wakee_to_waker, + .maxlen = sizeof(unsigned int), + .mode = 0644, + .proc_handler = proc_dointvec_minmax, + .extra1 = &zero, + .extra2 = &one, + }, + { .procname = "sched_enable_thread_grouping", .data = &sysctl_sched_enable_thread_grouping, .maxlen = sizeof(unsigned int), diff --git a/kernel/time/hrtimer.c b/kernel/time/hrtimer.c index 1b0117198a08..9e1349fc5bbe 100644 --- a/kernel/time/hrtimer.c +++ b/kernel/time/hrtimer.c @@ -1625,20 +1625,36 @@ static void init_hrtimers_cpu(int cpu) } #if defined(CONFIG_HOTPLUG_CPU) -static void migrate_hrtimer_list(struct hrtimer_clock_base *old_base, - struct hrtimer_clock_base *new_base, +static void migrate_hrtimer_list(struct hrtimer_cpu_base *old_base, + struct hrtimer_cpu_base *new_base, + unsigned int i, + bool wait, bool remove_pinned) { struct hrtimer *timer; struct timerqueue_node *node; struct timerqueue_head pinned; int is_pinned; + struct hrtimer_clock_base *old_c_base = &old_base->clock_base[i]; + struct hrtimer_clock_base *new_c_base = &new_base->clock_base[i]; timerqueue_init_head(&pinned); - while ((node = timerqueue_getnext(&old_base->active))) { + while ((node = timerqueue_getnext(&old_c_base->active))) { timer = container_of(node, struct hrtimer, node); - BUG_ON(hrtimer_callback_running(timer)); + if (wait) { + /* Ensure timers are done running before continuing */ + while (hrtimer_callback_running(timer)) { + raw_spin_unlock(&old_base->lock); + raw_spin_unlock(&new_base->lock); + cpu_relax(); + raw_spin_lock(&new_base->lock); + raw_spin_lock_nested(&old_base->lock, + SINGLE_DEPTH_NESTING); + } + } else { + BUG_ON(hrtimer_callback_running(timer)); + } debug_deactivate(timer); /* @@ -1646,7 +1662,7 @@ static void migrate_hrtimer_list(struct hrtimer_clock_base *old_base, * timer could be seen as !active and just vanish away * under us on another CPU */ - __remove_hrtimer(timer, old_base, HRTIMER_STATE_ENQUEUED, 0); + __remove_hrtimer(timer, old_c_base, HRTIMER_STATE_ENQUEUED, 0); is_pinned = timer->state & HRTIMER_STATE_PINNED; if (!remove_pinned && is_pinned) { @@ -1654,7 +1670,7 @@ static void migrate_hrtimer_list(struct hrtimer_clock_base *old_base, continue; } - timer->base = new_base; + timer->base = new_c_base; /* * Enqueue the timers on the new cpu. This does not * reprogram the event device in case the timer @@ -1663,7 +1679,7 @@ static void migrate_hrtimer_list(struct hrtimer_clock_base *old_base, * sort out already expired timers and reprogram the * event device. */ - enqueue_hrtimer(timer, new_base); + enqueue_hrtimer(timer, new_c_base); } /* Re-queue pinned timers for non-hotplug usecase */ @@ -1671,11 +1687,11 @@ static void migrate_hrtimer_list(struct hrtimer_clock_base *old_base, timer = container_of(node, struct hrtimer, node); timerqueue_del(&pinned, &timer->node); - enqueue_hrtimer(timer, old_base); + enqueue_hrtimer(timer, old_c_base); } } -static void __migrate_hrtimers(int scpu, bool remove_pinned) +static void __migrate_hrtimers(int scpu, bool wait, bool remove_pinned) { struct hrtimer_cpu_base *old_base, *new_base; unsigned long flags; @@ -1692,8 +1708,8 @@ static void __migrate_hrtimers(int scpu, bool remove_pinned) raw_spin_lock_nested(&old_base->lock, SINGLE_DEPTH_NESTING); for (i = 0; i < HRTIMER_MAX_CLOCK_BASES; i++) { - migrate_hrtimer_list(&old_base->clock_base[i], - &new_base->clock_base[i], remove_pinned); + migrate_hrtimer_list(old_base, new_base, i, wait, + remove_pinned); } raw_spin_unlock(&old_base->lock); @@ -1709,12 +1725,12 @@ static void migrate_hrtimers(int scpu) BUG_ON(cpu_online(scpu)); tick_cancel_sched_timer(scpu); - __migrate_hrtimers(scpu, true); + __migrate_hrtimers(scpu, false, true); } void hrtimer_quiesce_cpu(void *cpup) { - __migrate_hrtimers(*(int *)cpup, false); + __migrate_hrtimers(*(int *)cpup, true, false); } #endif /* CONFIG_HOTPLUG_CPU */ diff --git a/sound/soc/msm/qdsp6v2/msm-pcm-q6-v2.c b/sound/soc/msm/qdsp6v2/msm-pcm-q6-v2.c index 4e3745d4d976..4e93780c4da0 100644 --- a/sound/soc/msm/qdsp6v2/msm-pcm-q6-v2.c +++ b/sound/soc/msm/qdsp6v2/msm-pcm-q6-v2.c @@ -57,6 +57,7 @@ struct snd_msm { #define CMD_EOS_MIN_TIMEOUT_LENGTH 50 #define CMD_EOS_TIMEOUT_MULTIPLIER (HZ * 50) +#define MAX_PB_COPY_RETRIES 3 static struct snd_pcm_hardware msm_pcm_hardware_capture = { .info = (SNDRV_PCM_INFO_MMAP | @@ -629,6 +630,7 @@ static int msm_pcm_playback_copy(struct snd_pcm_substream *substream, int a, void *data = NULL; uint32_t idx = 0; uint32_t size = 0; + uint32_t retries = 0; struct snd_pcm_runtime *runtime = substream->runtime; struct msm_audio *prtd = runtime->private_data; @@ -637,7 +639,7 @@ static int msm_pcm_playback_copy(struct snd_pcm_substream *substream, int a, pr_debug("%s: prtd->out_count = %d\n", __func__, atomic_read(&prtd->out_count)); - while (fbytes > 0) { + while ((fbytes > 0) && (retries < MAX_PB_COPY_RETRIES)) { if (prtd->reset_event) { pr_err("%s: In SSR return ENETRESET before wait\n", __func__); @@ -666,6 +668,13 @@ static int msm_pcm_playback_copy(struct snd_pcm_substream *substream, int a, data = q6asm_is_cpu_buf_avail(IN, prtd->audio_client, &size, &idx); + if (data == NULL) { + retries++; + continue; + } else { + retries = 0; + } + if (fbytes > size) xfer = size; else @@ -677,6 +686,9 @@ static int msm_pcm_playback_copy(struct snd_pcm_substream *substream, int a, __func__, fbytes, xfer, size); if (copy_from_user(bufptr, buf, xfer)) { ret = -EFAULT; + pr_err("%s: copy_from_user failed\n", + __func__); + q6asm_cpu_buf_release(IN, prtd->audio_client); goto fail; } buf += xfer; @@ -690,6 +702,8 @@ static int msm_pcm_playback_copy(struct snd_pcm_substream *substream, int a, 0, 0, NO_TIMESTAMP); if (ret < 0) { ret = -EFAULT; + q6asm_cpu_buf_release(IN, + prtd->audio_client); goto fail; } } else @@ -698,6 +712,9 @@ static int msm_pcm_playback_copy(struct snd_pcm_substream *substream, int a, } } fail: + if (retries >= MAX_PB_COPY_RETRIES) + ret = -ENOMEM; + return ret; } @@ -802,6 +819,7 @@ static int msm_pcm_capture_copy(struct snd_pcm_substream *substream, if (copy_to_user(buf, bufptr+offset, xfer)) { pr_err("Failed to copy buf to user\n"); ret = -EFAULT; + q6asm_cpu_buf_release(OUT, prtd->audio_client); goto fail; } fbytes -= xfer; @@ -817,6 +835,7 @@ static int msm_pcm_capture_copy(struct snd_pcm_substream *substream, if (ret < 0) { pr_err("q6asm read failed\n"); ret = -EFAULT; + q6asm_cpu_buf_release(OUT, prtd->audio_client); goto fail; } } else diff --git a/sound/soc/msm/qdsp6v2/msm-pcm-routing-v2.c b/sound/soc/msm/qdsp6v2/msm-pcm-routing-v2.c index 3eb540cf6a98..5c40c55a4a0c 100644 --- a/sound/soc/msm/qdsp6v2/msm-pcm-routing-v2.c +++ b/sound/soc/msm/qdsp6v2/msm-pcm-routing-v2.c @@ -8907,6 +8907,7 @@ static const struct snd_soc_dapm_route intercon[] = { {"MultiMedia5 Mixer", "MI2S_TX", "MI2S_TX"}, {"MultiMedia1 Mixer", "QUAT_MI2S_TX", "QUAT_MI2S_TX"}, {"MultiMedia2 Mixer", "QUAT_MI2S_TX", "QUAT_MI2S_TX"}, + {"MultiMedia6 Mixer", "QUAT_MI2S_TX", "QUAT_MI2S_TX"}, {"MultiMedia1 Mixer", "QUIN_MI2S_TX", "QUIN_MI2S_TX"}, {"MultiMedia2 Mixer", "QUIN_MI2S_TX", "QUIN_MI2S_TX"}, {"MultiMedia1 Mixer", "TERT_MI2S_TX", "TERT_MI2S_TX"}, diff --git a/sound/soc/msm/qdsp6v2/q6asm.c b/sound/soc/msm/qdsp6v2/q6asm.c index 206fbec249fa..b4257f990aa5 100644 --- a/sound/soc/msm/qdsp6v2/q6asm.c +++ b/sound/soc/msm/qdsp6v2/q6asm.c @@ -1996,6 +1996,40 @@ void *q6asm_is_cpu_buf_avail(int dir, struct audio_client *ac, uint32_t *size, return NULL; } +int q6asm_cpu_buf_release(int dir, struct audio_client *ac) +{ + struct audio_port_data *port; + int ret = 0; + int idx; + + if (!ac || ((dir != IN) && (dir != OUT))) { + pr_err("%s: ac %pK dir %d\n", __func__, ac, dir); + ret = -EINVAL; + goto exit; + } + + if (ac->io_mode & SYNC_IO_MODE) { + port = &ac->port[dir]; + mutex_lock(&port->lock); + idx = port->cpu_buf; + if (port->cpu_buf == 0) { + port->cpu_buf = port->max_buf_cnt - 1; + } else if (port->cpu_buf < port->max_buf_cnt) { + port->cpu_buf = port->cpu_buf - 1; + } else { + pr_err("%s: buffer index(%d) out of range\n", + __func__, port->cpu_buf); + ret = -EINVAL; + mutex_unlock(&port->lock); + goto exit; + } + port->buf[port->cpu_buf].used = dir ^ 1; + mutex_unlock(&port->lock); + } +exit: + return ret; +} + void *q6asm_is_cpu_buf_avail_nolock(int dir, struct audio_client *ac, uint32_t *size, uint32_t *index) { |
