summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--Documentation/devicetree/bindings/arm/msm/wil6210.txt3
-rw-r--r--Documentation/devicetree/bindings/clock/sunxi.txt2
-rw-r--r--Documentation/devicetree/bindings/net/neutrino_avb.txt6
-rw-r--r--Documentation/devicetree/bindings/power/supply/qcom/qpnp-smb2.txt6
-rw-r--r--Documentation/devicetree/bindings/soc/qcom/qpnp-haptic.txt4
-rw-r--r--Documentation/devicetree/bindings/sound/qcom-audio-dev.txt27
-rw-r--r--Documentation/devicetree/bindings/usb/msm-phy.txt2
-rw-r--r--Makefile2
-rw-r--r--android/configs/android-base.cfg3
-rw-r--r--arch/arc/include/asm/entry-arcv2.h2
-rw-r--r--arch/arc/include/asm/ptrace.h2
-rw-r--r--arch/arm/boot/dts/qcom/Makefile2
-rw-r--r--arch/arm/boot/dts/qcom/apq8096-auto-dragonboard.dtsi13
-rw-r--r--arch/arm/boot/dts/qcom/apq8098-v2.1-mediabox.dts1
-rw-r--r--arch/arm/boot/dts/qcom/msm-audio-lpass.dtsi88
-rw-r--r--arch/arm/boot/dts/qcom/msm-audio.dtsi88
-rw-r--r--arch/arm/boot/dts/qcom/msm-pm660.dtsi1
-rw-r--r--arch/arm/boot/dts/qcom/msm-pm660l.dtsi3
-rw-r--r--arch/arm/boot/dts/qcom/msm-pmi8998.dtsi3
-rw-r--r--arch/arm/boot/dts/qcom/msm8996-agave-adp.dtsi13
-rw-r--r--arch/arm/boot/dts/qcom/msm8996-auto-cdp.dtsi23
-rw-r--r--arch/arm/boot/dts/qcom/msm8996-mmxf-adp.dtsi13
-rw-r--r--arch/arm/boot/dts/qcom/msm8996-regulator.dtsi19
-rw-r--r--arch/arm/boot/dts/qcom/msm8996.dtsi151
-rw-r--r--arch/arm/boot/dts/qcom/msm8996pro.dtsi57
-rw-r--r--arch/arm/boot/dts/qcom/msm8998-camera-sensor-mtp.dtsi54
-rw-r--r--arch/arm/boot/dts/qcom/msm8998-interposer-camera-sensor-mtp.dtsi12
-rw-r--r--arch/arm/boot/dts/qcom/msm8998-interposer-camera-sensor-qrd.dtsi12
-rw-r--r--arch/arm/boot/dts/qcom/msm8998-pinctrl.dtsi71
-rw-r--r--arch/arm/boot/dts/qcom/msm8998.dtsi4
-rw-r--r--arch/arm/boot/dts/qcom/sda660-pm660a-qrd-hdk.dts137
-rw-r--r--arch/arm/boot/dts/qcom/sdm630-mdss.dtsi5
-rw-r--r--arch/arm/boot/dts/qcom/sdm630-qrd.dtsi14
-rw-r--r--arch/arm/boot/dts/qcom/sdm630.dtsi2
-rw-r--r--arch/arm/boot/dts/qcom/sdm660-camera-sensor-mtp.dtsi206
-rw-r--r--arch/arm/boot/dts/qcom/sdm660-camera.dtsi32
-rw-r--r--arch/arm/boot/dts/qcom/sdm660-mdss.dtsi5
-rw-r--r--arch/arm/boot/dts/qcom/sdm660-pinctrl.dtsi70
-rw-r--r--arch/arm/boot/dts/qcom/sdm660-qrd.dtsi16
-rw-r--r--arch/arm/boot/dts/qcom/vplatform-lfv-ion.dtsi31
-rw-r--r--arch/arm/boot/dts/qcom/vplatform-lfv-msm8996.dts487
-rw-r--r--arch/arm/configs/msmcortex_defconfig3
-rw-r--r--arch/arm/configs/sdm660-perf_defconfig1
-rw-r--r--arch/arm/configs/sdm660_defconfig1
-rw-r--r--arch/arm/mach-omap2/timer.c7
-rw-r--r--arch/arm/mm/dma-mapping.c2
-rw-r--r--arch/arm64/Kconfig.debug2
-rw-r--r--arch/arm64/configs/msm-auto-perf_defconfig46
-rw-r--r--arch/arm64/configs/msm-auto_defconfig4
-rw-r--r--arch/arm64/configs/msm-perf_defconfig1
-rw-r--r--arch/arm64/configs/msm_defconfig2
-rw-r--r--arch/arm64/configs/msmcortex-perf_defconfig3
-rw-r--r--arch/arm64/configs/msmcortex_defconfig3
-rw-r--r--arch/arm64/configs/msmcortex_mediabox-perf_defconfig641
-rw-r--r--arch/arm64/configs/msmcortex_mediabox_defconfig1
-rw-r--r--arch/arm64/configs/sdm660-perf_defconfig2
-rw-r--r--arch/arm64/configs/sdm660_defconfig1
-rw-r--r--arch/arm64/include/asm/exec.h3
-rw-r--r--arch/arm64/kernel/process.c3
-rw-r--r--arch/arm64/kernel/suspend.c2
-rw-r--r--arch/mips/kernel/crash.c16
-rw-r--r--arch/mips/kernel/elf.c2
-rw-r--r--arch/mips/kernel/kgdb.c48
-rw-r--r--arch/sparc/include/asm/pgtable_64.h15
-rw-r--r--arch/sparc/mm/init_64.c2
-rw-r--r--arch/x86/kernel/ftrace.c12
-rw-r--r--arch/x86/xen/time.c6
-rw-r--r--crypto/testmgr.c5
-rw-r--r--drivers/block/drbd/drbd_bitmap.c6
-rw-r--r--drivers/bluetooth/bluetooth-power.c1
-rw-r--r--drivers/bluetooth/btfm_slim.h2
-rw-r--r--drivers/bluetooth/btfm_slim_codec.c3
-rw-r--r--drivers/bluetooth/btfm_slim_wcn3990.c31
-rw-r--r--drivers/char/adsprpc.c34
-rw-r--r--drivers/char/diag/diag_masks.c65
-rw-r--r--drivers/char/diag/diag_memorydevice.c57
-rw-r--r--drivers/char/diag/diag_mux.c5
-rw-r--r--drivers/char/diag/diagchar.h2
-rw-r--r--drivers/char/diag/diagchar_core.c3
-rw-r--r--drivers/char/diag/diagfwd_cntl.c11
-rw-r--r--drivers/clk/clk.c18
-rw-r--r--drivers/clk/sunxi/clk-simple-gates.c2
-rw-r--r--drivers/crypto/msm/ota_crypto.c3
-rw-r--r--drivers/devfreq/governor_bw_hwmon.c6
-rw-r--r--drivers/gpu/drm/amd/amdgpu/kv_dpm.c2
-rw-r--r--drivers/gpu/drm/msm/adreno/a5xx_gpu.c31
-rw-r--r--drivers/gpu/drm/msm/adreno/adreno_gpu.c19
-rw-r--r--drivers/gpu/drm/msm/adreno/adreno_gpu.h2
-rw-r--r--drivers/gpu/drm/msm/hdmi-staging/sde_hdmi.c51
-rw-r--r--drivers/gpu/drm/msm/hdmi-staging/sde_hdmi.h9
-rw-r--r--drivers/gpu/drm/msm/hdmi-staging/sde_hdmi_bridge.c41
-rw-r--r--drivers/gpu/drm/msm/msm_drv.c30
-rw-r--r--drivers/gpu/drm/msm/msm_drv.h2
-rw-r--r--drivers/gpu/drm/msm/msm_gem.c60
-rw-r--r--drivers/gpu/drm/msm/msm_gem.h2
-rw-r--r--drivers/gpu/drm/msm/msm_gem_prime.c12
-rw-r--r--drivers/gpu/drm/msm/msm_gem_submit.c57
-rw-r--r--drivers/gpu/drm/msm/msm_gpu.c81
-rw-r--r--drivers/gpu/drm/msm/msm_gpu.h5
-rw-r--r--drivers/gpu/drm/msm/msm_snapshot.h4
-rw-r--r--drivers/gpu/drm/msm/sde/sde_crtc.c8
-rw-r--r--drivers/gpu/drm/msm/sde/sde_rm.c26
-rw-r--r--drivers/gpu/msm/kgsl.c35
-rw-r--r--drivers/infiniband/hw/qib/qib_qp.c18
-rw-r--r--drivers/input/misc/hbtp_input.c5
-rw-r--r--drivers/input/misc/vl53L0/stmvl53l0_module-cci.c20
-rw-r--r--drivers/input/misc/vl53L0/stmvl53l0_module.c28
-rw-r--r--drivers/input/serio/i8042-x86ia64io.h7
-rw-r--r--drivers/input/touchscreen/st/fts.c2
-rw-r--r--drivers/input/touchscreen/st/fts_lib/ftsFlash.c2
-rw-r--r--drivers/input/touchscreen/st/fts_lib/ftsGesture.c12
-rw-r--r--drivers/input/touchscreen/st/fts_lib/ftsTest.c12
-rw-r--r--drivers/md/dm-ioctl.c2
-rw-r--r--drivers/md/raid1.c2
-rw-r--r--drivers/media/dvb-core/dmxdev.c8
-rw-r--r--drivers/media/platform/msm/broadcast/tspp.c8
-rw-r--r--drivers/media/platform/msm/camera_v2/isp/msm_isp.h4
-rw-r--r--drivers/media/platform/msm/camera_v2/isp/msm_isp47.c6
-rw-r--r--drivers/media/platform/msm/camera_v2/isp/msm_isp_axi_util.c136
-rw-r--r--drivers/media/platform/msm/camera_v2/isp/msm_isp_stats_util.c8
-rw-r--r--drivers/media/platform/msm/camera_v2/isp/msm_isp_util.c7
-rw-r--r--drivers/media/platform/msm/camera_v2/msm_buf_mgr/msm_generic_buf_mgr.c21
-rw-r--r--drivers/media/platform/msm/camera_v2/sensor/eeprom/msm_eeprom.c12
-rw-r--r--drivers/media/platform/msm/camera_v2/sensor/msm_sensor_driver.c48
-rw-r--r--drivers/media/platform/msm/dvb/demux/mpq_dmx_plugin_common.c11
-rw-r--r--drivers/media/usb/uvc/uvc_ctrl.c3
-rw-r--r--drivers/misc/qseecom.c159
-rw-r--r--drivers/mmc/core/bus.h2
-rw-r--r--drivers/mmc/core/mmc.c3
-rw-r--r--drivers/mmc/host/sdhci-msm-ice.c2
-rw-r--r--drivers/mmc/host/sdhci-msm.c1
-rw-r--r--drivers/mtd/chips/Kconfig1
-rw-r--r--drivers/net/ethernet/broadcom/tg3.c2
-rw-r--r--drivers/net/ethernet/cavium/liquidio/lio_main.c9
-rw-r--r--drivers/net/macvlan.c11
-rw-r--r--drivers/net/phy/dp83640.c2
-rw-r--r--drivers/net/phy/phy.c2
-rw-r--r--drivers/net/ppp/pppolac.c4
-rw-r--r--drivers/net/ppp/pppopns.c4
-rw-r--r--drivers/net/wireless/ath/ath10k/qmi.c5
-rw-r--r--drivers/net/wireless/ath/ath10k/snoc.c23
-rw-r--r--drivers/net/wireless/ath/ath10k/snoc.h12
-rw-r--r--drivers/net/wireless/ath/wil6210/Kconfig2
-rw-r--r--drivers/net/wireless/ath/wil6210/cfg80211.c53
-rw-r--r--drivers/net/wireless/ath/wil6210/debugfs.c49
-rw-r--r--drivers/net/wireless/ath/wil6210/fw_inc.c4
-rw-r--r--drivers/net/wireless/ath/wil6210/interrupt.c6
-rw-r--r--drivers/net/wireless/ath/wil6210/main.c39
-rw-r--r--drivers/net/wireless/ath/wil6210/pcie_bus.c50
-rw-r--r--drivers/net/wireless/ath/wil6210/pm.c222
-rw-r--r--drivers/net/wireless/ath/wil6210/pmc.c4
-rw-r--r--drivers/net/wireless/ath/wil6210/rx_reorder.c12
-rw-r--r--drivers/net/wireless/ath/wil6210/txrx.c90
-rw-r--r--drivers/net/wireless/ath/wil6210/wil6210.h32
-rw-r--r--drivers/net/wireless/ath/wil6210/wil_platform.h5
-rw-r--r--drivers/net/wireless/ath/wil6210/wmi.c146
-rw-r--r--drivers/net/wireless/ath/wil6210/wmi.h27
-rw-r--r--drivers/net/wireless/cnss/Kconfig9
-rw-r--r--drivers/net/wireless/cnss/cnss_pci.c5
-rw-r--r--drivers/nfc/nq-nci.c1
-rw-r--r--drivers/pci/host/pci-msm.c3
-rw-r--r--drivers/platform/msm/ipa/ipa_v2/ipa_debugfs.c3
-rw-r--r--drivers/platform/msm/ipa/ipa_v2/ipa_i.h1
-rw-r--r--drivers/platform/msm/ipa/ipa_v2/ipa_qmi_service.h3
-rw-r--r--drivers/platform/msm/ipa/ipa_v2/ipa_uc.c15
-rw-r--r--drivers/platform/msm/ipa/ipa_v2/ipa_uc_offload_i.h45
-rw-r--r--drivers/platform/msm/ipa/ipa_v2/ipa_uc_wdi.c41
-rw-r--r--drivers/platform/msm/ipa/ipa_v2/ipa_utils.c2
-rw-r--r--drivers/platform/msm/ipa/ipa_v2/rmnet_ipa.c103
-rw-r--r--drivers/platform/msm/ipa/ipa_v2/rmnet_ipa_fd_ioctl.c30
-rw-r--r--drivers/platform/msm/ipa/ipa_v3/ipa_client.c24
-rw-r--r--drivers/platform/msm/ipa/ipa_v3/ipa_debugfs.c3
-rw-r--r--drivers/platform/msm/ipa/ipa_v3/ipa_dp.c2
-rw-r--r--drivers/platform/msm/ipa/ipa_v3/ipa_qmi_service.h3
-rw-r--r--drivers/platform/msm/ipa/ipa_v3/ipa_uc_wdi.c2
-rw-r--r--drivers/platform/msm/ipa/ipa_v3/ipa_utils.c2
-rw-r--r--drivers/platform/msm/ipa/ipa_v3/ipahal/ipahal_reg.c18
-rw-r--r--drivers/platform/msm/ipa/ipa_v3/rmnet_ipa.c99
-rw-r--r--drivers/platform/msm/ipa/ipa_v3/rmnet_ipa_fd_ioctl.c31
-rw-r--r--drivers/platform/msm/msm_11ad/msm_11ad.c260
-rw-r--r--drivers/platform/msm/msm_ext_display.c17
-rw-r--r--drivers/platform/msm/seemp_core/seemp_logk.c2
-rw-r--r--drivers/power/supply/qcom/qpnp-fg-gen3.c10
-rw-r--r--drivers/power/supply/qcom/qpnp-smb2.c11
-rw-r--r--drivers/power/supply/qcom/smb-lib.c52
-rw-r--r--drivers/power/supply/qcom/smb-lib.h3
-rw-r--r--drivers/regulator/onsemi-ncp6335d.c18
-rw-r--r--drivers/scsi/cxlflash/main.c23
-rw-r--r--drivers/scsi/ufs/Kconfig12
-rw-r--r--drivers/scsi/ufs/ufs-qcom-ice.c2
-rw-r--r--drivers/scsi/ufs/ufs-qcom.c2
-rw-r--r--drivers/scsi/ufs/ufshcd.c202
-rw-r--r--drivers/scsi/ufs/ufshcd.h46
-rw-r--r--drivers/soc/qcom/icnss_utils.c36
-rw-r--r--drivers/soc/qcom/memshare/msm_memshare.c20
-rw-r--r--drivers/soc/qcom/memshare/msm_memshare.h3
-rw-r--r--drivers/soc/qcom/msm_bus/msm_bus_rules.c9
-rw-r--r--drivers/soc/qcom/qbt1000.c21
-rw-r--r--drivers/soc/qcom/qpnp-haptic.c956
-rw-r--r--drivers/soc/qcom/rpm_master_stat.c10
-rw-r--r--drivers/soc/qcom/service-locator.c9
-rw-r--r--drivers/soc/qcom/service-notifier.c21
-rw-r--r--drivers/soc/qcom/smcinvoke.c11
-rw-r--r--drivers/soc/qcom/spcom.c149
-rw-r--r--drivers/soc/qcom/wcd-dsp-glink.c81
-rw-r--r--drivers/staging/android/ion/ion.c93
-rw-r--r--drivers/staging/android/ion/ion.h17
-rw-r--r--drivers/staging/rdma/ehca/ehca_mrmw.c3
-rw-r--r--drivers/tty/serial/8250/8250_pci.c12
-rw-r--r--drivers/usb/gadget/function/f_audio_source.c11
-rw-r--r--drivers/usb/gadget/function/f_cdev.c8
-rw-r--r--drivers/usb/gadget/function/f_midi.c4
-rw-r--r--drivers/usb/gadget/function/f_mtp.c23
-rw-r--r--drivers/usb/gadget/function/f_qdss.c26
-rw-r--r--drivers/usb/phy/phy-msm-qusb-v2.c31
-rw-r--r--drivers/video/fbdev/msm/dsi_status_6g.c4
-rw-r--r--drivers/video/fbdev/msm/mdss.h1
-rw-r--r--drivers/video/fbdev/msm/mdss_compat_utils.c6
-rw-r--r--drivers/video/fbdev/msm/mdss_compat_utils.h3
-rw-r--r--drivers/video/fbdev/msm/mdss_debug.c2
-rw-r--r--drivers/video/fbdev/msm/mdss_debug_xlog.c53
-rw-r--r--drivers/video/fbdev/msm/mdss_dp.c6
-rw-r--r--drivers/video/fbdev/msm/mdss_fb.c1
-rw-r--r--drivers/video/fbdev/msm/mdss_hdmi_edid.c42
-rw-r--r--drivers/video/fbdev/msm/mdss_hdmi_edid.h1
-rw-r--r--drivers/video/fbdev/msm/mdss_hdmi_tx.c8
-rw-r--r--drivers/video/fbdev/msm/mdss_mdp.c11
-rw-r--r--drivers/video/fbdev/msm/mdss_mdp.h2
-rw-r--r--drivers/video/fbdev/msm/mdss_mdp_ctl.c25
-rw-r--r--drivers/video/fbdev/msm/mdss_mdp_debug.c4
-rw-r--r--drivers/video/fbdev/msm/mdss_mdp_hwio.h2
-rw-r--r--drivers/video/fbdev/msm/mdss_mdp_intf_video.c61
-rw-r--r--drivers/video/fbdev/msm/mdss_mdp_layer.c219
-rw-r--r--drivers/video/fbdev/msm/mdss_mdp_overlay.c17
-rw-r--r--drivers/video/fbdev/msm/mdss_mdp_pp.c9
-rw-r--r--drivers/video/fbdev/msm/mdss_mdp_util.c2
-rw-r--r--drivers/video/fbdev/msm/mdss_mdp_wfd.c8
-rw-r--r--drivers/video/fbdev/msm/mdss_rotator.c20
-rw-r--r--fs/cifs/cifsglob.h11
-rw-r--r--fs/cifs/cifssmb.c4
-rw-r--r--fs/cifs/connect.c13
-rw-r--r--fs/cifs/smb2misc.c44
-rw-r--r--fs/cifs/smb2ops.c4
-rw-r--r--fs/cifs/smb2proto.h7
-rw-r--r--fs/cifs/smb2transport.c58
-rw-r--r--fs/cifs/transport.c2
-rw-r--r--fs/ext4/crypto.c5
-rw-r--r--fs/ext4/ioctl.c3
-rw-r--r--fs/f2fs/super.c90
-rw-r--r--fs/mbcache.c18
-rw-r--r--fs/nfsd/nfs3xdr.c12
-rw-r--r--fs/nfsd/nfssvc.c36
-rw-r--r--fs/nfsd/nfsxdr.c10
-rw-r--r--fs/timerfd.c17
-rw-r--r--include/linux/msm_ext_display.h2
-rw-r--r--include/linux/mtd/map.h19
-rw-r--r--include/soc/qcom/msm_qmi_interface.h2
-rw-r--r--include/sound/apr_audio-v2.h92
-rw-r--r--include/sound/q6asm-v2.h17
-rw-r--r--include/uapi/drm/drm.h22
-rw-r--r--include/uapi/drm/drm_fourcc.h8
-rw-r--r--include/uapi/drm/drm_mode.h8
-rw-r--r--include/uapi/drm/drm_sarea.h8
-rw-r--r--include/uapi/drm/msm_drm.h17
-rw-r--r--include/uapi/linux/ipv6_route.h2
-rw-r--r--include/uapi/linux/msm_audio.h10
-rw-r--r--include/uapi/linux/msm_ipa.h14
-rw-r--r--include/uapi/linux/msm_mdp_ext.h14
-rw-r--r--include/uapi/linux/rmnet_ipa_fd_ioctl.h17
-rw-r--r--include/uapi/sound/compress_offload.h7
-rw-r--r--kernel/time/timer.c9
-rw-r--r--kernel/trace/trace_printk.c2
-rw-r--r--net/9p/client.c4
-rw-r--r--net/core/neighbour.c3
-rw-r--r--net/core/netpoll.c10
-rw-r--r--net/ipv4/route.c2
-rw-r--r--net/ipv4/tcp.c1
-rw-r--r--net/ipv6/ip6_tunnel.c34
-rw-r--r--net/ipv6/ip6mr.c13
-rw-r--r--net/ipv6/raw.c3
-rw-r--r--net/ipv6/route.c4
-rw-r--r--net/l2tp/l2tp_core.c8
-rw-r--r--net/l2tp/l2tp_core.h3
-rw-r--r--net/l2tp/l2tp_debugfs.c10
-rw-r--r--net/l2tp/l2tp_netlink.c7
-rw-r--r--net/l2tp/l2tp_ppp.c19
-rw-r--r--net/netlink/af_netlink.c2
-rw-r--r--net/packet/af_packet.c4
-rw-r--r--net/rds/cong.c4
-rw-r--r--net/sched/act_mirred.c5
-rw-r--r--net/sctp/socket.c3
-rw-r--r--net/wireless/db.txt109
-rw-r--r--sound/core/seq/seq_lock.c9
-rw-r--r--sound/firewire/lib.h2
-rw-r--r--sound/ppc/awacs.c1
-rw-r--r--sound/soc/codecs/Kconfig2
-rw-r--r--sound/soc/codecs/sdm660_cdc/msm-digital-cdc.c9
-rw-r--r--sound/soc/codecs/wsa881x-analog.c4
-rw-r--r--sound/soc/intel/boards/bytcr_rt5640.c3
-rw-r--r--sound/soc/msm/qdsp6v2/Makefile2
-rw-r--r--sound/soc/msm/qdsp6v2/audio_cal_utils.c2
-rw-r--r--sound/soc/msm/qdsp6v2/msm-compr-q6-v2.c1694
-rw-r--r--sound/soc/msm/qdsp6v2/msm-compr-q6-v2.h36
-rw-r--r--sound/soc/msm/qdsp6v2/msm-compress-q6-v2.c279
-rw-r--r--sound/soc/msm/qdsp6v2/msm-dai-q6-hdmi-v2.c4
-rw-r--r--sound/soc/msm/qdsp6v2/msm-dai-q6-v2.c187
-rw-r--r--sound/soc/msm/qdsp6v2/msm-pcm-q6-v2.c40
-rw-r--r--sound/soc/msm/qdsp6v2/msm-pcm-routing-v2.c16
-rw-r--r--sound/soc/msm/qdsp6v2/msm-qti-pp-config.c281
-rw-r--r--sound/soc/msm/qdsp6v2/msm-qti-pp-config.h5
-rw-r--r--sound/soc/msm/qdsp6v2/q6asm.c372
-rw-r--r--sound/usb/format.c5
-rw-r--r--sound/usb/mixer.c4
-rw-r--r--sound/usb/stream.c13
-rw-r--r--sound/usb/usb_audio_qmi_svc.c6
315 files changed, 7738 insertions, 3873 deletions
diff --git a/Documentation/devicetree/bindings/arm/msm/wil6210.txt b/Documentation/devicetree/bindings/arm/msm/wil6210.txt
index c4673279953d..54bbf2535340 100644
--- a/Documentation/devicetree/bindings/arm/msm/wil6210.txt
+++ b/Documentation/devicetree/bindings/arm/msm/wil6210.txt
@@ -32,6 +32,8 @@ Optional properties:
- clocks : List of phandle and clock specifier pairs
- clock-names : List of clock input name strings sorted in the same
order as the clocks property.
+- qcom,keep_radio_on_during_sleep: Boolean flag to indicate if to suspend to d3hot
+ instead of turning off the device
Example:
wil6210: qcom,wil6210 {
@@ -56,5 +58,6 @@ Example:
clocks = <&clock_gcc clk_rf_clk3>,
<&clock_gcc clk_rf_clk3_pin>;
clock-names = "rf_clk3_clk", "rf_clk3_pin_clk";
+ qcom,keep_radio_on_during_sleep;
};
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/net/neutrino_avb.txt b/Documentation/devicetree/bindings/net/neutrino_avb.txt
index 46c6a5208eba..471d59f2a3c0 100644
--- a/Documentation/devicetree/bindings/net/neutrino_avb.txt
+++ b/Documentation/devicetree/bindings/net/neutrino_avb.txt
@@ -2,6 +2,11 @@
This driver implements Ethernet driver for Neutrino ethernet controller
Required properties:
- compatible: Should be "qcom,ntn_avb"
+ - ntn-rst-delay-msec: delay (msec) required after PCIe reset for stabilization
+ - ntn-rc-num: PCIe root complex number on which Neutrino is connected
+
+Optional properties:
+ - ntn-bus-num: PCIe bus number on which Neutrino is connected
- ntn-rst-gpio: Neutrino reset GPIO
- vdd-ntn-hsic-supply: neutrino HSIC power supply
- vdd-ntn-pci-supply: PCIe core power supply
@@ -25,4 +30,5 @@ Example:
pinctrl-0 = <&ntn_default>;
qcom,ntn-rst-delay-msec = <100>;
qcom,ntn-rc-num = <1>;
+ qcom,ntn-bus-num = <1>;
};
diff --git a/Documentation/devicetree/bindings/power/supply/qcom/qpnp-smb2.txt b/Documentation/devicetree/bindings/power/supply/qcom/qpnp-smb2.txt
index 894c34553a22..b41219d51973 100644
--- a/Documentation/devicetree/bindings/power/supply/qcom/qpnp-smb2.txt
+++ b/Documentation/devicetree/bindings/power/supply/qcom/qpnp-smb2.txt
@@ -181,6 +181,12 @@ Charger specific properties:
Definition: Specifies the maximum charger buck/boost switching frequency in
KHz. It overrides the max frequency defined for the charger.
+- qcom,otg-deglitch-time-ms
+ Usage: optional
+ Value type: <u32>
+ Definition: Specifies the deglitch interval for OTG detection.
+ If the value is not present, 50 msec is used as default.
+
=============================================
Second Level Nodes - SMB2 Charger Peripherals
=============================================
diff --git a/Documentation/devicetree/bindings/soc/qcom/qpnp-haptic.txt b/Documentation/devicetree/bindings/soc/qcom/qpnp-haptic.txt
index 337649824257..aa3363b52a03 100644
--- a/Documentation/devicetree/bindings/soc/qcom/qpnp-haptic.txt
+++ b/Documentation/devicetree/bindings/soc/qcom/qpnp-haptic.txt
@@ -76,6 +76,10 @@ Optional properties when qcom,actuator-type is "lra"
at End of Pattern
- qcom,lra-res-cal-period : Auto resonance calibration period. The values range from
4 to 32(default)
+- qcom,lra-auto-mode : If this property is specified, haptics mode for LRA
+ actuators will be automatically configured along with
+ other required settings runtime based on the duration
+ of the pattern.
- qcom,perform-lra-auto-resonance-search : boolean, define this property if:
a) the underlying PMI chip does not have a register in the MISC block to
read the error percentage in RC clock
diff --git a/Documentation/devicetree/bindings/sound/qcom-audio-dev.txt b/Documentation/devicetree/bindings/sound/qcom-audio-dev.txt
index acf12239c813..dec5442b33d6 100644
--- a/Documentation/devicetree/bindings/sound/qcom-audio-dev.txt
+++ b/Documentation/devicetree/bindings/sound/qcom-audio-dev.txt
@@ -1245,12 +1245,9 @@ Required properties:
When clock rate is set to zero,
then external clock is assumed.
- [Second Level Nodes]
-
-Required properties:
-
- - compatible : "qcom,msm-dai-q6-tdm"
- - qcom,msm-dai-q6-mi2s-dev-id: TDM port ID.
+ - qcom,msm-cpudai-tdm-clk-internal: Clock Source.
+ 0 - EBIT clock from clk tree
+ 1 - IBIT clock from clk tree
- qcom,msm-cpudai-tdm-sync-mode: Synchronization setting.
0 - Short sync bit mode
@@ -1275,6 +1272,13 @@ Required properties:
1 - 1 bit clock cycle
2 - 2 bit clock cycle
+ [Second Level Nodes]
+
+Required properties:
+
+ - compatible : "qcom,msm-dai-q6-tdm"
+ - qcom,msm-dai-q6-mi2s-dev-id: TDM port ID.
+
- qcom,msm-cpudai-tdm-data-align: Indicate how data is packed
within the slot. For example, 32 slot width in case of
sample bit width is 24.
@@ -1309,17 +1313,18 @@ Example:
qcom,msm-cpudai-tdm-group-num-ports = <1>;
qcom,msm-cpudai-tdm-group-port-id = <36912>;
qcom,msm-cpudai-tdm-clk-rate = <12288000>;
+ qcom,msm-cpudai-tdm-clk-internal = <1>;
+ qcom,msm-cpudai-tdm-sync-mode = <0>;
+ qcom,msm-cpudai-tdm-sync-src = <1>;
+ qcom,msm-cpudai-tdm-data-out = <0>;
+ qcom,msm-cpudai-tdm-invert-sync = <0>;
+ qcom,msm-cpudai-tdm-data-delay = <0>;
pinctrl-names = "default", "sleep";
pinctrl-0 = <&quat_tdm_active &quat_tdm_dout_active>;
pinctrl-1 = <&quat_tdm_sleep &quat_tdm_dout_sleep>;
dai_quat_tdm_rx_0: qcom,msm-dai-q6-tdm-quat-rx-0 {
compatible = "qcom,msm-dai-q6-tdm";
qcom,msm-cpudai-tdm-dev-id = <36912>;
- qcom,msm-cpudai-tdm-sync-mode = <0>;
- qcom,msm-cpudai-tdm-sync-src = <1>;
- qcom,msm-cpudai-tdm-data-out = <0>;
- qcom,msm-cpudai-tdm-invert-sync = <0>;
- qcom,msm-cpudai-tdm-data-delay = <0>;
qcom,msm-cpudai-tdm-data-align = <0>;
qcom,msm-cpudai-tdm-header-start-offset = <0>;
qcom,msm-cpudai-tdm-header-width = <2>;
diff --git a/Documentation/devicetree/bindings/usb/msm-phy.txt b/Documentation/devicetree/bindings/usb/msm-phy.txt
index 032f07535415..88ad24900f28 100644
--- a/Documentation/devicetree/bindings/usb/msm-phy.txt
+++ b/Documentation/devicetree/bindings/usb/msm-phy.txt
@@ -212,6 +212,8 @@ Optional properties:
- qcom,hold-reset: Indicates that hold QUSB PHY into reset state.
- qcom,phy-clk-scheme: Should be one of "cml" or "cmos" if ref_clk_addr is provided.
- qcom,major-rev: provide major revision number to differentiate power up sequence. default is 2.0
+ - qcom,vdda33-voltage-level: A list of three integer values (min, op, max) representing
+ specific voltages (in microvolts) used for the vdda33 supply.
Example:
qusb_phy: qusb@f9b39000 {
diff --git a/Makefile b/Makefile
index 933d159a74d7..13486839df5b 100644
--- a/Makefile
+++ b/Makefile
@@ -1,6 +1,6 @@
VERSION = 4
PATCHLEVEL = 4
-SUBLEVEL = 65
+SUBLEVEL = 67
EXTRAVERSION =
NAME = Blurry Fish Butt
diff --git a/android/configs/android-base.cfg b/android/configs/android-base.cfg
index 67842e7007a8..73429a4b25b1 100644
--- a/android/configs/android-base.cfg
+++ b/android/configs/android-base.cfg
@@ -29,7 +29,6 @@ CONFIG_HIGH_RES_TIMERS=y
CONFIG_IKCONFIG=y
CONFIG_IKCONFIG_PROC=y
CONFIG_INET6_AH=y
-CONFIG_INET6_DIAG_DESTROY=y
CONFIG_INET6_ESP=y
CONFIG_INET6_IPCOMP=y
CONFIG_INET=y
@@ -72,7 +71,6 @@ CONFIG_MODVERSIONS=y
CONFIG_NET=y
CONFIG_NETDEVICES=y
CONFIG_NETFILTER=y
-CONFIG_NETFILTER_TPROXY=y
CONFIG_NETFILTER_XT_MATCH_COMMENT=y
CONFIG_NETFILTER_XT_MATCH_CONNLIMIT=y
CONFIG_NETFILTER_XT_MATCH_CONNMARK=y
@@ -173,5 +171,4 @@ CONFIG_USB_CONFIGFS_F_MTP=y
CONFIG_USB_CONFIGFS_F_PTP=y
CONFIG_USB_CONFIGFS_UEVENT=y
CONFIG_USB_GADGET=y
-CONFIG_USB_OTG_WAKELOCK=y
CONFIG_XFRM_USER=y
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/Makefile b/arch/arm/boot/dts/qcom/Makefile
index 8e7f26bc85ae..c938988d6634 100644
--- a/arch/arm/boot/dts/qcom/Makefile
+++ b/arch/arm/boot/dts/qcom/Makefile
@@ -114,6 +114,8 @@ dtb-$(CONFIG_ARCH_MSM8996) += msm8996-v2-pmi8994-cdp.dtb \
apq8096-v3-pmi8996-mdm9x55-slimbus-mtp.dtb \
apq8096-v3-pmi8996-dragonboard.dtb
+dtb-$(CONFIG_MSM_GVM_QUIN) += vplatform-lfv-msm8996.dtb
+
ifeq ($(CONFIG_BUILD_ARM64_DT_OVERLAY),y)
dtbo-$(CONFIG_ARCH_MSM8998) += \
msm8998-cdp-overlay.dtbo \
diff --git a/arch/arm/boot/dts/qcom/apq8096-auto-dragonboard.dtsi b/arch/arm/boot/dts/qcom/apq8096-auto-dragonboard.dtsi
index 549bb9c169ce..ea8fc87c9b67 100644
--- a/arch/arm/boot/dts/qcom/apq8096-auto-dragonboard.dtsi
+++ b/arch/arm/boot/dts/qcom/apq8096-auto-dragonboard.dtsi
@@ -705,22 +705,9 @@
};
qcom,msm-dai-tdm-tert-rx {
- qcom,msm-cpudai-tdm-group-num-ports = <5>;
- qcom,msm-cpudai-tdm-group-port-id = <36896 36898 36900
- 36902 36904>;
pinctrl-names = "default", "sleep";
pinctrl-0 = <&tert_tdm_dout_active>;
pinctrl-1 = <&tert_tdm_dout_sleep>;
- dai_tert_tdm_rx_4: qcom,msm-dai-q6-tdm-tert-rx-4 {
- compatible = "qcom,msm-dai-q6-tdm";
- qcom,msm-cpudai-tdm-dev-id = <36904>;
- qcom,msm-cpudai-tdm-sync-mode = <1>;
- qcom,msm-cpudai-tdm-sync-src = <0>;
- qcom,msm-cpudai-tdm-data-out = <0>;
- qcom,msm-cpudai-tdm-invert-sync = <0>;
- qcom,msm-cpudai-tdm-data-delay = <0>;
- qcom,msm-cpudai-tdm-data-align = <0>;
- };
};
qcom,msm-dai-tdm-quat-rx {
diff --git a/arch/arm/boot/dts/qcom/apq8098-v2.1-mediabox.dts b/arch/arm/boot/dts/qcom/apq8098-v2.1-mediabox.dts
index 03e1e05a3739..822757ae1ec4 100644
--- a/arch/arm/boot/dts/qcom/apq8098-v2.1-mediabox.dts
+++ b/arch/arm/boot/dts/qcom/apq8098-v2.1-mediabox.dts
@@ -31,7 +31,6 @@
};
&mdss_mdp {
- status = "disabled";
qcom,mdss-pref-prim-intf = "hdmi";
};
diff --git a/arch/arm/boot/dts/qcom/msm-audio-lpass.dtsi b/arch/arm/boot/dts/qcom/msm-audio-lpass.dtsi
index 97a134b46713..d4962df321ed 100644
--- a/arch/arm/boot/dts/qcom/msm-audio-lpass.dtsi
+++ b/arch/arm/boot/dts/qcom/msm-audio-lpass.dtsi
@@ -377,14 +377,15 @@
qcom,msm-cpudai-tdm-group-num-ports = <1>;
qcom,msm-cpudai-tdm-group-port-id = <36864>;
qcom,msm-cpudai-tdm-clk-rate = <1536000>;
+ qcom,msm-cpudai-tdm-clk-internal = <1>;
+ 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>;
dai_pri_tdm_rx_0: qcom,msm-dai-q6-tdm-pri-rx-0 {
compatible = "qcom,msm-dai-q6-tdm";
qcom,msm-cpudai-tdm-dev-id = <36864>;
- 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>;
};
};
@@ -395,14 +396,15 @@
qcom,msm-cpudai-tdm-group-num-ports = <1>;
qcom,msm-cpudai-tdm-group-port-id = <36865>;
qcom,msm-cpudai-tdm-clk-rate = <1536000>;
+ qcom,msm-cpudai-tdm-clk-internal = <1>;
+ 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>;
dai_pri_tdm_tx_0: qcom,msm-dai-q6-tdm-pri-tx-0 {
compatible = "qcom,msm-dai-q6-tdm";
qcom,msm-cpudai-tdm-dev-id = <36865>;
- 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>;
};
};
@@ -413,14 +415,15 @@
qcom,msm-cpudai-tdm-group-num-ports = <1>;
qcom,msm-cpudai-tdm-group-port-id = <36880>;
qcom,msm-cpudai-tdm-clk-rate = <1536000>;
+ qcom,msm-cpudai-tdm-clk-internal = <1>;
+ 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>;
dai_sec_tdm_rx_0: qcom,msm-dai-q6-tdm-sec-rx-0 {
compatible = "qcom,msm-dai-q6-tdm";
qcom,msm-cpudai-tdm-dev-id = <36880>;
- 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>;
};
};
@@ -431,14 +434,15 @@
qcom,msm-cpudai-tdm-group-num-ports = <1>;
qcom,msm-cpudai-tdm-group-port-id = <36881>;
qcom,msm-cpudai-tdm-clk-rate = <1536000>;
+ qcom,msm-cpudai-tdm-clk-internal = <1>;
+ 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>;
dai_sec_tdm_tx_0: qcom,msm-dai-q6-tdm-sec-tx-0 {
compatible = "qcom,msm-dai-q6-tdm";
qcom,msm-cpudai-tdm-dev-id = <36881>;
- 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>;
};
};
@@ -449,14 +453,15 @@
qcom,msm-cpudai-tdm-group-num-ports = <1>;
qcom,msm-cpudai-tdm-group-port-id = <36896>;
qcom,msm-cpudai-tdm-clk-rate = <1536000>;
+ qcom,msm-cpudai-tdm-clk-internal = <1>;
+ 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>;
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>;
};
};
@@ -467,14 +472,15 @@
qcom,msm-cpudai-tdm-group-num-ports = <1>;
qcom,msm-cpudai-tdm-group-port-id = <36897 >;
qcom,msm-cpudai-tdm-clk-rate = <1536000>;
+ qcom,msm-cpudai-tdm-clk-internal = <1>;
+ 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>;
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>;
};
};
@@ -485,14 +491,15 @@
qcom,msm-cpudai-tdm-group-num-ports = <1>;
qcom,msm-cpudai-tdm-group-port-id = <36912>;
qcom,msm-cpudai-tdm-clk-rate = <1536000>;
+ qcom,msm-cpudai-tdm-clk-internal = <1>;
+ 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>;
dai_quat_tdm_rx_0: qcom,msm-dai-q6-tdm-quat-rx-0 {
compatible = "qcom,msm-dai-q6-tdm";
qcom,msm-cpudai-tdm-dev-id = <36912>;
- 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>;
};
};
@@ -503,14 +510,15 @@
qcom,msm-cpudai-tdm-group-num-ports = <1>;
qcom,msm-cpudai-tdm-group-port-id = <36913 >;
qcom,msm-cpudai-tdm-clk-rate = <1536000>;
+ qcom,msm-cpudai-tdm-clk-internal = <1>;
+ 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>;
dai_quat_tdm_tx_0: qcom,msm-dai-q6-tdm-quat-tx-0 {
compatible = "qcom,msm-dai-q6-tdm";
qcom,msm-cpudai-tdm-dev-id = <36913 >;
- 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-audio.dtsi b/arch/arm/boot/dts/qcom/msm-audio.dtsi
index d450f43f8c22..3a7514397139 100644
--- a/arch/arm/boot/dts/qcom/msm-audio.dtsi
+++ b/arch/arm/boot/dts/qcom/msm-audio.dtsi
@@ -445,14 +445,15 @@
qcom,msm-cpudai-tdm-group-num-ports = <1>;
qcom,msm-cpudai-tdm-group-port-id = <36864>;
qcom,msm-cpudai-tdm-clk-rate = <1536000>;
+ qcom,msm-cpudai-tdm-clk-internal = <1>;
+ 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>;
dai_pri_tdm_rx_0: qcom,msm-dai-q6-tdm-pri-rx-0 {
compatible = "qcom,msm-dai-q6-tdm";
qcom,msm-cpudai-tdm-dev-id = <36864>;
- 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>;
};
};
@@ -463,14 +464,15 @@
qcom,msm-cpudai-tdm-group-num-ports = <1>;
qcom,msm-cpudai-tdm-group-port-id = <36865>;
qcom,msm-cpudai-tdm-clk-rate = <1536000>;
+ qcom,msm-cpudai-tdm-clk-internal = <1>;
+ 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>;
dai_pri_tdm_tx_0: qcom,msm-dai-q6-tdm-pri-tx-0 {
compatible = "qcom,msm-dai-q6-tdm";
qcom,msm-cpudai-tdm-dev-id = <36865>;
- 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>;
};
};
@@ -481,14 +483,15 @@
qcom,msm-cpudai-tdm-group-num-ports = <1>;
qcom,msm-cpudai-tdm-group-port-id = <36880>;
qcom,msm-cpudai-tdm-clk-rate = <1536000>;
+ qcom,msm-cpudai-tdm-clk-internal = <1>;
+ 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>;
dai_sec_tdm_rx_0: qcom,msm-dai-q6-tdm-sec-rx-0 {
compatible = "qcom,msm-dai-q6-tdm";
qcom,msm-cpudai-tdm-dev-id = <36880>;
- 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>;
};
};
@@ -499,14 +502,15 @@
qcom,msm-cpudai-tdm-group-num-ports = <1>;
qcom,msm-cpudai-tdm-group-port-id = <36881>;
qcom,msm-cpudai-tdm-clk-rate = <1536000>;
+ qcom,msm-cpudai-tdm-clk-internal = <1>;
+ 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>;
dai_sec_tdm_tx_0: qcom,msm-dai-q6-tdm-sec-tx-0 {
compatible = "qcom,msm-dai-q6-tdm";
qcom,msm-cpudai-tdm-dev-id = <36881>;
- 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>;
};
};
@@ -517,14 +521,15 @@
qcom,msm-cpudai-tdm-group-num-ports = <1>;
qcom,msm-cpudai-tdm-group-port-id = <36896>;
qcom,msm-cpudai-tdm-clk-rate = <1536000>;
+ qcom,msm-cpudai-tdm-clk-internal = <1>;
+ 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>;
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>;
};
};
@@ -535,14 +540,15 @@
qcom,msm-cpudai-tdm-group-num-ports = <1>;
qcom,msm-cpudai-tdm-group-port-id = <36897 >;
qcom,msm-cpudai-tdm-clk-rate = <1536000>;
+ qcom,msm-cpudai-tdm-clk-internal = <1>;
+ 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>;
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>;
};
};
@@ -553,14 +559,15 @@
qcom,msm-cpudai-tdm-group-num-ports = <1>;
qcom,msm-cpudai-tdm-group-port-id = <36912>;
qcom,msm-cpudai-tdm-clk-rate = <1536000>;
+ qcom,msm-cpudai-tdm-clk-internal = <1>;
+ 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>;
dai_quat_tdm_rx_0: qcom,msm-dai-q6-tdm-quat-rx-0 {
compatible = "qcom,msm-dai-q6-tdm";
qcom,msm-cpudai-tdm-dev-id = <36912>;
- 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>;
};
};
@@ -571,14 +578,15 @@
qcom,msm-cpudai-tdm-group-num-ports = <1>;
qcom,msm-cpudai-tdm-group-port-id = <36913 >;
qcom,msm-cpudai-tdm-clk-rate = <1536000>;
+ qcom,msm-cpudai-tdm-clk-internal = <1>;
+ 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>;
dai_quat_tdm_tx_0: qcom,msm-dai-q6-tdm-quat-tx-0 {
compatible = "qcom,msm-dai-q6-tdm";
qcom,msm-cpudai-tdm-dev-id = <36913 >;
- 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-pm660.dtsi b/arch/arm/boot/dts/qcom/msm-pm660.dtsi
index 9bdaedd72585..7fde74f3d570 100644
--- a/arch/arm/boot/dts/qcom/msm-pm660.dtsi
+++ b/arch/arm/boot/dts/qcom/msm-pm660.dtsi
@@ -547,6 +547,7 @@
qcom,rradc-base = <0x4500>;
qcom,fg-esr-timer-awake = <96>;
qcom,fg-esr-timer-asleep = <256>;
+ qcom,fg-esr-timer-charging = <96>;
qcom,cycle-counter-en;
status = "okay";
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/msm8996-agave-adp.dtsi b/arch/arm/boot/dts/qcom/msm8996-agave-adp.dtsi
index fc26c16f6bf5..eae8c29fe21e 100644
--- a/arch/arm/boot/dts/qcom/msm8996-agave-adp.dtsi
+++ b/arch/arm/boot/dts/qcom/msm8996-agave-adp.dtsi
@@ -1010,22 +1010,9 @@
};
qcom,msm-dai-tdm-tert-rx {
- qcom,msm-cpudai-tdm-group-num-ports = <5>;
- qcom,msm-cpudai-tdm-group-port-id = <36896 36898 36900
- 36902 36904>;
pinctrl-names = "default", "sleep";
pinctrl-0 = <&tert_tdm_dout_active>;
pinctrl-1 = <&tert_tdm_dout_sleep>;
- dai_tert_tdm_rx_4: qcom,msm-dai-q6-tdm-tert-rx-4 {
- compatible = "qcom,msm-dai-q6-tdm";
- qcom,msm-cpudai-tdm-dev-id = <36904>;
- qcom,msm-cpudai-tdm-sync-mode = <1>;
- qcom,msm-cpudai-tdm-sync-src = <0>;
- qcom,msm-cpudai-tdm-data-out = <0>;
- qcom,msm-cpudai-tdm-invert-sync = <0>;
- qcom,msm-cpudai-tdm-data-delay = <0>;
- qcom,msm-cpudai-tdm-data-align = <0>;
- };
};
qcom,msm-dai-tdm-quat-rx {
diff --git a/arch/arm/boot/dts/qcom/msm8996-auto-cdp.dtsi b/arch/arm/boot/dts/qcom/msm8996-auto-cdp.dtsi
index 01f67b041b76..a1299027ae18 100644
--- a/arch/arm/boot/dts/qcom/msm8996-auto-cdp.dtsi
+++ b/arch/arm/boot/dts/qcom/msm8996-auto-cdp.dtsi
@@ -454,7 +454,7 @@
};
&soc {
- qcom,ntn_avb {
+ ntn1: ntn_avb@1 { /* Neutrno device on RC1*/
compatible = "qcom,ntn_avb";
ntn-rst-gpio = <&pm8994_gpios 13 0>;
@@ -465,6 +465,14 @@
qcom,ntn-rst-delay-msec = <100>;
qcom,ntn-rc-num = <1>;
+ qcom,ntn-bus-num = <1>;
+ };
+
+ ntn2: ntn_avb@2 { /*Neutrino device on RC2*/
+ compatible = "qcom,ntn_avb";
+ qcom,ntn-rst-delay-msec = <100>;
+ qcom,ntn-rc-num = <2>;
+ qcom,ntn-bus-num = <1>;
};
i2c@75ba000 {
@@ -725,22 +733,9 @@
};
qcom,msm-dai-tdm-tert-rx {
- qcom,msm-cpudai-tdm-group-num-ports = <5>;
- qcom,msm-cpudai-tdm-group-port-id = <36896 36898 36900
- 36902 36904>;
pinctrl-names = "default", "sleep";
pinctrl-0 = <&tert_tdm_dout_active>;
pinctrl-1 = <&tert_tdm_dout_sleep>;
- dai_tert_tdm_rx_4: qcom,msm-dai-q6-tdm-tert-rx-4 {
- compatible = "qcom,msm-dai-q6-tdm";
- qcom,msm-cpudai-tdm-dev-id = <36904>;
- qcom,msm-cpudai-tdm-sync-mode = <1>;
- qcom,msm-cpudai-tdm-sync-src = <0>;
- qcom,msm-cpudai-tdm-data-out = <0>;
- qcom,msm-cpudai-tdm-invert-sync = <0>;
- qcom,msm-cpudai-tdm-data-delay = <0>;
- qcom,msm-cpudai-tdm-data-align = <0>;
- };
};
qcom,msm-dai-tdm-quat-rx {
diff --git a/arch/arm/boot/dts/qcom/msm8996-mmxf-adp.dtsi b/arch/arm/boot/dts/qcom/msm8996-mmxf-adp.dtsi
index c5b6e7d0a3dc..53c3c7e727bc 100644
--- a/arch/arm/boot/dts/qcom/msm8996-mmxf-adp.dtsi
+++ b/arch/arm/boot/dts/qcom/msm8996-mmxf-adp.dtsi
@@ -595,22 +595,9 @@
};
qcom,msm-dai-tdm-tert-rx {
- qcom,msm-cpudai-tdm-group-num-ports = <5>;
- qcom,msm-cpudai-tdm-group-port-id = <36896 36898 36900
- 36902 36904>;
pinctrl-names = "default", "sleep";
pinctrl-0 = <&tert_tdm_dout_active>;
pinctrl-1 = <&tert_tdm_dout_sleep>;
- dai_tert_tdm_rx_4: qcom,msm-dai-q6-tdm-tert-rx-4 {
- compatible = "qcom,msm-dai-q6-tdm";
- qcom,msm-cpudai-tdm-dev-id = <36904>;
- qcom,msm-cpudai-tdm-sync-mode = <1>;
- qcom,msm-cpudai-tdm-sync-src = <0>;
- qcom,msm-cpudai-tdm-data-out = <0>;
- qcom,msm-cpudai-tdm-invert-sync = <0>;
- qcom,msm-cpudai-tdm-data-delay = <0>;
- qcom,msm-cpudai-tdm-data-align = <0>;
- };
};
qcom,msm-dai-tdm-quat-rx {
diff --git a/arch/arm/boot/dts/qcom/msm8996-regulator.dtsi b/arch/arm/boot/dts/qcom/msm8996-regulator.dtsi
index c70003a0a6dd..b86542a174da 100644
--- a/arch/arm/boot/dts/qcom/msm8996-regulator.dtsi
+++ b/arch/arm/boot/dts/qcom/msm8996-regulator.dtsi
@@ -1,4 +1,4 @@
-/* Copyright (c) 2014-2016, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2014-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
@@ -1950,4 +1950,21 @@
regulator-ramp-delay = <500>;
status = "disabled";
};
+
+ ncp6335d_vreg: ncp6335d-regulator@68 {
+ compatible = "onnn,ncp6335d-regulator";
+ reg = <0x68>;
+ vin-supply = <&hl7509_en_vreg>;
+ onnn,vsel = <0>;
+ onnn,slew-ns = <2666>;
+ onnn,step-size = <6250>;
+ onnn,min-slew-ns = <333>;
+ onnn,max-slew-ns = <2666>;
+ regulator-min-microvolt = <600000>;
+ regulator-max-microvolt = <1143750>;
+ onnn,min-setpoint = <600000>;
+ onnn,discharge-enable;
+ onnn,restore-reg;
+ status = "disabled";
+ };
};
diff --git a/arch/arm/boot/dts/qcom/msm8996.dtsi b/arch/arm/boot/dts/qcom/msm8996.dtsi
index 1752256029e7..ee069f5d8bdf 100644
--- a/arch/arm/boot/dts/qcom/msm8996.dtsi
+++ b/arch/arm/boot/dts/qcom/msm8996.dtsi
@@ -3356,48 +3356,34 @@
qcom,msm-cpudai-tdm-group-id = <37137>;
qcom,msm-cpudai-tdm-group-num-ports = <4>;
qcom,msm-cpudai-tdm-group-port-id = <36881 36883 36885 36887>;
- qcom,msm-cpudai-tdm-clk-rate = <0>;
+ qcom,msm-cpudai-tdm-clk-rate = <12288000>;
+ qcom,msm-cpudai-tdm-clk-internal = <0>;
+ qcom,msm-cpudai-tdm-sync-mode = <1>;
+ qcom,msm-cpudai-tdm-sync-src = <0>;
+ qcom,msm-cpudai-tdm-data-out = <0>;
+ qcom,msm-cpudai-tdm-invert-sync = <0>;
+ qcom,msm-cpudai-tdm-data-delay = <0>;
dai_sec_tdm_tx_0: qcom,msm-dai-q6-tdm-sec-tx-0 {
compatible = "qcom,msm-dai-q6-tdm";
qcom,msm-cpudai-tdm-dev-id = <36881>;
- qcom,msm-cpudai-tdm-sync-mode = <1>;
- qcom,msm-cpudai-tdm-sync-src = <0>;
- qcom,msm-cpudai-tdm-data-out = <0>;
- qcom,msm-cpudai-tdm-invert-sync = <0>;
- qcom,msm-cpudai-tdm-data-delay = <0>;
qcom,msm-cpudai-tdm-data-align = <0>;
};
dai_sec_tdm_tx_1: qcom,msm-dai-q6-tdm-sec-tx-1 {
compatible = "qcom,msm-dai-q6-tdm";
qcom,msm-cpudai-tdm-dev-id = <36883>;
- qcom,msm-cpudai-tdm-sync-mode = <1>;
- qcom,msm-cpudai-tdm-sync-src = <0>;
- qcom,msm-cpudai-tdm-data-out = <0>;
- qcom,msm-cpudai-tdm-invert-sync = <0>;
- qcom,msm-cpudai-tdm-data-delay = <0>;
qcom,msm-cpudai-tdm-data-align = <0>;
};
dai_sec_tdm_tx_2: qcom,msm-dai-q6-tdm-sec-tx-2 {
compatible = "qcom,msm-dai-q6-tdm";
qcom,msm-cpudai-tdm-dev-id = <36885>;
- qcom,msm-cpudai-tdm-sync-mode = <1>;
- qcom,msm-cpudai-tdm-sync-src = <0>;
- qcom,msm-cpudai-tdm-data-out = <0>;
- qcom,msm-cpudai-tdm-invert-sync = <0>;
- qcom,msm-cpudai-tdm-data-delay = <0>;
qcom,msm-cpudai-tdm-data-align = <0>;
};
dai_sec_tdm_tx_3: qcom,msm-dai-q6-tdm-sec-tx-3 {
compatible = "qcom,msm-dai-q6-tdm";
qcom,msm-cpudai-tdm-dev-id = <36887>;
- qcom,msm-cpudai-tdm-sync-mode = <1>;
- qcom,msm-cpudai-tdm-sync-src = <0>;
- qcom,msm-cpudai-tdm-data-out = <0>;
- qcom,msm-cpudai-tdm-invert-sync = <0>;
- qcom,msm-cpudai-tdm-data-delay = <0>;
qcom,msm-cpudai-tdm-data-align = <0>;
};
};
@@ -3405,50 +3391,43 @@
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 = <4>;
- qcom,msm-cpudai-tdm-group-port-id = <36896 36898 36900 36902>;
- qcom,msm-cpudai-tdm-clk-rate = <0>;
+ qcom,msm-cpudai-tdm-group-num-ports = <5>;
+ qcom,msm-cpudai-tdm-group-port-id = <36896 36898 36900
+ 36902 36904>;
+ qcom,msm-cpudai-tdm-clk-rate = <12288000>;
+ qcom,msm-cpudai-tdm-clk-internal = <0>;
+ qcom,msm-cpudai-tdm-sync-mode = <1>;
+ qcom,msm-cpudai-tdm-sync-src = <0>;
+ qcom,msm-cpudai-tdm-data-out = <0>;
+ qcom,msm-cpudai-tdm-invert-sync = <0>;
+ qcom,msm-cpudai-tdm-data-delay = <0>;
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 = <0>;
- qcom,msm-cpudai-tdm-data-out = <0>;
- qcom,msm-cpudai-tdm-invert-sync = <0>;
- qcom,msm-cpudai-tdm-data-delay = <0>;
qcom,msm-cpudai-tdm-data-align = <0>;
};
dai_tert_tdm_rx_1: qcom,msm-dai-q6-tdm-tert-rx-1 {
compatible = "qcom,msm-dai-q6-tdm";
qcom,msm-cpudai-tdm-dev-id = <36898>;
- qcom,msm-cpudai-tdm-sync-mode = <1>;
- qcom,msm-cpudai-tdm-sync-src = <0>;
- qcom,msm-cpudai-tdm-data-out = <0>;
- qcom,msm-cpudai-tdm-invert-sync = <0>;
- qcom,msm-cpudai-tdm-data-delay = <0>;
qcom,msm-cpudai-tdm-data-align = <0>;
};
dai_tert_tdm_rx_2: qcom,msm-dai-q6-tdm-tert-rx-2 {
compatible = "qcom,msm-dai-q6-tdm";
qcom,msm-cpudai-tdm-dev-id = <36900>;
- qcom,msm-cpudai-tdm-sync-mode = <1>;
- qcom,msm-cpudai-tdm-sync-src = <0>;
- qcom,msm-cpudai-tdm-data-out = <0>;
- qcom,msm-cpudai-tdm-invert-sync = <0>;
- qcom,msm-cpudai-tdm-data-delay = <0>;
qcom,msm-cpudai-tdm-data-align = <0>;
};
dai_tert_tdm_rx_3: qcom,msm-dai-q6-tdm-tert-rx-3 {
compatible = "qcom,msm-dai-q6-tdm";
qcom,msm-cpudai-tdm-dev-id = <36902>;
- qcom,msm-cpudai-tdm-sync-mode = <1>;
- qcom,msm-cpudai-tdm-sync-src = <0>;
- qcom,msm-cpudai-tdm-data-out = <0>;
- qcom,msm-cpudai-tdm-invert-sync = <0>;
- qcom,msm-cpudai-tdm-data-delay = <0>;
+ qcom,msm-cpudai-tdm-data-align = <0>;
+ };
+
+ dai_tert_tdm_rx_4: qcom,msm-dai-q6-tdm-tert-rx-4 {
+ compatible = "qcom,msm-dai-q6-tdm";
+ qcom,msm-cpudai-tdm-dev-id = <36904>;
qcom,msm-cpudai-tdm-data-align = <0>;
};
};
@@ -3458,48 +3437,34 @@
qcom,msm-cpudai-tdm-group-id = <37153>;
qcom,msm-cpudai-tdm-group-num-ports = <4>;
qcom,msm-cpudai-tdm-group-port-id = <36897 36899 36901 36903>;
- qcom,msm-cpudai-tdm-clk-rate = <0>;
+ qcom,msm-cpudai-tdm-clk-rate = <12288000>;
+ qcom,msm-cpudai-tdm-clk-internal = <0>;
+ qcom,msm-cpudai-tdm-sync-mode = <1>;
+ qcom,msm-cpudai-tdm-sync-src = <0>;
+ qcom,msm-cpudai-tdm-data-out = <0>;
+ qcom,msm-cpudai-tdm-invert-sync = <0>;
+ qcom,msm-cpudai-tdm-data-delay = <0>;
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 = <0>;
- qcom,msm-cpudai-tdm-data-out = <0>;
- qcom,msm-cpudai-tdm-invert-sync = <0>;
- qcom,msm-cpudai-tdm-data-delay = <0>;
qcom,msm-cpudai-tdm-data-align = <0>;
};
dai_tert_tdm_tx_1: qcom,msm-dai-q6-tdm-tert-tx-1 {
compatible = "qcom,msm-dai-q6-tdm";
qcom,msm-cpudai-tdm-dev-id = <36899>;
- qcom,msm-cpudai-tdm-sync-mode = <1>;
- qcom,msm-cpudai-tdm-sync-src = <0>;
- qcom,msm-cpudai-tdm-data-out = <0>;
- qcom,msm-cpudai-tdm-invert-sync = <0>;
- qcom,msm-cpudai-tdm-data-delay = <0>;
qcom,msm-cpudai-tdm-data-align = <0>;
};
dai_tert_tdm_tx_2: qcom,msm-dai-q6-tdm-tert-tx-2 {
compatible = "qcom,msm-dai-q6-tdm";
qcom,msm-cpudai-tdm-dev-id = <36901>;
- qcom,msm-cpudai-tdm-sync-mode = <1>;
- qcom,msm-cpudai-tdm-sync-src = <0>;
- qcom,msm-cpudai-tdm-data-out = <0>;
- qcom,msm-cpudai-tdm-invert-sync = <0>;
- qcom,msm-cpudai-tdm-data-delay = <0>;
qcom,msm-cpudai-tdm-data-align = <0>;
};
dai_tert_tdm_tx_3: qcom,msm-dai-q6-tdm-tert-tx-3 {
compatible = "qcom,msm-dai-q6-tdm";
qcom,msm-cpudai-tdm-dev-id = <36903>;
- qcom,msm-cpudai-tdm-sync-mode = <1>;
- qcom,msm-cpudai-tdm-sync-src = <0>;
- qcom,msm-cpudai-tdm-data-out = <0>;
- qcom,msm-cpudai-tdm-invert-sync = <0>;
- qcom,msm-cpudai-tdm-data-delay = <0>;
qcom,msm-cpudai-tdm-data-align = <0>;
};
};
@@ -3509,48 +3474,34 @@
qcom,msm-cpudai-tdm-group-id = <37168>;
qcom,msm-cpudai-tdm-group-num-ports = <4>;
qcom,msm-cpudai-tdm-group-port-id = <36912 36914 36916 36918>;
- qcom,msm-cpudai-tdm-clk-rate = <0>;
+ qcom,msm-cpudai-tdm-clk-rate = <12288000>;
+ qcom,msm-cpudai-tdm-clk-internal = <0>;
+ qcom,msm-cpudai-tdm-sync-mode = <1>;
+ qcom,msm-cpudai-tdm-sync-src = <0>;
+ qcom,msm-cpudai-tdm-data-out = <0>;
+ qcom,msm-cpudai-tdm-invert-sync = <0>;
+ qcom,msm-cpudai-tdm-data-delay = <0>;
dai_quat_tdm_rx_0: qcom,msm-dai-q6-tdm-quat-rx-0 {
compatible = "qcom,msm-dai-q6-tdm";
qcom,msm-cpudai-tdm-dev-id = <36912>;
- qcom,msm-cpudai-tdm-sync-mode = <1>;
- qcom,msm-cpudai-tdm-sync-src = <0>;
- qcom,msm-cpudai-tdm-data-out = <0>;
- qcom,msm-cpudai-tdm-invert-sync = <0>;
- qcom,msm-cpudai-tdm-data-delay = <0>;
qcom,msm-cpudai-tdm-data-align = <0>;
};
dai_quat_tdm_rx_1: qcom,msm-dai-q6-tdm-quat-rx-1 {
compatible = "qcom,msm-dai-q6-tdm";
qcom,msm-cpudai-tdm-dev-id = <36914>;
- qcom,msm-cpudai-tdm-sync-mode = <1>;
- qcom,msm-cpudai-tdm-sync-src = <0>;
- qcom,msm-cpudai-tdm-data-out = <0>;
- qcom,msm-cpudai-tdm-invert-sync = <0>;
- qcom,msm-cpudai-tdm-data-delay = <0>;
qcom,msm-cpudai-tdm-data-align = <0>;
};
dai_quat_tdm_rx_2: qcom,msm-dai-q6-tdm-quat-rx-2 {
compatible = "qcom,msm-dai-q6-tdm";
qcom,msm-cpudai-tdm-dev-id = <36916>;
- qcom,msm-cpudai-tdm-sync-mode = <1>;
- qcom,msm-cpudai-tdm-sync-src = <0>;
- qcom,msm-cpudai-tdm-data-out = <0>;
- qcom,msm-cpudai-tdm-invert-sync = <0>;
- qcom,msm-cpudai-tdm-data-delay = <0>;
qcom,msm-cpudai-tdm-data-align = <0>;
};
dai_quat_tdm_rx_3: qcom,msm-dai-q6-tdm-quat-rx-3 {
compatible = "qcom,msm-dai-q6-tdm";
qcom,msm-cpudai-tdm-dev-id = <36918>;
- qcom,msm-cpudai-tdm-sync-mode = <1>;
- qcom,msm-cpudai-tdm-sync-src = <0>;
- qcom,msm-cpudai-tdm-data-out = <0>;
- qcom,msm-cpudai-tdm-invert-sync = <0>;
- qcom,msm-cpudai-tdm-data-delay = <0>;
qcom,msm-cpudai-tdm-data-align = <0>;
};
};
@@ -3560,48 +3511,34 @@
qcom,msm-cpudai-tdm-group-id = <37169>;
qcom,msm-cpudai-tdm-group-num-ports = <4>;
qcom,msm-cpudai-tdm-group-port-id = <36913 36915 36917 36919>;
- qcom,msm-cpudai-tdm-clk-rate = <0>;
+ qcom,msm-cpudai-tdm-clk-rate = <12288000>;
+ qcom,msm-cpudai-tdm-clk-internal = <0>;
+ qcom,msm-cpudai-tdm-sync-mode = <1>;
+ qcom,msm-cpudai-tdm-sync-src = <0>;
+ qcom,msm-cpudai-tdm-data-out = <0>;
+ qcom,msm-cpudai-tdm-invert-sync = <0>;
+ qcom,msm-cpudai-tdm-data-delay = <0>;
dai_quat_tdm_tx_0: qcom,msm-dai-q6-tdm-quat-tx-0 {
compatible = "qcom,msm-dai-q6-tdm";
qcom,msm-cpudai-tdm-dev-id = <36913>;
- qcom,msm-cpudai-tdm-sync-mode = <1>;
- qcom,msm-cpudai-tdm-sync-src = <0>;
- qcom,msm-cpudai-tdm-data-out = <0>;
- qcom,msm-cpudai-tdm-invert-sync = <0>;
- qcom,msm-cpudai-tdm-data-delay = <0>;
qcom,msm-cpudai-tdm-data-align = <0>;
};
dai_quat_tdm_tx_1: qcom,msm-dai-q6-tdm-quat-tx-1 {
compatible = "qcom,msm-dai-q6-tdm";
qcom,msm-cpudai-tdm-dev-id = <36915>;
- qcom,msm-cpudai-tdm-sync-mode = <1>;
- qcom,msm-cpudai-tdm-sync-src = <0>;
- qcom,msm-cpudai-tdm-data-out = <0>;
- qcom,msm-cpudai-tdm-invert-sync = <0>;
- qcom,msm-cpudai-tdm-data-delay = <0>;
qcom,msm-cpudai-tdm-data-align = <0>;
};
dai_quat_tdm_tx_2: qcom,msm-dai-q6-tdm-quat-tx-2 {
compatible = "qcom,msm-dai-q6-tdm";
qcom,msm-cpudai-tdm-dev-id = <36917>;
- qcom,msm-cpudai-tdm-sync-mode = <1>;
- qcom,msm-cpudai-tdm-sync-src = <0>;
- qcom,msm-cpudai-tdm-data-out = <0>;
- qcom,msm-cpudai-tdm-invert-sync = <0>;
- qcom,msm-cpudai-tdm-data-delay = <0>;
qcom,msm-cpudai-tdm-data-align = <0>;
};
dai_quat_tdm_tx_3: qcom,msm-dai-q6-tdm-quat-tx-3 {
compatible = "qcom,msm-dai-q6-tdm";
qcom,msm-cpudai-tdm-dev-id = <36919>;
- qcom,msm-cpudai-tdm-sync-mode = <1>;
- qcom,msm-cpudai-tdm-sync-src = <0>;
- qcom,msm-cpudai-tdm-data-out = <0>;
- qcom,msm-cpudai-tdm-invert-sync = <0>;
- qcom,msm-cpudai-tdm-data-delay = <0>;
qcom,msm-cpudai-tdm-data-align = <0>;
};
};
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/msm8998.dtsi b/arch/arm/boot/dts/qcom/msm8998.dtsi
index c25f3ebcb113..c1d785e42669 100644
--- a/arch/arm/boot/dts/qcom/msm8998.dtsi
+++ b/arch/arm/boot/dts/qcom/msm8998.dtsi
@@ -3200,6 +3200,10 @@
<&clock_gcc clk_rf_clk3_pin>;
clock-names = "rf_clk3_clk", "rf_clk3_pin_clk";
qcom,smmu-support;
+ qcom,smmu-s1-en;
+ qcom,smmu-fast-map;
+ qcom,smmu-coherent;
+ qcom,smmu-mapping = <0x20000000 0xe0000000>;
status = "disabled";
};
diff --git a/arch/arm/boot/dts/qcom/sda660-pm660a-qrd-hdk.dts b/arch/arm/boot/dts/qcom/sda660-pm660a-qrd-hdk.dts
index a767853cd829..c2bf2c4a088e 100644
--- a/arch/arm/boot/dts/qcom/sda660-pm660a-qrd-hdk.dts
+++ b/arch/arm/boot/dts/qcom/sda660-pm660a-qrd-hdk.dts
@@ -17,6 +17,143 @@
#include "sdm660-qrd.dtsi"
#include "msm-pm660a.dtsi"
+&smb1351_charger {
+ status = "disabled";
+};
+
+&i2c_2 {
+ smb138x: qcom,smb138x@8 {
+ compatible = "qcom,i2c-pmic";
+ reg = <0x8>;
+ #address-cells = <1>;
+ #size-cells = <1>;
+ interrupt-parent = <&tlmm>;
+ interrupts = <21 IRQ_TYPE_LEVEL_LOW>;
+ interrupt_names = "smb138x";
+ interrupt-controller;
+ #interrupt-cells = <3>;
+ qcom,periph-map = <0x10 0x11 0x12 0x13 0x14 0x16 0x36>;
+ pinctrl-names = "default";
+ pinctrl-0 = <&smb_int_default>;
+
+ smb138x_revid: qcom,revid@100 {
+ compatible = "qcom,qpnp-revid";
+ reg = <0x100 0x100>;
+ };
+
+ smb138x_tadc: qcom,tadc@3600 {
+ compatible = "qcom,tadc";
+ reg = <0x3600 0x100>;
+ #address-cells = <1>;
+ #size-cells = <0>;
+ #io-channel-cells = <1>;
+ interrupt-parent = <&smb138x>;
+ interrupts = <0x36 0x0 IRQ_TYPE_EDGE_BOTH>;
+ interrupt-names = "eoc";
+
+ batt_temp@0 {
+ reg = <0>;
+ qcom,rbias = <68100>;
+ qcom,rtherm-at-25degc = <68000>;
+ qcom,beta-coefficient = <3450>;
+ };
+
+ skin_temp@1 {
+ reg = <1>;
+ qcom,rbias = <33000>;
+ qcom,rtherm-at-25degc = <68000>;
+ qcom,beta-coefficient = <3450>;
+ };
+
+ die_temp@2 {
+ reg = <2>;
+ qcom,scale = <(-1306)>;
+ qcom,offset = <397904>;
+ };
+
+ batt_i@3 {
+ reg = <3>;
+ qcom,channel = <3>;
+ qcom,scale = <(-20000000)>;
+ };
+
+ batt_v@4 {
+ reg = <4>;
+ qcom,scale = <5000000>;
+ };
+
+ input_i@5 {
+ reg = <5>;
+ qcom,scale = <14285714>;
+ };
+
+ input_v@6 {
+ reg = <6>;
+ qcom,scale = <25000000>;
+ };
+
+ otg_i@7 {
+ reg = <7>;
+ qcom,scale = <5714286>;
+ };
+ };
+
+ smb138x_parallel_slave: qcom,smb138x-parallel-slave@1000 {
+ compatible = "qcom,smb138x-parallel-slave";
+ qcom,pmic-revid = <&smb138x_revid>;
+ reg = <0x1000 0x700>;
+ #address-cells = <1>;
+ #size-cells = <1>;
+ interrupt-parent = <&smb138x>;
+ io-channels =
+ <&smb138x_tadc 1>,
+ <&smb138x_tadc 2>,
+ <&smb138x_tadc 3>,
+ <&smb138x_tadc 14>,
+ <&smb138x_tadc 15>,
+ <&smb138x_tadc 16>,
+ <&smb138x_tadc 17>;
+ io-channel-names =
+ "connector_temp",
+ "charger_temp",
+ "batt_i",
+ "connector_temp_thr1",
+ "connector_temp_thr2",
+ "connector_temp_thr3",
+ "charger_temp_max";
+
+ qcom,chgr@1000 {
+ reg = <0x1000 0x100>;
+ interrupts = <0x10 0x1 IRQ_TYPE_EDGE_RISING>;
+ interrupt-names = "chg-state-change";
+ };
+
+ qcom,chgr-misc@1600 {
+ reg = <0x1600 0x100>;
+ interrupts = <0x16 0x1 IRQ_TYPE_EDGE_RISING>,
+ <0x16 0x6 IRQ_TYPE_EDGE_RISING>;
+ interrupt-names = "wdog-bark",
+ "temperature-change";
+ };
+ };
+ };
+};
+
+&tlmm {
+ smb_int_default: smb_int_default {
+ mux {
+ pins = "gpio21";
+ function = "gpio";
+ };
+
+ config {
+ pins = "gpio21";
+ drive-strength = <2>;
+ bias-pull-up;
+ };
+ };
+};
+
/ {
model = "Qualcomm Technologies, Inc. SDA 660 PM660 + PM660A QRD HDK660";
compatible = "qcom,sda660-qrd", "qcom,sda660", "qcom,qrd";
diff --git a/arch/arm/boot/dts/qcom/sdm630-mdss.dtsi b/arch/arm/boot/dts/qcom/sdm630-mdss.dtsi
index d35704224f45..49e4fd7e5ba7 100644
--- a/arch/arm/boot/dts/qcom/sdm630-mdss.dtsi
+++ b/arch/arm/boot/dts/qcom/sdm630-mdss.dtsi
@@ -112,13 +112,14 @@
clocks = <&clock_mmss MMSS_MNOC_AHB_CLK>,
<&clock_mmss MMSS_MDSS_AHB_CLK>,
<&clock_mmss MMSS_MDSS_AXI_CLK>,
+ <&clock_mmss MMSS_THROTTLE_MDSS_AXI_CLK>,
<&clock_mmss MDP_CLK_SRC>,
<&clock_mmss MMSS_MDSS_MDP_CLK>,
<&clock_mmss MMSS_MDSS_VSYNC_CLK>,
<&clock_mmss MDP_CLK_SRC>;
clock-names = "mnoc_clk", "iface_clk", "bus_clk",
- "core_clk_src", "core_clk", "vsync_clk",
- "lut_clk";
+ "throttle_bus_clk", "core_clk_src",
+ "core_clk", "vsync_clk", "lut_clk";
qcom,mdp-settings = <0x01190 0x00000000>,
<0x012ac 0xc0000ccc>,
diff --git a/arch/arm/boot/dts/qcom/sdm630-qrd.dtsi b/arch/arm/boot/dts/qcom/sdm630-qrd.dtsi
index c677df529dd7..c24a41656f3a 100644
--- a/arch/arm/boot/dts/qcom/sdm630-qrd.dtsi
+++ b/arch/arm/boot/dts/qcom/sdm630-qrd.dtsi
@@ -159,6 +159,7 @@
&pm660_fg {
qcom,battery-data = <&qrd_batterydata>;
qcom,fg-jeita-thresholds = <0 5 55 55>;
+ qcom,battery-thermal-coefficients = [9d 50 ff];
};
&uartblsp1dm1 {
@@ -395,3 +396,16 @@
qcom,afe-power-off-delay-us = <6>;
};
};
+
+&qusb_phy0 {
+ qcom,qusb-phy-init-seq = <0xf8 0x80
+ 0x80 0x84
+ 0x83 0x88
+ 0xc7 0x8c
+ 0x30 0x08
+ 0x79 0x0c
+ 0x21 0x10
+ 0x14 0x9c
+ 0x9f 0x1c
+ 0x00 0x18>;
+};
diff --git a/arch/arm/boot/dts/qcom/sdm630.dtsi b/arch/arm/boot/dts/qcom/sdm630.dtsi
index 24a935ffebec..9897900d3fd5 100644
--- a/arch/arm/boot/dts/qcom/sdm630.dtsi
+++ b/arch/arm/boot/dts/qcom/sdm630.dtsi
@@ -1323,7 +1323,7 @@
< 1670400000 0x04040057 0x08450045 0x2 6 >,
< 1881600000 0x04040062 0x094e004e 0x2 7 >,
< 2016000000 0x04040069 0x0a540054 0x2 8 >,
- < 2150400000 0x04040070 0x0b590059 0x2 8 >,
+ < 2150400000 0x04040070 0x0b590059 0x2 9 >,
< 2208000000 0x04040073 0x0b5c005c 0x3 10 >;
qcom,perfcl-speedbin2-v0 =
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-mdss.dtsi b/arch/arm/boot/dts/qcom/sdm660-mdss.dtsi
index 787c4f1e2fb6..ab4e71e3cd65 100644
--- a/arch/arm/boot/dts/qcom/sdm660-mdss.dtsi
+++ b/arch/arm/boot/dts/qcom/sdm660-mdss.dtsi
@@ -117,13 +117,14 @@
clocks = <&clock_mmss MMSS_MNOC_AHB_CLK>,
<&clock_mmss MMSS_MDSS_AHB_CLK>,
<&clock_mmss MMSS_MDSS_AXI_CLK>,
+ <&clock_mmss MMSS_THROTTLE_MDSS_AXI_CLK>,
<&clock_mmss MDP_CLK_SRC>,
<&clock_mmss MMSS_MDSS_MDP_CLK>,
<&clock_mmss MMSS_MDSS_VSYNC_CLK>,
<&clock_mmss MDP_CLK_SRC>;
clock-names = "mnoc_clk", "iface_clk", "bus_clk",
- "core_clk_src", "core_clk", "vsync_clk",
- "lut_clk";
+ "throttle_bus_clk", "core_clk_src",
+ "core_clk", "vsync_clk", "lut_clk";
qcom,mdp-settings = <0x01190 0x00000000>,
<0x012ac 0xc0000ccc>,
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/boot/dts/qcom/sdm660-qrd.dtsi b/arch/arm/boot/dts/qcom/sdm660-qrd.dtsi
index 3d2cfedc1009..e78c2474df4d 100644
--- a/arch/arm/boot/dts/qcom/sdm660-qrd.dtsi
+++ b/arch/arm/boot/dts/qcom/sdm660-qrd.dtsi
@@ -119,6 +119,19 @@
};
};
+&qusb_phy0 {
+ qcom,qusb-phy-init-seq = <0xf8 0x80
+ 0x80 0x84
+ 0x83 0x88
+ 0xc7 0x8c
+ 0x30 0x08
+ 0x79 0x0c
+ 0x21 0x10
+ 0x14 0x9c
+ 0x9f 0x1c
+ 0x00 0x18>;
+};
+
&pm660_gpios {
/* GPIO 4 (NFC_CLK_REQ) */
gpio@c300 {
@@ -230,11 +243,12 @@
&pm660_fg {
qcom,battery-data = <&qrd_batterydata>;
qcom,fg-jeita-thresholds = <0 5 55 55>;
+ qcom,battery-thermal-coefficients = [9d 50 ff];
};
&i2c_2 {
status = "ok";
- smb1351-charger@1d {
+ smb1351_charger: smb1351-charger@1d {
compatible = "qcom,smb1351-charger";
reg = <0x1d>;
qcom,parallel-charger;
diff --git a/arch/arm/boot/dts/qcom/vplatform-lfv-ion.dtsi b/arch/arm/boot/dts/qcom/vplatform-lfv-ion.dtsi
new file mode 100644
index 000000000000..1176b54835b1
--- /dev/null
+++ b/arch/arm/boot/dts/qcom/vplatform-lfv-ion.dtsi
@@ -0,0 +1,31 @@
+/* Copyright (c) 2017, The Linux Foundation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ */
+
+&soc {
+ qcom,ion {
+ compatible = "qcom,msm-ion";
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ system_heap: qcom,ion-heap@25 {
+ reg = <25>;
+ memory-region = <&ion_system>;
+ qcom,ion-heap-type = "CARVEOUT";
+ };
+
+ qcom,ion-heap@28 { /* Audio Heap */
+ reg = <28>;
+ memory-region = <&ion_audio>;
+ qcom,ion-heap-type = "CARVEOUT";
+ };
+ };
+};
diff --git a/arch/arm/boot/dts/qcom/vplatform-lfv-msm8996.dts b/arch/arm/boot/dts/qcom/vplatform-lfv-msm8996.dts
new file mode 100644
index 000000000000..99f17844e508
--- /dev/null
+++ b/arch/arm/boot/dts/qcom/vplatform-lfv-msm8996.dts
@@ -0,0 +1,487 @@
+/* Copyright (c) 2017, The Linux Foundation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ */
+
+/dts-v1/;
+
+#include "skeleton64.dtsi"
+
+/ {
+ model = "Qualcomm Technologies, Inc. MSM 8996";
+ compatible = "qcom,msm8996";
+ qcom,msm-id = <246 0x0>;
+
+ soc: soc { };
+
+ psci {
+ compatible = "arm,psci";
+ method = "smc";
+ cpu_suspend = <0xc4000001>;
+ cpu_off = <0x84000002>;
+ cpu_on = <0xc4000003>;
+ };
+
+ reserved-memory {
+ #address-cells = <2>;
+ #size-cells = <2>;
+ ranges;
+
+ pmem_shared: pmem_shared_region {
+ reg = <0 0xd0000000 0 0x20000000>;
+ label = "pmem_shared_mem";
+ };
+ ion_system: ion_system_region {
+ reg = <0x1 0x0 0 0x10000000>;
+ label = "ion_system_mem";
+ };
+ ion_audio: ion_audio_region {
+ reg = <0 0xc8000000 0 0x00400000>;
+ label = "ion_audio_mem";
+ };
+ };
+};
+
+#include "vplatform-lfv-ion.dtsi"
+
+&soc {
+ #address-cells = <1>;
+ #size-cells = <1>;
+ ranges = <0 0 0 0xffffffff>;
+ compatible = "simple-bus";
+
+ sound-adp-agave {
+ compatible = "qcom,apq8096-asoc-snd-adp-agave";
+ qcom,model = "apq8096-adp-agave-snd-card";
+
+ asoc-platform = <&pcm0>, <&pcm1>, <&pcm2>, <&voip>, <&voice>,
+ <&loopback>, <&compress>, <&hostless>,
+ <&afe>, <&lsm>, <&routing>, <&compr>,
+ <&loopback1>;
+ asoc-platform-names = "msm-pcm-dsp.0", "msm-pcm-dsp.1",
+ "msm-pcm-dsp.2", "msm-voip-dsp",
+ "msm-pcm-voice", "msm-pcm-loopback",
+ "msm-compress-dsp", "msm-pcm-hostless",
+ "msm-pcm-afe", "msm-lsm-client",
+ "msm-pcm-routing", "msm-compr-dsp",
+ "msm-pcm-loopback.1";
+ asoc-cpu = <&dai_pri_auxpcm>, <&dai_sec_auxpcm>, <&dai_hdmi>,
+ <&dai_mi2s_sec>, <&dai_mi2s>, <&dai_mi2s_quat>,
+ <&afe_pcm_rx>, <&afe_pcm_tx>,
+ <&afe_proxy_rx>, <&afe_proxy_tx>,
+ <&incall_record_rx>, <&incall_record_tx>,
+ <&incall_music_rx>, <&incall_music2_rx>,
+ <&dai_tert_tdm_rx_0>, <&dai_tert_tdm_rx_1>,
+ <&dai_tert_tdm_rx_2>, <&dai_tert_tdm_rx_3>,
+ <&dai_tert_tdm_tx_0>, <&dai_tert_tdm_tx_1>,
+ <&dai_tert_tdm_tx_2>, <&dai_tert_tdm_tx_3>,
+ <&dai_quat_tdm_rx_0>, <&dai_quat_tdm_rx_1>,
+ <&dai_quat_tdm_rx_2>, <&dai_quat_tdm_rx_3>,
+ <&dai_quat_tdm_tx_0>, <&dai_quat_tdm_tx_1>,
+ <&dai_quat_tdm_tx_2>, <&dai_quat_tdm_tx_3>;
+ asoc-cpu-names = "msm-dai-q6-auxpcm.1", "msm-dai-q6-auxpcm.2",
+ "msm-dai-q6-hdmi.8", "msm-dai-q6-mi2s.1",
+ "msm-dai-q6-mi2s.2", "msm-dai-q6-mi2s.3",
+ "msm-dai-q6-dev.224", "msm-dai-q6-dev.225",
+ "msm-dai-q6-dev.241", "msm-dai-q6-dev.240",
+ "msm-dai-q6-dev.32771", "msm-dai-q6-dev.32772",
+ "msm-dai-q6-dev.32773", "msm-dai-q6-dev.32770",
+ "msm-dai-q6-tdm.36896", "msm-dai-q6-tdm.36898",
+ "msm-dai-q6-tdm.36900", "msm-dai-q6-tdm.36902",
+ "msm-dai-q6-tdm.36897", "msm-dai-q6-tdm.36899",
+ "msm-dai-q6-tdm.36901", "msm-dai-q6-tdm.36903",
+ "msm-dai-q6-tdm.36912", "msm-dai-q6-tdm.36914",
+ "msm-dai-q6-tdm.36916", "msm-dai-q6-tdm.36918",
+ "msm-dai-q6-tdm.36913", "msm-dai-q6-tdm.36915",
+ "msm-dai-q6-tdm.36917", "msm-dai-q6-tdm.36919";
+ asoc-codec = <&stub_codec>;
+ asoc-codec-names = "msm-stub-codec.1";
+ };
+
+ qcom,msm-audio-ion {
+ compatible = "qcom,msm-audio-ion";
+ qcom,smmu-enabled;
+ qcom,smmu-sid = <1>;
+ };
+
+ pcm0: qcom,msm-pcm {
+ compatible = "qcom,msm-pcm-dsp";
+ qcom,msm-pcm-dsp-id = <0>;
+ };
+
+ pcm1: qcom,msm-pcm-low-latency {
+ compatible = "qcom,msm-pcm-dsp";
+ qcom,msm-pcm-dsp-id = <1>;
+ qcom,msm-pcm-low-latency;
+ qcom,latency-level = "regular";
+ };
+
+ pcm2: qcom,msm-ultra-low-latency {
+ compatible = "qcom,msm-pcm-dsp";
+ qcom,msm-pcm-dsp-id = <2>;
+ qcom,msm-pcm-low-latency;
+ qcom,latency-level = "ultra";
+ };
+
+ routing: qcom,msm-pcm-routing {
+ compatible = "qcom,msm-pcm-routing";
+ };
+
+ compr: qcom,msm-compr-dsp {
+ compatible = "qcom,msm-compr-dsp";
+ };
+
+ compress: qcom,msm-compress-dsp {
+ compatible = "qcom,msm-compress-dsp";
+ };
+
+ voip: qcom,msm-voip-dsp {
+ compatible = "qcom,msm-voip-dsp";
+ };
+
+ voice: qcom,msm-pcm-voice {
+ compatible = "qcom,msm-pcm-voice";
+ qcom,destroy-cvd;
+ };
+
+ stub_codec: qcom,msm-stub-codec {
+ compatible = "qcom,msm-stub-codec";
+ };
+
+ qcom,msm-dai-fe {
+ compatible = "qcom,msm-dai-fe";
+ };
+
+ afe: qcom,msm-pcm-afe {
+ compatible = "qcom,msm-pcm-afe";
+ };
+
+ dai_hdmi: qcom,msm-dai-q6-hdmi {
+ compatible = "qcom,msm-dai-q6-hdmi";
+ qcom,msm-dai-q6-dev-id = <8>;
+ };
+
+ lsm: qcom,msm-lsm-client {
+ compatible = "qcom,msm-lsm-client";
+ };
+
+ loopback: qcom,msm-pcm-loopback {
+ compatible = "qcom,msm-pcm-loopback";
+ };
+
+ loopback1: qcom,msm-pcm-loopback-low-latency {
+ compatible = "qcom,msm-pcm-loopback";
+ qcom,msm-pcm-loopback-low-latency;
+ };
+
+ qcom,msm-dai-q6 {
+ compatible = "qcom,msm-dai-q6";
+
+ afe_pcm_rx: qcom,msm-dai-q6-be-afe-pcm-rx {
+ compatible = "qcom,msm-dai-q6-dev";
+ qcom,msm-dai-q6-dev-id = <224>;
+ };
+
+ afe_pcm_tx: qcom,msm-dai-q6-be-afe-pcm-tx {
+ compatible = "qcom,msm-dai-q6-dev";
+ qcom,msm-dai-q6-dev-id = <225>;
+ };
+
+ afe_proxy_rx: com,msm-dai-q6-afe-proxy-rx {
+ compatible = "qcom,msm-dai-q6-dev";
+ qcom,msm-dai-q6-dev-id = <241>;
+ };
+
+ afe_proxy_tx: qcom,msm-dai-q6-afe-proxy-tx {
+ compatible = "qcom,msm-dai-q6-dev";
+ qcom,msm-dai-q6-dev-id = <240>;
+ };
+
+ incall_record_rx: qcom,msm-dai-q6-incall-record-rx {
+ compatible = "qcom,msm-dai-q6-dev";
+ qcom,msm-dai-q6-dev-id = <32771>;
+ };
+
+ incall_record_tx: qcom,msm-dai-q6-incall-record-tx {
+ compatible = "qcom,msm-dai-q6-dev";
+ qcom,msm-dai-q6-dev-id = <32772>;
+ };
+
+ incall_music_rx: qcom,msm-dai-q6-incall-music-rx {
+ compatible = "qcom,msm-dai-q6-dev";
+ qcom,msm-dai-q6-dev-id = <32773>;
+ };
+
+ incall_music2_rx: qcom,msm-dai-q6-incall-music-2-rx {
+ compatible = "qcom,msm-dai-q6-dev";
+ qcom,msm-dai-q6-dev-id = <32770>;
+ };
+ };
+
+ dai_pri_auxpcm: qcom,msm-pri-auxpcm {
+ compatible = "qcom,msm-auxpcm-dev";
+ qcom,msm-cpudai-auxpcm-mode = <0>, <0>;
+ qcom,msm-cpudai-auxpcm-sync = <1>, <1>;
+ qcom,msm-cpudai-auxpcm-frame = <5>, <4>;
+ qcom,msm-cpudai-auxpcm-quant = <2>, <2>;
+ qcom,msm-cpudai-auxpcm-num-slots = <1>, <1>;
+ qcom,msm-cpudai-auxpcm-slot-mapping = <1>, <1>;
+ qcom,msm-cpudai-auxpcm-data = <0>, <0>;
+ qcom,msm-cpudai-auxpcm-pcm-clk-rate = <2048000>, <2048000>;
+ qcom,msm-auxpcm-interface = "primary";
+ qcom,msm-cpudai-afe-clk-ver = <2>;
+ };
+
+ dai_sec_auxpcm: qcom,msm-sec-auxpcm {
+ compatible = "qcom,msm-auxpcm-dev";
+ qcom,msm-cpudai-auxpcm-mode = <0>, <0>;
+ qcom,msm-cpudai-auxpcm-sync = <1>, <1>;
+ qcom,msm-cpudai-auxpcm-frame = <5>, <4>;
+ qcom,msm-cpudai-auxpcm-quant = <2>, <2>;
+ qcom,msm-cpudai-auxpcm-num-slots = <1>, <1>;
+ qcom,msm-cpudai-auxpcm-slot-mapping = <1>, <1>;
+ qcom,msm-cpudai-auxpcm-data = <0>, <0>;
+ qcom,msm-cpudai-auxpcm-pcm-clk-rate = <2048000>, <2048000>;
+ qcom,msm-auxpcm-interface = "secondary";
+ qcom,msm-cpudai-afe-clk-ver = <2>;
+ };
+
+ qcom,msm-dai-mi2s {
+ compatible = "qcom,msm-dai-mi2s";
+ dai_mi2s_sec: qcom,msm-dai-q6-mi2s-sec {
+ compatible = "qcom,msm-dai-q6-mi2s";
+ qcom,msm-dai-q6-mi2s-dev-id = <1>;
+ qcom,msm-mi2s-rx-lines = <2>;
+ qcom,msm-mi2s-tx-lines = <1>;
+ };
+
+ dai_mi2s: qcom,msm-dai-q6-mi2s-tert {
+ compatible = "qcom,msm-dai-q6-mi2s";
+ qcom,msm-dai-q6-mi2s-dev-id = <2>;
+ qcom,msm-mi2s-rx-lines = <2>;
+ qcom,msm-mi2s-tx-lines = <1>;
+ };
+
+ dai_mi2s_quat: qcom,msm-dai-q6-mi2s-quat {
+ compatible = "qcom,msm-dai-q6-mi2s";
+ qcom,msm-dai-q6-mi2s-dev-id = <3>;
+ qcom,msm-mi2s-rx-lines = <1>;
+ qcom,msm-mi2s-tx-lines = <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 = <4>;
+ qcom,msm-cpudai-tdm-group-port-id = <36896 36898 36900 36902>;
+ qcom,msm-cpudai-tdm-clk-rate = <0>;
+ 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 = <0>;
+ qcom,msm-cpudai-tdm-data-out = <0>;
+ qcom,msm-cpudai-tdm-invert-sync = <0>;
+ qcom,msm-cpudai-tdm-data-delay = <0>;
+ qcom,msm-cpudai-tdm-data-align = <0>;
+ };
+
+ dai_tert_tdm_rx_1: qcom,msm-dai-q6-tdm-tert-rx-1 {
+ compatible = "qcom,msm-dai-q6-tdm";
+ qcom,msm-cpudai-tdm-dev-id = <36898>;
+ qcom,msm-cpudai-tdm-sync-mode = <1>;
+ qcom,msm-cpudai-tdm-sync-src = <0>;
+ qcom,msm-cpudai-tdm-data-out = <0>;
+ qcom,msm-cpudai-tdm-invert-sync = <0>;
+ qcom,msm-cpudai-tdm-data-delay = <0>;
+ qcom,msm-cpudai-tdm-data-align = <0>;
+ };
+
+ dai_tert_tdm_rx_2: qcom,msm-dai-q6-tdm-tert-rx-2 {
+ compatible = "qcom,msm-dai-q6-tdm";
+ qcom,msm-cpudai-tdm-dev-id = <36900>;
+ qcom,msm-cpudai-tdm-sync-mode = <1>;
+ qcom,msm-cpudai-tdm-sync-src = <0>;
+ qcom,msm-cpudai-tdm-data-out = <0>;
+ qcom,msm-cpudai-tdm-invert-sync = <0>;
+ qcom,msm-cpudai-tdm-data-delay = <0>;
+ qcom,msm-cpudai-tdm-data-align = <0>;
+ };
+
+ dai_tert_tdm_rx_3: qcom,msm-dai-q6-tdm-tert-rx-3 {
+ compatible = "qcom,msm-dai-q6-tdm";
+ qcom,msm-cpudai-tdm-dev-id = <36902>;
+ qcom,msm-cpudai-tdm-sync-mode = <1>;
+ qcom,msm-cpudai-tdm-sync-src = <0>;
+ qcom,msm-cpudai-tdm-data-out = <0>;
+ qcom,msm-cpudai-tdm-invert-sync = <0>;
+ qcom,msm-cpudai-tdm-data-delay = <0>;
+ 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 = <4>;
+ qcom,msm-cpudai-tdm-group-port-id = <36897 36899 36901 36903>;
+ qcom,msm-cpudai-tdm-clk-rate = <0>;
+ 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 = <0>;
+ qcom,msm-cpudai-tdm-data-out = <0>;
+ qcom,msm-cpudai-tdm-invert-sync = <0>;
+ qcom,msm-cpudai-tdm-data-delay = <0>;
+ qcom,msm-cpudai-tdm-data-align = <0>;
+ };
+
+ dai_tert_tdm_tx_1: qcom,msm-dai-q6-tdm-tert-tx-1 {
+ compatible = "qcom,msm-dai-q6-tdm";
+ qcom,msm-cpudai-tdm-dev-id = <36899>;
+ qcom,msm-cpudai-tdm-sync-mode = <1>;
+ qcom,msm-cpudai-tdm-sync-src = <0>;
+ qcom,msm-cpudai-tdm-data-out = <0>;
+ qcom,msm-cpudai-tdm-invert-sync = <0>;
+ qcom,msm-cpudai-tdm-data-delay = <0>;
+ qcom,msm-cpudai-tdm-data-align = <0>;
+ };
+
+ dai_tert_tdm_tx_2: qcom,msm-dai-q6-tdm-tert-tx-2 {
+ compatible = "qcom,msm-dai-q6-tdm";
+ qcom,msm-cpudai-tdm-dev-id = <36901>;
+ qcom,msm-cpudai-tdm-sync-mode = <1>;
+ qcom,msm-cpudai-tdm-sync-src = <0>;
+ qcom,msm-cpudai-tdm-data-out = <0>;
+ qcom,msm-cpudai-tdm-invert-sync = <0>;
+ qcom,msm-cpudai-tdm-data-delay = <0>;
+ qcom,msm-cpudai-tdm-data-align = <0>;
+ };
+
+ dai_tert_tdm_tx_3: qcom,msm-dai-q6-tdm-tert-tx-3 {
+ compatible = "qcom,msm-dai-q6-tdm";
+ qcom,msm-cpudai-tdm-dev-id = <36903>;
+ qcom,msm-cpudai-tdm-sync-mode = <1>;
+ qcom,msm-cpudai-tdm-sync-src = <0>;
+ qcom,msm-cpudai-tdm-data-out = <0>;
+ qcom,msm-cpudai-tdm-invert-sync = <0>;
+ qcom,msm-cpudai-tdm-data-delay = <0>;
+ qcom,msm-cpudai-tdm-data-align = <0>;
+ };
+ };
+
+ qcom,msm-dai-tdm-quat-rx {
+ compatible = "qcom,msm-dai-tdm";
+ qcom,msm-cpudai-tdm-group-id = <37168>;
+ qcom,msm-cpudai-tdm-group-num-ports = <4>;
+ qcom,msm-cpudai-tdm-group-port-id = <36912 36914 36916 36918>;
+ qcom,msm-cpudai-tdm-clk-rate = <0>;
+ dai_quat_tdm_rx_0: qcom,msm-dai-q6-tdm-quat-rx-0 {
+ compatible = "qcom,msm-dai-q6-tdm";
+ qcom,msm-cpudai-tdm-dev-id = <36912>;
+ qcom,msm-cpudai-tdm-sync-mode = <1>;
+ qcom,msm-cpudai-tdm-sync-src = <0>;
+ qcom,msm-cpudai-tdm-data-out = <0>;
+ qcom,msm-cpudai-tdm-invert-sync = <0>;
+ qcom,msm-cpudai-tdm-data-delay = <0>;
+ qcom,msm-cpudai-tdm-data-align = <0>;
+ };
+
+ dai_quat_tdm_rx_1: qcom,msm-dai-q6-tdm-quat-rx-1 {
+ compatible = "qcom,msm-dai-q6-tdm";
+ qcom,msm-cpudai-tdm-dev-id = <36914>;
+ qcom,msm-cpudai-tdm-sync-mode = <1>;
+ qcom,msm-cpudai-tdm-sync-src = <0>;
+ qcom,msm-cpudai-tdm-data-out = <0>;
+ qcom,msm-cpudai-tdm-invert-sync = <0>;
+ qcom,msm-cpudai-tdm-data-delay = <0>;
+ qcom,msm-cpudai-tdm-data-align = <0>;
+ };
+
+ dai_quat_tdm_rx_2: qcom,msm-dai-q6-tdm-quat-rx-2 {
+ compatible = "qcom,msm-dai-q6-tdm";
+ qcom,msm-cpudai-tdm-dev-id = <36916>;
+ qcom,msm-cpudai-tdm-sync-mode = <1>;
+ qcom,msm-cpudai-tdm-sync-src = <0>;
+ qcom,msm-cpudai-tdm-data-out = <0>;
+ qcom,msm-cpudai-tdm-invert-sync = <0>;
+ qcom,msm-cpudai-tdm-data-delay = <0>;
+ qcom,msm-cpudai-tdm-data-align = <0>;
+ };
+
+ dai_quat_tdm_rx_3: qcom,msm-dai-q6-tdm-quat-rx-3 {
+ compatible = "qcom,msm-dai-q6-tdm";
+ qcom,msm-cpudai-tdm-dev-id = <36918>;
+ qcom,msm-cpudai-tdm-sync-mode = <1>;
+ qcom,msm-cpudai-tdm-sync-src = <0>;
+ qcom,msm-cpudai-tdm-data-out = <0>;
+ qcom,msm-cpudai-tdm-invert-sync = <0>;
+ qcom,msm-cpudai-tdm-data-delay = <0>;
+ qcom,msm-cpudai-tdm-data-align = <0>;
+ };
+ };
+
+ qcom,msm-dai-tdm-quat-tx {
+ compatible = "qcom,msm-dai-tdm";
+ qcom,msm-cpudai-tdm-group-id = <37169>;
+ qcom,msm-cpudai-tdm-group-num-ports = <4>;
+ qcom,msm-cpudai-tdm-group-port-id = <36913 36915 36917 36919>;
+ qcom,msm-cpudai-tdm-clk-rate = <0>;
+ dai_quat_tdm_tx_0: qcom,msm-dai-q6-tdm-quat-tx-0 {
+ compatible = "qcom,msm-dai-q6-tdm";
+ qcom,msm-cpudai-tdm-dev-id = <36913>;
+ qcom,msm-cpudai-tdm-sync-mode = <1>;
+ qcom,msm-cpudai-tdm-sync-src = <0>;
+ qcom,msm-cpudai-tdm-data-out = <0>;
+ qcom,msm-cpudai-tdm-invert-sync = <0>;
+ qcom,msm-cpudai-tdm-data-delay = <0>;
+ qcom,msm-cpudai-tdm-data-align = <0>;
+ };
+
+ dai_quat_tdm_tx_1: qcom,msm-dai-q6-tdm-quat-tx-1 {
+ compatible = "qcom,msm-dai-q6-tdm";
+ qcom,msm-cpudai-tdm-dev-id = <36915>;
+ qcom,msm-cpudai-tdm-sync-mode = <1>;
+ qcom,msm-cpudai-tdm-sync-src = <0>;
+ qcom,msm-cpudai-tdm-data-out = <0>;
+ qcom,msm-cpudai-tdm-invert-sync = <0>;
+ qcom,msm-cpudai-tdm-data-delay = <0>;
+ qcom,msm-cpudai-tdm-data-align = <0>;
+ };
+
+ dai_quat_tdm_tx_2: qcom,msm-dai-q6-tdm-quat-tx-2 {
+ compatible = "qcom,msm-dai-q6-tdm";
+ qcom,msm-cpudai-tdm-dev-id = <36917>;
+ qcom,msm-cpudai-tdm-sync-mode = <1>;
+ qcom,msm-cpudai-tdm-sync-src = <0>;
+ qcom,msm-cpudai-tdm-data-out = <0>;
+ qcom,msm-cpudai-tdm-invert-sync = <0>;
+ qcom,msm-cpudai-tdm-data-delay = <0>;
+ qcom,msm-cpudai-tdm-data-align = <0>;
+ };
+
+ dai_quat_tdm_tx_3: qcom,msm-dai-q6-tdm-quat-tx-3 {
+ compatible = "qcom,msm-dai-q6-tdm";
+ qcom,msm-cpudai-tdm-dev-id = <36919>;
+ qcom,msm-cpudai-tdm-sync-mode = <1>;
+ qcom,msm-cpudai-tdm-sync-src = <0>;
+ qcom,msm-cpudai-tdm-data-out = <0>;
+ qcom,msm-cpudai-tdm-invert-sync = <0>;
+ qcom,msm-cpudai-tdm-data-delay = <0>;
+ qcom,msm-cpudai-tdm-data-align = <0>;
+ };
+ };
+
+ hostless: qcom,msm-pcm-hostless {
+ compatible = "qcom,msm-pcm-hostless";
+ };
+};
diff --git a/arch/arm/configs/msmcortex_defconfig b/arch/arm/configs/msmcortex_defconfig
index 1658cc992ee6..60a7cff4836d 100644
--- a/arch/arm/configs/msmcortex_defconfig
+++ b/arch/arm/configs/msmcortex_defconfig
@@ -224,7 +224,6 @@ CONFIG_ZRAM=y
CONFIG_BLK_DEV_LOOP=y
CONFIG_BLK_DEV_RAM=y
CONFIG_BLK_DEV_RAM_SIZE=8192
-CONFIG_UID_CPUTIME=y
CONFIG_MSM_ULTRASOUND=y
CONFIG_SCSI=y
CONFIG_BLK_DEV_SD=y
@@ -294,7 +293,6 @@ CONFIG_PINCTRL_SDM660=y
CONFIG_GPIO_SYSFS=y
CONFIG_GPIO_QPNP_PIN=y
CONFIG_POWER_SUPPLY=y
-CONFIG_QPNP_SMBCHARGER=y
CONFIG_SMB135X_CHARGER=y
CONFIG_SMB1351_USB_CHARGER=y
CONFIG_MSM_BCL_CTL=y
@@ -526,7 +524,6 @@ CONFIG_PANIC_ON_SCHED_BUG=y
CONFIG_PANIC_ON_RT_THROTTLING=y
CONFIG_SCHEDSTATS=y
CONFIG_SCHED_STACK_END_CHECK=y
-CONFIG_TIMER_STATS=y
# CONFIG_DEBUG_PREEMPT is not set
CONFIG_DEBUG_SPINLOCK=y
CONFIG_DEBUG_MUTEXES=y
diff --git a/arch/arm/configs/sdm660-perf_defconfig b/arch/arm/configs/sdm660-perf_defconfig
index fe6988ebbb53..43b6432118f0 100644
--- a/arch/arm/configs/sdm660-perf_defconfig
+++ b/arch/arm/configs/sdm660-perf_defconfig
@@ -635,7 +635,6 @@ CONFIG_PANIC_ON_SCHED_BUG=y
CONFIG_PANIC_ON_RT_THROTTLING=y
CONFIG_SCHEDSTATS=y
CONFIG_SCHED_STACK_END_CHECK=y
-CONFIG_TIMER_STATS=y
# CONFIG_DEBUG_PREEMPT is not set
CONFIG_IPC_LOGGING=y
CONFIG_FUNCTION_TRACER=y
diff --git a/arch/arm/configs/sdm660_defconfig b/arch/arm/configs/sdm660_defconfig
index 3942da1a768d..e3aa35da81ce 100644
--- a/arch/arm/configs/sdm660_defconfig
+++ b/arch/arm/configs/sdm660_defconfig
@@ -655,7 +655,6 @@ CONFIG_PANIC_ON_SCHED_BUG=y
CONFIG_PANIC_ON_RT_THROTTLING=y
CONFIG_SCHEDSTATS=y
CONFIG_SCHED_STACK_END_CHECK=y
-CONFIG_TIMER_STATS=y
# CONFIG_DEBUG_PREEMPT is not set
CONFIG_DEBUG_SPINLOCK=y
CONFIG_DEBUG_MUTEXES=y
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/arm/mm/dma-mapping.c b/arch/arm/mm/dma-mapping.c
index a25d6b0e22a4..7708d83f16ac 100644
--- a/arch/arm/mm/dma-mapping.c
+++ b/arch/arm/mm/dma-mapping.c
@@ -672,7 +672,7 @@ static void __free_from_contiguous(struct device *dev, struct page *page,
if (PageHighMem(page))
__dma_free_remap(cpu_addr, size, true);
else
- __dma_remap(page, size, PAGE_KERNEL, false);
+ __dma_remap(page, size, PAGE_KERNEL, true);
dma_release_from_contiguous(dev, page, size >> PAGE_SHIFT);
}
diff --git a/arch/arm64/Kconfig.debug b/arch/arm64/Kconfig.debug
index 2b9a966791d8..441005f88761 100644
--- a/arch/arm64/Kconfig.debug
+++ b/arch/arm64/Kconfig.debug
@@ -87,7 +87,6 @@ config DEBUG_ALIGN_RODATA
config FORCE_PAGES
bool "Force lowmem to be mapped with 4K pages"
- depends on !DEBUG_RODATA
help
There are some advanced debug features that can only be done when
memory is mapped with pages instead of sections. Enable this option
@@ -112,6 +111,7 @@ config FREE_PAGES_RDONLY
config KERNEL_TEXT_RDONLY
bool "Set kernel text section pages as read only"
depends on FREE_PAGES_RDONLY
+ depends on !DEBUG_RODATA
help
The kernel text pages are always mapped in the kernel.
This means that anyone can write to the page if they have
diff --git a/arch/arm64/configs/msm-auto-perf_defconfig b/arch/arm64/configs/msm-auto-perf_defconfig
index a42cc936e002..81fa3afa8cca 100644
--- a/arch/arm64/configs/msm-auto-perf_defconfig
+++ b/arch/arm64/configs/msm-auto-perf_defconfig
@@ -89,7 +89,9 @@ 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_LRO is not set
CONFIG_INET_DIAG_DESTROY=y
CONFIG_IPV6_ROUTER_PREF=y
@@ -217,21 +219,10 @@ CONFIG_SOCKEV_NLMCAST=y
CONFIG_CAN=y
CONFIG_CAN_RH850=y
CONFIG_BT=y
-CONFIG_BT_RFCOMM=y
-CONFIG_BT_RFCOMM_TTY=y
-CONFIG_BT_BNEP=y
-CONFIG_BT_BNEP_MC_FILTER=y
-CONFIG_BT_BNEP_PROTO_FILTER=y
-CONFIG_BT_HIDP=y
-# CONFIG_BT_HS is not set
-# CONFIG_BT_LE is not set
-# CONFIG_BT_DEBUGFS is not set
CONFIG_MSM_BT_POWER=y
CONFIG_BTFM_SLIM=y
CONFIG_BTFM_SLIM_WCN3990=y
CONFIG_CFG80211=y
-CONFIG_CFG80211_INTERNAL_REGDB=y
-# CONFIG_CFG80211_CRDA_SUPPORT is not set
CONFIG_RFKILL=y
CONFIG_IPC_ROUTER=y
CONFIG_IPC_ROUTER_SECURITY=y
@@ -273,27 +264,23 @@ CONFIG_RNDIS_IPA=y
CONFIG_PPP=y
CONFIG_PPP_BSDCOMP=y
CONFIG_PPP_DEFLATE=y
-CONFIG_PPP_FILTER=y
CONFIG_PPP_MPPE=y
-CONFIG_PPP_MULTILINK=y
-CONFIG_PPPOE=y
-CONFIG_PPPOL2TP=y
CONFIG_PPPOLAC=y
CONFIG_PPPOPNS=y
-CONFIG_PPP_ASYNC=y
-CONFIG_PPP_SYNC_TTY=y
CONFIG_USB_USBNET=y
CONFIG_WCNSS_MEM_PRE_ALLOC=y
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
CONFIG_INPUT_KEYRESET=y
CONFIG_KEYBOARD_GPIO=y
# CONFIG_INPUT_MOUSE is not set
+CONFIG_INPUT_JOYSTICK=y
CONFIG_INPUT_TOUCHSCREEN=y
CONFIG_TOUCHSCREEN_SYNAPTICS_DSX_CORE_v21=y
CONFIG_TOUCHSCREEN_SYNAPTICS_DSX_FW_UPDATE_v21=y
@@ -304,7 +291,6 @@ CONFIG_TOUCHSCREEN_GEN_VKEYS=y
CONFIG_INPUT_MISC=y
CONFIG_INPUT_HBTP_INPUT=y
CONFIG_INPUT_QPNP_POWER_ON=y
-CONFIG_INPUT_KEYCHORD=y
CONFIG_INPUT_UINPUT=y
CONFIG_INPUT_GPIO=y
# CONFIG_SERIO_SERPORT is not set
@@ -319,7 +305,6 @@ CONFIG_HW_RANDOM=y
CONFIG_HW_RANDOM_MSM_LEGACY=y
CONFIG_MSM_ADSPRPC=y
CONFIG_MSM_RDBG=m
-# CONFIG_ACPI_I2C_OPREGION is not set
CONFIG_I2C_CHARDEV=y
CONFIG_I2C_QUP=y
CONFIG_I2C_MSM_V2=y
@@ -356,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
@@ -428,7 +414,6 @@ CONFIG_HID_MAGICMOUSE=y
CONFIG_HID_MICROSOFT=y
CONFIG_HID_MULTITOUCH=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
@@ -437,7 +422,6 @@ CONFIG_USB_OHCI_HCD_PLATFORM=y
CONFIG_USB_STORAGE=y
CONFIG_USB_DWC3=y
CONFIG_USB_ISP1760=y
-CONFIG_USB_SERIAL=y
CONFIG_USB_QTI_KS_BRIDGE=y
CONFIG_NOP_USB_XCEIV=y
CONFIG_USB_MSM_SSPHY_QMP=y
@@ -445,7 +429,6 @@ CONFIG_MSM_QUSB_PHY=y
CONFIG_USB_ULPI=y
CONFIG_USB_GADGET=y
CONFIG_USB_GADGET_VBUS_DRAW=500
-CONFIG_USB_GADGET_STORAGE_NUM_BUFFERS=4
CONFIG_USB_CONFIGFS=y
CONFIG_USB_CONFIGFS_SERIAL=y
CONFIG_USB_CONFIGFS_NCM=y
@@ -470,11 +453,17 @@ CONFIG_MMC_TEST=y
CONFIG_MMC_SDHCI=y
CONFIG_MMC_SDHCI_PLTFM=y
CONFIG_MMC_SDHCI_MSM=y
+CONFIG_MMC_SPI=y
+CONFIG_MMC_DW=y
+CONFIG_MMC_DW_EXYNOS=y
CONFIG_MMC_CQ_HCI=y
CONFIG_LEDS_QPNP=y
CONFIG_LEDS_QPNP_FLASH_V2=y
CONFIG_LEDS_QPNP_WLED=y
+CONFIG_LEDS_SYSCON=y
CONFIG_LEDS_TRIGGERS=y
+CONFIG_LEDS_TRIGGER_HEARTBEAT=y
+CONFIG_LEDS_TRIGGER_CPU=y
CONFIG_SWITCH=y
CONFIG_RTC_CLASS=y
CONFIG_RTC_DRV_QPNP=y
@@ -500,6 +489,10 @@ 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_IPA_UT=y
CONFIG_GPIO_USB_DETECT=y
CONFIG_MSM_MHI=y
CONFIG_MSM_MHI_UCI=y
@@ -524,6 +517,7 @@ 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_MHI_XPRT=y
@@ -545,9 +539,12 @@ 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
@@ -567,6 +564,8 @@ CONFIG_QCOM_DEVFREQ_DEVBW=y
CONFIG_EXTCON=y
CONFIG_PWM=y
CONFIG_PWM_QPNP=y
+CONFIG_ARM_GIC_V3_ACL=y
+CONFIG_PHY_XGENE=y
CONFIG_ANDROID=y
CONFIG_ANDROID_BINDER_IPC=y
CONFIG_MSM_TZ_LOG=y
@@ -592,7 +591,6 @@ 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_DEBUG_BUGVERBOSE is not set
CONFIG_IPC_LOGGING=y
@@ -612,8 +610,8 @@ CONFIG_CORESIGHT_QPDI=y
CONFIG_CORESIGHT_SOURCE_DUMMY=y
CONFIG_PFK=y
CONFIG_SECURITY=y
-CONFIG_SECURITY_NETWORK=y
CONFIG_SECURITY_SELINUX=y
+CONFIG_SECURITY_SMACK=y
CONFIG_CRYPTO_ECHAINIV=y
CONFIG_CRYPTO_XCBC=y
CONFIG_CRYPTO_MD4=y
diff --git a/arch/arm64/configs/msm-auto_defconfig b/arch/arm64/configs/msm-auto_defconfig
index df5060eadd9c..70674f6043cf 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
@@ -615,7 +617,6 @@ CONFIG_PANIC_TIMEOUT=5
CONFIG_PANIC_ON_SCHED_BUG=y
CONFIG_PANIC_ON_RT_THROTTLING=y
CONFIG_SCHEDSTATS=y
-CONFIG_TIMER_STATS=y
CONFIG_DEBUG_SPINLOCK=y
CONFIG_DEBUG_MUTEXES=y
CONFIG_DEBUG_ATOMIC_SLEEP=y
@@ -636,7 +637,6 @@ CONFIG_PANIC_ON_DATA_CORRUPTION=y
CONFIG_ARM64_PTDUMP=y
CONFIG_DEBUG_SET_MODULE_RONX=y
CONFIG_FREE_PAGES_RDONLY=y
-CONFIG_KERNEL_TEXT_RDONLY=y
CONFIG_CORESIGHT=y
CONFIG_CORESIGHT_EVENT=y
CONFIG_CORESIGHT_LINK_AND_SINK_TMC=y
diff --git a/arch/arm64/configs/msm-perf_defconfig b/arch/arm64/configs/msm-perf_defconfig
index 3cd68ecf8634..acde18d2fe31 100644
--- a/arch/arm64/configs/msm-perf_defconfig
+++ b/arch/arm64/configs/msm-perf_defconfig
@@ -578,7 +578,6 @@ 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_DEBUG_BUGVERBOSE is not set
CONFIG_IPC_LOGGING=y
diff --git a/arch/arm64/configs/msm_defconfig b/arch/arm64/configs/msm_defconfig
index 80e737e5726c..f510f43427ce 100644
--- a/arch/arm64/configs/msm_defconfig
+++ b/arch/arm64/configs/msm_defconfig
@@ -601,7 +601,6 @@ CONFIG_PANIC_TIMEOUT=5
CONFIG_PANIC_ON_SCHED_BUG=y
CONFIG_PANIC_ON_RT_THROTTLING=y
CONFIG_SCHEDSTATS=y
-CONFIG_TIMER_STATS=y
CONFIG_DEBUG_SPINLOCK=y
CONFIG_DEBUG_MUTEXES=y
CONFIG_DEBUG_ATOMIC_SLEEP=y
@@ -622,7 +621,6 @@ CONFIG_PANIC_ON_DATA_CORRUPTION=y
CONFIG_ARM64_PTDUMP=y
CONFIG_DEBUG_SET_MODULE_RONX=y
CONFIG_FREE_PAGES_RDONLY=y
-CONFIG_KERNEL_TEXT_RDONLY=y
CONFIG_PFK=y
CONFIG_SECURITY=y
CONFIG_SECURITY_SELINUX=y
diff --git a/arch/arm64/configs/msmcortex-perf_defconfig b/arch/arm64/configs/msmcortex-perf_defconfig
index a5c58dc66191..6ee2f4003574 100644
--- a/arch/arm64/configs/msmcortex-perf_defconfig
+++ b/arch/arm64/configs/msmcortex-perf_defconfig
@@ -65,12 +65,12 @@ 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_ARM64_SW_TTBR0_PAN=y
CONFIG_RANDOMIZE_BASE=y
# CONFIG_RANDOMIZE_MODULE_REGION_FULL is not set
# CONFIG_EFI is not set
@@ -621,7 +621,6 @@ 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
diff --git a/arch/arm64/configs/msmcortex_defconfig b/arch/arm64/configs/msmcortex_defconfig
index 7a82377302fe..bbe23b823b5d 100644
--- a/arch/arm64/configs/msmcortex_defconfig
+++ b/arch/arm64/configs/msmcortex_defconfig
@@ -71,6 +71,7 @@ CONFIG_ARMV8_DEPRECATED=y
CONFIG_SWP_EMULATION=y
CONFIG_CP15_BARRIER_EMULATION=y
CONFIG_SETEND_EMULATION=y
+CONFIG_ARM64_SW_TTBR0_PAN=y
CONFIG_RANDOMIZE_BASE=y
CONFIG_BUILD_ARM64_APPENDED_DTB_IMAGE=y
# CONFIG_CORE_DUMP_DEFAULT_ELF_HEADERS is not set
@@ -262,6 +263,7 @@ CONFIG_SCSI_UFSHCD=y
CONFIG_SCSI_UFSHCD_PLATFORM=y
CONFIG_SCSI_UFS_QCOM=y
CONFIG_SCSI_UFS_QCOM_ICE=y
+CONFIG_SCSI_UFSHCD_CMD_LOGGING=y
CONFIG_MD=y
CONFIG_BLK_DEV_MD=y
CONFIG_MD_LINEAR=y
@@ -672,7 +674,6 @@ CONFIG_PANIC_ON_SCHED_BUG=y
CONFIG_PANIC_ON_RT_THROTTLING=y
CONFIG_SCHEDSTATS=y
CONFIG_SCHED_STACK_END_CHECK=y
-CONFIG_TIMER_STATS=y
# CONFIG_DEBUG_PREEMPT is not set
CONFIG_DEBUG_SPINLOCK=y
CONFIG_DEBUG_MUTEXES=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..953d700c20cc
--- /dev/null
+++ b/arch/arm64/configs/msmcortex_mediabox-perf_defconfig
@@ -0,0 +1,641 @@
+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_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/arm64/configs/msmcortex_mediabox_defconfig b/arch/arm64/configs/msmcortex_mediabox_defconfig
index 28d900cf5b18..d81c10d11318 100644
--- a/arch/arm64/configs/msmcortex_mediabox_defconfig
+++ b/arch/arm64/configs/msmcortex_mediabox_defconfig
@@ -638,7 +638,6 @@ CONFIG_PANIC_ON_SCHED_BUG=y
CONFIG_PANIC_ON_RT_THROTTLING=y
CONFIG_SCHEDSTATS=y
CONFIG_SCHED_STACK_END_CHECK=y
-CONFIG_TIMER_STATS=y
# CONFIG_DEBUG_PREEMPT is not set
CONFIG_DEBUG_SPINLOCK=y
CONFIG_DEBUG_MUTEXES=y
diff --git a/arch/arm64/configs/sdm660-perf_defconfig b/arch/arm64/configs/sdm660-perf_defconfig
index b75b4244aa72..939b34f7d6dd 100644
--- a/arch/arm64/configs/sdm660-perf_defconfig
+++ b/arch/arm64/configs/sdm660-perf_defconfig
@@ -545,7 +545,6 @@ CONFIG_MSM_QMI_INTERFACE=y
CONFIG_MSM_RPM_SMD=y
CONFIG_QCOM_BUS_SCALING=y
CONFIG_MSM_SERVICE_LOCATOR=y
-CONFIG_QCOM_DCC=y
CONFIG_MSM_IPC_ROUTER_SMD_XPRT=y
CONFIG_MSM_SYSMON_GLINK_COMM=y
CONFIG_MSM_IPC_ROUTER_GLINK_XPRT=y
@@ -619,7 +618,6 @@ 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
diff --git a/arch/arm64/configs/sdm660_defconfig b/arch/arm64/configs/sdm660_defconfig
index 3fe9e2bda6d2..aafde733099b 100644
--- a/arch/arm64/configs/sdm660_defconfig
+++ b/arch/arm64/configs/sdm660_defconfig
@@ -668,7 +668,6 @@ CONFIG_PANIC_ON_SCHED_BUG=y
CONFIG_PANIC_ON_RT_THROTTLING=y
CONFIG_SCHEDSTATS=y
CONFIG_SCHED_STACK_END_CHECK=y
-CONFIG_TIMER_STATS=y
# CONFIG_DEBUG_PREEMPT is not set
CONFIG_DEBUG_SPINLOCK=y
CONFIG_DEBUG_MUTEXES=y
diff --git a/arch/arm64/include/asm/exec.h b/arch/arm64/include/asm/exec.h
index db0563c23482..f7865dd9d868 100644
--- a/arch/arm64/include/asm/exec.h
+++ b/arch/arm64/include/asm/exec.h
@@ -18,6 +18,9 @@
#ifndef __ASM_EXEC_H
#define __ASM_EXEC_H
+#include <linux/sched.h>
+
extern unsigned long arch_align_stack(unsigned long sp);
+void uao_thread_switch(struct task_struct *next);
#endif /* __ASM_EXEC_H */
diff --git a/arch/arm64/kernel/process.c b/arch/arm64/kernel/process.c
index 5a09efa75722..fc0a7aa2ca82 100644
--- a/arch/arm64/kernel/process.c
+++ b/arch/arm64/kernel/process.c
@@ -49,6 +49,7 @@
#include <asm/alternative.h>
#include <asm/compat.h>
#include <asm/cacheflush.h>
+#include <asm/exec.h>
#include <asm/fpsimd.h>
#include <asm/mmu_context.h>
#include <asm/processor.h>
@@ -383,7 +384,7 @@ static void tls_thread_switch(struct task_struct *next)
}
/* Restore the UAO state depending on next's addr_limit */
-static void uao_thread_switch(struct task_struct *next)
+void uao_thread_switch(struct task_struct *next)
{
if (IS_ENABLED(CONFIG_ARM64_UAO)) {
if (task_thread_info(next)->addr_limit == KERNEL_DS)
diff --git a/arch/arm64/kernel/suspend.c b/arch/arm64/kernel/suspend.c
index 5a0b1088c17c..0acdb63d19b6 100644
--- a/arch/arm64/kernel/suspend.c
+++ b/arch/arm64/kernel/suspend.c
@@ -5,6 +5,7 @@
#include <asm/cacheflush.h>
#include <asm/cpufeature.h>
#include <asm/debug-monitors.h>
+#include <asm/exec.h>
#include <asm/pgtable.h>
#include <asm/memory.h>
#include <asm/mmu_context.h>
@@ -95,6 +96,7 @@ int cpu_suspend(unsigned long arg, int (*fn)(unsigned long))
*/
asm(ALTERNATIVE("nop", SET_PSTATE_PAN(1), ARM64_HAS_PAN,
CONFIG_ARM64_PAN));
+ uao_thread_switch(current);
/*
* Restore HW breakpoint registers to sane values
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/block/drbd/drbd_bitmap.c b/drivers/block/drbd/drbd_bitmap.c
index 9462d2752850..8bdc34dbaedf 100644
--- a/drivers/block/drbd/drbd_bitmap.c
+++ b/drivers/block/drbd/drbd_bitmap.c
@@ -479,8 +479,14 @@ void drbd_bm_cleanup(struct drbd_device *device)
* this masks out the remaining bits.
* Returns the number of bits cleared.
*/
+#ifndef BITS_PER_PAGE
#define BITS_PER_PAGE (1UL << (PAGE_SHIFT + 3))
#define BITS_PER_PAGE_MASK (BITS_PER_PAGE - 1)
+#else
+# if BITS_PER_PAGE != (1UL << (PAGE_SHIFT + 3))
+# error "ambiguous BITS_PER_PAGE"
+# endif
+#endif
#define BITS_PER_LONG_MASK (BITS_PER_LONG - 1)
static int bm_clear_surplus(struct drbd_bitmap *b)
{
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.h b/drivers/bluetooth/btfm_slim.h
index 5d105fba2193..e67c6964ee65 100644
--- a/drivers/bluetooth/btfm_slim.h
+++ b/drivers/bluetooth/btfm_slim.h
@@ -13,7 +13,7 @@
#define BTFM_SLIM_H
#include <linux/slimbus/slimbus.h>
-#define BTFMSLIM_DBG(fmt, arg...) pr_debug(fmt "\n", ## arg)
+#define BTFMSLIM_DBG(fmt, arg...) pr_debug("%s: " fmt "\n", __func__, ## arg)
#define BTFMSLIM_INFO(fmt, arg...) pr_info("%s: " fmt "\n", __func__, ## arg)
#define BTFMSLIM_ERR(fmt, arg...) pr_err("%s: " fmt "\n", __func__, ## arg)
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/bluetooth/btfm_slim_wcn3990.c b/drivers/bluetooth/btfm_slim_wcn3990.c
index c93b29281e35..a451ff33103c 100644
--- a/drivers/bluetooth/btfm_slim_wcn3990.c
+++ b/drivers/bluetooth/btfm_slim_wcn3990.c
@@ -83,19 +83,34 @@ int btfm_slim_chrk_enable_port(struct btfmslim *btfmslim, uint8_t port_num,
{
int ret = 0;
uint8_t reg_val = 0;
+ uint8_t port_bit = 0;
uint16_t reg;
BTFMSLIM_DBG("port(%d) enable(%d)", port_num, enable);
if (rxport) {
+ if (enable) {
+ /* For SCO Rx, A2DP Rx */
+ reg_val = 0x1;
+ port_bit = port_num - 0x10;
+ reg = CHRK_SB_PGD_RX_PORTn_MULTI_CHNL_0(port_bit);
+ BTFMSLIM_DBG("writing reg_val (%d) to reg(%x)",
+ reg_val, reg);
+ ret = btfm_slim_write(btfmslim, reg, 1, &reg_val, IFD);
+ if (ret) {
+ BTFMSLIM_ERR("failed to write (%d) reg 0x%x",
+ ret, reg);
+ goto error;
+ }
+ }
/* Port enable */
reg = CHRK_SB_PGD_PORT_RX_CFGN(port_num - 0x10);
goto enable_disable_rxport;
}
- /* txport */
if (!enable)
goto enable_disable_txport;
- /* Multiple Channel Setting - only for FM Tx */
+ /* txport */
+ /* Multiple Channel Setting */
if (is_fm_port(port_num)) {
reg_val = (0x1 << CHRK_SB_PGD_PORT_TX1_FM) |
(0x1 << CHRK_SB_PGD_PORT_TX2_FM);
@@ -105,6 +120,18 @@ int btfm_slim_chrk_enable_port(struct btfmslim *btfmslim, uint8_t port_num,
BTFMSLIM_ERR("failed to write (%d) reg 0x%x", ret, reg);
goto error;
}
+ } else if (port_num == CHRK_SB_PGD_PORT_TX_SCO) {
+ /* SCO Tx */
+ reg_val = 0x1 << CHRK_SB_PGD_PORT_TX_SCO;
+ reg = CHRK_SB_PGD_TX_PORTn_MULTI_CHNL_0(port_num);
+ BTFMSLIM_DBG("writing reg_val (%d) to reg(%x)",
+ reg_val, reg);
+ ret = btfm_slim_write(btfmslim, reg, 1, &reg_val, IFD);
+ if (ret) {
+ BTFMSLIM_ERR("failed to write (%d) reg 0x%x",
+ ret, reg);
+ goto error;
+ }
}
/* Enable Tx port hw auto recovery for underrun or overrun error */
diff --git a/drivers/char/adsprpc.c b/drivers/char/adsprpc.c
index 7e44b38bbfca..1b76f58809b3 100644
--- a/drivers/char/adsprpc.c
+++ b/drivers/char/adsprpc.c
@@ -1488,14 +1488,15 @@ static int fastrpc_internal_invoke(struct fastrpc_file *fl, uint32_t mode,
int err = 0;
struct timespec invoket;
+ if (fl->profile)
+ getnstimeofday(&invoket);
+
VERIFY(err, fl->sctx);
if (err)
goto bail;
VERIFY(err, fl->cid >= 0 && fl->cid < NUM_CHANNELS);
if (err)
goto bail;
- if (fl->profile)
- getnstimeofday(&invoket);
if (!kernel) {
VERIFY(err, 0 == context_restore_interrupted(fl, inv,
&ctx));
@@ -1584,6 +1585,7 @@ static int fastrpc_init_process(struct fastrpc_file *fl,
struct fastrpc_ioctl_init *init = &uproc->init;
struct smq_phy_page pages[1];
struct fastrpc_mmap *file = 0, *mem = 0;
+ char *proc_name = NULL;
int srcVM[1] = {VMID_HLOS};
int destVM[1] = {VMID_ADSP_Q6};
int destVMperm[1] = {PERM_READ | PERM_WRITE | PERM_EXEC};
@@ -1679,12 +1681,18 @@ static int fastrpc_init_process(struct fastrpc_file *fl,
uint64_t phys = 0;
ssize_t size = 0;
int fds[3];
- char *proc_name = (unsigned char *)init->file;
struct {
int pgid;
int namelen;
int pageslen;
} inbuf;
+ VERIFY(err, proc_name = kzalloc(init->filelen, GFP_KERNEL));
+ if (err)
+ goto bail;
+ VERIFY(err, 0 == copy_from_user(proc_name,
+ (unsigned char *)init->file, init->filelen));
+ if (err)
+ goto bail;
inbuf.pgid = current->tgid;
inbuf.namelen = strlen(proc_name)+1;
inbuf.pageslen = 0;
@@ -1737,6 +1745,7 @@ static int fastrpc_init_process(struct fastrpc_file *fl,
err = -ENOTTY;
}
bail:
+ kfree(proc_name);
if (err && (init->flags == FASTRPC_INIT_CREATE_STATIC))
me->staticpd_flags = 0;
if (mem && err) {
@@ -2126,11 +2135,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 +2303,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;
@@ -2443,6 +2449,9 @@ static int fastrpc_channel_open(struct fastrpc_file *fl)
if (err)
goto bail;
cid = fl->cid;
+ VERIFY(err, cid >= 0 && cid < NUM_CHANNELS);
+ if (err)
+ goto bail;
if (me->channel[cid].ssrcount !=
me->channel[cid].prevssrcount) {
if (!me->channel[cid].issubsystemup) {
@@ -2451,14 +2460,13 @@ static int fastrpc_channel_open(struct fastrpc_file *fl)
goto bail;
}
}
- VERIFY(err, cid >= 0 && cid < NUM_CHANNELS);
- if (err)
- goto bail;
fl->ssrcount = me->channel[cid].ssrcount;
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/diag_masks.c b/drivers/char/diag/diag_masks.c
index 3c10462c2274..382717bad828 100644
--- a/drivers/char/diag/diag_masks.c
+++ b/drivers/char/diag/diag_masks.c
@@ -309,10 +309,12 @@ static void diag_send_msg_mask_update(uint8_t peripheral, int first, int last)
if (!mask_info || !mask_info->ptr || !mask_info->update_buf)
return;
-
+ mutex_lock(&driver->msg_mask_lock);
mask = (struct diag_msg_mask_t *)mask_info->ptr;
- if (!mask->ptr)
+ if (!mask->ptr) {
+ mutex_unlock(&driver->msg_mask_lock);
return;
+ }
buf = mask_info->update_buf;
mutex_lock(&mask_info->lock);
switch (mask_info->status) {
@@ -385,6 +387,7 @@ proceed:
}
err:
mutex_unlock(&mask_info->lock);
+ mutex_unlock(&driver->msg_mask_lock);
}
static void diag_send_time_sync_update(uint8_t peripheral)
@@ -506,7 +509,7 @@ static int diag_cmd_get_ssid_range(unsigned char *src_buf, int src_len,
if (!diag_apps_responds())
return 0;
-
+ mutex_lock(&driver->msg_mask_lock);
rsp.cmd_code = DIAG_CMD_MSG_CONFIG;
rsp.sub_cmd = DIAG_CMD_OP_GET_SSID_RANGE;
rsp.status = MSG_STATUS_SUCCESS;
@@ -514,7 +517,6 @@ static int diag_cmd_get_ssid_range(unsigned char *src_buf, int src_len,
rsp.count = driver->msg_mask_tbl_count;
memcpy(dest_buf, &rsp, sizeof(rsp));
write_len += sizeof(rsp);
-
mask_ptr = (struct diag_msg_mask_t *)mask_info->ptr;
for (i = 0; i < driver->msg_mask_tbl_count; i++, mask_ptr++) {
if (write_len + sizeof(ssid_range) > dest_len) {
@@ -527,7 +529,7 @@ static int diag_cmd_get_ssid_range(unsigned char *src_buf, int src_len,
memcpy(dest_buf + write_len, &ssid_range, sizeof(ssid_range));
write_len += sizeof(ssid_range);
}
-
+ mutex_unlock(&driver->msg_mask_lock);
return write_len;
}
@@ -551,7 +553,7 @@ static int diag_cmd_get_build_mask(unsigned char *src_buf, int src_len,
if (!diag_apps_responds())
return 0;
-
+ mutex_lock(&driver->msg_mask_lock);
req = (struct diag_build_mask_req_t *)src_buf;
rsp.cmd_code = DIAG_CMD_MSG_CONFIG;
rsp.sub_cmd = DIAG_CMD_OP_GET_BUILD_MASK;
@@ -559,9 +561,8 @@ static int diag_cmd_get_build_mask(unsigned char *src_buf, int src_len,
rsp.ssid_last = req->ssid_last;
rsp.status = MSG_STATUS_FAIL;
rsp.padding = 0;
-
build_mask = (struct diag_msg_mask_t *)msg_bt_mask.ptr;
- for (i = 0; i < driver->msg_mask_tbl_count; i++, build_mask++) {
+ for (i = 0; i < driver->bt_msg_mask_tbl_count; i++, build_mask++) {
if (build_mask->ssid_first != req->ssid_first)
continue;
num_entries = req->ssid_last - req->ssid_first + 1;
@@ -582,7 +583,7 @@ static int diag_cmd_get_build_mask(unsigned char *src_buf, int src_len,
}
memcpy(dest_buf, &rsp, sizeof(rsp));
write_len += sizeof(rsp);
-
+ mutex_unlock(&driver->msg_mask_lock);
return write_len;
}
@@ -610,6 +611,7 @@ static int diag_cmd_get_msg_mask(unsigned char *src_buf, int src_len,
if (!diag_apps_responds())
return 0;
+ mutex_lock(&driver->msg_mask_lock);
req = (struct diag_build_mask_req_t *)src_buf;
rsp.cmd_code = DIAG_CMD_MSG_CONFIG;
rsp.sub_cmd = DIAG_CMD_OP_GET_MSG_MASK;
@@ -617,7 +619,6 @@ static int diag_cmd_get_msg_mask(unsigned char *src_buf, int src_len,
rsp.ssid_last = req->ssid_last;
rsp.status = MSG_STATUS_FAIL;
rsp.padding = 0;
-
mask = (struct diag_msg_mask_t *)mask_info->ptr;
for (i = 0; i < driver->msg_mask_tbl_count; i++, mask++) {
if ((req->ssid_first < mask->ssid_first) ||
@@ -635,7 +636,7 @@ static int diag_cmd_get_msg_mask(unsigned char *src_buf, int src_len,
}
memcpy(dest_buf, &rsp, sizeof(rsp));
write_len += sizeof(rsp);
-
+ mutex_unlock(&driver->msg_mask_lock);
return write_len;
}
@@ -666,7 +667,7 @@ static int diag_cmd_set_msg_mask(unsigned char *src_buf, int src_len,
}
req = (struct diag_msg_build_mask_t *)src_buf;
-
+ mutex_lock(&driver->msg_mask_lock);
mutex_lock(&mask_info->lock);
mask = (struct diag_msg_mask_t *)mask_info->ptr;
for (i = 0; i < driver->msg_mask_tbl_count; i++, mask++) {
@@ -726,7 +727,7 @@ static int diag_cmd_set_msg_mask(unsigned char *src_buf, int src_len,
break;
}
mutex_unlock(&mask_info->lock);
-
+ mutex_unlock(&driver->msg_mask_lock);
if (diag_check_update(APPS_DATA))
diag_update_userspace_clients(MSG_MASKS_TYPE);
@@ -779,7 +780,7 @@ static int diag_cmd_set_all_msg_mask(unsigned char *src_buf, int src_len,
}
req = (struct diag_msg_config_rsp_t *)src_buf;
-
+ mutex_lock(&driver->msg_mask_lock);
mask = (struct diag_msg_mask_t *)mask_info->ptr;
mutex_lock(&mask_info->lock);
mask_info->status = (req->rt_mask) ? DIAG_CTRL_MASK_ALL_ENABLED :
@@ -791,6 +792,7 @@ static int diag_cmd_set_all_msg_mask(unsigned char *src_buf, int src_len,
mutex_unlock(&mask->lock);
}
mutex_unlock(&mask_info->lock);
+ mutex_unlock(&driver->msg_mask_lock);
if (diag_check_update(APPS_DATA))
diag_update_userspace_clients(MSG_MASKS_TYPE);
@@ -1294,6 +1296,7 @@ static int diag_create_msg_mask_table(void)
struct diag_msg_mask_t *mask = (struct diag_msg_mask_t *)msg_mask.ptr;
struct diag_ssid_range_t range;
+ mutex_lock(&driver->msg_mask_lock);
mutex_lock(&msg_mask.lock);
driver->msg_mask_tbl_count = MSG_MASK_TBL_CNT;
for (i = 0; i < driver->msg_mask_tbl_count; i++, mask++) {
@@ -1304,6 +1307,7 @@ static int diag_create_msg_mask_table(void)
break;
}
mutex_unlock(&msg_mask.lock);
+ mutex_unlock(&driver->msg_mask_lock);
return err;
}
@@ -1316,9 +1320,11 @@ static int diag_create_build_time_mask(void)
struct diag_msg_mask_t *build_mask = NULL;
struct diag_ssid_range_t range;
+ mutex_lock(&driver->msg_mask_lock);
mutex_lock(&msg_bt_mask.lock);
+ driver->bt_msg_mask_tbl_count = MSG_MASK_TBL_CNT;
build_mask = (struct diag_msg_mask_t *)msg_bt_mask.ptr;
- for (i = 0; i < driver->msg_mask_tbl_count; i++, build_mask++) {
+ for (i = 0; i < driver->bt_msg_mask_tbl_count; i++, build_mask++) {
range.ssid_first = msg_mask_tbl[i].ssid_first;
range.ssid_last = msg_mask_tbl[i].ssid_last;
err = diag_create_msg_mask_table_entry(build_mask, &range);
@@ -1429,6 +1435,7 @@ static int diag_create_build_time_mask(void)
memcpy(build_mask->ptr, tbl, tbl_size);
}
mutex_unlock(&msg_bt_mask.lock);
+ mutex_unlock(&driver->msg_mask_lock);
return err;
}
@@ -1576,10 +1583,11 @@ static int diag_msg_mask_init(void)
pr_err("diag: Unable to create msg masks, err: %d\n", err);
return err;
}
+ mutex_lock(&driver->msg_mask_lock);
driver->msg_mask = &msg_mask;
-
for (i = 0; i < NUM_PERIPHERALS; i++)
driver->max_ssid_count[i] = 0;
+ mutex_unlock(&driver->msg_mask_lock);
return 0;
}
@@ -1598,7 +1606,7 @@ int diag_msg_mask_copy(struct diag_mask_info *dest, struct diag_mask_info *src)
err = __diag_mask_init(dest, MSG_MASK_SIZE, APPS_BUF_SIZE);
if (err)
return err;
-
+ mutex_lock(&driver->msg_mask_lock);
mutex_lock(&dest->lock);
src_mask = (struct diag_msg_mask_t *)src->ptr;
dest_mask = (struct diag_msg_mask_t *)dest->ptr;
@@ -1617,6 +1625,7 @@ int diag_msg_mask_copy(struct diag_mask_info *dest, struct diag_mask_info *src)
dest_mask++;
}
mutex_unlock(&dest->lock);
+ mutex_unlock(&driver->msg_mask_lock);
return err;
}
@@ -1628,7 +1637,7 @@ void diag_msg_mask_free(struct diag_mask_info *mask_info)
if (!mask_info)
return;
-
+ mutex_lock(&driver->msg_mask_lock);
mutex_lock(&mask_info->lock);
mask = (struct diag_msg_mask_t *)mask_info->ptr;
for (i = 0; i < driver->msg_mask_tbl_count; i++, mask++) {
@@ -1636,7 +1645,7 @@ void diag_msg_mask_free(struct diag_mask_info *mask_info)
mask->ptr = NULL;
}
mutex_unlock(&mask_info->lock);
-
+ mutex_unlock(&driver->msg_mask_lock);
__diag_mask_exit(mask_info);
}
@@ -1644,15 +1653,17 @@ static void diag_msg_mask_exit(void)
{
int i;
struct diag_msg_mask_t *mask = NULL;
-
+ mutex_lock(&driver->msg_mask_lock);
mask = (struct diag_msg_mask_t *)(msg_mask.ptr);
if (mask) {
for (i = 0; i < driver->msg_mask_tbl_count; i++, mask++)
kfree(mask->ptr);
kfree(msg_mask.ptr);
+ msg_mask.ptr = NULL;
}
-
kfree(msg_mask.update_buf);
+ msg_mask.update_buf = NULL;
+ mutex_unlock(&driver->msg_mask_lock);
}
static int diag_build_time_mask_init(void)
@@ -1677,13 +1688,15 @@ static void diag_build_time_mask_exit(void)
{
int i;
struct diag_msg_mask_t *mask = NULL;
-
+ mutex_lock(&driver->msg_mask_lock);
mask = (struct diag_msg_mask_t *)(msg_bt_mask.ptr);
if (mask) {
- for (i = 0; i < driver->msg_mask_tbl_count; i++, mask++)
+ for (i = 0; i < driver->bt_msg_mask_tbl_count; i++, mask++)
kfree(mask->ptr);
- kfree(msg_mask.ptr);
+ kfree(msg_bt_mask.ptr);
+ msg_bt_mask.ptr = NULL;
}
+ mutex_unlock(&driver->msg_mask_lock);
}
static int diag_log_mask_init(void)
@@ -1801,7 +1814,7 @@ int diag_copy_to_user_msg_mask(char __user *buf, size_t count,
return -EIO;
}
mutex_unlock(&driver->diag_maskclear_mutex);
-
+ mutex_lock(&driver->msg_mask_lock);
mutex_lock(&mask_info->lock);
mask = (struct diag_msg_mask_t *)(mask_info->ptr);
for (i = 0; i < driver->msg_mask_tbl_count; i++, mask++) {
@@ -1840,7 +1853,7 @@ int diag_copy_to_user_msg_mask(char __user *buf, size_t count,
total_len += len;
}
mutex_unlock(&mask_info->lock);
-
+ mutex_unlock(&driver->msg_mask_lock);
return err ? err : total_len;
}
diff --git a/drivers/char/diag/diag_memorydevice.c b/drivers/char/diag/diag_memorydevice.c
index bd34e6cceec0..a5d92c51cc0b 100644
--- a/drivers/char/diag/diag_memorydevice.c
+++ b/drivers/char/diag/diag_memorydevice.c
@@ -252,6 +252,7 @@ int diag_md_copy_to_user(char __user *buf, int *pret, size_t buf_size,
uint8_t drain_again = 0;
uint8_t peripheral = 0;
struct diag_md_session_t *session_info = NULL;
+ struct pid *pid_struct = NULL;
mutex_lock(&driver->diagfwd_untag_mutex);
@@ -278,6 +279,14 @@ int diag_md_copy_to_user(char __user *buf, int *pret, size_t buf_size,
if ((info && (info->peripheral_mask &
MD_PERIPHERAL_MASK(peripheral)) == 0))
goto drop_data;
+ pid_struct = find_get_pid(session_info->pid);
+ if (!pid_struct) {
+ err = -ESRCH;
+ DIAG_LOG(DIAG_DEBUG_PERIPHERALS,
+ "diag: No such md_session_map[%d] with pid = %d err=%d exists..\n",
+ peripheral, session_info->pid, err);
+ goto drop_data;
+ }
/*
* If the data is from remote processor, copy the remote
* token first
@@ -297,27 +306,35 @@ int diag_md_copy_to_user(char __user *buf, int *pret, size_t buf_size,
}
if (i > 0) {
remote_token = diag_get_remote(i);
- err = copy_to_user(buf + ret, &remote_token,
- sizeof(int));
+ if (get_pid_task(pid_struct, PIDTYPE_PID)) {
+ err = copy_to_user(buf + ret,
+ &remote_token,
+ sizeof(int));
+ if (err)
+ goto drop_data;
+ ret += sizeof(int);
+ }
+ }
+
+ /* Copy the length of data being passed */
+ if (get_pid_task(pid_struct, PIDTYPE_PID)) {
+ err = copy_to_user(buf + ret,
+ (void *)&(entry->len),
+ sizeof(int));
if (err)
goto drop_data;
ret += sizeof(int);
}
- /* Copy the length of data being passed */
- err = copy_to_user(buf + ret, (void *)&(entry->len),
- sizeof(int));
- if (err)
- goto drop_data;
- ret += sizeof(int);
-
/* Copy the actual data being passed */
- err = copy_to_user(buf + ret, (void *)entry->buf,
- entry->len);
- if (err)
- goto drop_data;
- ret += entry->len;
-
+ if (get_pid_task(pid_struct, PIDTYPE_PID)) {
+ err = copy_to_user(buf + ret,
+ (void *)entry->buf,
+ entry->len);
+ if (err)
+ goto drop_data;
+ ret += entry->len;
+ }
/*
* The data is now copied to the user space client,
* Notify that the write is complete and delete its
@@ -339,7 +356,15 @@ drop_data:
}
*pret = ret;
- err = copy_to_user(buf + sizeof(int), (void *)&num_data, sizeof(int));
+ if (pid_struct && get_pid_task(pid_struct, PIDTYPE_PID)) {
+ err = copy_to_user(buf + sizeof(int),
+ (void *)&num_data,
+ sizeof(int));
+ } else {
+ DIAG_LOG(DIAG_DEBUG_PERIPHERALS,
+ "diag: md_session_map[%d] with pid = %d Exited..\n",
+ peripheral, driver->md_session_map[peripheral]->pid);
+ }
diag_ws_on_copy_complete(DIAG_WS_MUX);
if (drain_again)
chk_logging_wakeup();
diff --git a/drivers/char/diag/diag_mux.c b/drivers/char/diag/diag_mux.c
index 39f4b08d9b0a..d6f6ea7af8ea 100644
--- a/drivers/char/diag/diag_mux.c
+++ b/drivers/char/diag/diag_mux.c
@@ -153,8 +153,13 @@ int diag_mux_write(int proc, unsigned char *buf, int len, int ctx)
upd = PERIPHERAL_CDSP;
break;
case UPD_WLAN:
+ if (!driver->num_pd_session)
+ upd = PERIPHERAL_MODEM;
+ break;
case UPD_AUDIO:
case UPD_SENSORS:
+ if (!driver->num_pd_session)
+ upd = PERIPHERAL_LPASS;
break;
default:
pr_err("diag: invalid pd ctxt= %d\n", upd);
diff --git a/drivers/char/diag/diagchar.h b/drivers/char/diag/diagchar.h
index b17538a10ea9..4047a2c42bb7 100644
--- a/drivers/char/diag/diagchar.h
+++ b/drivers/char/diag/diagchar.h
@@ -627,8 +627,10 @@ struct diagchar_dev {
struct diag_mask_info *event_mask;
struct diag_mask_info *build_time_mask;
uint8_t msg_mask_tbl_count;
+ uint8_t bt_msg_mask_tbl_count;
uint16_t event_mask_size;
uint16_t last_event_id;
+ struct mutex msg_mask_lock;
/* Variables for Mask Centralization */
uint16_t num_event_id[NUM_PERIPHERALS];
uint32_t num_equip_id[NUM_PERIPHERALS];
diff --git a/drivers/char/diag/diagchar_core.c b/drivers/char/diag/diagchar_core.c
index 682c035c5bd4..60bfb2af49d0 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);
@@ -3568,6 +3570,7 @@ static int __init diagchar_init(void)
mutex_init(&driver->diag_file_mutex);
mutex_init(&driver->delayed_rsp_mutex);
mutex_init(&apps_data_mutex);
+ mutex_init(&driver->msg_mask_lock);
for (i = 0; i < NUM_PERIPHERALS; i++)
mutex_init(&driver->diagfwd_channel_mutex[i]);
mutex_init(&driver->diagfwd_untag_mutex);
diff --git a/drivers/char/diag/diagfwd_cntl.c b/drivers/char/diag/diagfwd_cntl.c
index 82a67f1f6f47..729fbf4fc145 100644
--- a/drivers/char/diag/diagfwd_cntl.c
+++ b/drivers/char/diag/diagfwd_cntl.c
@@ -548,6 +548,7 @@ static void process_ssid_range_report(uint8_t *buf, uint32_t len,
/* Don't account for pkt_id and length */
read_len += header_len - (2 * sizeof(uint32_t));
+ mutex_lock(&driver->msg_mask_lock);
driver->max_ssid_count[peripheral] = header->count;
for (i = 0; i < header->count && read_len < len; i++) {
ssid_range = (struct diag_ssid_range_t *)ptr;
@@ -591,6 +592,7 @@ static void process_ssid_range_report(uint8_t *buf, uint32_t len,
}
driver->msg_mask_tbl_count += 1;
}
+ mutex_unlock(&driver->msg_mask_lock);
}
static void diag_build_time_mask_update(uint8_t *buf,
@@ -615,11 +617,11 @@ static void diag_build_time_mask_update(uint8_t *buf,
__func__, range->ssid_first, range->ssid_last);
return;
}
-
+ mutex_lock(&driver->msg_mask_lock);
build_mask = (struct diag_msg_mask_t *)(driver->build_time_mask->ptr);
num_items = range->ssid_last - range->ssid_first + 1;
- for (i = 0; i < driver->msg_mask_tbl_count; i++, build_mask++) {
+ for (i = 0; i < driver->bt_msg_mask_tbl_count; i++, build_mask++) {
if (build_mask->ssid_first != range->ssid_first)
continue;
found = 1;
@@ -638,7 +640,7 @@ static void diag_build_time_mask_update(uint8_t *buf,
if (found)
goto end;
- new_size = (driver->msg_mask_tbl_count + 1) *
+ new_size = (driver->bt_msg_mask_tbl_count + 1) *
sizeof(struct diag_msg_mask_t);
temp = krealloc(driver->build_time_mask->ptr, new_size, GFP_KERNEL);
if (!temp) {
@@ -653,8 +655,9 @@ static void diag_build_time_mask_update(uint8_t *buf,
__func__, err);
goto end;
}
- driver->msg_mask_tbl_count += 1;
+ driver->bt_msg_mask_tbl_count += 1;
end:
+ mutex_unlock(&driver->msg_mask_lock);
return;
}
diff --git a/drivers/clk/clk.c b/drivers/clk/clk.c
index 4996f4f312f4..73d65813de8b 100644
--- a/drivers/clk/clk.c
+++ b/drivers/clk/clk.c
@@ -1751,6 +1751,15 @@ static int clk_change_rate(struct clk_core *core)
else if (core->parent)
best_parent_rate = core->parent->rate;
+ trace_clk_set_rate(core, core->new_rate);
+
+ /* Enforce vdd requirements for new frequency. */
+ if (core->prepare_count) {
+ rc = clk_vote_rate_vdd(core, core->new_rate);
+ if (rc)
+ goto out;
+ }
+
if (core->new_parent && core->new_parent != core->parent) {
old_parent = __clk_set_parent_before(core, core->new_parent);
trace_clk_set_parent(core, core->new_parent);
@@ -1768,15 +1777,6 @@ static int clk_change_rate(struct clk_core *core)
__clk_set_parent_after(core, core->new_parent, old_parent);
}
- trace_clk_set_rate(core, core->new_rate);
-
- /* Enforce vdd requirements for new frequency. */
- if (core->prepare_count) {
- rc = clk_vote_rate_vdd(core, core->new_rate);
- if (rc)
- goto out;
- }
-
if (!skip_set_rate && core->ops->set_rate) {
rc = core->ops->set_rate(core->hw, core->new_rate,
best_parent_rate);
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/devfreq/governor_bw_hwmon.c b/drivers/devfreq/governor_bw_hwmon.c
index b997e79e3d73..972de02ca549 100644
--- a/drivers/devfreq/governor_bw_hwmon.c
+++ b/drivers/devfreq/governor_bw_hwmon.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2013-2016, The Linux Foundation. All rights reserved.
+ * Copyright (c) 2013-2017, The Linux Foundation. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 and
@@ -86,6 +86,8 @@ static DEFINE_SPINLOCK(irq_lock);
static LIST_HEAD(hwmon_list);
static DEFINE_MUTEX(list_lock);
+static DEFINE_MUTEX(sync_lock);
+
static int use_cnt;
static DEFINE_MUTEX(state_lock);
@@ -846,6 +848,7 @@ static int devfreq_bw_hwmon_ev_handler(struct devfreq *df,
break;
case DEVFREQ_GOV_INTERVAL:
+ mutex_lock(&sync_lock);
sample_ms = *(unsigned int *)data;
sample_ms = max(MIN_MS, sample_ms);
sample_ms = min(MAX_MS, sample_ms);
@@ -865,6 +868,7 @@ static int devfreq_bw_hwmon_ev_handler(struct devfreq *df,
"Unable to resume HW monitor (%d)\n", ret);
return ret;
}
+ mutex_unlock(&sync_lock);
break;
case DEVFREQ_GOV_SUSPEND:
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..ac6c47bd33ae 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);
@@ -100,7 +103,7 @@ static void a5xx_set_pagetable(struct msm_gpu *gpu, struct msm_ringbuffer *ring,
OUT_RING(ring, 1);
}
-static int a5xx_submit(struct msm_gpu *gpu, struct msm_gem_submit *submit)
+static void a5xx_submit(struct msm_gpu *gpu, struct msm_gem_submit *submit)
{
struct adreno_gpu *adreno_gpu = to_adreno_gpu(gpu);
struct a5xx_gpu *a5xx_gpu = to_a5xx_gpu(adreno_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);
/*
@@ -259,8 +273,6 @@ static int a5xx_submit(struct msm_gpu *gpu, struct msm_gem_submit *submit)
/* Check to see if we need to start preemption */
a5xx_preempt_trigger(gpu);
-
- return 0;
}
static const struct {
@@ -762,14 +774,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 +1413,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..a66c7e80d2af 100644
--- a/drivers/gpu/drm/msm/adreno/adreno_gpu.c
+++ b/drivers/gpu/drm/msm/adreno/adreno_gpu.c
@@ -172,7 +172,7 @@ void adreno_recover(struct msm_gpu *gpu)
enable_irq(gpu->irq);
}
-int adreno_submit(struct msm_gpu *gpu, struct msm_gem_submit *submit)
+void adreno_submit(struct msm_gpu *gpu, struct msm_gem_submit *submit)
{
struct adreno_gpu *adreno_gpu = to_adreno_gpu(gpu);
struct msm_ringbuffer *ring = gpu->rb[submit->ring];
@@ -248,8 +248,6 @@ int adreno_submit(struct msm_gpu *gpu, struct msm_gem_submit *submit)
#endif
gpu->funcs->flush(gpu, ring);
-
- return 0;
}
void adreno_flush(struct msm_gpu *gpu, struct msm_ringbuffer *ring)
@@ -563,6 +561,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 +615,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/adreno/adreno_gpu.h b/drivers/gpu/drm/msm/adreno/adreno_gpu.h
index 3f9bc655c383..9e622fa06ce4 100644
--- a/drivers/gpu/drm/msm/adreno/adreno_gpu.h
+++ b/drivers/gpu/drm/msm/adreno/adreno_gpu.h
@@ -244,7 +244,7 @@ uint32_t adreno_last_fence(struct msm_gpu *gpu, struct msm_ringbuffer *ring);
uint32_t adreno_submitted_fence(struct msm_gpu *gpu,
struct msm_ringbuffer *ring);
void adreno_recover(struct msm_gpu *gpu);
-int adreno_submit(struct msm_gpu *gpu, struct msm_gem_submit *submit);
+void adreno_submit(struct msm_gpu *gpu, struct msm_gem_submit *submit);
void adreno_flush(struct msm_gpu *gpu, struct msm_ringbuffer *ring);
bool adreno_idle(struct msm_gpu *gpu, struct msm_ringbuffer *ring);
#ifdef CONFIG_DEBUG_FS
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..665f8db0e04f 100644
--- a/drivers/gpu/drm/msm/msm_drv.c
+++ b/drivers/gpu/drm/msm/msm_drv.c
@@ -251,17 +251,12 @@ static int msm_unload(struct drm_device *dev)
}
#define KMS_MDP4 0
-#define KMS_MDP5 1
-#define KMS_SDE 2
+#define KMS_SDE 1
static int get_mdp_ver(struct platform_device *pdev)
{
#ifdef CONFIG_OF
static const struct of_device_id match_types[] = { {
- .compatible = "qcom,mdss_mdp",
- .data = (void *)KMS_MDP5,
- },
- {
.compatible = "qcom,sde-kms",
.data = (void *)KMS_SDE,
/* end node */
@@ -432,9 +427,6 @@ static int msm_load(struct drm_device *dev, unsigned long flags)
case KMS_MDP4:
kms = mdp4_kms_init(dev);
break;
- case KMS_MDP5:
- kms = mdp5_kms_init(dev);
- break;
case KMS_SDE:
kms = sde_kms_init(dev);
break;
@@ -1208,23 +1200,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;
@@ -1937,7 +1940,6 @@ static const struct platform_device_id msm_id[] = {
static const struct of_device_id dt_match[] = {
{ .compatible = "qcom,mdp" }, /* mdp4 */
- { .compatible = "qcom,mdss_mdp" }, /* mdp5 */
{ .compatible = "qcom,sde-kms" }, /* sde */
{}
};
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..4bee797da746 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;
@@ -734,6 +778,13 @@ struct drm_gem_object *msm_gem_new(struct drm_device *dev,
size = PAGE_ALIGN(size);
+ /*
+ * Disallow zero sized objects as they make the underlying
+ * infrastructure grumpy
+ */
+ if (!size)
+ return ERR_PTR(-EINVAL);
+
ret = msm_gem_new_impl(dev, size, flags, &obj);
if (ret)
goto fail;
@@ -756,7 +807,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 +840,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..bef6e81de82a 100644
--- a/drivers/gpu/drm/msm/msm_gpu.c
+++ b/drivers/gpu/drm/msm/msm_gpu.c
@@ -547,7 +547,7 @@ int msm_gpu_submit(struct msm_gpu *gpu, struct msm_gem_submit *submit)
struct drm_device *dev = gpu->dev;
struct msm_drm_private *priv = dev->dev_private;
struct msm_ringbuffer *ring = gpu->rb[submit->ring];
- int i, ret;
+ int i;
WARN_ON(!mutex_is_locked(&dev->struct_mutex));
@@ -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)
@@ -586,11 +590,11 @@ int msm_gpu_submit(struct msm_gpu *gpu, struct msm_gem_submit *submit)
msm_gem_move_to_active(&msm_obj->base, gpu, true, submit->fence);
}
- ret = gpu->funcs->submit(gpu, submit);
+ gpu->funcs->submit(gpu, submit);
hangcheck_timer_reset(gpu);
- return ret;
+ return 0;
}
struct msm_context_counter {
@@ -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..a47eae68dd9b 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:
@@ -59,7 +61,7 @@ struct msm_gpu_funcs {
int (*hw_init)(struct msm_gpu *gpu);
int (*pm_suspend)(struct msm_gpu *gpu);
int (*pm_resume)(struct msm_gpu *gpu);
- int (*submit)(struct msm_gpu *gpu, struct msm_gem_submit *submit);
+ void (*submit)(struct msm_gpu *gpu, struct msm_gem_submit *submit);
void (*flush)(struct msm_gpu *gpu, struct msm_ringbuffer *ring);
irqreturn_t (*irq)(struct msm_gpu *irq);
uint32_t (*last_fence)(struct msm_gpu *gpu,
@@ -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/msm_snapshot.h b/drivers/gpu/drm/msm/msm_snapshot.h
index 247e1358c885..fd560b2129f1 100644
--- a/drivers/gpu/drm/msm/msm_snapshot.h
+++ b/drivers/gpu/drm/msm/msm_snapshot.h
@@ -71,8 +71,8 @@ static inline bool _snapshot_header(struct msm_snapshot *snapshot,
*/
#define SNAPSHOT_HEADER(_snapshot, _header, _id, _dwords) \
_snapshot_header((_snapshot), \
- (struct msm_snapshot_section_header *) &(header), \
- sizeof(header), (_dwords) << 2, (_id))
+ (struct msm_snapshot_section_header *) &(_header), \
+ sizeof(_header), (_dwords) << 2, (_id))
struct msm_gpu;
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/gpu/msm/kgsl.c b/drivers/gpu/msm/kgsl.c
index 986026aa1b66..50f55abd6db8 100644
--- a/drivers/gpu/msm/kgsl.c
+++ b/drivers/gpu/msm/kgsl.c
@@ -255,6 +255,13 @@ static void _deferred_put(struct work_struct *work)
kgsl_mem_entry_put(entry);
}
+static inline void
+kgsl_mem_entry_put_deferred(struct kgsl_mem_entry *entry)
+{
+ if (entry)
+ queue_work(kgsl_driver.mem_workqueue, &entry->work);
+}
+
static inline struct kgsl_mem_entry *
kgsl_mem_entry_create(void)
{
@@ -265,6 +272,7 @@ kgsl_mem_entry_create(void)
/* put this ref in the caller functions after init */
kref_get(&entry->refcount);
+ INIT_WORK(&entry->work, _deferred_put);
}
return entry;
}
@@ -1860,7 +1868,7 @@ long kgsl_ioctl_sharedmem_free(struct kgsl_device_private *dev_priv,
return -EINVAL;
ret = gpumem_free_entry(entry);
- kgsl_mem_entry_put(entry);
+ kgsl_mem_entry_put_deferred(entry);
return ret;
}
@@ -1878,7 +1886,7 @@ long kgsl_ioctl_gpumem_free_id(struct kgsl_device_private *dev_priv,
return -EINVAL;
ret = gpumem_free_entry(entry);
- kgsl_mem_entry_put(entry);
+ kgsl_mem_entry_put_deferred(entry);
return ret;
}
@@ -1915,8 +1923,7 @@ static void gpuobj_free_fence_func(void *priv)
{
struct kgsl_mem_entry *entry = priv;
- INIT_WORK(&entry->work, _deferred_put);
- queue_work(kgsl_driver.mem_workqueue, &entry->work);
+ kgsl_mem_entry_put_deferred(entry);
}
static long gpuobj_free_on_fence(struct kgsl_device_private *dev_priv,
@@ -1980,7 +1987,7 @@ long kgsl_ioctl_gpuobj_free(struct kgsl_device_private *dev_priv,
else
ret = -EINVAL;
- kgsl_mem_entry_put(entry);
+ kgsl_mem_entry_put_deferred(entry);
return ret;
}
@@ -3355,7 +3362,13 @@ long kgsl_ioctl_sparse_phys_free(struct kgsl_device_private *dev_priv,
if (entry == NULL)
return -EINVAL;
+ if (!kgsl_mem_entry_set_pend(entry)) {
+ kgsl_mem_entry_put(entry);
+ return -EBUSY;
+ }
+
if (entry->memdesc.cur_bindings != 0) {
+ kgsl_mem_entry_unset_pend(entry);
kgsl_mem_entry_put(entry);
return -EINVAL;
}
@@ -3364,7 +3377,7 @@ long kgsl_ioctl_sparse_phys_free(struct kgsl_device_private *dev_priv,
/* One put for find_id(), one put for the kgsl_mem_entry_create() */
kgsl_mem_entry_put(entry);
- kgsl_mem_entry_put(entry);
+ kgsl_mem_entry_put_deferred(entry);
return 0;
}
@@ -3424,7 +3437,13 @@ long kgsl_ioctl_sparse_virt_free(struct kgsl_device_private *dev_priv,
if (entry == NULL)
return -EINVAL;
+ if (!kgsl_mem_entry_set_pend(entry)) {
+ kgsl_mem_entry_put(entry);
+ return -EBUSY;
+ }
+
if (entry->bind_tree.rb_node != NULL) {
+ kgsl_mem_entry_unset_pend(entry);
kgsl_mem_entry_put(entry);
return -EINVAL;
}
@@ -3433,7 +3452,7 @@ long kgsl_ioctl_sparse_virt_free(struct kgsl_device_private *dev_priv,
/* One put for find_id(), one put for the kgsl_mem_entry_create() */
kgsl_mem_entry_put(entry);
- kgsl_mem_entry_put(entry);
+ kgsl_mem_entry_put_deferred(entry);
return 0;
}
@@ -4906,7 +4925,7 @@ static int __init kgsl_core_init(void)
WQ_UNBOUND | WQ_MEM_RECLAIM | WQ_SYSFS, 0);
kgsl_driver.mem_workqueue = alloc_workqueue("kgsl-mementry",
- WQ_UNBOUND | WQ_MEM_RECLAIM, 0);
+ WQ_MEM_RECLAIM, 0);
kgsl_events_init();
diff --git a/drivers/infiniband/hw/qib/qib_qp.c b/drivers/infiniband/hw/qib/qib_qp.c
index 3eff35c2d453..2684605fe67f 100644
--- a/drivers/infiniband/hw/qib/qib_qp.c
+++ b/drivers/infiniband/hw/qib/qib_qp.c
@@ -41,13 +41,13 @@
#include "qib.h"
-#define BITS_PER_PAGE (PAGE_SIZE*BITS_PER_BYTE)
-#define BITS_PER_PAGE_MASK (BITS_PER_PAGE-1)
+#define RVT_BITS_PER_PAGE (PAGE_SIZE*BITS_PER_BYTE)
+#define RVT_BITS_PER_PAGE_MASK (RVT_BITS_PER_PAGE-1)
static inline unsigned mk_qpn(struct qib_qpn_table *qpt,
struct qpn_map *map, unsigned off)
{
- return (map - qpt->map) * BITS_PER_PAGE + off;
+ return (map - qpt->map) * RVT_BITS_PER_PAGE + off;
}
static inline unsigned find_next_offset(struct qib_qpn_table *qpt,
@@ -59,7 +59,7 @@ static inline unsigned find_next_offset(struct qib_qpn_table *qpt,
if (((off & qpt->mask) >> 1) >= n)
off = (off | qpt->mask) + 2;
} else
- off = find_next_zero_bit(map->page, BITS_PER_PAGE, off);
+ off = find_next_zero_bit(map->page, RVT_BITS_PER_PAGE, off);
return off;
}
@@ -147,8 +147,8 @@ static int alloc_qpn(struct qib_devdata *dd, struct qib_qpn_table *qpt,
qpn = 2;
if (qpt->mask && ((qpn & qpt->mask) >> 1) >= dd->n_krcv_queues)
qpn = (qpn | qpt->mask) + 2;
- offset = qpn & BITS_PER_PAGE_MASK;
- map = &qpt->map[qpn / BITS_PER_PAGE];
+ offset = qpn & RVT_BITS_PER_PAGE_MASK;
+ map = &qpt->map[qpn / RVT_BITS_PER_PAGE];
max_scan = qpt->nmaps - !offset;
for (i = 0;;) {
if (unlikely(!map->page)) {
@@ -173,7 +173,7 @@ static int alloc_qpn(struct qib_devdata *dd, struct qib_qpn_table *qpt,
* We just need to be sure we don't loop
* forever.
*/
- } while (offset < BITS_PER_PAGE && qpn < QPN_MAX);
+ } while (offset < RVT_BITS_PER_PAGE && qpn < QPN_MAX);
/*
* In order to keep the number of pages allocated to a
* minimum, we scan the all existing pages before increasing
@@ -204,9 +204,9 @@ static void free_qpn(struct qib_qpn_table *qpt, u32 qpn)
{
struct qpn_map *map;
- map = qpt->map + qpn / BITS_PER_PAGE;
+ map = qpt->map + qpn / RVT_BITS_PER_PAGE;
if (map->page)
- clear_bit(qpn & BITS_PER_PAGE_MASK, map->page);
+ clear_bit(qpn & RVT_BITS_PER_PAGE_MASK, map->page);
}
static inline unsigned qpn_hash(struct qib_ibdev *dev, u32 qpn)
diff --git a/drivers/input/misc/hbtp_input.c b/drivers/input/misc/hbtp_input.c
index 599605a3cf76..56f2732334db 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);
@@ -1477,6 +1479,7 @@ static int __init hbtp_init(void)
sensor_kobject = kobject_create_and_add("hbtpsensor", kernel_kobj);
if (!sensor_kobject) {
pr_err("%s: Could not create hbtpsensor kobject\n", __func__);
+ error = -ENOMEM;
goto err_kobject_create;
}
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/input/touchscreen/st/fts.c b/drivers/input/touchscreen/st/fts.c
index bbe872001407..78bdd24af28b 100644
--- a/drivers/input/touchscreen/st/fts.c
+++ b/drivers/input/touchscreen/st/fts.c
@@ -1252,7 +1252,7 @@ static void fts_event_handler(struct work_struct *work)
static int cx_crc_check(void)
{
unsigned char regAdd1[3] = {FTS_CMD_HW_REG_R, ADDR_CRC_BYTE0, ADDR_CRC_BYTE1};
- unsigned char val;
+ unsigned char val = 0;
unsigned char crc_status;
unsigned int error;
diff --git a/drivers/input/touchscreen/st/fts_lib/ftsFlash.c b/drivers/input/touchscreen/st/fts_lib/ftsFlash.c
index 59c73f4c4edb..f3becac79102 100644
--- a/drivers/input/touchscreen/st/fts_lib/ftsFlash.c
+++ b/drivers/input/touchscreen/st/fts_lib/ftsFlash.c
@@ -93,7 +93,7 @@ int getFirmwareVersion(u16 *fw_vers, u16 *config_id)
int flash_status(void)
{
u8 cmd[2] = {FLASH_CMD_READSTATUS, 0x00};
- u8 readData;
+ u8 readData = 0;
logError(0, "%s Reading flash_status...\n", tag);
if (fts_readCmd(cmd, 2, &readData, FLASH_STATUS_BYTES) < 0) {
diff --git a/drivers/input/touchscreen/st/fts_lib/ftsGesture.c b/drivers/input/touchscreen/st/fts_lib/ftsGesture.c
index fda4ab281948..ee97a417d4cb 100644
--- a/drivers/input/touchscreen/st/fts_lib/ftsGesture.c
+++ b/drivers/input/touchscreen/st/fts_lib/ftsGesture.c
@@ -28,7 +28,7 @@ static u8 custom_gesture_index[GESTURE_CUSTOM_NUMBER] = { 0 };
int enableGesture(u8 *mask, int size)
{
u8 cmd[size+2];
- u8 readData[FIFO_EVENT_SIZE];
+ u8 readData[FIFO_EVENT_SIZE] = {0};
int i, res;
int event_to_search[4] = {EVENTID_GESTURE, EVENT_TYPE_ENB, 0x00, GESTURE_ENABLE};
@@ -82,7 +82,7 @@ int enableGesture(u8 *mask, int size)
int disableGesture(u8 *mask, int size)
{
u8 cmd[2+GESTURE_MASK_SIZE];
- u8 readData[FIFO_EVENT_SIZE];
+ u8 readData[FIFO_EVENT_SIZE] = {0};
u8 temp;
int i, res;
int event_to_search[4] = { EVENTID_GESTURE, EVENT_TYPE_ENB, 0x00, GESTURE_DISABLE };
@@ -141,7 +141,7 @@ int startAddCustomGesture(u8 gestureID)
{
u8 cmd[3] = { FTS_CMD_GESTURE_CMD, GESTURE_START_ADD, gestureID };
int res;
- u8 readData[FIFO_EVENT_SIZE];
+ u8 readData[FIFO_EVENT_SIZE] = {0};
int event_to_search[4] = { EVENTID_GESTURE, EVENT_TYPE_ENB, gestureID, GESTURE_START_ADD };
res = fts_writeFwCmd(cmd, 3);
@@ -168,7 +168,7 @@ int finishAddCustomGesture(u8 gestureID)
{
u8 cmd[3] = { FTS_CMD_GESTURE_CMD, GESTURE_FINISH_ADD, gestureID };
int res;
- u8 readData[FIFO_EVENT_SIZE];
+ u8 readData[FIFO_EVENT_SIZE] = {0};
int event_to_search[4] = { EVENTID_GESTURE, EVENT_TYPE_ENB, gestureID, GESTURE_FINISH_ADD };
res = fts_writeFwCmd(cmd, 3);
@@ -199,7 +199,7 @@ int loadCustomGesture(u8 *template, u8 gestureID)
int toWrite, offset = 0;
u8 cmd[TEMPLATE_CHUNK + 5];
int event_to_search[4] = { EVENTID_GESTURE, EVENT_TYPE_ENB, gestureID, GESTURE_DATA_ADD };
- u8 readData[FIFO_EVENT_SIZE];
+ u8 readData[FIFO_EVENT_SIZE] = {0};
logError(0, "%s Starting adding custom gesture procedure...\n", tag);
@@ -359,7 +359,7 @@ int removeCustomGesture(u8 gestureID)
int res, index;
u8 cmd[3] = { FTS_CMD_GESTURE_CMD, GETURE_REMOVE_CUSTOM, gestureID };
int event_to_search[4] = {EVENTID_GESTURE, EVENT_TYPE_ENB, gestureID, GETURE_REMOVE_CUSTOM };
- u8 readData[FIFO_EVENT_SIZE];
+ u8 readData[FIFO_EVENT_SIZE] = {0};
index = gestureID - GESTURE_CUSTOM_OFFSET;
diff --git a/drivers/input/touchscreen/st/fts_lib/ftsTest.c b/drivers/input/touchscreen/st/fts_lib/ftsTest.c
index 68bd04eff316..3810fd02001a 100644
--- a/drivers/input/touchscreen/st/fts_lib/ftsTest.c
+++ b/drivers/input/touchscreen/st/fts_lib/ftsTest.c
@@ -301,7 +301,7 @@ int production_test_ito(void)
{
int res = OK;
u8 cmd;
- u8 readData[FIFO_EVENT_SIZE];
+ u8 readData[FIFO_EVENT_SIZE] = {0};
int eventToSearch[2] = {EVENTID_ERROR_EVENT, EVENT_TYPE_ITO}; /* look for ito event */
logError(0, "%s ITO Production test is starting...\n", tag);
@@ -347,7 +347,7 @@ int production_test_initialization(void)
{
int res;
u8 cmd;
- u8 readData[FIFO_EVENT_SIZE];
+ u8 readData[FIFO_EVENT_SIZE] = {0};
int eventToSearch[2] = {EVENTID_STATUS_UPDATE, EVENT_TYPE_FULL_INITIALIZATION};
logError(0, "%s INITIALIZATION Production test is starting...\n", tag);
@@ -397,7 +397,7 @@ int ms_compensation_tuning(void)
{
int res;
u8 cmd;
- u8 readData[FIFO_EVENT_SIZE];
+ u8 readData[FIFO_EVENT_SIZE] = {0};
int eventToSearch[2] = {EVENTID_STATUS_UPDATE, EVENT_TYPE_MS_TUNING_CMPL};
logError(0, "%s MS INITIALIZATION command sent...\n", tag);
@@ -429,7 +429,7 @@ int ss_compensation_tuning(void)
{
int res;
u8 cmd;
- u8 readData[FIFO_EVENT_SIZE];
+ u8 readData[FIFO_EVENT_SIZE] = {0};
int eventToSearch[2] = {EVENTID_STATUS_UPDATE, EVENT_TYPE_SS_TUNING_CMPL};
logError(0, "%s SS INITIALIZATION command sent...\n", tag);
@@ -461,7 +461,7 @@ int lp_timer_calibration(void)
{
int res;
u8 cmd;
- u8 readData[FIFO_EVENT_SIZE];
+ u8 readData[FIFO_EVENT_SIZE] = {0};
int eventToSearch[2] = {EVENTID_STATUS_UPDATE, EVENT_TYPE_LPTIMER_TUNING_CMPL};
logError(0, "%s LP TIMER CALIBRATION command sent...\n", tag);
@@ -493,7 +493,7 @@ int save_cx_tuning(void)
{
int res;
u8 cmd;
- u8 readData[FIFO_EVENT_SIZE];
+ u8 readData[FIFO_EVENT_SIZE] = {0};
int eventToSearch[2] = {EVENTID_STATUS_UPDATE, EVENT_TYPE_COMP_DATA_SAVED};
logError(0, "%s SAVE CX command sent...\n", tag);
diff --git a/drivers/md/dm-ioctl.c b/drivers/md/dm-ioctl.c
index bc5e9a5b1f30..7baeeafa059d 100644
--- a/drivers/md/dm-ioctl.c
+++ b/drivers/md/dm-ioctl.c
@@ -1843,7 +1843,7 @@ static int ctl_ioctl(uint command, struct dm_ioctl __user *user)
if (r)
goto out;
- param->data_size = sizeof(*param);
+ param->data_size = offsetof(struct dm_ioctl, data);
r = fn(param, input_param_size);
if (unlikely(param->flags & DM_BUFFER_FULL_FLAG) &&
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/dvb-core/dmxdev.c b/drivers/media/dvb-core/dmxdev.c
index a9c4237d631a..9b743f5fdcf8 100644
--- a/drivers/media/dvb-core/dmxdev.c
+++ b/drivers/media/dvb-core/dmxdev.c
@@ -1615,7 +1615,7 @@ static int dvb_dvr_get_event(struct dmxdev *dmxdev,
unsigned int f_flags,
struct dmx_filter_event *event)
{
- int res;
+ int res = 0;
if (!((f_flags & O_ACCMODE) == O_RDONLY))
return -EINVAL;
@@ -2402,8 +2402,10 @@ static int dvb_dmxdev_set_playback_mode(struct dmxdev_filter *dmxdevfilter,
(playback_mode != DMX_PB_MODE_PULL))
return -EINVAL;
+ if (dmxdev->demux->set_playback_mode == NULL)
+ return -EINVAL;
+
if (((dmxdev->source < DMX_SOURCE_DVR0) ||
- !dmxdev->demux->set_playback_mode ||
!(caps.caps & DMX_CAP_PULL_MODE)) &&
(playback_mode == DMX_PB_MODE_PULL))
return -EPERM;
@@ -2520,7 +2522,7 @@ static int dvb_dmxdev_release_data(struct dmxdev_filter *dmxdevfilter,
static int dvb_dmxdev_get_event(struct dmxdev_filter *dmxdevfilter,
struct dmx_filter_event *event)
{
- int res;
+ int res = 0;
spin_lock_irq(&dmxdevfilter->dev->lock);
diff --git a/drivers/media/platform/msm/broadcast/tspp.c b/drivers/media/platform/msm/broadcast/tspp.c
index b706d598e6b8..fa566ad01d99 100644
--- a/drivers/media/platform/msm/broadcast/tspp.c
+++ b/drivers/media/platform/msm/broadcast/tspp.c
@@ -2210,7 +2210,13 @@ int tspp_remove_filter(u32 dev, u32 channel_id,
channel = &pdev->channels[channel_id];
src = channel->src;
- tspp_filter = &(pdev->filters[src]->filter[filter->priority]);
+ if ((src == TSPP_SOURCE_TSIF0) || (src == TSPP_SOURCE_TSIF1))
+ tspp_filter = &(pdev->filters[src]->filter[filter->priority]);
+ else {
+ pr_err("tspp_remove: wrong source type %d", src);
+ return -EINVAL;
+ }
+
/* disable pipe (channel) */
val = readl_relaxed(pdev->base + TSPP_PS_DISABLE);
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..f9809615b407 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)
@@ -841,7 +844,6 @@ static void msm_isp_sync_dual_cam_frame_id(
}
}
- WARN_ON(ms_res->dual_sync_mode == MSM_ISP_DUAL_CAM_ASYNC);
/* find highest frame id */
for (i = 0; i < MAX_VFE * VFE_SRC_MAX; i++) {
if (ms_res->src_info[i] == NULL)
@@ -915,7 +917,7 @@ void msm_isp_increment_frame_id(struct vfe_device *vfe_dev,
*/
if (ms_res->src_sof_mask & (1 <<
src_info->dual_hw_ms_info.index)) {
- pr_err("Frame out of sync on vfe %d\n",
+ pr_err_ratelimited("Frame out of sync on vfe %d\n",
vfe_dev->pdev->id);
/*
* set this isp as async mode to force
@@ -995,6 +997,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 +1015,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 +2433,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 +2492,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 +2512,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 +2933,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 +2951,14 @@ static void __msm_isp_stop_axi_streams(struct vfe_device *vfe_dev,
vfe_dev->hw_info->vfe_ops.axi_ops.
clear_wm_irq_mask(vfe_dev, stream_info);
}
- if (stream_info->state == ACTIVE &&
- !vfe_dev->axi_data.src_info[intf].lpm) {
- init_completion(&stream_info->inactive_comp);
- stream_info->state = STOP_PENDING;
- } else if (vfe_dev->axi_data.src_info[intf].lpm ||
+ init_completion(&stream_info->inactive_comp);
+ stream_info->state = STOP_PENDING;
+ if (stream_info->lpm_mode ||
stream_info->state == PAUSED) {
/* don't wait for reg update */
- stream_info->state = STOP_PENDING;
- msm_isp_axi_stream_enable_cfg(stream_info);
- stream_info->state = INACTIVE;
+ while (stream_info->state != INACTIVE)
+ __msm_isp_axi_stream_update(stream_info,
+ &timestamp);
}
spin_unlock_irqrestore(&stream_info->lock, flags);
}
@@ -3029,6 +3019,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 +3036,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 +3129,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 +3146,7 @@ static int msm_isp_start_axi_stream(struct vfe_device *vfe_dev_ioctl,
vfe_dev_ioctl->pdev->id);
if (src_state) {
src_mask |= (1 << SRC_TO_INTF(stream_info->stream_src));
- if (vfe_dev_ioctl->axi_data.src_info[intf].lpm) {
+ if (stream_info->lpm_mode) {
while (stream_info->state != ACTIVE)
__msm_isp_axi_stream_update(
stream_info, &timestamp);
@@ -3187,7 +3180,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..891e528f75f1 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
@@ -793,6 +793,21 @@ int32_t msm_sensor_driver_probe(void *setting,
}
}
+ if (strlen(slave_info->sensor_name) >= MAX_SENSOR_NAME ||
+ strlen(slave_info->eeprom_name) >= MAX_SENSOR_NAME ||
+ strlen(slave_info->actuator_name) >= MAX_SENSOR_NAME ||
+ strlen(slave_info->ois_name) >= MAX_SENSOR_NAME) {
+ pr_err("failed: name len greater than 32.\n");
+ pr_err("sensor name len:%zu, eeprom name len: %zu.\n",
+ strlen(slave_info->sensor_name),
+ strlen(slave_info->eeprom_name));
+ pr_err("actuator name len: %zu, ois name len:%zu.\n",
+ strlen(slave_info->actuator_name),
+ strlen(slave_info->ois_name));
+ rc = -EINVAL;
+ goto free_slave_info;
+ }
+
/* Print slave info */
CDBG("camera id %d Slave addr 0x%X addr_type %d\n",
slave_info->camera_id, slave_info->slave_addr,
@@ -847,9 +862,12 @@ int32_t msm_sensor_driver_probe(void *setting,
*/
if (slave_info->sensor_id_info.sensor_id ==
s_ctrl->sensordata->cam_slave_info->
- sensor_id_info.sensor_id) {
- pr_err("slot%d: sensor id%d already probed\n",
+ sensor_id_info.sensor_id &&
+ !(strcmp(slave_info->sensor_name,
+ s_ctrl->sensordata->cam_slave_info->sensor_name))) {
+ pr_err("slot%d: sensor name: %s sensor id%d already probed\n",
slave_info->camera_id,
+ slave_info->sensor_name,
s_ctrl->sensordata->cam_slave_info->
sensor_id_info.sensor_id);
msm_sensor_fill_sensor_info(s_ctrl,
@@ -1353,18 +1371,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/media/platform/msm/dvb/demux/mpq_dmx_plugin_common.c b/drivers/media/platform/msm/dvb/demux/mpq_dmx_plugin_common.c
index 2fc3ce406c27..2d2296893140 100644
--- a/drivers/media/platform/msm/dvb/demux/mpq_dmx_plugin_common.c
+++ b/drivers/media/platform/msm/dvb/demux/mpq_dmx_plugin_common.c
@@ -6536,10 +6536,8 @@ static int mpq_sdmx_write(struct mpq_demux *mpq_demux,
const char *buf,
size_t count)
{
- struct ion_handle *ion_handle =
- mpq_demux->demux.dmx.dvr_input.priv_handle;
- struct dvb_ringbuffer *rbuf = (struct dvb_ringbuffer *)
- mpq_demux->demux.dmx.dvr_input.ringbuff;
+ struct ion_handle *ion_handle;
+ struct dvb_ringbuffer *rbuf;
struct sdmx_buff_descr buf_desc;
u32 read_offset;
int ret;
@@ -6549,10 +6547,13 @@ static int mpq_sdmx_write(struct mpq_demux *mpq_demux,
return -EINVAL;
}
+ ion_handle = mpq_demux->demux.dmx.dvr_input.priv_handle;
+ rbuf = (struct dvb_ringbuffer *)mpq_demux->demux.dmx.dvr_input.ringbuff;
+
ret = mpq_sdmx_dvr_buffer_desc(mpq_demux, &buf_desc);
if (ret) {
MPQ_DVB_ERR_PRINT(
- "%s: Failed to init input buffer descriptor. ret = %d\n",
+ "%s: Failed to init input buffer descriptor. ret = %d\n",
__func__, ret);
return ret;
}
diff --git a/drivers/media/usb/uvc/uvc_ctrl.c b/drivers/media/usb/uvc/uvc_ctrl.c
index 3e59b288b8a8..57d2f89350d2 100644
--- a/drivers/media/usb/uvc/uvc_ctrl.c
+++ b/drivers/media/usb/uvc/uvc_ctrl.c
@@ -1991,6 +1991,9 @@ int uvc_ctrl_add_mapping(struct uvc_video_chain *chain,
if (!found)
return -ENOENT;
+ if (ctrl->info.size < mapping->size)
+ return -EINVAL;
+
if (mutex_lock_interruptible(&chain->ctrl_mutex))
return -ERESTARTSYS;
diff --git a/drivers/misc/qseecom.c b/drivers/misc/qseecom.c
index 9855bee67627..1c7cc917faa6 100644
--- a/drivers/misc/qseecom.c
+++ b/drivers/misc/qseecom.c
@@ -6843,6 +6843,60 @@ static void __qseecom_clean_data_sglistinfo(struct qseecom_dev_handle *data)
}
}
+
+static int __qseecom_bus_scaling_enable(struct qseecom_dev_handle *data,
+ bool *perf_enabled)
+{
+ int ret = 0;
+
+ if (qseecom.support_bus_scaling) {
+ if (!data->mode) {
+ mutex_lock(&qsee_bw_mutex);
+ __qseecom_register_bus_bandwidth_needs(
+ data, HIGH);
+ mutex_unlock(&qsee_bw_mutex);
+ }
+ ret = qseecom_scale_bus_bandwidth_timer(INACTIVE);
+ if (ret) {
+ pr_err("Failed to set bw\n");
+ ret = -EINVAL;
+ goto exit;
+ }
+ }
+ /*
+ * On targets where crypto clock is handled by HLOS,
+ * if clk_access_cnt is zero and perf_enabled is false,
+ * then the crypto clock was not enabled before sending cmd
+ * to tz, qseecom will enable the clock to avoid service failure.
+ */
+ if (!qseecom.no_clock_support &&
+ !qseecom.qsee.clk_access_cnt && !data->perf_enabled) {
+ pr_debug("ce clock is not enabled\n");
+ ret = qseecom_perf_enable(data);
+ if (ret) {
+ pr_err("Failed to vote for clock with err %d\n",
+ ret);
+ ret = -EINVAL;
+ goto exit;
+ }
+ *perf_enabled = true;
+ }
+exit:
+ return ret;
+}
+
+static void __qseecom_bus_scaling_disable(struct qseecom_dev_handle *data,
+ bool perf_enabled)
+{
+ if (qseecom.support_bus_scaling)
+ __qseecom_add_bw_scale_down_timer(
+ QSEECOM_SEND_CMD_CRYPTO_TIMEOUT);
+ if (perf_enabled) {
+ qsee_disable_clock_vote(data, CLK_DFAB);
+ qsee_disable_clock_vote(data, CLK_SFPB);
+ }
+}
+
long qseecom_ioctl(struct file *file, unsigned cmd, unsigned long arg)
{
int ret = 0;
@@ -6909,50 +6963,14 @@ long qseecom_ioctl(struct file *file, unsigned cmd, unsigned long arg)
}
/* Only one client allowed here at a time */
mutex_lock(&app_access_lock);
- if (qseecom.support_bus_scaling) {
- /* register bus bw in case the client doesn't do it */
- if (!data->mode) {
- mutex_lock(&qsee_bw_mutex);
- __qseecom_register_bus_bandwidth_needs(
- data, HIGH);
- mutex_unlock(&qsee_bw_mutex);
- }
- ret = qseecom_scale_bus_bandwidth_timer(INACTIVE);
- if (ret) {
- pr_err("Failed to set bw.\n");
- ret = -EINVAL;
- mutex_unlock(&app_access_lock);
- break;
- }
- }
- /*
- * On targets where crypto clock is handled by HLOS,
- * if clk_access_cnt is zero and perf_enabled is false,
- * then the crypto clock was not enabled before sending cmd
- * to tz, qseecom will enable the clock to avoid service failure.
- */
- if (!qseecom.no_clock_support &&
- !qseecom.qsee.clk_access_cnt && !data->perf_enabled) {
- pr_debug("ce clock is not enabled!\n");
- ret = qseecom_perf_enable(data);
- if (ret) {
- pr_err("Failed to vote for clock with err %d\n",
- ret);
- mutex_unlock(&app_access_lock);
- ret = -EINVAL;
- break;
- }
- perf_enabled = true;
+ ret = __qseecom_bus_scaling_enable(data, &perf_enabled);
+ if (ret) {
+ mutex_unlock(&app_access_lock);
+ break;
}
atomic_inc(&data->ioctl_count);
ret = qseecom_send_cmd(data, argp);
- if (qseecom.support_bus_scaling)
- __qseecom_add_bw_scale_down_timer(
- QSEECOM_SEND_CMD_CRYPTO_TIMEOUT);
- if (perf_enabled) {
- qsee_disable_clock_vote(data, CLK_DFAB);
- qsee_disable_clock_vote(data, CLK_SFPB);
- }
+ __qseecom_bus_scaling_disable(data, perf_enabled);
atomic_dec(&data->ioctl_count);
wake_up_all(&data->abort_wq);
mutex_unlock(&app_access_lock);
@@ -6971,52 +6989,17 @@ long qseecom_ioctl(struct file *file, unsigned cmd, unsigned long arg)
}
/* Only one client allowed here at a time */
mutex_lock(&app_access_lock);
- if (qseecom.support_bus_scaling) {
- if (!data->mode) {
- mutex_lock(&qsee_bw_mutex);
- __qseecom_register_bus_bandwidth_needs(
- data, HIGH);
- mutex_unlock(&qsee_bw_mutex);
- }
- ret = qseecom_scale_bus_bandwidth_timer(INACTIVE);
- if (ret) {
- pr_err("Failed to set bw.\n");
- mutex_unlock(&app_access_lock);
- ret = -EINVAL;
- break;
- }
- }
- /*
- * On targets where crypto clock is handled by HLOS,
- * if clk_access_cnt is zero and perf_enabled is false,
- * then the crypto clock was not enabled before sending cmd
- * to tz, qseecom will enable the clock to avoid service failure.
- */
- if (!qseecom.no_clock_support &&
- !qseecom.qsee.clk_access_cnt && !data->perf_enabled) {
- pr_debug("ce clock is not enabled!\n");
- ret = qseecom_perf_enable(data);
- if (ret) {
- pr_err("Failed to vote for clock with err %d\n",
- ret);
- mutex_unlock(&app_access_lock);
- ret = -EINVAL;
- break;
- }
- perf_enabled = true;
+ ret = __qseecom_bus_scaling_enable(data, &perf_enabled);
+ if (ret) {
+ mutex_unlock(&app_access_lock);
+ break;
}
atomic_inc(&data->ioctl_count);
if (cmd == QSEECOM_IOCTL_SEND_MODFD_CMD_REQ)
ret = qseecom_send_modfd_cmd(data, argp);
else
ret = qseecom_send_modfd_cmd_64(data, argp);
- if (qseecom.support_bus_scaling)
- __qseecom_add_bw_scale_down_timer(
- QSEECOM_SEND_CMD_CRYPTO_TIMEOUT);
- if (perf_enabled) {
- qsee_disable_clock_vote(data, CLK_DFAB);
- qsee_disable_clock_vote(data, CLK_SFPB);
- }
+ __qseecom_bus_scaling_disable(data, perf_enabled);
atomic_dec(&data->ioctl_count);
wake_up_all(&data->abort_wq);
mutex_unlock(&app_access_lock);
@@ -7418,8 +7401,14 @@ long qseecom_ioctl(struct file *file, unsigned cmd, unsigned long arg)
}
/* Only one client allowed here at a time */
mutex_lock(&app_access_lock);
+ ret = __qseecom_bus_scaling_enable(data, &perf_enabled);
+ if (ret) {
+ mutex_unlock(&app_access_lock);
+ break;
+ }
atomic_inc(&data->ioctl_count);
ret = qseecom_qteec_open_session(data, argp);
+ __qseecom_bus_scaling_disable(data, perf_enabled);
atomic_dec(&data->ioctl_count);
wake_up_all(&data->abort_wq);
mutex_unlock(&app_access_lock);
@@ -7467,8 +7456,14 @@ long qseecom_ioctl(struct file *file, unsigned cmd, unsigned long arg)
}
/* Only one client allowed here at a time */
mutex_lock(&app_access_lock);
+ ret = __qseecom_bus_scaling_enable(data, &perf_enabled);
+ if (ret) {
+ mutex_unlock(&app_access_lock);
+ break;
+ }
atomic_inc(&data->ioctl_count);
ret = qseecom_qteec_invoke_modfd_cmd(data, argp);
+ __qseecom_bus_scaling_disable(data, perf_enabled);
atomic_dec(&data->ioctl_count);
wake_up_all(&data->abort_wq);
mutex_unlock(&app_access_lock);
@@ -7750,7 +7745,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/core/mmc.c b/drivers/mmc/core/mmc.c
index 691287125895..5eda4f4fb0fe 100644
--- a/drivers/mmc/core/mmc.c
+++ b/drivers/mmc/core/mmc.c
@@ -2617,6 +2617,9 @@ static int mmc_partial_init(struct mmc_host *host)
if (mmc_card_hs400(card)) {
if (card->ext_csd.strobe_support && host->ops->enhanced_strobe)
err = host->ops->enhanced_strobe(host);
+ else if (host->ops->execute_tuning)
+ err = host->ops->execute_tuning(host,
+ MMC_SEND_TUNING_BLOCK_HS200);
} else if (mmc_card_hs200(card) && host->ops->execute_tuning) {
err = host->ops->execute_tuning(host,
MMC_SEND_TUNING_BLOCK_HS200);
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/mtd/chips/Kconfig b/drivers/mtd/chips/Kconfig
index 54479c481a7a..8a25adced79f 100644
--- a/drivers/mtd/chips/Kconfig
+++ b/drivers/mtd/chips/Kconfig
@@ -111,6 +111,7 @@ config MTD_MAP_BANK_WIDTH_16
config MTD_MAP_BANK_WIDTH_32
bool "Support 256-bit buswidth" if MTD_CFI_GEOMETRY
+ select MTD_COMPLEX_MAPPINGS if HAS_IOMEM
default n
help
If you wish to support CFI devices on a physical bus which is
diff --git a/drivers/net/ethernet/broadcom/tg3.c b/drivers/net/ethernet/broadcom/tg3.c
index 49056c33be74..21e5b9ed1ead 100644
--- a/drivers/net/ethernet/broadcom/tg3.c
+++ b/drivers/net/ethernet/broadcom/tg3.c
@@ -12031,7 +12031,7 @@ static int tg3_set_eeprom(struct net_device *dev, struct ethtool_eeprom *eeprom,
int ret;
u32 offset, len, b_offset, odd_len;
u8 *buf;
- __be32 start, end;
+ __be32 start = 0, end;
if (tg3_flag(tp, NO_NVRAM) ||
eeprom->magic != TG3_EEPROM_MAGIC)
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/ppp/pppolac.c b/drivers/net/ppp/pppolac.c
index 0184c96579e9..3a45cf805288 100644
--- a/drivers/net/ppp/pppolac.c
+++ b/drivers/net/ppp/pppolac.c
@@ -206,7 +206,9 @@ static void pppolac_xmit_core(struct work_struct *delivery_work)
while ((skb = skb_dequeue(&delivery_queue))) {
struct sock *sk_udp = skb->sk;
struct kvec iov = {.iov_base = skb->data, .iov_len = skb->len};
- struct msghdr msg = { 0 };
+ struct msghdr msg = {
+ .msg_flags = MSG_NOSIGNAL | MSG_DONTWAIT,
+ };
iov_iter_kvec(&msg.msg_iter, WRITE | ITER_KVEC, &iov, 1,
skb->len);
diff --git a/drivers/net/ppp/pppopns.c b/drivers/net/ppp/pppopns.c
index d9e06039794e..cdb4fa1af734 100644
--- a/drivers/net/ppp/pppopns.c
+++ b/drivers/net/ppp/pppopns.c
@@ -189,7 +189,9 @@ static void pppopns_xmit_core(struct work_struct *delivery_work)
while ((skb = skb_dequeue(&delivery_queue))) {
struct sock *sk_raw = skb->sk;
struct kvec iov = {.iov_base = skb->data, .iov_len = skb->len};
- struct msghdr msg = { 0 };
+ struct msghdr msg = {
+ .msg_flags = MSG_NOSIGNAL | MSG_DONTWAIT,
+ };
iov_iter_kvec(&msg.msg_iter, WRITE | ITER_KVEC, &iov, 1,
skb->len);
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..9406b6f71a6b 100644
--- a/drivers/net/wireless/ath/ath10k/snoc.c
+++ b/drivers/net/wireless/ath/ath10k/snoc.c
@@ -969,7 +969,7 @@ int ath10k_snoc_get_ce_id(struct ath10k *ar, int irq)
struct ath10k_snoc *ar_snoc = ath10k_snoc_priv(ar);
for (i = 0; i < CE_COUNT_MAX; i++) {
- if (ar_snoc->ce_irqs[i] == irq)
+ if (ar_snoc->ce_irqs[i].irq_line == irq)
return i;
}
ath10k_err(ar, "No matching CE id for irq %d\n", irq);
@@ -1002,15 +1002,17 @@ static int ath10k_snoc_request_irq(struct ath10k *ar)
int irqflags = IRQF_TRIGGER_RISING;
for (id = 0; id < CE_COUNT_MAX; id++) {
- ret = request_irq(ar_snoc->ce_irqs[id],
+ ret = request_irq(ar_snoc->ce_irqs[id].irq_line,
ath10k_snoc_per_engine_handler,
irqflags, ce_name[id], ar);
if (ret) {
ath10k_err(ar,
"%s: cannot register CE %d irq handler, ret = %d",
__func__, id, ret);
- free_irq(ar_snoc->ce_irqs[id], ar);
+ atomic_set(&ar_snoc->ce_irqs[id].irq_req_stat, 0);
return ret;
+ } else {
+ atomic_set(&ar_snoc->ce_irqs[id].irq_req_stat, 1);
}
}
@@ -1022,11 +1024,14 @@ static void ath10k_snoc_free_irq(struct ath10k *ar)
int id;
struct ath10k_snoc *ar_snoc = ath10k_snoc_priv(ar);
- for (id = 0; id < CE_COUNT_MAX; id++)
- free_irq(ar_snoc->ce_irqs[id], ar);
+ for (id = 0; id < CE_COUNT_MAX; id++) {
+ if (atomic_read(&ar_snoc->ce_irqs[id].irq_req_stat)) {
+ free_irq(ar_snoc->ce_irqs[id].irq_line, ar);
+ atomic_set(&ar_snoc->ce_irqs[id].irq_req_stat, 0);
+ }
+ }
}
-
static int ath10k_snoc_get_soc_info(struct ath10k *ar)
{
struct resource *res;
@@ -1146,8 +1151,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) {
@@ -1196,7 +1203,7 @@ static int ath10k_snoc_resource_init(struct ath10k *ar)
ret = -ENODEV;
goto out;
} else {
- ar_snoc->ce_irqs[i] = res->start;
+ ar_snoc->ce_irqs[i].irq_line = res->start;
}
}
diff --git a/drivers/net/wireless/ath/ath10k/snoc.h b/drivers/net/wireless/ath/ath10k/snoc.h
index 99ae157885bb..7a223b1d3ded 100644
--- a/drivers/net/wireless/ath/ath10k/snoc.h
+++ b/drivers/net/wireless/ath/ath10k/snoc.h
@@ -103,6 +103,15 @@ struct ath10k_service_notifier_context {
char name[QMI_SERVREG_LOC_NAME_LENGTH_V01 + 1];
};
+/* struct ath10k_snoc_ce_irq: copy engine irq struct
+ * @irq_req_stat: irq request status
+ * @irq_line: irq line
+ */
+struct ath10k_snoc_ce_irq {
+ atomic_t irq_req_stat;
+ u32 irq_line;
+};
+
/* struct ath10k_snoc: SNOC info struct
* @dev: device structure
* @ar:ath10k base structure
@@ -111,6 +120,7 @@ struct ath10k_service_notifier_context {
* @target_info: snoc target info
* @mem_len: mempry map length
* @pipe_info: pipe info struct
+ * @ce_irqs: copy engine irq list
* @ce_lock: protect ce structures
* @ce_states: maps ce id to ce state
* @rx_post_retry: rx buffer post processing timer
@@ -134,7 +144,7 @@ struct ath10k_snoc {
size_t mem_len;
struct ath10k_snoc_pipe pipe_info[CE_COUNT_MAX];
struct timer_list rx_post_retry;
- u32 ce_irqs[CE_COUNT_MAX];
+ struct ath10k_snoc_ce_irq ce_irqs[CE_COUNT_MAX];
u32 *vaddr_rri_on_ddr;
bool is_driver_probed;
struct notifier_block modem_ssr_nb;
diff --git a/drivers/net/wireless/ath/wil6210/Kconfig b/drivers/net/wireless/ath/wil6210/Kconfig
index 8f0bde5825d5..0e66348e7513 100644
--- a/drivers/net/wireless/ath/wil6210/Kconfig
+++ b/drivers/net/wireless/ath/wil6210/Kconfig
@@ -44,7 +44,7 @@ config WIL6210_TRACING
config WIL6210_WRITE_IOCTL
bool "wil6210 write ioctl to the device"
depends on WIL6210
- default n
+ default y
---help---
Say Y here to allow write-access from user-space to
the device memory through ioctl. This is useful for
diff --git a/drivers/net/wireless/ath/wil6210/cfg80211.c b/drivers/net/wireless/ath/wil6210/cfg80211.c
index 37898146f01d..69214fb2586c 100644
--- a/drivers/net/wireless/ath/wil6210/cfg80211.c
+++ b/drivers/net/wireless/ath/wil6210/cfg80211.c
@@ -26,6 +26,10 @@ bool disable_ap_sme;
module_param(disable_ap_sme, bool, 0444);
MODULE_PARM_DESC(disable_ap_sme, " let user space handle AP mode SME");
+static bool ignore_reg_hints = true;
+module_param(ignore_reg_hints, bool, 0444);
+MODULE_PARM_DESC(ignore_reg_hints, " Ignore OTA regulatory hints (Default: true)");
+
#define CHAN60G(_channel, _flags) { \
.band = IEEE80211_BAND_60GHZ, \
.center_freq = 56160 + (2160 * (_channel)), \
@@ -1650,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);
@@ -1665,13 +1663,45 @@ 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);
+ return wil_ps_update(wil, ps_profile);
+}
+
+static int wil_cfg80211_suspend(struct wiphy *wiphy,
+ struct cfg80211_wowlan *wow)
+{
+ struct wil6210_priv *wil = wiphy_to_wil(wiphy);
+ int rc;
+
+ /* Setting the wakeup trigger based on wow is TBD */
+
+ if (test_bit(wil_status_suspended, wil->status)) {
+ wil_dbg_pm(wil, "trying to suspend while suspended\n");
+ return 0;
+ }
+
+ rc = wil_can_suspend(wil, false);
if (rc)
- wil_err(wil, "wmi_ps_dev_profile_cfg failed (%d)\n", rc);
+ goto out;
+
+ wil_dbg_pm(wil, "suspending\n");
+
+ wil_p2p_stop_discovery(wil);
+
+ wil_abort_scan(wil, true);
+out:
return rc;
}
+static int wil_cfg80211_resume(struct wiphy *wiphy)
+{
+ struct wil6210_priv *wil = wiphy_to_wil(wiphy);
+
+ wil_dbg_pm(wil, "resuming\n");
+
+ return 0;
+}
+
static struct cfg80211_ops wil_cfg80211_ops = {
.add_virtual_intf = wil_cfg80211_add_iface,
.del_virtual_intf = wil_cfg80211_del_iface,
@@ -1703,6 +1733,8 @@ static struct cfg80211_ops wil_cfg80211_ops = {
.start_p2p_device = wil_cfg80211_start_p2p_device,
.stop_p2p_device = wil_cfg80211_stop_p2p_device,
.set_power_mgmt = wil_cfg80211_set_power_mgmt,
+ .suspend = wil_cfg80211_suspend,
+ .resume = wil_cfg80211_resume,
};
static void wil_wiphy_init(struct wiphy *wiphy)
@@ -1743,6 +1775,11 @@ static void wil_wiphy_init(struct wiphy *wiphy)
wiphy->vendor_commands = wil_nl80211_vendor_commands;
wiphy->vendor_events = wil_nl80211_vendor_events;
wiphy->n_vendor_events = ARRAY_SIZE(wil_nl80211_vendor_events);
+
+ if (ignore_reg_hints) {
+ wiphy->regulatory_flags |= REGULATORY_DISABLE_BEACON_HINTS;
+ wiphy->regulatory_flags |= REGULATORY_COUNTRY_IE_IGNORE;
+ }
}
struct wireless_dev *wil_cfg80211_init(struct device *dev)
diff --git a/drivers/net/wireless/ath/wil6210/debugfs.c b/drivers/net/wireless/ath/wil6210/debugfs.c
index 4a299f238c54..d3691c64d47a 100644
--- a/drivers/net/wireless/ath/wil6210/debugfs.c
+++ b/drivers/net/wireless/ath/wil6210/debugfs.c
@@ -509,6 +509,10 @@ static ssize_t wil_read_file_ioblob(struct file *file, char __user *user_buf,
void *buf;
size_t ret;
+ if (test_bit(wil_status_suspending, wil_blob->wil->status) ||
+ test_bit(wil_status_suspended, wil_blob->wil->status))
+ return 0;
+
if (pos < 0)
return -EINVAL;
@@ -1610,6 +1614,49 @@ static const struct file_operations fops_fw_version = {
.llseek = seq_lseek,
};
+/*---------suspend_stats---------*/
+static ssize_t wil_write_suspend_stats(struct file *file,
+ const char __user *buf,
+ size_t len, loff_t *ppos)
+{
+ struct wil6210_priv *wil = file->private_data;
+
+ memset(&wil->suspend_stats, 0, sizeof(wil->suspend_stats));
+
+ return len;
+}
+
+static ssize_t wil_read_suspend_stats(struct file *file,
+ char __user *user_buf,
+ size_t count, loff_t *ppos)
+{
+ struct wil6210_priv *wil = file->private_data;
+ static char text[400];
+ int n;
+
+ n = snprintf(text, sizeof(text),
+ "Suspend statistics:\n"
+ "successful suspends:%ld failed suspends:%ld\n"
+ "successful resumes:%ld failed resumes:%ld\n"
+ "rejected by host:%ld rejected by device:%ld\n",
+ wil->suspend_stats.successful_suspends,
+ wil->suspend_stats.failed_suspends,
+ wil->suspend_stats.successful_resumes,
+ wil->suspend_stats.failed_resumes,
+ wil->suspend_stats.rejected_by_host,
+ wil->suspend_stats.rejected_by_device);
+
+ n = min_t(int, n, sizeof(text));
+
+ return simple_read_from_buffer(user_buf, count, ppos, text, n);
+}
+
+static const struct file_operations fops_suspend_stats = {
+ .read = wil_read_suspend_stats,
+ .write = wil_write_suspend_stats,
+ .open = simple_open,
+};
+
/*----------------*/
static void wil6210_debugfs_init_blobs(struct wil6210_priv *wil,
struct dentry *dbg)
@@ -1662,6 +1709,7 @@ static const struct {
{"led_blink_time", 0644, &fops_led_blink_time},
{"fw_capabilities", 0444, &fops_fw_capabilities},
{"fw_version", 0444, &fops_fw_version},
+ {"suspend_stats", 0644, &fops_suspend_stats},
};
static void wil6210_debugfs_init_files(struct wil6210_priv *wil,
@@ -1708,6 +1756,7 @@ static const struct dbg_off dbg_wil_off[] = {
WIL_FIELD(discovery_mode, 0644, doff_u8),
WIL_FIELD(chip_revision, 0444, doff_u8),
WIL_FIELD(abft_len, 0644, doff_u8),
+ WIL_FIELD(wakeup_trigger, 0644, doff_u8),
{},
};
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/interrupt.c b/drivers/net/wireless/ath/wil6210/interrupt.c
index cab1e5c0e374..cad8a95c4e4e 100644
--- a/drivers/net/wireless/ath/wil6210/interrupt.c
+++ b/drivers/net/wireless/ath/wil6210/interrupt.c
@@ -467,6 +467,12 @@ static irqreturn_t wil6210_thread_irq(int irq, void *cookie)
wil6210_unmask_irq_pseudo(wil);
+ if (wil->suspend_resp_rcvd) {
+ wil_dbg_irq(wil, "set suspend_resp_comp to true\n");
+ wil->suspend_resp_comp = true;
+ wake_up_interruptible(&wil->wq);
+ }
+
return IRQ_HANDLED;
}
diff --git a/drivers/net/wireless/ath/wil6210/main.c b/drivers/net/wireless/ath/wil6210/main.c
index fca8acffeed5..78091b7910c7 100644
--- a/drivers/net/wireless/ath/wil6210/main.c
+++ b/drivers/net/wireless/ath/wil6210/main.c
@@ -576,6 +576,12 @@ 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;
+
+ wil->wakeup_trigger = WMI_WAKEUP_TRIGGER_UCAST |
+ WMI_WAKEUP_TRIGGER_BCAST;
+
return 0;
out_wmi_wq:
@@ -586,8 +592,10 @@ out_wmi_wq:
void wil6210_bus_request(struct wil6210_priv *wil, u32 kbps)
{
- if (wil->platform_ops.bus_request)
+ if (wil->platform_ops.bus_request) {
+ wil->bus_request_kbps = kbps;
wil->platform_ops.bus_request(wil->platform_handle, kbps);
+ }
}
/**
@@ -901,6 +909,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 +976,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 +1061,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/pcie_bus.c b/drivers/net/wireless/ath/wil6210/pcie_bus.c
index 2a515e848820..8d3d25333ba5 100644
--- a/drivers/net/wireless/ath/wil6210/pcie_bus.c
+++ b/drivers/net/wireless/ath/wil6210/pcie_bus.c
@@ -112,8 +112,6 @@ static int wil_if_pcie_enable(struct wil6210_priv *wil)
wil_dbg_misc(wil, "if_pcie_enable, wmi_only %d\n", wmi_only);
- pdev->msi_enabled = 0;
-
pci_set_master(pdev);
wil_dbg_misc(wil, "Setup %s interrupt\n", use_msi ? "MSI" : "INTx");
@@ -249,7 +247,7 @@ static int wil_pcie_probe(struct pci_dev *pdev, const struct pci_device_id *id)
}
rc = pci_enable_device(pdev);
- if (rc) {
+ if (rc && pdev->msi_enabled == 0) {
wil_err(wil,
"pci_enable_device failed, retry with MSI only\n");
/* Work around for platforms that can't allocate IRQ:
@@ -264,6 +262,7 @@ static int wil_pcie_probe(struct pci_dev *pdev, const struct pci_device_id *id)
goto err_plat;
}
/* rollback to err_disable_pdev */
+ pci_set_power_state(pdev, PCI_D0);
rc = pci_request_region(pdev, 0, WIL_NAME);
if (rc) {
@@ -284,6 +283,15 @@ static int wil_pcie_probe(struct pci_dev *pdev, const struct pci_device_id *id)
wil_set_capabilities(wil);
wil6210_clear_irq(wil);
+ wil->keep_radio_on_during_sleep =
+ wil->platform_ops.keep_radio_on_during_sleep &&
+ wil->platform_ops.keep_radio_on_during_sleep(
+ wil->platform_handle) &&
+ test_bit(WMI_FW_CAPABILITY_D3_SUSPEND, wil->fw_capabilities);
+
+ wil_info(wil, "keep_radio_on_during_sleep (%d)\n",
+ wil->keep_radio_on_during_sleep);
+
/* FW should raise IRQ when ready */
rc = wil_if_pcie_enable(wil);
if (rc) {
@@ -383,15 +391,16 @@ static int wil6210_suspend(struct device *dev, bool is_runtime)
goto out;
rc = wil_suspend(wil, is_runtime);
- if (rc)
- goto out;
-
- /* TODO: how do I bring card in low power state? */
-
- /* disable bus mastering */
- pci_clear_master(pdev);
- /* PCI will call pci_save_state(pdev) and pci_prepare_to_sleep(pdev) */
+ if (!rc) {
+ wil->suspend_stats.successful_suspends++;
+ /* If platform device supports keep_radio_on_during_sleep
+ * it will control PCIe master
+ */
+ if (!wil->keep_radio_on_during_sleep)
+ /* disable bus mastering */
+ pci_clear_master(pdev);
+ }
out:
return rc;
}
@@ -404,12 +413,21 @@ static int wil6210_resume(struct device *dev, bool is_runtime)
wil_dbg_pm(wil, "resume: %s\n", is_runtime ? "runtime" : "system");
- /* allow master */
- pci_set_master(pdev);
-
+ /* If platform device supports keep_radio_on_during_sleep it will
+ * control PCIe master
+ */
+ if (!wil->keep_radio_on_during_sleep)
+ /* allow master */
+ pci_set_master(pdev);
rc = wil_resume(wil, is_runtime);
- if (rc)
- pci_clear_master(pdev);
+ if (rc) {
+ wil_err(wil, "device failed to resume (%d)\n", rc);
+ wil->suspend_stats.failed_resumes++;
+ if (!wil->keep_radio_on_during_sleep)
+ pci_clear_master(pdev);
+ } else {
+ wil->suspend_stats.successful_resumes++;
+ }
return rc;
}
diff --git a/drivers/net/wireless/ath/wil6210/pm.c b/drivers/net/wireless/ath/wil6210/pm.c
index 2ae4fe85cc8c..015dc3c1493f 100644
--- a/drivers/net/wireless/ath/wil6210/pm.c
+++ b/drivers/net/wireless/ath/wil6210/pm.c
@@ -15,6 +15,7 @@
*/
#include "wil6210.h"
+#include <linux/jiffies.h>
int wil_can_suspend(struct wil6210_priv *wil, bool is_runtime)
{
@@ -61,21 +62,165 @@ out:
wil_dbg_pm(wil, "can_suspend: %s => %s (%d)\n",
is_runtime ? "runtime" : "system", rc ? "No" : "Yes", rc);
+ if (rc)
+ wil->suspend_stats.rejected_by_host++;
+
return rc;
}
-int wil_suspend(struct wil6210_priv *wil, bool is_runtime)
+static int wil_resume_keep_radio_on(struct wil6210_priv *wil)
{
int rc = 0;
- struct net_device *ndev = wil_to_ndev(wil);
- wil_dbg_pm(wil, "suspend: %s\n", is_runtime ? "runtime" : "system");
+ /* wil_status_resuming will be cleared when getting
+ * WMI_TRAFFIC_RESUME_EVENTID
+ */
+ set_bit(wil_status_resuming, wil->status);
+ clear_bit(wil_status_suspended, wil->status);
+ wil_c(wil, RGF_USER_CLKS_CTL_0, BIT_USER_CLKS_RST_PWGD);
+ wil_unmask_irq(wil);
- if (test_bit(wil_status_suspended, wil->status)) {
- wil_dbg_pm(wil, "trying to suspend while suspended\n");
- return 0;
+ /* Send WMI resume request to the device */
+ rc = wmi_resume(wil);
+ if (rc) {
+ wil_err(wil, "device failed to resume (%d), resetting\n", rc);
+ rc = wil_down(wil);
+ if (rc) {
+ wil_err(wil, "wil_down failed (%d)\n", rc);
+ goto out;
+ }
+ rc = wil_up(wil);
+ if (rc) {
+ wil_err(wil, "wil_up failed (%d)\n", rc);
+ goto out;
+ }
+ }
+
+ wil6210_bus_request(wil, wil->bus_request_kbps_pre_suspend);
+
+out:
+ if (rc)
+ set_bit(wil_status_suspended, wil->status);
+ return rc;
+}
+
+static int wil_suspend_keep_radio_on(struct wil6210_priv *wil)
+{
+ int rc = 0;
+ unsigned long start, data_comp_to;
+
+ wil_dbg_pm(wil, "suspend keep radio on\n");
+
+ /* Prevent handling of new tx and wmi commands */
+ set_bit(wil_status_suspending, wil->status);
+
+ if (!wil_is_tx_idle(wil)) {
+ wil_dbg_pm(wil, "Pending TX data, reject suspend\n");
+ wil->suspend_stats.rejected_by_host++;
+ goto reject_suspend;
}
+ if (!wil_is_rx_idle(wil)) {
+ wil_dbg_pm(wil, "Pending RX data, reject suspend\n");
+ wil->suspend_stats.rejected_by_host++;
+ goto reject_suspend;
+ }
+
+ if (!wil_is_wmi_idle(wil)) {
+ wil_dbg_pm(wil, "Pending WMI events, reject suspend\n");
+ wil->suspend_stats.rejected_by_host++;
+ goto reject_suspend;
+ }
+
+ /* Send WMI suspend request to the device */
+ rc = wmi_suspend(wil);
+ if (rc) {
+ wil_dbg_pm(wil, "wmi_suspend failed, reject suspend (%d)\n",
+ rc);
+ goto reject_suspend;
+ }
+
+ /* Wait for completion of the pending RX packets */
+ start = jiffies;
+ data_comp_to = jiffies + msecs_to_jiffies(WIL_DATA_COMPLETION_TO_MS);
+ if (test_bit(wil_status_napi_en, wil->status)) {
+ while (!wil_is_rx_idle(wil)) {
+ if (time_after(jiffies, data_comp_to)) {
+ if (wil_is_rx_idle(wil))
+ break;
+ wil_err(wil,
+ "TO waiting for idle RX, suspend failed\n");
+ wil->suspend_stats.failed_suspends++;
+ goto resume_after_fail;
+ }
+ wil_dbg_ratelimited(wil, "rx vring is not empty -> NAPI\n");
+ napi_synchronize(&wil->napi_rx);
+ msleep(20);
+ }
+ }
+
+ /* In case of pending WMI events, reject the suspend
+ * and resume the device.
+ * This can happen if the device sent the WMI events before
+ * approving the suspend.
+ */
+ if (!wil_is_wmi_idle(wil)) {
+ wil_err(wil, "suspend failed due to pending WMI events\n");
+ wil->suspend_stats.failed_suspends++;
+ goto resume_after_fail;
+ }
+
+ wil_mask_irq(wil);
+
+ /* Disable device reset on PERST */
+ wil_s(wil, RGF_USER_CLKS_CTL_0, BIT_USER_CLKS_RST_PWGD);
+
+ /* Save the current bus request to return to the same in resume */
+ wil->bus_request_kbps_pre_suspend = wil->bus_request_kbps;
+ wil6210_bus_request(wil, 0);
+
+ if (wil->platform_ops.suspend) {
+ rc = wil->platform_ops.suspend(wil->platform_handle, true);
+ if (rc) {
+ wil_err(wil, "platform device failed to suspend (%d)\n",
+ rc);
+ wil->suspend_stats.failed_suspends++;
+ clear_bit(wil_status_suspending, wil->status);
+ rc = wil_resume_keep_radio_on(wil);
+ /* if resume succeeded, reject the suspend */
+ if (!rc)
+ rc = -EBUSY;
+ goto out;
+ }
+ }
+
+ set_bit(wil_status_suspended, wil->status);
+ clear_bit(wil_status_suspending, wil->status);
+
+ return rc;
+
+resume_after_fail:
+ clear_bit(wil_status_suspending, wil->status);
+ rc = wmi_resume(wil);
+ /* if resume succeeded, reject the suspend */
+ if (!rc)
+ rc = -EBUSY;
+
+out:
+ return rc;
+
+reject_suspend:
+ clear_bit(wil_status_suspending, wil->status);
+ return -EBUSY;
+}
+
+static int wil_suspend_radio_off(struct wil6210_priv *wil)
+{
+ int rc = 0;
+ struct net_device *ndev = wil_to_ndev(wil);
+
+ wil_dbg_pm(wil, "suspend radio off\n");
+
/* if netif up, hardware is alive, shut it down */
if (ndev->flags & IFF_UP) {
rc = wil_down(wil);
@@ -90,7 +235,7 @@ int wil_suspend(struct wil6210_priv *wil, bool is_runtime)
wil_disable_irq(wil);
if (wil->platform_ops.suspend) {
- rc = wil->platform_ops.suspend(wil->platform_handle);
+ rc = wil->platform_ops.suspend(wil->platform_handle, false);
if (rc) {
wil_enable_irq(wil);
goto out;
@@ -100,6 +245,50 @@ int wil_suspend(struct wil6210_priv *wil, bool is_runtime)
set_bit(wil_status_suspended, wil->status);
out:
+ wil_dbg_pm(wil, "suspend radio off: %d\n", rc);
+
+ return rc;
+}
+
+static int wil_resume_radio_off(struct wil6210_priv *wil)
+{
+ int rc = 0;
+ struct net_device *ndev = wil_to_ndev(wil);
+
+ wil_dbg_pm(wil, "Enabling PCIe IRQ\n");
+ wil_enable_irq(wil);
+ /* if netif up, bring hardware up
+ * During open(), IFF_UP set after actual device method
+ * invocation. This prevent recursive call to wil_up()
+ * wil_status_suspended will be cleared in wil_reset
+ */
+ if (ndev->flags & IFF_UP)
+ rc = wil_up(wil);
+ else
+ clear_bit(wil_status_suspended, wil->status);
+
+ return rc;
+}
+
+int wil_suspend(struct wil6210_priv *wil, bool is_runtime)
+{
+ int rc = 0;
+ struct net_device *ndev = wil_to_ndev(wil);
+ bool keep_radio_on = ndev->flags & IFF_UP &&
+ wil->keep_radio_on_during_sleep;
+
+ wil_dbg_pm(wil, "suspend: %s\n", is_runtime ? "runtime" : "system");
+
+ if (test_bit(wil_status_suspended, wil->status)) {
+ wil_dbg_pm(wil, "trying to suspend while suspended\n");
+ return 0;
+ }
+
+ if (!keep_radio_on)
+ rc = wil_suspend_radio_off(wil);
+ else
+ rc = wil_suspend_keep_radio_on(wil);
+
wil_dbg_pm(wil, "suspend: %s => %d\n",
is_runtime ? "runtime" : "system", rc);
@@ -110,29 +299,24 @@ int wil_resume(struct wil6210_priv *wil, bool is_runtime)
{
int rc = 0;
struct net_device *ndev = wil_to_ndev(wil);
+ bool keep_radio_on = ndev->flags & IFF_UP &&
+ wil->keep_radio_on_during_sleep;
wil_dbg_pm(wil, "resume: %s\n", is_runtime ? "runtime" : "system");
if (wil->platform_ops.resume) {
- rc = wil->platform_ops.resume(wil->platform_handle);
+ rc = wil->platform_ops.resume(wil->platform_handle,
+ keep_radio_on);
if (rc) {
wil_err(wil, "platform_ops.resume : %d\n", rc);
goto out;
}
}
- wil_dbg_pm(wil, "Enabling PCIe IRQ\n");
- wil_enable_irq(wil);
-
- /* if netif up, bring hardware up
- * During open(), IFF_UP set after actual device method
- * invocation. This prevent recursive call to wil_up().
- * wil_status_suspended will be cleared in wil_reset
- */
- if (ndev->flags & IFF_UP)
- rc = wil_up(wil);
+ if (keep_radio_on)
+ rc = wil_resume_keep_radio_on(wil);
else
- clear_bit(wil_status_suspended, wil->status);
+ rc = wil_resume_radio_off(wil);
out:
wil_dbg_pm(wil, "resume: %s => %d\n",
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..439fe30936b6 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;
@@ -100,6 +104,51 @@ static inline int wil_vring_avail_high(struct vring *vring)
return wil_vring_avail_tx(vring) > wil_vring_wmark_high(vring);
}
+/* returns true when all tx vrings are empty */
+bool wil_is_tx_idle(struct wil6210_priv *wil)
+{
+ int i;
+ unsigned long data_comp_to;
+
+ for (i = 0; i < WIL6210_MAX_TX_RINGS; i++) {
+ struct vring *vring = &wil->vring_tx[i];
+ int vring_index = vring - wil->vring_tx;
+ struct vring_tx_data *txdata = &wil->vring_tx_data[vring_index];
+
+ spin_lock(&txdata->lock);
+
+ if (!vring->va || !txdata->enabled) {
+ spin_unlock(&txdata->lock);
+ continue;
+ }
+
+ data_comp_to = jiffies + msecs_to_jiffies(
+ WIL_DATA_COMPLETION_TO_MS);
+ if (test_bit(wil_status_napi_en, wil->status)) {
+ while (!wil_vring_is_empty(vring)) {
+ if (time_after(jiffies, data_comp_to)) {
+ wil_dbg_pm(wil,
+ "TO waiting for idle tx\n");
+ spin_unlock(&txdata->lock);
+ return false;
+ }
+ wil_dbg_ratelimited(wil,
+ "tx vring is not empty -> NAPI\n");
+ spin_unlock(&txdata->lock);
+ napi_synchronize(&wil->napi_tx);
+ msleep(20);
+ spin_lock(&txdata->lock);
+ if (!vring->va || !txdata->enabled)
+ break;
+ }
+ }
+
+ spin_unlock(&txdata->lock);
+ }
+
+ return true;
+}
+
/* wil_val_in_range - check if value in [min,max) */
static inline bool wil_val_in_range(int val, int min, int max)
{
@@ -255,7 +304,7 @@ static int wil_vring_alloc_skb(struct wil6210_priv *wil, struct vring *vring,
u32 i, int headroom)
{
struct device *dev = wil_to_dev(wil);
- unsigned int sz = mtu_max + ETH_HLEN + wil_rx_snaplen();
+ unsigned int sz = wil->rx_buf_len + ETH_HLEN + wil_rx_snaplen();
struct vring_rx_desc dd, *d = &dd;
volatile struct vring_rx_desc *_d = &vring->va[i].rx;
dma_addr_t pa;
@@ -402,6 +451,18 @@ static inline int wil_is_back_req(u8 fc)
(IEEE80211_FTYPE_CTL | IEEE80211_STYPE_BACK_REQ);
}
+bool wil_is_rx_idle(struct wil6210_priv *wil)
+{
+ struct vring_rx_desc *_d;
+ struct vring *vring = &wil->vring_rx;
+
+ _d = (struct vring_rx_desc *)&vring->va[vring->swhead].rx;
+ if (_d->dma.status & RX_DMA_STATUS_DU)
+ return false;
+
+ return true;
+}
+
/**
* reap 1 frame from @swhead
*
@@ -419,7 +480,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 +841,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 +867,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)
@@ -1792,6 +1869,15 @@ static int wil_tx_vring(struct wil6210_priv *wil, struct vring *vring,
spin_lock(&txdata->lock);
+ if (test_bit(wil_status_suspending, wil->status) ||
+ test_bit(wil_status_suspended, wil->status) ||
+ test_bit(wil_status_resuming, wil->status)) {
+ wil_dbg_txrx(wil,
+ "suspend/resume in progress. drop packet\n");
+ spin_unlock(&txdata->lock);
+ return -EINVAL;
+ }
+
rc = (skb_is_gso(skb) ? __wil_tx_vring_tso : __wil_tx_vring)
(wil, vring, skb);
diff --git a/drivers/net/wireless/ath/wil6210/wil6210.h b/drivers/net/wireless/ath/wil6210/wil6210.h
index 0529d10a8268..e76ec6ed9995 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;
@@ -82,6 +83,15 @@ static inline u32 WIL_GET_BITS(u32 x, int b0, int b1)
*/
#define WIL_MAX_MPDU_OVERHEAD (62)
+struct wil_suspend_stats {
+ unsigned long successful_suspends;
+ unsigned long failed_suspends;
+ unsigned long successful_resumes;
+ unsigned long failed_resumes;
+ unsigned long rejected_by_device;
+ unsigned long rejected_by_host;
+};
+
/* Calculate MAC buffer size for the firmware. It includes all overhead,
* as it will go over the air, and need to be 8 byte aligned
*/
@@ -295,6 +305,8 @@ enum {
#define ISR_MISC_MBOX_EVT BIT_DMA_EP_MISC_ICR_FW_INT(1)
#define ISR_MISC_FW_ERROR BIT_DMA_EP_MISC_ICR_FW_INT(3)
+#define WIL_DATA_COMPLETION_TO_MS 200
+
/* Hardware definitions end */
struct fw_map {
u32 from; /* linker address - from, inclusive */
@@ -423,7 +435,9 @@ enum { /* for wil6210_priv.status */
wil_status_irqen, /* FIXME: interrupts enabled - for debug */
wil_status_napi_en, /* NAPI enabled protected by wil->mutex */
wil_status_resetting, /* reset in progress */
+ wil_status_suspending, /* suspend in progress */
wil_status_suspended, /* suspend completed, device is suspended */
+ wil_status_resuming, /* resume in progress */
wil_status_last /* keep last */
};
@@ -670,6 +684,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 */
@@ -687,9 +702,12 @@ struct wil6210_priv {
struct wil_blob_wrapper blobs[ARRAY_SIZE(fw_mapping)];
u8 discovery_mode;
u8 abft_len;
+ u8 wakeup_trigger;
+ struct wil_suspend_stats suspend_stats;
void *platform_handle;
struct wil_platform_ops platform_ops;
+ bool keep_radio_on_during_sleep;
struct pmc_ctx pmc;
@@ -705,6 +723,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;
@@ -714,6 +734,11 @@ struct wil6210_priv {
struct notifier_block pm_notify;
#endif /* CONFIG_PM_SLEEP */
#endif /* CONFIG_PM */
+
+ bool suspend_resp_rcvd;
+ bool suspend_resp_comp;
+ u32 bus_request_kbps;
+ u32 bus_request_kbps_pre_suspend;
};
#define wil_to_wiphy(i) (i->wdev->wiphy)
@@ -824,6 +849,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);
@@ -974,6 +1001,11 @@ bool wil_fw_verify_file_exists(struct wil6210_priv *wil, const char *name);
int wil_can_suspend(struct wil6210_priv *wil, bool is_runtime);
int wil_suspend(struct wil6210_priv *wil, bool is_runtime);
int wil_resume(struct wil6210_priv *wil, bool is_runtime);
+bool wil_is_wmi_idle(struct wil6210_priv *wil);
+int wmi_resume(struct wil6210_priv *wil);
+int wmi_suspend(struct wil6210_priv *wil);
+bool wil_is_tx_idle(struct wil6210_priv *wil);
+bool wil_is_rx_idle(struct wil6210_priv *wil);
int wil_fw_copy_crash_dump(struct wil6210_priv *wil, void *dest, u32 size);
void wil_fw_core_dump(struct wil6210_priv *wil);
diff --git a/drivers/net/wireless/ath/wil6210/wil_platform.h b/drivers/net/wireless/ath/wil6210/wil_platform.h
index f8c41172a3f4..621005b0c5ca 100644
--- a/drivers/net/wireless/ath/wil6210/wil_platform.h
+++ b/drivers/net/wireless/ath/wil6210/wil_platform.h
@@ -33,10 +33,11 @@ enum wil_platform_event {
*/
struct wil_platform_ops {
int (*bus_request)(void *handle, uint32_t kbps /* KBytes/Sec */);
- int (*suspend)(void *handle);
- int (*resume)(void *handle);
+ int (*suspend)(void *handle, bool keep_device_power);
+ int (*resume)(void *handle, bool device_powered_on);
void (*uninit)(void *handle);
int (*notify)(void *handle, enum wil_platform_event evt);
+ bool (*keep_radio_on_during_sleep)(void *handle);
};
/**
diff --git a/drivers/net/wireless/ath/wil6210/wmi.c b/drivers/net/wireless/ath/wil6210/wmi.c
index 41afbdc34c18..24878ecf7e93 100644
--- a/drivers/net/wireless/ath/wil6210/wmi.c
+++ b/drivers/net/wireless/ath/wil6210/wmi.c
@@ -38,6 +38,8 @@ module_param(led_id, byte, 0444);
MODULE_PARM_DESC(led_id,
" 60G device led enablement. Set the led ID (0-2) to enable");
+#define WIL_WAIT_FOR_SUSPEND_RESUME_COMP 200
+
/**
* WMI event receiving - theory of operations
*
@@ -234,6 +236,16 @@ static int __wmi_send(struct wil6210_priv *wil, u16 cmdid, void *buf, u16 len)
return -EAGAIN;
}
+ /* Allow sending only suspend / resume commands during susepnd flow */
+ if ((test_bit(wil_status_suspending, wil->status) ||
+ test_bit(wil_status_suspended, wil->status) ||
+ test_bit(wil_status_resuming, wil->status)) &&
+ ((cmdid != WMI_TRAFFIC_SUSPEND_CMDID) &&
+ (cmdid != WMI_TRAFFIC_RESUME_CMDID))) {
+ wil_err(wil, "WMI: reject send_command during suspend\n");
+ return -EINVAL;
+ }
+
if (!head) {
wil_err(wil, "WMI head is garbage: 0x%08x\n", r->head);
return -EINVAL;
@@ -893,6 +905,11 @@ void wmi_recv_cmd(struct wil6210_priv *wil)
return;
}
+ if (test_bit(wil_status_suspended, wil->status)) {
+ wil_err(wil, "suspended. cannot handle WMI event\n");
+ return;
+ }
+
for (n = 0;; n++) {
u16 len;
bool q;
@@ -945,6 +962,15 @@ void wmi_recv_cmd(struct wil6210_priv *wil)
struct wmi_cmd_hdr *wmi = &evt->event.wmi;
u16 id = le16_to_cpu(wmi->command_id);
u32 tstamp = le32_to_cpu(wmi->fw_timestamp);
+ if (test_bit(wil_status_resuming, wil->status)) {
+ if (id == WMI_TRAFFIC_RESUME_EVENTID)
+ clear_bit(wil_status_resuming,
+ wil->status);
+ else
+ wil_err(wil,
+ "WMI evt %d while resuming\n",
+ id);
+ }
spin_lock_irqsave(&wil->wmi_ev_lock, flags);
if (wil->reply_id && wil->reply_id == id) {
if (wil->reply_buf) {
@@ -952,6 +978,11 @@ void wmi_recv_cmd(struct wil6210_priv *wil)
min(len, wil->reply_size));
immed_reply = true;
}
+ if (id == WMI_TRAFFIC_SUSPEND_EVENTID) {
+ wil_dbg_wmi(wil,
+ "set suspend_resp_rcvd\n");
+ wil->suspend_resp_rcvd = true;
+ }
}
spin_unlock_irqrestore(&wil->wmi_ev_lock, flags);
@@ -1436,7 +1467,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),
},
@@ -1908,6 +1940,85 @@ int wmi_link_maintain_cfg_write(struct wil6210_priv *wil,
return rc;
}
+int wmi_suspend(struct wil6210_priv *wil)
+{
+ int rc;
+ struct wmi_traffic_suspend_cmd cmd = {
+ .wakeup_trigger = wil->wakeup_trigger,
+ };
+ struct {
+ struct wmi_cmd_hdr wmi;
+ struct wmi_traffic_suspend_event evt;
+ } __packed reply;
+ u32 suspend_to = WIL_WAIT_FOR_SUSPEND_RESUME_COMP;
+
+ wil->suspend_resp_rcvd = false;
+ wil->suspend_resp_comp = false;
+
+ reply.evt.status = WMI_TRAFFIC_SUSPEND_REJECTED;
+
+ rc = wmi_call(wil, WMI_TRAFFIC_SUSPEND_CMDID, &cmd, sizeof(cmd),
+ WMI_TRAFFIC_SUSPEND_EVENTID, &reply, sizeof(reply),
+ suspend_to);
+ if (rc) {
+ wil_err(wil, "wmi_call for suspend req failed, rc=%d\n", rc);
+ if (rc == -ETIME)
+ /* wmi_call TO */
+ wil->suspend_stats.rejected_by_device++;
+ else
+ wil->suspend_stats.rejected_by_host++;
+ goto out;
+ }
+
+ wil_dbg_wmi(wil, "waiting for suspend_response_completed\n");
+
+ rc = wait_event_interruptible_timeout(wil->wq,
+ wil->suspend_resp_comp,
+ msecs_to_jiffies(suspend_to));
+ if (rc == 0) {
+ wil_err(wil, "TO waiting for suspend_response_completed\n");
+ if (wil->suspend_resp_rcvd)
+ /* Device responded but we TO due to another reason */
+ wil->suspend_stats.rejected_by_host++;
+ else
+ wil->suspend_stats.rejected_by_device++;
+ rc = -EBUSY;
+ goto out;
+ }
+
+ wil_dbg_wmi(wil, "suspend_response_completed rcvd\n");
+ if (reply.evt.status == WMI_TRAFFIC_SUSPEND_REJECTED) {
+ wil_dbg_pm(wil, "device rejected the suspend\n");
+ wil->suspend_stats.rejected_by_device++;
+ }
+ rc = reply.evt.status;
+
+out:
+ wil->suspend_resp_rcvd = false;
+ wil->suspend_resp_comp = false;
+
+ return rc;
+}
+
+int wmi_resume(struct wil6210_priv *wil)
+{
+ int rc;
+ struct {
+ struct wmi_cmd_hdr wmi;
+ struct wmi_traffic_resume_event evt;
+ } __packed reply;
+
+ reply.evt.status = WMI_TRAFFIC_RESUME_FAILED;
+
+ rc = wmi_call(wil, WMI_TRAFFIC_RESUME_CMDID, NULL, 0,
+ WMI_TRAFFIC_RESUME_EVENTID, &reply, sizeof(reply),
+ WIL_WAIT_FOR_SUSPEND_RESUME_COMP);
+ if (rc)
+ return rc;
+
+ return reply.evt.status;
+}
+
static bool wmi_evt_call_handler(struct wil6210_priv *wil, int id,
void *d, int len)
{
@@ -1997,3 +2108,36 @@ void wmi_event_worker(struct work_struct *work)
}
wil_dbg_wmi(wil, "event_worker: Finished\n");
}
+
+bool wil_is_wmi_idle(struct wil6210_priv *wil)
+{
+ ulong flags;
+ struct wil6210_mbox_ring *r = &wil->mbox_ctl.rx;
+ bool rc = false;
+
+ spin_lock_irqsave(&wil->wmi_ev_lock, flags);
+
+ /* Check if there are pending WMI events in the events queue */
+ if (!list_empty(&wil->pending_wmi_ev)) {
+ wil_dbg_pm(wil, "Pending WMI events in queue\n");
+ goto out;
+ }
+
+ /* Check if there is a pending WMI call */
+ if (wil->reply_id) {
+ wil_dbg_pm(wil, "Pending WMI call\n");
+ goto out;
+ }
+
+ /* Check if there are pending RX events in mbox */
+ r->head = wil_r(wil, RGF_MBOX +
+ offsetof(struct wil6210_mbox_ctl, rx.head));
+ if (r->tail != r->head)
+ wil_dbg_pm(wil, "Pending WMI mbox events\n");
+ else
+ rc = true;
+
+out:
+ spin_unlock_irqrestore(&wil->wmi_ev_lock, flags);
+ return rc;
+}
diff --git a/drivers/net/wireless/ath/wil6210/wmi.h b/drivers/net/wireless/ath/wil6210/wmi.h
index f7f5f4f801e3..256f63c57da0 100644
--- a/drivers/net/wireless/ath/wil6210/wmi.h
+++ b/drivers/net/wireless/ath/wil6210/wmi.h
@@ -59,6 +59,7 @@ enum wmi_fw_capability {
WMI_FW_CAPABILITY_DISABLE_AP_SME = 4,
WMI_FW_CAPABILITY_WMI_ONLY = 5,
WMI_FW_CAPABILITY_THERMAL_THROTTLING = 7,
+ WMI_FW_CAPABILITY_D3_SUSPEND = 8,
WMI_FW_CAPABILITY_MAX,
};
@@ -157,7 +158,7 @@ enum wmi_command_id {
WMI_FLASH_READ_CMDID = 0x902,
WMI_FLASH_WRITE_CMDID = 0x903,
/* Power management */
- WMI_TRAFFIC_DEFERRAL_CMDID = 0x904,
+ WMI_TRAFFIC_SUSPEND_CMDID = 0x904,
WMI_TRAFFIC_RESUME_CMDID = 0x905,
/* P2P */
WMI_P2P_CFG_CMDID = 0x910,
@@ -500,8 +501,14 @@ struct wmi_port_delete_cmd {
u8 reserved[3];
} __packed;
-/* WMI_TRAFFIC_DEFERRAL_CMDID */
-struct wmi_traffic_deferral_cmd {
+/* WMI_TRAFFIC_SUSPEND_CMD wakeup trigger bit mask values */
+enum wmi_wakeup_trigger {
+ WMI_WAKEUP_TRIGGER_UCAST = 0x01,
+ WMI_WAKEUP_TRIGGER_BCAST = 0x02,
+};
+
+/* WMI_TRAFFIC_SUSPEND_CMDID */
+struct wmi_traffic_suspend_cmd {
/* Bit vector: bit[0] - wake on Unicast, bit[1] - wake on Broadcast */
u8 wakeup_trigger;
} __packed;
@@ -1084,7 +1091,7 @@ enum wmi_event_id {
WMI_FLASH_READ_DONE_EVENTID = 0x1902,
WMI_FLASH_WRITE_DONE_EVENTID = 0x1903,
/* Power management */
- WMI_TRAFFIC_DEFERRAL_EVENTID = 0x1904,
+ WMI_TRAFFIC_SUSPEND_EVENTID = 0x1904,
WMI_TRAFFIC_RESUME_EVENTID = 0x1905,
/* P2P */
WMI_P2P_CFG_DONE_EVENTID = 0x1910,
@@ -1926,14 +1933,14 @@ struct wmi_link_maintain_cfg_read_done_event {
struct wmi_link_maintain_cfg lm_cfg;
} __packed;
-enum wmi_traffic_deferral_status {
- WMI_TRAFFIC_DEFERRAL_APPROVED = 0x0,
- WMI_TRAFFIC_DEFERRAL_REJECTED = 0x1,
+enum wmi_traffic_suspend_status {
+ WMI_TRAFFIC_SUSPEND_APPROVED = 0x0,
+ WMI_TRAFFIC_SUSPEND_REJECTED = 0x1,
};
-/* WMI_TRAFFIC_DEFERRAL_EVENTID */
-struct wmi_traffic_deferral_event {
- /* enum wmi_traffic_deferral_status_e */
+/* WMI_TRAFFIC_SUSPEND_EVENTID */
+struct wmi_traffic_suspend_event {
+ /* enum wmi_traffic_suspend_status_e */
u8 status;
} __packed;
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/pci/host/pci-msm.c b/drivers/pci/host/pci-msm.c
index 243afbe44df3..8bb759d10074 100644
--- a/drivers/pci/host/pci-msm.c
+++ b/drivers/pci/host/pci-msm.c
@@ -6449,7 +6449,6 @@ static int msm_pcie_probe(struct platform_device *pdev)
}
dev_set_drvdata(&msm_pcie_dev[rc_idx].pdev->dev, &msm_pcie_dev[rc_idx]);
- msm_pcie_sysfs_init(&msm_pcie_dev[rc_idx]);
ret = msm_pcie_get_resources(&msm_pcie_dev[rc_idx],
msm_pcie_dev[rc_idx].pdev);
@@ -6500,6 +6499,8 @@ static int msm_pcie_probe(struct platform_device *pdev)
goto decrease_rc_num;
}
+ msm_pcie_sysfs_init(&msm_pcie_dev[rc_idx]);
+
msm_pcie_dev[rc_idx].drv_ready = true;
if (msm_pcie_dev[rc_idx].boot_option &
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_i.h b/drivers/platform/msm/ipa/ipa_v2/ipa_i.h
index a14d1fee9c35..bb11230c960a 100644
--- a/drivers/platform/msm/ipa/ipa_v2/ipa_i.h
+++ b/drivers/platform/msm/ipa/ipa_v2/ipa_i.h
@@ -51,6 +51,7 @@
#define IPA_UC_FINISH_MAX 6
#define IPA_UC_WAIT_MIN_SLEEP 1000
#define IPA_UC_WAII_MAX_SLEEP 1200
+#define IPA_BAM_STOP_MAX_RETRY 10
#define IPA_MAX_STATUS_STAT_NUM 30
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_uc.c b/drivers/platform/msm/ipa/ipa_v2/ipa_uc.c
index 3dd2eb093317..364cd4b7d38a 100644
--- a/drivers/platform/msm/ipa/ipa_v2/ipa_uc.c
+++ b/drivers/platform/msm/ipa/ipa_v2/ipa_uc.c
@@ -590,6 +590,7 @@ int ipa_uc_send_cmd(u32 cmd, u32 opcode, u32 expected_status,
{
int index;
union IpaHwCpuCmdCompletedResponseData_t uc_rsp;
+ int retries = 0;
mutex_lock(&ipa_ctx->uc_ctx.uc_lock);
@@ -599,6 +600,7 @@ int ipa_uc_send_cmd(u32 cmd, u32 opcode, u32 expected_status,
return -EBADF;
}
+send_cmd:
init_completion(&ipa_ctx->uc_ctx.uc_completion);
ipa_ctx->uc_ctx.uc_sram_mmio->cmdParams = cmd;
@@ -658,6 +660,19 @@ int ipa_uc_send_cmd(u32 cmd, u32 opcode, u32 expected_status,
}
if (ipa_ctx->uc_ctx.uc_status != expected_status) {
+ if (IPA_HW_2_CPU_WDI_RX_FSM_TRANSITION_ERROR ==
+ ipa_ctx->uc_ctx.uc_status) {
+ retries++;
+ if (retries == IPA_BAM_STOP_MAX_RETRY) {
+ IPAERR("Failed after %d tries\n", retries);
+ } else {
+ /* sleep for short period to flush IPA */
+ usleep_range(IPA_UC_WAIT_MIN_SLEEP,
+ IPA_UC_WAII_MAX_SLEEP);
+ goto send_cmd;
+ }
+ }
+
IPAERR("Recevied status %u, Expected status %u\n",
ipa_ctx->uc_ctx.uc_status, expected_status);
ipa_ctx->uc_ctx.pending_cmd = -1;
diff --git a/drivers/platform/msm/ipa/ipa_v2/ipa_uc_offload_i.h b/drivers/platform/msm/ipa/ipa_v2/ipa_uc_offload_i.h
index 3bec471b4656..a98d60249c0e 100644
--- a/drivers/platform/msm/ipa/ipa_v2/ipa_uc_offload_i.h
+++ b/drivers/platform/msm/ipa/ipa_v2/ipa_uc_offload_i.h
@@ -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
@@ -441,7 +441,7 @@ enum ipa_hw_offload_channel_states {
/**
- * enum ipa_hw_2_cpu_cmd_resp_status - Values that represent
+ * enum ipa_hw_2_cpu_offload_cmd_resp_status - Values that represent
* offload related command response status to be sent to CPU.
*/
enum ipa_hw_2_cpu_offload_cmd_resp_status {
@@ -478,6 +478,47 @@ enum ipa_hw_2_cpu_offload_cmd_resp_status {
};
/**
+ * enum ipa_hw_2_cpu_cmd_resp_status - Values that represent WDI related
+ * command response status to be sent to CPU.
+ */
+enum ipa_hw_2_cpu_cmd_resp_status {
+ IPA_HW_2_CPU_WDI_CMD_STATUS_SUCCESS =
+ FEATURE_ENUM_VAL(IPA_HW_FEATURE_WDI, 0),
+ IPA_HW_2_CPU_MAX_WDI_TX_CHANNELS =
+ FEATURE_ENUM_VAL(IPA_HW_FEATURE_WDI, 1),
+ IPA_HW_2_CPU_WDI_CE_RING_OVERRUN_POSSIBILITY =
+ FEATURE_ENUM_VAL(IPA_HW_FEATURE_WDI, 2),
+ IPA_HW_2_CPU_WDI_CE_RING_SET_UP_FAILURE =
+ FEATURE_ENUM_VAL(IPA_HW_FEATURE_WDI, 3),
+ IPA_HW_2_CPU_WDI_CE_RING_PARAMS_UNALIGNED =
+ FEATURE_ENUM_VAL(IPA_HW_FEATURE_WDI, 4),
+ IPA_HW_2_CPU_WDI_COMP_RING_OVERRUN_POSSIBILITY =
+ FEATURE_ENUM_VAL(IPA_HW_FEATURE_WDI, 5),
+ IPA_HW_2_CPU_WDI_COMP_RING_SET_UP_FAILURE =
+ FEATURE_ENUM_VAL(IPA_HW_FEATURE_WDI, 6),
+ IPA_HW_2_CPU_WDI_COMP_RING_PARAMS_UNALIGNED =
+ FEATURE_ENUM_VAL(IPA_HW_FEATURE_WDI, 7),
+ IPA_HW_2_CPU_WDI_UNKNOWN_TX_CHANNEL =
+ FEATURE_ENUM_VAL(IPA_HW_FEATURE_WDI, 8),
+ IPA_HW_2_CPU_WDI_TX_INVALID_FSM_TRANSITION =
+ FEATURE_ENUM_VAL(IPA_HW_FEATURE_WDI, 9),
+ IPA_HW_2_CPU_WDI_TX_FSM_TRANSITION_ERROR =
+ FEATURE_ENUM_VAL(IPA_HW_FEATURE_WDI, 10),
+ IPA_HW_2_CPU_MAX_WDI_RX_CHANNELS =
+ FEATURE_ENUM_VAL(IPA_HW_FEATURE_WDI, 11),
+ IPA_HW_2_CPU_WDI_RX_RING_PARAMS_UNALIGNED =
+ FEATURE_ENUM_VAL(IPA_HW_FEATURE_WDI, 12),
+ IPA_HW_2_CPU_WDI_RX_RING_SET_UP_FAILURE =
+ FEATURE_ENUM_VAL(IPA_HW_FEATURE_WDI, 13),
+ IPA_HW_2_CPU_WDI_UNKNOWN_RX_CHANNEL =
+ FEATURE_ENUM_VAL(IPA_HW_FEATURE_WDI, 14),
+ IPA_HW_2_CPU_WDI_RX_INVALID_FSM_TRANSITION =
+ FEATURE_ENUM_VAL(IPA_HW_FEATURE_WDI, 15),
+ IPA_HW_2_CPU_WDI_RX_FSM_TRANSITION_ERROR =
+ FEATURE_ENUM_VAL(IPA_HW_FEATURE_WDI, 16),
+};
+
+/**
* struct IpaHwSetUpCmd -
*
*
diff --git a/drivers/platform/msm/ipa/ipa_v2/ipa_uc_wdi.c b/drivers/platform/msm/ipa/ipa_v2/ipa_uc_wdi.c
index f60669132865..56b4bf1a2d1e 100644
--- a/drivers/platform/msm/ipa/ipa_v2/ipa_uc_wdi.c
+++ b/drivers/platform/msm/ipa/ipa_v2/ipa_uc_wdi.c
@@ -110,47 +110,6 @@ enum ipa_cpu_2_hw_wdi_commands {
};
/**
- * enum ipa_hw_2_cpu_cmd_resp_status - Values that represent WDI related
- * command response status to be sent to CPU.
- */
-enum ipa_hw_2_cpu_cmd_resp_status {
- IPA_HW_2_CPU_WDI_CMD_STATUS_SUCCESS =
- FEATURE_ENUM_VAL(IPA_HW_FEATURE_WDI, 0),
- IPA_HW_2_CPU_MAX_WDI_TX_CHANNELS =
- FEATURE_ENUM_VAL(IPA_HW_FEATURE_WDI, 1),
- IPA_HW_2_CPU_WDI_CE_RING_OVERRUN_POSSIBILITY =
- FEATURE_ENUM_VAL(IPA_HW_FEATURE_WDI, 2),
- IPA_HW_2_CPU_WDI_CE_RING_SET_UP_FAILURE =
- FEATURE_ENUM_VAL(IPA_HW_FEATURE_WDI, 3),
- IPA_HW_2_CPU_WDI_CE_RING_PARAMS_UNALIGNED =
- FEATURE_ENUM_VAL(IPA_HW_FEATURE_WDI, 4),
- IPA_HW_2_CPU_WDI_COMP_RING_OVERRUN_POSSIBILITY =
- FEATURE_ENUM_VAL(IPA_HW_FEATURE_WDI, 5),
- IPA_HW_2_CPU_WDI_COMP_RING_SET_UP_FAILURE =
- FEATURE_ENUM_VAL(IPA_HW_FEATURE_WDI, 6),
- IPA_HW_2_CPU_WDI_COMP_RING_PARAMS_UNALIGNED =
- FEATURE_ENUM_VAL(IPA_HW_FEATURE_WDI, 7),
- IPA_HW_2_CPU_WDI_UNKNOWN_TX_CHANNEL =
- FEATURE_ENUM_VAL(IPA_HW_FEATURE_WDI, 8),
- IPA_HW_2_CPU_WDI_TX_INVALID_FSM_TRANSITION =
- FEATURE_ENUM_VAL(IPA_HW_FEATURE_WDI, 9),
- IPA_HW_2_CPU_WDI_TX_FSM_TRANSITION_ERROR =
- FEATURE_ENUM_VAL(IPA_HW_FEATURE_WDI, 10),
- IPA_HW_2_CPU_MAX_WDI_RX_CHANNELS =
- FEATURE_ENUM_VAL(IPA_HW_FEATURE_WDI, 11),
- IPA_HW_2_CPU_WDI_RX_RING_PARAMS_UNALIGNED =
- FEATURE_ENUM_VAL(IPA_HW_FEATURE_WDI, 12),
- IPA_HW_2_CPU_WDI_RX_RING_SET_UP_FAILURE =
- FEATURE_ENUM_VAL(IPA_HW_FEATURE_WDI, 13),
- IPA_HW_2_CPU_WDI_UNKNOWN_RX_CHANNEL =
- FEATURE_ENUM_VAL(IPA_HW_FEATURE_WDI, 14),
- IPA_HW_2_CPU_WDI_RX_INVALID_FSM_TRANSITION =
- FEATURE_ENUM_VAL(IPA_HW_FEATURE_WDI, 15),
- IPA_HW_2_CPU_WDI_RX_FSM_TRANSITION_ERROR =
- FEATURE_ENUM_VAL(IPA_HW_FEATURE_WDI, 16),
-};
-
-/**
* enum ipa_hw_wdi_errors - WDI specific error types.
* @IPA_HW_WDI_ERROR_NONE : No error persists
* @IPA_HW_WDI_CHANNEL_ERROR : Error is specific to channel
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_uc_wdi.c b/drivers/platform/msm/ipa/ipa_v3/ipa_uc_wdi.c
index 57fa2465c9ea..e49bdc8c7083 100644
--- a/drivers/platform/msm/ipa/ipa_v3/ipa_uc_wdi.c
+++ b/drivers/platform/msm/ipa/ipa_v3/ipa_uc_wdi.c
@@ -1205,6 +1205,8 @@ int ipa3_connect_wdi_pipe(struct ipa_wdi_in_params *in,
IPADBG("Skipping endpoint configuration.\n");
}
+ ipa3_enable_data_path(ipa_ep_idx);
+
out->clnt_hdl = ipa_ep_idx;
if (!ep->skip_ep_cfg && IPA_CLIENT_IS_PROD(in->sys.client))
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_11ad/msm_11ad.c b/drivers/platform/msm/msm_11ad/msm_11ad.c
index f1e348969c7b..4d4aad84b9d7 100644
--- a/drivers/platform/msm/msm_11ad/msm_11ad.c
+++ b/drivers/platform/msm/msm_11ad/msm_11ad.c
@@ -40,9 +40,6 @@
#define SMMU_SIZE ((SZ_1G * 4ULL) - SMMU_BASE)
#define WIGIG_ENABLE_DELAY 50
-#define PM_OPT_SUSPEND (MSM_PCIE_CONFIG_NO_CFG_RESTORE | \
- MSM_PCIE_CONFIG_LINKDOWN)
-#define PM_OPT_RESUME MSM_PCIE_CONFIG_NO_CFG_RESTORE
#define WIGIG_SUBSYS_NAME "WIGIG"
#define WIGIG_RAMDUMP_SIZE 0x200000 /* maximum ramdump size */
@@ -127,6 +124,8 @@ struct msm11ad_ctx {
bool use_cpu_boost;
bool is_cpu_boosted;
struct cpumask boost_cpu;
+
+ bool keep_radio_on_during_sleep;
};
static LIST_HEAD(dev_list);
@@ -523,30 +522,8 @@ int msm_11ad_ctrl_aspm_l1(struct msm11ad_ctx *ctx, bool enable)
return rc;
}
-static int ops_suspend(void *handle)
+static int msm_11ad_turn_device_power_off(struct msm11ad_ctx *ctx)
{
- int rc;
- struct msm11ad_ctx *ctx = handle;
- struct pci_dev *pcidev;
-
- pr_info("%s(%p)\n", __func__, handle);
- if (!ctx) {
- pr_err("No context\n");
- return -ENODEV;
- }
- pcidev = ctx->pcidev;
- rc = pci_save_state(pcidev);
- if (rc) {
- dev_err(ctx->dev, "pci_save_state failed :%d\n", rc);
- return rc;
- }
- rc = msm_pcie_pm_control(MSM_PCIE_SUSPEND, pcidev->bus->number,
- pcidev, NULL, PM_OPT_SUSPEND);
- if (rc) {
- dev_err(ctx->dev, "msm_pcie_pm_control(SUSPEND) failed :%d\n",
- rc);
- return rc;
- }
if (ctx->gpio_en >= 0)
gpio_direction_output(ctx->gpio_en, 0);
@@ -557,20 +534,12 @@ static int ops_suspend(void *handle)
msm_11ad_disable_vregs(ctx);
- return rc;
+ return 0;
}
-static int ops_resume(void *handle)
+static int msm_11ad_turn_device_power_on(struct msm11ad_ctx *ctx)
{
int rc;
- struct msm11ad_ctx *ctx = handle;
- struct pci_dev *pcidev;
-
- pr_info("%s(%p)\n", __func__, handle);
- if (!ctx) {
- pr_err("No context\n");
- return -ENODEV;
- }
rc = msm_11ad_enable_vregs(ctx);
if (rc) {
@@ -588,26 +557,125 @@ static int ops_resume(void *handle)
if (ctx->sleep_clk_en >= 0)
gpio_direction_output(ctx->sleep_clk_en, 1);
- pcidev = ctx->pcidev;
if (ctx->gpio_en >= 0) {
gpio_direction_output(ctx->gpio_en, 1);
msleep(WIGIG_ENABLE_DELAY);
}
- rc = msm_pcie_pm_control(MSM_PCIE_RESUME, pcidev->bus->number,
- pcidev, NULL, PM_OPT_RESUME);
+ return 0;
+
+err_disable_vregs:
+ msm_11ad_disable_vregs(ctx);
+ return rc;
+}
+
+static int msm_11ad_suspend_power_off(void *handle)
+{
+ int rc;
+ struct msm11ad_ctx *ctx = handle;
+ struct pci_dev *pcidev;
+
+ pr_debug("%s\n", __func__);
+
+ if (!ctx) {
+ pr_err("%s: No context\n", __func__);
+ return -ENODEV;
+ }
+
+ pcidev = ctx->pcidev;
+
+ msm_pcie_shadow_control(ctx->pcidev, 0);
+
+ rc = pci_save_state(pcidev);
if (rc) {
- dev_err(ctx->dev, "msm_pcie_pm_control(RESUME) failed :%d\n",
+ dev_err(ctx->dev, "pci_save_state failed :%d\n", rc);
+ goto out;
+ }
+ ctx->pristine_state = pci_store_saved_state(pcidev);
+
+ rc = msm_pcie_pm_control(MSM_PCIE_SUSPEND, pcidev->bus->number,
+ pcidev, NULL, 0);
+ if (rc) {
+ dev_err(ctx->dev, "msm_pcie_pm_control(SUSPEND) failed :%d\n",
rc);
- goto err_disable_power;
+ goto out;
+ }
+
+ rc = msm_11ad_turn_device_power_off(ctx);
+
+out:
+ return rc;
+}
+
+static int ops_suspend(void *handle, bool keep_device_power)
+{
+ struct msm11ad_ctx *ctx = handle;
+ struct pci_dev *pcidev;
+ int rc;
+
+ pr_debug("11ad suspend: %s\n", __func__);
+ if (!ctx) {
+ pr_err("11ad suspend: No context\n");
+ return -ENODEV;
}
- rc = msm_pcie_recover_config(pcidev);
+
+ if (!keep_device_power)
+ return msm_11ad_suspend_power_off(handle);
+
+ pcidev = ctx->pcidev;
+
+ msm_pcie_shadow_control(pcidev, 0);
+
+ dev_dbg(ctx->dev, "disable device and save config\n");
+ pci_disable_device(pcidev);
+ pci_save_state(pcidev);
+ ctx->pristine_state = pci_store_saved_state(pcidev);
+ dev_dbg(ctx->dev, "moving to D3\n");
+ pci_set_power_state(pcidev, PCI_D3hot);
+
+ rc = msm_pcie_pm_control(MSM_PCIE_SUSPEND, pcidev->bus->number,
+ pcidev, NULL, 0);
+ if (rc)
+ dev_err(ctx->dev, "msm_pcie_pm_control(SUSPEND) failed :%d\n",
+ rc);
+
+ return rc;
+}
+
+static int msm_11ad_resume_power_on(void *handle)
+{
+ int rc;
+ struct msm11ad_ctx *ctx = handle;
+ struct pci_dev *pcidev;
+
+ pr_debug("%s\n", __func__);
+
+ if (!ctx) {
+ pr_err("%s: No context\n", __func__);
+ return -ENODEV;
+ }
+ pcidev = ctx->pcidev;
+
+ rc = msm_11ad_turn_device_power_on(ctx);
+ if (rc)
+ return rc;
+
+ rc = msm_pcie_pm_control(MSM_PCIE_RESUME, pcidev->bus->number,
+ pcidev, NULL, 0);
if (rc) {
- dev_err(ctx->dev, "msm_pcie_recover_config failed :%d\n",
+ dev_err(ctx->dev, "msm_pcie_pm_control(RESUME) failed :%d\n",
rc);
- goto err_suspend_rc;
+ goto err_disable_power;
}
+ pci_set_power_state(pcidev, PCI_D0);
+
+ if (ctx->pristine_state)
+ pci_load_saved_state(ctx->pcidev, ctx->pristine_state);
+ pci_restore_state(ctx->pcidev);
+
+ msm_pcie_shadow_control(ctx->pcidev, 1);
+
/* Disable L1, in case it is enabled */
if (ctx->l1_enabled_in_enum) {
rc = msm_11ad_ctrl_aspm_l1(ctx, false);
@@ -622,18 +690,54 @@ static int ops_resume(void *handle)
err_suspend_rc:
msm_pcie_pm_control(MSM_PCIE_SUSPEND, pcidev->bus->number,
- pcidev, NULL, PM_OPT_SUSPEND);
+ pcidev, NULL, 0);
err_disable_power:
- if (ctx->gpio_en >= 0)
- gpio_direction_output(ctx->gpio_en, 0);
+ msm_11ad_turn_device_power_off(ctx);
+ return rc;
+}
- if (ctx->sleep_clk_en >= 0)
- gpio_direction_output(ctx->sleep_clk_en, 0);
+static int ops_resume(void *handle, bool device_powered_on)
+{
+ struct msm11ad_ctx *ctx = handle;
+ struct pci_dev *pcidev;
+ int rc;
- msm_11ad_disable_clocks(ctx);
-err_disable_vregs:
- msm_11ad_disable_vregs(ctx);
+ pr_debug("11ad resume: %s\n", __func__);
+ if (!ctx) {
+ pr_err("11ad resume: No context\n");
+ return -ENODEV;
+ }
+
+ pcidev = ctx->pcidev;
+
+ if (!device_powered_on)
+ return msm_11ad_resume_power_on(handle);
+
+ rc = msm_pcie_pm_control(MSM_PCIE_RESUME, pcidev->bus->number,
+ pcidev, NULL, 0);
+ if (rc) {
+ dev_err(ctx->dev, "msm_pcie_pm_control(RESUME) failed :%d\n",
+ rc);
+ return rc;
+ }
+ pci_set_power_state(pcidev, PCI_D0);
+ dev_dbg(ctx->dev, "restore state and enable device\n");
+ pci_load_saved_state(pcidev, ctx->pristine_state);
+ pci_restore_state(pcidev);
+
+ rc = pci_enable_device(pcidev);
+ if (rc) {
+ dev_err(ctx->dev, "pci_enable_device failed (%d)\n", rc);
+ goto out;
+ }
+
+ msm_pcie_shadow_control(pcidev, 1);
+
+ dev_dbg(ctx->dev, "pci set master\n");
+ pci_set_master(pcidev);
+
+out:
return rc;
}
@@ -906,7 +1010,7 @@ out_rc:
static void msm_11ad_init_cpu_boost(struct msm11ad_ctx *ctx)
{
unsigned int minfreq = 0, maxfreq = 0, freq;
- int i, boost_cpu;
+ int i, boost_cpu = 0;
for_each_possible_cpu(i) {
freq = cpufreq_quick_get_max(i);
@@ -993,6 +1097,8 @@ static int msm_11ad_probe(struct platform_device *pdev)
return -EINVAL;
}
ctx->use_smmu = of_property_read_bool(of_node, "qcom,smmu-support");
+ ctx->keep_radio_on_during_sleep = of_property_read_bool(of_node,
+ "qcom,keep_radio_on_during_sleep");
ctx->bus_scale = msm_bus_cl_get_pdata(pdev);
ctx->smmu_s1_en = of_property_read_bool(of_node, "qcom,smmu-s1-en");
@@ -1105,13 +1211,6 @@ static int msm_11ad_probe(struct platform_device *pdev)
}
}
- rc = pci_save_state(pcidev);
- if (rc) {
- dev_err(ctx->dev, "pci_save_state failed :%d\n", rc);
- goto out_rc;
- }
- ctx->pristine_state = pci_store_saved_state(pcidev);
-
if (ctx->sleep_clk_en >= 0) {
rc = gpio_request(ctx->sleep_clk_en, "msm_11ad");
if (rc < 0) {
@@ -1147,7 +1246,7 @@ static int msm_11ad_probe(struct platform_device *pdev)
device_disable_async_suspend(&pcidev->dev);
list_add_tail(&ctx->list, &dev_list);
- ops_suspend(ctx);
+ msm_11ad_suspend_power_off(ctx);
return 0;
out_rc:
@@ -1237,6 +1336,17 @@ static void msm_11ad_set_boost_affinity(struct msm11ad_ctx *ctx)
dev_warn(ctx->dev, "failed to set CPU boost affinity\n");
}
+static void msm_11ad_clear_boost_affinity(struct msm11ad_ctx *ctx)
+{
+ int rc;
+
+ irq_modify_status(ctx->pcidev->irq, IRQ_NO_BALANCING, 0);
+ rc = irq_set_affinity_hint(ctx->pcidev->irq, NULL);
+ if (rc)
+ dev_warn(ctx->dev,
+ "Failed clear affinity, rc=%d\n", rc);
+}
+
/* hooks for the wil6210 driver */
static int ops_bus_request(void *handle, u32 kbps /* KBytes/Sec */)
{
@@ -1286,8 +1396,7 @@ static int ops_bus_request(void *handle, u32 kbps /* KBytes/Sec */)
dev_err(ctx->dev,
"Failed disable boost rc=%d\n",
rc);
- irq_modify_status(ctx->pcidev->irq,
- IRQ_NO_BALANCING, 0);
+ msm_11ad_clear_boost_affinity(ctx);
dev_dbg(ctx->dev, "CPU boost disabled\n");
}
ctx->is_cpu_boosted = needs_boost;
@@ -1315,7 +1424,7 @@ static void ops_uninit(void *handle)
memset(&ctx->rops, 0, sizeof(ctx->rops));
ctx->wil_handle = NULL;
- ops_suspend(ctx);
+ msm_11ad_suspend_power_off(ctx);
}
static int msm_11ad_notify_crash(struct msm11ad_ctx *ctx)
@@ -1373,6 +1482,16 @@ static int ops_notify(void *handle, enum wil_platform_event evt)
return rc;
}
+bool ops_keep_radio_on_during_sleep(void *handle)
+{
+ struct msm11ad_ctx *ctx = (struct msm11ad_ctx *)handle;
+
+ pr_debug("%s: keep radio on during sleep is %s\n", __func__,
+ ctx->keep_radio_on_during_sleep ? "allowed" : "not allowed");
+
+ return ctx->keep_radio_on_during_sleep;
+}
+
void *msm_11ad_dev_init(struct device *dev, struct wil_platform_ops *ops,
const struct wil_platform_rops *rops, void *wil_handle)
{
@@ -1412,6 +1531,7 @@ void *msm_11ad_dev_init(struct device *dev, struct wil_platform_ops *ops,
ops->resume = ops_resume;
ops->uninit = ops_uninit;
ops->notify = ops_notify;
+ ops->keep_radio_on_during_sleep = ops_keep_radio_on_during_sleep;
return ctx;
}
@@ -1428,19 +1548,9 @@ int msm_11ad_modinit(void)
return -EINVAL;
}
- if (ctx->pristine_state) {
- /* in old kernels, pci_load_saved_state() is not exported;
- * so use pci_load_and_free_saved_state()
- * and re-allocate ctx->saved_state again
- */
- pci_load_and_free_saved_state(ctx->pcidev,
- &ctx->pristine_state);
- ctx->pristine_state = pci_store_saved_state(ctx->pcidev);
- }
-
ctx->subsys_handle = subsystem_get(ctx->subsysdesc.name);
- return ops_resume(ctx);
+ return msm_11ad_resume_power_on(ctx);
}
EXPORT_SYMBOL(msm_11ad_modinit);
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/platform/msm/seemp_core/seemp_logk.c b/drivers/platform/msm/seemp_core/seemp_logk.c
index d0f21943cb0f..264db54f0d6e 100644
--- a/drivers/platform/msm/seemp_core/seemp_logk.c
+++ b/drivers/platform/msm/seemp_core/seemp_logk.c
@@ -287,7 +287,7 @@ static bool seemp_logk_get_bit_from_vector(__u8 *pVec, __u32 index)
unsigned int bit_num = index%8;
unsigned char byte;
- if (DIV_ROUND_UP(index, 8) > MASK_BUFFER_SIZE)
+ if (byte_num >= MASK_BUFFER_SIZE)
return false;
byte = pVec[byte_num];
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/power/supply/qcom/qpnp-smb2.c b/drivers/power/supply/qcom/qpnp-smb2.c
index 94b9e9c4d912..b2597987292b 100644
--- a/drivers/power/supply/qcom/qpnp-smb2.c
+++ b/drivers/power/supply/qcom/qpnp-smb2.c
@@ -266,8 +266,9 @@ module_param_named(
debug_mask, __debug_mask, int, S_IRUSR | S_IWUSR
);
-#define MICRO_1P5A 1500000
-#define MICRO_P1A 100000
+#define MICRO_1P5A 1500000
+#define MICRO_P1A 100000
+#define OTG_DEFAULT_DEGLITCH_TIME_MS 50
static int smb2_parse_dt(struct smb2 *chip)
{
struct smb_charger *chg = &chip->chg;
@@ -400,6 +401,12 @@ static int smb2_parse_dt(struct smb2 *chip)
chg->suspend_input_on_debug_batt = of_property_read_bool(node,
"qcom,suspend-input-on-debug-batt");
+
+ rc = of_property_read_u32(node, "qcom,otg-deglitch-time-ms",
+ &chg->otg_delay_ms);
+ if (rc < 0)
+ chg->otg_delay_ms = OTG_DEFAULT_DEGLITCH_TIME_MS;
+
return 0;
}
diff --git a/drivers/power/supply/qcom/smb-lib.c b/drivers/power/supply/qcom/smb-lib.c
index a191391a3904..cc50e0f478d1 100644
--- a/drivers/power/supply/qcom/smb-lib.c
+++ b/drivers/power/supply/qcom/smb-lib.c
@@ -3750,26 +3750,6 @@ static void smblib_handle_typec_debounce_done(struct smb_charger *chg,
smblib_typec_mode_name[pval.intval]);
}
-irqreturn_t smblib_handle_usb_typec_change_for_uusb(struct smb_charger *chg)
-{
- int rc;
- u8 stat;
-
- rc = smblib_read(chg, TYPE_C_STATUS_3_REG, &stat);
- if (rc < 0) {
- smblib_err(chg, "Couldn't read TYPE_C_STATUS_3 rc=%d\n", rc);
- return IRQ_HANDLED;
- }
- smblib_dbg(chg, PR_REGISTER, "TYPE_C_STATUS_3 = 0x%02x OTG=%d\n",
- stat, !!(stat & (U_USB_GND_NOVBUS_BIT | U_USB_GND_BIT)));
-
- extcon_set_cable_state_(chg->extcon, EXTCON_USB_HOST,
- !!(stat & (U_USB_GND_NOVBUS_BIT | U_USB_GND_BIT)));
- power_supply_changed(chg->usb_psy);
-
- return IRQ_HANDLED;
-}
-
static void smblib_usb_typec_change(struct smb_charger *chg)
{
int rc;
@@ -3804,7 +3784,11 @@ irqreturn_t smblib_handle_usb_typec_change(int irq, void *data)
struct smb_charger *chg = irq_data->parent_data;
if (chg->micro_usb_mode) {
- smblib_handle_usb_typec_change_for_uusb(chg);
+ cancel_delayed_work_sync(&chg->uusb_otg_work);
+ vote(chg->awake_votable, OTG_DELAY_VOTER, true, 0);
+ smblib_dbg(chg, PR_INTERRUPT, "Scheduling OTG work\n");
+ schedule_delayed_work(&chg->uusb_otg_work,
+ msecs_to_jiffies(chg->otg_delay_ms));
return IRQ_HANDLED;
}
@@ -3889,6 +3873,30 @@ irqreturn_t smblib_handle_wdog_bark(int irq, void *data)
/***************
* Work Queues *
***************/
+static void smblib_uusb_otg_work(struct work_struct *work)
+{
+ struct smb_charger *chg = container_of(work, struct smb_charger,
+ uusb_otg_work.work);
+ int rc;
+ u8 stat;
+ bool otg;
+
+ rc = smblib_read(chg, TYPE_C_STATUS_3_REG, &stat);
+ if (rc < 0) {
+ smblib_err(chg, "Couldn't read TYPE_C_STATUS_3 rc=%d\n", rc);
+ goto out;
+ }
+
+ otg = !!(stat & (U_USB_GND_NOVBUS_BIT | U_USB_GND_BIT));
+ extcon_set_cable_state_(chg->extcon, EXTCON_USB_HOST, otg);
+ smblib_dbg(chg, PR_REGISTER, "TYPE_C_STATUS_3 = 0x%02x OTG=%d\n",
+ stat, otg);
+ power_supply_changed(chg->usb_psy);
+
+out:
+ vote(chg->awake_votable, OTG_DELAY_VOTER, false, 0);
+}
+
static void smblib_hvdcp_detect_work(struct work_struct *work)
{
@@ -4482,6 +4490,7 @@ int smblib_init(struct smb_charger *chg)
INIT_DELAYED_WORK(&chg->icl_change_work, smblib_icl_change_work);
INIT_DELAYED_WORK(&chg->pl_enable_work, smblib_pl_enable_work);
INIT_WORK(&chg->legacy_detection_work, smblib_legacy_detection_work);
+ INIT_DELAYED_WORK(&chg->uusb_otg_work, smblib_uusb_otg_work);
chg->fake_capacity = -EINVAL;
chg->fake_input_current_limited = -EINVAL;
@@ -4536,6 +4545,7 @@ int smblib_deinit(struct smb_charger *chg)
cancel_delayed_work_sync(&chg->icl_change_work);
cancel_delayed_work_sync(&chg->pl_enable_work);
cancel_work_sync(&chg->legacy_detection_work);
+ cancel_delayed_work_sync(&chg->uusb_otg_work);
power_supply_unreg_notifier(&chg->nb);
smblib_destroy_votables(chg);
qcom_batt_deinit();
diff --git a/drivers/power/supply/qcom/smb-lib.h b/drivers/power/supply/qcom/smb-lib.h
index 5dc60ecb9436..3fedff8897ee 100644
--- a/drivers/power/supply/qcom/smb-lib.h
+++ b/drivers/power/supply/qcom/smb-lib.h
@@ -64,6 +64,7 @@ enum print_reason {
#define CC2_WA_VOTER "CC2_WA_VOTER"
#define QNOVO_VOTER "QNOVO_VOTER"
#define BATT_PROFILE_VOTER "BATT_PROFILE_VOTER"
+#define OTG_DELAY_VOTER "OTG_DELAY_VOTER"
#define VCONN_MAX_ATTEMPTS 3
#define OTG_MAX_ATTEMPTS 3
@@ -230,6 +231,7 @@ struct smb_charger {
bool external_vconn;
struct smb_chg_freq chg_freq;
int smb_version;
+ int otg_delay_ms;
/* locks */
struct mutex lock;
@@ -290,6 +292,7 @@ struct smb_charger {
struct delayed_work icl_change_work;
struct delayed_work pl_enable_work;
struct work_struct legacy_detection_work;
+ struct delayed_work uusb_otg_work;
/* cached status */
int voltage_min_uv;
diff --git a/drivers/regulator/onsemi-ncp6335d.c b/drivers/regulator/onsemi-ncp6335d.c
index 595fde1c825f..3b4ca4f81527 100644
--- a/drivers/regulator/onsemi-ncp6335d.c
+++ b/drivers/regulator/onsemi-ncp6335d.c
@@ -153,6 +153,20 @@ static void ncp633d_slew_delay(struct ncp6335d_info *dd,
udelay(delay);
}
+static int ncp6335d_is_enabled(struct regulator_dev *rdev)
+{
+ int rc, val = 0;
+ struct ncp6335d_info *dd = rdev_get_drvdata(rdev);
+
+ rc = ncp6335x_read(dd, dd->vsel_reg, &val);
+ if (rc)
+ dev_err(dd->dev, "Unable to read enable register rc(%d)", rc);
+
+ dump_registers(dd, dd->vsel_reg, __func__);
+
+ return ((val & NCP6335D_ENABLE) ? 1 : 0);
+}
+
static int ncp6335d_enable(struct regulator_dev *rdev)
{
int rc;
@@ -297,6 +311,7 @@ static struct regulator_ops ncp6335d_ops = {
.set_voltage = ncp6335d_set_voltage,
.get_voltage = ncp6335d_get_voltage,
.list_voltage = ncp6335d_list_voltage,
+ .is_enabled = ncp6335d_is_enabled,
.enable = ncp6335d_enable,
.disable = ncp6335d_disable,
.set_mode = ncp6335d_set_mode,
@@ -305,6 +320,7 @@ static struct regulator_ops ncp6335d_ops = {
static struct regulator_desc rdesc = {
.name = "ncp6335d",
+ .supply_name = "vin",
.owner = THIS_MODULE,
.n_voltages = NCP6335D_VOLTAGE_STEPS,
.ops = &ncp6335d_ops,
@@ -748,7 +764,7 @@ int __init ncp6335d_regulator_init(void)
return i2c_add_driver(&ncp6335d_regulator_driver);
}
EXPORT_SYMBOL(ncp6335d_regulator_init);
-arch_initcall(ncp6335d_regulator_init);
+subsys_initcall(ncp6335d_regulator_init);
static void __exit ncp6335d_regulator_exit(void)
{
diff --git a/drivers/scsi/cxlflash/main.c b/drivers/scsi/cxlflash/main.c
index 2882bcac918a..0b096730c72a 100644
--- a/drivers/scsi/cxlflash/main.c
+++ b/drivers/scsi/cxlflash/main.c
@@ -996,6 +996,8 @@ static int wait_port_online(__be64 __iomem *fc_regs, u32 delay_us, u32 nretry)
do {
msleep(delay_us / 1000);
status = readq_be(&fc_regs[FC_MTIP_STATUS / 8]);
+ if (status == U64_MAX)
+ nretry /= 2;
} while ((status & FC_MTIP_STATUS_MASK) != FC_MTIP_STATUS_ONLINE &&
nretry--);
@@ -1027,6 +1029,8 @@ static int wait_port_offline(__be64 __iomem *fc_regs, u32 delay_us, u32 nretry)
do {
msleep(delay_us / 1000);
status = readq_be(&fc_regs[FC_MTIP_STATUS / 8]);
+ if (status == U64_MAX)
+ nretry /= 2;
} while ((status & FC_MTIP_STATUS_MASK) != FC_MTIP_STATUS_OFFLINE &&
nretry--);
@@ -1137,7 +1141,7 @@ static const struct asyc_intr_info ainfo[] = {
{SISL_ASTATUS_FC0_LOGI_F, "login failed", 0, CLR_FC_ERROR},
{SISL_ASTATUS_FC0_LOGI_S, "login succeeded", 0, SCAN_HOST},
{SISL_ASTATUS_FC0_LINK_DN, "link down", 0, 0},
- {SISL_ASTATUS_FC0_LINK_UP, "link up", 0, SCAN_HOST},
+ {SISL_ASTATUS_FC0_LINK_UP, "link up", 0, 0},
{SISL_ASTATUS_FC1_OTHER, "other error", 1, CLR_FC_ERROR | LINK_RESET},
{SISL_ASTATUS_FC1_LOGO, "target initiated LOGO", 1, 0},
{SISL_ASTATUS_FC1_CRC_T, "CRC threshold exceeded", 1, LINK_RESET},
@@ -1145,7 +1149,7 @@ static const struct asyc_intr_info ainfo[] = {
{SISL_ASTATUS_FC1_LOGI_F, "login failed", 1, CLR_FC_ERROR},
{SISL_ASTATUS_FC1_LOGI_S, "login succeeded", 1, SCAN_HOST},
{SISL_ASTATUS_FC1_LINK_DN, "link down", 1, 0},
- {SISL_ASTATUS_FC1_LINK_UP, "link up", 1, SCAN_HOST},
+ {SISL_ASTATUS_FC1_LINK_UP, "link up", 1, 0},
{0x0, "", 0, 0} /* terminator */
};
@@ -1962,6 +1966,11 @@ retry:
* cxlflash_eh_host_reset_handler() - reset the host adapter
* @scp: SCSI command from stack identifying host.
*
+ * Following a reset, the state is evaluated again in case an EEH occurred
+ * during the reset. In such a scenario, the host reset will either yield
+ * until the EEH recovery is complete or return success or failure based
+ * upon the current device state.
+ *
* Return:
* SUCCESS as defined in scsi/scsi.h
* FAILED as defined in scsi/scsi.h
@@ -1993,7 +2002,8 @@ static int cxlflash_eh_host_reset_handler(struct scsi_cmnd *scp)
} else
cfg->state = STATE_NORMAL;
wake_up_all(&cfg->reset_waitq);
- break;
+ ssleep(1);
+ /* fall through */
case STATE_RESET:
wait_event(cfg->reset_waitq, cfg->state != STATE_RESET);
if (cfg->state == STATE_NORMAL)
@@ -2534,6 +2544,9 @@ static void drain_ioctls(struct cxlflash_cfg *cfg)
* @pdev: PCI device struct.
* @state: PCI channel state.
*
+ * When an EEH occurs during an active reset, wait until the reset is
+ * complete and then take action based upon the device state.
+ *
* Return: PCI_ERS_RESULT_NEED_RESET or PCI_ERS_RESULT_DISCONNECT
*/
static pci_ers_result_t cxlflash_pci_error_detected(struct pci_dev *pdev,
@@ -2547,6 +2560,10 @@ static pci_ers_result_t cxlflash_pci_error_detected(struct pci_dev *pdev,
switch (state) {
case pci_channel_io_frozen:
+ wait_event(cfg->reset_waitq, cfg->state != STATE_RESET);
+ if (cfg->state == STATE_FAILTERM)
+ return PCI_ERS_RESULT_DISCONNECT;
+
cfg->state = STATE_RESET;
scsi_block_requests(cfg->host);
drain_ioctls(cfg);
diff --git a/drivers/scsi/ufs/Kconfig b/drivers/scsi/ufs/Kconfig
index b3ed361eff26..fb2f2159c0e1 100644
--- a/drivers/scsi/ufs/Kconfig
+++ b/drivers/scsi/ufs/Kconfig
@@ -106,3 +106,15 @@ config SCSI_UFS_TEST
The UFS unit-tests register as a block device test utility to
the test-iosched and will be initiated when the test-iosched will
be chosen to be the active I/O scheduler.
+
+config SCSI_UFSHCD_CMD_LOGGING
+ bool "Universal Flash Storage host controller driver layer command logging support"
+ depends on SCSI_UFSHCD
+ help
+ This selects the UFS host controller driver layer command logging.
+ UFS host controller driver layer command logging records all the
+ command information sent from UFS host controller for debugging
+ purpose.
+
+ Select this if you want above mentioned debug information captured.
+ If unsure, say N.
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/ufs-qcom.c b/drivers/scsi/ufs/ufs-qcom.c
index bc00a7e9572f..aadaef7d1bed 100644
--- a/drivers/scsi/ufs/ufs-qcom.c
+++ b/drivers/scsi/ufs/ufs-qcom.c
@@ -1497,7 +1497,7 @@ static void ufs_qcom_advertise_quirks(struct ufs_hba *hba)
hba->quirks |= UFSHCD_QUIRK_BROKEN_LCC;
}
- if (host->hw_ver.major >= 0x2) {
+ if (host->hw_ver.major == 0x2) {
hba->quirks |= UFSHCD_QUIRK_BROKEN_UFS_HCI_VERSION;
if (!ufs_qcom_cap_qunipro(host))
diff --git a/drivers/scsi/ufs/ufshcd.c b/drivers/scsi/ufs/ufshcd.c
index c5393d517432..a90c51a113d2 100644
--- a/drivers/scsi/ufs/ufshcd.c
+++ b/drivers/scsi/ufs/ufshcd.c
@@ -516,14 +516,145 @@ static inline void ufshcd_remove_non_printable(char *val)
*val = ' ';
}
+#define UFSHCD_MAX_CMD_LOGGING 100
+
#ifdef CONFIG_TRACEPOINTS
-static void ufshcd_add_command_trace(struct ufs_hba *hba,
- unsigned int tag, const char *str)
+static inline void ufshcd_add_command_trace(struct ufs_hba *hba,
+ struct ufshcd_cmd_log_entry *entry, u8 opcode)
+{
+ if (trace_ufshcd_command_enabled()) {
+ u32 intr = ufshcd_readl(hba, REG_INTERRUPT_STATUS);
+
+ trace_ufshcd_command(dev_name(hba->dev), entry->str, entry->tag,
+ entry->doorbell, entry->transfer_len, intr,
+ entry->lba, opcode);
+ }
+}
+#else
+static inline void ufshcd_add_command_trace(struct ufs_hba *hba,
+ struct ufshcd_cmd_log_entry *entry, u8 opcode)
+{
+}
+#endif
+
+#ifdef CONFIG_SCSI_UFSHCD_CMD_LOGGING
+static void ufshcd_cmd_log_init(struct ufs_hba *hba)
+{
+ /* Allocate log entries */
+ if (!hba->cmd_log.entries) {
+ hba->cmd_log.entries = kzalloc(UFSHCD_MAX_CMD_LOGGING *
+ sizeof(struct ufshcd_cmd_log_entry), GFP_KERNEL);
+ if (!hba->cmd_log.entries)
+ return;
+ dev_dbg(hba->dev, "%s: cmd_log.entries initialized\n",
+ __func__);
+ }
+}
+
+static void __ufshcd_cmd_log(struct ufs_hba *hba, char *str, char *cmd_type,
+ unsigned int tag, u8 cmd_id, u8 idn, u8 lun,
+ sector_t lba, int transfer_len, u8 opcode)
+{
+ struct ufshcd_cmd_log_entry *entry;
+
+ if (!hba->cmd_log.entries)
+ return;
+
+ entry = &hba->cmd_log.entries[hba->cmd_log.pos];
+ entry->lun = lun;
+ entry->str = str;
+ entry->cmd_type = cmd_type;
+ entry->cmd_id = cmd_id;
+ entry->lba = lba;
+ entry->transfer_len = transfer_len;
+ entry->idn = idn;
+ entry->doorbell = ufshcd_readl(hba, REG_UTP_TRANSFER_REQ_DOOR_BELL);
+ entry->tag = tag;
+ entry->tstamp = ktime_get();
+ entry->outstanding_reqs = hba->outstanding_reqs;
+ entry->seq_num = hba->cmd_log.seq_num;
+ hba->cmd_log.seq_num++;
+ hba->cmd_log.pos =
+ (hba->cmd_log.pos + 1) % UFSHCD_MAX_CMD_LOGGING;
+
+ ufshcd_add_command_trace(hba, entry, opcode);
+}
+
+static void ufshcd_cmd_log(struct ufs_hba *hba, char *str, char *cmd_type,
+ unsigned int tag, u8 cmd_id, u8 idn)
+{
+ __ufshcd_cmd_log(hba, str, cmd_type, tag, cmd_id, idn,
+ 0xff, (sector_t)-1, -1, -1);
+}
+
+static void ufshcd_dme_cmd_log(struct ufs_hba *hba, char *str, u8 cmd_id)
+{
+ ufshcd_cmd_log(hba, str, "dme", 0xff, cmd_id, 0xff);
+}
+
+static void ufshcd_cmd_log_print(struct ufs_hba *hba)
+{
+ int i;
+ int pos;
+ struct ufshcd_cmd_log_entry *p;
+
+ if (!hba->cmd_log.entries)
+ return;
+
+ pos = hba->cmd_log.pos;
+ for (i = 0; i < UFSHCD_MAX_CMD_LOGGING; i++) {
+ p = &hba->cmd_log.entries[pos];
+ pos = (pos + 1) % UFSHCD_MAX_CMD_LOGGING;
+
+ if (ktime_to_us(p->tstamp)) {
+ pr_err("%s: %s: seq_no=%u lun=0x%x cmd_id=0x%02x lba=0x%llx txfer_len=%d tag=%u, doorbell=0x%x outstanding=0x%x idn=%d time=%lld us\n",
+ p->cmd_type, p->str, p->seq_num,
+ p->lun, p->cmd_id, (unsigned long long)p->lba,
+ p->transfer_len, p->tag, p->doorbell,
+ p->outstanding_reqs, p->idn,
+ ktime_to_us(p->tstamp));
+ usleep_range(1000, 1100);
+ }
+ }
+}
+#else
+static void ufshcd_cmd_log_init(struct ufs_hba *hba)
+{
+}
+
+static void __ufshcd_cmd_log(struct ufs_hba *hba, char *str, char *cmd_type,
+ unsigned int tag, u8 cmd_id, u8 idn, u8 lun,
+ sector_t lba, int transfer_len, u8 opcode)
+{
+ struct ufshcd_cmd_log_entry entry;
+
+ entry.str = str;
+ entry.lba = lba;
+ entry.transfer_len = transfer_len;
+ entry.doorbell = ufshcd_readl(hba, REG_UTP_TRANSFER_REQ_DOOR_BELL);
+ entry.tag = tag;
+
+ ufshcd_add_command_trace(hba, &entry, opcode);
+}
+
+static void ufshcd_dme_cmd_log(struct ufs_hba *hba, char *str, u8 cmd_id)
+{
+}
+
+static void ufshcd_cmd_log_print(struct ufs_hba *hba)
+{
+}
+#endif
+
+#ifdef CONFIG_TRACEPOINTS
+static inline void ufshcd_cond_add_cmd_trace(struct ufs_hba *hba,
+ unsigned int tag, const char *str)
{
- sector_t lba = -1;
- u8 opcode = 0;
- u32 intr, doorbell;
struct ufshcd_lrb *lrbp;
+ char *cmd_type;
+ u8 opcode = 0;
+ u8 cmd_id = 0, idn = 0;
+ sector_t lba = -1;
int transfer_len = -1;
lrbp = &hba->lrb[tag];
@@ -537,23 +668,28 @@ static void ufshcd_add_command_trace(struct ufs_hba *hba,
*/
if (lrbp->cmd->request && lrbp->cmd->request->bio)
lba =
- lrbp->cmd->request->bio->bi_iter.bi_sector;
+ lrbp->cmd->request->bio->bi_iter.bi_sector;
transfer_len = be32_to_cpu(
lrbp->ucd_req_ptr->sc.exp_data_transfer_len);
}
}
- intr = ufshcd_readl(hba, REG_INTERRUPT_STATUS);
- doorbell = ufshcd_readl(hba, REG_UTP_TRANSFER_REQ_DOOR_BELL);
- trace_ufshcd_command(dev_name(hba->dev), str, tag,
- doorbell, transfer_len, intr, lba, opcode);
-}
+ if (lrbp->cmd && (lrbp->command_type == UTP_CMD_TYPE_SCSI)) {
+ cmd_type = "scsi";
+ cmd_id = (u8)(*lrbp->cmd->cmnd);
+ } else if (lrbp->command_type == UTP_CMD_TYPE_DEV_MANAGE) {
+ if (hba->dev_cmd.type == DEV_CMD_TYPE_NOP) {
+ cmd_type = "nop";
+ cmd_id = 0;
+ } else if (hba->dev_cmd.type == DEV_CMD_TYPE_QUERY) {
+ cmd_type = "query";
+ cmd_id = hba->dev_cmd.query.request.upiu_req.opcode;
+ idn = hba->dev_cmd.query.request.upiu_req.idn;
+ }
+ }
-static inline void ufshcd_cond_add_cmd_trace(struct ufs_hba *hba,
- unsigned int tag, const char *str)
-{
- if (trace_ufshcd_command_enabled())
- ufshcd_add_command_trace(hba, tag, str);
+ __ufshcd_cmd_log(hba, (char *) str, cmd_type, tag, cmd_id, idn,
+ lrbp->lun, lba, transfer_len, opcode);
}
#else
static inline void ufshcd_cond_add_cmd_trace(struct ufs_hba *hba,
@@ -1370,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);
@@ -1474,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),
@@ -1920,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);
@@ -2263,6 +2403,7 @@ ufshcd_dispatch_uic_cmd(struct ufs_hba *hba, struct uic_command *uic_cmd)
hba->active_uic_cmd = uic_cmd;
+ ufshcd_dme_cmd_log(hba, "send", hba->active_uic_cmd->command);
/* Write Args */
ufshcd_writel(hba, uic_cmd->argument1, REG_UIC_COMMAND_ARG_1);
ufshcd_writel(hba, uic_cmd->argument2, REG_UIC_COMMAND_ARG_2);
@@ -2296,6 +2437,8 @@ ufshcd_wait_for_uic_cmd(struct ufs_hba *hba, struct uic_command *uic_cmd)
if (ret)
ufsdbg_set_err_state(hba);
+ ufshcd_dme_cmd_log(hba, "cmp1", hba->active_uic_cmd->command);
+
spin_lock_irqsave(hba->host->host_lock, flags);
hba->active_uic_cmd = NULL;
spin_unlock_irqrestore(hba->host->host_lock, flags);
@@ -2344,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);
@@ -2357,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);
@@ -2834,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;
@@ -2847,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;
}
@@ -4113,6 +4260,8 @@ static int ufshcd_uic_pwr_ctrl(struct ufs_hba *hba, struct uic_command *cmd)
cmd->command, status);
ret = (status != PWR_OK) ? status : -1;
}
+ ufshcd_dme_cmd_log(hba, "cmp2", hba->active_uic_cmd->command);
+
out:
if (ret) {
ufsdbg_set_err_state(hba);
@@ -4216,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;
@@ -5385,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) {
@@ -5421,7 +5573,7 @@ static void __ufshcd_transfer_req_compl(struct ufs_hba *hba,
} else if (lrbp->command_type == UTP_CMD_TYPE_DEV_MANAGE) {
if (hba->dev_cmd.complete) {
ufshcd_cond_add_cmd_trace(hba, index,
- "dev_complete");
+ "dcmp");
complete(hba->dev_cmd.complete);
}
}
@@ -5907,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;
@@ -5943,6 +6096,7 @@ static void ufshcd_err_handler(struct work_struct *work)
ufshcd_print_host_state(hba);
ufshcd_print_pwr_info(hba);
ufshcd_print_tmrs(hba, hba->outstanding_tasks);
+ ufshcd_cmd_log_print(hba);
spin_lock_irqsave(hba->host->host_lock, flags);
}
}
@@ -6049,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);
@@ -6286,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
@@ -6365,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);
@@ -6422,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;
@@ -6449,6 +6608,7 @@ static int ufshcd_eh_device_reset_handler(struct scsi_cmnd *cmd)
hba = shost_priv(host);
tag = cmd->request->tag;
+ ufshcd_cmd_log_print(hba);
lrbp = &hba->lrb[tag];
err = ufshcd_issue_tm_cmd(hba, lrbp->lun, 0, UFS_LOGICAL_RESET, &resp);
if (err || resp != UPIU_TASK_MANAGEMENT_FUNC_COMPL) {
@@ -9315,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);
@@ -9378,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;
}
@@ -9809,6 +9971,8 @@ int ufshcd_init(struct ufs_hba *hba, void __iomem *mmio_base, unsigned int irq)
*/
ufshcd_set_ufs_dev_active(hba);
+ ufshcd_cmd_log_init(hba);
+
async_schedule(ufshcd_async_scan, hba);
ufsdbg_add_debugfs(hba);
diff --git a/drivers/scsi/ufs/ufshcd.h b/drivers/scsi/ufs/ufshcd.h
index c34a998aac17..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>
@@ -519,7 +519,7 @@ struct ufs_init_prefetch {
u32 icc_level;
};
-#define UIC_ERR_REG_HIST_LENGTH 8
+#define UIC_ERR_REG_HIST_LENGTH 20
/**
* struct ufs_uic_err_reg_hist - keeps history of uic errors
* @pos: index to indicate cyclic buffer position
@@ -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;
@@ -641,6 +661,27 @@ struct ufs_stats {
UFSHCD_DBG_PRINT_TMRS_EN | UFSHCD_DBG_PRINT_PWR_EN | \
UFSHCD_DBG_PRINT_HOST_STATE_EN)
+struct ufshcd_cmd_log_entry {
+ char *str; /* context like "send", "complete" */
+ char *cmd_type; /* "scsi", "query", "nop", "dme" */
+ u8 lun;
+ u8 cmd_id;
+ sector_t lba;
+ int transfer_len;
+ u8 idn; /* used only for query idn */
+ u32 doorbell;
+ u32 outstanding_reqs;
+ u32 seq_num;
+ unsigned int tag;
+ ktime_t tstamp;
+};
+
+struct ufshcd_cmd_log {
+ struct ufshcd_cmd_log_entry *entries;
+ int pos;
+ u32 seq_num;
+};
+
/**
* struct ufs_hba - per adapter private structure
* @mmio_base: UFSHCI base register address
@@ -856,6 +897,7 @@ struct ufs_hba {
struct ufs_clk_gating clk_gating;
struct ufs_hibern8_on_idle hibern8_on_idle;
+ struct ufshcd_cmd_log cmd_log;
/* Control to enable/disable host capabilities */
u32 caps;
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..7406dba44320 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",
@@ -523,12 +524,12 @@ static int handle_alloc_generic_req(void *req_h, void *req, void *conn_h)
return -EINVAL;
}
- memblock[client_id].free_memory += 1;
- pr_debug("memshare: In %s, free memory count for client id: %d = %d",
- __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",
@@ -536,11 +537,16 @@ static int handle_alloc_generic_req(void *req_h, void *req, void *conn_h)
resp = 1;
}
if (!resp) {
+ memblock[client_id].free_memory += 1;
memblock[client_id].alloted = 1;
memblock[client_id].size = alloc_req->num_bytes;
memblock[client_id].peripheral = alloc_req->proc_id;
}
}
+ pr_debug("memshare: In %s, free memory count for client id: %d = %d",
+ __func__, memblock[client_id].client_id,
+ memblock[client_id].free_memory);
+
memblock[client_id].sequence_id = alloc_req->sequence_id;
fill_alloc_response(alloc_resp, client_id, &resp);
@@ -963,8 +969,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/msm_bus/msm_bus_rules.c b/drivers/soc/qcom/msm_bus/msm_bus_rules.c
index 297ba9fc3c35..ea29e303bbde 100644
--- a/drivers/soc/qcom/msm_bus/msm_bus_rules.c
+++ b/drivers/soc/qcom/msm_bus/msm_bus_rules.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2014-2015, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2014-2017, The Linux Foundation. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 and
@@ -410,8 +410,10 @@ void print_all_rules(void)
{
struct rule_node_info *node_it = NULL;
+ mutex_lock(&msm_bus_rules_lock);
list_for_each_entry(node_it, &node_list, link)
print_rules(node_it);
+ mutex_unlock(&msm_bus_rules_lock);
}
void print_rules_buf(char *buf, int max_buf)
@@ -421,6 +423,7 @@ void print_rules_buf(char *buf, int max_buf)
int i;
int cnt = 0;
+ mutex_lock(&msm_bus_rules_lock);
list_for_each_entry(node_it, &node_list, link) {
cnt += scnprintf(buf + cnt, max_buf - cnt,
"\n Now printing rules for Node %d cur_rule %d\n",
@@ -452,6 +455,7 @@ void print_rules_buf(char *buf, int max_buf)
node_rule->rule_ops.mode);
}
}
+ mutex_unlock(&msm_bus_rules_lock);
}
static int copy_rule(struct bus_rule_type *src, struct rules_def *node_rule,
@@ -721,11 +725,12 @@ bool msm_rule_are_rules_registered(void)
{
bool ret = false;
+ mutex_lock(&msm_bus_rules_lock);
if (list_empty(&node_list))
ret = false;
else
ret = true;
-
+ mutex_unlock(&msm_bus_rules_lock);
return ret;
}
diff --git a/drivers/soc/qcom/qbt1000.c b/drivers/soc/qcom/qbt1000.c
index 4ba92436bd06..6e7d34ac9163 100644
--- a/drivers/soc/qcom/qbt1000.c
+++ b/drivers/soc/qcom/qbt1000.c
@@ -377,6 +377,12 @@ static long qbt1000_ioctl(struct file *file, unsigned cmd, unsigned long arg)
drvdata = file->private_data;
+ if (IS_ERR(priv_arg)) {
+ dev_err(drvdata->dev, "%s: invalid user space pointer %lu\n",
+ __func__, arg);
+ return -EINVAL;
+ }
+
mutex_lock(&drvdata->mutex);
pr_debug("qbt1000_ioctl %d\n", cmd);
@@ -401,6 +407,13 @@ static long qbt1000_ioctl(struct file *file, unsigned cmd, unsigned long arg)
goto end;
}
+ if (strcmp(app.name, FP_APP_NAME)) {
+ dev_err(drvdata->dev, "%s: Invalid app name\n",
+ __func__);
+ rc = -EINVAL;
+ goto end;
+ }
+
if (drvdata->app_handle) {
dev_err(drvdata->dev, "%s: LOAD app already loaded, unloading first\n",
__func__);
@@ -414,6 +427,7 @@ static long qbt1000_ioctl(struct file *file, unsigned cmd, unsigned long arg)
}
pr_debug("app %s load before\n", app.name);
+ app.name[MAX_NAME_SIZE - 1] = '\0';
/* start the TZ app */
rc = qseecom_start_app(
@@ -427,7 +441,8 @@ static long qbt1000_ioctl(struct file *file, unsigned cmd, unsigned long arg)
pr_err("App %s failed to set bw\n", app.name);
}
} else {
- pr_err("app %s failed to load\n", app.name);
+ dev_err(drvdata->dev, "%s: Fingerprint Trusted App failed to load\n",
+ __func__);
goto end;
}
@@ -447,9 +462,7 @@ static long qbt1000_ioctl(struct file *file, unsigned cmd, unsigned long arg)
pr_debug("app %s load after\n", app.name);
- if (!strcmp(app.name, FP_APP_NAME))
- drvdata->fp_app_handle = drvdata->app_handle;
-
+ drvdata->fp_app_handle = drvdata->app_handle;
break;
}
case QBT1000_UNLOAD_APP:
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/soc/qcom/rpm_master_stat.c b/drivers/soc/qcom/rpm_master_stat.c
index 14004a2b721e..7bf18ffe6ad2 100644
--- a/drivers/soc/qcom/rpm_master_stat.c
+++ b/drivers/soc/qcom/rpm_master_stat.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2012-2016, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2012-2017, The Linux Foundation. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 and
@@ -96,6 +96,7 @@ static int msm_rpm_master_copy_stats(
int count, j = 0;
char *buf;
static DEFINE_MUTEX(msm_rpm_master_stats_mutex);
+ unsigned long active_cores;
mutex_lock(&msm_rpm_master_stats_mutex);
@@ -247,12 +248,11 @@ static int msm_rpm_master_copy_stats(
record.active_cores);
}
- j = find_first_bit((unsigned long *)&record.active_cores,
- BITS_PER_LONG);
+ active_cores = record.active_cores;
+ j = find_first_bit(&active_cores, BITS_PER_LONG);
while (j < BITS_PER_LONG) {
SNPRINTF(buf, count, "\t\tcore%d\n", j);
- j = find_next_bit((unsigned long *)&record.active_cores,
- BITS_PER_LONG, j + 1);
+ j = find_next_bit(&active_cores, BITS_PER_LONG, j + 1);
}
master_cnt++;
diff --git a/drivers/soc/qcom/service-locator.c b/drivers/soc/qcom/service-locator.c
index 97cd11201262..f19db5fe99b3 100644
--- a/drivers/soc/qcom/service-locator.c
+++ b/drivers/soc/qcom/service-locator.c
@@ -31,7 +31,6 @@
#define SERVREG_LOC_SERVICE_INSTANCE_ID 1
-#define QMI_RESP_BIT_SHIFT(x) (x << 16)
#define QMI_SERVREG_LOC_SERVER_INITIAL_TIMEOUT 2000
#define QMI_SERVREG_LOC_SERVER_TIMEOUT 2000
#define INITIAL_TIMEOUT 100000
@@ -199,9 +198,9 @@ static int servreg_loc_send_msg(struct msg_desc *req_desc,
}
/* Check the response */
- if (QMI_RESP_BIT_SHIFT(resp->resp.result) != QMI_RESULT_SUCCESS_V01) {
+ if (resp->resp.result != QMI_RESULT_SUCCESS_V01) {
pr_err("QMI request for client %s failed 0x%x\n",
- pd->client_name, QMI_RESP_BIT_SHIFT(resp->resp.error));
+ pd->client_name, resp->resp.error);
return -EREMOTEIO;
}
return rc;
@@ -220,7 +219,7 @@ static int service_locator_send_msg(struct pd_qmi_client_data *pd)
return -EAGAIN;
}
- req = kmalloc(sizeof(
+ req = kzalloc(sizeof(
struct qmi_servreg_loc_get_domain_list_req_msg_v01),
GFP_KERNEL);
if (!req) {
@@ -228,7 +227,7 @@ static int service_locator_send_msg(struct pd_qmi_client_data *pd)
rc = -ENOMEM;
goto out;
}
- resp = kmalloc(sizeof(
+ resp = kzalloc(sizeof(
struct qmi_servreg_loc_get_domain_list_resp_msg_v01),
GFP_KERNEL);
if (!resp) {
diff --git a/drivers/soc/qcom/service-notifier.c b/drivers/soc/qcom/service-notifier.c
index b5681a5c6817..221ae0c1fefb 100644
--- a/drivers/soc/qcom/service-notifier.c
+++ b/drivers/soc/qcom/service-notifier.c
@@ -30,7 +30,6 @@
#include <soc/qcom/service-notifier.h>
#include "service-notifier-private.h"
-#define QMI_RESP_BIT_SHIFT(x) (x << 16)
#define SERVREG_NOTIF_NAME_LENGTH QMI_SERVREG_NOTIF_NAME_LENGTH_V01
#define SERVREG_NOTIF_SERVICE_ID SERVREG_NOTIF_SERVICE_ID_V01
#define SERVREG_NOTIF_SERVICE_VERS SERVREG_NOTIF_SERVICE_VERS_V01
@@ -225,9 +224,8 @@ static void send_ind_ack(struct work_struct *work)
}
/* Check the response */
- if (QMI_RESP_BIT_SHIFT(resp.resp.result) != QMI_RESULT_SUCCESS_V01)
- pr_err("QMI request failed 0x%x\n",
- QMI_RESP_BIT_SHIFT(resp.resp.error));
+ if (resp.resp.result != QMI_RESULT_SUCCESS_V01)
+ pr_err("QMI request failed 0x%x\n", resp.resp.error);
pr_info("Indication ACKed for transid %d, service %s, instance %d!\n",
data->ind_msg.transaction_id, data->ind_msg.service_path,
data->instance_id);
@@ -318,9 +316,8 @@ static int send_notif_listener_msg_req(struct service_notif_info *service_notif,
}
/* Check the response */
- if (QMI_RESP_BIT_SHIFT(resp.resp.result) != QMI_RESULT_SUCCESS_V01) {
- pr_err("QMI request failed 0x%x\n",
- QMI_RESP_BIT_SHIFT(resp.resp.error));
+ if (resp.resp.result != QMI_RESULT_SUCCESS_V01) {
+ pr_err("QMI request failed 0x%x\n", resp.resp.error);
return -EREMOTEIO;
}
@@ -645,15 +642,15 @@ static int send_pd_restart_req(const char *service_path,
}
/* Check response if PDR is disabled */
- if (QMI_RESP_BIT_SHIFT(resp.resp.result) == QMI_ERR_DISABLED_V01) {
- pr_err("PD restart is disabled 0x%x\n",
- QMI_RESP_BIT_SHIFT(resp.resp.error));
+ if (resp.resp.result == QMI_RESULT_FAILURE_V01 &&
+ resp.resp.error == QMI_ERR_DISABLED_V01) {
+ pr_err("PD restart is disabled 0x%x\n", resp.resp.error);
return -EOPNOTSUPP;
}
/* Check the response for other error case*/
- if (QMI_RESP_BIT_SHIFT(resp.resp.result) != QMI_RESULT_SUCCESS_V01) {
+ if (resp.resp.result != QMI_RESULT_SUCCESS_V01) {
pr_err("QMI request for PD restart failed 0x%x\n",
- QMI_RESP_BIT_SHIFT(resp.resp.error));
+ resp.resp.error);
return -EREMOTEIO;
}
diff --git a/drivers/soc/qcom/smcinvoke.c b/drivers/soc/qcom/smcinvoke.c
index 99ae24735f05..f69ff47ae0f7 100644
--- a/drivers/soc/qcom/smcinvoke.c
+++ b/drivers/soc/qcom/smcinvoke.c
@@ -429,10 +429,17 @@ long smcinvoke_ioctl(struct file *filp, unsigned cmd, unsigned long arg)
if (ret)
goto out;
- ret = marshal_out(in_msg, inmsg_size, &req, args_buf);
+ /*
+ * if invoke op results in an err, no need to marshal_out and
+ * copy args buf to user space
+ */
+ if (!req.result) {
+ ret = marshal_out(in_msg, inmsg_size, &req, args_buf);
- ret |= copy_to_user((void __user *)(uintptr_t)(req.args),
+ ret |= copy_to_user(
+ (void __user *)(uintptr_t)(req.args),
args_buf, nr_args * req.argsize);
+ }
ret |= copy_to_user((void __user *)arg, &req, sizeof(req));
if (ret)
goto out;
diff --git a/drivers/soc/qcom/spcom.c b/drivers/soc/qcom/spcom.c
index 10eebb0316e8..c2af34926b37 100644
--- a/drivers/soc/qcom/spcom.c
+++ b/drivers/soc/qcom/spcom.c
@@ -220,9 +220,9 @@ struct spcom_channel {
bool tx_abort;
/* rx data info */
- int rx_buf_size; /* allocated rx buffer size */
+ size_t rx_buf_size; /* allocated rx buffer size */
bool rx_buf_ready;
- int actual_rx_size; /* actual data size received */
+ size_t actual_rx_size; /* actual data size received */
const void *glink_rx_buf;
/* ION lock/unlock support */
@@ -302,6 +302,10 @@ static inline bool spcom_is_channel_open(struct spcom_channel *ch)
*/
static inline bool spcom_is_channel_connected(struct spcom_channel *ch)
{
+ /* Channel must be open before it gets connected */
+ if (!spcom_is_channel_open(ch))
+ return false;
+
return (ch->glink_state == GLINK_CONNECTED);
}
@@ -359,6 +363,11 @@ static void spcom_link_state_notif_cb(struct glink_link_state_cb_info *cb_info,
struct spcom_channel *ch = NULL;
const char *ch_name = "sp_kernel";
+ if (!cb_info) {
+ pr_err("invalid NULL cb_info.\n");
+ return;
+ }
+
if (!spcom_is_ready()) {
pr_err("spcom is not ready.\n");
return;
@@ -411,13 +420,17 @@ static void spcom_notify_rx(void *handle,
struct spcom_channel *ch = (struct spcom_channel *) priv;
if (!ch) {
- pr_err("invalid ch parameter.\n");
+ pr_err("invalid NULL channel param\n");
+ return;
+ }
+ if (!buf) {
+ pr_err("invalid NULL buf param\n");
return;
}
- pr_debug("ch [%s] rx size [%d].\n", ch->name, (int) size);
+ pr_debug("ch [%s] rx size [%zu]\n", ch->name, size);
- ch->actual_rx_size = (int) size;
+ ch->actual_rx_size = size;
ch->glink_rx_buf = (void *) buf;
complete_all(&ch->rx_done);
@@ -436,7 +449,11 @@ static void spcom_notify_tx_done(void *handle,
int *tx_buf = (int *) buf;
if (!ch) {
- pr_err("invalid ch parameter.\n");
+ pr_err("invalid NULL channel param\n");
+ return;
+ }
+ if (!buf) {
+ pr_err("invalid NULL buf param\n");
return;
}
@@ -460,6 +477,11 @@ static void spcom_notify_state(void *handle, const void *priv, unsigned event)
int ret;
struct spcom_channel *ch = (struct spcom_channel *) priv;
+ if (!ch) {
+ pr_err("invalid NULL channel param\n");
+ return;
+ }
+
switch (event) {
case GLINK_CONNECTED:
pr_debug("GLINK_CONNECTED, ch name [%s].\n", ch->name);
@@ -479,7 +501,7 @@ static void spcom_notify_state(void *handle, const void *priv, unsigned event)
if (ret) {
pr_err("glink_queue_rx_intent() err [%d]\n", ret);
} else {
- pr_debug("rx buf is ready, size [%d].\n",
+ pr_debug("rx buf is ready, size [%zu]\n",
ch->rx_buf_size);
ch->rx_buf_ready = true;
}
@@ -536,9 +558,7 @@ static void spcom_notify_state(void *handle, const void *priv, unsigned event)
static bool spcom_notify_rx_intent_req(void *handle, const void *priv,
size_t req_size)
{
- struct spcom_channel *ch = (struct spcom_channel *) priv;
-
- pr_err("Unexpected intent request for ch [%s].\n", ch->name);
+ pr_err("Unexpected intent request\n");
return false;
}
@@ -554,6 +574,11 @@ static void spcom_notify_rx_abort(void *handle, const void *priv,
{
struct spcom_channel *ch = (struct spcom_channel *) priv;
+ if (!ch) {
+ pr_err("invalid NULL channel param\n");
+ return;
+ }
+
pr_debug("ch [%s] pending rx aborted.\n", ch->name);
if (spcom_is_channel_open(ch) && (!ch->rx_abort)) {
@@ -574,6 +599,11 @@ static void spcom_notify_tx_abort(void *handle, const void *priv,
{
struct spcom_channel *ch = (struct spcom_channel *) priv;
+ if (!ch) {
+ pr_err("invalid NULL channel param\n");
+ return;
+ }
+
pr_debug("ch [%s] pending tx aborted.\n", ch->name);
if (spcom_is_channel_connected(ch) && (!ch->tx_abort)) {
@@ -792,6 +822,8 @@ static int spcom_close(struct spcom_channel *ch)
* @size: buffer size
*
* ACK is expected within a very short time (few msec).
+ *
+ * Return: 0 on successful operation, negative value otherwise.
*/
static int spcom_tx(struct spcom_channel *ch,
void *buf,
@@ -856,13 +888,15 @@ exit_err:
* @size: buffer size
*
* ACK is expected within a very short time (few msec).
+ *
+ * Return: size in bytes on success, negative value on failure.
*/
static int spcom_rx(struct spcom_channel *ch,
void *buf,
uint32_t size,
uint32_t timeout_msec)
{
- int ret;
+ int ret = -1;
unsigned long jiffies = msecs_to_jiffies(timeout_msec);
long timeleft = 1;
@@ -870,7 +904,7 @@ static int spcom_rx(struct spcom_channel *ch,
/* check for already pending data */
if (ch->actual_rx_size) {
- pr_debug("already pending data size [%d].\n",
+ pr_debug("already pending data size [%zu]\n",
ch->actual_rx_size);
goto copy_buf;
}
@@ -893,7 +927,7 @@ static int spcom_rx(struct spcom_channel *ch,
mutex_unlock(&ch->lock);
return -ERESTART; /* probably SSR */
} else if (ch->actual_rx_size) {
- pr_debug("actual_rx_size is [%d].\n", ch->actual_rx_size);
+ pr_debug("actual_rx_size is [%zu]\n", ch->actual_rx_size);
} else {
pr_err("actual_rx_size is zero.\n");
goto exit_err;
@@ -922,7 +956,7 @@ copy_buf:
pr_err("glink_queue_rx_intent() failed, ret [%d]", ret);
goto exit_err;
} else {
- pr_debug("queue rx_buf, size [%d].\n", ch->rx_buf_size);
+ pr_debug("queue rx_buf, size [%zu]\n", ch->rx_buf_size);
}
mutex_unlock(&ch->lock);
@@ -942,6 +976,8 @@ exit_err:
* Server needs the size of the next request to allocate a request buffer.
* Initially used intent-request, however this complicated the remote side,
* so both sides are not using glink_tx() with INTENT_REQ anymore.
+ *
+ * Return: size in bytes on success, negative value on failure.
*/
static int spcom_get_next_request_size(struct spcom_channel *ch)
{
@@ -953,7 +989,7 @@ static int spcom_get_next_request_size(struct spcom_channel *ch)
/* check if already got it via callback */
if (ch->actual_rx_size) {
- pr_debug("next-req-size already ready ch [%s] size [%d].\n",
+ pr_debug("next-req-size already ready ch [%s] size [%zu]\n",
ch->name, ch->actual_rx_size);
goto exit_ready;
}
@@ -968,7 +1004,7 @@ static int spcom_get_next_request_size(struct spcom_channel *ch)
}
if (ch->actual_rx_size <= 0) {
- pr_err("invalid rx size [%d] ch [%s].\n",
+ pr_err("invalid rx size [%zu] ch [%s]\n",
ch->actual_rx_size, ch->name);
goto exit_error;
}
@@ -1101,16 +1137,21 @@ int spcom_unregister_client(struct spcom_client *client)
}
if (!client) {
- pr_err("Invalid parameter.\n");
+ pr_err("Invalid client parameter.\n");
return -EINVAL;
}
- ch = client->ch;
- kfree(client);
+ ch = client->ch;
+ if (!ch) {
+ pr_err("Invalid channel.\n");
+ return -EINVAL;
+ }
spcom_close(ch);
+ kfree(client);
+
return 0;
}
EXPORT_SYMBOL(spcom_unregister_client);
@@ -1127,6 +1168,8 @@ EXPORT_SYMBOL(spcom_unregister_client);
* @timeout_msec: timeout waiting for response.
*
* The timeout depends on the specific request handling time at the remote side.
+ *
+ * Return: number of rx bytes on success, negative value on failure.
*/
int spcom_client_send_message_sync(struct spcom_client *client,
void *req_ptr,
@@ -1149,6 +1192,10 @@ int spcom_client_send_message_sync(struct spcom_client *client,
}
ch = client->ch;
+ if (!ch) {
+ pr_err("Invalid channel.\n");
+ return -EINVAL;
+ }
/* Check if remote side connect */
if (!spcom_is_channel_connected(ch)) {
@@ -1183,6 +1230,7 @@ EXPORT_SYMBOL(spcom_client_send_message_sync);
bool spcom_client_is_server_connected(struct spcom_client *client)
{
bool connected;
+ struct spcom_channel *ch;
if (!spcom_is_ready()) {
pr_err("spcom is not ready.\n");
@@ -1194,7 +1242,13 @@ bool spcom_client_is_server_connected(struct spcom_client *client)
return false;
}
- connected = spcom_is_channel_connected(client->ch);
+ ch = client->ch;
+ if (!ch) {
+ pr_err("Invalid channel.\n");
+ return -EINVAL;
+ }
+
+ connected = spcom_is_channel_connected(ch);
return connected;
}
@@ -1267,16 +1321,20 @@ int spcom_unregister_service(struct spcom_server *server)
}
if (!server) {
- pr_err("Invalid parameter.\n");
+ pr_err("Invalid server parameter.\n");
return -EINVAL;
}
ch = server->ch;
-
- kfree(server);
+ if (!ch) {
+ pr_err("Invalid channel parameter.\n");
+ return -EINVAL;
+ }
spcom_close(ch);
+ kfree(server);
+
return 0;
}
EXPORT_SYMBOL(spcom_unregister_service);
@@ -1286,7 +1344,7 @@ EXPORT_SYMBOL(spcom_unregister_service);
*
* @server: server handle
*
- * Return: request size in bytes.
+ * Return: size in bytes on success, negative value on failure.
*/
int spcom_server_get_next_request_size(struct spcom_server *server)
{
@@ -1299,6 +1357,10 @@ int spcom_server_get_next_request_size(struct spcom_server *server)
}
ch = server->ch;
+ if (!ch) {
+ pr_err("Invalid channel.\n");
+ return -EINVAL;
+ }
/* Check if remote side connect */
if (!spcom_is_channel_connected(ch)) {
@@ -1321,7 +1383,7 @@ EXPORT_SYMBOL(spcom_server_get_next_request_size);
* @req_ptr: request buffer pointer
* @req_size: max request size
*
- * Return: request size in bytes.
+ * Return: size in bytes on success, negative value on failure.
*/
int spcom_server_wait_for_request(struct spcom_server *server,
void *req_ptr,
@@ -1341,6 +1403,10 @@ int spcom_server_wait_for_request(struct spcom_server *server,
}
ch = server->ch;
+ if (!ch) {
+ pr_err("Invalid channel.\n");
+ return -EINVAL;
+ }
/* Check if remote side connect */
if (!spcom_is_channel_connected(ch)) {
@@ -1379,6 +1445,10 @@ int spcom_server_send_response(struct spcom_server *server,
}
ch = server->ch;
+ if (!ch) {
+ pr_err("Invalid channel.\n");
+ return -EINVAL;
+ }
/* Check if remote side connect */
if (!spcom_is_channel_connected(ch)) {
@@ -1845,18 +1915,6 @@ static int spcom_handle_unlock_ion_buf_command(struct spcom_channel *ch,
}
/**
- * spcom_handle_fake_ssr_command() - Handle fake ssr command from user space.
- */
-static int spcom_handle_fake_ssr_command(struct spcom_channel *ch, int arg)
-{
- pr_debug("Start Fake glink SSR subsystem [%s].\n", spcom_edge);
- glink_ssr(spcom_edge);
- pr_debug("Fake glink SSR subsystem [%s] done.\n", spcom_edge);
-
- return 0;
-}
-
-/**
* spcom_handle_write() - Handle user space write commands.
*
* @buf: command buffer.
@@ -1900,9 +1958,6 @@ static int spcom_handle_write(struct spcom_channel *ch,
case SPCOM_CMD_UNLOCK_ION_BUF:
ret = spcom_handle_unlock_ion_buf_command(ch, buf, buf_size);
break;
- case SPCOM_CMD_FSSR:
- ret = spcom_handle_fake_ssr_command(ch, cmd->arg);
- break;
case SPCOM_CMD_CREATE_CHANNEL:
ret = spcom_handle_create_channel_command(buf, buf_size);
break;
@@ -1921,7 +1976,7 @@ static int spcom_handle_write(struct spcom_channel *ch,
* @buf: command buffer.
* @size: command buffer size.
*
- * Return: size in bytes.
+ * Return: size in bytes on success, negative value on failure.
*/
static int spcom_handle_get_req_size(struct spcom_channel *ch,
void *buf,
@@ -1949,7 +2004,7 @@ static int spcom_handle_get_req_size(struct spcom_channel *ch,
* @buf: command buffer.
* @size: command buffer size.
*
- * Return: size in bytes.
+ * Return: size in bytes on success, negative value on failure.
*/
static int spcom_handle_read_req_resp(struct spcom_channel *ch,
void *buf,
@@ -2033,7 +2088,7 @@ exit_err:
* A special size SPCOM_GET_NEXT_REQUEST_SIZE, which is bigger than the max
* response/request tells the kernel that user space only need the size.
*
- * Return: size in bytes.
+ * Return: size in bytes on success, negative value on failure.
*/
static int spcom_handle_read(struct spcom_channel *ch,
void *buf,
@@ -2115,8 +2170,6 @@ static int spcom_device_open(struct inode *inode, struct file *filp)
return -ENODEV;
}
- filp->private_data = ch;
-
ret = spcom_open(ch, OPEN_CHANNEL_TIMEOUT_MSEC);
if (ret == -ETIMEDOUT) {
pr_err("Connection timeout channel [%s].\n", name);
@@ -2125,6 +2178,8 @@ static int spcom_device_open(struct inode *inode, struct file *filp)
return ret;
}
+ filp->private_data = ch;
+
pr_debug("finished.\n");
return 0;
@@ -2209,8 +2264,8 @@ static ssize_t spcom_device_write(struct file *filp,
ch = filp->private_data;
if (!ch) {
- pr_debug("invalid ch pointer.\n");
- /* Allow some special commands via /dev/spcom and /dev/sp_ssr */
+ pr_err("invalid ch pointer, command not allowed.\n");
+ return -EINVAL;
} else {
/* Check if remote side connect */
if (!spcom_is_channel_connected(ch)) {
diff --git a/drivers/soc/qcom/wcd-dsp-glink.c b/drivers/soc/qcom/wcd-dsp-glink.c
index f601e6646852..3c9d8efd3956 100644
--- a/drivers/soc/qcom/wcd-dsp-glink.c
+++ b/drivers/soc/qcom/wcd-dsp-glink.c
@@ -21,6 +21,7 @@
#include <linux/list.h>
#include <linux/cdev.h>
#include <linux/platform_device.h>
+#include <linux/vmalloc.h>
#include <soc/qcom/glink.h>
#include "sound/wcd-dsp-glink.h"
@@ -29,6 +30,10 @@
#define WDSP_MAX_READ_SIZE (4 * 1024)
#define WDSP_MAX_NO_OF_INTENTS (20)
#define WDSP_MAX_NO_OF_CHANNELS (10)
+#define WDSP_WRITE_PKT_SIZE (sizeof(struct wdsp_write_pkt))
+#define WDSP_REG_PKT_SIZE (sizeof(struct wdsp_reg_pkt))
+#define WDSP_CMD_PKT_SIZE (sizeof(struct wdsp_cmd_pkt))
+#define WDSP_CH_CFG_SIZE (sizeof(struct wdsp_glink_ch_cfg))
#define MINOR_NUMBER_COUNT 1
#define WDSP_EDGE "wdsp"
@@ -183,7 +188,7 @@ static void wdsp_glink_notify_tx_done(void *handle, const void *priv,
return;
}
/* Free tx pkt */
- kfree(pkt_priv);
+ vfree(pkt_priv);
}
/*
@@ -201,7 +206,7 @@ static void wdsp_glink_notify_tx_abort(void *handle, const void *priv,
return;
}
/* Free tx pkt */
- kfree(pkt_priv);
+ vfree(pkt_priv);
}
/*
@@ -519,9 +524,10 @@ static void wdsp_glink_link_state_cb(struct glink_link_state_cb_info *cb_info,
* and register with glink
* wpriv: Wdsp_glink private structure.
* pkt: Glink registration packet contains glink channel information.
+ * pkt_size: Size of the pkt.
*/
static int wdsp_glink_ch_info_init(struct wdsp_glink_priv *wpriv,
- struct wdsp_reg_pkt *pkt)
+ struct wdsp_reg_pkt *pkt, size_t pkt_size)
{
int ret = 0, i, j;
struct glink_link_info link_info;
@@ -530,6 +536,7 @@ static int wdsp_glink_ch_info_init(struct wdsp_glink_priv *wpriv,
u8 no_of_channels;
u8 *payload;
u32 ch_size, ch_cfg_size;
+ size_t size = WDSP_WRITE_PKT_SIZE + WDSP_REG_PKT_SIZE;
mutex_lock(&wpriv->glink_mutex);
if (wpriv->ch) {
@@ -542,9 +549,10 @@ static int wdsp_glink_ch_info_init(struct wdsp_glink_priv *wpriv,
no_of_channels = pkt->no_of_channels;
if (no_of_channels > WDSP_MAX_NO_OF_CHANNELS) {
- dev_info(wpriv->dev, "%s: no_of_channels = %d are limited to %d\n",
- __func__, no_of_channels, WDSP_MAX_NO_OF_CHANNELS);
- no_of_channels = WDSP_MAX_NO_OF_CHANNELS;
+ dev_err(wpriv->dev, "%s: no_of_channels: %d but max allowed are %d\n",
+ __func__, no_of_channels, WDSP_MAX_NO_OF_CHANNELS);
+ ret = -EINVAL;
+ goto done;
}
ch = kcalloc(no_of_channels, sizeof(struct wdsp_glink_ch *),
GFP_KERNEL);
@@ -558,20 +566,34 @@ static int wdsp_glink_ch_info_init(struct wdsp_glink_priv *wpriv,
for (i = 0; i < no_of_channels; i++) {
ch_cfg = (struct wdsp_glink_ch_cfg *)payload;
+ size += WDSP_CH_CFG_SIZE;
+ if (size > pkt_size) {
+ dev_err(wpriv->dev, "%s: Invalid size = %zd, pkt_size = %zd\n",
+ __func__, size, pkt_size);
+ ret = -EINVAL;
+ goto err_ch_mem;
+ }
if (ch_cfg->no_of_intents > WDSP_MAX_NO_OF_INTENTS) {
dev_err(wpriv->dev, "%s: Invalid no_of_intents = %d\n",
__func__, ch_cfg->no_of_intents);
ret = -EINVAL;
goto err_ch_mem;
}
+ size += (sizeof(u32) * ch_cfg->no_of_intents);
+ if (size > pkt_size) {
+ dev_err(wpriv->dev, "%s: Invalid size = %zd, pkt_size = %zd\n",
+ __func__, size, pkt_size);
+ ret = -EINVAL;
+ goto err_ch_mem;
+ }
ch_cfg_size = sizeof(struct wdsp_glink_ch_cfg) +
(sizeof(u32) * ch_cfg->no_of_intents);
ch_size = sizeof(struct wdsp_glink_ch) +
(sizeof(u32) * ch_cfg->no_of_intents);
- dev_dbg(wpriv->dev, "%s: channels = %d, ch_cfg_size %d",
- __func__, no_of_channels, ch_cfg_size);
+ dev_dbg(wpriv->dev, "%s: channels: %d ch_cfg_size: %d, size: %zd, pkt_size: %zd",
+ __func__, no_of_channels, ch_cfg_size, size, pkt_size);
ch[i] = kzalloc(ch_size, GFP_KERNEL);
if (!ch[i]) {
@@ -658,7 +680,7 @@ static void wdsp_glink_tx_buf_work(struct work_struct *work)
* there won't be any tx_done notification to
* free the buffer.
*/
- kfree(tx_buf);
+ vfree(tx_buf);
}
} else {
mutex_unlock(&tx_buf->ch->mutex);
@@ -668,7 +690,7 @@ static void wdsp_glink_tx_buf_work(struct work_struct *work)
* Free tx_buf here as there won't be any tx_done
* notification in this case also.
*/
- kfree(tx_buf);
+ vfree(tx_buf);
}
}
@@ -761,6 +783,7 @@ static ssize_t wdsp_glink_write(struct file *file, const char __user *buf,
struct wdsp_cmd_pkt *cpkt;
struct wdsp_glink_tx_buf *tx_buf;
struct wdsp_glink_priv *wpriv;
+ size_t pkt_max_size;
wpriv = (struct wdsp_glink_priv *)file->private_data;
if (!wpriv) {
@@ -769,7 +792,7 @@ static ssize_t wdsp_glink_write(struct file *file, const char __user *buf,
goto done;
}
- if ((count < sizeof(struct wdsp_write_pkt)) ||
+ if ((count < WDSP_WRITE_PKT_SIZE) ||
(count > WDSP_MAX_WRITE_SIZE)) {
dev_err(wpriv->dev, "%s: Invalid count = %zd\n",
__func__, count);
@@ -779,8 +802,8 @@ static ssize_t wdsp_glink_write(struct file *file, const char __user *buf,
dev_dbg(wpriv->dev, "%s: count = %zd\n", __func__, count);
- tx_buf_size = WDSP_MAX_WRITE_SIZE + sizeof(struct wdsp_glink_tx_buf);
- tx_buf = kzalloc(tx_buf_size, GFP_KERNEL);
+ tx_buf_size = count + sizeof(struct wdsp_glink_tx_buf);
+ tx_buf = vzalloc(tx_buf_size);
if (!tx_buf) {
ret = -ENOMEM;
goto done;
@@ -797,19 +820,20 @@ static ssize_t wdsp_glink_write(struct file *file, const char __user *buf,
wpkt = (struct wdsp_write_pkt *)tx_buf->buf;
switch (wpkt->pkt_type) {
case WDSP_REG_PKT:
- if (count <= (sizeof(struct wdsp_write_pkt) +
- sizeof(struct wdsp_reg_pkt))) {
+ if (count < (WDSP_WRITE_PKT_SIZE + WDSP_REG_PKT_SIZE +
+ WDSP_CH_CFG_SIZE)) {
dev_err(wpriv->dev, "%s: Invalid reg pkt size = %zd\n",
__func__, count);
ret = -EINVAL;
goto free_buf;
}
ret = wdsp_glink_ch_info_init(wpriv,
- (struct wdsp_reg_pkt *)wpkt->payload);
+ (struct wdsp_reg_pkt *)wpkt->payload,
+ count);
if (IS_ERR_VALUE(ret))
dev_err(wpriv->dev, "%s: glink register failed, ret = %d\n",
__func__, ret);
- kfree(tx_buf);
+ vfree(tx_buf);
break;
case WDSP_READY_PKT:
ret = wait_event_timeout(wpriv->link_state_wait,
@@ -823,11 +847,10 @@ static ssize_t wdsp_glink_write(struct file *file, const char __user *buf,
goto free_buf;
}
ret = 0;
- kfree(tx_buf);
+ vfree(tx_buf);
break;
case WDSP_CMD_PKT:
- if (count <= (sizeof(struct wdsp_write_pkt) +
- sizeof(struct wdsp_cmd_pkt))) {
+ if (count <= (WDSP_WRITE_PKT_SIZE + WDSP_CMD_PKT_SIZE)) {
dev_err(wpriv->dev, "%s: Invalid cmd pkt size = %zd\n",
__func__, count);
ret = -EINVAL;
@@ -843,10 +866,18 @@ static ssize_t wdsp_glink_write(struct file *file, const char __user *buf,
goto free_buf;
}
mutex_unlock(&wpriv->glink_mutex);
-
cpkt = (struct wdsp_cmd_pkt *)wpkt->payload;
- dev_dbg(wpriv->dev, "%s: requested ch_name: %s\n", __func__,
- cpkt->ch_name);
+ pkt_max_size = sizeof(struct wdsp_write_pkt) +
+ sizeof(struct wdsp_cmd_pkt) +
+ cpkt->payload_size;
+ if (count < pkt_max_size) {
+ dev_err(wpriv->dev, "%s: Invalid cmd pkt count = %zd, pkt_size = %zd\n",
+ __func__, count, pkt_max_size);
+ ret = -EINVAL;
+ goto free_buf;
+ }
+ dev_dbg(wpriv->dev, "%s: requested ch_name: %s, pkt_size: %zd\n",
+ __func__, cpkt->ch_name, pkt_max_size);
for (i = 0; i < wpriv->no_of_channels; i++) {
if (wpriv->ch && wpriv->ch[i] &&
(!strcmp(cpkt->ch_name,
@@ -881,13 +912,13 @@ static ssize_t wdsp_glink_write(struct file *file, const char __user *buf,
default:
dev_err(wpriv->dev, "%s: Invalid packet type\n", __func__);
ret = -EINVAL;
- kfree(tx_buf);
+ vfree(tx_buf);
break;
}
goto done;
free_buf:
- kfree(tx_buf);
+ vfree(tx_buf);
done:
return ret;
diff --git a/drivers/staging/android/ion/ion.c b/drivers/staging/android/ion/ion.c
index 58bf3d2f52bd..49ed6de1a95e 100644
--- a/drivers/staging/android/ion/ion.c
+++ b/drivers/staging/android/ion/ion.c
@@ -3,7 +3,7 @@
* drivers/staging/android/ion/ion.c
*
* Copyright (C) 2011 Google, Inc.
- * Copyright (c) 2011-2016, The Linux Foundation. All rights reserved.
+ * Copyright (c) 2011-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
@@ -122,8 +122,6 @@ struct ion_handle {
int id;
};
-static struct ion_device *ion_dev;
-
bool ion_buffer_fault_user_mappings(struct ion_buffer *buffer)
{
return (buffer->flags & ION_FLAG_CACHED) &&
@@ -844,32 +842,45 @@ void ion_unmap_kernel(struct ion_client *client, struct ion_handle *handle)
}
EXPORT_SYMBOL(ion_unmap_kernel);
-static int ion_debug_client_show(struct seq_file *s, void *unused)
+static struct mutex debugfs_mutex;
+static struct rb_root *ion_root_client;
+static int is_client_alive(struct ion_client *client)
{
- struct ion_client *client = s->private;
- struct rb_node *n, *cnode;
- bool found = false;
-
- down_write(&ion_dev->lock);
+ struct rb_node *node;
+ struct ion_client *tmp;
+ struct ion_device *dev;
- if (!client || (client->dev != ion_dev)) {
- up_write(&ion_dev->lock);
- return -EINVAL;
- }
+ node = ion_root_client->rb_node;
+ dev = container_of(ion_root_client, struct ion_device, clients);
- cnode = rb_first(&ion_dev->clients);
- for ( ; cnode; cnode = rb_next(cnode)) {
- struct ion_client *c = rb_entry(cnode,
- struct ion_client, node);
- if (client == c) {
- found = true;
- break;
+ down_read(&dev->lock);
+ while (node) {
+ tmp = rb_entry(node, struct ion_client, node);
+ if (client < tmp) {
+ node = node->rb_left;
+ } else if (client > tmp) {
+ node = node->rb_right;
+ } else {
+ up_read(&dev->lock);
+ return 1;
}
}
- if (!found) {
- up_write(&ion_dev->lock);
- return -EINVAL;
+ up_read(&dev->lock);
+ return 0;
+}
+
+static int ion_debug_client_show(struct seq_file *s, void *unused)
+{
+ struct ion_client *client = s->private;
+ struct rb_node *n;
+
+ mutex_lock(&debugfs_mutex);
+ if (!is_client_alive(client)) {
+ seq_printf(s, "ion_client 0x%pK dead, can't dump its buffers\n",
+ client);
+ mutex_unlock(&debugfs_mutex);
+ return 0;
}
seq_printf(s, "%16.16s: %16.16s : %16.16s : %12.12s\n",
@@ -890,7 +901,7 @@ static int ion_debug_client_show(struct seq_file *s, void *unused)
seq_printf(s, "\n");
}
mutex_unlock(&client->lock);
- up_write(&ion_dev->lock);
+ mutex_unlock(&debugfs_mutex);
return 0;
}
@@ -1021,7 +1032,7 @@ void ion_client_destroy(struct ion_client *client)
struct rb_node *n;
pr_debug("%s: %d\n", __func__, __LINE__);
- mutex_lock(&client->lock);
+ mutex_lock(&debugfs_mutex);
while ((n = rb_first(&client->handles))) {
struct ion_handle *handle = rb_entry(n, struct ion_handle,
node);
@@ -1029,7 +1040,6 @@ void ion_client_destroy(struct ion_client *client)
}
idr_destroy(&client->idr);
- mutex_unlock(&client->lock);
down_write(&dev->lock);
if (client->task)
@@ -1042,6 +1052,7 @@ void ion_client_destroy(struct ion_client *client)
kfree(client->display_name);
kfree(client->name);
kfree(client);
+ mutex_unlock(&debugfs_mutex);
}
EXPORT_SYMBOL(ion_client_destroy);
@@ -1462,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;
@@ -1838,7 +1871,7 @@ static int ion_debug_heap_show(struct seq_file *s, void *unused)
seq_printf(s, "%16s %16s %16s\n", "client", "pid", "size");
seq_puts(s, "----------------------------------------------------\n");
- down_read(&dev->lock);
+ mutex_lock(&debugfs_mutex);
for (n = rb_first(&dev->clients); n; n = rb_next(n)) {
struct ion_client *client = rb_entry(n, struct ion_client,
node);
@@ -1857,7 +1890,8 @@ static int ion_debug_heap_show(struct seq_file *s, void *unused)
client->pid, size);
}
}
- up_read(&dev->lock);
+ mutex_unlock(&debugfs_mutex);
+
seq_puts(s, "----------------------------------------------------\n");
seq_puts(s, "orphaned allocations (info is from last known client):\n");
mutex_lock(&dev->buffer_lock);
@@ -2095,7 +2129,8 @@ debugfs_done:
init_rwsem(&idev->lock);
plist_head_init(&idev->heaps);
idev->clients = RB_ROOT;
- ion_dev = idev;
+ ion_root_client = &idev->clients;
+ mutex_init(&debugfs_mutex);
return idev;
}
EXPORT_SYMBOL(ion_device_create);
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/staging/rdma/ehca/ehca_mrmw.c b/drivers/staging/rdma/ehca/ehca_mrmw.c
index f914b30999f8..4d52ca42644a 100644
--- a/drivers/staging/rdma/ehca/ehca_mrmw.c
+++ b/drivers/staging/rdma/ehca/ehca_mrmw.c
@@ -1921,7 +1921,7 @@ static int ehca_set_pagebuf_user2(struct ehca_mr_pginfo *pginfo,
u64 *kpage)
{
int ret = 0;
- u64 pgaddr, prev_pgaddr;
+ u64 pgaddr, prev_pgaddr = 0;
u32 j = 0;
int kpages_per_hwpage = pginfo->hwpage_size / PAGE_SIZE;
int nr_kpages = kpages_per_hwpage;
@@ -2417,6 +2417,7 @@ static int ehca_reg_bmap_mr_rpages(struct ehca_shca *shca,
ehca_err(&shca->ib_device, "kpage alloc failed");
return -ENOMEM;
}
+ hret = H_SUCCESS;
for (top = 0; top < EHCA_MAP_ENTRIES; top++) {
if (!ehca_bmap_valid(ehca_bmap->top[top]))
continue;
diff --git a/drivers/tty/serial/8250/8250_pci.c b/drivers/tty/serial/8250/8250_pci.c
index 83ff1724ec79..cf3da51a3536 100644
--- a/drivers/tty/serial/8250/8250_pci.c
+++ b/drivers/tty/serial/8250/8250_pci.c
@@ -5850,17 +5850,15 @@ static pci_ers_result_t serial8250_io_slot_reset(struct pci_dev *dev)
static void serial8250_io_resume(struct pci_dev *dev)
{
struct serial_private *priv = pci_get_drvdata(dev);
- const struct pciserial_board *board;
+ struct serial_private *new;
if (!priv)
return;
- board = priv->board;
- kfree(priv);
- priv = pciserial_init_ports(dev, board);
-
- if (!IS_ERR(priv)) {
- pci_set_drvdata(dev, priv);
+ new = pciserial_init_ports(dev, priv->board);
+ if (!IS_ERR(new)) {
+ pci_set_drvdata(dev, new);
+ kfree(priv);
}
}
diff --git a/drivers/usb/gadget/function/f_audio_source.c b/drivers/usb/gadget/function/f_audio_source.c
index a2a9185a0143..51ab794ef6f9 100644
--- a/drivers/usb/gadget/function/f_audio_source.c
+++ b/drivers/usb/gadget/function/f_audio_source.c
@@ -17,6 +17,7 @@
#include <linux/device.h>
#include <linux/usb/audio.h>
#include <linux/wait.h>
+#include <linux/pm_qos.h>
#include <sound/core.h>
#include <sound/initval.h>
#include <sound/pcm.h>
@@ -268,6 +269,8 @@ struct audio_dev {
/* number of frames sent since start_time */
s64 frames_sent;
struct audio_source_config *config;
+ /* for creating and issuing QoS requests */
+ struct pm_qos_request pm_qos;
};
static inline struct audio_dev *func_to_audio(struct usb_function *f)
@@ -740,6 +743,10 @@ static int audio_pcm_open(struct snd_pcm_substream *substream)
runtime->hw.channels_max = 2;
audio->substream = substream;
+
+ /* Add the QoS request and set the latency to 0 */
+ pm_qos_add_request(&audio->pm_qos, PM_QOS_CPU_DMA_LATENCY, 0);
+
return 0;
}
@@ -749,6 +756,10 @@ static int audio_pcm_close(struct snd_pcm_substream *substream)
unsigned long flags;
spin_lock_irqsave(&audio->lock, flags);
+
+ /* Remove the QoS request */
+ pm_qos_remove_request(&audio->pm_qos);
+
audio->substream = NULL;
spin_unlock_irqrestore(&audio->lock, flags);
diff --git a/drivers/usb/gadget/function/f_cdev.c b/drivers/usb/gadget/function/f_cdev.c
index d45f4be4a075..34ec15ab9010 100644
--- a/drivers/usb/gadget/function/f_cdev.c
+++ b/drivers/usb/gadget/function/f_cdev.c
@@ -48,7 +48,7 @@
#define DEVICE_NAME "at_usb"
#define MODULE_NAME "msm_usb_bridge"
-#define NUM_INSTANCE 2
+#define NUM_INSTANCE 3
#define MAX_CDEV_INST_NAME 15
#define MAX_CDEV_FUNC_NAME 5
@@ -823,8 +823,10 @@ static void cser_free_inst(struct usb_function_instance *fi)
opts = container_of(fi, struct f_cdev_opts, func_inst);
- device_destroy(fcdev_classp, MKDEV(major, opts->port->minor));
- cdev_del(&opts->port->fcdev_cdev);
+ if (opts->port) {
+ device_destroy(fcdev_classp, MKDEV(major, opts->port->minor));
+ cdev_del(&opts->port->fcdev_cdev);
+ }
usb_cser_chardev_deinit();
kfree(opts->func_name);
kfree(opts->port);
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 4a0b3a0aa65e..999433ae2d72 100644
--- a/drivers/usb/gadget/function/f_mtp.c
+++ b/drivers/usb/gadget/function/f_mtp.c
@@ -47,6 +47,7 @@
#define MTP_BULK_BUFFER_SIZE 16384
#define INTR_BUFFER_SIZE 28
#define MAX_INST_NAME_LEN 40
+#define MTP_MAX_FILE_SIZE 0xFFFFFFFFL
/* String IDs */
#define INTERFACE_STRING_INDEX 0
@@ -868,14 +869,11 @@ static void send_file_work(struct work_struct *data)
/* prepend MTP data header */
header = (struct mtp_data_header *)req->buf;
/*
- * Set length as 0xffffffff, if it is greater than
- * 0xffffffff. Otherwise host will throw error, if file
- * size greater than 0xffffffff being transferred.
- */
- if (count > 0xffffffffLL)
- header->length = 0xffffffff;
- else
- header->length = __cpu_to_le32(count);
+ * set file size with header according to
+ * MTP Specification v1.0
+ */
+ header->length = (count > MTP_MAX_FILE_SIZE) ?
+ MTP_MAX_FILE_SIZE : __cpu_to_le32(count);
header->type = __cpu_to_le16(2); /* data packet */
header->command = __cpu_to_le16(dev->xfer_command);
header->transaction_id =
@@ -1490,6 +1488,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 +1500,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 +1517,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,
@@ -1854,6 +1855,8 @@ struct usb_function_instance *alloc_inst_mtp_ptp(bool mtp_config)
config_group_init_type_name(&fi_mtp->func_inst.group,
"", &mtp_func_type);
+ mutex_init(&fi_mtp->dev->read_mutex);
+
return &fi_mtp->func_inst;
}
EXPORT_SYMBOL_GPL(alloc_inst_mtp_ptp);
@@ -1914,9 +1917,7 @@ 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;
- mutex_init(&dev->read_mutex);
return &dev->function;
}
EXPORT_SYMBOL_GPL(function_alloc_mtp_ptp);
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/usb/phy/phy-msm-qusb-v2.c b/drivers/usb/phy/phy-msm-qusb-v2.c
index 6fb91134b0c5..5df091a5454b 100644
--- a/drivers/usb/phy/phy-msm-qusb-v2.c
+++ b/drivers/usb/phy/phy-msm-qusb-v2.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2014-2016, The Linux Foundation. All rights reserved.
+ * Copyright (c) 2014-2017, The Linux Foundation. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 and
@@ -90,6 +90,7 @@ struct qusb_phy {
struct regulator *vdda18;
struct regulator *vdda12;
int vdd_levels[3]; /* none, low, high */
+ int vdda33_levels[3];
int init_seq_len;
int *qusb_phy_init_seq;
int host_init_seq_len;
@@ -236,8 +237,8 @@ static int qusb_phy_enable_power(struct qusb_phy *qphy, bool on,
goto disable_vdda18;
}
- ret = regulator_set_voltage(qphy->vdda33, QUSB2PHY_3P3_VOL_MIN,
- QUSB2PHY_3P3_VOL_MAX);
+ ret = regulator_set_voltage(qphy->vdda33, qphy->vdda33_levels[0],
+ qphy->vdda33_levels[2]);
if (ret) {
dev_err(qphy->phy.dev,
"Unable to set voltage for vdda33:%d\n", ret);
@@ -262,7 +263,7 @@ disable_vdda33:
dev_err(qphy->phy.dev, "Unable to disable vdda33:%d\n", ret);
unset_vdd33:
- ret = regulator_set_voltage(qphy->vdda33, 0, QUSB2PHY_3P3_VOL_MAX);
+ ret = regulator_set_voltage(qphy->vdda33, 0, qphy->vdda33_levels[2]);
if (ret)
dev_err(qphy->phy.dev,
"Unable to set (0) voltage for vdda33:%d\n", ret);
@@ -455,6 +456,15 @@ static int qusb_phy_init(struct usb_phy *phy)
if (ret)
return ret;
+ /* bump up vdda33 voltage to operating level*/
+ ret = regulator_set_voltage(qphy->vdda33, qphy->vdda33_levels[1],
+ qphy->vdda33_levels[2]);
+ if (ret) {
+ dev_err(qphy->phy.dev,
+ "Unable to set voltage for vdda33:%d\n", ret);
+ return ret;
+ }
+
qusb_phy_enable_clocks(qphy, true);
/* Perform phy reset */
@@ -1016,6 +1026,19 @@ static int qusb_phy_probe(struct platform_device *pdev)
return ret;
}
+ ret = of_property_read_u32_array(dev->of_node,
+ "qcom,vdda33-voltage-level",
+ (u32 *) qphy->vdda33_levels,
+ ARRAY_SIZE(qphy->vdda33_levels));
+ if (ret == -EINVAL) {
+ qphy->vdda33_levels[0] = QUSB2PHY_3P3_VOL_MIN;
+ qphy->vdda33_levels[1] = QUSB2PHY_3P3_VOL_MIN;
+ qphy->vdda33_levels[2] = QUSB2PHY_3P3_VOL_MAX;
+ } else if (ret) {
+ dev_err(dev, "error reading qcom,vdda33-voltage-level property\n");
+ return ret;
+ }
+
qphy->vdd = devm_regulator_get(dev, "vdd");
if (IS_ERR(qphy->vdd)) {
dev_err(dev, "unable to get vdd supply\n");
diff --git a/drivers/video/fbdev/msm/dsi_status_6g.c b/drivers/video/fbdev/msm/dsi_status_6g.c
index 869ff1d9df37..d24b19ea77ad 100644
--- a/drivers/video/fbdev/msm/dsi_status_6g.c
+++ b/drivers/video/fbdev/msm/dsi_status_6g.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
@@ -17,6 +17,7 @@
#include "mdss_dsi.h"
#include "mdss_mdp.h"
+#include "mdss_debug.h"
/*
* mdss_check_te_status() - Check the status of panel for TE based ESD.
@@ -157,6 +158,7 @@ void mdss_check_dsi_ctrl_status(struct work_struct *work, uint32_t interval)
ctl->ops.wait_pingpong(ctl, NULL);
pr_debug("%s: DSI ctrl wait for ping pong done\n", __func__);
+ MDSS_XLOG(mipi->mode);
mdss_mdp_clk_ctrl(MDP_BLOCK_POWER_ON);
ret = ctrl_pdata->check_status(ctrl_pdata);
diff --git a/drivers/video/fbdev/msm/mdss.h b/drivers/video/fbdev/msm/mdss.h
index 796246a856b4..1c984d02755e 100644
--- a/drivers/video/fbdev/msm/mdss.h
+++ b/drivers/video/fbdev/msm/mdss.h
@@ -45,6 +45,7 @@ enum mdss_mdp_clk_type {
MDSS_CLK_MDP_LUT,
MDSS_CLK_MDP_VSYNC,
MDSS_CLK_MNOC_AHB,
+ MDSS_CLK_THROTTLE_AXI,
MDSS_MAX_CLK
};
diff --git a/drivers/video/fbdev/msm/mdss_compat_utils.c b/drivers/video/fbdev/msm/mdss_compat_utils.c
index e9ba77501b38..2b9c71441d68 100644
--- a/drivers/video/fbdev/msm/mdss_compat_utils.c
+++ b/drivers/video/fbdev/msm/mdss_compat_utils.c
@@ -119,6 +119,9 @@ static unsigned int __do_compat_ioctl_nr(unsigned int cmd32)
static void __copy_atomic_commit_struct(struct mdp_layer_commit *commit,
struct mdp_layer_commit32 *commit32)
{
+ unsigned int destSize = sizeof(commit->commit_v1.reserved);
+ unsigned int srcSize = sizeof(commit32->commit_v1.reserved);
+ unsigned int count = (destSize <= srcSize ? destSize : srcSize);
commit->version = commit32->version;
commit->commit_v1.flags = commit32->commit_v1.flags;
commit->commit_v1.input_layer_cnt =
@@ -127,7 +130,7 @@ static void __copy_atomic_commit_struct(struct mdp_layer_commit *commit,
commit->commit_v1.right_roi = commit32->commit_v1.right_roi;
commit->commit_v1.bl_level = commit32->commit_v1.bl_level;
memcpy(&commit->commit_v1.reserved, &commit32->commit_v1.reserved,
- sizeof(commit32->commit_v1.reserved));
+ count);
}
static struct mdp_input_layer32 *__create_layer_list32(
@@ -220,6 +223,7 @@ static struct mdp_input_layer *__create_layer_list(
layer->flags = layer32->flags;
layer->pipe_ndx = layer32->pipe_ndx;
+ layer->rect_num = layer32->rect_num;
layer->horz_deci = layer32->horz_deci;
layer->vert_deci = layer32->vert_deci;
layer->z_order = layer32->z_order;
diff --git a/drivers/video/fbdev/msm/mdss_compat_utils.h b/drivers/video/fbdev/msm/mdss_compat_utils.h
index 4f44cd1c9471..b7fa401f52d2 100644
--- a/drivers/video/fbdev/msm/mdss_compat_utils.h
+++ b/drivers/video/fbdev/msm/mdss_compat_utils.h
@@ -515,7 +515,8 @@ struct mdp_input_layer32 {
struct mdp_layer_buffer buffer;
compat_caddr_t pp_info;
int error_code;
- uint32_t reserved[6];
+ uint32_t rect_num;
+ uint32_t reserved[5];
};
struct mdp_output_layer32 {
diff --git a/drivers/video/fbdev/msm/mdss_debug.c b/drivers/video/fbdev/msm/mdss_debug.c
index ddb7a4c31f68..8cb6c7157230 100644
--- a/drivers/video/fbdev/msm/mdss_debug.c
+++ b/drivers/video/fbdev/msm/mdss_debug.c
@@ -1077,7 +1077,7 @@ static ssize_t mdss_debug_perf_bw_limit_read(struct file *file,
struct mdss_data_type *mdata = file->private_data;
struct mdss_max_bw_settings *temp_settings;
int len = 0, i;
- char buf[256];
+ char buf[256] = {'\0'};
if (!mdata)
return -ENODEV;
diff --git a/drivers/video/fbdev/msm/mdss_debug_xlog.c b/drivers/video/fbdev/msm/mdss_debug_xlog.c
index bf4117650e3c..aeefc81657b0 100644
--- a/drivers/video/fbdev/msm/mdss_debug_xlog.c
+++ b/drivers/video/fbdev/msm/mdss_debug_xlog.c
@@ -93,6 +93,48 @@ static inline bool mdss_xlog_is_enabled(u32 flag)
(flag == MDSS_XLOG_ALL && mdss_dbg_xlog.xlog_enable);
}
+static void __halt_vbif_xin(void)
+{
+ struct mdss_data_type *mdata = mdss_mdp_get_mdata();
+
+ pr_err("Halting VBIF-XIN\n");
+ MDSS_VBIF_WRITE(mdata, MMSS_VBIF_XIN_HALT_CTRL0, 0xFFFFFFFF, false);
+}
+
+static void __halt_vbif_axi(void)
+{
+ struct mdss_data_type *mdata = mdss_mdp_get_mdata();
+
+ pr_err("Halting VBIF-AXI\n");
+ MDSS_VBIF_WRITE(mdata, MMSS_VBIF_AXI_HALT_CTRL0, 0xFFFFFFFF, false);
+}
+
+static void __dump_vbif_state(void)
+{
+ struct mdss_data_type *mdata = mdss_mdp_get_mdata();
+ unsigned int reg_vbif_src_err, reg_vbif_err_info,
+ reg_vbif_xin_halt_ctrl0, reg_vbif_xin_halt_ctrl1,
+ reg_vbif_axi_halt_ctrl0, reg_vbif_axi_halt_ctrl1;
+
+ reg_vbif_src_err = MDSS_VBIF_READ(mdata,
+ MMSS_VBIF_SRC_ERR, false);
+ reg_vbif_err_info = MDSS_VBIF_READ(mdata,
+ MMSS_VBIF_ERR_INFO, false);
+ reg_vbif_xin_halt_ctrl0 = MDSS_VBIF_READ(mdata,
+ MMSS_VBIF_XIN_HALT_CTRL0, false);
+ reg_vbif_xin_halt_ctrl1 = MDSS_VBIF_READ(mdata,
+ MMSS_VBIF_XIN_HALT_CTRL1, false);
+ reg_vbif_axi_halt_ctrl0 = MDSS_VBIF_READ(mdata,
+ MMSS_VBIF_AXI_HALT_CTRL0, false);
+ reg_vbif_axi_halt_ctrl1 = MDSS_VBIF_READ(mdata,
+ MMSS_VBIF_AXI_HALT_CTRL1, false);
+ pr_err("VBIF SRC_ERR=%x, ERR_INFO=%x\n",
+ reg_vbif_src_err, reg_vbif_err_info);
+ pr_err("VBIF XIN_HALT_CTRL0=%x, XIN_HALT_CTRL1=%x, AXI_HALT_CTRL0=%x, AXI_HALT_CTRL1=%x\n"
+ , reg_vbif_xin_halt_ctrl0, reg_vbif_xin_halt_ctrl1,
+ reg_vbif_axi_halt_ctrl0, reg_vbif_axi_halt_ctrl1);
+}
+
void mdss_xlog(const char *name, int line, int flag, ...)
{
unsigned long flags;
@@ -611,8 +653,17 @@ static void mdss_xlog_dump_array(struct mdss_debug_base *blk_arr[],
mdss_dump_dsi_debug_bus(mdss_dbg_xlog.enable_dsi_dbgbus_dump,
&mdss_dbg_xlog.dsi_dbgbus_dump);
- if (dead && mdss_dbg_xlog.panic_on_err)
+ if (dead && mdss_dbg_xlog.panic_on_err) {
+ mdss_mdp_clk_ctrl(MDP_BLOCK_POWER_ON);
+ __dump_vbif_state();
+ __halt_vbif_xin();
+ usleep_range(10000, 10010);
+ __halt_vbif_axi();
+ usleep_range(10000, 10010);
+ __dump_vbif_state();
+ mdss_mdp_clk_ctrl(MDP_BLOCK_POWER_OFF);
panic(name);
+ }
}
static void xlog_debug_work(struct work_struct *work)
diff --git a/drivers/video/fbdev/msm/mdss_dp.c b/drivers/video/fbdev/msm/mdss_dp.c
index 1e878e9a00cb..37346c40d81d 100644
--- a/drivers/video/fbdev/msm/mdss_dp.c
+++ b/drivers/video/fbdev/msm/mdss_dp.c
@@ -3943,6 +3943,12 @@ static int mdss_dp_process_hpd_irq_high(struct mdss_dp_drv_pdata *dp)
{
int ret = 0;
+ /* In case of HPD_IRQ events without DP link being turned on such as
+ * adb shell stop, skip handling hpd_irq event.
+ */
+ if (!dp->dp_initialized)
+ goto exit;
+
pr_debug("start\n");
dp->hpd_irq_on = true;
diff --git a/drivers/video/fbdev/msm/mdss_fb.c b/drivers/video/fbdev/msm/mdss_fb.c
index 698c5633cf6a..4eca9cb39223 100644
--- a/drivers/video/fbdev/msm/mdss_fb.c
+++ b/drivers/video/fbdev/msm/mdss_fb.c
@@ -2121,6 +2121,7 @@ static int mdss_fb_blank(int blank_mode, struct fb_info *info)
mdss_mdp_enable_panel_disable_mode(mfd, false);
ret = mdss_fb_blank_sub(blank_mode, info, mfd->op_enable);
+ MDSS_XLOG(blank_mode);
end:
mutex_unlock(&mfd->mdss_sysfs_lock);
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.c b/drivers/video/fbdev/msm/mdss_mdp.c
index a645a3495593..d88d87bd2092 100644
--- a/drivers/video/fbdev/msm/mdss_mdp.c
+++ b/drivers/video/fbdev/msm/mdss_mdp.c
@@ -1373,7 +1373,9 @@ static inline void __mdss_mdp_reg_access_clk_enable(
mdss_mdp_clk_update(MDSS_CLK_AHB, 1);
mdss_mdp_clk_update(MDSS_CLK_AXI, 1);
mdss_mdp_clk_update(MDSS_CLK_MDP_CORE, 1);
+ mdss_mdp_clk_update(MDSS_CLK_THROTTLE_AXI, 1);
} else {
+ mdss_mdp_clk_update(MDSS_CLK_THROTTLE_AXI, 0);
mdss_mdp_clk_update(MDSS_CLK_MDP_CORE, 0);
mdss_mdp_clk_update(MDSS_CLK_AXI, 0);
mdss_mdp_clk_update(MDSS_CLK_AHB, 0);
@@ -1415,6 +1417,7 @@ static void __mdss_mdp_clk_control(struct mdss_data_type *mdata, bool enable)
mdss_mdp_clk_update(MDSS_CLK_AXI, 1);
mdss_mdp_clk_update(MDSS_CLK_MDP_CORE, 1);
mdss_mdp_clk_update(MDSS_CLK_MDP_LUT, 1);
+ mdss_mdp_clk_update(MDSS_CLK_THROTTLE_AXI, 1);
if (mdata->vsync_ena)
mdss_mdp_clk_update(MDSS_CLK_MDP_VSYNC, 1);
} else {
@@ -1430,6 +1433,7 @@ static void __mdss_mdp_clk_control(struct mdss_data_type *mdata, bool enable)
mdss_mdp_clk_update(MDSS_CLK_AXI, 0);
mdss_mdp_clk_update(MDSS_CLK_AHB, 0);
mdss_mdp_clk_update(MDSS_CLK_MNOC_AHB, 0);
+ mdss_mdp_clk_update(MDSS_CLK_THROTTLE_AXI, 0);
/* release iommu control */
mdss_iommu_ctrl(0);
@@ -1915,8 +1919,7 @@ static int mdss_mdp_irq_clk_setup(struct mdss_data_type *mdata)
if (mdss_mdp_irq_clk_register(mdata, "bus_clk", MDSS_CLK_AXI) ||
mdss_mdp_irq_clk_register(mdata, "iface_clk", MDSS_CLK_AHB) ||
- mdss_mdp_irq_clk_register(mdata, "core_clk",
- MDSS_CLK_MDP_CORE))
+ mdss_mdp_irq_clk_register(mdata, "core_clk", MDSS_CLK_MDP_CORE))
return -EINVAL;
/* lut_clk is not present on all MDSS revisions */
@@ -1928,6 +1931,10 @@ static int mdss_mdp_irq_clk_setup(struct mdss_data_type *mdata)
/* this clk is not present on all MDSS revisions */
mdss_mdp_irq_clk_register(mdata, "mnoc_clk", MDSS_CLK_MNOC_AHB);
+ /* this clk is not present on all MDSS revisions */
+ mdss_mdp_irq_clk_register(mdata, "throttle_bus_clk",
+ MDSS_CLK_THROTTLE_AXI);
+
/* Setting the default clock rate to the max supported.*/
mdss_mdp_set_clk_rate(mdata->max_mdp_clk_rate, false);
pr_debug("mdp clk rate=%ld\n",
diff --git a/drivers/video/fbdev/msm/mdss_mdp.h b/drivers/video/fbdev/msm/mdss_mdp.h
index a2139f495f52..fd2c2cdb3820 100644
--- a/drivers/video/fbdev/msm/mdss_mdp.h
+++ b/drivers/video/fbdev/msm/mdss_mdp.h
@@ -2023,6 +2023,8 @@ void mdss_mdp_set_supported_formats(struct mdss_data_type *mdata);
int mdss_mdp_dest_scaler_setup_locked(struct mdss_mdp_mixer *mixer);
void *mdss_mdp_intf_get_ctx_base(struct mdss_mdp_ctl *ctl, int intf_num);
+int mdss_mdp_mixer_get_hw_num(struct mdss_mdp_mixer *mixer);
+
#ifdef CONFIG_FB_MSM_MDP_NONE
struct mdss_data_type *mdss_mdp_get_mdata(void)
{
diff --git a/drivers/video/fbdev/msm/mdss_mdp_ctl.c b/drivers/video/fbdev/msm/mdss_mdp_ctl.c
index 1f29a9f86e24..c062de3c1e59 100644
--- a/drivers/video/fbdev/msm/mdss_mdp_ctl.c
+++ b/drivers/video/fbdev/msm/mdss_mdp_ctl.c
@@ -4802,7 +4802,7 @@ static void __mdss_mdp_mixer_get_offsets(u32 mixer_num,
offsets[2] = MDSS_MDP_REG_CTL_LAYER_EXTN2(mixer_num);
}
-static inline int __mdss_mdp_mixer_get_hw_num(struct mdss_mdp_mixer *mixer)
+int mdss_mdp_mixer_get_hw_num(struct mdss_mdp_mixer *mixer)
{
struct mdss_data_type *mdata = mdss_mdp_get_mdata();
@@ -4858,7 +4858,7 @@ static void __mdss_mdp_mixer_write_cfg(struct mdss_mdp_mixer *mixer,
if (!mixer)
return;
- mixer_num = __mdss_mdp_mixer_get_hw_num(mixer);
+ mixer_num = mdss_mdp_mixer_get_hw_num(mixer);
if (cfg) {
for (i = 0; i < NUM_MIXERCFG_REGS; i++)
@@ -4905,7 +4905,7 @@ bool mdss_mdp_mixer_reg_has_pipe(struct mdss_mdp_mixer *mixer,
memset(&mixercfg, 0, sizeof(mixercfg));
- mixer_num = __mdss_mdp_mixer_get_hw_num(mixer);
+ mixer_num = mdss_mdp_mixer_get_hw_num(mixer);
__mdss_mdp_mixer_get_offsets(mixer_num, offs, NUM_MIXERCFG_REGS);
for (i = 0; i < NUM_MIXERCFG_REGS; i++)
@@ -5130,7 +5130,7 @@ static void mdss_mdp_mixer_setup(struct mdss_mdp_ctl *master_ctl,
mixercfg.cursor_enabled = true;
update_mixer:
- mixer_num = __mdss_mdp_mixer_get_hw_num(mixer_hw);
+ mixer_num = mdss_mdp_mixer_get_hw_num(mixer_hw);
ctl_hw->flush_bits |= BIT(mixer_num < 5 ? 6 + mixer_num : 20);
/* Read GC enable/disable status on LM */
@@ -5775,6 +5775,7 @@ int mdss_mdp_display_commit(struct mdss_mdp_ctl *ctl, void *arg,
mdss_mdp_clk_ctrl(MDP_BLOCK_POWER_ON);
if (ctl->ops.avr_ctrl_fnc) {
+ /* avr_ctrl_fnc will configure both master & slave */
ret = ctl->ops.avr_ctrl_fnc(ctl, true);
if (ret) {
pr_err("error configuring avr ctrl registers ctl=%d err=%d\n",
@@ -5784,16 +5785,6 @@ int mdss_mdp_display_commit(struct mdss_mdp_ctl *ctl, void *arg,
}
}
- if (sctl && sctl->ops.avr_ctrl_fnc) {
- ret = sctl->ops.avr_ctrl_fnc(sctl, true);
- if (ret) {
- pr_err("error configuring avr ctrl registers sctl=%d err=%d\n",
- sctl->num, ret);
- mutex_unlock(&ctl->lock);
- return ret;
- }
- }
-
mutex_lock(&ctl->flush_lock);
/*
@@ -6046,6 +6037,10 @@ int mdss_mdp_display_commit(struct mdss_mdp_ctl *ctl, void *arg,
ctl_flush_bits |= ctl->flush_bits;
ATRACE_BEGIN("flush_kickoff");
+
+ MDSS_XLOG(ctl->intf_num, ctl_flush_bits, sctl_flush_bits,
+ mdss_mdp_ctl_read(ctl, MDSS_MDP_REG_CTL_FLUSH), split_lm_valid);
+
mdss_mdp_ctl_write(ctl, MDSS_MDP_REG_CTL_FLUSH, ctl_flush_bits);
if (sctl) {
if (sctl_flush_bits) {
@@ -6057,8 +6052,6 @@ int mdss_mdp_display_commit(struct mdss_mdp_ctl *ctl, void *arg,
}
ctl->commit_in_progress = false;
- MDSS_XLOG(ctl->intf_num, ctl_flush_bits, sctl_flush_bits,
- split_lm_valid);
wmb();
ctl->flush_reg_data = ctl_flush_bits;
ctl->flush_bits = 0;
diff --git a/drivers/video/fbdev/msm/mdss_mdp_debug.c b/drivers/video/fbdev/msm/mdss_mdp_debug.c
index 1ad6810a6bb6..1035d23fe9ce 100644
--- a/drivers/video/fbdev/msm/mdss_mdp_debug.c
+++ b/drivers/video/fbdev/msm/mdss_mdp_debug.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2014-2016, The Linux Foundation. All rights reserved.
+ * Copyright (c) 2014-2017, The Linux Foundation. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 and
@@ -1757,6 +1757,8 @@ void mdss_mdp_hw_rev_debug_caps_init(struct mdss_data_type *mdata)
break;
case MDSS_MDP_HW_REV_300:
case MDSS_MDP_HW_REV_301:
+ case MDSS_MDP_HW_REV_320:
+ case MDSS_MDP_HW_REV_330:
mdata->dbg_bus = dbg_bus_msm8998;
mdata->dbg_bus_size = ARRAY_SIZE(dbg_bus_msm8998);
mdata->vbif_dbg_bus = vbif_dbg_bus_msm8998;
diff --git a/drivers/video/fbdev/msm/mdss_mdp_hwio.h b/drivers/video/fbdev/msm/mdss_mdp_hwio.h
index d9e2b042bfc3..78bfab7d8ce8 100644
--- a/drivers/video/fbdev/msm/mdss_mdp_hwio.h
+++ b/drivers/video/fbdev/msm/mdss_mdp_hwio.h
@@ -829,6 +829,8 @@ enum mdss_mdp_pingpong_index {
#define MMSS_VBIF_WR_LIM_CONF 0x0C0
#define MDSS_VBIF_WRITE_GATHER_EN 0x0AC
+#define MMSS_VBIF_SRC_ERR 0x194
+#define MMSS_VBIF_ERR_INFO 0x1A0
#define MMSS_VBIF_XIN_HALT_CTRL0 0x200
#define MMSS_VBIF_XIN_HALT_CTRL1 0x204
#define MMSS_VBIF_AXI_HALT_CTRL0 0x208
diff --git a/drivers/video/fbdev/msm/mdss_mdp_intf_video.c b/drivers/video/fbdev/msm/mdss_mdp_intf_video.c
index 13c70822e266..587150bbc9fa 100644
--- a/drivers/video/fbdev/msm/mdss_mdp_intf_video.c
+++ b/drivers/video/fbdev/msm/mdss_mdp_intf_video.c
@@ -72,6 +72,7 @@ struct mdss_mdp_video_ctx {
u8 ref_cnt;
u8 timegen_en;
+ bool timegen_flush_pending;
bool polling_en;
u32 poll_cnt;
struct completion vsync_comp;
@@ -451,13 +452,32 @@ static int mdss_mdp_video_intf_recovery(void *data, int event)
}
}
+static int mdss_mdp_video_wait_one_frame(struct mdss_mdp_ctl *ctl)
+{
+ u32 frame_time, frame_rate;
+ int ret = 0;
+ struct mdss_panel_data *pdata = ctl->panel_data;
+
+ if (pdata == NULL) {
+ frame_rate = DEFAULT_FRAME_RATE;
+ } else {
+ frame_rate = mdss_panel_get_framerate(&pdata->panel_info);
+ if (!(frame_rate >= 24 && frame_rate <= 240))
+ frame_rate = 24;
+ }
+
+ frame_time = ((1000/frame_rate) + 1);
+
+ msleep(frame_time);
+
+ return ret;
+}
+
static void mdss_mdp_video_avr_vtotal_setup(struct mdss_mdp_ctl *ctl,
struct intf_timing_params *p,
struct mdss_mdp_video_ctx *ctx)
{
struct mdss_data_type *mdata = ctl->mdata;
- struct mdss_mdp_ctl *sctl = NULL;
- struct mdss_mdp_video_ctx *sctx = NULL;
if (test_bit(MDSS_CAPS_AVR_SUPPORTED, mdata->mdss_caps_map)) {
struct mdss_panel_data *pdata = ctl->panel_data;
@@ -484,14 +504,11 @@ static void mdss_mdp_video_avr_vtotal_setup(struct mdss_mdp_ctl *ctl,
/*
* Make sure config goes through
+ * and queue timegen flush
*/
wmb();
- sctl = mdss_mdp_get_split_ctl(ctl);
- if (sctl)
- sctx = (struct mdss_mdp_video_ctx *)
- sctl->intf_ctx[MASTER_CTX];
- mdss_mdp_video_timegen_flush(ctl, sctx);
+ ctx->timegen_flush_pending = true;
MDSS_XLOG(pinfo->min_fps, pinfo->default_fps, avr_vtotal);
}
@@ -687,8 +704,10 @@ static void mdss_mdp_video_timegen_flush(struct mdss_mdp_ctl *ctl,
ctl_flush |= (BIT(31) >>
(sctx->intf_num - MDSS_MDP_INTF0));
}
+ MDSS_XLOG(ctl->intf_num, sctx?sctx->intf_num:0xf00, ctl_flush,
+ mdss_mdp_ctl_read(ctl, MDSS_MDP_REG_CTL_FLUSH));
mdss_mdp_ctl_write(ctl, MDSS_MDP_REG_CTL_FLUSH, ctl_flush);
- MDSS_XLOG(ctl->intf_num, sctx?sctx->intf_num:0xf00, ctl_flush);
+
}
static inline void video_vsync_irq_enable(struct mdss_mdp_ctl *ctl, bool clear)
@@ -2464,25 +2483,41 @@ static int mdss_mdp_video_early_wake_up(struct mdss_mdp_ctl *ctl)
static int mdss_mdp_video_avr_ctrl(struct mdss_mdp_ctl *ctl, bool enable)
{
struct mdss_mdp_video_ctx *ctx = NULL, *sctx = NULL;
+ struct mdss_mdp_ctl *sctl;
ctx = (struct mdss_mdp_video_ctx *) ctl->intf_ctx[MASTER_CTX];
if (!ctx || !ctx->ref_cnt) {
pr_err("invalid master ctx\n");
return -EINVAL;
}
- mdss_mdp_video_avr_ctrl_setup(ctx, ctl, ctl->is_master,
- enable);
- if (is_pingpong_split(ctl->mfd)) {
+ sctl = mdss_mdp_get_split_ctl(ctl);
+ if (sctl) {
+ sctx = (struct mdss_mdp_video_ctx *) sctl->intf_ctx[MASTER_CTX];
+ } else if (is_pingpong_split(ctl->mfd)) {
sctx = (struct mdss_mdp_video_ctx *) ctl->intf_ctx[SLAVE_CTX];
if (!sctx || !sctx->ref_cnt) {
pr_err("invalid slave ctx\n");
return -EINVAL;
}
- mdss_mdp_video_avr_ctrl_setup(sctx, ctl, false,
- enable);
}
+ if (ctx->timegen_flush_pending) {
+ mdss_mdp_video_timegen_flush(ctl, sctx);
+
+ /* wait a frame for flush to be completed */
+ mdss_mdp_video_wait_one_frame(ctl);
+
+ ctx->timegen_flush_pending = false;
+ if (sctx)
+ sctx->timegen_flush_pending = false;
+ }
+
+ mdss_mdp_video_avr_ctrl_setup(ctx, ctl, ctl->is_master, enable);
+
+ if (sctx)
+ mdss_mdp_video_avr_ctrl_setup(sctx, ctl, false, enable);
+
return 0;
}
diff --git a/drivers/video/fbdev/msm/mdss_mdp_layer.c b/drivers/video/fbdev/msm/mdss_mdp_layer.c
index 09a34223c2a5..472f1e8e8e3b 100644
--- a/drivers/video/fbdev/msm/mdss_mdp_layer.c
+++ b/drivers/video/fbdev/msm/mdss_mdp_layer.c
@@ -2160,115 +2160,157 @@ static int __multirect_validate_mode(struct msm_fb_data_type *mfd,
return 0;
}
-static int __update_multirect_info(struct msm_fb_data_type *mfd,
- struct mdss_mdp_validate_info_t *validate_info_list,
- struct mdp_input_layer *layer_list, int ndx, int layer_cnt)
+/*
+ * linear search for a layer with given source pipe and rectangle number.
+ * If rectangle number is invalid, it's dropped from search criteria
+ */
+static int find_layer(enum mdss_mdp_sspp_index pnum,
+ int rect_num,
+ struct mdp_input_layer *layer_list,
+ size_t layer_cnt, int start_index)
{
- struct mdss_data_type *mdata = mdss_mdp_get_mdata();
- struct mdss_mdp_validate_info_t *vinfo[MDSS_MDP_PIPE_MAX_RECTS];
- int i, ptype, max_rects, mode;
- int cnt = 1;
+ int i;
- mode = __multirect_layer_flags_to_mode(layer_list[ndx].flags);
- if (IS_ERR_VALUE(mode))
- return mode;
+ if (start_index < 0)
+ start_index = 0;
- pr_debug("layer #%d pipe_ndx=%d multirect mode=%d\n",
- ndx, layer_list[ndx].pipe_ndx, mode);
+ if (start_index >= layer_cnt)
+ return -EINVAL;
- vinfo[0] = &validate_info_list[ndx];
- vinfo[0]->layer = &layer_list[ndx];
- vinfo[0]->multirect.mode = mode;
- vinfo[0]->multirect.num = MDSS_MDP_PIPE_RECT0;
- vinfo[0]->multirect.next = NULL;
+ for (i = start_index; i < layer_cnt; i++) {
+ if (get_pipe_num_from_ndx(layer_list[i].pipe_ndx) == pnum &&
+ (rect_num < MDSS_MDP_PIPE_RECT0 ||
+ rect_num >= MDSS_MDP_PIPE_MAX_RECTS ||
+ layer_list[i].rect_num == rect_num))
+ return i;
+ }
- /* nothing to be done if multirect is disabled */
- if (mode == MDSS_MDP_PIPE_MULTIRECT_NONE)
- return cnt;
+ return -ENOENT; /* no match found */
+}
- ptype = get_pipe_type_from_ndx(layer_list[ndx].pipe_ndx);
- if (ptype == MDSS_MDP_PIPE_TYPE_INVALID) {
- pr_err("invalid pipe ndx %d\n", layer_list[ndx].pipe_ndx);
- return -EINVAL;
- }
+static int __validate_multirect_param(struct msm_fb_data_type *mfd,
+ struct mdss_mdp_validate_info_t *validate_info_list,
+ struct mdp_input_layer *layer_list,
+ int ndx, size_t layer_count)
+{
+ int multirect_mode;
+ int pnum;
+ int rect_num;
+
+ /* populate v_info with default values */
+ validate_info_list[ndx].layer = &layer_list[ndx];
+ validate_info_list[ndx].multirect.max_rects = MDSS_MDP_PIPE_MAX_RECTS;
+ validate_info_list[ndx].multirect.next = NULL;
+ validate_info_list[ndx].multirect.num = MDSS_MDP_PIPE_RECT0;
+ validate_info_list[ndx].multirect.mode = MDSS_MDP_PIPE_MULTIRECT_NONE;
+
+ multirect_mode = __multirect_layer_flags_to_mode(
+ layer_list[ndx].flags);
+ if (IS_ERR_VALUE(multirect_mode))
+ return multirect_mode;
- max_rects = mdata->rects_per_sspp[ptype] ? : 1;
+ /* nothing to be done if multirect is disabled */
+ if (multirect_mode == MDSS_MDP_PIPE_MULTIRECT_NONE)
+ return 0;
- for (i = ndx + 1; i < layer_cnt; i++) {
- if (layer_list[ndx].pipe_ndx == layer_list[i].pipe_ndx) {
- if (cnt >= max_rects) {
- pr_err("more than %d layers of type %d with same pipe_ndx=%d indexes=%d %d\n",
- max_rects, ptype,
- layer_list[ndx].pipe_ndx, ndx, i);
- return -EINVAL;
- }
+ validate_info_list[ndx].multirect.mode = multirect_mode;
- mode = __multirect_layer_flags_to_mode(
- layer_list[i].flags);
- if (IS_ERR_VALUE(mode))
- return mode;
+ pnum = get_pipe_num_from_ndx(layer_list[ndx].pipe_ndx);
+ if (get_pipe_type_from_num(pnum) != MDSS_MDP_PIPE_TYPE_DMA) {
+ pr_err("Multirect not supported on pipe ndx 0x%x\n",
+ layer_list[ndx].pipe_ndx);
+ return -EINVAL;
+ }
- if (mode != vinfo[0]->multirect.mode) {
- pr_err("unable to set different multirect modes for pipe_ndx=%d (%d %d)\n",
- layer_list[ndx].pipe_ndx, ndx, i);
- return -EINVAL;
- }
+ rect_num = layer_list[ndx].rect_num;
+ if (rect_num >= MDSS_MDP_PIPE_MAX_RECTS)
+ return -EINVAL;
+ validate_info_list[ndx].multirect.num = rect_num;
- pr_debug("found matching pair for pipe_ndx=%d (%d %d)\n",
- layer_list[i].pipe_ndx, ndx, i);
+ return 0;
+}
- vinfo[cnt] = &validate_info_list[i];
- vinfo[cnt]->multirect.num = cnt;
- vinfo[cnt]->multirect.next = vinfo[0]->layer;
- vinfo[cnt]->multirect.mode = mode;
- vinfo[cnt]->layer = &layer_list[i];
+static int __update_multirect_info(struct msm_fb_data_type *mfd,
+ struct mdss_mdp_validate_info_t *validate_info_list,
+ struct mdp_input_layer *layer_list,
+ int ndx, size_t layer_cnt, int is_rect_num_valid)
+{
+ int ret;
+ int pair_rect_num = -1;
+ int pair_index;
+
+ if (!is_rect_num_valid)
+ layer_list[ndx].rect_num = MDSS_MDP_PIPE_RECT0;
+
+ ret = __validate_multirect_param(mfd, validate_info_list,
+ layer_list, ndx, layer_cnt);
+ /* return if we hit error or multirectangle mode is disabled. */
+ if (IS_ERR_VALUE(ret) ||
+ (!ret && validate_info_list[ndx].multirect.mode ==
+ MDSS_MDP_PIPE_MULTIRECT_NONE))
+ return ret;
- vinfo[cnt - 1]->multirect.next = vinfo[cnt]->layer;
- cnt++;
- }
- }
+ if (is_rect_num_valid)
+ pair_rect_num = (validate_info_list[ndx].multirect.num ==
+ MDSS_MDP_PIPE_RECT0) ? MDSS_MDP_PIPE_RECT1 :
+ MDSS_MDP_PIPE_RECT0;
- if (cnt == 1) {
- pr_err("multirect mode enabled but unable to find extra rects for pipe_ndx=%x\n",
+ pair_index = find_layer(get_pipe_num_from_ndx(
+ layer_list[ndx].pipe_ndx), pair_rect_num,
+ layer_list, layer_cnt, ndx + 1);
+ if (IS_ERR_VALUE(pair_index)) {
+ pr_err("Multirect pair not found for pipe ndx 0x%x\n",
layer_list[ndx].pipe_ndx);
return -EINVAL;
}
- return cnt;
+ if (!is_rect_num_valid)
+ layer_list[pair_index].rect_num = MDSS_MDP_PIPE_RECT1;
+
+ ret = __validate_multirect_param(mfd, validate_info_list,
+ layer_list, pair_index, layer_cnt);
+ if (IS_ERR_VALUE(ret) ||
+ (validate_info_list[ndx].multirect.mode !=
+ validate_info_list[pair_index].multirect.mode))
+ return -EINVAL;
+
+ validate_info_list[ndx].multirect.next = &layer_list[pair_index];
+ validate_info_list[pair_index].multirect.next = &layer_list[ndx];
+
+ return 0;
}
static int __validate_multirect(struct msm_fb_data_type *mfd,
- struct mdss_mdp_validate_info_t *validate_info_list,
- struct mdp_input_layer *layer_list, int ndx, int layer_cnt)
+ struct mdss_mdp_validate_info_t *validate_info_list,
+ struct mdp_input_layer *layer_list,
+ int ndx, size_t layer_cnt, int is_rect_num_valid)
{
- struct mdp_input_layer *layers[MDSS_MDP_PIPE_MAX_RECTS] = { 0 };
- int i, cnt, rc;
-
- cnt = __update_multirect_info(mfd, validate_info_list,
- layer_list, ndx, layer_cnt);
- if (IS_ERR_VALUE(cnt))
- return cnt;
-
- if (cnt <= 1) {
- /* nothing to validate in single rect mode */
- return 0;
- } else if (cnt > 2) {
- pr_err("unsupported multirect configuration, multirect cnt=%d\n",
- cnt);
- return -EINVAL;
- }
+ int ret;
+ int i;
+ struct mdp_input_layer *layers[MDSS_MDP_PIPE_MAX_RECTS];
+ struct mdp_input_layer *pair_layer;
+
+ ret = __update_multirect_info(mfd, validate_info_list,
+ layer_list, ndx, layer_cnt, is_rect_num_valid);
+ /* return if we hit error or multirectangle mode is disabled. */
+ if (IS_ERR_VALUE(ret) ||
+ (!ret && validate_info_list[ndx].multirect.mode ==
+ MDSS_MDP_PIPE_MULTIRECT_NONE))
+ return ret;
- layers[0] = validate_info_list[ndx].layer;
- layers[1] = validate_info_list[ndx].multirect.next;
+ layers[validate_info_list[ndx].multirect.num] = &layer_list[ndx];
+ pair_layer = validate_info_list[ndx].multirect.next;
+ layers[pair_layer->rect_num] = pair_layer;
+ /* check against smart DMA v1.0 restrictions */
for (i = 0; i < ARRAY_SIZE(__multirect_validators); i++) {
- if (!__multirect_validators[i](layers, cnt))
+ if (!__multirect_validators[i](layers,
+ MDSS_MDP_PIPE_MAX_RECTS))
return -EINVAL;
}
-
- rc = __multirect_validate_mode(mfd, layers, cnt);
- if (IS_ERR_VALUE(rc))
- return rc;
+ ret = __multirect_validate_mode(mfd, layers, MDSS_MDP_PIPE_MAX_RECTS);
+ if (IS_ERR_VALUE(ret))
+ return ret;
return 0;
}
@@ -2416,14 +2458,14 @@ static int __validate_layers(struct msm_fb_data_type *mfd,
if (!validate_info_list[i].layer) {
ret = __validate_multirect(mfd, validate_info_list,
- layer_list, i, layer_count);
+ layer_list, i, layer_count,
+ !!(commit->flags & MDP_COMMIT_RECT_NUM));
if (ret) {
pr_err("error validating multirect config. ret=%d i=%d\n",
ret, i);
goto end;
}
}
-
rect_num = validate_info_list[i].multirect.num;
BUG_ON(rect_num >= MDSS_MDP_PIPE_MAX_RECTS);
@@ -2782,7 +2824,8 @@ int mdss_mdp_layer_pre_commit(struct msm_fb_data_type *mfd,
for (i = 0; i < layer_count; i++) {
if (!validate_info_list[i].layer) {
ret = __update_multirect_info(mfd, validate_info_list,
- layer_list, i, layer_count);
+ layer_list, i, layer_count,
+ !!(commit->flags & MDP_COMMIT_RECT_NUM));
if (IS_ERR_VALUE(ret)) {
pr_err("error updating multirect config. ret=%d i=%d\n",
ret, i);
@@ -3035,6 +3078,12 @@ int mdss_mdp_layer_pre_commit_wfd(struct msm_fb_data_type *mfd,
wfd = mdp5_data->wfd;
output_layer = commit->output_layer;
+ if (output_layer->buffer.plane_count > MAX_PLANES) {
+ pr_err("Output buffer plane_count exceeds MAX_PLANES limit:%d\n",
+ output_layer->buffer.plane_count);
+ return -EINVAL;
+ }
+
data = mdss_mdp_wfd_add_data(wfd, output_layer);
if (IS_ERR_OR_NULL(data))
return PTR_ERR(data);
diff --git a/drivers/video/fbdev/msm/mdss_mdp_overlay.c b/drivers/video/fbdev/msm/mdss_mdp_overlay.c
index 8c612e2b83fb..87fff44af389 100644
--- a/drivers/video/fbdev/msm/mdss_mdp_overlay.c
+++ b/drivers/video/fbdev/msm/mdss_mdp_overlay.c
@@ -3053,6 +3053,13 @@ static void mdss_mdp_overlay_pan_display(struct msm_fb_data_type *mfd)
goto pipe_release;
}
+ if (l_pipe_allocated &&
+ (l_pipe->multirect.num == MDSS_MDP_PIPE_RECT1)) {
+ pr_err("Invalid: L_Pipe-%d is assigned for RECT-%d\n",
+ l_pipe->num, l_pipe->multirect.num);
+ goto pipe_release;
+ }
+
if (mdss_mdp_pipe_map(l_pipe)) {
pr_err("unable to map base pipe\n");
goto pipe_release;
@@ -3100,6 +3107,16 @@ static void mdss_mdp_overlay_pan_display(struct msm_fb_data_type *mfd)
goto iommu_disable;
}
+ if (l_pipe_allocated && r_pipe_allocated &&
+ (l_pipe->num != r_pipe->num) &&
+ (r_pipe->multirect.num ==
+ MDSS_MDP_PIPE_RECT1)) {
+ pr_err("Invalid: L_Pipe-%d,RECT-%d R_Pipe-%d,RECT-%d\n",
+ l_pipe->num, l_pipe->multirect.num,
+ r_pipe->num, l_pipe->multirect.num);
+ goto iommu_disable;
+ }
+
if (mdss_mdp_pipe_map(r_pipe)) {
pr_err("unable to map right base pipe\n");
goto iommu_disable;
diff --git a/drivers/video/fbdev/msm/mdss_mdp_pp.c b/drivers/video/fbdev/msm/mdss_mdp_pp.c
index f128f82fab04..2e85072c4cf7 100644
--- a/drivers/video/fbdev/msm/mdss_mdp_pp.c
+++ b/drivers/video/fbdev/msm/mdss_mdp_pp.c
@@ -2599,6 +2599,7 @@ int mdss_mdp_dest_scaler_setup_locked(struct mdss_mdp_mixer *mixer)
u32 op_mode;
u32 mask;
char *ds_offset;
+ int mixer_num = 0;
if (!mixer || !mixer->ctl || !mixer->ctl->mdata)
return -EINVAL;
@@ -2658,6 +2659,14 @@ int mdss_mdp_dest_scaler_setup_locked(struct mdss_mdp_mixer *mixer)
pr_err("Failed setup destination scaler\n");
return ret;
}
+ /* Set LM Flush in order to update DS registers */
+ if (ds->flags & DS_SCALE_UPDATE) {
+ mutex_lock(&ctl->flush_lock);
+ mixer_num = mdss_mdp_mixer_get_hw_num(mixer);
+ ctl->flush_bits |=
+ BIT(mixer_num < 5 ? 6 + mixer_num : 20);
+ mutex_unlock(&ctl->flush_lock);
+ }
/*
* Clearing the flag because we don't need to program the block
* for each commit if there is no change.
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/drivers/video/fbdev/msm/mdss_mdp_wfd.c b/drivers/video/fbdev/msm/mdss_mdp_wfd.c
index 71a07f6b7d39..7868dc0f1999 100644
--- a/drivers/video/fbdev/msm/mdss_mdp_wfd.c
+++ b/drivers/video/fbdev/msm/mdss_mdp_wfd.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2015-2016, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2015-2017, The Linux Foundation. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 and
@@ -322,6 +322,12 @@ int mdss_mdp_wb_import_data(struct device *device,
if (wfd_data->layer.flags & MDP_LAYER_SECURE_SESSION)
flags = MDP_SECURE_OVERLAY_SESSION;
+ if (buffer->plane_count > MAX_PLANES) {
+ pr_err("buffer plane_count exceeds MAX_PLANES limit:%d",
+ buffer->plane_count);
+ return -EINVAL;
+ }
+
memset(planes, 0, sizeof(planes));
for (i = 0; i < buffer->plane_count; i++) {
diff --git a/drivers/video/fbdev/msm/mdss_rotator.c b/drivers/video/fbdev/msm/mdss_rotator.c
index fdd1c0153ce0..399a12e3dcc8 100644
--- a/drivers/video/fbdev/msm/mdss_rotator.c
+++ b/drivers/video/fbdev/msm/mdss_rotator.c
@@ -501,6 +501,12 @@ static int mdss_rotator_import_buffer(struct mdp_layer_buffer *buffer,
memset(planes, 0, sizeof(planes));
+ if (buffer->plane_count > MAX_PLANES) {
+ pr_err("buffer plane_count exceeds MAX_PLANES limit:%d\n",
+ buffer->plane_count);
+ return -EINVAL;
+ }
+
for (i = 0; i < buffer->plane_count; i++) {
planes[i].memory_id = buffer->planes[i].fd;
planes[i].offset = buffer->planes[i].offset;
@@ -2104,6 +2110,20 @@ struct mdss_rot_entry_container *mdss_rotator_req_init(
struct mdss_rot_entry_container *req;
int size, i;
+ /*
+ * Check input and output plane_count from each given item
+ * are within the MAX_PLANES limit
+ */
+ for (i = 0 ; i < count; i++) {
+ if ((items[i].input.plane_count > MAX_PLANES) ||
+ (items[i].output.plane_count > MAX_PLANES)) {
+ pr_err("Input/Output plane_count exceeds MAX_PLANES limit, input:%d, output:%d\n",
+ items[i].input.plane_count,
+ items[i].output.plane_count);
+ return ERR_PTR(-EINVAL);
+ }
+ }
+
size = sizeof(struct mdss_rot_entry_container);
size += sizeof(struct mdss_rot_entry) * count;
req = devm_kzalloc(&mgr->pdev->dev, size, GFP_KERNEL);
diff --git a/fs/cifs/cifsglob.h b/fs/cifs/cifsglob.h
index 94906aaa9b7c..e2f6a79e9b01 100644
--- a/fs/cifs/cifsglob.h
+++ b/fs/cifs/cifsglob.h
@@ -227,6 +227,7 @@ struct smb_version_operations {
/* verify the message */
int (*check_message)(char *, unsigned int);
bool (*is_oplock_break)(char *, struct TCP_Server_Info *);
+ int (*handle_cancelled_mid)(char *, struct TCP_Server_Info *);
void (*downgrade_oplock)(struct TCP_Server_Info *,
struct cifsInodeInfo *, bool);
/* process transaction2 response */
@@ -1289,12 +1290,19 @@ struct mid_q_entry {
void *callback_data; /* general purpose pointer for callback */
void *resp_buf; /* pointer to received SMB header */
int mid_state; /* wish this were enum but can not pass to wait_event */
+ unsigned int mid_flags;
__le16 command; /* smb command code */
bool large_buf:1; /* if valid response, is pointer to large buf */
bool multiRsp:1; /* multiple trans2 responses for one request */
bool multiEnd:1; /* both received */
};
+struct close_cancelled_open {
+ struct cifs_fid fid;
+ struct cifs_tcon *tcon;
+ struct work_struct work;
+};
+
/* Make code in transport.c a little cleaner by moving
update of optional stats into function below */
#ifdef CONFIG_CIFS_STATS2
@@ -1426,6 +1434,9 @@ static inline void free_dfs_info_array(struct dfs_info3_param *param,
#define MID_RESPONSE_MALFORMED 0x10
#define MID_SHUTDOWN 0x20
+/* Flags */
+#define MID_WAIT_CANCELLED 1 /* Cancelled while waiting for response */
+
/* Types of response buffer returned from SendReceive2 */
#define CIFS_NO_BUFFER 0 /* Response buffer not returned */
#define CIFS_SMALL_BUFFER 1
diff --git a/fs/cifs/cifssmb.c b/fs/cifs/cifssmb.c
index b1104ed8f54c..5e2f8b8ca08a 100644
--- a/fs/cifs/cifssmb.c
+++ b/fs/cifs/cifssmb.c
@@ -1424,6 +1424,8 @@ cifs_readv_discard(struct TCP_Server_Info *server, struct mid_q_entry *mid)
length = discard_remaining_data(server);
dequeue_mid(mid, rdata->result);
+ mid->resp_buf = server->smallbuf;
+ server->smallbuf = NULL;
return length;
}
@@ -1538,6 +1540,8 @@ cifs_readv_receive(struct TCP_Server_Info *server, struct mid_q_entry *mid)
return cifs_readv_discard(server, mid);
dequeue_mid(mid, false);
+ mid->resp_buf = server->smallbuf;
+ server->smallbuf = NULL;
return length;
}
diff --git a/fs/cifs/connect.c b/fs/cifs/connect.c
index 5d59f25521ce..156bc18eac69 100644
--- a/fs/cifs/connect.c
+++ b/fs/cifs/connect.c
@@ -924,10 +924,19 @@ cifs_demultiplex_thread(void *p)
server->lstrp = jiffies;
if (mid_entry != NULL) {
+ if ((mid_entry->mid_flags & MID_WAIT_CANCELLED) &&
+ mid_entry->mid_state == MID_RESPONSE_RECEIVED &&
+ server->ops->handle_cancelled_mid)
+ server->ops->handle_cancelled_mid(
+ mid_entry->resp_buf,
+ server);
+
if (!mid_entry->multiRsp || mid_entry->multiEnd)
mid_entry->callback(mid_entry);
- } else if (!server->ops->is_oplock_break ||
- !server->ops->is_oplock_break(buf, server)) {
+ } else if (server->ops->is_oplock_break &&
+ server->ops->is_oplock_break(buf, server)) {
+ cifs_dbg(FYI, "Received oplock break\n");
+ } else {
cifs_dbg(VFS, "No task to wake, unknown frame received! NumMids %d\n",
atomic_read(&midCount));
cifs_dump_mem("Received Data is: ", buf,
diff --git a/fs/cifs/smb2misc.c b/fs/cifs/smb2misc.c
index e5bc85e49be7..76ccf20fbfb7 100644
--- a/fs/cifs/smb2misc.c
+++ b/fs/cifs/smb2misc.c
@@ -630,3 +630,47 @@ smb2_is_valid_oplock_break(char *buffer, struct TCP_Server_Info *server)
cifs_dbg(FYI, "Can not process oplock break for non-existent connection\n");
return false;
}
+
+void
+smb2_cancelled_close_fid(struct work_struct *work)
+{
+ struct close_cancelled_open *cancelled = container_of(work,
+ struct close_cancelled_open, work);
+
+ cifs_dbg(VFS, "Close unmatched open\n");
+
+ SMB2_close(0, cancelled->tcon, cancelled->fid.persistent_fid,
+ cancelled->fid.volatile_fid);
+ cifs_put_tcon(cancelled->tcon);
+ kfree(cancelled);
+}
+
+int
+smb2_handle_cancelled_mid(char *buffer, struct TCP_Server_Info *server)
+{
+ struct smb2_hdr *hdr = (struct smb2_hdr *)buffer;
+ struct smb2_create_rsp *rsp = (struct smb2_create_rsp *)buffer;
+ struct cifs_tcon *tcon;
+ struct close_cancelled_open *cancelled;
+
+ if (hdr->Command != SMB2_CREATE || hdr->Status != STATUS_SUCCESS)
+ return 0;
+
+ cancelled = kzalloc(sizeof(*cancelled), GFP_KERNEL);
+ if (!cancelled)
+ return -ENOMEM;
+
+ tcon = smb2_find_smb_tcon(server, hdr->SessionId, hdr->TreeId);
+ if (!tcon) {
+ kfree(cancelled);
+ return -ENOENT;
+ }
+
+ cancelled->fid.persistent_fid = rsp->PersistentFileId;
+ cancelled->fid.volatile_fid = rsp->VolatileFileId;
+ cancelled->tcon = tcon;
+ INIT_WORK(&cancelled->work, smb2_cancelled_close_fid);
+ queue_work(cifsiod_wq, &cancelled->work);
+
+ return 0;
+}
diff --git a/fs/cifs/smb2ops.c b/fs/cifs/smb2ops.c
index be34b4860675..087918c4612a 100644
--- a/fs/cifs/smb2ops.c
+++ b/fs/cifs/smb2ops.c
@@ -1511,6 +1511,7 @@ struct smb_version_operations smb20_operations = {
.clear_stats = smb2_clear_stats,
.print_stats = smb2_print_stats,
.is_oplock_break = smb2_is_valid_oplock_break,
+ .handle_cancelled_mid = smb2_handle_cancelled_mid,
.downgrade_oplock = smb2_downgrade_oplock,
.need_neg = smb2_need_neg,
.negotiate = smb2_negotiate,
@@ -1589,6 +1590,7 @@ struct smb_version_operations smb21_operations = {
.clear_stats = smb2_clear_stats,
.print_stats = smb2_print_stats,
.is_oplock_break = smb2_is_valid_oplock_break,
+ .handle_cancelled_mid = smb2_handle_cancelled_mid,
.downgrade_oplock = smb2_downgrade_oplock,
.need_neg = smb2_need_neg,
.negotiate = smb2_negotiate,
@@ -1670,6 +1672,7 @@ struct smb_version_operations smb30_operations = {
.print_stats = smb2_print_stats,
.dump_share_caps = smb2_dump_share_caps,
.is_oplock_break = smb2_is_valid_oplock_break,
+ .handle_cancelled_mid = smb2_handle_cancelled_mid,
.downgrade_oplock = smb2_downgrade_oplock,
.need_neg = smb2_need_neg,
.negotiate = smb2_negotiate,
@@ -1757,6 +1760,7 @@ struct smb_version_operations smb311_operations = {
.print_stats = smb2_print_stats,
.dump_share_caps = smb2_dump_share_caps,
.is_oplock_break = smb2_is_valid_oplock_break,
+ .handle_cancelled_mid = smb2_handle_cancelled_mid,
.downgrade_oplock = smb2_downgrade_oplock,
.need_neg = smb2_need_neg,
.negotiate = smb2_negotiate,
diff --git a/fs/cifs/smb2proto.h b/fs/cifs/smb2proto.h
index 0a406ae78129..adc5234486c3 100644
--- a/fs/cifs/smb2proto.h
+++ b/fs/cifs/smb2proto.h
@@ -47,6 +47,10 @@ extern struct mid_q_entry *smb2_setup_request(struct cifs_ses *ses,
struct smb_rqst *rqst);
extern struct mid_q_entry *smb2_setup_async_request(
struct TCP_Server_Info *server, struct smb_rqst *rqst);
+extern struct cifs_ses *smb2_find_smb_ses(struct TCP_Server_Info *server,
+ __u64 ses_id);
+extern struct cifs_tcon *smb2_find_smb_tcon(struct TCP_Server_Info *server,
+ __u64 ses_id, __u32 tid);
extern int smb2_calc_signature(struct smb_rqst *rqst,
struct TCP_Server_Info *server);
extern int smb3_calc_signature(struct smb_rqst *rqst,
@@ -157,6 +161,9 @@ extern int SMB2_set_compression(const unsigned int xid, struct cifs_tcon *tcon,
extern int SMB2_oplock_break(const unsigned int xid, struct cifs_tcon *tcon,
const u64 persistent_fid, const u64 volatile_fid,
const __u8 oplock_level);
+extern int smb2_handle_cancelled_mid(char *buffer,
+ struct TCP_Server_Info *server);
+void smb2_cancelled_close_fid(struct work_struct *work);
extern int SMB2_QFS_info(const unsigned int xid, struct cifs_tcon *tcon,
u64 persistent_file_id, u64 volatile_file_id,
struct kstatfs *FSData);
diff --git a/fs/cifs/smb2transport.c b/fs/cifs/smb2transport.c
index d4c5b6f109a7..69e3b322bbfe 100644
--- a/fs/cifs/smb2transport.c
+++ b/fs/cifs/smb2transport.c
@@ -115,22 +115,68 @@ smb3_crypto_shash_allocate(struct TCP_Server_Info *server)
}
static struct cifs_ses *
-smb2_find_smb_ses(struct smb2_hdr *smb2hdr, struct TCP_Server_Info *server)
+smb2_find_smb_ses_unlocked(struct TCP_Server_Info *server, __u64 ses_id)
{
struct cifs_ses *ses;
- spin_lock(&cifs_tcp_ses_lock);
list_for_each_entry(ses, &server->smb_ses_list, smb_ses_list) {
- if (ses->Suid != smb2hdr->SessionId)
+ if (ses->Suid != ses_id)
continue;
- spin_unlock(&cifs_tcp_ses_lock);
return ses;
}
+
+ return NULL;
+}
+
+struct cifs_ses *
+smb2_find_smb_ses(struct TCP_Server_Info *server, __u64 ses_id)
+{
+ struct cifs_ses *ses;
+
+ spin_lock(&cifs_tcp_ses_lock);
+ ses = smb2_find_smb_ses_unlocked(server, ses_id);
spin_unlock(&cifs_tcp_ses_lock);
+ return ses;
+}
+
+static struct cifs_tcon *
+smb2_find_smb_sess_tcon_unlocked(struct cifs_ses *ses, __u32 tid)
+{
+ struct cifs_tcon *tcon;
+
+ list_for_each_entry(tcon, &ses->tcon_list, tcon_list) {
+ if (tcon->tid != tid)
+ continue;
+ ++tcon->tc_count;
+ return tcon;
+ }
+
return NULL;
}
+/*
+ * Obtain tcon corresponding to the tid in the given
+ * cifs_ses
+ */
+
+struct cifs_tcon *
+smb2_find_smb_tcon(struct TCP_Server_Info *server, __u64 ses_id, __u32 tid)
+{
+ struct cifs_ses *ses;
+ struct cifs_tcon *tcon;
+
+ spin_lock(&cifs_tcp_ses_lock);
+ ses = smb2_find_smb_ses_unlocked(server, ses_id);
+ if (!ses) {
+ spin_unlock(&cifs_tcp_ses_lock);
+ return NULL;
+ }
+ tcon = smb2_find_smb_sess_tcon_unlocked(ses, tid);
+ spin_unlock(&cifs_tcp_ses_lock);
+
+ return tcon;
+}
int
smb2_calc_signature(struct smb_rqst *rqst, struct TCP_Server_Info *server)
@@ -143,7 +189,7 @@ smb2_calc_signature(struct smb_rqst *rqst, struct TCP_Server_Info *server)
struct smb2_hdr *smb2_pdu = (struct smb2_hdr *)iov[0].iov_base;
struct cifs_ses *ses;
- ses = smb2_find_smb_ses(smb2_pdu, server);
+ ses = smb2_find_smb_ses(server, smb2_pdu->SessionId);
if (!ses) {
cifs_dbg(VFS, "%s: Could not find session\n", __func__);
return 0;
@@ -314,7 +360,7 @@ smb3_calc_signature(struct smb_rqst *rqst, struct TCP_Server_Info *server)
struct smb2_hdr *smb2_pdu = (struct smb2_hdr *)iov[0].iov_base;
struct cifs_ses *ses;
- ses = smb2_find_smb_ses(smb2_pdu, server);
+ ses = smb2_find_smb_ses(server, smb2_pdu->SessionId);
if (!ses) {
cifs_dbg(VFS, "%s: Could not find session\n", __func__);
return 0;
diff --git a/fs/cifs/transport.c b/fs/cifs/transport.c
index 87abe8ed074c..54af10204e83 100644
--- a/fs/cifs/transport.c
+++ b/fs/cifs/transport.c
@@ -786,9 +786,11 @@ SendReceive2(const unsigned int xid, struct cifs_ses *ses,
rc = wait_for_response(ses->server, midQ);
if (rc != 0) {
+ cifs_dbg(FYI, "Cancelling wait for mid %llu\n", midQ->mid);
send_cancel(ses->server, buf, midQ);
spin_lock(&GlobalMid_Lock);
if (midQ->mid_state == MID_REQUEST_SUBMITTED) {
+ midQ->mid_flags |= MID_WAIT_CANCELLED;
midQ->callback = DeleteMidQEntry;
spin_unlock(&GlobalMid_Lock);
cifs_small_buf_release(buf);
diff --git a/fs/ext4/crypto.c b/fs/ext4/crypto.c
index 664f42c850b7..e14b1b8fceb0 100644
--- a/fs/ext4/crypto.c
+++ b/fs/ext4/crypto.c
@@ -497,11 +497,6 @@ static int ext4_d_revalidate(struct dentry *dentry, unsigned int flags)
return 0;
}
ci = EXT4_I(d_inode(dir))->i_crypt_info;
- if (ci && ci->ci_keyring_key &&
- (ci->ci_keyring_key->flags & ((1 << KEY_FLAG_INVALIDATED) |
- (1 << KEY_FLAG_REVOKED) |
- (1 << KEY_FLAG_DEAD))))
- ci = NULL;
/* this should eventually be an flag in d_flags */
cached_with_key = dentry->d_fsdata != NULL;
diff --git a/fs/ext4/ioctl.c b/fs/ext4/ioctl.c
index 3a2594665b44..c21826be1cb3 100644
--- a/fs/ext4/ioctl.c
+++ b/fs/ext4/ioctl.c
@@ -626,6 +626,9 @@ resizefs_out:
struct ext4_encryption_policy policy;
int err = 0;
+ if (!ext4_has_feature_encrypt(sb))
+ return -EOPNOTSUPP;
+
if (copy_from_user(&policy,
(struct ext4_encryption_policy __user *)arg,
sizeof(policy))) {
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/mbcache.c b/fs/mbcache.c
index 187477ded6b3..ab1da987d1ae 100644
--- a/fs/mbcache.c
+++ b/fs/mbcache.c
@@ -262,7 +262,6 @@ mb_cache_shrink_scan(struct shrinker *shrink, struct shrink_control *sc)
list_del_init(&ce->e_lru_list);
if (ce->e_used || ce->e_queued || atomic_read(&ce->e_refcnt))
continue;
- spin_unlock(&mb_cache_spinlock);
/* Prevent any find or get operation on the entry */
hlist_bl_lock(ce->e_block_hash_p);
hlist_bl_lock(ce->e_index_hash_p);
@@ -271,10 +270,10 @@ mb_cache_shrink_scan(struct shrinker *shrink, struct shrink_control *sc)
!list_empty(&ce->e_lru_list)) {
hlist_bl_unlock(ce->e_index_hash_p);
hlist_bl_unlock(ce->e_block_hash_p);
- spin_lock(&mb_cache_spinlock);
continue;
}
__mb_cache_entry_unhash_unlock(ce);
+ spin_unlock(&mb_cache_spinlock);
list_add_tail(&ce->e_lru_list, &free_list);
spin_lock(&mb_cache_spinlock);
}
@@ -516,7 +515,6 @@ mb_cache_entry_alloc(struct mb_cache *cache, gfp_t gfp_flags)
if (ce->e_used || ce->e_queued ||
atomic_read(&ce->e_refcnt))
continue;
- spin_unlock(&mb_cache_spinlock);
/*
* Prevent any find or get operation on the
* entry.
@@ -530,13 +528,13 @@ mb_cache_entry_alloc(struct mb_cache *cache, gfp_t gfp_flags)
hlist_bl_unlock(ce->e_index_hash_p);
hlist_bl_unlock(ce->e_block_hash_p);
l = &mb_cache_lru_list;
- spin_lock(&mb_cache_spinlock);
continue;
}
mb_assert(list_empty(&ce->e_lru_list));
mb_assert(!(ce->e_used || ce->e_queued ||
atomic_read(&ce->e_refcnt)));
__mb_cache_entry_unhash_unlock(ce);
+ spin_unlock(&mb_cache_spinlock);
goto found;
}
}
@@ -670,6 +668,7 @@ mb_cache_entry_get(struct mb_cache *cache, struct block_device *bdev,
cache->c_bucket_bits);
block_hash_p = &cache->c_block_hash[bucket];
/* First serialize access to the block corresponding hash chain. */
+ spin_lock(&mb_cache_spinlock);
hlist_bl_lock(block_hash_p);
hlist_bl_for_each_entry(ce, l, block_hash_p, e_block_list) {
mb_assert(ce->e_block_hash_p == block_hash_p);
@@ -678,9 +677,11 @@ mb_cache_entry_get(struct mb_cache *cache, struct block_device *bdev,
* Prevent a free from removing the entry.
*/
atomic_inc(&ce->e_refcnt);
+ if (!list_empty(&ce->e_lru_list))
+ list_del_init(&ce->e_lru_list);
hlist_bl_unlock(block_hash_p);
+ spin_unlock(&mb_cache_spinlock);
__spin_lock_mb_cache_entry(ce);
- atomic_dec(&ce->e_refcnt);
if (ce->e_used > 0) {
DEFINE_WAIT(wait);
while (ce->e_used > 0) {
@@ -695,13 +696,9 @@ mb_cache_entry_get(struct mb_cache *cache, struct block_device *bdev,
finish_wait(&mb_cache_queue, &wait);
}
ce->e_used += 1 + MB_CACHE_WRITER;
+ atomic_dec(&ce->e_refcnt);
__spin_unlock_mb_cache_entry(ce);
- if (!list_empty(&ce->e_lru_list)) {
- spin_lock(&mb_cache_spinlock);
- list_del_init(&ce->e_lru_list);
- spin_unlock(&mb_cache_spinlock);
- }
if (!__mb_cache_entry_is_block_hashed(ce)) {
__mb_cache_entry_release(ce);
return NULL;
@@ -710,6 +707,7 @@ mb_cache_entry_get(struct mb_cache *cache, struct block_device *bdev,
}
}
hlist_bl_unlock(block_hash_p);
+ spin_unlock(&mb_cache_spinlock);
return NULL;
}
diff --git a/fs/nfsd/nfs3xdr.c b/fs/nfsd/nfs3xdr.c
index 00575d776d91..7162ab7bc093 100644
--- a/fs/nfsd/nfs3xdr.c
+++ b/fs/nfsd/nfs3xdr.c
@@ -358,6 +358,7 @@ nfs3svc_decode_writeargs(struct svc_rqst *rqstp, __be32 *p,
{
unsigned int len, v, hdr, dlen;
u32 max_blocksize = svc_max_payload(rqstp);
+ struct kvec *head = rqstp->rq_arg.head;
p = decode_fh(p, &args->fh);
if (!p)
@@ -367,6 +368,8 @@ nfs3svc_decode_writeargs(struct svc_rqst *rqstp, __be32 *p,
args->count = ntohl(*p++);
args->stable = ntohl(*p++);
len = args->len = ntohl(*p++);
+ if ((void *)p > head->iov_base + head->iov_len)
+ return 0;
/*
* The count must equal the amount of data passed.
*/
@@ -377,9 +380,8 @@ nfs3svc_decode_writeargs(struct svc_rqst *rqstp, __be32 *p,
* Check to make sure that we got the right number of
* bytes.
*/
- hdr = (void*)p - rqstp->rq_arg.head[0].iov_base;
- dlen = rqstp->rq_arg.head[0].iov_len + rqstp->rq_arg.page_len
- - hdr;
+ hdr = (void*)p - head->iov_base;
+ dlen = head->iov_len + rqstp->rq_arg.page_len - hdr;
/*
* Round the length of the data which was specified up to
* the next multiple of XDR units and then compare that
@@ -396,7 +398,7 @@ nfs3svc_decode_writeargs(struct svc_rqst *rqstp, __be32 *p,
len = args->len = max_blocksize;
}
rqstp->rq_vec[0].iov_base = (void*)p;
- rqstp->rq_vec[0].iov_len = rqstp->rq_arg.head[0].iov_len - hdr;
+ rqstp->rq_vec[0].iov_len = head->iov_len - hdr;
v = 0;
while (len > rqstp->rq_vec[v].iov_len) {
len -= rqstp->rq_vec[v].iov_len;
@@ -471,6 +473,8 @@ nfs3svc_decode_symlinkargs(struct svc_rqst *rqstp, __be32 *p,
/* first copy and check from the first page */
old = (char*)p;
vec = &rqstp->rq_arg.head[0];
+ if ((void *)old > vec->iov_base + vec->iov_len)
+ return 0;
avail = vec->iov_len - (old - (char*)vec->iov_base);
while (len && avail && *old) {
*new++ = *old++;
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/fs/nfsd/nfsxdr.c b/fs/nfsd/nfsxdr.c
index 79d964aa8079..bf913201a6ad 100644
--- a/fs/nfsd/nfsxdr.c
+++ b/fs/nfsd/nfsxdr.c
@@ -280,6 +280,7 @@ nfssvc_decode_writeargs(struct svc_rqst *rqstp, __be32 *p,
struct nfsd_writeargs *args)
{
unsigned int len, hdr, dlen;
+ struct kvec *head = rqstp->rq_arg.head;
int v;
p = decode_fh(p, &args->fh);
@@ -300,9 +301,10 @@ nfssvc_decode_writeargs(struct svc_rqst *rqstp, __be32 *p,
* Check to make sure that we got the right number of
* bytes.
*/
- hdr = (void*)p - rqstp->rq_arg.head[0].iov_base;
- dlen = rqstp->rq_arg.head[0].iov_len + rqstp->rq_arg.page_len
- - hdr;
+ hdr = (void*)p - head->iov_base;
+ if (hdr > head->iov_len)
+ return 0;
+ dlen = head->iov_len + rqstp->rq_arg.page_len - hdr;
/*
* Round the length of the data which was specified up to
@@ -316,7 +318,7 @@ nfssvc_decode_writeargs(struct svc_rqst *rqstp, __be32 *p,
return 0;
rqstp->rq_vec[0].iov_base = (void*)p;
- rqstp->rq_vec[0].iov_len = rqstp->rq_arg.head[0].iov_len - hdr;
+ rqstp->rq_vec[0].iov_len = head->iov_len - hdr;
v = 0;
while (len > rqstp->rq_vec[v].iov_len) {
len -= rqstp->rq_vec[v].iov_len;
diff --git a/fs/timerfd.c b/fs/timerfd.c
index 815e5348f048..0548c572839c 100644
--- a/fs/timerfd.c
+++ b/fs/timerfd.c
@@ -40,6 +40,7 @@ struct timerfd_ctx {
short unsigned settime_flags; /* to show in fdinfo */
struct rcu_head rcu;
struct list_head clist;
+ spinlock_t cancel_lock;
bool might_cancel;
};
@@ -113,7 +114,7 @@ void timerfd_clock_was_set(void)
rcu_read_unlock();
}
-static void timerfd_remove_cancel(struct timerfd_ctx *ctx)
+static void __timerfd_remove_cancel(struct timerfd_ctx *ctx)
{
if (ctx->might_cancel) {
ctx->might_cancel = false;
@@ -123,6 +124,13 @@ static void timerfd_remove_cancel(struct timerfd_ctx *ctx)
}
}
+static void timerfd_remove_cancel(struct timerfd_ctx *ctx)
+{
+ spin_lock(&ctx->cancel_lock);
+ __timerfd_remove_cancel(ctx);
+ spin_unlock(&ctx->cancel_lock);
+}
+
static bool timerfd_canceled(struct timerfd_ctx *ctx)
{
if (!ctx->might_cancel || ctx->moffs.tv64 != KTIME_MAX)
@@ -133,6 +141,7 @@ static bool timerfd_canceled(struct timerfd_ctx *ctx)
static void timerfd_setup_cancel(struct timerfd_ctx *ctx, int flags)
{
+ spin_lock(&ctx->cancel_lock);
if ((ctx->clockid == CLOCK_REALTIME ||
ctx->clockid == CLOCK_REALTIME_ALARM ||
ctx->clockid == CLOCK_POWEROFF_ALARM) &&
@@ -143,9 +152,10 @@ static void timerfd_setup_cancel(struct timerfd_ctx *ctx, int flags)
list_add_rcu(&ctx->clist, &cancel_list);
spin_unlock(&cancel_lock);
}
- } else if (ctx->might_cancel) {
- timerfd_remove_cancel(ctx);
+ } else {
+ __timerfd_remove_cancel(ctx);
}
+ spin_unlock(&ctx->cancel_lock);
}
static ktime_t timerfd_get_remaining(struct timerfd_ctx *ctx)
@@ -398,6 +408,7 @@ SYSCALL_DEFINE2(timerfd_create, int, clockid, int, flags)
return -ENOMEM;
init_waitqueue_head(&ctx->wqh);
+ spin_lock_init(&ctx->cancel_lock);
ctx->clockid = clockid;
if (isalarm(ctx)) {
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/linux/mtd/map.h b/include/linux/mtd/map.h
index 366cf77953b5..806d0ab845e0 100644
--- a/include/linux/mtd/map.h
+++ b/include/linux/mtd/map.h
@@ -122,18 +122,13 @@
#endif
#ifdef CONFIG_MTD_MAP_BANK_WIDTH_32
-# ifdef map_bankwidth
-# undef map_bankwidth
-# define map_bankwidth(map) ((map)->bankwidth)
-# undef map_bankwidth_is_large
-# define map_bankwidth_is_large(map) (map_bankwidth(map) > BITS_PER_LONG/8)
-# undef map_words
-# define map_words(map) map_calc_words(map)
-# else
-# define map_bankwidth(map) 32
-# define map_bankwidth_is_large(map) (1)
-# define map_words(map) map_calc_words(map)
-# endif
+/* always use indirect access for 256-bit to preserve kernel stack */
+# undef map_bankwidth
+# define map_bankwidth(map) ((map)->bankwidth)
+# undef map_bankwidth_is_large
+# define map_bankwidth_is_large(map) (map_bankwidth(map) > BITS_PER_LONG/8)
+# undef map_words
+# define map_words(map) map_calc_words(map)
#define map_bankwidth_is_32(map) (map_bankwidth(map) == 32)
#undef MAX_MAP_BANKWIDTH
#define MAX_MAP_BANKWIDTH 32
diff --git a/include/soc/qcom/msm_qmi_interface.h b/include/soc/qcom/msm_qmi_interface.h
index 5ca808dd1fc2..38f390ee71b7 100644
--- a/include/soc/qcom/msm_qmi_interface.h
+++ b/include/soc/qcom/msm_qmi_interface.h
@@ -92,7 +92,6 @@ enum qmi_result_type_v01 {
QMI_RESULT_TYPE_MIN_ENUM_VAL_V01 = INT_MIN,
QMI_RESULT_SUCCESS_V01 = 0,
QMI_RESULT_FAILURE_V01 = 1,
- QMI_ERR_DISABLED_V01 = 0x45,
QMI_RESULT_TYPE_MAX_ENUM_VAL_V01 = INT_MAX,
};
@@ -106,6 +105,7 @@ enum qmi_error_type_v01 {
QMI_ERR_CLIENT_IDS_EXHAUSTED_V01 = 0x0005,
QMI_ERR_INVALID_ID_V01 = 0x0029,
QMI_ERR_ENCODING_V01 = 0x003A,
+ QMI_ERR_DISABLED_V01 = 0x0045,
QMI_ERR_INCOMPATIBLE_STATE_V01 = 0x005A,
QMI_ERR_NOT_SUPPORTED_V01 = 0x005E,
QMI_ERR_TYPE_MAX_ENUM_VAL_V01 = INT_MAX,
diff --git a/include/sound/apr_audio-v2.h b/include/sound/apr_audio-v2.h
index bcb53faaf678..084232a1d06e 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
@@ -6321,6 +6334,62 @@ struct asm_stream_cmd_get_pp_params_v2 {
#define ASM_STREAM_CMD_SET_ENCDEC_PARAM 0x00010C10
+#define ASM_STREAM_CMD_SET_ENCDEC_PARAM_V2 0x00013218
+
+struct asm_stream_cmd_set_encdec_param_v2 {
+ u16 service_id;
+ /* 0 - ASM_ENCODER_SVC; 1 - ASM_DECODER_SVC */
+
+ u16 reserved;
+
+ u32 param_id;
+ /* ID of the parameter. */
+
+ u32 param_size;
+ /*
+ * Data size of this parameter, in bytes. The size is a multiple
+ * of 4 bytes.
+ */
+} __packed;
+
+#define ASM_STREAM_CMD_REGISTER_ENCDEC_EVENTS 0x00013219
+
+#define ASM_STREAM_CMD_ENCDEC_EVENTS 0x0001321A
+
+#define AVS_PARAM_ID_RTIC_SHARED_MEMORY_ADDR 0x00013237
+
+struct avs_rtic_shared_mem_addr {
+ struct apr_hdr hdr;
+ struct asm_stream_cmd_set_encdec_param_v2 encdec;
+ u32 shm_buf_addr_lsw;
+ /* Lower 32 bit of the RTIC shared memory */
+
+ u32 shm_buf_addr_msw;
+ /* Upper 32 bit of the RTIC shared memory */
+
+ u32 buf_size;
+ /* Size of buffer */
+
+ u16 shm_buf_mem_pool_id;
+ /* ADSP_MEMORY_MAP_SHMEM8_4K_POOL */
+
+ u16 shm_buf_num_regions;
+ /* number of regions to map */
+
+ u32 shm_buf_flag;
+ /* buffer property flag */
+
+ struct avs_shared_map_region_payload map_region;
+ /* memory map region*/
+} __packed;
+
+#define AVS_PARAM_ID_RTIC_EVENT_ACK 0x00013238
+
+struct avs_param_rtic_event_ack {
+ struct apr_hdr hdr;
+ struct asm_stream_cmd_set_encdec_param_v2 encdec;
+} __packed;
+
#define ASM_PARAM_ID_ENCDEC_BITRATE 0x00010C13
struct asm_bitrate_param {
@@ -10320,10 +10389,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..42dd677610d9 100644
--- a/include/sound/q6asm-v2.h
+++ b/include/sound/q6asm-v2.h
@@ -619,8 +619,13 @@ int q6asm_get_session_time_legacy(struct audio_client *ac, uint64_t *tstamp);
int q6asm_send_audio_effects_params(struct audio_client *ac, char *params,
uint32_t params_length);
-int q6asm_send_stream_cmd(struct audio_client *ac, uint32_t opcode,
- void *param, uint32_t params_length);
+int q6asm_send_stream_cmd(struct audio_client *ac,
+ struct msm_adsp_event_data *data);
+
+int q6asm_send_ion_fd(struct audio_client *ac, int fd);
+
+int q6asm_send_rtic_event_ack(struct audio_client *ac,
+ void *param, uint32_t params_length);
/* Client can set the IO mode to either AIO/SIO mode */
int q6asm_set_io_mode(struct audio_client *ac, uint32_t mode);
@@ -655,6 +660,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 +671,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..48c49741d77f 100644
--- a/include/uapi/drm/msm_drm.h
+++ b/include/uapi/drm/msm_drm.h
@@ -22,6 +22,10 @@
#include <drm/drm.h>
#include <drm/sde_drm.h>
+#if defined(__cplusplus)
+extern "C" {
+#endif
+
/* Please note that modifications to all structs defined here are
* subject to backwards-compatibility constraints:
* 1) Do not use pointers, use __u64 instead for 32 bit / 64 bit
@@ -78,6 +82,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 +91,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)
@@ -139,7 +145,11 @@ struct drm_msm_gem_cpu_fini {
*/
struct drm_msm_gem_submit_reloc {
__u32 submit_offset; /* in, offset from submit_bo */
- __u32 or; /* in, value OR'd with result */
+#ifdef __cplusplus
+ __u32 or_val;
+#else
+ __u32 or; /* in, value OR'd with result */
+#endif
__s32 shift; /* in, amount of left shift (can be negative) */
__u32 reloc_idx; /* in, index of reloc_bo buffer */
__u64 reloc_offset; /* in, offset from start of reloc_bo */
@@ -385,4 +395,9 @@ struct drm_msm_gem_sync {
struct drm_msm_counter_read)
#define DRM_IOCTL_MSM_GEM_SYNC DRM_IOW(DRM_COMMAND_BASE + DRM_MSM_GEM_SYNC,\
struct drm_msm_gem_sync)
+
+#if defined(__cplusplus)
+}
+#endif
+
#endif /* __MSM_DRM_H__ */
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/msm_mdp_ext.h b/include/uapi/linux/msm_mdp_ext.h
index 35029f227f8b..da9ee3bcc525 100644
--- a/include/uapi/linux/msm_mdp_ext.h
+++ b/include/uapi/linux/msm_mdp_ext.h
@@ -178,6 +178,12 @@ VALIDATE/COMMIT FLAG CONFIGURATION
*/
#define MDP_COMMIT_CWB_DSPP 0x1000
+/*
+ * Flag to indicate that rectangle number is being assigned
+ * by userspace in multi-rectangle mode
+ */
+#define MDP_COMMIT_RECT_NUM 0x2000
+
#define MDP_COMMIT_VERSION_1_0 0x00010000
#define OUT_LAYER_COLOR_SPACE
@@ -425,8 +431,14 @@ struct mdp_input_layer {
*/
int error_code;
+ /*
+ * For source pipes supporting multi-rectangle, this field identifies
+ * the rectangle index of the source pipe.
+ */
+ uint32_t rect_num;
+
/* 32bits reserved value for future usage. */
- uint32_t reserved[6];
+ uint32_t reserved[5];
};
struct mdp_output_layer {
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/kernel/time/timer.c b/kernel/time/timer.c
index 8315d4d72cc3..75ce9cbc313d 100644
--- a/kernel/time/timer.c
+++ b/kernel/time/timer.c
@@ -151,10 +151,11 @@ static inline struct tvec_base *get_target_base(struct tvec_base *base,
static inline void __run_deferrable_timers(void)
{
- if (time_after_eq(jiffies, tvec_base_deferrable.timer_jiffies)) {
- if ((atomic_cmpxchg(&deferrable_pending, 1, 0) &&
- tick_do_timer_cpu == TICK_DO_TIMER_NONE) ||
- tick_do_timer_cpu == smp_processor_id())
+ if ((atomic_cmpxchg(&deferrable_pending, 1, 0) &&
+ tick_do_timer_cpu == TICK_DO_TIMER_NONE) ||
+ tick_do_timer_cpu == smp_processor_id()) {
+ if (time_after_eq(jiffies,
+ tvec_base_deferrable.timer_jiffies))
__run_timers(&tvec_base_deferrable);
}
}
diff --git a/kernel/trace/trace_printk.c b/kernel/trace/trace_printk.c
index ad1d6164e946..e82cff5c842c 100644
--- a/kernel/trace/trace_printk.c
+++ b/kernel/trace/trace_printk.c
@@ -304,7 +304,7 @@ static int t_show(struct seq_file *m, void *v)
if (!*fmt)
return 0;
- seq_printf(m, "0x%lx : \"", *(unsigned long *)fmt);
+ seq_printf(m, "0x%lx : \"", 0L);
/*
* Tabs and new lines need to be converted.
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/netlink/af_netlink.c b/net/netlink/af_netlink.c
index 96fe1c103bf9..2141d047301d 100644
--- a/net/netlink/af_netlink.c
+++ b/net/netlink/af_netlink.c
@@ -2087,7 +2087,7 @@ static int netlink_dump(struct sock *sk)
if (!skb) {
alloc_size = alloc_min_size;
skb = netlink_alloc_skb(sk, alloc_size, nlk->portid,
- (GFP_KERNEL & ~__GFP_DIRECT_RECLAIM));
+ GFP_KERNEL);
}
if (!skb)
goto errout_skb;
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 55087dc93424..c8c4f547b4f1 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)
@@ -831,9 +817,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)
@@ -863,7 +848,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)
@@ -880,7 +865,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)
@@ -896,17 +881,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)
@@ -993,7 +976,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)
@@ -1020,7 +1003,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)
@@ -1030,7 +1012,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)
@@ -1052,7 +1033,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)
@@ -1071,7 +1051,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)
@@ -1088,7 +1068,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)
@@ -1101,9 +1081,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)
@@ -1143,9 +1122,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)
@@ -1166,7 +1144,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)
@@ -1203,7 +1181,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)
@@ -1218,7 +1196,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)
@@ -1247,7 +1224,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
@@ -1257,14 +1234,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)
@@ -1296,7 +1272,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)
@@ -1304,9 +1280,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)
@@ -1323,7 +1298,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)
@@ -1340,7 +1315,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)
@@ -1388,7 +1363,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)
@@ -1408,7 +1382,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)
@@ -1418,7 +1391,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)
@@ -1477,7 +1449,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)
@@ -1511,7 +1482,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)
@@ -1556,7 +1526,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/ppc/awacs.c b/sound/ppc/awacs.c
index 09da7b52bc2e..1468e4b7bf93 100644
--- a/sound/ppc/awacs.c
+++ b/sound/ppc/awacs.c
@@ -991,6 +991,7 @@ snd_pmac_awacs_init(struct snd_pmac *chip)
if (err < 0)
return err;
}
+ master_vol = NULL;
if (pm7500)
err = build_mixers(chip,
ARRAY_SIZE(snd_pmac_awacs_mixers_pmac7500),
diff --git a/sound/soc/codecs/Kconfig b/sound/soc/codecs/Kconfig
index 566bcb04ea51..8f3e787501f1 100644
--- a/sound/soc/codecs/Kconfig
+++ b/sound/soc/codecs/Kconfig
@@ -775,7 +775,7 @@ config SND_SOC_WCD_DSP_MGR
tristate
config SND_SOC_WCD_SPI
- depends on CONFIG_SPI
+ depends on SPI
tristate
config SND_SOC_WL1273
diff --git a/sound/soc/codecs/sdm660_cdc/msm-digital-cdc.c b/sound/soc/codecs/sdm660_cdc/msm-digital-cdc.c
index c6074570bb50..6c702c8fc35f 100644
--- a/sound/soc/codecs/sdm660_cdc/msm-digital-cdc.c
+++ b/sound/soc/codecs/sdm660_cdc/msm-digital-cdc.c
@@ -30,6 +30,7 @@
#include "msm-digital-cdc.h"
#include "msm-cdc-common.h"
#include "../../msm/sdm660-common.h"
+#include "../../../../drivers/base/regmap/internal.h"
#define DRV_NAME "msm_digital_codec"
#define MCLK_RATE_9P6MHZ 9600000
@@ -71,6 +72,8 @@ static int msm_digcdc_clock_control(bool flag)
{
int ret = -EINVAL;
struct msm_asoc_mach_data *pdata = NULL;
+ struct msm_dig_priv *msm_dig_cdc =
+ snd_soc_codec_get_drvdata(registered_digcodec);
pdata = snd_soc_card_get_drvdata(registered_digcodec->component.card);
@@ -84,6 +87,12 @@ static int msm_digcdc_clock_control(bool flag)
if (ret < 0) {
pr_err("%s:failed to enable the MCLK\n",
__func__);
+ /*
+ * Avoid access to lpass register
+ * as clock enable failed during SSR.
+ */
+ if (ret == -ENODEV)
+ msm_dig_cdc->regmap->cache_only = true;
mutex_unlock(&pdata->cdc_int_mclk0_mutex);
return ret;
}
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/intel/boards/bytcr_rt5640.c b/sound/soc/intel/boards/bytcr_rt5640.c
index 7a5c9a36c1db..daba8c56b43b 100644
--- a/sound/soc/intel/boards/bytcr_rt5640.c
+++ b/sound/soc/intel/boards/bytcr_rt5640.c
@@ -139,7 +139,7 @@ static struct snd_soc_dai_link byt_dailink[] = {
.codec_dai_name = "snd-soc-dummy-dai",
.codec_name = "snd-soc-dummy",
.platform_name = "sst-mfld-platform",
- .ignore_suspend = 1,
+ .nonatomic = true,
.dynamic = 1,
.dpcm_playback = 1,
.dpcm_capture = 1,
@@ -166,6 +166,7 @@ static struct snd_soc_dai_link byt_dailink[] = {
| SND_SOC_DAIFMT_CBS_CFS,
.be_hw_params_fixup = byt_codec_fixup,
.ignore_suspend = 1,
+ .nonatomic = true,
.dpcm_playback = 1,
.dpcm_capture = 1,
.ops = &byt_be_ssp2_ops,
diff --git a/sound/soc/msm/qdsp6v2/Makefile b/sound/soc/msm/qdsp6v2/Makefile
index 24672f4da788..219892a85da2 100644
--- a/sound/soc/msm/qdsp6v2/Makefile
+++ b/sound/soc/msm/qdsp6v2/Makefile
@@ -1,5 +1,5 @@
snd-soc-qdsp6v2-objs += msm-dai-q6-v2.o msm-pcm-q6-v2.o msm-pcm-routing-v2.o \
- msm-compress-q6-v2.o msm-compr-q6-v2.o \
+ msm-compress-q6-v2.o \
msm-pcm-afe-v2.o msm-pcm-voip-v2.o \
msm-pcm-voice-v2.o msm-dai-q6-hdmi-v2.o \
msm-lsm-client.o msm-pcm-host-voice-v2.o \
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-compr-q6-v2.c b/sound/soc/msm/qdsp6v2/msm-compr-q6-v2.c
deleted file mode 100644
index 58a4de5af145..000000000000
--- a/sound/soc/msm/qdsp6v2/msm-compr-q6-v2.c
+++ /dev/null
@@ -1,1694 +0,0 @@
-/* Copyright (c) 2012-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 <linux/init.h>
-#include <linux/err.h>
-#include <linux/module.h>
-#include <linux/moduleparam.h>
-#include <linux/time.h>
-#include <linux/wait.h>
-#include <linux/platform_device.h>
-#include <linux/slab.h>
-#include <sound/core.h>
-#include <sound/soc.h>
-#include <sound/soc-dapm.h>
-#include <sound/pcm.h>
-#include <sound/initval.h>
-#include <sound/control.h>
-#include <sound/q6asm-v2.h>
-#include <sound/pcm_params.h>
-#include <asm/dma.h>
-#include <linux/dma-mapping.h>
-#include <linux/msm_audio_ion.h>
-
-#include <sound/timer.h>
-
-#include "msm-compr-q6-v2.h"
-#include "msm-pcm-routing-v2.h"
-#include <sound/tlv.h>
-
-#define COMPRE_CAPTURE_NUM_PERIODS 16
-/* Allocate the worst case frame size for compressed audio */
-#define COMPRE_CAPTURE_HEADER_SIZE (sizeof(struct snd_compr_audio_info))
-/* Changing period size to 4032. 4032 will make sure COMPRE_CAPTURE_PERIOD_SIZE
- * is 4096 with meta data size of 64 and MAX_NUM_FRAMES_PER_BUFFER 1
- */
-#define COMPRE_CAPTURE_MAX_FRAME_SIZE (4032)
-#define COMPRE_CAPTURE_PERIOD_SIZE ((COMPRE_CAPTURE_MAX_FRAME_SIZE + \
- COMPRE_CAPTURE_HEADER_SIZE) * \
- MAX_NUM_FRAMES_PER_BUFFER)
-#define COMPRE_OUTPUT_METADATA_SIZE (sizeof(struct output_meta_data_st))
-#define COMPRESSED_LR_VOL_MAX_STEPS 0x20002000
-
-#define MAX_AC3_PARAM_SIZE (18*2*sizeof(int))
-#define AMR_WB_BAND_MODE 8
-#define AMR_WB_DTX_MODE 0
-
-
-const DECLARE_TLV_DB_LINEAR(compr_rx_vol_gain, 0,
- COMPRESSED_LR_VOL_MAX_STEPS);
-
-static struct audio_locks the_locks;
-
-static struct snd_pcm_hardware msm_compr_hardware_capture = {
- .info = (SNDRV_PCM_INFO_MMAP |
- SNDRV_PCM_INFO_BLOCK_TRANSFER |
- SNDRV_PCM_INFO_MMAP_VALID |
- SNDRV_PCM_INFO_INTERLEAVED |
- SNDRV_PCM_INFO_PAUSE | SNDRV_PCM_INFO_RESUME),
- .formats = SNDRV_PCM_FMTBIT_S16_LE,
- .rates = SNDRV_PCM_RATE_8000_48000,
- .rate_min = 8000,
- .rate_max = 48000,
- .channels_min = 1,
- .channels_max = 8,
- .buffer_bytes_max =
- COMPRE_CAPTURE_PERIOD_SIZE * COMPRE_CAPTURE_NUM_PERIODS ,
- .period_bytes_min = COMPRE_CAPTURE_PERIOD_SIZE,
- .period_bytes_max = COMPRE_CAPTURE_PERIOD_SIZE,
- .periods_min = COMPRE_CAPTURE_NUM_PERIODS,
- .periods_max = COMPRE_CAPTURE_NUM_PERIODS,
- .fifo_size = 0,
-};
-
-static struct snd_pcm_hardware msm_compr_hardware_playback = {
- .info = (SNDRV_PCM_INFO_MMAP |
- SNDRV_PCM_INFO_BLOCK_TRANSFER |
- SNDRV_PCM_INFO_MMAP_VALID |
- SNDRV_PCM_INFO_INTERLEAVED |
- SNDRV_PCM_INFO_PAUSE | SNDRV_PCM_INFO_RESUME),
- .formats = SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S24_LE,
- .rates = SNDRV_PCM_RATE_8000_48000 | SNDRV_PCM_RATE_KNOT,
- .rate_min = 8000,
- .rate_max = 48000,
- .channels_min = 1,
- .channels_max = 8,
- .buffer_bytes_max = 1024 * 1024,
- .period_bytes_min = 128 * 1024,
- .period_bytes_max = 256 * 1024,
- .periods_min = 4,
- .periods_max = 8,
- .fifo_size = 0,
-};
-
-/* Conventional and unconventional sample rate supported */
-static unsigned int supported_sample_rates[] = {
- 8000, 11025, 12000, 16000, 22050, 24000, 32000, 44100, 48000
-};
-
-/* Add supported codecs for compress capture path */
-static uint32_t supported_compr_capture_codecs[] = {
- SND_AUDIOCODEC_AMRWB
-};
-
-static struct snd_pcm_hw_constraint_list constraints_sample_rates = {
- .count = ARRAY_SIZE(supported_sample_rates),
- .list = supported_sample_rates,
- .mask = 0,
-};
-
-static bool msm_compr_capture_codecs(uint32_t req_codec)
-{
- int i;
- pr_debug("%s req_codec:%d\n", __func__, req_codec);
- if (req_codec == 0)
- return false;
- for (i = 0; i < ARRAY_SIZE(supported_compr_capture_codecs); i++) {
- if (req_codec == supported_compr_capture_codecs[i])
- return true;
- }
- return false;
-}
-
-static void compr_event_handler(uint32_t opcode,
- uint32_t token, uint32_t *payload, void *priv)
-{
- struct compr_audio *compr = priv;
- struct msm_audio *prtd = &compr->prtd;
- struct snd_pcm_substream *substream = prtd->substream;
- struct snd_pcm_runtime *runtime = substream->runtime;
- struct audio_aio_write_param param;
- struct audio_aio_read_param read_param;
- struct audio_buffer *buf = NULL;
- phys_addr_t temp;
- struct output_meta_data_st output_meta_data;
- uint32_t *ptrmem = (uint32_t *)payload;
- int i = 0;
- int time_stamp_flag = 0;
- int buffer_length = 0;
- int stop_playback = 0;
-
- pr_debug("%s opcode =%08x\n", __func__, opcode);
- switch (opcode) {
- case ASM_DATA_EVENT_WRITE_DONE_V2: {
- uint32_t *ptrmem = (uint32_t *)&param;
- pr_debug("ASM_DATA_EVENT_WRITE_DONE\n");
- pr_debug("Buffer Consumed = 0x%08x\n", *ptrmem);
- prtd->pcm_irq_pos += prtd->pcm_count;
- if (atomic_read(&prtd->start))
- snd_pcm_period_elapsed(substream);
- else
- if (substream->timer_running)
- snd_timer_interrupt(substream->timer, 1);
- atomic_inc(&prtd->out_count);
- wake_up(&the_locks.write_wait);
- if (!atomic_read(&prtd->start)) {
- atomic_set(&prtd->pending_buffer, 1);
- break;
- } else
- atomic_set(&prtd->pending_buffer, 0);
-
- /*
- * check for underrun
- */
- snd_pcm_stream_lock_irq(substream);
- if (runtime->status->hw_ptr >= runtime->control->appl_ptr) {
- runtime->render_flag |= SNDRV_RENDER_STOPPED;
- stop_playback = 1;
- }
- snd_pcm_stream_unlock_irq(substream);
-
- if (stop_playback) {
- pr_err("underrun! render stopped\n");
- break;
- }
-
- buf = prtd->audio_client->port[IN].buf;
- pr_debug("%s:writing %d bytes of buffer[%d] to dsp 2\n",
- __func__, prtd->pcm_count, prtd->out_head);
- temp = buf[0].phys + (prtd->out_head * prtd->pcm_count);
- pr_debug("%s:writing buffer[%d] from 0x%pK\n",
- __func__, prtd->out_head, &temp);
-
- if (runtime->tstamp_mode == SNDRV_PCM_TSTAMP_ENABLE)
- time_stamp_flag = SET_TIMESTAMP;
- else
- time_stamp_flag = NO_TIMESTAMP;
- memcpy(&output_meta_data, (char *)(buf->data +
- prtd->out_head * prtd->pcm_count),
- COMPRE_OUTPUT_METADATA_SIZE);
-
- buffer_length = output_meta_data.frame_size;
- pr_debug("meta_data_length: %d, frame_length: %d\n",
- output_meta_data.meta_data_length,
- output_meta_data.frame_size);
- pr_debug("timestamp_msw: %d, timestamp_lsw: %d\n",
- output_meta_data.timestamp_msw,
- output_meta_data.timestamp_lsw);
- if (buffer_length == 0) {
- pr_debug("Recieved a zero length buffer-break out");
- break;
- }
- param.paddr = temp + output_meta_data.meta_data_length;
- param.len = buffer_length;
- param.msw_ts = output_meta_data.timestamp_msw;
- param.lsw_ts = output_meta_data.timestamp_lsw;
- param.flags = time_stamp_flag;
- param.uid = prtd->session_id;
- for (i = 0; i < sizeof(struct audio_aio_write_param)/4;
- i++, ++ptrmem)
- pr_debug("cmd[%d]=0x%08x\n", i, *ptrmem);
- if (q6asm_async_write(prtd->audio_client,
- &param) < 0)
- pr_err("%s:q6asm_async_write failed\n",
- __func__);
- else
- prtd->out_head =
- (prtd->out_head + 1) & (runtime->periods - 1);
- break;
- }
- case ASM_DATA_EVENT_RENDERED_EOS:
- pr_debug("ASM_DATA_CMDRSP_EOS\n");
- if (atomic_read(&prtd->eos)) {
- pr_debug("ASM_DATA_CMDRSP_EOS wake up\n");
- prtd->cmd_ack = 1;
- wake_up(&the_locks.eos_wait);
- atomic_set(&prtd->eos, 0);
- }
- break;
- case ASM_DATA_EVENT_READ_DONE_V2: {
- pr_debug("ASM_DATA_EVENT_READ_DONE\n");
- pr_debug("buf = %pK, data = 0x%X, *data = %pK,\n"
- "prtd->pcm_irq_pos = %d\n",
- prtd->audio_client->port[OUT].buf,
- *(uint32_t *)prtd->audio_client->port[OUT].buf->data,
- prtd->audio_client->port[OUT].buf->data,
- prtd->pcm_irq_pos);
-
- memcpy(prtd->audio_client->port[OUT].buf->data +
- prtd->pcm_irq_pos, (ptrmem + READDONE_IDX_SIZE),
- COMPRE_CAPTURE_HEADER_SIZE);
- pr_debug("buf = %pK, updated data = 0x%X, *data = %pK\n",
- prtd->audio_client->port[OUT].buf,
- *(uint32_t *)(prtd->audio_client->port[OUT].buf->data +
- prtd->pcm_irq_pos),
- prtd->audio_client->port[OUT].buf->data);
- if (!atomic_read(&prtd->start))
- break;
- pr_debug("frame size=%d, buffer = 0x%X\n",
- ptrmem[READDONE_IDX_SIZE],
- ptrmem[READDONE_IDX_BUFADD_LSW]);
- if (ptrmem[READDONE_IDX_SIZE] > COMPRE_CAPTURE_MAX_FRAME_SIZE) {
- pr_err("Frame length exceeded the max length");
- break;
- }
- buf = prtd->audio_client->port[OUT].buf;
-
- pr_debug("pcm_irq_pos=%d, buf[0].phys = 0x%pK\n",
- prtd->pcm_irq_pos, &buf[0].phys);
- read_param.len = prtd->pcm_count - COMPRE_CAPTURE_HEADER_SIZE;
- read_param.paddr = buf[0].phys +
- prtd->pcm_irq_pos + COMPRE_CAPTURE_HEADER_SIZE;
- prtd->pcm_irq_pos += prtd->pcm_count;
-
- if (atomic_read(&prtd->start))
- snd_pcm_period_elapsed(substream);
-
- q6asm_async_read(prtd->audio_client, &read_param);
- break;
- }
- case APR_BASIC_RSP_RESULT: {
- switch (payload[0]) {
- case ASM_SESSION_CMD_RUN_V2: {
- if (substream->stream
- != SNDRV_PCM_STREAM_PLAYBACK) {
- atomic_set(&prtd->start, 1);
- break;
- }
- if (!atomic_read(&prtd->pending_buffer))
- break;
- pr_debug("%s: writing %d bytes of buffer[%d] to dsp\n",
- __func__, prtd->pcm_count, prtd->out_head);
- buf = prtd->audio_client->port[IN].buf;
- pr_debug("%s: writing buffer[%d] from 0x%pK head %d count %d\n",
- __func__, prtd->out_head, &buf[0].phys,
- prtd->pcm_count, prtd->out_head);
- if (runtime->tstamp_mode == SNDRV_PCM_TSTAMP_ENABLE)
- time_stamp_flag = SET_TIMESTAMP;
- else
- time_stamp_flag = NO_TIMESTAMP;
- memcpy(&output_meta_data, (char *)(buf->data +
- prtd->out_head * prtd->pcm_count),
- COMPRE_OUTPUT_METADATA_SIZE);
- buffer_length = output_meta_data.frame_size;
- pr_debug("meta_data_length: %d, frame_length: %d\n",
- output_meta_data.meta_data_length,
- output_meta_data.frame_size);
- pr_debug("timestamp_msw: %d, timestamp_lsw: %d\n",
- output_meta_data.timestamp_msw,
- output_meta_data.timestamp_lsw);
- param.paddr = buf[prtd->out_head].phys
- + output_meta_data.meta_data_length;
- param.len = buffer_length;
- param.msw_ts = output_meta_data.timestamp_msw;
- param.lsw_ts = output_meta_data.timestamp_lsw;
- param.flags = time_stamp_flag;
- param.uid = prtd->session_id;
- param.metadata_len = COMPRE_OUTPUT_METADATA_SIZE;
- if (q6asm_async_write(prtd->audio_client,
- &param) < 0)
- pr_err("%s:q6asm_async_write failed\n",
- __func__);
- else
- prtd->out_head =
- (prtd->out_head + 1)
- & (runtime->periods - 1);
- atomic_set(&prtd->pending_buffer, 0);
- }
- break;
- case ASM_STREAM_CMD_FLUSH:
- pr_debug("ASM_STREAM_CMD_FLUSH\n");
- prtd->cmd_ack = 1;
- wake_up(&the_locks.flush_wait);
- break;
- default:
- break;
- }
- break;
- }
- default:
- pr_debug("Not Supported Event opcode[0x%x]\n", opcode);
- break;
- }
-}
-
-static int msm_compr_send_ddp_cfg(struct audio_client *ac,
- struct snd_dec_ddp *ddp)
-{
- int i, rc;
- pr_debug("%s\n", __func__);
-
- if (ddp->params_length / 2 > SND_DEC_DDP_MAX_PARAMS) {
- pr_err("%s: Invalid number of params %u, max allowed %u\n",
- __func__, ddp->params_length / 2,
- SND_DEC_DDP_MAX_PARAMS);
- return -EINVAL;
- }
-
- for (i = 0; i < ddp->params_length/2; i++) {
- rc = q6asm_ds1_set_endp_params(ac, ddp->params_id[i],
- ddp->params_value[i]);
- if (rc) {
- pr_err("sending params_id: %d failed\n",
- ddp->params_id[i]);
- return rc;
- }
- }
- return 0;
-}
-
-static int msm_compr_playback_prepare(struct snd_pcm_substream *substream)
-{
- struct snd_pcm_runtime *runtime = substream->runtime;
- struct compr_audio *compr = runtime->private_data;
- struct snd_soc_pcm_runtime *soc_prtd = substream->private_data;
- struct msm_audio *prtd = &compr->prtd;
- struct snd_pcm_hw_params *params;
- struct asm_aac_cfg aac_cfg;
- uint16_t bits_per_sample = 16;
- int ret;
-
- struct asm_softpause_params softpause = {
- .enable = SOFT_PAUSE_ENABLE,
- .period = SOFT_PAUSE_PERIOD,
- .step = SOFT_PAUSE_STEP,
- .rampingcurve = SOFT_PAUSE_CURVE_LINEAR,
- };
- struct asm_softvolume_params softvol = {
- .period = SOFT_VOLUME_PERIOD,
- .step = SOFT_VOLUME_STEP,
- .rampingcurve = SOFT_VOLUME_CURVE_LINEAR,
- };
-
- pr_debug("%s\n", __func__);
-
- params = &soc_prtd->dpcm[substream->stream].hw_params;
- if (runtime->format == SNDRV_PCM_FORMAT_S24_LE)
- bits_per_sample = 24;
-
- ret = q6asm_open_write_v2(prtd->audio_client,
- compr->codec, bits_per_sample);
- if (ret < 0) {
- pr_err("%s: Session out open failed\n",
- __func__);
- return -ENOMEM;
- }
- msm_pcm_routing_reg_phy_stream(
- soc_prtd->dai_link->be_id,
- prtd->audio_client->perf_mode,
- prtd->session_id,
- substream->stream);
- /*
- * the number of channels are required to call volume api
- * accoridngly. So, get channels from hw params
- */
- if ((params_channels(params) > 0) &&
- (params_periods(params) <= runtime->hw.channels_max))
- prtd->channel_mode = params_channels(params);
-
- ret = q6asm_set_softpause(prtd->audio_client, &softpause);
- if (ret < 0)
- pr_err("%s: Send SoftPause Param failed ret=%d\n",
- __func__, ret);
- ret = q6asm_set_softvolume(prtd->audio_client, &softvol);
- if (ret < 0)
- pr_err("%s: Send SoftVolume Param failed ret=%d\n",
- __func__, ret);
-
- ret = q6asm_set_io_mode(prtd->audio_client,
- (COMPRESSED_IO | ASYNC_IO_MODE));
- if (ret < 0) {
- pr_err("%s: Set IO mode failed\n", __func__);
- return -ENOMEM;
- }
-
- prtd->pcm_size = snd_pcm_lib_buffer_bytes(substream);
- prtd->pcm_count = snd_pcm_lib_period_bytes(substream);
- prtd->pcm_irq_pos = 0;
- /* rate and channels are sent to audio driver */
- prtd->samp_rate = runtime->rate;
- prtd->channel_mode = runtime->channels;
- prtd->out_head = 0;
- atomic_set(&prtd->out_count, runtime->periods);
-
- if (prtd->enabled)
- return 0;
-
- switch (compr->info.codec_param.codec.id) {
- case SND_AUDIOCODEC_MP3:
- /* No media format block for mp3 */
- break;
- case SND_AUDIOCODEC_AAC:
- pr_debug("%s: SND_AUDIOCODEC_AAC\n", __func__);
- memset(&aac_cfg, 0x0, sizeof(struct asm_aac_cfg));
- aac_cfg.aot = AAC_ENC_MODE_EAAC_P;
- aac_cfg.format = 0x03;
- aac_cfg.ch_cfg = runtime->channels;
- aac_cfg.sample_rate = runtime->rate;
- ret = q6asm_media_format_block_aac(prtd->audio_client,
- &aac_cfg);
- if (ret < 0)
- pr_err("%s: CMD Format block failed\n", __func__);
- break;
- case SND_AUDIOCODEC_AC3: {
- struct snd_dec_ddp *ddp =
- &compr->info.codec_param.codec.options.ddp;
- pr_debug("%s: SND_AUDIOCODEC_AC3\n", __func__);
- ret = msm_compr_send_ddp_cfg(prtd->audio_client, ddp);
- if (ret < 0)
- pr_err("%s: DDP CMD CFG failed\n", __func__);
- break;
- }
- case SND_AUDIOCODEC_EAC3: {
- struct snd_dec_ddp *ddp =
- &compr->info.codec_param.codec.options.ddp;
- pr_debug("%s: SND_AUDIOCODEC_EAC3\n", __func__);
- ret = msm_compr_send_ddp_cfg(prtd->audio_client, ddp);
- if (ret < 0)
- pr_err("%s: DDP CMD CFG failed\n", __func__);
- break;
- }
- default:
- return -EINVAL;
- }
-
- prtd->enabled = 1;
- prtd->cmd_ack = 0;
- prtd->cmd_interrupt = 0;
-
- return 0;
-}
-
-static int msm_compr_capture_prepare(struct snd_pcm_substream *substream)
-{
- struct snd_pcm_runtime *runtime = substream->runtime;
- struct compr_audio *compr = runtime->private_data;
- struct msm_audio *prtd = &compr->prtd;
- struct audio_buffer *buf = prtd->audio_client->port[OUT].buf;
- struct snd_codec *codec = &compr->info.codec_param.codec;
- struct snd_soc_pcm_runtime *soc_prtd = substream->private_data;
- struct audio_aio_read_param read_param;
- uint16_t bits_per_sample = 16;
- int ret = 0;
- int i;
-
- prtd->pcm_size = snd_pcm_lib_buffer_bytes(substream);
- prtd->pcm_count = snd_pcm_lib_period_bytes(substream);
- prtd->pcm_irq_pos = 0;
-
- if (runtime->format == SNDRV_PCM_FORMAT_S24_LE)
- bits_per_sample = 24;
-
- if (!msm_compr_capture_codecs(
- compr->info.codec_param.codec.id)) {
- /*
- * request codec invalid or not supported,
- * use default compress format
- */
- compr->info.codec_param.codec.id =
- SND_AUDIOCODEC_AMRWB;
- }
- switch (compr->info.codec_param.codec.id) {
- case SND_AUDIOCODEC_AMRWB:
- pr_debug("q6asm_open_read(FORMAT_AMRWB)\n");
- ret = q6asm_open_read(prtd->audio_client,
- FORMAT_AMRWB);
- if (ret < 0) {
- pr_err("%s: compressed Session out open failed\n",
- __func__);
- return -ENOMEM;
- }
- pr_debug("msm_pcm_routing_reg_phy_stream\n");
- msm_pcm_routing_reg_phy_stream(
- soc_prtd->dai_link->be_id,
- prtd->audio_client->perf_mode,
- prtd->session_id, substream->stream);
- break;
- default:
- pr_debug("q6asm_open_read_compressed(COMPRESSED_META_DATA_MODE)\n");
- /*
- ret = q6asm_open_read_compressed(prtd->audio_client,
- MAX_NUM_FRAMES_PER_BUFFER,
- COMPRESSED_META_DATA_MODE);
- */
- ret = -EINVAL;
- break;
- }
-
- if (ret < 0) {
- pr_err("%s: compressed Session out open failed\n",
- __func__);
- return -ENOMEM;
- }
-
- ret = q6asm_set_io_mode(prtd->audio_client,
- (COMPRESSED_IO | ASYNC_IO_MODE));
- if (ret < 0) {
- pr_err("%s: Set IO mode failed\n", __func__);
- return -ENOMEM;
- }
-
- if (!msm_compr_capture_codecs(codec->id)) {
- /*
- * request codec invalid or not supported,
- * use default compress format
- */
- codec->id = SND_AUDIOCODEC_AMRWB;
- }
- /* rate and channels are sent to audio driver */
- prtd->samp_rate = runtime->rate;
- prtd->channel_mode = runtime->channels;
-
- if (prtd->enabled)
- return ret;
- read_param.len = prtd->pcm_count;
-
- switch (codec->id) {
- case SND_AUDIOCODEC_AMRWB:
- pr_debug("SND_AUDIOCODEC_AMRWB\n");
- ret = q6asm_enc_cfg_blk_amrwb(prtd->audio_client,
- MAX_NUM_FRAMES_PER_BUFFER,
- /*
- * use fixed band mode and dtx mode
- * band mode - 23.85 kbps
- */
- AMR_WB_BAND_MODE,
- /* dtx mode - disable */
- AMR_WB_DTX_MODE);
- if (ret < 0)
- pr_err("%s: CMD Format block failed: %d\n",
- __func__, ret);
- break;
- default:
- pr_debug("No config for codec %d\n", codec->id);
- }
- pr_debug("%s: Samp_rate = %d, Channel = %d, pcm_size = %d,\n"
- "pcm_count = %d, periods = %d\n",
- __func__, prtd->samp_rate, prtd->channel_mode,
- prtd->pcm_size, prtd->pcm_count, runtime->periods);
-
- for (i = 0; i < runtime->periods; i++) {
- read_param.uid = i;
- switch (codec->id) {
- case SND_AUDIOCODEC_AMRWB:
- read_param.len = prtd->pcm_count
- - COMPRE_CAPTURE_HEADER_SIZE;
- read_param.paddr = buf[i].phys
- + COMPRE_CAPTURE_HEADER_SIZE;
- pr_debug("Push buffer [%d] to DSP, paddr: %pK, vaddr: %pK\n",
- i, &read_param.paddr,
- buf[i].data);
- q6asm_async_read(prtd->audio_client, &read_param);
- break;
- default:
- read_param.paddr = buf[i].phys;
- /*q6asm_async_read_compressed(prtd->audio_client,
- &read_param);*/
- pr_debug("%s: To add support for read compressed\n",
- __func__);
- ret = -EINVAL;
- break;
- }
- }
- prtd->periods = runtime->periods;
-
- prtd->enabled = 1;
-
- return ret;
-}
-
-static int msm_compr_trigger(struct snd_pcm_substream *substream, int cmd)
-{
- int ret = 0;
- struct snd_pcm_runtime *runtime = substream->runtime;
- struct snd_soc_pcm_runtime *soc_prtd = substream->private_data;
- struct compr_audio *compr = runtime->private_data;
- struct msm_audio *prtd = &compr->prtd;
-
- pr_debug("%s\n", __func__);
- switch (cmd) {
- case SNDRV_PCM_TRIGGER_START:
- prtd->pcm_irq_pos = 0;
-
- if (substream->stream == SNDRV_PCM_STREAM_CAPTURE) {
- if (!msm_compr_capture_codecs(
- compr->info.codec_param.codec.id)) {
- /*
- * request codec invalid or not supported,
- * use default compress format
- */
- compr->info.codec_param.codec.id =
- SND_AUDIOCODEC_AMRWB;
- }
- switch (compr->info.codec_param.codec.id) {
- case SND_AUDIOCODEC_AMRWB:
- break;
- default:
- msm_pcm_routing_reg_psthr_stream(
- soc_prtd->dai_link->be_id,
- prtd->session_id, substream->stream);
- break;
- }
- }
- atomic_set(&prtd->pending_buffer, 1);
- case SNDRV_PCM_TRIGGER_RESUME:
- case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
- pr_debug("%s: Trigger start\n", __func__);
- q6asm_run_nowait(prtd->audio_client, 0, 0, 0);
- atomic_set(&prtd->start, 1);
- break;
- case SNDRV_PCM_TRIGGER_STOP:
- pr_debug("SNDRV_PCM_TRIGGER_STOP\n");
- if (substream->stream == SNDRV_PCM_STREAM_CAPTURE) {
- switch (compr->info.codec_param.codec.id) {
- case SND_AUDIOCODEC_AMRWB:
- break;
- default:
- msm_pcm_routing_reg_psthr_stream(
- soc_prtd->dai_link->be_id,
- prtd->session_id, substream->stream);
- break;
- }
- }
- atomic_set(&prtd->start, 0);
- runtime->render_flag &= ~SNDRV_RENDER_STOPPED;
- break;
- case SNDRV_PCM_TRIGGER_SUSPEND:
- case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
- pr_debug("SNDRV_PCM_TRIGGER_PAUSE\n");
- q6asm_cmd_nowait(prtd->audio_client, CMD_PAUSE);
- atomic_set(&prtd->start, 0);
- runtime->render_flag &= ~SNDRV_RENDER_STOPPED;
- break;
- default:
- ret = -EINVAL;
- break;
- }
-
- return ret;
-}
-
-static void populate_codec_list(struct compr_audio *compr,
- struct snd_pcm_runtime *runtime)
-{
- pr_debug("%s\n", __func__);
- /* MP3 Block */
- compr->info.compr_cap.num_codecs = 5;
- compr->info.compr_cap.min_fragment_size = runtime->hw.period_bytes_min;
- compr->info.compr_cap.max_fragment_size = runtime->hw.period_bytes_max;
- compr->info.compr_cap.min_fragments = runtime->hw.periods_min;
- compr->info.compr_cap.max_fragments = runtime->hw.periods_max;
- compr->info.compr_cap.codecs[0] = SND_AUDIOCODEC_MP3;
- compr->info.compr_cap.codecs[1] = SND_AUDIOCODEC_AAC;
- compr->info.compr_cap.codecs[2] = SND_AUDIOCODEC_AC3;
- compr->info.compr_cap.codecs[3] = SND_AUDIOCODEC_EAC3;
- compr->info.compr_cap.codecs[4] = SND_AUDIOCODEC_AMRWB;
- /* Add new codecs here */
-}
-
-static int msm_compr_open(struct snd_pcm_substream *substream)
-{
- struct snd_pcm_runtime *runtime = substream->runtime;
- struct compr_audio *compr;
- struct msm_audio *prtd;
- int ret = 0;
-
- pr_debug("%s\n", __func__);
- compr = kzalloc(sizeof(struct compr_audio), GFP_KERNEL);
- if (compr == NULL) {
- pr_err("Failed to allocate memory for msm_audio\n");
- return -ENOMEM;
- }
- prtd = &compr->prtd;
- prtd->substream = substream;
- runtime->render_flag = SNDRV_DMA_MODE;
- prtd->audio_client = q6asm_audio_client_alloc(
- (app_cb)compr_event_handler, compr);
- if (!prtd->audio_client) {
- pr_info("%s: Could not allocate memory\n", __func__);
- kfree(prtd);
- return -ENOMEM;
- }
-
- prtd->audio_client->perf_mode = false;
- pr_info("%s: session ID %d\n", __func__, prtd->audio_client->session);
-
- prtd->session_id = prtd->audio_client->session;
-
- if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
- runtime->hw = msm_compr_hardware_playback;
- prtd->cmd_ack = 1;
- } else {
- runtime->hw = msm_compr_hardware_capture;
- }
-
-
- ret = snd_pcm_hw_constraint_list(runtime, 0,
- SNDRV_PCM_HW_PARAM_RATE,
- &constraints_sample_rates);
- if (ret < 0)
- pr_info("snd_pcm_hw_constraint_list failed\n");
- /* Ensure that buffer size is a multiple of period size */
- ret = snd_pcm_hw_constraint_integer(runtime,
- SNDRV_PCM_HW_PARAM_PERIODS);
- if (ret < 0)
- pr_info("snd_pcm_hw_constraint_integer failed\n");
-
- prtd->dsp_cnt = 0;
- atomic_set(&prtd->pending_buffer, 1);
- if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
- compr->codec = FORMAT_MP3;
- populate_codec_list(compr, runtime);
- runtime->private_data = compr;
- atomic_set(&prtd->eos, 0);
- return 0;
-}
-
-static int compressed_set_volume(struct msm_audio *prtd, uint32_t volume)
-{
- int rc = 0;
- int avg_vol = 0;
- int lgain = (volume >> 16) & 0xFFFF;
- int rgain = volume & 0xFFFF;
- if (prtd && prtd->audio_client) {
- pr_debug("%s: channels %d volume 0x%x\n", __func__,
- prtd->channel_mode, volume);
- if ((prtd->channel_mode == 2) &&
- (lgain != rgain)) {
- pr_debug("%s: call q6asm_set_lrgain\n", __func__);
- rc = q6asm_set_lrgain(prtd->audio_client, lgain, rgain);
- } else {
- avg_vol = (lgain + rgain)/2;
- pr_debug("%s: call q6asm_set_volume\n", __func__);
- rc = q6asm_set_volume(prtd->audio_client, avg_vol);
- }
- if (rc < 0) {
- pr_err("%s: Send Volume command failed rc=%d\n",
- __func__, rc);
- }
- }
- return rc;
-}
-
-static int msm_compr_playback_close(struct snd_pcm_substream *substream)
-{
- struct snd_pcm_runtime *runtime = substream->runtime;
- struct snd_soc_pcm_runtime *soc_prtd = substream->private_data;
- struct compr_audio *compr = runtime->private_data;
- struct msm_audio *prtd = &compr->prtd;
- int dir = 0;
-
- pr_debug("%s\n", __func__);
-
- dir = IN;
- atomic_set(&prtd->pending_buffer, 0);
-
- prtd->pcm_irq_pos = 0;
- q6asm_cmd(prtd->audio_client, CMD_CLOSE);
- q6asm_audio_client_buf_free_contiguous(dir,
- prtd->audio_client);
- msm_pcm_routing_dereg_phy_stream(
- soc_prtd->dai_link->be_id,
- SNDRV_PCM_STREAM_PLAYBACK);
- q6asm_audio_client_free(prtd->audio_client);
- kfree(prtd);
- return 0;
-}
-
-static int msm_compr_capture_close(struct snd_pcm_substream *substream)
-{
- struct snd_pcm_runtime *runtime = substream->runtime;
- struct snd_soc_pcm_runtime *soc_prtd = substream->private_data;
- struct compr_audio *compr = runtime->private_data;
- struct msm_audio *prtd = &compr->prtd;
- int dir = OUT;
-
- pr_debug("%s\n", __func__);
- atomic_set(&prtd->pending_buffer, 0);
- q6asm_cmd(prtd->audio_client, CMD_CLOSE);
- q6asm_audio_client_buf_free_contiguous(dir,
- prtd->audio_client);
- msm_pcm_routing_dereg_phy_stream(soc_prtd->dai_link->be_id,
- SNDRV_PCM_STREAM_CAPTURE);
- q6asm_audio_client_free(prtd->audio_client);
- kfree(prtd);
- return 0;
-}
-
-static int msm_compr_close(struct snd_pcm_substream *substream)
-{
- int ret = 0;
-
- if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
- ret = msm_compr_playback_close(substream);
- else if (substream->stream == SNDRV_PCM_STREAM_CAPTURE)
- ret = msm_compr_capture_close(substream);
- return ret;
-}
-
-static int msm_compr_prepare(struct snd_pcm_substream *substream)
-{
- int ret = 0;
-
- if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
- ret = msm_compr_playback_prepare(substream);
- else if (substream->stream == SNDRV_PCM_STREAM_CAPTURE)
- ret = msm_compr_capture_prepare(substream);
- return ret;
-}
-
-static snd_pcm_uframes_t msm_compr_pointer(struct snd_pcm_substream *substream)
-{
-
- struct snd_pcm_runtime *runtime = substream->runtime;
- struct compr_audio *compr = runtime->private_data;
- struct msm_audio *prtd = &compr->prtd;
-
- if (prtd->pcm_irq_pos >= prtd->pcm_size)
- prtd->pcm_irq_pos = 0;
-
- pr_debug("%s: pcm_irq_pos = %d, pcm_size = %d, sample_bits = %d,\n"
- "frame_bits = %d\n", __func__, prtd->pcm_irq_pos,
- prtd->pcm_size, runtime->sample_bits,
- runtime->frame_bits);
- return bytes_to_frames(runtime, (prtd->pcm_irq_pos));
-}
-
-static int msm_compr_mmap(struct snd_pcm_substream *substream,
- struct vm_area_struct *vma)
-{
- struct snd_pcm_runtime *runtime = substream->runtime;
- struct msm_audio *prtd = runtime->private_data;
- struct audio_client *ac = prtd->audio_client;
- struct audio_port_data *apd = ac->port;
- struct audio_buffer *ab;
- int dir = -1;
-
- prtd->mmap_flag = 1;
- runtime->render_flag = SNDRV_NON_DMA_MODE;
- if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
- dir = IN;
- else
- dir = OUT;
- ab = &(apd[dir].buf[0]);
-
- return msm_audio_ion_mmap(ab, vma);
-}
-
-static int msm_compr_hw_params(struct snd_pcm_substream *substream,
- struct snd_pcm_hw_params *params)
-{
- struct snd_pcm_runtime *runtime = substream->runtime;
- struct compr_audio *compr = runtime->private_data;
- struct msm_audio *prtd = &compr->prtd;
- struct snd_dma_buffer *dma_buf = &substream->dma_buffer;
- struct audio_buffer *buf;
- int dir, ret;
-
- if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
- dir = IN;
- else
- dir = OUT;
- /* Modifying kernel hardware params based on userspace config */
- if (params_periods(params) > 0 &&
- (params_periods(params) != runtime->hw.periods_max)) {
- runtime->hw.periods_max = params_periods(params);
- }
- if (params_period_bytes(params) > 0 &&
- (params_period_bytes(params) != runtime->hw.period_bytes_min)) {
- runtime->hw.period_bytes_min = params_period_bytes(params);
- }
- runtime->hw.buffer_bytes_max =
- runtime->hw.period_bytes_min * runtime->hw.periods_max;
- pr_debug("allocate %zd buffers each of size %d\n",
- runtime->hw.period_bytes_min,
- runtime->hw.periods_max);
- ret = q6asm_audio_client_buf_alloc_contiguous(dir,
- prtd->audio_client,
- runtime->hw.period_bytes_min,
- runtime->hw.periods_max);
- if (ret < 0) {
- pr_err("Audio Start: Buffer Allocation failed rc = %d\n",
- ret);
- return -ENOMEM;
- }
- buf = prtd->audio_client->port[dir].buf;
-
- dma_buf->dev.type = SNDRV_DMA_TYPE_DEV;
- dma_buf->dev.dev = substream->pcm->card->dev;
- dma_buf->private_data = NULL;
- dma_buf->area = buf[0].data;
- dma_buf->addr = buf[0].phys;
- dma_buf->bytes = runtime->hw.buffer_bytes_max;
-
- pr_debug("%s: buf[%pK]dma_buf->area[%pK]dma_buf->addr[%pK]\n"
- "dma_buf->bytes[%zd]\n", __func__,
- (void *)buf, (void *)dma_buf->area,
- &dma_buf->addr, dma_buf->bytes);
- if (!dma_buf->area)
- return -ENOMEM;
-
- snd_pcm_set_runtime_buffer(substream, &substream->dma_buffer);
- return 0;
-}
-
-static int msm_compr_ioctl_shared(struct snd_pcm_substream *substream,
- unsigned int cmd, void *arg)
-{
- int rc = 0;
- struct snd_pcm_runtime *runtime = substream->runtime;
- struct compr_audio *compr = runtime->private_data;
- struct msm_audio *prtd = &compr->prtd;
- uint64_t timestamp;
- uint64_t temp;
-
- switch (cmd) {
- case SNDRV_COMPRESS_TSTAMP: {
- struct snd_compr_tstamp *tstamp;
- pr_debug("SNDRV_COMPRESS_TSTAMP\n");
- tstamp = arg;
- memset(tstamp, 0x0, sizeof(*tstamp));
- rc = q6asm_get_session_time(prtd->audio_client, &timestamp);
- if (rc < 0) {
- pr_err("%s: Get Session Time return value =%lld\n",
- __func__, timestamp);
- return -EAGAIN;
- }
- temp = (timestamp * 2 * runtime->channels);
- temp = temp * (runtime->rate/1000);
- temp = div_u64(temp, 1000);
- tstamp->sampling_rate = runtime->rate;
- tstamp->timestamp = timestamp;
- pr_debug("%s: bytes_consumed:,timestamp = %lld,\n",
- __func__,
- tstamp->timestamp);
- return 0;
- }
- case SNDRV_COMPRESS_GET_CAPS: {
- struct snd_compr_caps *caps;
- caps = arg;
- memset(caps, 0, sizeof(*caps));
- pr_debug("SNDRV_COMPRESS_GET_CAPS\n");
- memcpy(caps, &compr->info.compr_cap, sizeof(*caps));
- return 0;
- }
- case SNDRV_COMPRESS_SET_PARAMS:
- pr_debug("SNDRV_COMPRESS_SET_PARAMS:\n");
- memcpy(&compr->info.codec_param, (void *) arg,
- sizeof(struct snd_compr_params));
- switch (compr->info.codec_param.codec.id) {
- case SND_AUDIOCODEC_MP3:
- /* For MP3 we dont need any other parameter */
- pr_debug("SND_AUDIOCODEC_MP3\n");
- compr->codec = FORMAT_MP3;
- break;
- case SND_AUDIOCODEC_AAC:
- pr_debug("SND_AUDIOCODEC_AAC\n");
- compr->codec = FORMAT_MPEG4_AAC;
- break;
- case SND_AUDIOCODEC_AC3: {
- char params_value[MAX_AC3_PARAM_SIZE];
- int *params_value_data = (int *)params_value;
- /* 36 is the max param length for ddp */
- int i;
- struct snd_dec_ddp *ddp =
- &compr->info.codec_param.codec.options.ddp;
- uint32_t params_length = 0;
- memset(params_value, 0, MAX_AC3_PARAM_SIZE);
- /* check integer overflow */
- if (ddp->params_length > UINT_MAX/sizeof(int)) {
- pr_err("%s: Integer overflow ddp->params_length %d\n",
- __func__, ddp->params_length);
- return -EINVAL;
- }
- params_length = ddp->params_length*sizeof(int);
- if (params_length > MAX_AC3_PARAM_SIZE) {
- /*MAX is 36*sizeof(int) this should not happen*/
- pr_err("%s: params_length(%d) is greater than %zd\n",
- __func__, params_length, MAX_AC3_PARAM_SIZE);
- return -EINVAL;
- }
- pr_debug("SND_AUDIOCODEC_AC3\n");
- compr->codec = FORMAT_AC3;
- pr_debug("params_length: %d\n", ddp->params_length);
- for (i = 0; i < params_length/sizeof(int); i++)
- pr_debug("params_value[%d]: %x\n", i,
- params_value_data[i]);
- for (i = 0; i < ddp->params_length/2; i++) {
- ddp->params_id[i] = params_value_data[2*i];
- ddp->params_value[i] = params_value_data[2*i+1];
- }
- if (atomic_read(&prtd->start)) {
- rc = msm_compr_send_ddp_cfg(prtd->audio_client,
- ddp);
- if (rc < 0)
- pr_err("%s: DDP CMD CFG failed\n",
- __func__);
- }
- break;
- }
- case SND_AUDIOCODEC_EAC3: {
- char params_value[MAX_AC3_PARAM_SIZE];
- int *params_value_data = (int *)params_value;
- /* 36 is the max param length for ddp */
- int i;
- struct snd_dec_ddp *ddp =
- &compr->info.codec_param.codec.options.ddp;
- uint32_t params_length = 0;
- memset(params_value, 0, MAX_AC3_PARAM_SIZE);
- /* check integer overflow */
- if (ddp->params_length > UINT_MAX/sizeof(int)) {
- pr_err("%s: Integer overflow ddp->params_length %d\n",
- __func__, ddp->params_length);
- return -EINVAL;
- }
- params_length = ddp->params_length*sizeof(int);
- if (params_length > MAX_AC3_PARAM_SIZE) {
- /*MAX is 36*sizeof(int) this should not happen*/
- pr_err("%s: params_length(%d) is greater than %zd\n",
- __func__, params_length, MAX_AC3_PARAM_SIZE);
- return -EINVAL;
- }
- pr_debug("SND_AUDIOCODEC_EAC3\n");
- compr->codec = FORMAT_EAC3;
- pr_debug("params_length: %d\n", ddp->params_length);
- for (i = 0; i < ddp->params_length; i++)
- pr_debug("params_value[%d]: %x\n", i,
- params_value_data[i]);
- for (i = 0; i < ddp->params_length/2; i++) {
- ddp->params_id[i] = params_value_data[2*i];
- ddp->params_value[i] = params_value_data[2*i+1];
- }
- if (atomic_read(&prtd->start)) {
- rc = msm_compr_send_ddp_cfg(prtd->audio_client,
- ddp);
- if (rc < 0)
- pr_err("%s: DDP CMD CFG failed\n",
- __func__);
- }
- break;
- }
- default:
- pr_debug("FORMAT_LINEAR_PCM\n");
- compr->codec = FORMAT_LINEAR_PCM;
- break;
- }
- return 0;
- case SNDRV_PCM_IOCTL1_RESET:
- pr_debug("SNDRV_PCM_IOCTL1_RESET\n");
- /* Flush only when session is started during CAPTURE,
- while PLAYBACK has no such restriction. */
- if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK ||
- (substream->stream == SNDRV_PCM_STREAM_CAPTURE &&
- atomic_read(&prtd->start))) {
- if (atomic_read(&prtd->eos)) {
- prtd->cmd_interrupt = 1;
- wake_up(&the_locks.eos_wait);
- atomic_set(&prtd->eos, 0);
- }
-
- /* A unlikely race condition possible with FLUSH
- DRAIN if ack is set by flush and reset by drain */
- prtd->cmd_ack = 0;
- rc = q6asm_cmd(prtd->audio_client, CMD_FLUSH);
- if (rc < 0) {
- pr_err("%s: flush cmd failed rc=%d\n",
- __func__, rc);
- return rc;
- }
- rc = wait_event_timeout(the_locks.flush_wait,
- prtd->cmd_ack, 5 * HZ);
- if (!rc)
- pr_err("Flush cmd timeout\n");
- prtd->pcm_irq_pos = 0;
- }
- break;
- case SNDRV_COMPRESS_DRAIN:
- pr_debug("%s: SNDRV_COMPRESS_DRAIN\n", __func__);
- if (atomic_read(&prtd->pending_buffer)) {
- pr_debug("%s: no pending writes, drain would block\n",
- __func__);
- return -EWOULDBLOCK;
- }
-
- atomic_set(&prtd->eos, 1);
- atomic_set(&prtd->pending_buffer, 0);
- prtd->cmd_ack = 0;
- q6asm_cmd_nowait(prtd->audio_client, CMD_EOS);
- /* Wait indefinitely for DRAIN. Flush can also signal this*/
- rc = wait_event_interruptible(the_locks.eos_wait,
- (prtd->cmd_ack || prtd->cmd_interrupt));
-
- if (rc < 0)
- pr_err("EOS cmd interrupted\n");
- pr_debug("%s: SNDRV_COMPRESS_DRAIN out of wait\n", __func__);
-
- if (prtd->cmd_interrupt)
- rc = -EINTR;
-
- prtd->cmd_interrupt = 0;
- return rc;
- default:
- break;
- }
- return snd_pcm_lib_ioctl(substream, cmd, arg);
-}
-#ifdef CONFIG_COMPAT
-struct snd_enc_wma32 {
- u32 super_block_align; /* WMA Type-specific data */
- u32 encodeopt1;
- u32 encodeopt2;
-};
-
-struct snd_enc_vorbis32 {
- s32 quality;
- u32 managed;
- u32 max_bit_rate;
- u32 min_bit_rate;
- u32 downmix;
-};
-
-struct snd_enc_real32 {
- u32 quant_bits;
- u32 start_region;
- u32 num_regions;
-};
-
-struct snd_enc_flac32 {
- u32 num;
- u32 gain;
-};
-
-struct snd_enc_generic32 {
- u32 bw; /* encoder bandwidth */
- s32 reserved[15];
-};
-struct snd_dec_ddp32 {
- u32 params_length;
- u32 params_id[18];
- u32 params_value[18];
-};
-
-union snd_codec_options32 {
- struct snd_enc_wma32 wma;
- struct snd_enc_vorbis32 vorbis;
- struct snd_enc_real32 real;
- struct snd_enc_flac32 flac;
- struct snd_enc_generic32 generic;
- struct snd_dec_ddp32 ddp;
-};
-
-struct snd_codec32 {
- u32 id;
- u32 ch_in;
- u32 ch_out;
- u32 sample_rate;
- u32 bit_rate;
- u32 rate_control;
- u32 profile;
- u32 level;
- u32 ch_mode;
- u32 format;
- u32 align;
- union snd_codec_options32 options;
- u32 reserved[3];
-};
-
-struct snd_compressed_buffer32 {
- u32 fragment_size;
- u32 fragments;
-};
-
-struct snd_compr_params32 {
- struct snd_compressed_buffer32 buffer;
- struct snd_codec32 codec;
- u8 no_wake_mode;
-};
-
-struct snd_compr_caps32 {
- u32 num_codecs;
- u32 direction;
- u32 min_fragment_size;
- u32 max_fragment_size;
- u32 min_fragments;
- u32 max_fragments;
- u32 codecs[MAX_NUM_CODECS];
- u32 reserved[11];
-};
-struct snd_compr_tstamp32 {
- u32 byte_offset;
- u32 copied_total;
- compat_ulong_t pcm_frames;
- compat_ulong_t pcm_io_frames;
- u32 sampling_rate;
- compat_u64 timestamp;
-};
-enum {
- SNDRV_COMPRESS_TSTAMP32 = _IOR('C', 0x20, struct snd_compr_tstamp32),
- SNDRV_COMPRESS_GET_CAPS32 = _IOWR('C', 0x10, struct snd_compr_caps32),
- SNDRV_COMPRESS_SET_PARAMS32 =
- _IOW('C', 0x12, struct snd_compr_params32),
-};
-static int msm_compr_compat_ioctl(struct snd_pcm_substream *substream,
- unsigned int cmd, void *arg)
-{
- int err = 0;
- switch (cmd) {
- case SNDRV_COMPRESS_TSTAMP32: {
- struct snd_compr_tstamp tstamp;
- struct snd_compr_tstamp32 tstamp32;
- memset(&tstamp, 0, sizeof(tstamp));
- memset(&tstamp32, 0, sizeof(tstamp32));
- cmd = SNDRV_COMPRESS_TSTAMP;
- err = msm_compr_ioctl_shared(substream, cmd, &tstamp);
- if (err) {
- pr_err("%s: COMPRESS_TSTAMP failed rc %d\n",
- __func__, err);
- goto bail_out;
- }
- tstamp32.byte_offset = tstamp.byte_offset;
- tstamp32.copied_total = tstamp.copied_total;
- tstamp32.pcm_frames = tstamp.pcm_frames;
- tstamp32.pcm_io_frames = tstamp.pcm_io_frames;
- tstamp32.sampling_rate = tstamp.sampling_rate;
- tstamp32.timestamp = tstamp.timestamp;
- if (copy_to_user(arg, &tstamp32, sizeof(tstamp32))) {
- pr_err("%s: copytouser failed COMPRESS_TSTAMP32\n",
- __func__);
- err = -EFAULT;
- }
- break;
- }
- case SNDRV_COMPRESS_GET_CAPS32: {
- struct snd_compr_caps caps;
- struct snd_compr_caps32 caps32;
- u32 i;
- memset(&caps, 0, sizeof(caps));
- memset(&caps32, 0, sizeof(caps32));
- cmd = SNDRV_COMPRESS_GET_CAPS;
- err = msm_compr_ioctl_shared(substream, cmd, &caps);
- if (err) {
- pr_err("%s: GET_CAPS failed rc %d\n",
- __func__, err);
- goto bail_out;
- }
- pr_debug("SNDRV_COMPRESS_GET_CAPS_32\n");
- if (!err && caps.num_codecs >= MAX_NUM_CODECS) {
- pr_err("%s: Invalid number of codecs\n", __func__);
- err = -EINVAL;
- goto bail_out;
- }
- caps32.direction = caps.direction;
- caps32.max_fragment_size = caps.max_fragment_size;
- caps32.max_fragments = caps.max_fragments;
- caps32.min_fragment_size = caps.min_fragment_size;
- caps32.num_codecs = caps.num_codecs;
- for (i = 0; i < caps.num_codecs; i++)
- caps32.codecs[i] = caps.codecs[i];
- if (copy_to_user(arg, &caps32, sizeof(caps32))) {
- pr_err("%s: copytouser failed COMPRESS_GETCAPS32\n",
- __func__);
- err = -EFAULT;
- }
- break;
- }
- case SNDRV_COMPRESS_SET_PARAMS32: {
- struct snd_compr_params32 params32;
- struct snd_compr_params params;
- memset(&params32, 0 , sizeof(params32));
- memset(&params, 0 , sizeof(params));
- cmd = SNDRV_COMPRESS_SET_PARAMS;
- if (copy_from_user(&params32, arg, sizeof(params32))) {
- pr_err("%s: copyfromuser failed SET_PARAMS32\n",
- __func__);
- err = -EFAULT;
- goto bail_out;
- }
- params.no_wake_mode = params32.no_wake_mode;
- params.codec.id = params32.codec.id;
- params.codec.ch_in = params32.codec.ch_in;
- params.codec.ch_out = params32.codec.ch_out;
- params.codec.sample_rate = params32.codec.sample_rate;
- params.codec.bit_rate = params32.codec.bit_rate;
- params.codec.rate_control = params32.codec.rate_control;
- params.codec.profile = params32.codec.profile;
- params.codec.level = params32.codec.level;
- params.codec.ch_mode = params32.codec.ch_mode;
- params.codec.format = params32.codec.format;
- params.codec.align = params32.codec.align;
-
- switch (params.codec.id) {
- case SND_AUDIOCODEC_WMA:
- case SND_AUDIOCODEC_WMA_PRO:
- params.codec.options.wma.encodeopt1 =
- params32.codec.options.wma.encodeopt1;
- params.codec.options.wma.encodeopt2 =
- params32.codec.options.wma.encodeopt2;
- params.codec.options.wma.super_block_align =
- params32.codec.options.wma.super_block_align;
- break;
- case SND_AUDIOCODEC_VORBIS:
- params.codec.options.vorbis.downmix =
- params32.codec.options.vorbis.downmix;
- params.codec.options.vorbis.managed =
- params32.codec.options.vorbis.managed;
- params.codec.options.vorbis.max_bit_rate =
- params32.codec.options.vorbis.max_bit_rate;
- params.codec.options.vorbis.min_bit_rate =
- params32.codec.options.vorbis.min_bit_rate;
- params.codec.options.vorbis.quality =
- params32.codec.options.vorbis.quality;
- break;
- case SND_AUDIOCODEC_REAL:
- params.codec.options.real.num_regions =
- params32.codec.options.real.num_regions;
- params.codec.options.real.quant_bits =
- params32.codec.options.real.quant_bits;
- params.codec.options.real.start_region =
- params32.codec.options.real.start_region;
- break;
- case SND_AUDIOCODEC_FLAC:
- params.codec.options.flac.gain =
- params32.codec.options.flac.gain;
- params.codec.options.flac.num =
- params32.codec.options.flac.num;
- break;
- case SND_AUDIOCODEC_DTS:
- case SND_AUDIOCODEC_DTS_PASS_THROUGH:
- case SND_AUDIOCODEC_DTS_LBR:
- case SND_AUDIOCODEC_DTS_LBR_PASS_THROUGH:
- case SND_AUDIOCODEC_DTS_TRANSCODE_LOOPBACK:
- break;
- case SND_AUDIOCODEC_AC3:
- case SND_AUDIOCODEC_EAC3:
- params.codec.options.ddp.params_length =
- params32.codec.options.ddp.params_length;
- memcpy(params.codec.options.ddp.params_value,
- params32.codec.options.ddp.params_value,
- sizeof(params32.codec.options.ddp.params_value));
- memcpy(params.codec.options.ddp.params_id,
- params32.codec.options.ddp.params_id,
- sizeof(params32.codec.options.ddp.params_id));
- break;
- default:
- params.codec.options.generic.bw =
- params32.codec.options.generic.bw;
- break;
- }
- if (!err)
- err = msm_compr_ioctl_shared(substream, cmd, &params);
- break;
- }
- default:
- err = msm_compr_ioctl_shared(substream, cmd, arg);
- }
-bail_out:
- return err;
-
-}
-#endif
-static int msm_compr_ioctl(struct snd_pcm_substream *substream,
- unsigned int cmd, void *arg)
-{
- int err = 0;
- if (!substream) {
- pr_err("%s: Invalid params\n", __func__);
- return -EINVAL;
- }
- pr_debug("%s called with cmd = %d\n", __func__, cmd);
- switch (cmd) {
- case SNDRV_COMPRESS_TSTAMP: {
- struct snd_compr_tstamp tstamp;
- if (!arg) {
- pr_err("%s: Invalid params Tstamp\n", __func__);
- return -EINVAL;
- }
- err = msm_compr_ioctl_shared(substream, cmd, &tstamp);
- if (err)
- pr_err("%s: COMPRESS_TSTAMP failed rc %d\n",
- __func__, err);
- if (!err && copy_to_user(arg, &tstamp, sizeof(tstamp))) {
- pr_err("%s: copytouser failed COMPRESS_TSTAMP\n",
- __func__);
- err = -EFAULT;
- }
- break;
- }
- case SNDRV_COMPRESS_GET_CAPS: {
- struct snd_compr_caps cap;
- if (!arg) {
- pr_err("%s: Invalid params getcaps\n", __func__);
- return -EINVAL;
- }
- pr_debug("SNDRV_COMPRESS_GET_CAPS\n");
- err = msm_compr_ioctl_shared(substream, cmd, &cap);
- if (err)
- pr_err("%s: GET_CAPS failed rc %d\n",
- __func__, err);
- if (!err && copy_to_user(arg, &cap, sizeof(cap))) {
- pr_err("%s: copytouser failed GET_CAPS\n",
- __func__);
- err = -EFAULT;
- }
- break;
- }
- case SNDRV_COMPRESS_SET_PARAMS: {
- struct snd_compr_params params;
- if (!arg) {
- pr_err("%s: Invalid params setparam\n", __func__);
- return -EINVAL;
- }
- if (copy_from_user(&params, arg,
- sizeof(struct snd_compr_params))) {
- pr_err("%s: SET_PARAMS\n", __func__);
- return -EFAULT;
- }
- err = msm_compr_ioctl_shared(substream, cmd, &params);
- if (err)
- pr_err("%s: SET_PARAMS failed rc %d\n",
- __func__, err);
- break;
- }
- default:
- err = msm_compr_ioctl_shared(substream, cmd, arg);
- }
- return err;
-}
-
-static int msm_compr_restart(struct snd_pcm_substream *substream)
-{
- struct snd_pcm_runtime *runtime = substream->runtime;
- struct compr_audio *compr = runtime->private_data;
- struct msm_audio *prtd = &compr->prtd;
- struct audio_aio_write_param param;
- struct audio_buffer *buf = NULL;
- struct output_meta_data_st output_meta_data;
- int time_stamp_flag = 0;
- int buffer_length = 0;
-
- pr_debug("%s, trigger restart\n", __func__);
-
- if (runtime->render_flag & SNDRV_RENDER_STOPPED) {
- buf = prtd->audio_client->port[IN].buf;
- pr_debug("%s:writing %d bytes of buffer[%d] to dsp 2\n",
- __func__, prtd->pcm_count, prtd->out_head);
- pr_debug("%s:writing buffer[%d] from 0x%08x\n",
- __func__, prtd->out_head,
- ((unsigned int)buf[0].phys
- + (prtd->out_head * prtd->pcm_count)));
-
- if (runtime->tstamp_mode == SNDRV_PCM_TSTAMP_ENABLE)
- time_stamp_flag = SET_TIMESTAMP;
- else
- time_stamp_flag = NO_TIMESTAMP;
- memcpy(&output_meta_data, (char *)(buf->data +
- prtd->out_head * prtd->pcm_count),
- COMPRE_OUTPUT_METADATA_SIZE);
-
- buffer_length = output_meta_data.frame_size;
- pr_debug("meta_data_length: %d, frame_length: %d\n",
- output_meta_data.meta_data_length,
- output_meta_data.frame_size);
- pr_debug("timestamp_msw: %d, timestamp_lsw: %d\n",
- output_meta_data.timestamp_msw,
- output_meta_data.timestamp_lsw);
-
- param.paddr = (unsigned long)buf[0].phys
- + (prtd->out_head * prtd->pcm_count)
- + output_meta_data.meta_data_length;
- param.len = buffer_length;
- param.msw_ts = output_meta_data.timestamp_msw;
- param.lsw_ts = output_meta_data.timestamp_lsw;
- param.flags = time_stamp_flag;
- param.uid = prtd->session_id;
- if (q6asm_async_write(prtd->audio_client,
- &param) < 0)
- pr_err("%s:q6asm_async_write failed\n",
- __func__);
- else
- prtd->out_head =
- (prtd->out_head + 1) & (runtime->periods - 1);
-
- runtime->render_flag &= ~SNDRV_RENDER_STOPPED;
- return 0;
- }
- return 0;
-}
-
-static int msm_compr_volume_ctl_put(struct snd_kcontrol *kcontrol,
- struct snd_ctl_elem_value *ucontrol)
-{
- int rc = 0;
- struct snd_pcm_volume *vol = snd_kcontrol_chip(kcontrol);
- struct snd_pcm_substream *substream =
- vol->pcm->streams[SNDRV_PCM_STREAM_PLAYBACK].substream;
- struct msm_audio *prtd;
- int volume = ucontrol->value.integer.value[0];
-
- pr_debug("%s: volume : %x\n", __func__, volume);
- if (!substream)
- return -ENODEV;
- if (!substream->runtime)
- return 0;
- prtd = substream->runtime->private_data;
- if (prtd)
- rc = compressed_set_volume(prtd, volume);
-
- return rc;
-}
-
-static int msm_compr_volume_ctl_get(struct snd_kcontrol *kcontrol,
- struct snd_ctl_elem_value *ucontrol)
-{
- struct snd_pcm_volume *vol = snd_kcontrol_chip(kcontrol);
- struct snd_pcm_substream *substream =
- vol->pcm->streams[SNDRV_PCM_STREAM_PLAYBACK].substream;
- struct msm_audio *prtd;
-
- pr_debug("%s\n", __func__);
- if (!substream)
- return -ENODEV;
- if (!substream->runtime)
- return 0;
- prtd = substream->runtime->private_data;
- if (prtd)
- ucontrol->value.integer.value[0] = prtd->volume;
- return 0;
-}
-
-static int msm_compr_add_controls(struct snd_soc_pcm_runtime *rtd)
-{
- int ret = 0;
- struct snd_pcm *pcm = rtd->pcm;
- struct snd_pcm_volume *volume_info;
- struct snd_kcontrol *kctl;
-
- dev_dbg(rtd->dev, "%s, Volume cntrl add\n", __func__);
- ret = snd_pcm_add_volume_ctls(pcm, SNDRV_PCM_STREAM_PLAYBACK,
- NULL, 1, rtd->dai_link->be_id,
- &volume_info);
- if (ret < 0)
- return ret;
- kctl = volume_info->kctl;
- kctl->put = msm_compr_volume_ctl_put;
- kctl->get = msm_compr_volume_ctl_get;
- kctl->tlv.p = compr_rx_vol_gain;
- return 0;
-}
-
-static struct snd_pcm_ops msm_compr_ops = {
- .open = msm_compr_open,
- .hw_params = msm_compr_hw_params,
- .close = msm_compr_close,
- .ioctl = msm_compr_ioctl,
- .prepare = msm_compr_prepare,
- .trigger = msm_compr_trigger,
- .pointer = msm_compr_pointer,
- .mmap = msm_compr_mmap,
- .restart = msm_compr_restart,
-#ifdef CONFIG_COMPAT
- .compat_ioctl = msm_compr_compat_ioctl,
-#endif
-};
-
-static int msm_asoc_pcm_new(struct snd_soc_pcm_runtime *rtd)
-{
- struct snd_card *card = rtd->card->snd_card;
- int ret = 0;
-
- if (!card->dev->coherent_dma_mask)
- card->dev->coherent_dma_mask = DMA_BIT_MASK(32);
-
- ret = msm_compr_add_controls(rtd);
- if (ret)
- pr_err("%s, kctl add failed\n", __func__);
- return ret;
-}
-
-static struct snd_soc_platform_driver msm_soc_platform = {
- .ops = &msm_compr_ops,
- .pcm_new = msm_asoc_pcm_new,
-};
-
-static int msm_compr_probe(struct platform_device *pdev)
-{
-
- dev_info(&pdev->dev, "%s: dev name %s\n",
- __func__, dev_name(&pdev->dev));
-
- return snd_soc_register_platform(&pdev->dev,
- &msm_soc_platform);
-}
-
-static int msm_compr_remove(struct platform_device *pdev)
-{
- snd_soc_unregister_platform(&pdev->dev);
- return 0;
-}
-
-static const struct of_device_id msm_compr_dt_match[] = {
- {.compatible = "qcom,msm-compr-dsp"},
- {}
-};
-MODULE_DEVICE_TABLE(of, msm_compr_dt_match);
-
-static struct platform_driver msm_compr_driver = {
- .driver = {
- .name = "msm-compr-dsp",
- .owner = THIS_MODULE,
- .of_match_table = msm_compr_dt_match,
- },
- .probe = msm_compr_probe,
- .remove = msm_compr_remove,
-};
-
-static int __init msm_soc_platform_init(void)
-{
- init_waitqueue_head(&the_locks.enable_wait);
- init_waitqueue_head(&the_locks.eos_wait);
- init_waitqueue_head(&the_locks.write_wait);
- init_waitqueue_head(&the_locks.read_wait);
- init_waitqueue_head(&the_locks.flush_wait);
-
- return platform_driver_register(&msm_compr_driver);
-}
-module_init(msm_soc_platform_init);
-
-static void __exit msm_soc_platform_exit(void)
-{
- platform_driver_unregister(&msm_compr_driver);
-}
-module_exit(msm_soc_platform_exit);
-
-MODULE_DESCRIPTION("PCM module platform driver");
-MODULE_LICENSE("GPL v2");
diff --git a/sound/soc/msm/qdsp6v2/msm-compr-q6-v2.h b/sound/soc/msm/qdsp6v2/msm-compr-q6-v2.h
deleted file mode 100644
index d6e3ec6956b1..000000000000
--- a/sound/soc/msm/qdsp6v2/msm-compr-q6-v2.h
+++ /dev/null
@@ -1,36 +0,0 @@
-/*
- * Copyright (c) 2012, 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.
- */
-
-#ifndef _MSM_COMPR_H
-#define _MSM_COMPR_H
-#include <sound/apr_audio-v2.h>
-#include <sound/q6asm-v2.h>
-#include <sound/compress_params.h>
-#include <sound/compress_offload.h>
-#include <sound/compress_driver.h>
-
-#include "msm-pcm-q6-v2.h"
-
-struct compr_info {
- struct snd_compr_caps compr_cap;
- struct snd_compr_codec_caps codec_caps;
- struct snd_compr_params codec_param;
-};
-
-struct compr_audio {
- struct msm_audio prtd;
- struct compr_info info;
- uint32_t codec;
-};
-
-#endif /*_MSM_COMPR_H*/
diff --git a/sound/soc/msm/qdsp6v2/msm-compress-q6-v2.c b/sound/soc/msm/qdsp6v2/msm-compress-q6-v2.c
index 5bd3b6d7014e..0a93ee593ed2 100644
--- a/sound/soc/msm/qdsp6v2/msm-compress-q6-v2.c
+++ b/sound/soc/msm/qdsp6v2/msm-compress-q6-v2.c
@@ -32,6 +32,7 @@
#include <asm/dma.h>
#include <linux/dma-mapping.h>
#include <linux/msm_audio_ion.h>
+#include <linux/msm_audio.h>
#include <sound/timer.h>
#include <sound/tlv.h>
@@ -302,6 +303,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)
{
@@ -709,21 +743,20 @@ static void compr_event_handler(uint32_t opcode,
spin_unlock_irqrestore(&prtd->lock, flags);
break;
case ASM_STREAM_PP_EVENT:
- pr_debug("%s: ASM_STREAM_PP_EVENT\n", __func__);
+ case ASM_STREAM_CMD_ENCDEC_EVENTS:
+ pr_debug("%s: ASM_STREAM_EVENT(0x%x)\n", __func__, opcode);
rtd = cstream->private_data;
if (!rtd) {
pr_err("%s: rtd is NULL\n", __func__);
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);
return;
}
-
break;
case ASM_DATA_EVENT_SR_CM_CHANGE_NOTIFY:
case ASM_DATA_EVENT_ENC_SR_CM_CHANGE_NOTIFY: {
@@ -1550,6 +1583,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 +1739,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 +2909,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;
@@ -3547,7 +3589,119 @@ static int msm_compr_adsp_stream_cmd_put(struct snd_kcontrol *kcontrol,
snd_soc_component_get_drvdata(comp);
struct snd_compr_stream *cstream = NULL;
struct msm_compr_audio *prtd;
- int ret = 0, param_length = 0;
+ int ret = 0;
+ struct msm_adsp_event_data *event_data = NULL;
+
+ if (fe_id >= MSM_FRONTEND_DAI_MAX) {
+ pr_err("%s Received invalid fe_id %lu\n",
+ __func__, fe_id);
+ ret = -EINVAL;
+ goto done;
+ }
+
+ cstream = pdata->cstream[fe_id];
+ if (cstream == NULL) {
+ pr_err("%s cstream is null\n", __func__);
+ ret = -EINVAL;
+ goto done;
+ }
+
+ prtd = cstream->runtime->private_data;
+ if (!prtd) {
+ pr_err("%s: prtd is null\n", __func__);
+ ret = -EINVAL;
+ goto done;
+ }
+
+ if (prtd->audio_client == NULL) {
+ pr_err("%s: audio_client is null\n", __func__);
+ ret = -EINVAL;
+ goto done;
+ }
+
+ event_data = (struct msm_adsp_event_data *)ucontrol->value.bytes.data;
+ if ((event_data->event_type < ADSP_STREAM_PP_EVENT) ||
+ (event_data->event_type >= ADSP_STREAM_EVENT_MAX)) {
+ pr_err("%s: invalid event_type=%d",
+ __func__, event_data->event_type);
+ ret = -EINVAL;
+ goto done;
+ }
+
+ if ((sizeof(struct msm_adsp_event_data) + event_data->payload_len) >=
+ sizeof(ucontrol->value.bytes.data)) {
+ pr_err("%s param length=%d exceeds limit",
+ __func__, event_data->payload_len);
+ ret = -EINVAL;
+ goto done;
+ }
+
+ ret = q6asm_send_stream_cmd(prtd->audio_client, event_data);
+ if (ret < 0)
+ pr_err("%s: failed to send stream event cmd, err = %d\n",
+ __func__, ret);
+done:
+ return ret;
+}
+
+static int msm_compr_ion_fd_map_put(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
+{
+ struct snd_soc_component *comp = snd_kcontrol_chip(kcontrol);
+ unsigned long fe_id = kcontrol->private_value;
+ struct msm_compr_pdata *pdata = (struct msm_compr_pdata *)
+ snd_soc_component_get_drvdata(comp);
+ struct snd_compr_stream *cstream = NULL;
+ struct msm_compr_audio *prtd;
+ int fd;
+ int ret = 0;
+
+ if (fe_id >= MSM_FRONTEND_DAI_MAX) {
+ pr_err("%s Received out of bounds invalid fe_id %lu\n",
+ __func__, fe_id);
+ ret = -EINVAL;
+ goto done;
+ }
+
+ cstream = pdata->cstream[fe_id];
+ if (cstream == NULL) {
+ pr_err("%s cstream is null\n", __func__);
+ ret = -EINVAL;
+ goto done;
+ }
+
+ prtd = cstream->runtime->private_data;
+ if (!prtd) {
+ pr_err("%s: prtd is null\n", __func__);
+ ret = -EINVAL;
+ goto done;
+ }
+
+ if (prtd->audio_client == NULL) {
+ pr_err("%s: audio_client is null\n", __func__);
+ ret = -EINVAL;
+ goto done;
+ }
+
+ memcpy(&fd, ucontrol->value.bytes.data, sizeof(fd));
+ ret = q6asm_send_ion_fd(prtd->audio_client, fd);
+ if (ret < 0)
+ pr_err("%s: failed to register ion fd\n", __func__);
+done:
+ return ret;
+}
+
+static int msm_compr_rtic_event_ack_put(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
+{
+ struct snd_soc_component *comp = snd_kcontrol_chip(kcontrol);
+ unsigned long fe_id = kcontrol->private_value;
+ struct msm_compr_pdata *pdata = (struct msm_compr_pdata *)
+ snd_soc_component_get_drvdata(comp);
+ struct snd_compr_stream *cstream = NULL;
+ struct msm_compr_audio *prtd;
+ int ret = 0;
+ int param_length = 0;
if (fe_id >= MSM_FRONTEND_DAI_MAX) {
pr_err("%s Received invalid fe_id %lu\n",
@@ -3558,20 +3712,20 @@ static int msm_compr_adsp_stream_cmd_put(struct snd_kcontrol *kcontrol,
cstream = pdata->cstream[fe_id];
if (cstream == NULL) {
- pr_err("%s cstream is null.\n", __func__);
+ pr_err("%s cstream is null\n", __func__);
ret = -EINVAL;
goto done;
}
prtd = cstream->runtime->private_data;
if (!prtd) {
- pr_err("%s: prtd is null.\n", __func__);
+ pr_err("%s: prtd is null\n", __func__);
ret = -EINVAL;
goto done;
}
if (prtd->audio_client == NULL) {
- pr_err("%s: audio_client is null.\n", __func__);
+ pr_err("%s: audio_client is null\n", __func__);
ret = -EINVAL;
goto done;
}
@@ -3586,12 +3740,11 @@ static int msm_compr_adsp_stream_cmd_put(struct snd_kcontrol *kcontrol,
goto done;
}
- ret = q6asm_send_stream_cmd(prtd->audio_client,
- ASM_STREAM_CMD_REGISTER_PP_EVENTS,
+ ret = q6asm_send_rtic_event_ack(prtd->audio_client,
ucontrol->value.bytes.data + sizeof(param_length),
param_length);
if (ret < 0)
- pr_err("%s: failed to register pp event. err = %d\n",
+ pr_err("%s: failed to send rtic event ack, err = %d\n",
__func__, ret);
done:
return ret;
@@ -3937,7 +4090,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 +4130,7 @@ static int msm_compr_add_audio_adsp_stream_callback_control(
}
kctl->private_data = NULL;
+
free_mixer_str:
kfree(mixer_str);
done:
@@ -4165,6 +4318,96 @@ static int msm_compr_add_channel_map_control(struct snd_soc_pcm_runtime *rtd)
return 0;
}
+static int msm_compr_add_io_fd_cmd_control(struct snd_soc_pcm_runtime *rtd)
+{
+ const char *mixer_ctl_name = "Playback ION FD";
+ const char *deviceNo = "NN";
+ char *mixer_str = NULL;
+ int ctl_len = 0, ret = 0;
+ struct snd_kcontrol_new fe_ion_fd_config_control[1] = {
+ {
+ .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
+ .name = "?",
+ .access = SNDRV_CTL_ELEM_ACCESS_READWRITE,
+ .info = msm_adsp_stream_cmd_info,
+ .put = msm_compr_ion_fd_map_put,
+ .private_value = 0,
+ }
+ };
+
+ if (!rtd) {
+ pr_err("%s NULL rtd\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 = -ENOMEM;
+ goto done;
+ }
+
+ snprintf(mixer_str, ctl_len, "%s %d", mixer_ctl_name, rtd->pcm->device);
+ fe_ion_fd_config_control[0].name = mixer_str;
+ fe_ion_fd_config_control[0].private_value = rtd->dai_link->be_id;
+ pr_debug("%s: Registering new mixer ctl %s\n", __func__, mixer_str);
+ ret = snd_soc_add_platform_controls(rtd->platform,
+ fe_ion_fd_config_control,
+ ARRAY_SIZE(fe_ion_fd_config_control));
+ if (ret < 0)
+ pr_err("%s: failed to add ctl %s\n", __func__, mixer_str);
+
+ kfree(mixer_str);
+done:
+ return ret;
+}
+
+static int msm_compr_add_event_ack_cmd_control(struct snd_soc_pcm_runtime *rtd)
+{
+ const char *mixer_ctl_name = "Playback Event Ack";
+ const char *deviceNo = "NN";
+ char *mixer_str = NULL;
+ int ctl_len = 0, ret = 0;
+ struct snd_kcontrol_new fe_event_ack_config_control[1] = {
+ {
+ .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
+ .name = "?",
+ .access = SNDRV_CTL_ELEM_ACCESS_READWRITE,
+ .info = msm_adsp_stream_cmd_info,
+ .put = msm_compr_rtic_event_ack_put,
+ .private_value = 0,
+ }
+ };
+
+ if (!rtd) {
+ pr_err("%s NULL rtd\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 = -ENOMEM;
+ goto done;
+ }
+
+ snprintf(mixer_str, ctl_len, "%s %d", mixer_ctl_name, rtd->pcm->device);
+ fe_event_ack_config_control[0].name = mixer_str;
+ fe_event_ack_config_control[0].private_value = rtd->dai_link->be_id;
+ pr_debug("%s: Registering new mixer ctl %s\n", __func__, mixer_str);
+ ret = snd_soc_add_platform_controls(rtd->platform,
+ fe_event_ack_config_control,
+ ARRAY_SIZE(fe_event_ack_config_control));
+ if (ret < 0)
+ pr_err("%s: failed to add ctl %s\n", __func__, mixer_str);
+
+ kfree(mixer_str);
+done:
+ return ret;
+}
+
static int msm_compr_new(struct snd_soc_pcm_runtime *rtd)
{
int rc;
@@ -4188,6 +4431,16 @@ static int msm_compr_new(struct snd_soc_pcm_runtime *rtd)
pr_err("%s: Could not add Compr ADSP Stream Callback Control\n",
__func__);
+ rc = msm_compr_add_io_fd_cmd_control(rtd);
+ if (rc)
+ pr_err("%s: Could not add Compr ion fd Control\n",
+ __func__);
+
+ rc = msm_compr_add_event_ack_cmd_control(rtd);
+ if (rc)
+ pr_err("%s: Could not add Compr event ack Control\n",
+ __func__);
+
rc = msm_compr_add_query_audio_effect_control(rtd);
if (rc)
pr_err("%s: Could not add Compr Query Audio Effect Control\n",
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..64b1961794b9 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",
@@ -4952,6 +5026,44 @@ static struct platform_driver msm_dai_q6_spdif_driver = {
},
};
+static int msm_dai_q6_tdm_set_clk_param(u32 group_id,
+ struct afe_clk_set *clk_set, u32 mode)
+{
+ switch (group_id) {
+ case AFE_GROUP_DEVICE_ID_PRIMARY_TDM_RX:
+ case AFE_GROUP_DEVICE_ID_PRIMARY_TDM_TX:
+ if (mode)
+ clk_set->clk_id = Q6AFE_LPASS_CLK_ID_PRI_TDM_IBIT;
+ else
+ clk_set->clk_id = Q6AFE_LPASS_CLK_ID_PRI_TDM_EBIT;
+ break;
+ case AFE_GROUP_DEVICE_ID_SECONDARY_TDM_RX:
+ case AFE_GROUP_DEVICE_ID_SECONDARY_TDM_TX:
+ if (mode)
+ clk_set->clk_id = Q6AFE_LPASS_CLK_ID_SEC_TDM_IBIT;
+ else
+ clk_set->clk_id = Q6AFE_LPASS_CLK_ID_SEC_TDM_EBIT;
+ break;
+ case AFE_GROUP_DEVICE_ID_TERTIARY_TDM_RX:
+ case AFE_GROUP_DEVICE_ID_TERTIARY_TDM_TX:
+ if (mode)
+ clk_set->clk_id = Q6AFE_LPASS_CLK_ID_TER_TDM_IBIT;
+ else
+ clk_set->clk_id = Q6AFE_LPASS_CLK_ID_TER_TDM_EBIT;
+ break;
+ case AFE_GROUP_DEVICE_ID_QUATERNARY_TDM_RX:
+ case AFE_GROUP_DEVICE_ID_QUATERNARY_TDM_TX:
+ if (mode)
+ clk_set->clk_id = Q6AFE_LPASS_CLK_ID_QUAD_TDM_IBIT;
+ else
+ clk_set->clk_id = Q6AFE_LPASS_CLK_ID_QUAD_TDM_EBIT;
+ break;
+ default:
+ return -EINVAL;
+ }
+ return 0;
+}
+
static int msm_dai_tdm_q6_probe(struct platform_device *pdev)
{
int rc = 0;
@@ -4959,6 +5071,7 @@ static int msm_dai_tdm_q6_probe(struct platform_device *pdev)
uint32_t array_length = 0;
int i = 0;
int group_idx = 0;
+ u32 clk_mode = 0;
/* extract tdm group info into static */
rc = of_property_read_u32(pdev->dev.of_node,
@@ -5031,6 +5144,26 @@ static int msm_dai_tdm_q6_probe(struct platform_device *pdev)
dev_dbg(&pdev->dev, "%s: Clk Rate from DT file %d\n",
__func__, tdm_clk_set.clk_freq_in_hz);
+ /* extract tdm clk src master/slave info into static */
+ rc = of_property_read_u32(pdev->dev.of_node,
+ "qcom,msm-cpudai-tdm-clk-internal",
+ &clk_mode);
+ if (rc) {
+ dev_err(&pdev->dev, "%s: Clk id from DT file %s\n",
+ __func__, "qcom,msm-cpudai-tdm-clk-internal");
+ goto rtn;
+ }
+ dev_dbg(&pdev->dev, "%s: Clk id from DT file %d\n",
+ __func__, clk_mode);
+
+ rc = msm_dai_q6_tdm_set_clk_param(tdm_group_cfg.group_id,
+ &tdm_clk_set, clk_mode);
+ if (rc) {
+ dev_err(&pdev->dev, "%s: group id not supported 0x%x\n",
+ __func__, tdm_group_cfg.group_id);
+ goto rtn;
+ }
+
/* other initializations within device group */
group_idx = msm_dai_q6_get_group_idx(tdm_group_cfg.group_id);
if (group_idx < 0) {
@@ -5826,48 +5959,6 @@ static int msm_dai_q6_tdm_set_clk(
{
int rc = 0;
- switch (dai_data->group_cfg.tdm_cfg.group_id) {
- case AFE_GROUP_DEVICE_ID_PRIMARY_TDM_RX:
- case AFE_GROUP_DEVICE_ID_PRIMARY_TDM_TX:
- if (dai_data->clk_set.clk_freq_in_hz) {
- dai_data->clk_set.clk_id =
- Q6AFE_LPASS_CLK_ID_PRI_TDM_IBIT;
- } else
- dai_data->clk_set.clk_id =
- Q6AFE_LPASS_CLK_ID_PRI_TDM_EBIT;
- break;
- case AFE_GROUP_DEVICE_ID_SECONDARY_TDM_RX:
- case AFE_GROUP_DEVICE_ID_SECONDARY_TDM_TX:
- if (dai_data->clk_set.clk_freq_in_hz) {
- dai_data->clk_set.clk_id =
- Q6AFE_LPASS_CLK_ID_SEC_TDM_IBIT;
- } else
- dai_data->clk_set.clk_id =
- Q6AFE_LPASS_CLK_ID_SEC_TDM_EBIT;
- break;
- case AFE_GROUP_DEVICE_ID_TERTIARY_TDM_RX:
- case AFE_GROUP_DEVICE_ID_TERTIARY_TDM_TX:
- if (dai_data->clk_set.clk_freq_in_hz) {
- dai_data->clk_set.clk_id =
- Q6AFE_LPASS_CLK_ID_TER_TDM_IBIT;
- } else
- dai_data->clk_set.clk_id =
- Q6AFE_LPASS_CLK_ID_TER_TDM_EBIT;
- break;
- case AFE_GROUP_DEVICE_ID_QUATERNARY_TDM_RX:
- case AFE_GROUP_DEVICE_ID_QUATERNARY_TDM_TX:
- if (dai_data->clk_set.clk_freq_in_hz) {
- dai_data->clk_set.clk_id =
- Q6AFE_LPASS_CLK_ID_QUAD_TDM_IBIT;
- } else
- dai_data->clk_set.clk_id =
- Q6AFE_LPASS_CLK_ID_QUAD_TDM_EBIT;
- break;
- default:
- pr_err("%s: port id 0x%x not supported\n",
- __func__, port_id);
- return -EINVAL;
- }
dai_data->clk_set.enable = enable;
rc = afe_set_lpass_clock_v2(port_id,
@@ -7856,6 +7947,7 @@ static int msm_dai_q6_tdm_dev_probe(struct platform_device *pdev)
int rc = 0;
u32 tdm_dev_id = 0;
int port_idx = 0;
+ struct device_node *tdm_parent_node = NULL;
/* retrieve device/afe id */
rc = of_property_read_u32(pdev->dev.of_node,
@@ -7890,7 +7982,8 @@ static int msm_dai_q6_tdm_dev_probe(struct platform_device *pdev)
memset(dai_data, 0, sizeof(*dai_data));
/* TDM CFG */
- rc = of_property_read_u32(pdev->dev.of_node,
+ tdm_parent_node = of_get_parent(pdev->dev.of_node);
+ rc = of_property_read_u32(tdm_parent_node,
"qcom,msm-cpudai-tdm-sync-mode",
(u32 *)&dai_data->port_cfg.tdm.sync_mode);
if (rc) {
@@ -7901,7 +7994,7 @@ static int msm_dai_q6_tdm_dev_probe(struct platform_device *pdev)
dev_dbg(&pdev->dev, "%s: Sync Mode from DT file 0x%x\n",
__func__, dai_data->port_cfg.tdm.sync_mode);
- rc = of_property_read_u32(pdev->dev.of_node,
+ rc = of_property_read_u32(tdm_parent_node,
"qcom,msm-cpudai-tdm-sync-src",
(u32 *)&dai_data->port_cfg.tdm.sync_src);
if (rc) {
@@ -7912,7 +8005,7 @@ static int msm_dai_q6_tdm_dev_probe(struct platform_device *pdev)
dev_dbg(&pdev->dev, "%s: Sync Src from DT file 0x%x\n",
__func__, dai_data->port_cfg.tdm.sync_src);
- rc = of_property_read_u32(pdev->dev.of_node,
+ rc = of_property_read_u32(tdm_parent_node,
"qcom,msm-cpudai-tdm-data-out",
(u32 *)&dai_data->port_cfg.tdm.ctrl_data_out_enable);
if (rc) {
@@ -7923,7 +8016,7 @@ static int msm_dai_q6_tdm_dev_probe(struct platform_device *pdev)
dev_dbg(&pdev->dev, "%s: Data Out from DT file 0x%x\n",
__func__, dai_data->port_cfg.tdm.ctrl_data_out_enable);
- rc = of_property_read_u32(pdev->dev.of_node,
+ rc = of_property_read_u32(tdm_parent_node,
"qcom,msm-cpudai-tdm-invert-sync",
(u32 *)&dai_data->port_cfg.tdm.ctrl_invert_sync_pulse);
if (rc) {
@@ -7934,7 +8027,7 @@ static int msm_dai_q6_tdm_dev_probe(struct platform_device *pdev)
dev_dbg(&pdev->dev, "%s: Invert Sync from DT file 0x%x\n",
__func__, dai_data->port_cfg.tdm.ctrl_invert_sync_pulse);
- rc = of_property_read_u32(pdev->dev.of_node,
+ rc = of_property_read_u32(tdm_parent_node,
"qcom,msm-cpudai-tdm-data-delay",
(u32 *)&dai_data->port_cfg.tdm.ctrl_sync_data_delay);
if (rc) {
diff --git a/sound/soc/msm/qdsp6v2/msm-pcm-q6-v2.c b/sound/soc/msm/qdsp6v2/msm-pcm-q6-v2.c
index 73eadfa4eebb..3be6567aefab 100644
--- a/sound/soc/msm/qdsp6v2/msm-pcm-q6-v2.c
+++ b/sound/soc/msm/qdsp6v2/msm-pcm-q6-v2.c
@@ -30,6 +30,7 @@
#include <asm/dma.h>
#include <linux/dma-mapping.h>
#include <linux/msm_audio_ion.h>
+#include <linux/msm_audio.h>
#include <linux/of_device.h>
#include <sound/tlv.h>
@@ -226,8 +227,9 @@ static void event_handler(uint32_t opcode,
}
break;
}
- case ASM_STREAM_PP_EVENT: {
- pr_debug("%s: ASM_STREAM_PP_EVENT\n", __func__);
+ case ASM_STREAM_PP_EVENT:
+ case ASM_STREAM_CMD_ENCDEC_EVENTS: {
+ pr_debug("%s: ASM_STREAM_EVENT (0x%x)\n", __func__, opcode);
if (!substream) {
pr_err("%s: substream is NULL.\n", __func__);
return;
@@ -239,8 +241,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 +692,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 +835,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;
@@ -1074,7 +1077,8 @@ static int msm_pcm_adsp_stream_cmd_put(struct snd_kcontrol *kcontrol,
struct msm_plat_data *pdata = dev_get_drvdata(platform->dev);
struct snd_pcm_substream *substream;
struct msm_audio *prtd;
- int ret = 0, param_length = 0;
+ int ret = 0;
+ struct msm_adsp_event_data *event_data = NULL;
if (!pdata) {
pr_err("%s pdata is NULL\n", __func__);
@@ -1102,22 +1106,26 @@ static int msm_pcm_adsp_stream_cmd_put(struct snd_kcontrol *kcontrol,
goto done;
}
- memcpy(&param_length, ucontrol->value.bytes.data,
- sizeof(param_length));
- if ((param_length + sizeof(param_length))
- >= sizeof(ucontrol->value.bytes.data)) {
+ event_data = (struct msm_adsp_event_data *)ucontrol->value.bytes.data;
+ if ((event_data->event_type < ADSP_STREAM_PP_EVENT) ||
+ (event_data->event_type >= ADSP_STREAM_EVENT_MAX)) {
+ pr_err("%s: invalid event_type=%d",
+ __func__, event_data->event_type);
+ ret = -EINVAL;
+ goto done;
+ }
+
+ if ((sizeof(struct msm_adsp_event_data) + event_data->payload_len) >=
+ sizeof(ucontrol->value.bytes.data)) {
pr_err("%s param length=%d exceeds limit",
- __func__, param_length);
+ __func__, event_data->payload_len);
ret = -EINVAL;
goto done;
}
- ret = q6asm_send_stream_cmd(prtd->audio_client,
- ASM_STREAM_CMD_REGISTER_PP_EVENTS,
- ucontrol->value.bytes.data + sizeof(param_length),
- param_length);
+ ret = q6asm_send_stream_cmd(prtd->audio_client, event_data);
if (ret < 0)
- pr_err("%s: failed to register pp event. err = %d\n",
+ pr_err("%s: failed to send stream event cmd, err = %d\n",
__func__, ret);
done:
return ret;
@@ -1187,7 +1195,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 +1238,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-pcm-routing-v2.c b/sound/soc/msm/qdsp6v2/msm-pcm-routing-v2.c
index e199a6a0de0b..0f63fd6bbd00 100644
--- a/sound/soc/msm/qdsp6v2/msm-pcm-routing-v2.c
+++ b/sound/soc/msm/qdsp6v2/msm-pcm-routing-v2.c
@@ -8115,6 +8115,9 @@ static const struct snd_kcontrol_new primary_mi2s_rx_port_mixer_controls[] = {
SOC_SINGLE_EXT("SLIM_0_TX", MSM_BACKEND_DAI_PRI_MI2S_RX,
MSM_BACKEND_DAI_SLIMBUS_0_TX, 1, 0, msm_routing_get_port_mixer,
msm_routing_put_port_mixer),
+ SOC_SINGLE_EXT("SLIM_8_TX", MSM_BACKEND_DAI_PRI_MI2S_RX,
+ MSM_BACKEND_DAI_SLIMBUS_8_TX, 1, 0, msm_routing_get_port_mixer,
+ msm_routing_put_port_mixer),
};
static const struct snd_kcontrol_new usb_rx_port_mixer_controls[] = {
@@ -8145,6 +8148,9 @@ static const struct snd_kcontrol_new quat_mi2s_rx_port_mixer_controls[] = {
SOC_SINGLE_EXT("QUAT_MI2S_TX", MSM_BACKEND_DAI_QUATERNARY_MI2S_RX,
MSM_BACKEND_DAI_QUATERNARY_MI2S_TX, 1, 0, msm_routing_get_port_mixer,
msm_routing_put_port_mixer),
+ SOC_SINGLE_EXT("SLIM_8_TX", MSM_BACKEND_DAI_QUATERNARY_MI2S_RX,
+ MSM_BACKEND_DAI_SLIMBUS_8_TX, 1, 0, msm_routing_get_port_mixer,
+ msm_routing_put_port_mixer),
};
static const struct snd_kcontrol_new pri_tdm_rx_0_port_mixer_controls[] = {
@@ -9235,6 +9241,9 @@ static const struct snd_kcontrol_new tert_mi2s_rx_port_mixer_controls[] = {
SOC_SINGLE_EXT("SEC_MI2S_TX", MSM_BACKEND_DAI_TERTIARY_MI2S_RX,
MSM_BACKEND_DAI_SECONDARY_MI2S_TX, 1, 0, msm_routing_get_port_mixer,
msm_routing_put_port_mixer),
+ SOC_SINGLE_EXT("SLIM_8_TX", MSM_BACKEND_DAI_TERTIARY_MI2S_RX,
+ MSM_BACKEND_DAI_SLIMBUS_8_TX, 1, 0, msm_routing_get_port_mixer,
+ msm_routing_put_port_mixer),
};
static const struct snd_kcontrol_new sec_mi2s_rx_port_mixer_controls[] = {
@@ -9256,6 +9265,9 @@ static const struct snd_kcontrol_new sec_mi2s_rx_port_mixer_controls[] = {
SOC_SINGLE_EXT("INTERNAL_FM_TX", MSM_BACKEND_DAI_SECONDARY_MI2S_RX,
MSM_BACKEND_DAI_INT_FM_TX, 1, 0, msm_routing_get_port_mixer,
msm_routing_put_port_mixer),
+ SOC_SINGLE_EXT("SLIM_8_TX", MSM_BACKEND_DAI_SECONDARY_MI2S_RX,
+ MSM_BACKEND_DAI_SLIMBUS_8_TX, 1, 0, msm_routing_get_port_mixer,
+ msm_routing_put_port_mixer),
};
static const struct snd_kcontrol_new lsm1_mixer_controls[] = {
@@ -13881,6 +13893,7 @@ static const struct snd_soc_dapm_route intercon[] = {
{"PRI_MI2S_RX Port Mixer", "SLIM_0_TX", "SLIMBUS_0_TX"},
{"PRI_MI2S_RX Port Mixer", "INTERNAL_FM_TX", "INT_FM_TX"},
{"PRI_MI2S_RX Port Mixer", "INTERNAL_BT_SCO_TX", "INT_BT_SCO_TX"},
+ {"PRI_MI2S_RX Port Mixer", "SLIM_8_TX", "SLIMBUS_8_TX"},
{"PRI_MI2S_RX", NULL, "PRI_MI2S_RX Port Mixer"},
{"SEC_MI2S_RX Port Mixer", "PRI_MI2S_TX", "PRI_MI2S_TX"},
@@ -13889,6 +13902,7 @@ static const struct snd_soc_dapm_route intercon[] = {
{"SEC_MI2S_RX Port Mixer", "QUAT_MI2S_TX", "QUAT_MI2S_TX"},
{"SEC_MI2S_RX Port Mixer", "SLIM_0_TX", "SLIMBUS_0_TX"},
{"SEC_MI2S_RX Port Mixer", "INTERNAL_FM_TX", "INT_FM_TX"},
+ {"SEC_MI2S_RX Port Mixer", "SLIM_8_TX", "SLIMBUS_8_TX"},
{"SEC_MI2S_RX", NULL, "SEC_MI2S_RX Port Mixer"},
{"TERT_MI2S_RX Port Mixer", "PRI_MI2S_TX", "PRI_MI2S_TX"},
@@ -13896,6 +13910,7 @@ static const struct snd_soc_dapm_route intercon[] = {
{"TERT_MI2S_RX Port Mixer", "TERT_MI2S_TX", "TERT_MI2S_TX"},
{"TERT_MI2S_RX Port Mixer", "QUAT_MI2S_TX", "QUAT_MI2S_TX"},
{"TERT_MI2S_RX Port Mixer", "SLIM_0_TX", "SLIMBUS_0_TX"},
+ {"TERT_MI2S_RX Port Mixer", "SLIM_8_TX", "SLIMBUS_8_TX"},
{"TERT_MI2S_RX", NULL, "TERT_MI2S_RX Port Mixer"},
{"QUAT_MI2S_RX Port Mixer", "PRI_MI2S_TX", "PRI_MI2S_TX"},
@@ -13905,6 +13920,7 @@ static const struct snd_soc_dapm_route intercon[] = {
{"QUAT_MI2S_RX Port Mixer", "SLIM_0_TX", "SLIMBUS_0_TX"},
{"QUAT_MI2S_RX Port Mixer", "INTERNAL_FM_TX", "INT_FM_TX"},
{"QUAT_MI2S_RX Port Mixer", "AUX_PCM_UL_TX", "AUX_PCM_TX"},
+ {"QUAT_MI2S_RX Port Mixer", "SLIM_8_TX", "SLIMBUS_8_TX"},
{"QUAT_MI2S_RX", NULL, "QUAT_MI2S_RX Port Mixer"},
/* Backend Enablement */
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..50bad5c2e48c 100644
--- a/sound/soc/msm/qdsp6v2/q6asm.c
+++ b/sound/soc/msm/qdsp6v2/q6asm.c
@@ -155,6 +155,13 @@ static int out_cold_index;
static char *out_buffer;
static char *in_buffer;
+static uint32_t adsp_reg_event_opcode[] = {ASM_STREAM_CMD_REGISTER_PP_EVENTS,
+ ASM_STREAM_CMD_REGISTER_ENCDEC_EVENTS};
+
+static uint32_t adsp_raise_event_opcode[] = {ASM_STREAM_PP_EVENT,
+ ASM_STREAM_CMD_ENCDEC_EVENTS};
+
+
static inline void q6asm_set_flag_in_token(union asm_token_struct *asm_token,
int flag, int flag_offset)
{
@@ -1096,37 +1103,44 @@ fail:
return NULL;
}
-int q6asm_send_stream_cmd(struct audio_client *ac, uint32_t opcode,
- void *param, uint32_t params_length)
+int q6asm_send_stream_cmd(struct audio_client *ac,
+ struct msm_adsp_event_data *data)
{
char *asm_params = NULL;
struct apr_hdr hdr;
int sz, rc;
- if (!param || !ac) {
+ if (!data || !ac) {
pr_err("%s: %s is NULL\n", __func__,
- (!param) ? "param" : "ac");
+ (!data) ? "data" : "ac");
+ rc = -EINVAL;
+ goto done;
+ }
+
+ if (data->event_type >= ARRAY_SIZE(adsp_reg_event_opcode)) {
+ pr_err("%s: event %u out of boundary of array size of (%lu)\n",
+ __func__, data->event_type,
+ (long)ARRAY_SIZE(adsp_reg_event_opcode));
rc = -EINVAL;
goto done;
}
- sz = sizeof(struct apr_hdr) + params_length;
+ sz = sizeof(struct apr_hdr) + data->payload_len;
asm_params = kzalloc(sz, GFP_KERNEL);
if (!asm_params) {
rc = -ENOMEM;
goto done;
}
- q6asm_add_hdr_async(ac, &hdr, sizeof(struct apr_hdr) +
- params_length, TRUE);
+ q6asm_add_hdr_async(ac, &hdr, sz, TRUE);
atomic_set(&ac->cmd_state_pp, -1);
- hdr.opcode = opcode;
+ hdr.opcode = adsp_reg_event_opcode[data->event_type];
memcpy(asm_params, &hdr, sizeof(struct apr_hdr));
memcpy(asm_params + sizeof(struct apr_hdr),
- param, params_length);
+ data->payload, data->payload_len);
rc = apr_send_pkt(ac->apr, (uint32_t *) asm_params);
if (rc < 0) {
- pr_err("%s: audio adsp pp register failed\n", __func__);
+ pr_err("%s: stream event cmd apr pkt failed\n", __func__);
rc = -EINVAL;
goto fail_send_param;
}
@@ -1134,13 +1148,13 @@ int q6asm_send_stream_cmd(struct audio_client *ac, uint32_t opcode,
rc = wait_event_timeout(ac->cmd_wait,
(atomic_read(&ac->cmd_state_pp) >= 0), 1 * HZ);
if (!rc) {
- pr_err("%s: timeout, adsp pp register\n", __func__);
+ pr_err("%s: timeout for stream event cmd resp\n", __func__);
rc = -ETIMEDOUT;
goto fail_send_param;
}
if (atomic_read(&ac->cmd_state_pp) > 0) {
- pr_err("%s: DSP returned error[%s] adsp pp register\n",
+ pr_err("%s: DSP returned error[%s] for stream event cmd\n",
__func__, adsp_err_get_err_str(
atomic_read(&ac->cmd_state_pp)));
rc = adsp_err_get_lnx_err_code(
@@ -1675,7 +1689,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) {
@@ -1779,6 +1793,8 @@ static int32_t q6asm_callback(struct apr_client_data *data, void *priv)
case ASM_STREAM_CMD_OPEN_TRANSCODE_LOOPBACK:
case ASM_DATA_CMD_MEDIA_FMT_UPDATE_V2:
case ASM_STREAM_CMD_SET_ENCDEC_PARAM:
+ case ASM_STREAM_CMD_SET_ENCDEC_PARAM_V2:
+ case ASM_STREAM_CMD_REGISTER_ENCDEC_EVENTS:
case ASM_DATA_CMD_REMOVE_INITIAL_SILENCE:
case ASM_DATA_CMD_REMOVE_TRAILING_SILENCE:
case ASM_SESSION_CMD_REGISTER_FOR_RX_UNDERFLOW_EVENTS:
@@ -1793,7 +1809,9 @@ static int32_t q6asm_callback(struct apr_client_data *data, void *priv)
__func__, payload[0], payload[1]);
if (wakeup_flag) {
if (payload[0] ==
- ASM_STREAM_CMD_SET_PP_PARAMS_V2)
+ ASM_STREAM_CMD_SET_PP_PARAMS_V2
+ || payload[0] ==
+ ASM_STREAM_CMD_REGISTER_ENCDEC_EVENTS)
atomic_set(&ac->cmd_state_pp,
payload[1]);
else
@@ -1803,7 +1821,9 @@ static int32_t q6asm_callback(struct apr_client_data *data, void *priv)
}
return 0;
}
- if (payload[0] == ASM_STREAM_CMD_SET_PP_PARAMS_V2) {
+ if (payload[0] == ASM_STREAM_CMD_SET_PP_PARAMS_V2 ||
+ payload[0] ==
+ ASM_STREAM_CMD_REGISTER_ENCDEC_EVENTS) {
if (atomic_read(&ac->cmd_state_pp) &&
wakeup_flag) {
atomic_set(&ac->cmd_state_pp, 0);
@@ -2043,25 +2063,40 @@ static int32_t q6asm_callback(struct apr_client_data *data, void *priv)
q6asm_process_mtmx_get_param_rsp(ac, (void *) payload);
break;
case ASM_STREAM_PP_EVENT:
+ case ASM_STREAM_CMD_ENCDEC_EVENTS:
pr_debug("%s: ASM_STREAM_PP_EVENT payload[0][0x%x] payload[1][0x%x]",
__func__, payload[0], payload[1]);
+ for (i = 0; i < ARRAY_SIZE(adsp_raise_event_opcode); i++)
+ if (adsp_raise_event_opcode[i] == data->opcode)
+ break;
+
+ if (i >= ARRAY_SIZE(adsp_raise_event_opcode))
+ return 0;
+
/* 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),
- data->payload, payload_size);
+
+ pp_event_package->event_type = i;
+ 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 +2637,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 +2812,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;
@@ -6892,6 +6926,156 @@ fail_cmd:
return rc;
}
+int q6asm_send_ion_fd(struct audio_client *ac, int fd)
+{
+ struct ion_client *client;
+ struct ion_handle *handle;
+ ion_phys_addr_t paddr;
+ size_t pa_len = 0;
+ void *vaddr;
+ int ret;
+ int sz = 0;
+ struct avs_rtic_shared_mem_addr shm;
+
+ if (ac == NULL) {
+ pr_err("%s: APR handle NULL\n", __func__);
+ ret = -EINVAL;
+ goto fail_cmd;
+ }
+ if (ac->apr == NULL) {
+ pr_err("%s: AC APR handle NULL\n", __func__);
+ ret = -EINVAL;
+ goto fail_cmd;
+ }
+
+ ret = msm_audio_ion_import("audio_mem_client",
+ &client,
+ &handle,
+ fd,
+ NULL,
+ 0,
+ &paddr,
+ &pa_len,
+ &vaddr);
+ if (ret) {
+ pr_err("%s: audio ION import failed, rc = %d\n",
+ __func__, ret);
+ ret = -ENOMEM;
+ goto fail_cmd;
+ }
+ /* get payload length */
+ sz = sizeof(struct avs_rtic_shared_mem_addr);
+ q6asm_add_hdr_async(ac, &shm.hdr, sz, TRUE);
+ atomic_set(&ac->cmd_state, -1);
+ shm.shm_buf_addr_lsw = lower_32_bits(paddr);
+ shm.shm_buf_addr_msw = msm_audio_populate_upper_32_bits(paddr);
+ shm.buf_size = pa_len;
+ shm.shm_buf_num_regions = 1;
+ shm.shm_buf_mem_pool_id = ADSP_MEMORY_MAP_SHMEM8_4K_POOL;
+ shm.shm_buf_flag = 0x00;
+ shm.encdec.param_id = AVS_PARAM_ID_RTIC_SHARED_MEMORY_ADDR;
+ shm.encdec.param_size = sizeof(struct avs_rtic_shared_mem_addr) -
+ sizeof(struct apr_hdr) -
+ sizeof(struct asm_stream_cmd_set_encdec_param_v2);
+ shm.encdec.service_id = OUT;
+ shm.encdec.reserved = 0;
+ shm.map_region.shm_addr_lsw = shm.shm_buf_addr_lsw;
+ shm.map_region.shm_addr_msw = shm.shm_buf_addr_msw;
+ shm.map_region.mem_size_bytes = pa_len;
+ shm.hdr.opcode = ASM_STREAM_CMD_SET_ENCDEC_PARAM_V2;
+ ret = apr_send_pkt(ac->apr, (uint32_t *) &shm);
+ if (ret < 0) {
+ pr_err("%s: set-params send failed paramid[0x%x] rc %d\n",
+ __func__, shm.encdec.param_id, ret);
+ ret = -EINVAL;
+ goto fail_cmd;
+ }
+
+ ret = wait_event_timeout(ac->cmd_wait,
+ (atomic_read(&ac->cmd_state) >= 0), 1*HZ);
+ if (!ret) {
+ pr_err("%s: timeout, shm.encdec paramid[0x%x]\n", __func__,
+ shm.encdec.param_id);
+ ret = -ETIMEDOUT;
+ goto fail_cmd;
+ }
+ if (atomic_read(&ac->cmd_state) > 0) {
+ pr_err("%s: DSP returned error[%s] shm.encdec paramid[0x%x]\n",
+ __func__,
+ adsp_err_get_err_str(atomic_read(&ac->cmd_state)),
+ shm.encdec.param_id);
+ ret = adsp_err_get_lnx_err_code(atomic_read(&ac->cmd_state));
+ goto fail_cmd;
+ }
+ ret = 0;
+fail_cmd:
+ return ret;
+}
+
+int q6asm_send_rtic_event_ack(struct audio_client *ac,
+ void *param, uint32_t params_length)
+{
+ char *asm_params = NULL;
+ int sz, rc;
+ struct avs_param_rtic_event_ack ack;
+
+ if (!param || !ac) {
+ pr_err("%s: %s is NULL\n", __func__,
+ (!param) ? "param" : "ac");
+ rc = -EINVAL;
+ goto done;
+ }
+
+ sz = sizeof(struct avs_param_rtic_event_ack) + params_length;
+ asm_params = kzalloc(sz, GFP_KERNEL);
+ if (!asm_params) {
+ rc = -ENOMEM;
+ goto done;
+ }
+
+ q6asm_add_hdr_async(ac, &ack.hdr,
+ sizeof(struct avs_param_rtic_event_ack) +
+ params_length, TRUE);
+ atomic_set(&ac->cmd_state, -1);
+ ack.hdr.opcode = ASM_STREAM_CMD_SET_ENCDEC_PARAM_V2;
+ ack.encdec.param_id = AVS_PARAM_ID_RTIC_EVENT_ACK;
+ ack.encdec.param_size = params_length;
+ ack.encdec.reserved = 0;
+ ack.encdec.service_id = OUT;
+ memcpy(asm_params, &ack, sizeof(struct avs_param_rtic_event_ack));
+ memcpy(asm_params + sizeof(struct avs_param_rtic_event_ack),
+ param, params_length);
+ rc = apr_send_pkt(ac->apr, (uint32_t *) asm_params);
+ if (rc < 0) {
+ pr_err("%s: apr pkt failed for rtic event ack\n", __func__);
+ rc = -EINVAL;
+ goto fail_send_param;
+ }
+
+ rc = wait_event_timeout(ac->cmd_wait,
+ (atomic_read(&ac->cmd_state) >= 0), 1 * HZ);
+ if (!rc) {
+ pr_err("%s: timeout for rtic event ack cmd\n", __func__);
+ rc = -ETIMEDOUT;
+ goto fail_send_param;
+ }
+
+ if (atomic_read(&ac->cmd_state) > 0) {
+ pr_err("%s: DSP returned error[%s] for rtic event ack cmd\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_send_param;
+ }
+ rc = 0;
+
+fail_send_param:
+ kfree(asm_params);
+done:
+ return rc;
+}
+
int q6asm_set_softpause(struct audio_client *ac,
struct asm_softpause_params *pause_param)
{
@@ -8039,6 +8223,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 +8686,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/format.c b/sound/usb/format.c
index 2cc3b92f1fba..cb23dd1670b3 100644
--- a/sound/usb/format.c
+++ b/sound/usb/format.c
@@ -90,6 +90,11 @@ static u64 parse_audio_format_i_type(struct snd_usb_audio *chip,
sample_bytes = SUBSLOTSIZE_24_BIT;
break;
}
+
+ default:
+ usb_audio_err(chip, "%u:%d : Invalid wMaxPacketSize\n",
+ fp->iface, fp->altsetting);
+ return pcm_formats;
}
format = 1 << format;
break;
diff --git a/sound/usb/mixer.c b/sound/usb/mixer.c
index b9d9d2e99c78..70dfdd22102e 100644
--- a/sound/usb/mixer.c
+++ b/sound/usb/mixer.c
@@ -1632,6 +1632,10 @@ static int parse_audio_feature_unit(struct mixer_build *state, int unitid,
break;
}
break;
+
+ default:
+ usb_audio_err(state->chip, "Invalid unit %u\n", unitid);
+ return -EINVAL;
}
}
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;
diff --git a/sound/usb/usb_audio_qmi_svc.c b/sound/usb/usb_audio_qmi_svc.c
index 14ea2239fe11..28c5a3736a9c 100644
--- a/sound/usb/usb_audio_qmi_svc.c
+++ b/sound/usb/usb_audio_qmi_svc.c
@@ -497,6 +497,12 @@ static int prepare_qmi_response(struct snd_usb_substream *subs,
resp->usb_audio_subslot_size = SUBSLOTSIZE_24_BIT;
break;
}
+
+ default:
+ pr_err("%d: %u: Invalid wMaxPacketSize\n",
+ subs->interface, subs->altset_idx);
+ ret = -EINVAL;
+ goto err;
}
resp->usb_audio_subslot_size_valid = 1;
} else {