summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--Documentation/devicetree/bindings/gpu/adreno.txt1
-rw-r--r--Documentation/devicetree/bindings/platform/msm/qpnp-revid.txt2
-rw-r--r--Documentation/devicetree/bindings/regulator/qpnp-lcdb-regulator.txt7
-rw-r--r--Documentation/devicetree/bindings/soc/qcom/msm-early-cam.txt110
-rw-r--r--Documentation/devicetree/bindings/wcnss/wcnss-wlan.txt3
-rw-r--r--Makefile5
-rw-r--r--arch/arm/boot/dts/omap3-n900.dts2
-rw-r--r--arch/arm/boot/dts/qcom/apq8096pro-v1.1-auto-adp-lite.dts10
-rw-r--r--arch/arm/boot/dts/qcom/apq8098-v2.1-mediabox.dts4
-rw-r--r--arch/arm/boot/dts/qcom/msm-pm660.dtsi1
-rw-r--r--arch/arm/boot/dts/qcom/msm8996-agave-adp.dtsi98
-rw-r--r--arch/arm/boot/dts/qcom/msm8996-auto-cdp.dtsi98
-rw-r--r--arch/arm/boot/dts/qcom/msm8998-v2.dtsi2
-rw-r--r--arch/arm/boot/dts/qcom/msm8998.dtsi2
-rw-r--r--arch/arm/boot/dts/qcom/sdm630-camera-sensor-mtp.dtsi20
-rw-r--r--arch/arm/boot/dts/qcom/sdm660-camera-sensor-cdp.dtsi79
-rw-r--r--arch/arm/boot/dts/qcom/sdm660-camera-sensor-mtp.dtsi79
-rw-r--r--arch/arm/boot/dts/qcom/sdm660-mtp.dtsi10
-rw-r--r--arch/arm/boot/dts/qcom/sdm660-pinctrl.dtsi28
-rw-r--r--arch/arm/boot/dts/qcom/sdm660.dtsi10
-rw-r--r--arch/arm/boot/dts/qcom/vplatform-lfv-msm8996.dts76
-rw-r--r--arch/arm/configs/s3c2410_defconfig6
-rw-r--r--arch/arm64/boot/dts/xilinx/zynqmp-ep108.dts2
-rw-r--r--arch/arm64/boot/dts/xilinx/zynqmp.dtsi6
-rw-r--r--arch/arm64/configs/msmcortex-perf_defconfig1
-rw-r--r--arch/arm64/configs/msmcortex_defconfig1
-rw-r--r--arch/arm64/configs/sdm660-perf_defconfig2
-rw-r--r--arch/arm64/configs/sdm660_defconfig2
-rw-r--r--arch/arm64/include/asm/io.h4
-rw-r--r--arch/arm64/mm/fault.c8
-rw-r--r--arch/mips/include/asm/branch.h5
-rw-r--r--arch/mips/kernel/branch.c38
-rw-r--r--arch/mips/kernel/proc.c2
-rw-r--r--arch/mips/kernel/ptrace.c2
-rw-r--r--arch/mips/kernel/scall32-o32.S2
-rw-r--r--arch/mips/kernel/scall64-64.S2
-rw-r--r--arch/mips/kernel/scall64-n32.S2
-rw-r--r--arch/mips/kernel/scall64-o32.S2
-rw-r--r--arch/mips/kernel/syscall.c15
-rw-r--r--arch/mips/math-emu/cp1emu.c38
-rw-r--r--arch/openrisc/kernel/vmlinux.lds.S2
-rw-r--r--arch/powerpc/include/asm/atomic.h4
-rw-r--r--arch/powerpc/include/asm/reg.h2
-rw-r--r--arch/powerpc/include/asm/topology.h14
-rw-r--r--arch/powerpc/kernel/setup_64.c4
-rw-r--r--arch/powerpc/kvm/book3s_hv.c41
-rw-r--r--arch/powerpc/kvm/book3s_hv_rmhandlers.S41
-rw-r--r--arch/powerpc/lib/sstep.c19
-rw-r--r--arch/powerpc/platforms/pseries/reconfig.c1
-rw-r--r--arch/s390/include/asm/syscall.h6
-rw-r--r--arch/x86/include/asm/xen/hypercall.h3
-rw-r--r--arch/x86/kernel/acpi/boot.c8
-rw-r--r--arch/x86/kernel/apic/io_apic.c2
-rw-r--r--arch/x86/kernel/cpu/mcheck/mce_amd.c3
-rw-r--r--crypto/authencesn.c5
-rw-r--r--drivers/acpi/glue.c10
-rw-r--r--drivers/android/binder.c26
-rw-r--r--drivers/base/power/domain.c14
-rw-r--r--drivers/block/xen-blkback/blkback.c3
-rw-r--r--drivers/block/xen-blkback/xenbus.c8
-rw-r--r--drivers/bluetooth/btfm_slim.c14
-rw-r--r--drivers/bluetooth/btfm_slim_codec.c60
-rw-r--r--drivers/bluetooth/btfm_slim_wcn3990.c24
-rw-r--r--drivers/bluetooth/btfm_slim_wcn3990.h3
-rw-r--r--drivers/char/adsprpc.c16
-rw-r--r--drivers/char/ipmi/ipmi_msghandler.c5
-rw-r--r--drivers/char/ipmi/ipmi_ssif.c5
-rw-r--r--drivers/char/ipmi/ipmi_watchdog.c7
-rw-r--r--drivers/char/tpm/tpm-chip.c85
-rw-r--r--drivers/char/tpm/tpm-interface.c1
-rw-r--r--drivers/char/tpm/tpm-sysfs.c2
-rw-r--r--drivers/char/tpm/tpm.h5
-rw-r--r--drivers/clk/msm/clock-osm.c28
-rw-r--r--drivers/clk/qcom/clk-cpu-osm.c27
-rw-r--r--drivers/dma/ioat/hw.h2
-rw-r--r--drivers/dma/ioat/init.c11
-rw-r--r--drivers/dma/ti-dma-crossbar.c2
-rw-r--r--drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.c3
-rw-r--r--drivers/gpu/drm/drm_dp_mst_topology.c41
-rw-r--r--drivers/gpu/drm/msm/adreno/a5xx_gpu.c18
-rw-r--r--drivers/gpu/drm/msm/adreno/adreno_device.c3
-rw-r--r--drivers/gpu/drm/msm/msm_gem.h1
-rw-r--r--drivers/gpu/drm/msm/msm_gem_submit.c91
-rw-r--r--drivers/gpu/drm/msm/msm_gpu.c27
-rw-r--r--drivers/gpu/drm/msm/sde/sde_color_processing.c4
-rw-r--r--drivers/gpu/drm/msm/sde/sde_crtc.c9
-rw-r--r--drivers/gpu/drm/msm/sde/sde_splash.c98
-rw-r--r--drivers/gpu/drm/msm/sde/sde_splash.h10
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/subdev/bar/gf100.c2
-rw-r--r--drivers/gpu/drm/radeon/atombios_encoders.c13
-rw-r--r--drivers/gpu/drm/radeon/ci_dpm.c6
-rw-r--r--drivers/gpu/drm/rcar-du/rcar_du_crtc.c20
-rw-r--r--drivers/gpu/drm/rcar-du/rcar_du_crtc.h2
-rw-r--r--drivers/gpu/drm/rcar-du/rcar_du_drv.c185
-rw-r--r--drivers/gpu/drm/rcar-du/rcar_du_hdmicon.c11
-rw-r--r--drivers/gpu/drm/rcar-du/rcar_du_kms.c7
-rw-r--r--drivers/gpu/drm/rcar-du/rcar_du_lvdscon.c11
-rw-r--r--drivers/gpu/drm/rcar-du/rcar_du_vgacon.c11
-rw-r--r--drivers/gpu/drm/vmwgfx/vmwgfx_execbuf.c2
-rw-r--r--drivers/gpu/msm/adreno.c26
-rw-r--r--drivers/gpu/msm/kgsl_pwrctrl.h2
-rw-r--r--drivers/hid/hid-core.c1
-rw-r--r--drivers/hid/hid-ids.h3
-rw-r--r--drivers/iio/adc/qcom-rradc.c78
-rw-r--r--drivers/infiniband/core/cma.c2
-rw-r--r--drivers/infiniband/core/uverbs_cmd.c5
-rw-r--r--drivers/input/serio/i8042.c12
-rw-r--r--drivers/irqchip/irq-keystone.c28
-rw-r--r--drivers/irqchip/irq-mxs.c4
-rw-r--r--drivers/isdn/i4l/isdn_common.c1
-rw-r--r--drivers/isdn/i4l/isdn_net.c5
-rw-r--r--drivers/isdn/i4l/isdn_ppp.c2
-rw-r--r--drivers/leds/leds-qpnp.c29
-rw-r--r--drivers/mailbox/mailbox.c13
-rw-r--r--drivers/md/raid1.c5
-rw-r--r--drivers/md/raid5.c11
-rw-r--r--drivers/media/i2c/s5c73m3/s5c73m3-ctrls.c2
-rw-r--r--drivers/media/pci/cx88/cx88-cards.c9
-rw-r--r--drivers/media/pci/cx88/cx88-video.c2
-rw-r--r--drivers/media/platform/msm/ais/fd/msm_fd_dev.c21
-rw-r--r--drivers/media/platform/msm/ais/fd/msm_fd_dev.h1
-rw-r--r--drivers/media/platform/msm/ais/sensor/cci/Makefile1
-rw-r--r--drivers/media/platform/msm/ais/sensor/cci/msm_early_cam.c279
-rw-r--r--drivers/media/platform/msm/ais/sensor/cci/msm_early_cam.h53
-rw-r--r--drivers/media/platform/msm/ais/sensor/msm_sensor_init.c33
-rw-r--r--drivers/media/platform/msm/camera_v2/sensor/ois/msm_ois.c2
-rw-r--r--drivers/media/platform/msm/vidc/msm_vidc.c17
-rw-r--r--drivers/media/platform/s5p-jpeg/jpeg-core.c8
-rw-r--r--drivers/media/rc/imon.c2
-rw-r--r--drivers/misc/enclosure.c14
-rw-r--r--drivers/net/can/spi/rh850.c2
-rw-r--r--drivers/net/ethernet/mellanox/mlx4/icm.c7
-rw-r--r--drivers/net/ethernet/realtek/r8169.c1
-rw-r--r--drivers/net/ethernet/renesas/sh_eth.c1
-rw-r--r--drivers/net/phy/phy_device.c2
-rw-r--r--drivers/net/usb/kaweth.c10
-rw-r--r--drivers/net/wireless/ath/ath10k/debug.c52
-rw-r--r--drivers/net/wireless/ath/ath10k/debug.h9
-rw-r--r--drivers/net/wireless/ath/ath10k/htt.h13
-rw-r--r--drivers/net/wireless/ath/ath10k/htt_rx.c1
-rw-r--r--drivers/net/wireless/ath/ath10k/hw.h10
-rw-r--r--drivers/net/wireless/ath/ath10k/mac.c12
-rw-r--r--drivers/net/wireless/ath/ath10k/wmi-ops.h6
-rw-r--r--drivers/net/wireless/ath/ath9k/ar9003_phy.c2
-rw-r--r--drivers/net/wireless/ath/ath9k/tx99.c13
-rw-r--r--drivers/net/wireless/cnss2/debug.c25
-rw-r--r--drivers/net/wireless/cnss2/main.c7
-rw-r--r--drivers/net/wireless/cnss2/main.h1
-rw-r--r--drivers/net/wireless/ti/wlcore/spi.c2
-rw-r--r--drivers/net/wireless/wcnss/wcnss_vreg.c177
-rw-r--r--drivers/net/wireless/wcnss/wcnss_wlan.c205
-rw-r--r--drivers/nfc/fdp/i2c.c6
-rw-r--r--drivers/nfc/nfcmrvl/fw_dnld.c7
-rw-r--r--drivers/nfc/nfcmrvl/main.c35
-rw-r--r--drivers/nfc/nfcmrvl/uart.c8
-rw-r--r--drivers/nvdimm/btt.c9
-rw-r--r--drivers/nvmem/imx-ocotp.c2
-rw-r--r--drivers/of/device.c2
-rw-r--r--drivers/pci/host/pci-msm.c10
-rw-r--r--drivers/pci/pci-driver.c1
-rw-r--r--drivers/platform/msm/gsi/gsi.c14
-rw-r--r--drivers/platform/msm/ipa/ipa_v3/ipa.c43
-rw-r--r--drivers/platform/msm/ipa/ipa_v3/ipahal/ipahal_reg.c17
-rw-r--r--drivers/platform/msm/ipa/ipa_v3/ipahal/ipahal_reg.h2
-rw-r--r--drivers/platform/msm/qpnp-revid.c11
-rw-r--r--drivers/platform/msm/usb_bam.c134
-rw-r--r--drivers/power/power_supply_sysfs.c3
-rw-r--r--drivers/power/supply/qcom/pmic-voter.c17
-rw-r--r--drivers/power/supply/qcom/qpnp-smb2.c65
-rw-r--r--drivers/power/supply/qcom/smb-lib.c117
-rw-r--r--drivers/power/supply/qcom/smb-lib.h21
-rw-r--r--drivers/power/supply/qcom/smb138x-charger.c70
-rw-r--r--drivers/pwm/pwm-qpnp.c67
-rw-r--r--drivers/regulator/qpnp-lcdb-regulator.c84
-rw-r--r--drivers/scsi/fnic/fnic.h1
-rw-r--r--drivers/scsi/fnic/fnic_scsi.c16
-rw-r--r--drivers/scsi/mpt3sas/mpt3sas_base.c33
-rw-r--r--drivers/scsi/snic/snic_main.c3
-rw-r--r--drivers/soc/qcom/glink_smem_native_xprt.c1
-rw-r--r--drivers/soc/qcom/icnss.c28
-rw-r--r--drivers/soc/qcom/qbt1000.c101
-rw-r--r--drivers/soc/qcom/scm_qcpe.c8
-rw-r--r--drivers/spi/spi-dw.c5
-rw-r--r--drivers/spmi/spmi.c12
-rw-r--r--drivers/staging/android/ion/ion.c16
-rw-r--r--drivers/staging/android/ion/ion_priv.h6
-rw-r--r--drivers/staging/android/lowmemorykiller.c4
-rw-r--r--drivers/staging/comedi/comedi_fops.c6
-rw-r--r--drivers/staging/rtl8188eu/os_dep/usb_intf.c1
-rw-r--r--drivers/target/iscsi/iscsi_target_configfs.c2
-rw-r--r--drivers/target/iscsi/iscsi_target_nego.c6
-rw-r--r--drivers/target/iscsi/iscsi_target_parameters.c41
-rw-r--r--drivers/target/iscsi/iscsi_target_parameters.h2
-rw-r--r--drivers/target/iscsi/iscsi_target_tpg.c19
-rw-r--r--drivers/target/iscsi/iscsi_target_tpg.h1
-rw-r--r--drivers/target/target_core_transport.c9
-rw-r--r--drivers/thermal/cpu_cooling.c4
-rw-r--r--drivers/usb/class/cdc-acm.c3
-rw-r--r--drivers/usb/dwc3/dwc3-msm.c35
-rw-r--r--drivers/usb/gadget/function/f_hid.c2
-rw-r--r--drivers/usb/host/xhci-hub.c3
-rw-r--r--drivers/usb/host/xhci-ring.c11
-rw-r--r--drivers/usb/pd/policy_engine.c52
-rw-r--r--drivers/usb/pd/qpnp-pdphy.c34
-rw-r--r--drivers/usb/pd/usbpd.h14
-rw-r--r--drivers/usb/phy/phy-msm-ssusb-qmp.c10
-rw-r--r--drivers/usb/renesas_usbhs/common.c4
-rw-r--r--drivers/usb/renesas_usbhs/mod_gadget.c31
-rw-r--r--drivers/usb/storage/isd200.c5
-rw-r--r--drivers/vfio/pci/vfio_pci.c4
-rw-r--r--drivers/vfio/pci/vfio_pci_rdwr.c5
-rw-r--r--drivers/vfio/vfio.c46
-rw-r--r--drivers/video/fbdev/cobalt_lcdfb.c5
-rw-r--r--drivers/video/fbdev/msm/mdss_hdmi_tx.c21
-rw-r--r--fs/btrfs/inode.c11
-rw-r--r--fs/ceph/dir.c5
-rw-r--r--fs/dcache.c27
-rw-r--r--fs/debugfs/inode.c10
-rw-r--r--fs/f2fs/acl.c2
-rw-r--r--fs/namei.c8
-rw-r--r--fs/nfs/dir.c12
-rw-r--r--fs/nfs/inode.c4
-rw-r--r--fs/notify/fsnotify.c8
-rw-r--r--fs/pstore/ram.c5
-rw-r--r--fs/pstore/ram_core.c25
-rw-r--r--fs/seq_file.c7
-rw-r--r--fs/udf/inode.c4
-rw-r--r--fs/xfs/xfs_aops.c21
-rw-r--r--include/linux/dcache.h6
-rw-r--r--include/linux/fsnotify.h31
-rw-r--r--include/linux/phy.h4
-rw-r--r--include/linux/power_supply.h3
-rw-r--r--include/linux/pstore_ram.h11
-rw-r--r--include/linux/qpnp/qpnp-revid.h1
-rw-r--r--include/linux/seq_file.h13
-rw-r--r--include/linux/usb_bam.h6
-rw-r--r--include/linux/vfio.h2
-rw-r--r--include/linux/wcnss_wlan.h3
-rw-r--r--include/sound/apr_audio-v2.h2
-rw-r--r--include/sound/q6asm-v2.h2
-rw-r--r--include/target/iscsi/iscsi_target_core.h9
-rw-r--r--include/trace/events/sched.h42
-rw-r--r--include/uapi/drm/msm_drm.h6
-rw-r--r--include/uapi/sound/compress_offload.h7
-rw-r--r--kernel/events/core.c21
-rw-r--r--kernel/fork.c3
-rw-r--r--kernel/resource.c13
-rw-r--r--kernel/sched/core.c14
-rw-r--r--kernel/sched/fair.c408
-rw-r--r--kernel/sched/walt.h2
-rw-r--r--kernel/time/alarmtimer.c3
-rw-r--r--kernel/trace/ftrace.c2
-rw-r--r--kernel/trace/trace.c1
-rw-r--r--net/8021q/vlan.c5
-rw-r--r--net/8021q/vlan.h2
-rw-r--r--net/8021q/vlan_dev.c20
-rw-r--r--net/bluetooth/smp.c35
-rw-r--r--net/core/dev.c19
-rw-r--r--net/ipv6/ip6_output.c2
-rw-r--r--net/key/af_key.c93
-rw-r--r--net/netfilter/ipvs/ip_vs_core.c19
-rw-r--r--net/nfc/core.c31
-rw-r--r--net/nfc/llcp_sock.c9
-rw-r--r--net/nfc/nci/core.c3
-rw-r--r--net/nfc/netlink.c4
-rw-r--r--net/xfrm/xfrm_policy.c9
-rw-r--r--sound/soc/codecs/nau8825.c3
-rw-r--r--sound/soc/codecs/nau8825.h3
-rw-r--r--sound/soc/codecs/tlv320aic3x.c13
-rw-r--r--sound/soc/codecs/wcd-dsp-mgr.c23
-rw-r--r--sound/soc/codecs/wcd934x/wcd934x-dsp-cntl.c9
-rw-r--r--sound/soc/msm/msm8998.c21
-rw-r--r--sound/soc/msm/qdsp6v2/msm-dai-q6-v2.c3
-rw-r--r--sound/soc/msm/qdsp6v2/msm-pcm-q6-v2.c12
-rw-r--r--sound/soc/msm/qdsp6v2/msm-pcm-routing-v2.c17
-rw-r--r--sound/soc/msm/qdsp6v2/msm-transcode-loopback-q6-v2.c301
-rw-r--r--sound/soc/msm/qdsp6v2/q6asm.c15
-rw-r--r--sound/usb/endpoint.c3
-rw-r--r--tools/lib/traceevent/plugin_sched_switch.c4
-rw-r--r--tools/perf/Makefile.perf4
-rw-r--r--tools/perf/ui/browser.c2
-rw-r--r--tools/perf/util/intel-pt-decoder/intel-pt-decoder.c116
-rw-r--r--tools/perf/util/intel-pt-decoder/intel-pt-pkt-decoder.c24
-rw-r--r--tools/perf/util/symbol-elf.c6
-rw-r--r--virt/kvm/vfio.c27
285 files changed, 4369 insertions, 1711 deletions
diff --git a/Documentation/devicetree/bindings/gpu/adreno.txt b/Documentation/devicetree/bindings/gpu/adreno.txt
index 32de5ce3da7e..80813dd1b3e5 100644
--- a/Documentation/devicetree/bindings/gpu/adreno.txt
+++ b/Documentation/devicetree/bindings/gpu/adreno.txt
@@ -93,6 +93,7 @@ Optional Properties:
- qcom,chipid: If it exists this property is used to replace
the chip identification read from the GPU hardware.
This is used to override faulty hardware readings.
+- qcom,disable-wake-on-touch: Boolean. Disables the GPU power up on a touch input event.
- qcom,disable-busy-time-burst:
Boolean. Disables the busy time burst to avoid switching
of power level for large frames based on the busy time limit.
diff --git a/Documentation/devicetree/bindings/platform/msm/qpnp-revid.txt b/Documentation/devicetree/bindings/platform/msm/qpnp-revid.txt
index babc4523a29a..dd14890123e6 100644
--- a/Documentation/devicetree/bindings/platform/msm/qpnp-revid.txt
+++ b/Documentation/devicetree/bindings/platform/msm/qpnp-revid.txt
@@ -9,6 +9,8 @@ Required properties:
Optional property:
- qcom,fab-id-valid: Use this property when support to read Fab
identification from REV ID peripheral is available.
+- qcom,tp-rev-valid: Use this property when support to read TP
+ revision identification from REV ID peripheral.
Example:
qcom,revid@100 {
diff --git a/Documentation/devicetree/bindings/regulator/qpnp-lcdb-regulator.txt b/Documentation/devicetree/bindings/regulator/qpnp-lcdb-regulator.txt
index ed383ce9ea8f..9798ac60b493 100644
--- a/Documentation/devicetree/bindings/regulator/qpnp-lcdb-regulator.txt
+++ b/Documentation/devicetree/bindings/regulator/qpnp-lcdb-regulator.txt
@@ -209,6 +209,12 @@ Properties below are specific to BOOST subnode only.
Definition: Current limit (in mA) of the BOOST rail.
Possible values are 200 to 1600mA in 200mA steps.
+- qcom,bst-headroom-mv
+ Usage: optional
+ Value type: <u16>
+ Definition: Headroom of the boost (in mV). The minimum headroom is
+ 200mV and if not specified defaults to 200mV.
+
=======
Example
=======
@@ -250,5 +256,6 @@ pm660l_lcdb: qpnp-lcdb@ec00 {
qcom,bst-pd-strength = <1>;
qcom,bst-ps = <1>;
qcom,bst-ps-threshold-ma = <50>;
+ qcom,bst-headroom-mv = <200>;
};
};
diff --git a/Documentation/devicetree/bindings/soc/qcom/msm-early-cam.txt b/Documentation/devicetree/bindings/soc/qcom/msm-early-cam.txt
new file mode 100644
index 000000000000..388426f44524
--- /dev/null
+++ b/Documentation/devicetree/bindings/soc/qcom/msm-early-cam.txt
@@ -0,0 +1,110 @@
+* Qualcomm Technologies Inc MSM BA
+
+[Root level node]
+==================
+Required properties:
+- compatible: Must be "qcom,early-cam".
+
+[Subnode]
+==========
+- qcom,early-cam-input-profile-#: Defines child nodes for the profiles supported
+ by early camera driver. Each profile should have properties
+ "mmagic-supply", "gdscr-supply", "vfe0-vdd-supply",
+ "qcom,cam-vreg-name", "clocks", "clock-names",
+ "qcom,clock-rates".
+Required properties:
+- mmagic-supply : should contain mmagic regulator used for mmagic clocks.
+- gdscr-supply : should contain gdsr regulator used for cci clocks.
+- vfe0-vdd-supply: phandle to vfe0 regulator.
+- qcom,cam-vreg-name : name of the voltage regulators required for the device.
+- clocks: List of clock handles. The parent clocks of the input clocks to the
+ devices in this power domain are set to oscclk before power gating
+ and restored back after powering on a domain. This is required for
+ all domains which are powered on and off and not required for unused
+ domains.
+- clock-names: name of the clock used by the driver.
+- qcom,clock-rates: clock rate in Hz.
+Example:
+
+ qcom,early-cam {
+ cell-index = <0>;
+ compatible = "qcom,early-cam";
+ status = "ok";
+ mmagic-supply = <&gdsc_mmagic_camss>;
+ gdscr-supply = <&gdsc_camss_top>;
+ vfe0-vdd-supply = <&gdsc_vfe0>;
+ qcom,cam-vreg-name = "mmagic", "gdscr", "vfe0-vdd";
+ clocks = <&clock_mmss clk_mmss_mmagic_ahb_clk>,
+ <&clock_mmss clk_camss_top_ahb_clk>,
+ <&clock_mmss clk_cci_clk_src>,
+ <&clock_mmss clk_camss_cci_ahb_clk>,
+ <&clock_mmss clk_camss_cci_clk>,
+ <&clock_mmss clk_camss_ahb_clk>,
+ <&clock_mmss clk_mmagic_camss_axi_clk>,
+ <&clock_mmss clk_camss_vfe_ahb_clk>,
+ <&clock_mmss clk_camss_vfe0_ahb_clk>,
+ <&clock_mmss clk_camss_vfe_axi_clk>,
+ <&clock_mmss clk_camss_vfe0_stream_clk>,
+ <&clock_mmss clk_smmu_vfe_axi_clk>,
+ <&clock_mmss clk_smmu_vfe_ahb_clk>,
+ <&clock_mmss clk_camss_csi_vfe0_clk>,
+ <&clock_mmss clk_vfe0_clk_src>,
+ <&clock_mmss clk_camss_csi_vfe0_clk>,
+ <&clock_mmss clk_camss_csi2_ahb_clk>,
+ <&clock_mmss clk_camss_csi2_clk>,
+ <&clock_mmss clk_camss_csi2phy_clk>,
+ <&clock_mmss clk_csi2phytimer_clk_src>,
+ <&clock_mmss clk_camss_csi2phytimer_clk>,
+ <&clock_mmss clk_camss_csi2rdi_clk>,
+ <&clock_mmss clk_camss_ispif_ahb_clk>,
+ <&clock_mmss clk_camss_vfe0_clk>;
+ clock-names =
+ "mmss_mmagic_ahb_clk",
+ "camss_top_ahb_clk",
+ "cci_clk_src",
+ "camss_cci_ahb_clk",
+ "camss_cci_clk",
+ "camss_ahb_clk",
+ "mmagic_camss_axi_clk",
+ "camss_vfe_ahb_clk",
+ "camss_vfe0_ahb_clk",
+ "camss_vfe_axi_clk",
+ "camss_vfe0_stream_clk",
+ "smmu_vfe_axi_clk",
+ "smmu_vfe_ahb_clk",
+ "camss_csi_vfe0_clk",
+ "vfe0_clk_src",
+ "camss_csi_vfe0_clk",
+ "camss_csi2_ahb_clk",
+ "camss_csi2_clk",
+ "camss_csi2phy_clk",
+ "csi2phytimer_clk_src",
+ "camss_csi2phytimer_clk",
+ "camss_csi2rdi_clk",
+ "camss_ispif_ahb_clk",
+ "clk_camss_vfe0_clk";
+
+ qcom,clock-rates = <19200000
+ 19200000
+ 19200000
+ 19200000
+ 19200000
+ 19200000
+ 0
+ 0
+ 0
+ 320000000
+ 0
+ 0
+ 0
+ 0
+ 19200000
+ 0
+ 0
+ 200000000
+ 200000000
+ 200000000
+ 200000000
+ 200000000
+ 0
+ };
diff --git a/Documentation/devicetree/bindings/wcnss/wcnss-wlan.txt b/Documentation/devicetree/bindings/wcnss/wcnss-wlan.txt
index 77d6bf06ee26..d0855115b6d1 100644
--- a/Documentation/devicetree/bindings/wcnss/wcnss-wlan.txt
+++ b/Documentation/devicetree/bindings/wcnss/wcnss-wlan.txt
@@ -64,8 +64,6 @@ support for pronto hardware.
to use for VBATT feature.
- qcom,has-a2xb-split-reg: boolean flag to determine A2xb split timeout limit
register is available or not.
-- qcom,wcn-external-gpio-support: boolean flag to determine 3.3v gpio support
-for pronto hardware for a target.
Example:
@@ -87,7 +85,6 @@ Example:
gpios = <&msmgpio 36 0>, <&msmgpio 37 0>, <&msmgpio 38 0>,
<&msmgpio 39 0>, <&msmgpio 40 0>;
- qcom,wcn-external-gpio-support;
qcom,has-48mhz-xo;
qcom,is-pronto-vt;
qcom,wlan-rx-buff-count = <512>;
diff --git a/Makefile b/Makefile
index ce92cd6345d7..dbb22cf9f76a 100644
--- a/Makefile
+++ b/Makefile
@@ -1,6 +1,6 @@
VERSION = 4
PATCHLEVEL = 4
-SUBLEVEL = 78
+SUBLEVEL = 80
EXTRAVERSION =
NAME = Blurry Fish Butt
@@ -623,6 +623,9 @@ include arch/$(SRCARCH)/Makefile
KBUILD_CFLAGS += $(call cc-option,-fno-delete-null-pointer-checks,)
KBUILD_CFLAGS += $(call cc-disable-warning,maybe-uninitialized,)
KBUILD_CFLAGS += $(call cc-disable-warning,frame-address,)
+KBUILD_CFLAGS += $(call cc-disable-warning, format-truncation)
+KBUILD_CFLAGS += $(call cc-disable-warning, format-overflow)
+KBUILD_CFLAGS += $(call cc-disable-warning, int-in-bool-context)
ifdef CONFIG_CC_OPTIMIZE_FOR_SIZE
KBUILD_CFLAGS += -Os
diff --git a/arch/arm/boot/dts/omap3-n900.dts b/arch/arm/boot/dts/omap3-n900.dts
index 5f5e0f3d5b64..27cd4abfc74d 100644
--- a/arch/arm/boot/dts/omap3-n900.dts
+++ b/arch/arm/boot/dts/omap3-n900.dts
@@ -697,6 +697,8 @@
vmmc_aux-supply = <&vsim>;
bus-width = <8>;
non-removable;
+ no-sdio;
+ no-sd;
};
&mmc3 {
diff --git a/arch/arm/boot/dts/qcom/apq8096pro-v1.1-auto-adp-lite.dts b/arch/arm/boot/dts/qcom/apq8096pro-v1.1-auto-adp-lite.dts
index 9f8d432a3112..082b04791dbd 100644
--- a/arch/arm/boot/dts/qcom/apq8096pro-v1.1-auto-adp-lite.dts
+++ b/arch/arm/boot/dts/qcom/apq8096pro-v1.1-auto-adp-lite.dts
@@ -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
@@ -42,6 +42,10 @@
i2c@75b6000 { /* BLSP8 */
/* ADV7533 HDMI Bridge Chip removed on ADP Lite */
+ adv7533@3d {
+ status = "disabled";
+ };
+
adv7533@39 {
status = "disabled";
};
@@ -60,6 +64,10 @@
/delete-property/ qcom,dsi-display-active;
};
+&sde_kms {
+ connectors = <&sde_hdmi_tx &sde_hdmi &dsi_adv_7533_1>;
+};
+
&pil_modem {
pinctrl-names = "default";
pinctrl-0 = <&modem_mux>;
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 bd29c0307576..1fa49d8a060d 100644
--- a/arch/arm/boot/dts/qcom/apq8098-v2.1-mediabox.dts
+++ b/arch/arm/boot/dts/qcom/apq8098-v2.1-mediabox.dts
@@ -101,6 +101,10 @@
status = "disabled";
};
+&pcie0 {
+ qcom,boot-option = <0x0>;
+};
+
&soc {
qcom,msm-dai-mi2s {
dai_mi2s3: qcom,msm-dai-q6-mi2s-quat {
diff --git a/arch/arm/boot/dts/qcom/msm-pm660.dtsi b/arch/arm/boot/dts/qcom/msm-pm660.dtsi
index 93aeef07cfe0..460e7e76ac4d 100644
--- a/arch/arm/boot/dts/qcom/msm-pm660.dtsi
+++ b/arch/arm/boot/dts/qcom/msm-pm660.dtsi
@@ -24,6 +24,7 @@
compatible = "qcom,qpnp-revid";
reg = <0x100 0x100>;
qcom,fab-id-valid;
+ qcom,tp-rev-valid;
};
pm660_misc: qcom,misc@900 {
diff --git a/arch/arm/boot/dts/qcom/msm8996-agave-adp.dtsi b/arch/arm/boot/dts/qcom/msm8996-agave-adp.dtsi
index 2dc5c919190c..1283cdddc2db 100644
--- a/arch/arm/boot/dts/qcom/msm8996-agave-adp.dtsi
+++ b/arch/arm/boot/dts/qcom/msm8996-agave-adp.dtsi
@@ -858,6 +858,90 @@
};
&soc {
+ qcom,early-cam {
+ cell-index = <0>;
+ compatible = "qcom,early-cam";
+ status = "ok";
+ mmagic-supply = <&gdsc_mmagic_camss>;
+ gdscr-supply = <&gdsc_camss_top>;
+ vfe0-vdd-supply = <&gdsc_vfe0>;
+ qcom,cam-vreg-name = "mmagic", "gdscr", "vfe0-vdd";
+ clocks = <&clock_mmss clk_mmss_mmagic_ahb_clk>,
+ <&clock_mmss clk_camss_top_ahb_clk>,
+ <&clock_mmss clk_cci_clk_src>,
+ <&clock_mmss clk_camss_cci_ahb_clk>,
+ <&clock_mmss clk_camss_cci_clk>,
+ <&clock_mmss clk_camss_ahb_clk>,
+ <&clock_mmss clk_mmagic_camss_axi_clk>,
+ <&clock_mmss clk_camss_vfe_ahb_clk>,
+ <&clock_mmss clk_camss_vfe0_ahb_clk>,
+ <&clock_mmss clk_camss_vfe_axi_clk>,
+ <&clock_mmss clk_camss_vfe0_stream_clk>,
+ <&clock_mmss clk_smmu_vfe_axi_clk>,
+ <&clock_mmss clk_smmu_vfe_ahb_clk>,
+ <&clock_mmss clk_camss_csi_vfe0_clk>,
+ <&clock_mmss clk_vfe0_clk_src>,
+ <&clock_mmss clk_camss_csi_vfe0_clk>,
+ <&clock_mmss clk_camss_csi2_ahb_clk>,
+ <&clock_mmss clk_camss_csi2_clk>,
+ <&clock_mmss clk_camss_csi2phy_clk>,
+ <&clock_mmss clk_csi2phytimer_clk_src>,
+ <&clock_mmss clk_camss_csi2phytimer_clk>,
+ <&clock_mmss clk_camss_csi2rdi_clk>,
+ <&clock_mmss clk_camss_ispif_ahb_clk>,
+ <&clock_mmss clk_camss_vfe0_clk>;
+ clock-names =
+ "mmss_mmagic_ahb_clk",
+ "camss_top_ahb_clk",
+ "cci_clk_src",
+ "camss_cci_ahb_clk",
+ "camss_cci_clk",
+ "camss_ahb_clk",
+ "mmagic_camss_axi_clk",
+ "camss_vfe_ahb_clk",
+ "camss_vfe0_ahb_clk",
+ "camss_vfe_axi_clk",
+ "camss_vfe0_stream_clk",
+ "smmu_vfe_axi_clk",
+ "smmu_vfe_ahb_clk",
+ "camss_csi_vfe0_clk",
+ "vfe0_clk_src",
+ "camss_csi_vfe0_clk",
+ "camss_csi2_ahb_clk",
+ "camss_csi2_clk",
+ "camss_csi2phy_clk",
+ "csi2phytimer_clk_src",
+ "camss_csi2phytimer_clk",
+ "camss_csi2rdi_clk",
+ "camss_ispif_ahb_clk",
+ "clk_camss_vfe0_clk";
+
+ qcom,clock-rates = <19200000
+ 19200000
+ 19200000
+ 19200000
+ 19200000
+ 19200000
+ 0
+ 0
+ 0
+ 320000000
+ 0
+ 0
+ 0
+ 0
+ 19200000
+ 0
+ 0
+ 200000000
+ 200000000
+ 200000000
+ 200000000
+ 200000000
+ 0
+ 100000000>;
+ };
+
qcom,ntn_avb {
compatible = "qcom,ntn_avb";
@@ -1457,11 +1541,21 @@
};
};
+&vfe_smmu {
+ qcom,no-smr-check;
+};
+
/ {
reserved-memory {
- lk_mem: lk_pool@91600000 {
- reg = <0x0 0x91600000 0x0 0x600000>;
+ lk_mem: lk_pool@0x91600000 {
+ no-map;
+ reg = <0 0x91600000 0 0x00600000>;
label = "lk_pool";
};
+
+ early_camera_mem: early_camera_mem@b3fff000 {
+ reg = <0 0xb3fff000 0 0x800000>;
+ label = "early_camera_mem";
+ };
};
};
diff --git a/arch/arm/boot/dts/qcom/msm8996-auto-cdp.dtsi b/arch/arm/boot/dts/qcom/msm8996-auto-cdp.dtsi
index 1d5e3035afd0..c3b986786034 100644
--- a/arch/arm/boot/dts/qcom/msm8996-auto-cdp.dtsi
+++ b/arch/arm/boot/dts/qcom/msm8996-auto-cdp.dtsi
@@ -623,6 +623,90 @@
};
&soc {
+ qcom,early-cam {
+ cell-index = <0>;
+ compatible = "qcom,early-cam";
+ status = "ok";
+ mmagic-supply = <&gdsc_mmagic_camss>;
+ gdscr-supply = <&gdsc_camss_top>;
+ vfe0-vdd-supply = <&gdsc_vfe0>;
+ qcom,cam-vreg-name = "mmagic", "gdscr", "vfe0-vdd";
+ clocks = <&clock_mmss clk_mmss_mmagic_ahb_clk>,
+ <&clock_mmss clk_camss_top_ahb_clk>,
+ <&clock_mmss clk_cci_clk_src>,
+ <&clock_mmss clk_camss_cci_ahb_clk>,
+ <&clock_mmss clk_camss_cci_clk>,
+ <&clock_mmss clk_camss_ahb_clk>,
+ <&clock_mmss clk_mmagic_camss_axi_clk>,
+ <&clock_mmss clk_camss_vfe_ahb_clk>,
+ <&clock_mmss clk_camss_vfe0_ahb_clk>,
+ <&clock_mmss clk_camss_vfe_axi_clk>,
+ <&clock_mmss clk_camss_vfe0_stream_clk>,
+ <&clock_mmss clk_smmu_vfe_axi_clk>,
+ <&clock_mmss clk_smmu_vfe_ahb_clk>,
+ <&clock_mmss clk_camss_csi_vfe0_clk>,
+ <&clock_mmss clk_vfe0_clk_src>,
+ <&clock_mmss clk_camss_csi_vfe0_clk>,
+ <&clock_mmss clk_camss_csi2_ahb_clk>,
+ <&clock_mmss clk_camss_csi2_clk>,
+ <&clock_mmss clk_camss_csi2phy_clk>,
+ <&clock_mmss clk_csi2phytimer_clk_src>,
+ <&clock_mmss clk_camss_csi2phytimer_clk>,
+ <&clock_mmss clk_camss_csi2rdi_clk>,
+ <&clock_mmss clk_camss_ispif_ahb_clk>,
+ <&clock_mmss clk_camss_vfe0_clk>;
+ clock-names =
+ "mmss_mmagic_ahb_clk",
+ "camss_top_ahb_clk",
+ "cci_clk_src",
+ "camss_cci_ahb_clk",
+ "camss_cci_clk",
+ "camss_ahb_clk",
+ "mmagic_camss_axi_clk",
+ "camss_vfe_ahb_clk",
+ "camss_vfe0_ahb_clk",
+ "camss_vfe_axi_clk",
+ "camss_vfe0_stream_clk",
+ "smmu_vfe_axi_clk",
+ "smmu_vfe_ahb_clk",
+ "camss_csi_vfe0_clk",
+ "vfe0_clk_src",
+ "camss_csi_vfe0_clk",
+ "camss_csi2_ahb_clk",
+ "camss_csi2_clk",
+ "camss_csi2phy_clk",
+ "csi2phytimer_clk_src",
+ "camss_csi2phytimer_clk",
+ "camss_csi2rdi_clk",
+ "camss_ispif_ahb_clk",
+ "clk_camss_vfe0_clk";
+
+ qcom,clock-rates = <19200000
+ 19200000
+ 19200000
+ 19200000
+ 19200000
+ 19200000
+ 0
+ 0
+ 0
+ 320000000
+ 0
+ 0
+ 0
+ 0
+ 19200000
+ 0
+ 0
+ 200000000
+ 200000000
+ 200000000
+ 200000000
+ 200000000
+ 0
+ 100000000>;
+ };
+
ntn1: ntn_avb@1 { /* Neutrno device on RC1*/
compatible = "qcom,ntn_avb";
@@ -1231,12 +1315,22 @@
/delete-property/ qcom,spkr-sd-n-gpio;
};
+&vfe_smmu {
+ qcom,no-smr-check;
+};
+
/ {
reserved-memory {
- lk_mem: lk_pool@91600000 {
- reg = <0x0 0x91600000 0x0 0x600000>;
+ lk_mem: lk_pool@0x91600000 {
+ no-map;
+ reg = <0 0x91600000 0 0x00600000>;
label = "lk_pool";
};
+
+ early_camera_mem: early_camera_mem@b3fff000 {
+ reg = <0 0xb3fff000 0 0x800000>;
+ label = "early_camera_mem";
+ };
};
};
diff --git a/arch/arm/boot/dts/qcom/msm8998-v2.dtsi b/arch/arm/boot/dts/qcom/msm8998-v2.dtsi
index b2f30de94bbc..acdd4bdcd95b 100644
--- a/arch/arm/boot/dts/qcom/msm8998-v2.dtsi
+++ b/arch/arm/boot/dts/qcom/msm8998-v2.dtsi
@@ -436,7 +436,7 @@
0x9ac 0x00 0x00
0x8a0 0x01 0x00
0x9e0 0x00 0x00
- 0x9dc 0x01 0x00
+ 0x9dc 0x20 0x00
0x9a8 0x00 0x00
0x8a4 0x01 0x00
0x8a8 0x73 0x00
diff --git a/arch/arm/boot/dts/qcom/msm8998.dtsi b/arch/arm/boot/dts/qcom/msm8998.dtsi
index 3f8962de22be..eafa6b841c17 100644
--- a/arch/arm/boot/dts/qcom/msm8998.dtsi
+++ b/arch/arm/boot/dts/qcom/msm8998.dtsi
@@ -2675,7 +2675,7 @@
0x9ac 0x00 0x00
0x8a0 0x01 0x00
0x9e0 0x00 0x00
- 0x9dc 0x01 0x00
+ 0x9dc 0x20 0x00
0x9a8 0x00 0x00
0x8a4 0x01 0x00
0x8a8 0x73 0x00
diff --git a/arch/arm/boot/dts/qcom/sdm630-camera-sensor-mtp.dtsi b/arch/arm/boot/dts/qcom/sdm630-camera-sensor-mtp.dtsi
index 0275016c9662..32a251f00550 100644
--- a/arch/arm/boot/dts/qcom/sdm630-camera-sensor-mtp.dtsi
+++ b/arch/arm/boot/dts/qcom/sdm630-camera-sensor-mtp.dtsi
@@ -114,6 +114,26 @@
status = "disabled";
};
+ tof0: qcom,tof@29{
+ cell-index = <0>;
+ reg = <0x29>;
+ compatible = "st,stmvl53l0";
+ qcom,cci-master = <0>;
+ cam_laser-supply = <&pm660l_l8>;
+ qcom,cam-vreg-name = "cam_laser";
+ qcom,cam-vreg-min-voltage = <2800000>;
+ qcom,cam-vreg-max-voltage = <3400000>;
+ qcom,cam-vreg-op-mode = <100000>;
+ pinctrl-names = "cam_default", "cam_suspend";
+ pinctrl-0 = <&cam_tof_active>;
+ pinctrl-1 = <&cam_tof_suspend>;
+ stm,irq-gpio = <&tlmm 45 0x2008>;
+ gpios = <&tlmm 42 0>;
+ qcom,gpio-req-tbl-num = <0>;
+ qcom,gpio-req-tbl-flags = <0>;
+ qcom,gpio-req-tbl-label = "RNG_EN";
+ };
+
eeprom0: qcom,eeprom@0 {
cell-index = <0>;
reg = <0>;
diff --git a/arch/arm/boot/dts/qcom/sdm660-camera-sensor-cdp.dtsi b/arch/arm/boot/dts/qcom/sdm660-camera-sensor-cdp.dtsi
index 46f77e9a3253..476fedec35a4 100644
--- a/arch/arm/boot/dts/qcom/sdm660-camera-sensor-cdp.dtsi
+++ b/arch/arm/boot/dts/qcom/sdm660-camera-sensor-cdp.dtsi
@@ -29,6 +29,16 @@
qcom,switch-source = <&pm660l_switch1>;
status = "ok";
};
+
+ cam_actuator_regulator: cam_actuator_fixed_regulator {
+ compatible = "regulator-fixed";
+ regulator-name = "cam_actuator_regulator";
+ regulator-min-microvolt = <3600000>;
+ regulator-max-microvolt = <3600000>;
+ enable-active-high;
+ gpio = <&tlmm 50 0>;
+ vin-supply = <&pm660l_bob>;
+ };
};
&cci {
@@ -37,14 +47,11 @@
reg = <0x0>;
compatible = "qcom,actuator";
qcom,cci-master = <0>;
- gpios = <&tlmm 50 0>;
- qcom,gpio-vaf = <0>;
- qcom,gpio-req-tbl-num = <0>;
- qcom,gpio-req-tbl-flags = <0>;
- qcom,gpio-req-tbl-label = "CAM_VAF";
- pinctrl-names = "cam_default", "cam_suspend";
- pinctrl-0 = <&cam_actuator_vaf_active>;
- pinctrl-1 = <&cam_actuator_vaf_suspend>;
+ cam_vaf-supply = <&cam_actuator_regulator>;
+ qcom,cam-vreg-name = "cam_vaf";
+ qcom,cam-vreg-min-voltage = <3600000>;
+ qcom,cam-vreg-max-voltage = <3600000>;
+ qcom,cam-vreg-op-mode = <0>;
};
actuator1: qcom,actuator@1 {
@@ -52,14 +59,11 @@
reg = <0x1>;
compatible = "qcom,actuator";
qcom,cci-master = <1>;
- gpios = <&tlmm 50 0>;
- qcom,gpio-vaf = <0>;
- qcom,gpio-req-tbl-num = <0>;
- qcom,gpio-req-tbl-flags = <0>;
- qcom,gpio-req-tbl-label = "CAM_VAF";
- pinctrl-names = "cam_default", "cam_suspend";
- pinctrl-0 = <&cam_actuator_vaf_active>;
- pinctrl-1 = <&cam_actuator_vaf_suspend>;
+ cam_vaf-supply = <&cam_actuator_regulator>;
+ qcom,cam-vreg-name = "cam_vaf";
+ qcom,cam-vreg-min-voltage = <3600000>;
+ qcom,cam-vreg-max-voltage = <3600000>;
+ qcom,cam-vreg-op-mode = <0>;
};
actuator2: qcom,actuator@2 {
@@ -67,14 +71,11 @@
reg = <0x2>;
compatible = "qcom,actuator";
qcom,cci-master = <1>;
- gpios = <&tlmm 50 0>;
- qcom,gpio-vaf = <0>;
- qcom,gpio-req-tbl-num = <0>;
- qcom,gpio-req-tbl-flags = <0>;
- qcom,gpio-req-tbl-label = "CAM_VAF";
- pinctrl-names = "cam_default", "cam_suspend";
- pinctrl-0 = <&cam_actuator_vaf_active>;
- pinctrl-1 = <&cam_actuator_vaf_suspend>;
+ cam_vaf-supply = <&cam_actuator_regulator>;
+ qcom,cam-vreg-name = "cam_vaf";
+ qcom,cam-vreg-min-voltage = <3600000>;
+ qcom,cam-vreg-max-voltage = <3600000>;
+ qcom,cam-vreg-op-mode = <0>;
};
ois0: qcom,ois@0 {
@@ -82,15 +83,31 @@
reg = <0x0>;
compatible = "qcom,ois";
qcom,cci-master = <0>;
- gpios = <&tlmm 50 0>;
- qcom,gpio-vaf = <0>;
+ cam_vaf-supply = <&cam_actuator_regulator>;
+ qcom,cam-vreg-name = "cam_vaf";
+ qcom,cam-vreg-min-voltage = <3600000>;
+ qcom,cam-vreg-max-voltage = <3600000>;
+ qcom,cam-vreg-op-mode = <0>;
+ status = "disabled";
+ };
+
+ tof0: qcom,tof@29{
+ cell-index = <0>;
+ reg = <0x29>;
+ compatible = "st,stmvl53l0";
+ qcom,cci-master = <0>;
+ cam_laser-supply = <&cam_actuator_regulator>;
+ qcom,cam-vreg-name = "cam_laser";
+ qcom,cam-vreg-min-voltage = <3600000>;
+ qcom,cam-vreg-max-voltage = <3600000>;
+ pinctrl-names = "cam_default", "cam_suspend";
+ pinctrl-0 = <&cam_tof_active>;
+ pinctrl-1 = <&cam_tof_suspend>;
+ stm,irq-gpio = <&tlmm 45 0x2008>;
+ gpios = <&tlmm 42 0>;
qcom,gpio-req-tbl-num = <0>;
qcom,gpio-req-tbl-flags = <0>;
- qcom,gpio-req-tbl-label = "CAM_VAF";
- pinctrl-names = "cam_default", "cam_suspend";
- pinctrl-0 = <&cam_actuator_vaf_active>;
- pinctrl-1 = <&cam_actuator_vaf_suspend>;
- status = "disabled";
+ qcom,gpio-req-tbl-label = "RNG_EN";
};
eeprom0: qcom,eeprom@0 {
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 94166bf8dd3e..11eb288804ff 100644
--- a/arch/arm/boot/dts/qcom/sdm660-camera-sensor-mtp.dtsi
+++ b/arch/arm/boot/dts/qcom/sdm660-camera-sensor-mtp.dtsi
@@ -40,6 +40,16 @@
vin-supply = <&pm660l_bob>;
};
+ cam_actuator_regulator: cam_actuator_fixed_regulator {
+ compatible = "regulator-fixed";
+ regulator-name = "cam_actuator_regulator";
+ regulator-min-microvolt = <3600000>;
+ regulator-max-microvolt = <3600000>;
+ enable-active-high;
+ gpio = <&tlmm 50 0>;
+ vin-supply = <&pm660l_bob>;
+ };
+
cam_dvdd_gpio_regulator: cam_dvdd_fixed_regulator {
compatible = "regulator-fixed";
regulator-name = "cam_dvdd_gpio_regulator";
@@ -67,14 +77,11 @@
reg = <0x0>;
compatible = "qcom,actuator";
qcom,cci-master = <0>;
- gpios = <&tlmm 50 0>;
- qcom,gpio-vaf = <0>;
- qcom,gpio-req-tbl-num = <0>;
- qcom,gpio-req-tbl-flags = <0>;
- qcom,gpio-req-tbl-label = "CAM_VAF";
- pinctrl-names = "cam_default", "cam_suspend";
- pinctrl-0 = <&cam_actuator_vaf_active>;
- pinctrl-1 = <&cam_actuator_vaf_suspend>;
+ cam_vaf-supply = <&cam_actuator_regulator>;
+ qcom,cam-vreg-name = "cam_vaf";
+ qcom,cam-vreg-min-voltage = <3600000>;
+ qcom,cam-vreg-max-voltage = <3600000>;
+ qcom,cam-vreg-op-mode = <0>;
};
actuator1: qcom,actuator@1 {
@@ -82,14 +89,11 @@
reg = <0x1>;
compatible = "qcom,actuator";
qcom,cci-master = <1>;
- gpios = <&tlmm 50 0>;
- qcom,gpio-vaf = <0>;
- qcom,gpio-req-tbl-num = <0>;
- qcom,gpio-req-tbl-flags = <0>;
- qcom,gpio-req-tbl-label = "CAM_VAF";
- pinctrl-names = "cam_default", "cam_suspend";
- pinctrl-0 = <&cam_actuator_vaf_active>;
- pinctrl-1 = <&cam_actuator_vaf_suspend>;
+ cam_vaf-supply = <&cam_actuator_regulator>;
+ qcom,cam-vreg-name = "cam_vaf";
+ qcom,cam-vreg-min-voltage = <3600000>;
+ qcom,cam-vreg-max-voltage = <3600000>;
+ qcom,cam-vreg-op-mode = <0>;
};
actuator2: qcom,actuator@2 {
@@ -97,14 +101,11 @@
reg = <0x2>;
compatible = "qcom,actuator";
qcom,cci-master = <1>;
- gpios = <&tlmm 50 0>;
- qcom,gpio-vaf = <0>;
- qcom,gpio-req-tbl-num = <0>;
- qcom,gpio-req-tbl-flags = <0>;
- qcom,gpio-req-tbl-label = "CAM_VAF";
- pinctrl-names = "cam_default", "cam_suspend";
- pinctrl-0 = <&cam_actuator_vaf_active>;
- pinctrl-1 = <&cam_actuator_vaf_suspend>;
+ cam_vaf-supply = <&cam_actuator_regulator>;
+ qcom,cam-vreg-name = "cam_vaf";
+ qcom,cam-vreg-min-voltage = <3600000>;
+ qcom,cam-vreg-max-voltage = <3600000>;
+ qcom,cam-vreg-op-mode = <0>;
};
ois0: qcom,ois@0 {
@@ -112,15 +113,31 @@
reg = <0x0>;
compatible = "qcom,ois";
qcom,cci-master = <0>;
- gpios = <&tlmm 50 0>;
- qcom,gpio-vaf = <0>;
+ cam_vaf-supply = <&cam_actuator_regulator>;
+ qcom,cam-vreg-name = "cam_vaf";
+ qcom,cam-vreg-min-voltage = <3600000>;
+ qcom,cam-vreg-max-voltage = <3600000>;
+ qcom,cam-vreg-op-mode = <0>;
+ status = "disabled";
+ };
+
+ tof0: qcom,tof@29{
+ cell-index = <0>;
+ reg = <0x29>;
+ compatible = "st,stmvl53l0";
+ qcom,cci-master = <0>;
+ cam_laser-supply = <&cam_actuator_regulator>;
+ qcom,cam-vreg-name = "cam_laser";
+ qcom,cam-vreg-min-voltage = <3600000>;
+ qcom,cam-vreg-max-voltage = <3600000>;
+ pinctrl-names = "cam_default", "cam_suspend";
+ pinctrl-0 = <&cam_tof_active>;
+ pinctrl-1 = <&cam_tof_suspend>;
+ stm,irq-gpio = <&tlmm 45 0x2008>;
+ gpios = <&tlmm 42 0>;
qcom,gpio-req-tbl-num = <0>;
qcom,gpio-req-tbl-flags = <0>;
- qcom,gpio-req-tbl-label = "CAM_VAF";
- pinctrl-names = "cam_default", "cam_suspend";
- pinctrl-0 = <&cam_actuator_vaf_active>;
- pinctrl-1 = <&cam_actuator_vaf_suspend>;
- status = "disabled";
+ qcom,gpio-req-tbl-label = "RNG_EN";
};
eeprom0: qcom,eeprom@0 {
diff --git a/arch/arm/boot/dts/qcom/sdm660-mtp.dtsi b/arch/arm/boot/dts/qcom/sdm660-mtp.dtsi
index 45b7201fbf71..50f5d83346c6 100644
--- a/arch/arm/boot/dts/qcom/sdm660-mtp.dtsi
+++ b/arch/arm/boot/dts/qcom/sdm660-mtp.dtsi
@@ -56,6 +56,16 @@
qcom,master-en = <1>;
status = "okay";
};
+
+ /* GPIO 11 for Home Key */
+ gpio@ca00 {
+ status = "okay";
+ qcom,mode = <0>;
+ qcom,pull = <0>;
+ qcom,vin-sel = <0>;
+ qcom,src-sel = <0>;
+ qcom,out-strength = <1>;
+ };
};
&i2c_6 { /* BLSP1 QUP6 (NFC) */
diff --git a/arch/arm/boot/dts/qcom/sdm660-pinctrl.dtsi b/arch/arm/boot/dts/qcom/sdm660-pinctrl.dtsi
index d902078b1048..e55a67e68b36 100644
--- a/arch/arm/boot/dts/qcom/sdm660-pinctrl.dtsi
+++ b/arch/arm/boot/dts/qcom/sdm660-pinctrl.dtsi
@@ -1101,6 +1101,34 @@
};
};
+ cam_tof_active: cam_tof_active {
+ /* LASER */
+ mux {
+ pins = "gpio50", "gpio42", "gpio45";
+ function = "gpio";
+ };
+
+ config {
+ pins = "gpio50", "gpio42", "gpio45";
+ bias-pull-up;
+ drive-strength = <2>; /* 2 MA */
+ };
+ };
+
+ cam_tof_suspend: cam_tof_suspend {
+ /* LASER */
+ mux {
+ pins = "gpio50", "gpio42", "gpio45";
+ function = "gpio";
+ };
+
+ config {
+ pins = "gpio50", "gpio42", "gpio45";
+ bias-pull-down; /* PULL DOWN */
+ drive-strength = <2>; /* 2 MA */
+ };
+ };
+
cam_sensor_mclk0_active: cam_sensor_mclk0_active {
/* MCLK0 */
mux {
diff --git a/arch/arm/boot/dts/qcom/sdm660.dtsi b/arch/arm/boot/dts/qcom/sdm660.dtsi
index 105cfe3fbdc4..e00753f8b3e7 100644
--- a/arch/arm/boot/dts/qcom/sdm660.dtsi
+++ b/arch/arm/boot/dts/qcom/sdm660.dtsi
@@ -672,6 +672,16 @@
clock-names = "core", "iface";
};
+ qcom,qbt1000 {
+ compatible = "qcom,qbt1000";
+ clock-names = "core", "iface";
+ clocks = <&clock_gcc GCC_BLSP1_QUP3_SPI_APPS_CLK>,
+ <&clock_gcc GCC_BLSP1_AHB_CLK>;
+ clock-frequency = <15000000>;
+ qcom,ipc-gpio = <&tlmm 72 0>;
+ qcom,finger-detect-gpio = <&pm660_gpios 11 0>;
+ };
+
qcom,sensor-information {
compatible = "qcom,sensor-information";
sensor_information0: qcom,sensor-information-0 {
diff --git a/arch/arm/boot/dts/qcom/vplatform-lfv-msm8996.dts b/arch/arm/boot/dts/qcom/vplatform-lfv-msm8996.dts
index 30b36c0ac541..5c0bbbccafea 100644
--- a/arch/arm/boot/dts/qcom/vplatform-lfv-msm8996.dts
+++ b/arch/arm/boot/dts/qcom/vplatform-lfv-msm8996.dts
@@ -300,6 +300,82 @@
};
};
+ qcom,msm-dai-tdm-pri-rx {
+ compatible = "qcom,msm-dai-tdm";
+ qcom,msm-cpudai-tdm-group-id = <37120>;
+ qcom,msm-cpudai-tdm-group-num-ports = <4>;
+ qcom,msm-cpudai-tdm-group-port-id = <36864 36866 36868 36870>;
+ 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 = <1>;
+ qcom,msm-cpudai-tdm-clk-attribute = /bits/ 16 <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-data-align = <0>;
+ };
+
+ dai_pri_tdm_rx_1: qcom,msm-dai-q6-tdm-pri-rx-1 {
+ compatible = "qcom,msm-dai-q6-tdm";
+ qcom,msm-cpudai-tdm-dev-id = <36866>;
+ qcom,msm-cpudai-tdm-data-align = <0>;
+ };
+
+ dai_pri_tdm_rx_2: qcom,msm-dai-q6-tdm-pri-rx-2 {
+ compatible = "qcom,msm-dai-q6-tdm";
+ qcom,msm-cpudai-tdm-dev-id = <36868>;
+ qcom,msm-cpudai-tdm-data-align = <0>;
+ };
+
+ dai_pri_tdm_rx_3: qcom,msm-dai-q6-tdm-pri-rx-3 {
+ compatible = "qcom,msm-dai-q6-tdm";
+ qcom,msm-cpudai-tdm-dev-id = <36870>;
+ qcom,msm-cpudai-tdm-data-align = <0>;
+ };
+ };
+
+ qcom,msm-dai-tdm-pri-tx {
+ compatible = "qcom,msm-dai-tdm";
+ qcom,msm-cpudai-tdm-group-id = <37121>;
+ qcom,msm-cpudai-tdm-group-num-ports = <4>;
+ qcom,msm-cpudai-tdm-group-port-id = <36865 36867 36869 36871>;
+ 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 = <1>;
+ qcom,msm-cpudai-tdm-clk-attribute = /bits/ 16 <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-data-align = <0>;
+ };
+
+ dai_pri_tdm_tx_1: qcom,msm-dai-q6-tdm-pri-tx-1 {
+ compatible = "qcom,msm-dai-q6-tdm";
+ qcom,msm-cpudai-tdm-dev-id = <36867>;
+ qcom,msm-cpudai-tdm-data-align = <0>;
+ };
+
+ dai_pri_tdm_tx_2: qcom,msm-dai-q6-tdm-pri-tx-2 {
+ compatible = "qcom,msm-dai-q6-tdm";
+ qcom,msm-cpudai-tdm-dev-id = <36869>;
+ qcom,msm-cpudai-tdm-data-align = <0>;
+ };
+
+ dai_pri_tdm_tx_3: qcom,msm-dai-q6-tdm-pri-tx-3 {
+ compatible = "qcom,msm-dai-q6-tdm";
+ qcom,msm-cpudai-tdm-dev-id = <36871>;
+ qcom,msm-cpudai-tdm-data-align = <0>;
+ };
+ };
+
qcom,msm-dai-tdm-sec-tx {
compatible = "qcom,msm-dai-tdm";
qcom,msm-cpudai-tdm-group-id = <37137>;
diff --git a/arch/arm/configs/s3c2410_defconfig b/arch/arm/configs/s3c2410_defconfig
index f3142369f594..01116ee1284b 100644
--- a/arch/arm/configs/s3c2410_defconfig
+++ b/arch/arm/configs/s3c2410_defconfig
@@ -87,9 +87,9 @@ CONFIG_IPV6_TUNNEL=m
CONFIG_NETFILTER=y
CONFIG_NF_CONNTRACK=m
CONFIG_NF_CONNTRACK_EVENTS=y
-CONFIG_NF_CT_PROTO_DCCP=m
-CONFIG_NF_CT_PROTO_SCTP=m
-CONFIG_NF_CT_PROTO_UDPLITE=m
+CONFIG_NF_CT_PROTO_DCCP=y
+CONFIG_NF_CT_PROTO_SCTP=y
+CONFIG_NF_CT_PROTO_UDPLITE=y
CONFIG_NF_CONNTRACK_AMANDA=m
CONFIG_NF_CONNTRACK_FTP=m
CONFIG_NF_CONNTRACK_H323=m
diff --git a/arch/arm64/boot/dts/xilinx/zynqmp-ep108.dts b/arch/arm64/boot/dts/xilinx/zynqmp-ep108.dts
index ce5d848251fa..7b34822d61e9 100644
--- a/arch/arm64/boot/dts/xilinx/zynqmp-ep108.dts
+++ b/arch/arm64/boot/dts/xilinx/zynqmp-ep108.dts
@@ -26,7 +26,7 @@
stdout-path = "serial0:115200n8";
};
- memory {
+ memory@0 {
device_type = "memory";
reg = <0x0 0x0 0x40000000>;
};
diff --git a/arch/arm64/boot/dts/xilinx/zynqmp.dtsi b/arch/arm64/boot/dts/xilinx/zynqmp.dtsi
index 857eda5c7217..172402cc1a0f 100644
--- a/arch/arm64/boot/dts/xilinx/zynqmp.dtsi
+++ b/arch/arm64/boot/dts/xilinx/zynqmp.dtsi
@@ -71,7 +71,7 @@
<1 10 0xf01>;
};
- amba_apu {
+ amba_apu: amba_apu@0 {
compatible = "simple-bus";
#address-cells = <2>;
#size-cells = <1>;
@@ -191,7 +191,7 @@
};
i2c0: i2c@ff020000 {
- compatible = "cdns,i2c-r1p10";
+ compatible = "cdns,i2c-r1p14", "cdns,i2c-r1p10";
status = "disabled";
interrupt-parent = <&gic>;
interrupts = <0 17 4>;
@@ -202,7 +202,7 @@
};
i2c1: i2c@ff030000 {
- compatible = "cdns,i2c-r1p10";
+ compatible = "cdns,i2c-r1p14", "cdns,i2c-r1p10";
status = "disabled";
interrupt-parent = <&gic>;
interrupts = <0 18 4>;
diff --git a/arch/arm64/configs/msmcortex-perf_defconfig b/arch/arm64/configs/msmcortex-perf_defconfig
index ac919d751145..e16fc58ce913 100644
--- a/arch/arm64/configs/msmcortex-perf_defconfig
+++ b/arch/arm64/configs/msmcortex-perf_defconfig
@@ -295,6 +295,7 @@ CONFIG_WCNSS_MEM_PRE_ALLOC=y
CONFIG_ATH_CARDS=y
CONFIG_WIL6210=m
CONFIG_CLD_LL_CORE=y
+CONFIG_CNSS_GENL=y
CONFIG_INPUT_EVDEV=y
CONFIG_INPUT_KEYRESET=y
CONFIG_KEYBOARD_GPIO=y
diff --git a/arch/arm64/configs/msmcortex_defconfig b/arch/arm64/configs/msmcortex_defconfig
index fe6cf23caeab..77157bb85ee1 100644
--- a/arch/arm64/configs/msmcortex_defconfig
+++ b/arch/arm64/configs/msmcortex_defconfig
@@ -296,6 +296,7 @@ CONFIG_WCNSS_MEM_PRE_ALLOC=y
CONFIG_ATH_CARDS=y
CONFIG_WIL6210=m
CONFIG_CLD_LL_CORE=y
+CONFIG_CNSS_GENL=y
CONFIG_INPUT_EVDEV=y
CONFIG_INPUT_KEYRESET=y
CONFIG_KEYBOARD_GPIO=y
diff --git a/arch/arm64/configs/sdm660-perf_defconfig b/arch/arm64/configs/sdm660-perf_defconfig
index 493ed7e14437..c92551c69bf8 100644
--- a/arch/arm64/configs/sdm660-perf_defconfig
+++ b/arch/arm64/configs/sdm660-perf_defconfig
@@ -300,6 +300,7 @@ CONFIG_INPUT_MISC=y
CONFIG_INPUT_HBTP_INPUT=y
CONFIG_INPUT_QPNP_POWER_ON=y
CONFIG_INPUT_UINPUT=y
+CONFIG_INPUT_STMVL53L0=y
# CONFIG_SERIO_SERPORT is not set
# CONFIG_VT is not set
# CONFIG_LEGACY_PTYS is not set
@@ -575,6 +576,7 @@ CONFIG_MSM_EVENT_TIMER=y
CONFIG_MSM_AVTIMER=y
CONFIG_QCOM_REMOTEQDSS=y
CONFIG_MSM_SERVICE_NOTIFIER=y
+CONFIG_MSM_QBT1000=y
CONFIG_MSM_RPM_RBCPR_STATS_V2_LOG=y
CONFIG_MSM_RPM_LOG=y
CONFIG_MSM_RPM_STATS_LOG=y
diff --git a/arch/arm64/configs/sdm660_defconfig b/arch/arm64/configs/sdm660_defconfig
index 50762356cb6f..6b45087e2603 100644
--- a/arch/arm64/configs/sdm660_defconfig
+++ b/arch/arm64/configs/sdm660_defconfig
@@ -309,6 +309,7 @@ CONFIG_INPUT_QPNP_POWER_ON=y
CONFIG_INPUT_KEYCHORD=y
CONFIG_INPUT_UINPUT=y
CONFIG_INPUT_GPIO=y
+CONFIG_INPUT_STMVL53L0=y
# CONFIG_SERIO_SERPORT is not set
# CONFIG_VT is not set
# CONFIG_LEGACY_PTYS is not set
@@ -600,6 +601,7 @@ CONFIG_MSM_EVENT_TIMER=y
CONFIG_MSM_AVTIMER=y
CONFIG_QCOM_REMOTEQDSS=y
CONFIG_MSM_SERVICE_NOTIFIER=y
+CONFIG_MSM_QBT1000=y
CONFIG_MSM_RPM_RBCPR_STATS_V2_LOG=y
CONFIG_MSM_RPM_LOG=y
CONFIG_MSM_RPM_STATS_LOG=y
diff --git a/arch/arm64/include/asm/io.h b/arch/arm64/include/asm/io.h
index eea245bf546a..3112c2a9d96f 100644
--- a/arch/arm64/include/asm/io.h
+++ b/arch/arm64/include/asm/io.h
@@ -167,9 +167,9 @@ static inline u64 __raw_readq_no_log(const volatile void __iomem *addr)
#define readq_relaxed_no_log(c) ({ u64 __v = le64_to_cpu((__force __le64)__raw_readq_no_log(c)); __v; })
#define writeb_relaxed_no_log(v, c) ((void)__raw_writeb_no_log((v), (c)))
-#define writew_relaxed_no_log(v, c) ((void)__raw_writew_no_log((__force u16)cpu_to_le32(v), (c)))
+#define writew_relaxed_no_log(v, c) ((void)__raw_writew_no_log((__force u16)cpu_to_le16(v), (c)))
#define writel_relaxed_no_log(v, c) ((void)__raw_writel_no_log((__force u32)cpu_to_le32(v), (c)))
-#define writeq_relaxed_no_log(v, c) ((void)__raw_writeq_no_log((__force u64)cpu_to_le32(v), (c)))
+#define writeq_relaxed_no_log(v, c) ((void)__raw_writeq_no_log((__force u64)cpu_to_le64(v), (c)))
/*
* I/O memory access primitives. Reads are ordered relative to any
diff --git a/arch/arm64/mm/fault.c b/arch/arm64/mm/fault.c
index 1804aea44faa..2720d47da366 100644
--- a/arch/arm64/mm/fault.c
+++ b/arch/arm64/mm/fault.c
@@ -92,21 +92,21 @@ void show_pte(struct mm_struct *mm, unsigned long addr)
break;
pud = pud_offset(pgd, addr);
- printk(", *pud=%016llx", pud_val(*pud));
+ pr_cont(", *pud=%016llx", pud_val(*pud));
if (pud_none(*pud) || pud_bad(*pud))
break;
pmd = pmd_offset(pud, addr);
- printk(", *pmd=%016llx", pmd_val(*pmd));
+ pr_cont(", *pmd=%016llx", pmd_val(*pmd));
if (pmd_none(*pmd) || pmd_bad(*pmd))
break;
pte = pte_offset_map(pmd, addr);
- printk(", *pte=%016llx", pte_val(*pte));
+ pr_cont(", *pte=%016llx", pte_val(*pte));
pte_unmap(pte);
} while(0);
- printk("\n");
+ pr_cont("\n");
}
#ifdef CONFIG_ARM64_HW_AFDBM
diff --git a/arch/mips/include/asm/branch.h b/arch/mips/include/asm/branch.h
index de781cf54bc7..da80878f2c0d 100644
--- a/arch/mips/include/asm/branch.h
+++ b/arch/mips/include/asm/branch.h
@@ -74,10 +74,7 @@ static inline int compute_return_epc(struct pt_regs *regs)
return __microMIPS_compute_return_epc(regs);
if (cpu_has_mips16)
return __MIPS16e_compute_return_epc(regs);
- return regs->cp0_epc;
- }
-
- if (!delay_slot(regs)) {
+ } else if (!delay_slot(regs)) {
regs->cp0_epc += 4;
return 0;
}
diff --git a/arch/mips/kernel/branch.c b/arch/mips/kernel/branch.c
index e9fed8ca9b42..71e8f4c0b8da 100644
--- a/arch/mips/kernel/branch.c
+++ b/arch/mips/kernel/branch.c
@@ -399,7 +399,7 @@ int __MIPS16e_compute_return_epc(struct pt_regs *regs)
*
* @regs: Pointer to pt_regs
* @insn: branch instruction to decode
- * @returns: -EFAULT on error and forces SIGBUS, and on success
+ * @returns: -EFAULT on error and forces SIGILL, and on success
* returns 0 or BRANCH_LIKELY_TAKEN as appropriate after
* evaluating the branch.
*
@@ -431,7 +431,7 @@ int __compute_return_epc_for_insn(struct pt_regs *regs,
/* Fall through */
case jr_op:
if (NO_R6EMU && insn.r_format.func == jr_op)
- goto sigill_r6;
+ goto sigill_r2r6;
regs->cp0_epc = regs->regs[insn.r_format.rs];
break;
}
@@ -446,7 +446,7 @@ int __compute_return_epc_for_insn(struct pt_regs *regs,
switch (insn.i_format.rt) {
case bltzl_op:
if (NO_R6EMU)
- goto sigill_r6;
+ goto sigill_r2r6;
case bltz_op:
if ((long)regs->regs[insn.i_format.rs] < 0) {
epc = epc + 4 + (insn.i_format.simmediate << 2);
@@ -459,7 +459,7 @@ int __compute_return_epc_for_insn(struct pt_regs *regs,
case bgezl_op:
if (NO_R6EMU)
- goto sigill_r6;
+ goto sigill_r2r6;
case bgez_op:
if ((long)regs->regs[insn.i_format.rs] >= 0) {
epc = epc + 4 + (insn.i_format.simmediate << 2);
@@ -473,10 +473,8 @@ int __compute_return_epc_for_insn(struct pt_regs *regs,
case bltzal_op:
case bltzall_op:
if (NO_R6EMU && (insn.i_format.rs ||
- insn.i_format.rt == bltzall_op)) {
- ret = -SIGILL;
- break;
- }
+ insn.i_format.rt == bltzall_op))
+ goto sigill_r2r6;
regs->regs[31] = epc + 8;
/*
* OK we are here either because we hit a NAL
@@ -507,10 +505,8 @@ int __compute_return_epc_for_insn(struct pt_regs *regs,
case bgezal_op:
case bgezall_op:
if (NO_R6EMU && (insn.i_format.rs ||
- insn.i_format.rt == bgezall_op)) {
- ret = -SIGILL;
- break;
- }
+ insn.i_format.rt == bgezall_op))
+ goto sigill_r2r6;
regs->regs[31] = epc + 8;
/*
* OK we are here either because we hit a BAL
@@ -556,6 +552,7 @@ int __compute_return_epc_for_insn(struct pt_regs *regs,
/*
* These are unconditional and in j_format.
*/
+ case jalx_op:
case jal_op:
regs->regs[31] = regs->cp0_epc + 8;
case j_op:
@@ -573,7 +570,7 @@ int __compute_return_epc_for_insn(struct pt_regs *regs,
*/
case beql_op:
if (NO_R6EMU)
- goto sigill_r6;
+ goto sigill_r2r6;
case beq_op:
if (regs->regs[insn.i_format.rs] ==
regs->regs[insn.i_format.rt]) {
@@ -587,7 +584,7 @@ int __compute_return_epc_for_insn(struct pt_regs *regs,
case bnel_op:
if (NO_R6EMU)
- goto sigill_r6;
+ goto sigill_r2r6;
case bne_op:
if (regs->regs[insn.i_format.rs] !=
regs->regs[insn.i_format.rt]) {
@@ -601,7 +598,7 @@ int __compute_return_epc_for_insn(struct pt_regs *regs,
case blezl_op: /* not really i_format */
if (!insn.i_format.rt && NO_R6EMU)
- goto sigill_r6;
+ goto sigill_r2r6;
case blez_op:
/*
* Compact branches for R6 for the
@@ -636,7 +633,7 @@ int __compute_return_epc_for_insn(struct pt_regs *regs,
case bgtzl_op:
if (!insn.i_format.rt && NO_R6EMU)
- goto sigill_r6;
+ goto sigill_r2r6;
case bgtz_op:
/*
* Compact branches for R6 for the
@@ -843,11 +840,12 @@ int __compute_return_epc_for_insn(struct pt_regs *regs,
return ret;
sigill_dsp:
- printk("%s: DSP branch but not DSP ASE - sending SIGBUS.\n", current->comm);
- force_sig(SIGBUS, current);
+ pr_info("%s: DSP branch but not DSP ASE - sending SIGILL.\n",
+ current->comm);
+ force_sig(SIGILL, current);
return -EFAULT;
-sigill_r6:
- pr_info("%s: R2 branch but r2-to-r6 emulator is not preset - sending SIGILL.\n",
+sigill_r2r6:
+ pr_info("%s: R2 branch but r2-to-r6 emulator is not present - sending SIGILL.\n",
current->comm);
force_sig(SIGILL, current);
return -EFAULT;
diff --git a/arch/mips/kernel/proc.c b/arch/mips/kernel/proc.c
index 298b2b773d12..f1fab6ff53e6 100644
--- a/arch/mips/kernel/proc.c
+++ b/arch/mips/kernel/proc.c
@@ -83,7 +83,7 @@ static int show_cpuinfo(struct seq_file *m, void *v)
}
seq_printf(m, "isa\t\t\t:");
- if (cpu_has_mips_r1)
+ if (cpu_has_mips_1)
seq_printf(m, " mips1");
if (cpu_has_mips_2)
seq_printf(m, "%s", " mips2");
diff --git a/arch/mips/kernel/ptrace.c b/arch/mips/kernel/ptrace.c
index c95bf18260f8..24c115a0721a 100644
--- a/arch/mips/kernel/ptrace.c
+++ b/arch/mips/kernel/ptrace.c
@@ -927,7 +927,7 @@ asmlinkage void syscall_trace_leave(struct pt_regs *regs)
audit_syscall_exit(regs);
if (unlikely(test_thread_flag(TIF_SYSCALL_TRACEPOINT)))
- trace_sys_exit(regs, regs->regs[2]);
+ trace_sys_exit(regs, regs_return_value(regs));
if (test_thread_flag(TIF_SYSCALL_TRACE))
tracehook_report_syscall_exit(regs, 0);
diff --git a/arch/mips/kernel/scall32-o32.S b/arch/mips/kernel/scall32-o32.S
index 2d23c834ba96..29b0c5f978e4 100644
--- a/arch/mips/kernel/scall32-o32.S
+++ b/arch/mips/kernel/scall32-o32.S
@@ -372,7 +372,7 @@ EXPORT(sys_call_table)
PTR sys_writev
PTR sys_cacheflush
PTR sys_cachectl
- PTR sys_sysmips
+ PTR __sys_sysmips
PTR sys_ni_syscall /* 4150 */
PTR sys_getsid
PTR sys_fdatasync
diff --git a/arch/mips/kernel/scall64-64.S b/arch/mips/kernel/scall64-64.S
index deac63315d0e..a6323a969919 100644
--- a/arch/mips/kernel/scall64-64.S
+++ b/arch/mips/kernel/scall64-64.S
@@ -312,7 +312,7 @@ EXPORT(sys_call_table)
PTR sys_sched_getaffinity
PTR sys_cacheflush
PTR sys_cachectl
- PTR sys_sysmips
+ PTR __sys_sysmips
PTR sys_io_setup /* 5200 */
PTR sys_io_destroy
PTR sys_io_getevents
diff --git a/arch/mips/kernel/scall64-n32.S b/arch/mips/kernel/scall64-n32.S
index ee93d5fe61d7..e0fdca8d3abe 100644
--- a/arch/mips/kernel/scall64-n32.S
+++ b/arch/mips/kernel/scall64-n32.S
@@ -298,7 +298,7 @@ EXPORT(sysn32_call_table)
PTR compat_sys_sched_getaffinity
PTR sys_cacheflush
PTR sys_cachectl
- PTR sys_sysmips
+ PTR __sys_sysmips
PTR compat_sys_io_setup /* 6200 */
PTR sys_io_destroy
PTR compat_sys_io_getevents
diff --git a/arch/mips/kernel/scall64-o32.S b/arch/mips/kernel/scall64-o32.S
index b77052ec6fb2..87c697181d25 100644
--- a/arch/mips/kernel/scall64-o32.S
+++ b/arch/mips/kernel/scall64-o32.S
@@ -367,7 +367,7 @@ EXPORT(sys32_call_table)
PTR compat_sys_writev
PTR sys_cacheflush
PTR sys_cachectl
- PTR sys_sysmips
+ PTR __sys_sysmips
PTR sys_ni_syscall /* 4150 */
PTR sys_getsid
PTR sys_fdatasync
diff --git a/arch/mips/kernel/syscall.c b/arch/mips/kernel/syscall.c
index 53a7ef9a8f32..4234b2d726c5 100644
--- a/arch/mips/kernel/syscall.c
+++ b/arch/mips/kernel/syscall.c
@@ -28,6 +28,7 @@
#include <linux/elf.h>
#include <asm/asm.h>
+#include <asm/asm-eva.h>
#include <asm/branch.h>
#include <asm/cachectl.h>
#include <asm/cacheflush.h>
@@ -138,10 +139,12 @@ static inline int mips_atomic_set(unsigned long addr, unsigned long new)
__asm__ __volatile__ (
" .set "MIPS_ISA_ARCH_LEVEL" \n"
" li %[err], 0 \n"
- "1: ll %[old], (%[addr]) \n"
+ "1: \n"
+ user_ll("%[old]", "(%[addr])")
" move %[tmp], %[new] \n"
- "2: sc %[tmp], (%[addr]) \n"
- " bnez %[tmp], 4f \n"
+ "2: \n"
+ user_sc("%[tmp]", "(%[addr])")
+ " beqz %[tmp], 4f \n"
"3: \n"
" .insn \n"
" .subsection 2 \n"
@@ -199,6 +202,12 @@ static inline int mips_atomic_set(unsigned long addr, unsigned long new)
unreachable();
}
+/*
+ * mips_atomic_set() normally returns directly via syscall_exit potentially
+ * clobbering static registers, so be sure to preserve them.
+ */
+save_static_function(sys_sysmips);
+
SYSCALL_DEFINE3(sysmips, long, cmd, long, arg1, long, arg2)
{
switch (cmd) {
diff --git a/arch/mips/math-emu/cp1emu.c b/arch/mips/math-emu/cp1emu.c
index 734a2c7665ec..6da2e4a6ba39 100644
--- a/arch/mips/math-emu/cp1emu.c
+++ b/arch/mips/math-emu/cp1emu.c
@@ -2496,6 +2496,35 @@ dcopuop:
return 0;
}
+/*
+ * Emulate FPU instructions.
+ *
+ * If we use FPU hardware, then we have been typically called to handle
+ * an unimplemented operation, such as where an operand is a NaN or
+ * denormalized. In that case exit the emulation loop after a single
+ * iteration so as to let hardware execute any subsequent instructions.
+ *
+ * If we have no FPU hardware or it has been disabled, then continue
+ * emulating floating-point instructions until one of these conditions
+ * has occurred:
+ *
+ * - a non-FPU instruction has been encountered,
+ *
+ * - an attempt to emulate has ended with a signal,
+ *
+ * - the ISA mode has been switched.
+ *
+ * We need to terminate the emulation loop if we got switched to the
+ * MIPS16 mode, whether supported or not, so that we do not attempt
+ * to emulate a MIPS16 instruction as a regular MIPS FPU instruction.
+ * Similarly if we got switched to the microMIPS mode and only the
+ * regular MIPS mode is supported, so that we do not attempt to emulate
+ * a microMIPS instruction as a regular MIPS FPU instruction. Or if
+ * we got switched to the regular MIPS mode and only the microMIPS mode
+ * is supported, so that we do not attempt to emulate a regular MIPS
+ * instruction that should cause an Address Error exception instead.
+ * For simplicity we always terminate upon an ISA mode switch.
+ */
int fpu_emulator_cop1Handler(struct pt_regs *xcp, struct mips_fpu_struct *ctx,
int has_fpu, void *__user *fault_addr)
{
@@ -2581,6 +2610,15 @@ int fpu_emulator_cop1Handler(struct pt_regs *xcp, struct mips_fpu_struct *ctx,
break;
if (sig)
break;
+ /*
+ * We have to check for the ISA bit explicitly here,
+ * because `get_isa16_mode' may return 0 if support
+ * for code compression has been globally disabled,
+ * or otherwise we may produce the wrong signal or
+ * even proceed successfully where we must not.
+ */
+ if ((xcp->cp0_epc ^ prevepc) & 0x1)
+ break;
cond_resched();
} while (xcp->cp0_epc > prevepc);
diff --git a/arch/openrisc/kernel/vmlinux.lds.S b/arch/openrisc/kernel/vmlinux.lds.S
index 2d69a853b742..3a08b55609b6 100644
--- a/arch/openrisc/kernel/vmlinux.lds.S
+++ b/arch/openrisc/kernel/vmlinux.lds.S
@@ -38,6 +38,8 @@ SECTIONS
/* Read-only sections, merged into text segment: */
. = LOAD_BASE ;
+ _text = .;
+
/* _s_kernel_ro must be page aligned */
. = ALIGN(PAGE_SIZE);
_s_kernel_ro = .;
diff --git a/arch/powerpc/include/asm/atomic.h b/arch/powerpc/include/asm/atomic.h
index 55f106ed12bf..039c4b910615 100644
--- a/arch/powerpc/include/asm/atomic.h
+++ b/arch/powerpc/include/asm/atomic.h
@@ -460,7 +460,7 @@ static __inline__ int atomic64_add_unless(atomic64_t *v, long a, long u)
* Atomically increments @v by 1, so long as @v is non-zero.
* Returns non-zero if @v was non-zero, and zero otherwise.
*/
-static __inline__ long atomic64_inc_not_zero(atomic64_t *v)
+static __inline__ int atomic64_inc_not_zero(atomic64_t *v)
{
long t1, t2;
@@ -479,7 +479,7 @@ static __inline__ long atomic64_inc_not_zero(atomic64_t *v)
: "r" (&v->counter)
: "cc", "xer", "memory");
- return t1;
+ return t1 != 0;
}
#endif /* __powerpc64__ */
diff --git a/arch/powerpc/include/asm/reg.h b/arch/powerpc/include/asm/reg.h
index 627d129d7fcb..ca372bbc0ffe 100644
--- a/arch/powerpc/include/asm/reg.h
+++ b/arch/powerpc/include/asm/reg.h
@@ -1236,7 +1236,7 @@ static inline unsigned long mfvtb (void)
" .llong 0\n" \
".previous" \
: "=r" (rval) \
- : "i" (CPU_FTR_CELL_TB_BUG), "i" (SPRN_TBRL)); \
+ : "i" (CPU_FTR_CELL_TB_BUG), "i" (SPRN_TBRL) : "cr0"); \
rval;})
#else
#define mftb() ({unsigned long rval; \
diff --git a/arch/powerpc/include/asm/topology.h b/arch/powerpc/include/asm/topology.h
index 329771559cbb..8b3b46b7b0f2 100644
--- a/arch/powerpc/include/asm/topology.h
+++ b/arch/powerpc/include/asm/topology.h
@@ -44,22 +44,8 @@ extern void __init dump_numa_cpu_topology(void);
extern int sysfs_add_device_to_node(struct device *dev, int nid);
extern void sysfs_remove_device_from_node(struct device *dev, int nid);
-static inline int early_cpu_to_node(int cpu)
-{
- int nid;
-
- nid = numa_cpu_lookup_table[cpu];
-
- /*
- * Fall back to node 0 if nid is unset (it should be, except bugs).
- * This allows callers to safely do NODE_DATA(early_cpu_to_node(cpu)).
- */
- return (nid < 0) ? 0 : nid;
-}
#else
-static inline int early_cpu_to_node(int cpu) { return 0; }
-
static inline void dump_numa_cpu_topology(void) {}
static inline int sysfs_add_device_to_node(struct device *dev, int nid)
diff --git a/arch/powerpc/kernel/setup_64.c b/arch/powerpc/kernel/setup_64.c
index fe6e800c1357..a20823210ac0 100644
--- a/arch/powerpc/kernel/setup_64.c
+++ b/arch/powerpc/kernel/setup_64.c
@@ -751,7 +751,7 @@ void __init setup_arch(char **cmdline_p)
static void * __init pcpu_fc_alloc(unsigned int cpu, size_t size, size_t align)
{
- return __alloc_bootmem_node(NODE_DATA(early_cpu_to_node(cpu)), size, align,
+ return __alloc_bootmem_node(NODE_DATA(cpu_to_node(cpu)), size, align,
__pa(MAX_DMA_ADDRESS));
}
@@ -762,7 +762,7 @@ static void __init pcpu_fc_free(void *ptr, size_t size)
static int pcpu_cpu_distance(unsigned int from, unsigned int to)
{
- if (early_cpu_to_node(from) == early_cpu_to_node(to))
+ if (cpu_to_node(from) == cpu_to_node(to))
return LOCAL_DISTANCE;
else
return REMOTE_DISTANCE;
diff --git a/arch/powerpc/kvm/book3s_hv.c b/arch/powerpc/kvm/book3s_hv.c
index 396dc44e783b..428563b195c3 100644
--- a/arch/powerpc/kvm/book3s_hv.c
+++ b/arch/powerpc/kvm/book3s_hv.c
@@ -2687,6 +2687,10 @@ static int kvmppc_vcpu_run_hv(struct kvm_run *run, struct kvm_vcpu *vcpu)
{
int r;
int srcu_idx;
+ unsigned long ebb_regs[3] = {}; /* shut up GCC */
+ unsigned long user_tar = 0;
+ unsigned long proc_fscr = 0;
+ unsigned int user_vrsave;
if (!vcpu->arch.sane) {
run->exit_reason = KVM_EXIT_INTERNAL_ERROR;
@@ -2707,10 +2711,11 @@ static int kvmppc_vcpu_run_hv(struct kvm_run *run, struct kvm_vcpu *vcpu)
run->fail_entry.hardware_entry_failure_reason = 0;
return -EINVAL;
}
+ /* Enable TM so we can read the TM SPRs */
+ mtmsr(mfmsr() | MSR_TM);
current->thread.tm_tfhar = mfspr(SPRN_TFHAR);
current->thread.tm_tfiar = mfspr(SPRN_TFIAR);
current->thread.tm_texasr = mfspr(SPRN_TEXASR);
- current->thread.regs->msr &= ~MSR_TM;
}
#endif
@@ -2736,6 +2741,17 @@ static int kvmppc_vcpu_run_hv(struct kvm_run *run, struct kvm_vcpu *vcpu)
flush_fp_to_thread(current);
flush_altivec_to_thread(current);
flush_vsx_to_thread(current);
+
+ /* Save userspace EBB and other register values */
+ if (cpu_has_feature(CPU_FTR_ARCH_207S)) {
+ ebb_regs[0] = mfspr(SPRN_EBBHR);
+ ebb_regs[1] = mfspr(SPRN_EBBRR);
+ ebb_regs[2] = mfspr(SPRN_BESCR);
+ user_tar = mfspr(SPRN_TAR);
+ proc_fscr = mfspr(SPRN_FSCR);
+ }
+ user_vrsave = mfspr(SPRN_VRSAVE);
+
vcpu->arch.wqp = &vcpu->arch.vcore->wq;
vcpu->arch.pgdir = current->mm->pgd;
vcpu->arch.state = KVMPPC_VCPU_BUSY_IN_HOST;
@@ -2757,6 +2773,29 @@ static int kvmppc_vcpu_run_hv(struct kvm_run *run, struct kvm_vcpu *vcpu)
}
} while (is_kvmppc_resume_guest(r));
+ /* Restore userspace EBB and other register values */
+ if (cpu_has_feature(CPU_FTR_ARCH_207S)) {
+ mtspr(SPRN_EBBHR, ebb_regs[0]);
+ mtspr(SPRN_EBBRR, ebb_regs[1]);
+ mtspr(SPRN_BESCR, ebb_regs[2]);
+ mtspr(SPRN_TAR, user_tar);
+ mtspr(SPRN_FSCR, proc_fscr);
+ }
+ mtspr(SPRN_VRSAVE, user_vrsave);
+
+ /*
+ * Since we don't do lazy TM reload, we need to reload
+ * the TM registers here.
+ */
+#ifdef CONFIG_PPC_TRANSACTIONAL_MEM
+ if (cpu_has_feature(CPU_FTR_TM) && current->thread.regs &&
+ (current->thread.regs->msr & MSR_TM)) {
+ mtspr(SPRN_TFHAR, current->thread.tm_tfhar);
+ mtspr(SPRN_TFIAR, current->thread.tm_tfiar);
+ mtspr(SPRN_TEXASR, current->thread.tm_texasr);
+ }
+#endif
+
out:
vcpu->arch.state = KVMPPC_VCPU_NOTREADY;
atomic_dec(&vcpu->kvm->arch.vcpus_running);
diff --git a/arch/powerpc/kvm/book3s_hv_rmhandlers.S b/arch/powerpc/kvm/book3s_hv_rmhandlers.S
index 1a743f87b37d..ffab9269bfe4 100644
--- a/arch/powerpc/kvm/book3s_hv_rmhandlers.S
+++ b/arch/powerpc/kvm/book3s_hv_rmhandlers.S
@@ -36,6 +36,13 @@
#define NAPPING_CEDE 1
#define NAPPING_NOVCPU 2
+/* Stack frame offsets for kvmppc_hv_entry */
+#define SFS 112
+#define STACK_SLOT_TRAP (SFS-4)
+#define STACK_SLOT_CIABR (SFS-16)
+#define STACK_SLOT_DAWR (SFS-24)
+#define STACK_SLOT_DAWRX (SFS-32)
+
/*
* Call kvmppc_hv_entry in real mode.
* Must be called with interrupts hard-disabled.
@@ -274,10 +281,10 @@ kvm_novcpu_exit:
bl kvmhv_accumulate_time
#endif
13: mr r3, r12
- stw r12, 112-4(r1)
+ stw r12, STACK_SLOT_TRAP(r1)
bl kvmhv_commence_exit
nop
- lwz r12, 112-4(r1)
+ lwz r12, STACK_SLOT_TRAP(r1)
b kvmhv_switch_to_host
/*
@@ -489,7 +496,7 @@ kvmppc_hv_entry:
*/
mflr r0
std r0, PPC_LR_STKOFF(r1)
- stdu r1, -112(r1)
+ stdu r1, -SFS(r1)
/* Save R1 in the PACA */
std r1, HSTATE_HOST_R1(r13)
@@ -643,6 +650,16 @@ kvmppc_got_guest:
mtspr SPRN_PURR,r7
mtspr SPRN_SPURR,r8
+ /* Save host values of some registers */
+BEGIN_FTR_SECTION
+ mfspr r5, SPRN_CIABR
+ mfspr r6, SPRN_DAWR
+ mfspr r7, SPRN_DAWRX
+ std r5, STACK_SLOT_CIABR(r1)
+ std r6, STACK_SLOT_DAWR(r1)
+ std r7, STACK_SLOT_DAWRX(r1)
+END_FTR_SECTION_IFSET(CPU_FTR_ARCH_207S)
+
BEGIN_FTR_SECTION
/* Set partition DABR */
/* Do this before re-enabling PMU to avoid P7 DABR corruption bug */
@@ -1266,8 +1283,7 @@ END_FTR_SECTION_IFCLR(CPU_FTR_ARCH_207S)
*/
li r0, 0
mtspr SPRN_IAMR, r0
- mtspr SPRN_CIABR, r0
- mtspr SPRN_DAWRX, r0
+ mtspr SPRN_PSPB, r0
mtspr SPRN_TCSCR, r0
mtspr SPRN_WORT, r0
/* Set MMCRS to 1<<31 to freeze and disable the SPMC counters */
@@ -1283,6 +1299,7 @@ END_FTR_SECTION_IFCLR(CPU_FTR_ARCH_207S)
std r6,VCPU_UAMOR(r9)
li r6,0
mtspr SPRN_AMR,r6
+ mtspr SPRN_UAMOR, r6
/* Switch DSCR back to host value */
mfspr r8, SPRN_DSCR
@@ -1424,6 +1441,16 @@ END_FTR_SECTION_IFSET(CPU_FTR_ARCH_207S)
slbia
ptesync
+ /* Restore host values of some registers */
+BEGIN_FTR_SECTION
+ ld r5, STACK_SLOT_CIABR(r1)
+ ld r6, STACK_SLOT_DAWR(r1)
+ ld r7, STACK_SLOT_DAWRX(r1)
+ mtspr SPRN_CIABR, r5
+ mtspr SPRN_DAWR, r6
+ mtspr SPRN_DAWRX, r7
+END_FTR_SECTION_IFSET(CPU_FTR_ARCH_207S)
+
/*
* POWER7/POWER8 guest -> host partition switch code.
* We don't have to lock against tlbies but we do
@@ -1533,8 +1560,8 @@ END_FTR_SECTION_IFSET(CPU_FTR_ARCH_207S)
li r0, KVM_GUEST_MODE_NONE
stb r0, HSTATE_IN_GUEST(r13)
- ld r0, 112+PPC_LR_STKOFF(r1)
- addi r1, r1, 112
+ ld r0, SFS+PPC_LR_STKOFF(r1)
+ addi r1, r1, SFS
mtlr r0
blr
diff --git a/arch/powerpc/lib/sstep.c b/arch/powerpc/lib/sstep.c
index 4014881e9843..e37162d356d8 100644
--- a/arch/powerpc/lib/sstep.c
+++ b/arch/powerpc/lib/sstep.c
@@ -687,8 +687,10 @@ int __kprobes analyse_instr(struct instruction_op *op, struct pt_regs *regs,
case 19:
switch ((instr >> 1) & 0x3ff) {
case 0: /* mcrf */
- rd = (instr >> 21) & 0x1c;
- ra = (instr >> 16) & 0x1c;
+ rd = 7 - ((instr >> 23) & 0x7);
+ ra = 7 - ((instr >> 18) & 0x7);
+ rd *= 4;
+ ra *= 4;
val = (regs->ccr >> ra) & 0xf;
regs->ccr = (regs->ccr & ~(0xfUL << rd)) | (val << rd);
goto instr_done;
@@ -967,6 +969,19 @@ int __kprobes analyse_instr(struct instruction_op *op, struct pt_regs *regs,
#endif
case 19: /* mfcr */
+ if ((instr >> 20) & 1) {
+ imm = 0xf0000000UL;
+ for (sh = 0; sh < 8; ++sh) {
+ if (instr & (0x80000 >> sh)) {
+ regs->gpr[rd] = regs->ccr & imm;
+ break;
+ }
+ imm >>= 4;
+ }
+
+ goto instr_done;
+ }
+
regs->gpr[rd] = regs->ccr;
regs->gpr[rd] &= 0xffffffffUL;
goto instr_done;
diff --git a/arch/powerpc/platforms/pseries/reconfig.c b/arch/powerpc/platforms/pseries/reconfig.c
index 7c7fcc042549..fb695f142563 100644
--- a/arch/powerpc/platforms/pseries/reconfig.c
+++ b/arch/powerpc/platforms/pseries/reconfig.c
@@ -82,7 +82,6 @@ static int pSeries_reconfig_remove_node(struct device_node *np)
of_detach_node(np);
of_node_put(parent);
- of_node_put(np); /* Must decrement the refcount */
return 0;
}
diff --git a/arch/s390/include/asm/syscall.h b/arch/s390/include/asm/syscall.h
index 6ba0bf928909..6bc941be6921 100644
--- a/arch/s390/include/asm/syscall.h
+++ b/arch/s390/include/asm/syscall.h
@@ -64,6 +64,12 @@ static inline void syscall_get_arguments(struct task_struct *task,
{
unsigned long mask = -1UL;
+ /*
+ * No arguments for this syscall, there's nothing to do.
+ */
+ if (!n)
+ return;
+
BUG_ON(i + n > 6);
#ifdef CONFIG_COMPAT
if (test_tsk_thread_flag(task, TIF_31BIT))
diff --git a/arch/x86/include/asm/xen/hypercall.h b/arch/x86/include/asm/xen/hypercall.h
index 4c20dd333412..85133b2b8e99 100644
--- a/arch/x86/include/asm/xen/hypercall.h
+++ b/arch/x86/include/asm/xen/hypercall.h
@@ -43,6 +43,7 @@
#include <asm/page.h>
#include <asm/pgtable.h>
+#include <asm/smap.h>
#include <xen/interface/xen.h>
#include <xen/interface/sched.h>
@@ -213,10 +214,12 @@ privcmd_call(unsigned call,
__HYPERCALL_DECLS;
__HYPERCALL_5ARG(a1, a2, a3, a4, a5);
+ stac();
asm volatile("call *%[call]"
: __HYPERCALL_5PARAM
: [call] "a" (&hypercall_page[call])
: __HYPERCALL_CLOBBER5);
+ clac();
return (long)__res;
}
diff --git a/arch/x86/kernel/acpi/boot.c b/arch/x86/kernel/acpi/boot.c
index e75907601a41..1e5eb9f2ff5f 100644
--- a/arch/x86/kernel/acpi/boot.c
+++ b/arch/x86/kernel/acpi/boot.c
@@ -329,6 +329,14 @@ static void __init mp_override_legacy_irq(u8 bus_irq, u8 polarity, u8 trigger,
struct mpc_intsrc mp_irq;
/*
+ * Check bus_irq boundary.
+ */
+ if (bus_irq >= NR_IRQS_LEGACY) {
+ pr_warn("Invalid bus_irq %u for legacy override\n", bus_irq);
+ return;
+ }
+
+ /*
* Convert 'gsi' to 'ioapic.pin'.
*/
ioapic = mp_find_ioapic(gsi);
diff --git a/arch/x86/kernel/apic/io_apic.c b/arch/x86/kernel/apic/io_apic.c
index 1e5d2f07416b..fc91c98bee01 100644
--- a/arch/x86/kernel/apic/io_apic.c
+++ b/arch/x86/kernel/apic/io_apic.c
@@ -2115,7 +2115,7 @@ static inline void __init check_timer(void)
int idx;
idx = find_irq_entry(apic1, pin1, mp_INT);
if (idx != -1 && irq_trigger(idx))
- unmask_ioapic_irq(irq_get_chip_data(0));
+ unmask_ioapic_irq(irq_get_irq_data(0));
}
irq_domain_deactivate_irq(irq_data);
irq_domain_activate_irq(irq_data);
diff --git a/arch/x86/kernel/cpu/mcheck/mce_amd.c b/arch/x86/kernel/cpu/mcheck/mce_amd.c
index 62aca448726a..2116176c1721 100644
--- a/arch/x86/kernel/cpu/mcheck/mce_amd.c
+++ b/arch/x86/kernel/cpu/mcheck/mce_amd.c
@@ -682,6 +682,9 @@ static int threshold_create_bank(unsigned int cpu, unsigned int bank)
const char *name = th_names[bank];
int err = 0;
+ if (!dev)
+ return -ENODEV;
+
if (is_shared_bank(bank)) {
nb = node_to_amd_nb(amd_get_nb_id(cpu));
diff --git a/crypto/authencesn.c b/crypto/authencesn.c
index 0c0468869e25..52154ef21b5e 100644
--- a/crypto/authencesn.c
+++ b/crypto/authencesn.c
@@ -245,6 +245,9 @@ static int crypto_authenc_esn_decrypt_tail(struct aead_request *req,
u8 *ihash = ohash + crypto_ahash_digestsize(auth);
u32 tmp[2];
+ if (!authsize)
+ goto decrypt;
+
/* Move high-order bits of sequence number back. */
scatterwalk_map_and_copy(tmp, dst, 4, 4, 0);
scatterwalk_map_and_copy(tmp + 1, dst, assoclen + cryptlen, 4, 0);
@@ -253,6 +256,8 @@ static int crypto_authenc_esn_decrypt_tail(struct aead_request *req,
if (crypto_memneq(ihash, ohash, authsize))
return -EBADMSG;
+decrypt:
+
sg_init_table(areq_ctx->dst, 2);
dst = scatterwalk_ffwd(areq_ctx->dst, dst, assoclen);
diff --git a/drivers/acpi/glue.c b/drivers/acpi/glue.c
index 5ea5dc219f56..73c9c7fa9001 100644
--- a/drivers/acpi/glue.c
+++ b/drivers/acpi/glue.c
@@ -98,7 +98,15 @@ static int find_child_checks(struct acpi_device *adev, bool check_children)
if (check_children && list_empty(&adev->children))
return -ENODEV;
- return sta_present ? FIND_CHILD_MAX_SCORE : FIND_CHILD_MIN_SCORE;
+ /*
+ * If the device has a _HID (or _CID) returning a valid ACPI/PNP
+ * device ID, it is better to make it look less attractive here, so that
+ * the other device with the same _ADR value (that may not have a valid
+ * device ID) can be matched going forward. [This means a second spec
+ * violation in a row, so whatever we do here is best effort anyway.]
+ */
+ return sta_present && list_empty(&adev->pnp.ids) ?
+ FIND_CHILD_MAX_SCORE : FIND_CHILD_MIN_SCORE;
}
struct acpi_device *acpi_find_child_device(struct acpi_device *parent,
diff --git a/drivers/android/binder.c b/drivers/android/binder.c
index 7b30dcfabd48..71ebe36577c6 100644
--- a/drivers/android/binder.c
+++ b/drivers/android/binder.c
@@ -1014,7 +1014,7 @@ binder_select_thread_ilocked(struct binder_proc *proc)
{
struct binder_thread *thread;
- BUG_ON(!spin_is_locked(&proc->inner_lock));
+ assert_spin_locked(&proc->inner_lock);
thread = list_first_entry_or_null(&proc->waiting_threads,
struct binder_thread,
waiting_thread_node);
@@ -1045,7 +1045,7 @@ static void binder_wakeup_thread_ilocked(struct binder_proc *proc,
struct binder_thread *thread,
bool sync)
{
- BUG_ON(!spin_is_locked(&proc->inner_lock));
+ assert_spin_locked(&proc->inner_lock);
if (thread) {
if (sync)
@@ -1224,7 +1224,7 @@ static struct binder_node *binder_get_node_ilocked(struct binder_proc *proc,
struct rb_node *n = proc->nodes.rb_node;
struct binder_node *node;
- BUG_ON(!spin_is_locked(&proc->inner_lock));
+ assert_spin_locked(&proc->inner_lock);
while (n) {
node = rb_entry(n, struct binder_node, rb_node);
@@ -1270,7 +1270,8 @@ static struct binder_node *binder_init_node_ilocked(
__u32 flags = fp ? fp->flags : 0;
s8 priority;
- BUG_ON(!spin_is_locked(&proc->inner_lock));
+ assert_spin_locked(&proc->inner_lock);
+
while (*p) {
parent = *p;
@@ -1349,9 +1350,9 @@ static int binder_inc_node_nilocked(struct binder_node *node, int strong,
{
struct binder_proc *proc = node->proc;
- BUG_ON(!spin_is_locked(&node->lock));
+ assert_spin_locked(&node->lock);
if (proc)
- BUG_ON(!spin_is_locked(&proc->inner_lock));
+ assert_spin_locked(&proc->inner_lock);
if (strong) {
if (internal) {
if (target_list == NULL &&
@@ -1403,9 +1404,9 @@ static bool binder_dec_node_nilocked(struct binder_node *node,
{
struct binder_proc *proc = node->proc;
- BUG_ON(!spin_is_locked(&node->lock));
+ assert_spin_locked(&node->lock);
if (proc)
- BUG_ON(!spin_is_locked(&proc->inner_lock));
+ assert_spin_locked(&proc->inner_lock);
if (strong) {
if (internal)
node->internal_strong_refs--;
@@ -1929,7 +1930,7 @@ static void binder_pop_transaction_ilocked(struct binder_thread *target_thread,
struct binder_transaction *t)
{
BUG_ON(!target_thread);
- BUG_ON(!spin_is_locked(&target_thread->proc->inner_lock));
+ assert_spin_locked(&target_thread->proc->inner_lock);
BUG_ON(target_thread->transaction_stack != t);
BUG_ON(target_thread->transaction_stack->from != target_thread);
target_thread->transaction_stack =
@@ -5072,7 +5073,6 @@ static void print_binder_transaction_ilocked(struct seq_file *m,
struct binder_proc *to_proc;
struct binder_buffer *buffer = t->buffer;
- WARN_ON(!spin_is_locked(&proc->inner_lock));
spin_lock(&t->lock);
to_proc = t->to_proc;
seq_printf(m,
@@ -5161,7 +5161,6 @@ static void print_binder_thread_ilocked(struct seq_file *m,
size_t start_pos = m->count;
size_t header_pos;
- WARN_ON(!spin_is_locked(&thread->proc->inner_lock));
seq_printf(m, " thread %d: l %02x need_return %d tr %d\n",
thread->pid, thread->looper,
thread->looper_need_return,
@@ -5198,10 +5197,6 @@ static void print_binder_node_nilocked(struct seq_file *m,
struct binder_work *w;
int count;
- WARN_ON(!spin_is_locked(&node->lock));
- if (node->proc)
- WARN_ON(!spin_is_locked(&node->proc->inner_lock));
-
count = 0;
hlist_for_each_entry(ref, &node->refs, node_entry)
count++;
@@ -5228,7 +5223,6 @@ static void print_binder_node_nilocked(struct seq_file *m,
static void print_binder_ref_olocked(struct seq_file *m,
struct binder_ref *ref)
{
- WARN_ON(!spin_is_locked(&ref->proc->outer_lock));
binder_node_lock(ref->node);
seq_printf(m, " ref %d: desc %d %snode %d s %d w %d d %pK\n",
ref->data.debug_id, ref->data.desc,
diff --git a/drivers/base/power/domain.c b/drivers/base/power/domain.c
index a48824deabc5..78b0ece0c867 100644
--- a/drivers/base/power/domain.c
+++ b/drivers/base/power/domain.c
@@ -1188,7 +1188,6 @@ static struct generic_pm_domain_data *genpd_alloc_dev_data(struct device *dev,
}
dev->power.subsys_data->domain_data = &gpd_data->base;
- dev->pm_domain = &genpd->domain;
spin_unlock_irq(&dev->power.lock);
@@ -1207,7 +1206,6 @@ static void genpd_free_dev_data(struct device *dev,
{
spin_lock_irq(&dev->power.lock);
- dev->pm_domain = NULL;
dev->power.subsys_data->domain_data = NULL;
spin_unlock_irq(&dev->power.lock);
@@ -1248,6 +1246,8 @@ int __pm_genpd_add_device(struct generic_pm_domain *genpd, struct device *dev,
if (ret)
goto out;
+ dev->pm_domain = &genpd->domain;
+
genpd->device_count++;
genpd->max_off_time_changed = true;
@@ -1299,6 +1299,8 @@ int pm_genpd_remove_device(struct generic_pm_domain *genpd,
if (genpd->detach_dev)
genpd->detach_dev(genpd, dev);
+ dev->pm_domain = NULL;
+
list_del_init(&pdd->list_node);
mutex_unlock(&genpd->lock);
@@ -1373,7 +1375,7 @@ EXPORT_SYMBOL_GPL(pm_genpd_add_subdomain);
int pm_genpd_remove_subdomain(struct generic_pm_domain *genpd,
struct generic_pm_domain *subdomain)
{
- struct gpd_link *link;
+ struct gpd_link *l, *link;
int ret = -EINVAL;
if (IS_ERR_OR_NULL(genpd) || IS_ERR_OR_NULL(subdomain))
@@ -1388,7 +1390,7 @@ int pm_genpd_remove_subdomain(struct generic_pm_domain *genpd,
goto out;
}
- list_for_each_entry(link, &genpd->master_links, master_node) {
+ list_for_each_entry_safe(link, l, &genpd->master_links, master_node) {
if (link->slave != subdomain)
continue;
@@ -1642,10 +1644,10 @@ EXPORT_SYMBOL_GPL(__of_genpd_add_provider);
*/
void of_genpd_del_provider(struct device_node *np)
{
- struct of_genpd_provider *cp;
+ struct of_genpd_provider *cp, *tmp;
mutex_lock(&of_genpd_mutex);
- list_for_each_entry(cp, &of_genpd_providers, link) {
+ list_for_each_entry_safe(cp, tmp, &of_genpd_providers, link) {
if (cp->node == np) {
list_del(&cp->link);
of_node_put(cp->node);
diff --git a/drivers/block/xen-blkback/blkback.c b/drivers/block/xen-blkback/blkback.c
index 41fb1a917b17..33e23a7a691f 100644
--- a/drivers/block/xen-blkback/blkback.c
+++ b/drivers/block/xen-blkback/blkback.c
@@ -595,8 +595,6 @@ int xen_blkif_schedule(void *arg)
unsigned long timeout;
int ret;
- xen_blkif_get(blkif);
-
while (!kthread_should_stop()) {
if (try_to_freeze())
continue;
@@ -650,7 +648,6 @@ purge_gnt_list:
print_stats(blkif);
blkif->xenblkd = NULL;
- xen_blkif_put(blkif);
return 0;
}
diff --git a/drivers/block/xen-blkback/xenbus.c b/drivers/block/xen-blkback/xenbus.c
index f53cff42f8da..923308201375 100644
--- a/drivers/block/xen-blkback/xenbus.c
+++ b/drivers/block/xen-blkback/xenbus.c
@@ -221,7 +221,6 @@ static int xen_blkif_disconnect(struct xen_blkif *blkif)
if (blkif->xenblkd) {
kthread_stop(blkif->xenblkd);
wake_up(&blkif->shutdown_wq);
- blkif->xenblkd = NULL;
}
/* The above kthread_stop() guarantees that at this point we
@@ -266,9 +265,10 @@ static int xen_blkif_disconnect(struct xen_blkif *blkif)
static void xen_blkif_free(struct xen_blkif *blkif)
{
-
- xen_blkif_disconnect(blkif);
+ WARN_ON(xen_blkif_disconnect(blkif));
xen_vbd_free(&blkif->vbd);
+ kfree(blkif->be->mode);
+ kfree(blkif->be);
/* Make sure everything is drained before shutting down */
BUG_ON(blkif->persistent_gnt_c != 0);
@@ -445,8 +445,6 @@ static int xen_blkbk_remove(struct xenbus_device *dev)
xen_blkif_put(be->blkif);
}
- kfree(be->mode);
- kfree(be);
return 0;
}
diff --git a/drivers/bluetooth/btfm_slim.c b/drivers/bluetooth/btfm_slim.c
index 969f755f5dc4..0a61186167ba 100644
--- a/drivers/bluetooth/btfm_slim.c
+++ b/drivers/bluetooth/btfm_slim.c
@@ -155,23 +155,22 @@ int btfm_slim_enable_ch(struct btfmslim *btfmslim, struct btfmslim_ch *ch,
rxport, 1);
if (ret < 0) {
BTFMSLIM_ERR("vendor_port_en failed ret[%d]",
- ret);
+ ret);
goto error;
}
}
if (rxport) {
BTFMSLIM_INFO("slim_connect_sink(port: %d, ch: %d)",
- ch->port, ch->ch);
+ ch->port, ch->ch);
/* Connect Port with channel given by Machine driver*/
ret = slim_connect_sink(btfmslim->slim_pgd,
&ch->port_hdl, 1, ch->ch_hdl);
if (ret < 0) {
BTFMSLIM_ERR("slim_connect_sink failed ret[%d]",
- ret);
+ ret);
goto remove_channel;
}
-
} else {
BTFMSLIM_INFO("slim_connect_src(port: %d, ch: %d)",
ch->port, ch->ch);
@@ -180,7 +179,7 @@ int btfm_slim_enable_ch(struct btfmslim *btfmslim, struct btfmslim_ch *ch,
ch->ch_hdl);
if (ret < 0) {
BTFMSLIM_ERR("slim_connect_src failed ret[%d]",
- ret);
+ ret);
goto remove_channel;
}
}
@@ -190,6 +189,7 @@ int btfm_slim_enable_ch(struct btfmslim *btfmslim, struct btfmslim_ch *ch,
BTFMSLIM_INFO(
"port: %d, ch: %d, grp: %d, ch->grph: 0x%x, ch_hdl: 0x%x",
chan->port, chan->ch, grp, chan->grph, chan->ch_hdl);
+
ret = slim_control_ch(btfmslim->slim_pgd, (grp ? chan->grph :
chan->ch_hdl), SLIM_CH_ACTIVATE, true);
if (ret < 0) {
@@ -220,6 +220,7 @@ int btfm_slim_disable_ch(struct btfmslim *btfmslim, struct btfmslim_ch *ch,
BTFMSLIM_INFO("port:%d, grp: %d, ch->grph:0x%x, ch->ch_hdl:0x%x ",
ch->port, grp, ch->grph, ch->ch_hdl);
+
/* Remove the channel immediately*/
ret = slim_control_ch(btfmslim->slim_pgd, (grp ? ch->grph : ch->ch_hdl),
SLIM_CH_REMOVE, true);
@@ -233,7 +234,6 @@ int btfm_slim_disable_ch(struct btfmslim *btfmslim, struct btfmslim_ch *ch,
goto error;
}
}
-
/* Disable port through registration setting */
for (i = 0; i < nchan; i++, ch++) {
if (btfmslim->vendor_port_en) {
@@ -246,9 +246,11 @@ int btfm_slim_disable_ch(struct btfmslim *btfmslim, struct btfmslim_ch *ch,
}
}
}
+
error:
return ret;
}
+
static int btfm_slim_get_logical_addr(struct slim_device *slim)
{
int ret = 0;
diff --git a/drivers/bluetooth/btfm_slim_codec.c b/drivers/bluetooth/btfm_slim_codec.c
index 96be0e2f9183..035e8d9fb5fd 100644
--- a/drivers/bluetooth/btfm_slim_codec.c
+++ b/drivers/bluetooth/btfm_slim_codec.c
@@ -118,9 +118,6 @@ static void btfm_slim_dai_shutdown(struct snd_pcm_substream *substream,
return;
}
- if (dai->id == BTFM_FM_SLIM_TX)
- goto out;
-
/* Search for dai->id matched port handler */
for (i = 0; (i < BTFM_SLIM_NUM_CODEC_DAIS) &&
(ch->id != BTFM_SLIM_NUM_CODEC_DAIS) &&
@@ -134,7 +131,6 @@ static void btfm_slim_dai_shutdown(struct snd_pcm_substream *substream,
}
btfm_slim_disable_ch(btfmslim, ch, rxport, grp, nchan);
-out:
btfm_slim_hw_deinit(btfmslim);
}
@@ -205,61 +201,6 @@ int btfm_slim_dai_prepare(struct snd_pcm_substream *substream,
return ret;
}
-static int btfm_slim_dai_hw_free(struct snd_pcm_substream *substream,
- struct snd_soc_dai *dai)
-{
- int ret = -EINVAL, i;
- struct btfmslim *btfmslim = dai->dev->platform_data;
- struct btfmslim_ch *ch;
- uint8_t rxport, grp = false, nchan = 1;
-
- BTFMSLIM_DBG("dai->name: %s, dai->id: %d, dai->rate: %d", dai->name,
- dai->id, dai->rate);
-
- switch (dai->id) {
- case BTFM_FM_SLIM_TX:
- grp = true; nchan = 2;
- ch = btfmslim->tx_chs;
- rxport = 0;
- break;
- case BTFM_BT_SCO_SLIM_TX:
- ch = btfmslim->tx_chs;
- rxport = 0;
- break;
- case BTFM_BT_SCO_A2DP_SLIM_RX:
- case BTFM_BT_SPLIT_A2DP_SLIM_RX:
- ch = btfmslim->rx_chs;
- rxport = 1;
- break;
- case BTFM_SLIM_NUM_CODEC_DAIS:
- default:
- BTFMSLIM_ERR("dai->id is invalid:%d", dai->id);
- goto out;
- }
-
- if (dai->id != BTFM_FM_SLIM_TX) {
- ret = 0;
- goto out;
- }
-
- /* Search for dai->id matched port handler */
- for (i = 0; (i < BTFM_SLIM_NUM_CODEC_DAIS) &&
- (ch->id != BTFM_SLIM_NUM_CODEC_DAIS) &&
- (ch->id != dai->id); ch++, i++)
- ;
-
- if ((ch->port == BTFM_SLIM_PGD_PORT_LAST) ||
- (ch->id == BTFM_SLIM_NUM_CODEC_DAIS)) {
- BTFMSLIM_ERR("ch is invalid!!");
- goto out;
- }
-
- btfm_slim_disable_ch(btfmslim, ch, rxport, grp, nchan);
-
-out:
- return ret;
-}
-
/* This function will be called once during boot up */
static int btfm_slim_dai_set_channel_map(struct snd_soc_dai *dai,
unsigned int tx_num, unsigned int *tx_slot,
@@ -402,7 +343,6 @@ static struct snd_soc_dai_ops btfmslim_dai_ops = {
.shutdown = btfm_slim_dai_shutdown,
.hw_params = btfm_slim_dai_hw_params,
.prepare = btfm_slim_dai_prepare,
- .hw_free = btfm_slim_dai_hw_free,
.set_channel_map = btfm_slim_dai_set_channel_map,
.get_channel_map = btfm_slim_dai_get_channel_map,
};
diff --git a/drivers/bluetooth/btfm_slim_wcn3990.c b/drivers/bluetooth/btfm_slim_wcn3990.c
index 0c4e0b3d5c2e..363b4692d228 100644
--- a/drivers/bluetooth/btfm_slim_wcn3990.c
+++ b/drivers/bluetooth/btfm_slim_wcn3990.c
@@ -82,11 +82,12 @@ int btfm_slim_chrk_enable_port(struct btfmslim *btfmslim, uint8_t port_num,
uint8_t rxport, uint8_t enable)
{
int ret = 0;
- uint8_t reg_val = 0;
+ uint8_t reg_val = 0, en;
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 */
@@ -117,7 +118,8 @@ int btfm_slim_chrk_enable_port(struct btfmslim *btfmslim, uint8_t port_num,
reg = CHRK_SB_PGD_TX_PORTn_MULTI_CHNL_0(port_num);
ret = btfm_slim_write(btfmslim, reg, 1, &reg_val, IFD);
if (ret) {
- BTFMSLIM_ERR("failed to write (%d) reg 0x%x", ret, reg);
+ BTFMSLIM_ERR("failed to write (%d) reg 0x%x",
+ ret, reg);
goto error;
}
}
@@ -137,15 +139,15 @@ enable_disable_txport:
reg = CHRK_SB_PGD_PORT_TX_CFGN(port_num);
enable_disable_rxport:
- if (enable) {
- if (is_fm_port(port_num))
- reg_val = CHRK_SB_PGD_PORT_ENABLE |
- CHRK_SB_PGD_PORT_WM_L3;
- else
- reg_val = CHRK_SB_PGD_PORT_ENABLE |
- CHRK_SB_PGD_PORT_WM_LB;
- } else
- reg_val = CHRK_SB_PGD_PORT_DISABLE;
+ if (enable)
+ en = CHRK_SB_PGD_PORT_ENABLE;
+ else
+ en = CHRK_SB_PGD_PORT_DISABLE;
+
+ if (is_fm_port(port_num))
+ reg_val = en | CHRK_SB_PGD_PORT_WM_L8;
+ else
+ reg_val = enable ? en | CHRK_SB_PGD_PORT_WM_LB : en;
ret = btfm_slim_write(btfmslim, reg, 1, &reg_val, IFD);
if (ret)
diff --git a/drivers/bluetooth/btfm_slim_wcn3990.h b/drivers/bluetooth/btfm_slim_wcn3990.h
index f6a260096c91..b637ac581201 100644
--- a/drivers/bluetooth/btfm_slim_wcn3990.h
+++ b/drivers/bluetooth/btfm_slim_wcn3990.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
@@ -68,6 +68,7 @@
#define CHRK_SB_PGD_PORT_WM_L1 (0x1 << 1)
#define CHRK_SB_PGD_PORT_WM_L2 (0x2 << 1)
#define CHRK_SB_PGD_PORT_WM_L3 (0x3 << 1)
+#define CHRK_SB_PGD_PORT_WM_L8 (0x8 << 1)
#define CHRK_SB_PGD_PORT_WM_LB (0xB << 1)
#define CHRK_SB_PGD_PORT_RX_NUM 16
diff --git a/drivers/char/adsprpc.c b/drivers/char/adsprpc.c
index 774ac3538075..aba9010c5aa2 100644
--- a/drivers/char/adsprpc.c
+++ b/drivers/char/adsprpc.c
@@ -2402,16 +2402,16 @@ static ssize_t fastrpc_debugfs_read(struct file *filp, char __user *buffer,
spin_lock(&fl->hlock);
hlist_for_each_entry_safe(buf, n, &fl->bufs, hn) {
len += scnprintf(fileinfo + len, DEBUGFS_SIZE - len,
- "%s %p %s %p %s %llx\n", "buf:",
- buf, "buf->virt:", buf->virt,
- "buf->phys:", buf->phys);
+ "%s %pK %s %pK %s %llx\n", "buf:",
+ buf, "buf->virt:", buf->virt,
+ "buf->phys:", buf->phys);
}
len += scnprintf(fileinfo + len, DEBUGFS_SIZE - len,
"\n%s\n",
"LIST OF MAPS:");
hlist_for_each_entry_safe(map, n, &fl->maps, hn) {
len += scnprintf(fileinfo + len, DEBUGFS_SIZE - len,
- "%s %p %s %lx %s %llx\n",
+ "%s %pK %s %lx %s %llx\n",
"map:", map,
"map->va:", map->va,
"map->phys:", map->phys);
@@ -2421,7 +2421,7 @@ static ssize_t fastrpc_debugfs_read(struct file *filp, char __user *buffer,
"LIST OF PENDING SMQCONTEXTS:");
hlist_for_each_entry_safe(ictx, n, &fl->clst.pending, hn) {
len += scnprintf(fileinfo + len, DEBUGFS_SIZE - len,
- "%s %p %s %u %s %u %s %u\n",
+ "%s %pK %s %u %s %u %s %u\n",
"smqcontext:", ictx,
"sc:", ictx->sc,
"tid:", ictx->pid,
@@ -2432,7 +2432,7 @@ static ssize_t fastrpc_debugfs_read(struct file *filp, char __user *buffer,
"LIST OF INTERRUPTED SMQCONTEXTS:");
hlist_for_each_entry_safe(ictx, n, &fl->clst.interrupted, hn) {
len += scnprintf(fileinfo + len, DEBUGFS_SIZE - len,
- "%s %p %s %u %s %u %s %u\n",
+ "%s %pK %s %u %s %u %s %u\n",
"smqcontext:", ictx,
"sc:", ictx->sc,
"tid:", ictx->pid,
@@ -2700,6 +2700,10 @@ static long fastrpc_device_ioctl(struct file *file, unsigned int ioctl_num,
VERIFY(err, 0 == copy_from_user(&p.init, param, size));
if (err)
goto bail;
+ VERIFY(err, p.init.init.filelen >= 0 &&
+ p.init.init.memlen >= 0);
+ if (err)
+ goto bail;
VERIFY(err, 0 == fastrpc_init_process(fl, &p.init));
if (err)
goto bail;
diff --git a/drivers/char/ipmi/ipmi_msghandler.c b/drivers/char/ipmi/ipmi_msghandler.c
index a084a4751fa9..25372dc381d4 100644
--- a/drivers/char/ipmi/ipmi_msghandler.c
+++ b/drivers/char/ipmi/ipmi_msghandler.c
@@ -3877,6 +3877,9 @@ static void smi_recv_tasklet(unsigned long val)
* because the lower layer is allowed to hold locks while calling
* message delivery.
*/
+
+ rcu_read_lock();
+
if (!run_to_completion)
spin_lock_irqsave(&intf->xmit_msgs_lock, flags);
if (intf->curr_msg == NULL && !intf->in_shutdown) {
@@ -3899,6 +3902,8 @@ static void smi_recv_tasklet(unsigned long val)
if (newmsg)
intf->handlers->sender(intf->send_info, newmsg);
+ rcu_read_unlock();
+
handle_new_recv_msgs(intf);
}
diff --git a/drivers/char/ipmi/ipmi_ssif.c b/drivers/char/ipmi/ipmi_ssif.c
index 0d83cfb9708f..f53e8ba2c718 100644
--- a/drivers/char/ipmi/ipmi_ssif.c
+++ b/drivers/char/ipmi/ipmi_ssif.c
@@ -758,6 +758,11 @@ static void msg_done_handler(struct ssif_info *ssif_info, int result,
result, len, data[2]);
} else if (data[0] != (IPMI_NETFN_APP_REQUEST | 1) << 2
|| data[1] != IPMI_GET_MSG_FLAGS_CMD) {
+ /*
+ * Don't abort here, maybe it was a queued
+ * response to a previous command.
+ */
+ ipmi_ssif_unlock_cond(ssif_info, flags);
pr_warn(PFX "Invalid response getting flags: %x %x\n",
data[0], data[1]);
} else {
diff --git a/drivers/char/ipmi/ipmi_watchdog.c b/drivers/char/ipmi/ipmi_watchdog.c
index 096f0cef4da1..40d400fe5bb7 100644
--- a/drivers/char/ipmi/ipmi_watchdog.c
+++ b/drivers/char/ipmi/ipmi_watchdog.c
@@ -1162,10 +1162,11 @@ static int wdog_reboot_handler(struct notifier_block *this,
ipmi_watchdog_state = WDOG_TIMEOUT_NONE;
ipmi_set_timeout(IPMI_SET_TIMEOUT_NO_HB);
} else if (ipmi_watchdog_state != WDOG_TIMEOUT_NONE) {
- /* Set a long timer to let the reboot happens, but
- reboot if it hangs, but only if the watchdog
+ /* Set a long timer to let the reboot happen or
+ reset if it hangs, but only if the watchdog
timer was already running. */
- timeout = 120;
+ if (timeout < 120)
+ timeout = 120;
pretimeout = 0;
ipmi_watchdog_state = WDOG_TIMEOUT_RESET;
ipmi_set_timeout(IPMI_SET_TIMEOUT_NO_HB);
diff --git a/drivers/char/tpm/tpm-chip.c b/drivers/char/tpm/tpm-chip.c
index 6d56877b2e0a..a0d9ac6b6cc9 100644
--- a/drivers/char/tpm/tpm-chip.c
+++ b/drivers/char/tpm/tpm-chip.c
@@ -29,9 +29,8 @@
#include "tpm.h"
#include "tpm_eventlog.h"
-static DECLARE_BITMAP(dev_mask, TPM_NUM_DEVICES);
-static LIST_HEAD(tpm_chip_list);
-static DEFINE_SPINLOCK(driver_lock);
+DEFINE_IDR(dev_nums_idr);
+static DEFINE_MUTEX(idr_lock);
struct class *tpm_class;
dev_t tpm_devt;
@@ -92,20 +91,30 @@ EXPORT_SYMBOL_GPL(tpm_put_ops);
*/
struct tpm_chip *tpm_chip_find_get(int chip_num)
{
- struct tpm_chip *pos, *chip = NULL;
+ struct tpm_chip *chip, *res = NULL;
+ int chip_prev;
+
+ mutex_lock(&idr_lock);
+
+ if (chip_num == TPM_ANY_NUM) {
+ chip_num = 0;
+ do {
+ chip_prev = chip_num;
+ chip = idr_get_next(&dev_nums_idr, &chip_num);
+ if (chip && !tpm_try_get_ops(chip)) {
+ res = chip;
+ break;
+ }
+ } while (chip_prev != chip_num);
+ } else {
+ chip = idr_find_slowpath(&dev_nums_idr, chip_num);
+ if (chip && !tpm_try_get_ops(chip))
+ res = chip;
+ }
- rcu_read_lock();
- list_for_each_entry_rcu(pos, &tpm_chip_list, list) {
- if (chip_num != TPM_ANY_NUM && chip_num != pos->dev_num)
- continue;
+ mutex_unlock(&idr_lock);
- /* rcu prevents chip from being free'd */
- if (!tpm_try_get_ops(pos))
- chip = pos;
- break;
- }
- rcu_read_unlock();
- return chip;
+ return res;
}
/**
@@ -118,9 +127,10 @@ static void tpm_dev_release(struct device *dev)
{
struct tpm_chip *chip = container_of(dev, struct tpm_chip, dev);
- spin_lock(&driver_lock);
- clear_bit(chip->dev_num, dev_mask);
- spin_unlock(&driver_lock);
+ mutex_lock(&idr_lock);
+ idr_remove(&dev_nums_idr, chip->dev_num);
+ mutex_unlock(&idr_lock);
+
kfree(chip);
}
@@ -173,6 +183,7 @@ struct tpm_chip *tpmm_chip_alloc(struct device *dev,
const struct tpm_class_ops *ops)
{
struct tpm_chip *chip;
+ int rc;
chip = kzalloc(sizeof(*chip), GFP_KERNEL);
if (chip == NULL)
@@ -180,21 +191,18 @@ struct tpm_chip *tpmm_chip_alloc(struct device *dev,
mutex_init(&chip->tpm_mutex);
init_rwsem(&chip->ops_sem);
- INIT_LIST_HEAD(&chip->list);
chip->ops = ops;
- spin_lock(&driver_lock);
- chip->dev_num = find_first_zero_bit(dev_mask, TPM_NUM_DEVICES);
- spin_unlock(&driver_lock);
-
- if (chip->dev_num >= TPM_NUM_DEVICES) {
+ mutex_lock(&idr_lock);
+ rc = idr_alloc(&dev_nums_idr, NULL, 0, TPM_NUM_DEVICES, GFP_KERNEL);
+ mutex_unlock(&idr_lock);
+ if (rc < 0) {
dev_err(dev, "No available tpm device numbers\n");
kfree(chip);
- return ERR_PTR(-ENOMEM);
+ return ERR_PTR(rc);
}
-
- set_bit(chip->dev_num, dev_mask);
+ chip->dev_num = rc;
scnprintf(chip->devname, sizeof(chip->devname), "tpm%d", chip->dev_num);
@@ -252,19 +260,28 @@ static int tpm_add_char_device(struct tpm_chip *chip)
return rc;
}
+ /* Make the chip available. */
+ mutex_lock(&idr_lock);
+ idr_replace(&dev_nums_idr, chip, chip->dev_num);
+ mutex_unlock(&idr_lock);
+
return rc;
}
static void tpm_del_char_device(struct tpm_chip *chip)
{
cdev_del(&chip->cdev);
+ device_del(&chip->dev);
+
+ /* Make the chip unavailable. */
+ mutex_lock(&idr_lock);
+ idr_replace(&dev_nums_idr, NULL, chip->dev_num);
+ mutex_unlock(&idr_lock);
/* Make the driver uncallable. */
down_write(&chip->ops_sem);
chip->ops = NULL;
up_write(&chip->ops_sem);
-
- device_del(&chip->dev);
}
static int tpm1_chip_register(struct tpm_chip *chip)
@@ -319,11 +336,6 @@ int tpm_chip_register(struct tpm_chip *chip)
if (rc)
goto out_err;
- /* Make the chip available. */
- spin_lock(&driver_lock);
- list_add_tail_rcu(&chip->list, &tpm_chip_list);
- spin_unlock(&driver_lock);
-
chip->flags |= TPM_CHIP_FLAG_REGISTERED;
if (!(chip->flags & TPM_CHIP_FLAG_TPM2)) {
@@ -360,11 +372,6 @@ void tpm_chip_unregister(struct tpm_chip *chip)
if (!(chip->flags & TPM_CHIP_FLAG_REGISTERED))
return;
- spin_lock(&driver_lock);
- list_del_rcu(&chip->list);
- spin_unlock(&driver_lock);
- synchronize_rcu();
-
if (!(chip->flags & TPM_CHIP_FLAG_TPM2))
sysfs_remove_link(&chip->dev.parent->kobj, "ppi");
diff --git a/drivers/char/tpm/tpm-interface.c b/drivers/char/tpm/tpm-interface.c
index 8588f2e4b9af..aaa5fa95dede 100644
--- a/drivers/char/tpm/tpm-interface.c
+++ b/drivers/char/tpm/tpm-interface.c
@@ -1127,6 +1127,7 @@ static int __init tpm_init(void)
static void __exit tpm_exit(void)
{
+ idr_destroy(&dev_nums_idr);
class_destroy(tpm_class);
unregister_chrdev_region(tpm_devt, TPM_NUM_DEVICES);
}
diff --git a/drivers/char/tpm/tpm-sysfs.c b/drivers/char/tpm/tpm-sysfs.c
index 6a4056a3f7ee..06ac6e9657d2 100644
--- a/drivers/char/tpm/tpm-sysfs.c
+++ b/drivers/char/tpm/tpm-sysfs.c
@@ -38,6 +38,8 @@ static ssize_t pubek_show(struct device *dev, struct device_attribute *attr,
struct tpm_chip *chip = dev_get_drvdata(dev);
+ memset(&tpm_cmd, 0, sizeof(tpm_cmd));
+
tpm_cmd.header.in = tpm_readpubek_header;
err = tpm_transmit_cmd(chip, &tpm_cmd, READ_PUBEK_RESULT_SIZE, 0,
"attempting to read the PUBEK");
diff --git a/drivers/char/tpm/tpm.h b/drivers/char/tpm/tpm.h
index e21e2c599e66..772d99b3a8e4 100644
--- a/drivers/char/tpm/tpm.h
+++ b/drivers/char/tpm/tpm.h
@@ -34,7 +34,7 @@
enum tpm_const {
TPM_MINOR = 224, /* officially assigned */
TPM_BUFSIZE = 4096,
- TPM_NUM_DEVICES = 256,
+ TPM_NUM_DEVICES = 65536,
TPM_RETRY = 50, /* 5 seconds */
};
@@ -200,8 +200,6 @@ struct tpm_chip {
acpi_handle acpi_dev_handle;
char ppi_version[TPM_PPI_VERSION_LEN + 1];
#endif /* CONFIG_ACPI */
-
- struct list_head list;
};
#define to_tpm_chip(d) container_of(d, struct tpm_chip, dev)
@@ -497,6 +495,7 @@ static inline void tpm_buf_append_u32(struct tpm_buf *buf, const u32 value)
extern struct class *tpm_class;
extern dev_t tpm_devt;
extern const struct file_operations tpm_fops;
+extern struct idr dev_nums_idr;
enum tpm_transmit_flags {
TPM_TRANSMIT_UNLOCKED = BIT(0),
diff --git a/drivers/clk/msm/clock-osm.c b/drivers/clk/msm/clock-osm.c
index 72a75873b810..eb72217b9b1c 100644
--- a/drivers/clk/msm/clock-osm.c
+++ b/drivers/clk/msm/clock-osm.c
@@ -397,6 +397,7 @@ struct clk_osm {
u32 acd_extint1_cfg;
u32 acd_autoxfer_ctl;
u32 acd_debugfs_addr;
+ u32 acd_debugfs_addr_size;
bool acd_init;
bool secure_init;
bool red_fsm_en;
@@ -1449,6 +1450,7 @@ static int clk_osm_resources_init(struct platform_device *pdev)
return -ENOMEM;
}
pwrcl_clk.pbases[ACD_BASE] = pbase;
+ pwrcl_clk.acd_debugfs_addr_size = resource_size(res);
pwrcl_clk.vbases[ACD_BASE] = vbase;
pwrcl_clk.acd_init = true;
} else {
@@ -1466,6 +1468,7 @@ static int clk_osm_resources_init(struct platform_device *pdev)
return -ENOMEM;
}
perfcl_clk.pbases[ACD_BASE] = pbase;
+ perfcl_clk.acd_debugfs_addr_size = resource_size(res);
perfcl_clk.vbases[ACD_BASE] = vbase;
perfcl_clk.acd_init = true;
} else {
@@ -3015,6 +3018,11 @@ static int debugfs_get_debug_reg(void *data, u64 *val)
{
struct clk_osm *c = data;
+ if (!c->pbases[ACD_BASE]) {
+ pr_err("ACD base start not defined\n");
+ return -EINVAL;
+ }
+
if (c->acd_debugfs_addr >= ACD_MASTER_ONLY_REG_ADDR)
*val = readl_relaxed((char *)c->vbases[ACD_BASE] +
c->acd_debugfs_addr);
@@ -3027,6 +3035,11 @@ static int debugfs_set_debug_reg(void *data, u64 val)
{
struct clk_osm *c = data;
+ if (!c->pbases[ACD_BASE]) {
+ pr_err("ACD base start not defined\n");
+ return -EINVAL;
+ }
+
if (c->acd_debugfs_addr >= ACD_MASTER_ONLY_REG_ADDR)
clk_osm_acd_master_write_reg(c, val, c->acd_debugfs_addr);
else
@@ -3044,7 +3057,13 @@ static int debugfs_get_debug_reg_addr(void *data, u64 *val)
{
struct clk_osm *c = data;
+ if (!c->pbases[ACD_BASE]) {
+ pr_err("ACD base start not defined\n");
+ return -EINVAL;
+ }
+
*val = c->acd_debugfs_addr;
+
return 0;
}
@@ -3052,7 +3071,16 @@ static int debugfs_set_debug_reg_addr(void *data, u64 val)
{
struct clk_osm *c = data;
+ if (!c->pbases[ACD_BASE]) {
+ pr_err("ACD base start not defined\n");
+ return -EINVAL;
+ }
+
+ if (val >= c->acd_debugfs_addr_size)
+ return -EINVAL;
+
c->acd_debugfs_addr = val;
+
return 0;
}
DEFINE_SIMPLE_ATTRIBUTE(debugfs_acd_debug_reg_addr_fops,
diff --git a/drivers/clk/qcom/clk-cpu-osm.c b/drivers/clk/qcom/clk-cpu-osm.c
index d99e13817a29..ddaeca1b29e4 100644
--- a/drivers/clk/qcom/clk-cpu-osm.c
+++ b/drivers/clk/qcom/clk-cpu-osm.c
@@ -384,6 +384,7 @@ struct clk_osm {
u32 acd_extint1_cfg;
u32 acd_autoxfer_ctl;
u32 acd_debugfs_addr;
+ u32 acd_debugfs_addr_size;
bool acd_init;
bool secure_init;
bool red_fsm_en;
@@ -1371,6 +1372,7 @@ static int clk_osm_resources_init(struct platform_device *pdev)
return -ENOMEM;
}
pwrcl_clk.pbases[ACD_BASE] = pbase;
+ pwrcl_clk.acd_debugfs_addr_size = resource_size(res);
pwrcl_clk.vbases[ACD_BASE] = vbase;
pwrcl_clk.acd_init = true;
} else {
@@ -1388,6 +1390,7 @@ static int clk_osm_resources_init(struct platform_device *pdev)
return -ENOMEM;
}
perfcl_clk.pbases[ACD_BASE] = pbase;
+ perfcl_clk.acd_debugfs_addr_size = resource_size(res);
perfcl_clk.vbases[ACD_BASE] = vbase;
perfcl_clk.acd_init = true;
} else {
@@ -2832,6 +2835,11 @@ static int debugfs_get_debug_reg(void *data, u64 *val)
{
struct clk_osm *c = data;
+ if (!c->pbases[ACD_BASE]) {
+ pr_err("ACD base start not defined\n");
+ return -EINVAL;
+ }
+
if (c->acd_debugfs_addr >= ACD_MASTER_ONLY_REG_ADDR)
*val = readl_relaxed((char *)c->vbases[ACD_BASE] +
c->acd_debugfs_addr);
@@ -2844,6 +2852,11 @@ static int debugfs_set_debug_reg(void *data, u64 val)
{
struct clk_osm *c = data;
+ if (!c->pbases[ACD_BASE]) {
+ pr_err("ACD base start not defined\n");
+ return -EINVAL;
+ }
+
if (c->acd_debugfs_addr >= ACD_MASTER_ONLY_REG_ADDR)
clk_osm_acd_master_write_reg(c, val, c->acd_debugfs_addr);
else
@@ -2861,7 +2874,13 @@ static int debugfs_get_debug_reg_addr(void *data, u64 *val)
{
struct clk_osm *c = data;
+ if (!c->pbases[ACD_BASE]) {
+ pr_err("ACD base start not defined\n");
+ return -EINVAL;
+ }
+
*val = c->acd_debugfs_addr;
+
return 0;
}
@@ -2869,6 +2888,14 @@ static int debugfs_set_debug_reg_addr(void *data, u64 val)
{
struct clk_osm *c = data;
+ if (!c->pbases[ACD_BASE]) {
+ pr_err("ACD base start not defined\n");
+ return -EINVAL;
+ }
+
+ if (val >= c->acd_debugfs_addr_size)
+ return -EINVAL;
+
c->acd_debugfs_addr = val;
return 0;
}
diff --git a/drivers/dma/ioat/hw.h b/drivers/dma/ioat/hw.h
index 690e3b4f8202..b36da3c1073f 100644
--- a/drivers/dma/ioat/hw.h
+++ b/drivers/dma/ioat/hw.h
@@ -64,6 +64,8 @@
#define PCI_DEVICE_ID_INTEL_IOAT_BDX8 0x6f2e
#define PCI_DEVICE_ID_INTEL_IOAT_BDX9 0x6f2f
+#define PCI_DEVICE_ID_INTEL_IOAT_SKX 0x2021
+
#define IOAT_VER_1_2 0x12 /* Version 1.2 */
#define IOAT_VER_2_0 0x20 /* Version 2.0 */
#define IOAT_VER_3_0 0x30 /* Version 3.0 */
diff --git a/drivers/dma/ioat/init.c b/drivers/dma/ioat/init.c
index 4ef0c5e07912..abb75ebd65ea 100644
--- a/drivers/dma/ioat/init.c
+++ b/drivers/dma/ioat/init.c
@@ -105,6 +105,8 @@ static struct pci_device_id ioat_pci_tbl[] = {
{ PCI_VDEVICE(INTEL, PCI_DEVICE_ID_INTEL_IOAT_BDX8) },
{ PCI_VDEVICE(INTEL, PCI_DEVICE_ID_INTEL_IOAT_BDX9) },
+ { PCI_VDEVICE(INTEL, PCI_DEVICE_ID_INTEL_IOAT_SKX) },
+
/* I/OAT v3.3 platforms */
{ PCI_VDEVICE(INTEL, PCI_DEVICE_ID_INTEL_IOAT_BWD0) },
{ PCI_VDEVICE(INTEL, PCI_DEVICE_ID_INTEL_IOAT_BWD1) },
@@ -250,10 +252,15 @@ static bool is_bdx_ioat(struct pci_dev *pdev)
}
}
+static inline bool is_skx_ioat(struct pci_dev *pdev)
+{
+ return (pdev->device == PCI_DEVICE_ID_INTEL_IOAT_SKX) ? true : false;
+}
+
static bool is_xeon_cb32(struct pci_dev *pdev)
{
return is_jf_ioat(pdev) || is_snb_ioat(pdev) || is_ivb_ioat(pdev) ||
- is_hsw_ioat(pdev) || is_bdx_ioat(pdev);
+ is_hsw_ioat(pdev) || is_bdx_ioat(pdev) || is_skx_ioat(pdev);
}
bool is_bwd_ioat(struct pci_dev *pdev)
@@ -1350,6 +1357,8 @@ static int ioat_pci_probe(struct pci_dev *pdev, const struct pci_device_id *id)
device->version = readb(device->reg_base + IOAT_VER_OFFSET);
if (device->version >= IOAT_VER_3_0) {
+ if (is_skx_ioat(pdev))
+ device->version = IOAT_VER_3_2;
err = ioat3_dma_probe(device, ioat_dca_enabled);
if (device->version >= IOAT_VER_3_3)
diff --git a/drivers/dma/ti-dma-crossbar.c b/drivers/dma/ti-dma-crossbar.c
index a415edbe61b1..149ec2bd9bc6 100644
--- a/drivers/dma/ti-dma-crossbar.c
+++ b/drivers/dma/ti-dma-crossbar.c
@@ -146,6 +146,7 @@ static int ti_am335x_xbar_probe(struct platform_device *pdev)
match = of_match_node(ti_am335x_master_match, dma_node);
if (!match) {
dev_err(&pdev->dev, "DMA master is not supported\n");
+ of_node_put(dma_node);
return -EINVAL;
}
@@ -310,6 +311,7 @@ static int ti_dra7_xbar_probe(struct platform_device *pdev)
match = of_match_node(ti_dra7_master_match, dma_node);
if (!match) {
dev_err(&pdev->dev, "DMA master is not supported\n");
+ of_node_put(dma_node);
return -EINVAL;
}
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.c
index 475c38fe9245..e40a6d8b0b92 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.c
@@ -1126,6 +1126,9 @@ static ssize_t amdgpu_ttm_vram_read(struct file *f, char __user *buf,
if (size & 0x3 || *pos & 0x3)
return -EINVAL;
+ if (*pos >= adev->mc.mc_vram_size)
+ return -ENXIO;
+
while (size) {
unsigned long flags;
uint32_t value;
diff --git a/drivers/gpu/drm/drm_dp_mst_topology.c b/drivers/gpu/drm/drm_dp_mst_topology.c
index a3b96d691ac9..58bf94b69186 100644
--- a/drivers/gpu/drm/drm_dp_mst_topology.c
+++ b/drivers/gpu/drm/drm_dp_mst_topology.c
@@ -330,6 +330,13 @@ static bool drm_dp_sideband_msg_build(struct drm_dp_sideband_msg_rx *msg,
return false;
}
+ /*
+ * ignore out-of-order messages or messages that are part of a
+ * failed transaction
+ */
+ if (!recv_hdr.somt && !msg->have_somt)
+ return false;
+
/* get length contained in this portion */
msg->curchunk_len = recv_hdr.msg_len;
msg->curchunk_hdrlen = hdrlen;
@@ -2163,7 +2170,7 @@ out_unlock:
}
EXPORT_SYMBOL(drm_dp_mst_topology_mgr_resume);
-static void drm_dp_get_one_sb_msg(struct drm_dp_mst_topology_mgr *mgr, bool up)
+static bool drm_dp_get_one_sb_msg(struct drm_dp_mst_topology_mgr *mgr, bool up)
{
int len;
u8 replyblock[32];
@@ -2178,12 +2185,12 @@ static void drm_dp_get_one_sb_msg(struct drm_dp_mst_topology_mgr *mgr, bool up)
replyblock, len);
if (ret != len) {
DRM_DEBUG_KMS("failed to read DPCD down rep %d %d\n", len, ret);
- return;
+ return false;
}
ret = drm_dp_sideband_msg_build(msg, replyblock, len, true);
if (!ret) {
DRM_DEBUG_KMS("sideband msg build failed %d\n", replyblock[0]);
- return;
+ return false;
}
replylen = msg->curchunk_len + msg->curchunk_hdrlen;
@@ -2195,21 +2202,32 @@ static void drm_dp_get_one_sb_msg(struct drm_dp_mst_topology_mgr *mgr, bool up)
ret = drm_dp_dpcd_read(mgr->aux, basereg + curreply,
replyblock, len);
if (ret != len) {
- DRM_DEBUG_KMS("failed to read a chunk\n");
+ DRM_DEBUG_KMS("failed to read a chunk (len %d, ret %d)\n",
+ len, ret);
+ return false;
}
+
ret = drm_dp_sideband_msg_build(msg, replyblock, len, false);
- if (ret == false)
+ if (!ret) {
DRM_DEBUG_KMS("failed to build sideband msg\n");
+ return false;
+ }
+
curreply += len;
replylen -= len;
}
+ return true;
}
static int drm_dp_mst_handle_down_rep(struct drm_dp_mst_topology_mgr *mgr)
{
int ret = 0;
- drm_dp_get_one_sb_msg(mgr, false);
+ if (!drm_dp_get_one_sb_msg(mgr, false)) {
+ memset(&mgr->down_rep_recv, 0,
+ sizeof(struct drm_dp_sideband_msg_rx));
+ return 0;
+ }
if (mgr->down_rep_recv.have_eomt) {
struct drm_dp_sideband_msg_tx *txmsg;
@@ -2265,7 +2283,12 @@ static int drm_dp_mst_handle_down_rep(struct drm_dp_mst_topology_mgr *mgr)
static int drm_dp_mst_handle_up_req(struct drm_dp_mst_topology_mgr *mgr)
{
int ret = 0;
- drm_dp_get_one_sb_msg(mgr, true);
+
+ if (!drm_dp_get_one_sb_msg(mgr, true)) {
+ memset(&mgr->up_req_recv, 0,
+ sizeof(struct drm_dp_sideband_msg_rx));
+ return 0;
+ }
if (mgr->up_req_recv.have_eomt) {
struct drm_dp_sideband_msg_req_body msg;
@@ -2317,7 +2340,9 @@ static int drm_dp_mst_handle_up_req(struct drm_dp_mst_topology_mgr *mgr)
DRM_DEBUG_KMS("Got RSN: pn: %d avail_pbn %d\n", msg.u.resource_stat.port_number, msg.u.resource_stat.available_pbn);
}
- drm_dp_put_mst_branch_device(mstb);
+ if (mstb)
+ drm_dp_put_mst_branch_device(mstb);
+
memset(&mgr->up_req_recv, 0, sizeof(struct drm_dp_sideband_msg_rx));
}
return ret;
diff --git a/drivers/gpu/drm/msm/adreno/a5xx_gpu.c b/drivers/gpu/drm/msm/adreno/a5xx_gpu.c
index 45a38b247727..765c1c087c76 100644
--- a/drivers/gpu/drm/msm/adreno/a5xx_gpu.c
+++ b/drivers/gpu/drm/msm/adreno/a5xx_gpu.c
@@ -15,6 +15,7 @@
#include "msm_iommu.h"
#include "msm_trace.h"
#include "a5xx_gpu.h"
+#include <linux/clk/msm-clk.h>
#define SECURE_VA_START 0xc0000000
#define SECURE_VA_SIZE SZ_256M
@@ -1169,6 +1170,17 @@ static int a5xx_pm_resume(struct msm_gpu *gpu)
{
int ret;
+ /*
+ * Between suspend/resumes the GPU clocks need to be turned off
+ * but not a complete power down, typically between frames. Set the
+ * memory retention flags on the GPU core clock to retain memory
+ * across clock toggles.
+ */
+ if (gpu->core_clk) {
+ clk_set_flags(gpu->core_clk, CLKFLAG_RETAIN_PERIPH);
+ clk_set_flags(gpu->core_clk, CLKFLAG_RETAIN_MEM);
+ }
+
/* Turn on the core power */
ret = msm_gpu_pm_resume(gpu);
if (ret)
@@ -1208,6 +1220,12 @@ static int a5xx_pm_suspend(struct msm_gpu *gpu)
{
struct adreno_gpu *adreno_gpu = to_adreno_gpu(gpu);
+ /* Turn off the memory retention flag when not necessary */
+ if (gpu->core_clk) {
+ clk_set_flags(gpu->core_clk, CLKFLAG_NORETAIN_PERIPH);
+ clk_set_flags(gpu->core_clk, CLKFLAG_NORETAIN_MEM);
+ }
+
/* Only do this next bit if we are about to go down */
if (gpu->active_cnt == 1) {
/* Clear the VBIF pipe before shutting down */
diff --git a/drivers/gpu/drm/msm/adreno/adreno_device.c b/drivers/gpu/drm/msm/adreno/adreno_device.c
index a498a60cd52d..4e4709d6172f 100644
--- a/drivers/gpu/drm/msm/adreno/adreno_device.c
+++ b/drivers/gpu/drm/msm/adreno/adreno_device.c
@@ -173,6 +173,9 @@ struct msm_gpu *adreno_load_gpu(struct drm_device *dev)
ret = gpu->funcs->hw_init(gpu);
if (ret) {
dev_err(dev->dev, "gpu hw init failed: %d\n", ret);
+ mutex_lock(&dev->struct_mutex);
+ gpu->funcs->pm_suspend(gpu);
+ mutex_unlock(&dev->struct_mutex);
gpu->funcs->destroy(gpu);
gpu = NULL;
} else {
diff --git a/drivers/gpu/drm/msm/msm_gem.h b/drivers/gpu/drm/msm/msm_gem.h
index df9ddadc5c5c..0cd458fd184b 100644
--- a/drivers/gpu/drm/msm/msm_gem.h
+++ b/drivers/gpu/drm/msm/msm_gem.h
@@ -149,7 +149,6 @@ struct msm_gem_submit {
uint32_t fence;
int ring;
u32 flags;
- bool valid;
uint64_t profile_buf_iova;
struct drm_msm_gem_submit_profile_buffer *profile_buf;
bool secure;
diff --git a/drivers/gpu/drm/msm/msm_gem_submit.c b/drivers/gpu/drm/msm/msm_gem_submit.c
index b73379aa9ed7..f2b6aa29b410 100644
--- a/drivers/gpu/drm/msm/msm_gem_submit.c
+++ b/drivers/gpu/drm/msm/msm_gem_submit.c
@@ -212,15 +212,8 @@ static int submit_validate_objects(struct msm_gpu *gpu,
int contended, slow_locked = -1, i, ret = 0;
retry:
- submit->valid = true;
-
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;
@@ -247,28 +240,6 @@ retry:
goto fail;
}
}
-
- /* if locking succeeded, pin bo: */
- ret = msm_gem_get_iova(&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
- * let's notice if this starts happening in the future:
- */
- WARN_ON(ret == -EDEADLK);
-
- if (ret)
- goto fail;
-
- submit->bos[i].flags |= BO_PINNED;
-
- if (iova == submit->bos[i].iova) {
- submit->bos[i].flags |= BO_VALID;
- } else {
- submit->bos[i].iova = iova;
- submit->bos[i].flags &= ~BO_VALID;
- submit->valid = false;
- }
}
ww_acquire_done(&submit->ticket);
@@ -297,9 +268,14 @@ fail:
return ret;
}
-static int submit_bo(struct msm_gem_submit *submit, uint32_t idx,
+static int submit_bo(struct msm_gpu *gpu,
+ struct msm_gem_submit *submit, uint32_t idx,
struct msm_gem_object **obj, uint64_t *iova, bool *valid)
{
+ struct msm_gem_object *msm_obj;
+ struct msm_gem_address_space *aspace;
+ int ret;
+
if (idx >= submit->nr_bos) {
DRM_ERROR("invalid buffer index: %u (out of %u)\n",
idx, submit->nr_bos);
@@ -308,6 +284,39 @@ static int submit_bo(struct msm_gem_submit *submit, uint32_t idx,
if (obj)
*obj = submit->bos[idx].obj;
+
+ /* Only map and pin if the caller needs either the iova or valid */
+ if (!iova && !valid)
+ return 0;
+
+ if (!(submit->bos[idx].flags & BO_PINNED)) {
+ uint64_t buf_iova;
+
+ msm_obj = submit->bos[idx].obj;
+ aspace = (msm_obj->flags & MSM_BO_SECURE) ?
+ gpu->secure_aspace : submit->aspace;
+
+ ret = msm_gem_get_iova(&msm_obj->base, aspace, &buf_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
+ * let's notice if this starts happening in the future:
+ */
+ WARN_ON(ret == -EDEADLK);
+
+ if (ret)
+ return ret;
+
+ submit->bos[idx].flags |= BO_PINNED;
+
+ if (buf_iova == submit->bos[idx].iova) {
+ submit->bos[idx].flags |= BO_VALID;
+ } else {
+ submit->bos[idx].iova = buf_iova;
+ submit->bos[idx].flags &= ~BO_VALID;
+ }
+ }
+
if (iova)
*iova = submit->bos[idx].iova;
if (valid)
@@ -317,8 +326,10 @@ static int submit_bo(struct msm_gem_submit *submit, uint32_t idx,
}
/* process the reloc's and patch up the cmdstream as needed: */
-static int submit_reloc(struct msm_gem_submit *submit, struct msm_gem_object *obj,
- uint32_t offset, uint32_t nr_relocs, uint64_t relocs)
+static int submit_reloc(struct msm_gpu *gpu,
+ struct msm_gem_submit *submit,
+ struct msm_gem_object *obj, uint32_t offset,
+ uint32_t nr_relocs, uint64_t relocs)
{
uint32_t i, last_offset = 0;
uint32_t *ptr;
@@ -334,6 +345,9 @@ static int submit_reloc(struct msm_gem_submit *submit, struct msm_gem_object *ob
return -EINVAL;
}
+ if (nr_relocs == 0)
+ return 0;
+
/* For now, just map the entire thing. Eventually we probably
* to do it page-by-page, w/ kmap() if not vmap()d..
*/
@@ -372,7 +386,8 @@ static int submit_reloc(struct msm_gem_submit *submit, struct msm_gem_object *ob
return -EINVAL;
}
- ret = submit_bo(submit, submit_reloc.reloc_idx, NULL, &iova, &valid);
+ ret = submit_bo(gpu, submit, submit_reloc.reloc_idx,
+ NULL, &iova, &valid);
if (ret)
return ret;
@@ -482,7 +497,7 @@ int msm_ioctl_gem_submit(struct drm_device *dev, void *data,
goto out;
}
- ret = submit_bo(submit, submit_cmd.submit_idx,
+ ret = submit_bo(gpu, submit, submit_cmd.submit_idx,
&msm_obj, &iova, NULL);
if (ret)
goto out;
@@ -515,11 +530,9 @@ int msm_ioctl_gem_submit(struct drm_device *dev, void *data,
+ submit_cmd.submit_offset;
}
- if (submit->valid)
- continue;
-
- ret = submit_reloc(submit, msm_obj, submit_cmd.submit_offset,
- submit_cmd.nr_relocs, submit_cmd.relocs);
+ ret = submit_reloc(gpu, submit, msm_obj,
+ submit_cmd.submit_offset, submit_cmd.nr_relocs,
+ submit_cmd.relocs);
if (ret)
goto out;
}
diff --git a/drivers/gpu/drm/msm/msm_gpu.c b/drivers/gpu/drm/msm/msm_gpu.c
index 9320437e923d..7c109fdab545 100644
--- a/drivers/gpu/drm/msm/msm_gpu.c
+++ b/drivers/gpu/drm/msm/msm_gpu.c
@@ -863,7 +863,14 @@ int msm_gpu_init(struct drm_device *drm, struct platform_device *pdev,
gpu->dev = drm;
gpu->funcs = funcs;
gpu->name = name;
- gpu->inactive = true;
+ /*
+ * Set the inactive flag to false, so that when the retire worker
+ * kicks in from the init path, it knows that it has to turn off the
+ * clocks. This should be fine to do since this is the init sequence
+ * and we have an init_lock in msm_open() to protect against bad things
+ * from happening.
+ */
+ gpu->inactive = false;
INIT_LIST_HEAD(&gpu->active_list);
INIT_WORK(&gpu->retire_work, retire_worker);
@@ -1028,4 +1035,22 @@ void msm_gpu_cleanup(struct msm_gpu *gpu)
msm_gpu_destroy_address_space(gpu->aspace);
msm_gpu_destroy_address_space(gpu->secure_aspace);
+
+ if (gpu->gpu_reg)
+ devm_regulator_put(gpu->gpu_reg);
+
+ if (gpu->gpu_cx)
+ devm_regulator_put(gpu->gpu_cx);
+
+ if (gpu->ebi1_clk)
+ devm_clk_put(&pdev->dev, gpu->ebi1_clk);
+
+ for (i = gpu->nr_clocks - 1; i >= 0; i--)
+ if (gpu->grp_clks[i])
+ devm_clk_put(&pdev->dev, gpu->grp_clks[i]);
+
+ devm_kfree(&pdev->dev, gpu->grp_clks);
+
+ if (gpu->mmio)
+ devm_iounmap(&pdev->dev, gpu->mmio);
}
diff --git a/drivers/gpu/drm/msm/sde/sde_color_processing.c b/drivers/gpu/drm/msm/sde/sde_color_processing.c
index ef7492817983..a0f6b5c6a732 100644
--- a/drivers/gpu/drm/msm/sde/sde_color_processing.c
+++ b/drivers/gpu/drm/msm/sde/sde_color_processing.c
@@ -344,8 +344,8 @@ static void sde_cp_crtc_install_immutable_property(struct drm_crtc *crtc,
prop = priv->cp_property[feature];
if (!prop) {
- prop = drm_property_create(crtc->dev, DRM_MODE_PROP_IMMUTABLE,
- name, 0);
+ prop = drm_property_create_range(crtc->dev,
+ DRM_MODE_PROP_IMMUTABLE, name, 0, 1);
if (!prop) {
DRM_ERROR("property create failed: %s\n", name);
kfree(prop_node);
diff --git a/drivers/gpu/drm/msm/sde/sde_crtc.c b/drivers/gpu/drm/msm/sde/sde_crtc.c
index 9ab216213d8e..2e9e2192670d 100644
--- a/drivers/gpu/drm/msm/sde/sde_crtc.c
+++ b/drivers/gpu/drm/msm/sde/sde_crtc.c
@@ -601,6 +601,7 @@ void sde_crtc_complete_commit(struct drm_crtc *crtc,
struct sde_crtc *sde_crtc;
struct sde_crtc_state *cstate;
struct drm_connector *conn;
+ struct sde_connector *c_conn;
struct drm_device *dev;
struct msm_drm_private *priv;
struct sde_kms *sde_kms;
@@ -625,16 +626,18 @@ void sde_crtc_complete_commit(struct drm_crtc *crtc,
for (i = 0; i < cstate->num_connectors; ++i)
sde_connector_complete_commit(cstate->connectors[i]);
- if (!sde_kms->splash_info.handoff &&
- sde_kms->splash_info.lk_is_exited) {
+ if (sde_splash_get_lk_complete_status(&sde_kms->splash_info)) {
mutex_lock(&dev->mode_config.mutex);
drm_for_each_connector(conn, crtc->dev) {
if (conn->state->crtc != crtc)
continue;
+ c_conn = to_sde_connector(conn);
+
sde_splash_clean_up_free_resource(priv->kms,
&priv->phandle,
- conn->connector_type);
+ c_conn->connector_type,
+ c_conn->display);
}
mutex_unlock(&dev->mode_config.mutex);
}
diff --git a/drivers/gpu/drm/msm/sde/sde_splash.c b/drivers/gpu/drm/msm/sde/sde_splash.c
index 79989f3ac1e9..19e6406600cd 100644
--- a/drivers/gpu/drm/msm/sde/sde_splash.c
+++ b/drivers/gpu/drm/msm/sde/sde_splash.c
@@ -22,6 +22,7 @@
#include "sde_hw_util.h"
#include "sde_hw_intf.h"
#include "sde_hw_catalog.h"
+#include "dsi_display.h"
#define MDP_SSPP_TOP0_OFF 0x1000
#define DISP_INTF_SEL 0x004
@@ -37,6 +38,9 @@
#define SDE_LK_EXIT_VALUE 0xDEADBEEF
#define SDE_LK_EXIT_MAX_LOOP 20
+
+static DEFINE_MUTEX(sde_splash_lock);
+
/*
* In order to free reseved memory from bootup, and we are not
* able to call the __init free functions, so we need to free
@@ -279,6 +283,15 @@ static void _sde_splash_destroy_splash_node(struct sde_splash_info *sinfo)
sinfo->splash_mem_size = NULL;
}
+static void _sde_splash_get_connector_ref_cnt(struct sde_splash_info *sinfo,
+ u32 *hdmi_cnt, u32 *dsi_cnt)
+{
+ mutex_lock(&sde_splash_lock);
+ *hdmi_cnt = sinfo->hdmi_connector_cnt;
+ *dsi_cnt = sinfo->dsi_connector_cnt;
+ mutex_unlock(&sde_splash_lock);
+}
+
static int _sde_splash_free_resource(struct msm_mmu *mmu,
struct sde_splash_info *sinfo, enum splash_connector_type conn)
{
@@ -442,13 +455,13 @@ int sde_splash_get_handoff_status(struct msm_kms *kms)
if (num_of_display_on) {
sinfo->handoff = true;
sinfo->program_scratch_regs = true;
+ sinfo->lk_is_exited = false;
} else {
sinfo->handoff = false;
sinfo->program_scratch_regs = false;
+ sinfo->lk_is_exited = true;
}
- sinfo->lk_is_exited = false;
-
return 0;
}
@@ -505,15 +518,29 @@ void sde_splash_setup_connector_count(struct sde_splash_info *sinfo,
}
}
+bool sde_splash_get_lk_complete_status(struct sde_splash_info *sinfo)
+{
+ bool ret = 0;
+
+ mutex_lock(&sde_splash_lock);
+ ret = !sinfo->handoff && !sinfo->lk_is_exited;
+ mutex_unlock(&sde_splash_lock);
+
+ return ret;
+}
+
int sde_splash_clean_up_free_resource(struct msm_kms *kms,
- struct sde_power_handle *phandle, int connector_type)
+ struct sde_power_handle *phandle,
+ int connector_type, void *display)
{
struct sde_kms *sde_kms;
struct sde_splash_info *sinfo;
struct msm_mmu *mmu;
+ struct dsi_display *dsi_display = display;
int ret = 0;
- static bool hdmi_is_released;
- static bool dsi_is_released;
+ int hdmi_conn_count = 0;
+ int dsi_conn_count = 0;
+ static const char *last_commit_display_type = "unknown";
if (!phandle || !kms) {
SDE_ERROR("invalid phandle/kms.\n");
@@ -527,16 +554,20 @@ int sde_splash_clean_up_free_resource(struct msm_kms *kms,
return -EINVAL;
}
- /* When both hdmi's and dsi's resource are freed,
- * 1. Destroy splash node objects.
- * 2. Release the memory which LK's stack is running on.
- * 3. Withdraw AHB data bus bandwidth voting.
- */
- if (sinfo->hdmi_connector_cnt == 0 &&
- sinfo->dsi_connector_cnt == 0) {
+ _sde_splash_get_connector_ref_cnt(sinfo, &hdmi_conn_count,
+ &dsi_conn_count);
+
+ mutex_lock(&sde_splash_lock);
+ if (hdmi_conn_count == 0 && dsi_conn_count == 0 &&
+ !sinfo->lk_is_exited) {
+ /* When both hdmi's and dsi's handoff are finished,
+ * 1. Destroy splash node objects.
+ * 2. Release the memory which LK's stack is running on.
+ * 3. Withdraw AHB data bus bandwidth voting.
+ */
DRM_INFO("HDMI and DSI resource handoff is completed\n");
- sinfo->lk_is_exited = false;
+ sinfo->lk_is_exited = true;
_sde_splash_destroy_splash_node(sinfo);
@@ -546,6 +577,7 @@ int sde_splash_clean_up_free_resource(struct msm_kms *kms,
sde_power_data_bus_bandwidth_ctrl(phandle,
sde_kms->core_client, false);
+ mutex_unlock(&sde_splash_lock);
return 0;
}
@@ -553,25 +585,36 @@ int sde_splash_clean_up_free_resource(struct msm_kms *kms,
switch (connector_type) {
case DRM_MODE_CONNECTOR_HDMIA:
- if (!hdmi_is_released)
+ if (sinfo->hdmi_connector_cnt == 1) {
sinfo->hdmi_connector_cnt--;
- if ((sinfo->hdmi_connector_cnt == 0) && (!hdmi_is_released)) {
- hdmi_is_released = true;
-
ret = _sde_splash_free_resource(mmu,
- sinfo, SPLASH_HDMI);
+ sinfo, SPLASH_HDMI);
}
break;
case DRM_MODE_CONNECTOR_DSI:
- if (!dsi_is_released)
- sinfo->dsi_connector_cnt--;
-
- if ((sinfo->dsi_connector_cnt == 0) && (!dsi_is_released)) {
- dsi_is_released = true;
+ /*
+ * Basically, we have commits coming on two DSI connectors.
+ * So when releasing DSI resource, it's ensured that the
+ * coming commits should happen on different DSIs, to promise
+ * the handoff has finished on the two DSIs, then it's safe
+ * to release DSI resource, otherwise, problem happens when
+ * freeing memory, while DSI0 or DSI1 is still visiting
+ * the memory.
+ */
+ if (strcmp(dsi_display->display_type, "unknown") &&
+ strcmp(last_commit_display_type,
+ dsi_display->display_type)) {
+ if (sinfo->dsi_connector_cnt > 1)
+ sinfo->dsi_connector_cnt--;
+ else if (sinfo->dsi_connector_cnt == 1) {
+ ret = _sde_splash_free_resource(mmu,
+ sinfo, SPLASH_DSI);
+
+ sinfo->dsi_connector_cnt--;
+ }
- ret = _sde_splash_free_resource(mmu,
- sinfo, SPLASH_DSI);
+ last_commit_display_type = dsi_display->display_type;
}
break;
default:
@@ -580,6 +623,8 @@ int sde_splash_clean_up_free_resource(struct msm_kms *kms,
__func__, connector_type);
}
+ mutex_unlock(&sde_splash_lock);
+
return ret;
}
@@ -603,6 +648,7 @@ int sde_splash_clean_up_exit_lk(struct msm_kms *kms)
}
/* Monitor LK's status and tell it to exit. */
+ mutex_lock(&sde_splash_lock);
if (sinfo->program_scratch_regs) {
if (_sde_splash_lk_check(sde_kms->hw_intr))
_sde_splash_notify_lk_exit(sde_kms->hw_intr);
@@ -610,6 +656,7 @@ int sde_splash_clean_up_exit_lk(struct msm_kms *kms)
sinfo->handoff = false;
sinfo->program_scratch_regs = false;
}
+ mutex_unlock(&sde_splash_lock);
if (!sde_kms->aspace[0] || !sde_kms->aspace[0]->mmu) {
/* We do not return fault value here, to ensure
@@ -631,6 +678,5 @@ int sde_splash_clean_up_exit_lk(struct msm_kms *kms)
}
}
- sinfo->lk_is_exited = true;
return 0;
}
diff --git a/drivers/gpu/drm/msm/sde/sde_splash.h b/drivers/gpu/drm/msm/sde/sde_splash.h
index 47965693f0b8..babf88335e49 100644
--- a/drivers/gpu/drm/msm/sde/sde_splash.h
+++ b/drivers/gpu/drm/msm/sde/sde_splash.h
@@ -95,7 +95,8 @@ int sde_splash_clean_up_exit_lk(struct msm_kms *kms);
* HDMI's and DSI's resource respectively.
*/
int sde_splash_clean_up_free_resource(struct msm_kms *kms,
- struct sde_power_handle *phandle, int connector_type);
+ struct sde_power_handle *phandle,
+ int connector_type, void *display);
/**
* sde_splash_parse_dt.
@@ -121,4 +122,11 @@ void sde_splash_destroy(struct sde_splash_info *sinfo,
struct sde_power_handle *phandle,
struct sde_power_client *pclient);
+/**
+ * sde_splash_get_lk_complete_status
+ *
+ * Get LK's status to check if it has been stopped.
+ */
+bool sde_splash_get_lk_complete_status(struct sde_splash_info *sinfo);
+
#endif
diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/bar/gf100.c b/drivers/gpu/drm/nouveau/nvkm/subdev/bar/gf100.c
index c794b2c2d21e..6d8f21290aa2 100644
--- a/drivers/gpu/drm/nouveau/nvkm/subdev/bar/gf100.c
+++ b/drivers/gpu/drm/nouveau/nvkm/subdev/bar/gf100.c
@@ -129,7 +129,7 @@ gf100_bar_init(struct nvkm_bar *base)
if (bar->bar[0].mem) {
addr = nvkm_memory_addr(bar->bar[0].mem) >> 12;
- nvkm_wr32(device, 0x001714, 0xc0000000 | addr);
+ nvkm_wr32(device, 0x001714, 0x80000000 | addr);
}
return 0;
diff --git a/drivers/gpu/drm/radeon/atombios_encoders.c b/drivers/gpu/drm/radeon/atombios_encoders.c
index d4ac8c837314..8e86cf7da614 100644
--- a/drivers/gpu/drm/radeon/atombios_encoders.c
+++ b/drivers/gpu/drm/radeon/atombios_encoders.c
@@ -30,6 +30,7 @@
#include "radeon_audio.h"
#include "atom.h"
#include <linux/backlight.h>
+#include <linux/dmi.h>
extern int atom_debug;
@@ -2183,9 +2184,17 @@ int radeon_atom_pick_dig_encoder(struct drm_encoder *encoder, int fe_idx)
goto assigned;
}
- /* on DCE32 and encoder can driver any block so just crtc id */
+ /*
+ * On DCE32 any encoder can drive any block so usually just use crtc id,
+ * but Apple thinks different at least on iMac10,1, so there use linkb,
+ * otherwise the internal eDP panel will stay dark.
+ */
if (ASIC_IS_DCE32(rdev)) {
- enc_idx = radeon_crtc->crtc_id;
+ if (dmi_match(DMI_PRODUCT_NAME, "iMac10,1"))
+ enc_idx = (dig->linkb) ? 1 : 0;
+ else
+ enc_idx = radeon_crtc->crtc_id;
+
goto assigned;
}
diff --git a/drivers/gpu/drm/radeon/ci_dpm.c b/drivers/gpu/drm/radeon/ci_dpm.c
index 3c32f095a873..2ccf81168d1e 100644
--- a/drivers/gpu/drm/radeon/ci_dpm.c
+++ b/drivers/gpu/drm/radeon/ci_dpm.c
@@ -782,6 +782,12 @@ bool ci_dpm_vblank_too_short(struct radeon_device *rdev)
if (r600_dpm_get_vrefresh(rdev) > 120)
return true;
+ /* disable mclk switching if the refresh is >120Hz, even if the
+ * blanking period would allow it
+ */
+ if (r600_dpm_get_vrefresh(rdev) > 120)
+ return true;
+
if (vblank_time < switch_limit)
return true;
else
diff --git a/drivers/gpu/drm/rcar-du/rcar_du_crtc.c b/drivers/gpu/drm/rcar-du/rcar_du_crtc.c
index 48cb19949ca3..9255b9c096b6 100644
--- a/drivers/gpu/drm/rcar-du/rcar_du_crtc.c
+++ b/drivers/gpu/drm/rcar-du/rcar_du_crtc.c
@@ -282,26 +282,6 @@ static void rcar_du_crtc_update_planes(struct rcar_du_crtc *rcrtc)
* Page Flip
*/
-void rcar_du_crtc_cancel_page_flip(struct rcar_du_crtc *rcrtc,
- struct drm_file *file)
-{
- struct drm_pending_vblank_event *event;
- struct drm_device *dev = rcrtc->crtc.dev;
- unsigned long flags;
-
- /* Destroy the pending vertical blanking event associated with the
- * pending page flip, if any, and disable vertical blanking interrupts.
- */
- spin_lock_irqsave(&dev->event_lock, flags);
- event = rcrtc->event;
- if (event && event->base.file_priv == file) {
- rcrtc->event = NULL;
- event->base.destroy(&event->base);
- drm_crtc_vblank_put(&rcrtc->crtc);
- }
- spin_unlock_irqrestore(&dev->event_lock, flags);
-}
-
static void rcar_du_crtc_finish_page_flip(struct rcar_du_crtc *rcrtc)
{
struct drm_pending_vblank_event *event;
diff --git a/drivers/gpu/drm/rcar-du/rcar_du_crtc.h b/drivers/gpu/drm/rcar-du/rcar_du_crtc.h
index 4b95d9d08c49..2bbe3f5aab65 100644
--- a/drivers/gpu/drm/rcar-du/rcar_du_crtc.h
+++ b/drivers/gpu/drm/rcar-du/rcar_du_crtc.h
@@ -67,8 +67,6 @@ enum rcar_du_output {
int rcar_du_crtc_create(struct rcar_du_group *rgrp, unsigned int index);
void rcar_du_crtc_enable_vblank(struct rcar_du_crtc *rcrtc, bool enable);
-void rcar_du_crtc_cancel_page_flip(struct rcar_du_crtc *rcrtc,
- struct drm_file *file);
void rcar_du_crtc_suspend(struct rcar_du_crtc *rcrtc);
void rcar_du_crtc_resume(struct rcar_du_crtc *rcrtc);
diff --git a/drivers/gpu/drm/rcar-du/rcar_du_drv.c b/drivers/gpu/drm/rcar-du/rcar_du_drv.c
index 40422f6b645e..bf4674aa6405 100644
--- a/drivers/gpu/drm/rcar-du/rcar_du_drv.c
+++ b/drivers/gpu/drm/rcar-du/rcar_du_drv.c
@@ -144,91 +144,6 @@ MODULE_DEVICE_TABLE(of, rcar_du_of_table);
* DRM operations
*/
-static int rcar_du_unload(struct drm_device *dev)
-{
- struct rcar_du_device *rcdu = dev->dev_private;
-
- if (rcdu->fbdev)
- drm_fbdev_cma_fini(rcdu->fbdev);
-
- drm_kms_helper_poll_fini(dev);
- drm_mode_config_cleanup(dev);
- drm_vblank_cleanup(dev);
-
- dev->irq_enabled = 0;
- dev->dev_private = NULL;
-
- return 0;
-}
-
-static int rcar_du_load(struct drm_device *dev, unsigned long flags)
-{
- struct platform_device *pdev = dev->platformdev;
- struct device_node *np = pdev->dev.of_node;
- struct rcar_du_device *rcdu;
- struct resource *mem;
- int ret;
-
- if (np == NULL) {
- dev_err(dev->dev, "no platform data\n");
- return -ENODEV;
- }
-
- rcdu = devm_kzalloc(&pdev->dev, sizeof(*rcdu), GFP_KERNEL);
- if (rcdu == NULL) {
- dev_err(dev->dev, "failed to allocate private data\n");
- return -ENOMEM;
- }
-
- init_waitqueue_head(&rcdu->commit.wait);
-
- rcdu->dev = &pdev->dev;
- rcdu->info = of_match_device(rcar_du_of_table, rcdu->dev)->data;
- rcdu->ddev = dev;
- dev->dev_private = rcdu;
-
- /* I/O resources */
- mem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
- rcdu->mmio = devm_ioremap_resource(&pdev->dev, mem);
- if (IS_ERR(rcdu->mmio))
- return PTR_ERR(rcdu->mmio);
-
- /* Initialize vertical blanking interrupts handling. Start with vblank
- * disabled for all CRTCs.
- */
- ret = drm_vblank_init(dev, (1 << rcdu->info->num_crtcs) - 1);
- if (ret < 0) {
- dev_err(&pdev->dev, "failed to initialize vblank\n");
- goto done;
- }
-
- /* DRM/KMS objects */
- ret = rcar_du_modeset_init(rcdu);
- if (ret < 0) {
- dev_err(&pdev->dev, "failed to initialize DRM/KMS (%d)\n", ret);
- goto done;
- }
-
- dev->irq_enabled = 1;
-
- platform_set_drvdata(pdev, rcdu);
-
-done:
- if (ret)
- rcar_du_unload(dev);
-
- return ret;
-}
-
-static void rcar_du_preclose(struct drm_device *dev, struct drm_file *file)
-{
- struct rcar_du_device *rcdu = dev->dev_private;
- unsigned int i;
-
- for (i = 0; i < rcdu->num_crtcs; ++i)
- rcar_du_crtc_cancel_page_flip(&rcdu->crtcs[i], file);
-}
-
static void rcar_du_lastclose(struct drm_device *dev)
{
struct rcar_du_device *rcdu = dev->dev_private;
@@ -269,11 +184,7 @@ static const struct file_operations rcar_du_fops = {
static struct drm_driver rcar_du_driver = {
.driver_features = DRIVER_GEM | DRIVER_MODESET | DRIVER_PRIME
| DRIVER_ATOMIC,
- .load = rcar_du_load,
- .unload = rcar_du_unload,
- .preclose = rcar_du_preclose,
.lastclose = rcar_du_lastclose,
- .set_busid = drm_platform_set_busid,
.get_vblank_counter = drm_vblank_no_hw_counter,
.enable_vblank = rcar_du_enable_vblank,
.disable_vblank = rcar_du_disable_vblank,
@@ -333,18 +244,104 @@ static const struct dev_pm_ops rcar_du_pm_ops = {
* Platform driver
*/
-static int rcar_du_probe(struct platform_device *pdev)
+static int rcar_du_remove(struct platform_device *pdev)
{
- return drm_platform_init(&rcar_du_driver, pdev);
+ struct rcar_du_device *rcdu = platform_get_drvdata(pdev);
+ struct drm_device *ddev = rcdu->ddev;
+
+ mutex_lock(&ddev->mode_config.mutex);
+ drm_connector_unplug_all(ddev);
+ mutex_unlock(&ddev->mode_config.mutex);
+
+ drm_dev_unregister(ddev);
+
+ if (rcdu->fbdev)
+ drm_fbdev_cma_fini(rcdu->fbdev);
+
+ drm_kms_helper_poll_fini(ddev);
+ drm_mode_config_cleanup(ddev);
+
+ drm_dev_unref(ddev);
+
+ return 0;
}
-static int rcar_du_remove(struct platform_device *pdev)
+static int rcar_du_probe(struct platform_device *pdev)
{
- struct rcar_du_device *rcdu = platform_get_drvdata(pdev);
+ struct device_node *np = pdev->dev.of_node;
+ struct rcar_du_device *rcdu;
+ struct drm_connector *connector;
+ struct drm_device *ddev;
+ struct resource *mem;
+ int ret;
+
+ if (np == NULL) {
+ dev_err(&pdev->dev, "no device tree node\n");
+ return -ENODEV;
+ }
+
+ /* Allocate and initialize the DRM and R-Car device structures. */
+ rcdu = devm_kzalloc(&pdev->dev, sizeof(*rcdu), GFP_KERNEL);
+ if (rcdu == NULL)
+ return -ENOMEM;
+
+ init_waitqueue_head(&rcdu->commit.wait);
+
+ rcdu->dev = &pdev->dev;
+ rcdu->info = of_match_device(rcar_du_of_table, rcdu->dev)->data;
+
+ platform_set_drvdata(pdev, rcdu);
- drm_put_dev(rcdu->ddev);
+ /* I/O resources */
+ mem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+ rcdu->mmio = devm_ioremap_resource(&pdev->dev, mem);
+ if (IS_ERR(rcdu->mmio))
+ ret = PTR_ERR(rcdu->mmio);
+
+ /* DRM/KMS objects */
+ ddev = drm_dev_alloc(&rcar_du_driver, &pdev->dev);
+ if (!ddev)
+ return -ENOMEM;
+
+ drm_dev_set_unique(ddev, dev_name(&pdev->dev));
+
+ rcdu->ddev = ddev;
+ ddev->dev_private = rcdu;
+
+ ret = rcar_du_modeset_init(rcdu);
+ if (ret < 0) {
+ dev_err(&pdev->dev, "failed to initialize DRM/KMS (%d)\n", ret);
+ goto error;
+ }
+
+ ddev->irq_enabled = 1;
+
+ /* Register the DRM device with the core and the connectors with
+ * sysfs.
+ */
+ ret = drm_dev_register(ddev, 0);
+ if (ret)
+ goto error;
+
+ mutex_lock(&ddev->mode_config.mutex);
+ drm_for_each_connector(connector, ddev) {
+ ret = drm_connector_register(connector);
+ if (ret < 0)
+ break;
+ }
+ mutex_unlock(&ddev->mode_config.mutex);
+
+ if (ret < 0)
+ goto error;
+
+ DRM_INFO("Device %s probed\n", dev_name(&pdev->dev));
return 0;
+
+error:
+ rcar_du_remove(pdev);
+
+ return ret;
}
static struct platform_driver rcar_du_platform_driver = {
diff --git a/drivers/gpu/drm/rcar-du/rcar_du_hdmicon.c b/drivers/gpu/drm/rcar-du/rcar_du_hdmicon.c
index 96f2eb43713c..6038be93c58d 100644
--- a/drivers/gpu/drm/rcar-du/rcar_du_hdmicon.c
+++ b/drivers/gpu/drm/rcar-du/rcar_du_hdmicon.c
@@ -55,12 +55,6 @@ static const struct drm_connector_helper_funcs connector_helper_funcs = {
.best_encoder = rcar_du_connector_best_encoder,
};
-static void rcar_du_hdmi_connector_destroy(struct drm_connector *connector)
-{
- drm_connector_unregister(connector);
- drm_connector_cleanup(connector);
-}
-
static enum drm_connector_status
rcar_du_hdmi_connector_detect(struct drm_connector *connector, bool force)
{
@@ -79,7 +73,7 @@ static const struct drm_connector_funcs connector_funcs = {
.reset = drm_atomic_helper_connector_reset,
.detect = rcar_du_hdmi_connector_detect,
.fill_modes = drm_helper_probe_single_connector_modes,
- .destroy = rcar_du_hdmi_connector_destroy,
+ .destroy = drm_connector_cleanup,
.atomic_duplicate_state = drm_atomic_helper_connector_duplicate_state,
.atomic_destroy_state = drm_atomic_helper_connector_destroy_state,
};
@@ -108,9 +102,6 @@ int rcar_du_hdmi_connector_init(struct rcar_du_device *rcdu,
return ret;
drm_connector_helper_add(connector, &connector_helper_funcs);
- ret = drm_connector_register(connector);
- if (ret < 0)
- return ret;
connector->dpms = DRM_MODE_DPMS_OFF;
drm_object_property_set_value(&connector->base,
diff --git a/drivers/gpu/drm/rcar-du/rcar_du_kms.c b/drivers/gpu/drm/rcar-du/rcar_du_kms.c
index ca12e8ca5552..46429c4be8e5 100644
--- a/drivers/gpu/drm/rcar-du/rcar_du_kms.c
+++ b/drivers/gpu/drm/rcar-du/rcar_du_kms.c
@@ -761,6 +761,13 @@ int rcar_du_modeset_init(struct rcar_du_device *rcdu)
if (ret < 0)
return ret;
+ /* Initialize vertical blanking interrupts handling. Start with vblank
+ * disabled for all CRTCs.
+ */
+ ret = drm_vblank_init(dev, (1 << rcdu->info->num_crtcs) - 1);
+ if (ret < 0)
+ return ret;
+
/* Initialize the groups. */
num_groups = DIV_ROUND_UP(rcdu->num_crtcs, 2);
diff --git a/drivers/gpu/drm/rcar-du/rcar_du_lvdscon.c b/drivers/gpu/drm/rcar-du/rcar_du_lvdscon.c
index 0c43032fc693..e905f5da7aaa 100644
--- a/drivers/gpu/drm/rcar-du/rcar_du_lvdscon.c
+++ b/drivers/gpu/drm/rcar-du/rcar_du_lvdscon.c
@@ -62,12 +62,6 @@ static const struct drm_connector_helper_funcs connector_helper_funcs = {
.best_encoder = rcar_du_connector_best_encoder,
};
-static void rcar_du_lvds_connector_destroy(struct drm_connector *connector)
-{
- drm_connector_unregister(connector);
- drm_connector_cleanup(connector);
-}
-
static enum drm_connector_status
rcar_du_lvds_connector_detect(struct drm_connector *connector, bool force)
{
@@ -79,7 +73,7 @@ static const struct drm_connector_funcs connector_funcs = {
.reset = drm_atomic_helper_connector_reset,
.detect = rcar_du_lvds_connector_detect,
.fill_modes = drm_helper_probe_single_connector_modes,
- .destroy = rcar_du_lvds_connector_destroy,
+ .destroy = drm_connector_cleanup,
.atomic_duplicate_state = drm_atomic_helper_connector_duplicate_state,
.atomic_destroy_state = drm_atomic_helper_connector_destroy_state,
};
@@ -117,9 +111,6 @@ int rcar_du_lvds_connector_init(struct rcar_du_device *rcdu,
return ret;
drm_connector_helper_add(connector, &connector_helper_funcs);
- ret = drm_connector_register(connector);
- if (ret < 0)
- return ret;
connector->dpms = DRM_MODE_DPMS_OFF;
drm_object_property_set_value(&connector->base,
diff --git a/drivers/gpu/drm/rcar-du/rcar_du_vgacon.c b/drivers/gpu/drm/rcar-du/rcar_du_vgacon.c
index e0a5d8f93963..9d7e5c99caf6 100644
--- a/drivers/gpu/drm/rcar-du/rcar_du_vgacon.c
+++ b/drivers/gpu/drm/rcar-du/rcar_du_vgacon.c
@@ -31,12 +31,6 @@ static const struct drm_connector_helper_funcs connector_helper_funcs = {
.best_encoder = rcar_du_connector_best_encoder,
};
-static void rcar_du_vga_connector_destroy(struct drm_connector *connector)
-{
- drm_connector_unregister(connector);
- drm_connector_cleanup(connector);
-}
-
static enum drm_connector_status
rcar_du_vga_connector_detect(struct drm_connector *connector, bool force)
{
@@ -48,7 +42,7 @@ static const struct drm_connector_funcs connector_funcs = {
.reset = drm_atomic_helper_connector_reset,
.detect = rcar_du_vga_connector_detect,
.fill_modes = drm_helper_probe_single_connector_modes,
- .destroy = rcar_du_vga_connector_destroy,
+ .destroy = drm_connector_cleanup,
.atomic_duplicate_state = drm_atomic_helper_connector_duplicate_state,
.atomic_destroy_state = drm_atomic_helper_connector_destroy_state,
};
@@ -76,9 +70,6 @@ int rcar_du_vga_connector_init(struct rcar_du_device *rcdu,
return ret;
drm_connector_helper_add(connector, &connector_helper_funcs);
- ret = drm_connector_register(connector);
- if (ret < 0)
- return ret;
connector->dpms = DRM_MODE_DPMS_OFF;
drm_object_property_set_value(&connector->base,
diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_execbuf.c b/drivers/gpu/drm/vmwgfx/vmwgfx_execbuf.c
index ecf15cf0c3fd..04fd0f2b6af0 100644
--- a/drivers/gpu/drm/vmwgfx/vmwgfx_execbuf.c
+++ b/drivers/gpu/drm/vmwgfx/vmwgfx_execbuf.c
@@ -471,7 +471,7 @@ static int vmw_cmd_invalid(struct vmw_private *dev_priv,
struct vmw_sw_context *sw_context,
SVGA3dCmdHeader *header)
{
- return capable(CAP_SYS_ADMIN) ? : -EINVAL;
+ return -EINVAL;
}
static int vmw_cmd_ok(struct vmw_private *dev_priv,
diff --git a/drivers/gpu/msm/adreno.c b/drivers/gpu/msm/adreno.c
index afa71116c691..7cab049771de 100644
--- a/drivers/gpu/msm/adreno.c
+++ b/drivers/gpu/msm/adreno.c
@@ -902,6 +902,9 @@ static int adreno_of_get_power(struct adreno_device *adreno_dev,
device->pwrctrl.bus_control = of_property_read_bool(node,
"qcom,bus-control");
+ device->pwrctrl.input_disable = of_property_read_bool(node,
+ "qcom,disable-wake-on-touch");
+
return 0;
}
@@ -1016,15 +1019,19 @@ static int adreno_probe(struct platform_device *pdev)
/* Initialize coresight for the target */
adreno_coresight_init(adreno_dev);
- adreno_input_handler.private = device;
-
#ifdef CONFIG_INPUT
- /*
- * It isn't fatal if we cannot register the input handler. Sad,
- * perhaps, but not fatal
- */
- if (input_register_handler(&adreno_input_handler))
- KGSL_DRV_ERR(device, "Unable to register the input handler\n");
+ if (!device->pwrctrl.input_disable) {
+ adreno_input_handler.private = device;
+ /*
+ * It isn't fatal if we cannot register the input handler. Sad,
+ * perhaps, but not fatal
+ */
+ if (input_register_handler(&adreno_input_handler)) {
+ adreno_input_handler.private = NULL;
+ KGSL_DRV_ERR(device,
+ "Unable to register the input handler\n");
+ }
+ }
#endif
out:
if (status) {
@@ -1076,7 +1083,8 @@ static int adreno_remove(struct platform_device *pdev)
_adreno_free_memories(adreno_dev);
#ifdef CONFIG_INPUT
- input_unregister_handler(&adreno_input_handler);
+ if (adreno_input_handler.private)
+ input_unregister_handler(&adreno_input_handler);
#endif
adreno_sysfs_close(adreno_dev);
diff --git a/drivers/gpu/msm/kgsl_pwrctrl.h b/drivers/gpu/msm/kgsl_pwrctrl.h
index 5c0071544f60..02707c901839 100644
--- a/drivers/gpu/msm/kgsl_pwrctrl.h
+++ b/drivers/gpu/msm/kgsl_pwrctrl.h
@@ -146,6 +146,7 @@ struct kgsl_regulator {
* @pm_qos_req_dma - the power management quality of service structure
* @pm_qos_active_latency - allowed CPU latency in microseconds when active
* @pm_qos_cpu_mask_latency - allowed CPU mask latency in microseconds
+ * @input_disable - To disable GPU wakeup on touch input event
* @pm_qos_wakeup_latency - allowed CPU latency in microseconds during wakeup
* @bus_control - true if the bus calculation is independent
* @bus_mod - modifier from the current power level for the bus vote
@@ -203,6 +204,7 @@ struct kgsl_pwrctrl {
unsigned int pm_qos_active_latency;
unsigned int pm_qos_cpu_mask_latency;
unsigned int pm_qos_wakeup_latency;
+ bool input_disable;
bool bus_control;
int bus_mod;
unsigned int bus_percent_ab;
diff --git a/drivers/hid/hid-core.c b/drivers/hid/hid-core.c
index 34ea83d067af..13dc2731195b 100644
--- a/drivers/hid/hid-core.c
+++ b/drivers/hid/hid-core.c
@@ -2428,6 +2428,7 @@ static const struct hid_device_id hid_ignore_list[] = {
{ HID_USB_DEVICE(USB_VENDOR_ID_PANJIT, 0x0002) },
{ HID_USB_DEVICE(USB_VENDOR_ID_PANJIT, 0x0003) },
{ HID_USB_DEVICE(USB_VENDOR_ID_PANJIT, 0x0004) },
+ { HID_USB_DEVICE(USB_VENDOR_ID_PETZL, USB_DEVICE_ID_PETZL_HEADLAMP) },
{ HID_USB_DEVICE(USB_VENDOR_ID_PHILIPS, USB_DEVICE_ID_PHILIPS_IEEE802154_DONGLE) },
{ HID_USB_DEVICE(USB_VENDOR_ID_POWERCOM, USB_DEVICE_ID_POWERCOM_UPS) },
#if defined(CONFIG_MOUSE_SYNAPTICS_USB) || defined(CONFIG_MOUSE_SYNAPTICS_USB_MODULE)
diff --git a/drivers/hid/hid-ids.h b/drivers/hid/hid-ids.h
index c7f8b70d15ee..37cbc2ecfc5f 100644
--- a/drivers/hid/hid-ids.h
+++ b/drivers/hid/hid-ids.h
@@ -777,6 +777,9 @@
#define USB_VENDOR_ID_PETALYNX 0x18b1
#define USB_DEVICE_ID_PETALYNX_MAXTER_REMOTE 0x0037
+#define USB_VENDOR_ID_PETZL 0x2122
+#define USB_DEVICE_ID_PETZL_HEADLAMP 0x1234
+
#define USB_VENDOR_ID_PHILIPS 0x0471
#define USB_DEVICE_ID_PHILIPS_IEEE802154_DONGLE 0x0617
diff --git a/drivers/iio/adc/qcom-rradc.c b/drivers/iio/adc/qcom-rradc.c
index 5c20970ccbbb..28ab4e52dab5 100644
--- a/drivers/iio/adc/qcom-rradc.c
+++ b/drivers/iio/adc/qcom-rradc.c
@@ -180,6 +180,9 @@
#define FG_ADC_RR_VOLT_INPUT_FACTOR 8
#define FG_ADC_RR_CURR_INPUT_FACTOR 2000
#define FG_ADC_RR_CURR_USBIN_INPUT_FACTOR_MIL 1886
+#define FG_ADC_RR_CURR_USBIN_660_FACTOR_MIL 9
+#define FG_ADC_RR_CURR_USBIN_660_UV_VAL 579500
+
#define FG_ADC_SCALE_MILLI_FACTOR 1000
#define FG_ADC_KELVINMIL_CELSIUSMIL 273150
@@ -192,6 +195,9 @@
#define FG_RR_CONV_CONTINUOUS_TIME_MIN_US 50000
#define FG_RR_CONV_CONTINUOUS_TIME_MAX_US 51000
#define FG_RR_CONV_MAX_RETRY_CNT 50
+#define FG_RR_TP_REV_VERSION1 21
+#define FG_RR_TP_REV_VERSION2 29
+#define FG_RR_TP_REV_VERSION3 32
/*
* The channel number is not a physical index in hardware,
@@ -228,6 +234,7 @@ struct rradc_chip {
struct rradc_chan_prop *chan_props;
struct device_node *revid_dev_node;
struct pmic_revid_data *pmic_fab_id;
+ int volt;
};
struct rradc_channels {
@@ -353,7 +360,7 @@ static int rradc_post_process_volt(struct rradc_chip *chip,
return 0;
}
-static int rradc_post_process_curr(struct rradc_chip *chip,
+static int rradc_post_process_usbin_curr(struct rradc_chip *chip,
struct rradc_chan_prop *prop, u16 adc_code,
int *result_ua)
{
@@ -361,11 +368,33 @@ static int rradc_post_process_curr(struct rradc_chip *chip,
if (!prop)
return -EINVAL;
-
- if (prop->channel == RR_ADC_USBIN_I)
- scale = FG_ADC_RR_CURR_USBIN_INPUT_FACTOR_MIL;
- else
- scale = FG_ADC_RR_CURR_INPUT_FACTOR;
+ if (chip->revid_dev_node) {
+ switch (chip->pmic_fab_id->pmic_subtype) {
+ case PM660_SUBTYPE:
+ if (((chip->pmic_fab_id->tp_rev
+ >= FG_RR_TP_REV_VERSION1)
+ && (chip->pmic_fab_id->tp_rev
+ <= FG_RR_TP_REV_VERSION2))
+ || (chip->pmic_fab_id->tp_rev
+ >= FG_RR_TP_REV_VERSION3)) {
+ chip->volt = div64_s64(chip->volt, 1000);
+ chip->volt = chip->volt *
+ FG_ADC_RR_CURR_USBIN_660_FACTOR_MIL;
+ chip->volt = FG_ADC_RR_CURR_USBIN_660_UV_VAL -
+ (chip->volt);
+ chip->volt = div64_s64(1000000000, chip->volt);
+ scale = chip->volt;
+ } else
+ scale = FG_ADC_RR_CURR_USBIN_INPUT_FACTOR_MIL;
+ break;
+ case PMI8998_SUBTYPE:
+ scale = FG_ADC_RR_CURR_USBIN_INPUT_FACTOR_MIL;
+ break;
+ default:
+ pr_err("No PMIC subtype found\n");
+ return -EINVAL;
+ }
+ }
/* scale * V/A; 2.5V ADC full scale */
ua = ((int64_t)adc_code * scale);
@@ -376,6 +405,24 @@ static int rradc_post_process_curr(struct rradc_chip *chip,
return 0;
}
+static int rradc_post_process_dcin_curr(struct rradc_chip *chip,
+ struct rradc_chan_prop *prop, u16 adc_code,
+ int *result_ua)
+{
+ int64_t ua = 0;
+
+ if (!prop)
+ return -EINVAL;
+
+ /* 0.5 V/A; 2.5V ADC full scale */
+ ua = ((int64_t)adc_code * FG_ADC_RR_CURR_INPUT_FACTOR);
+ ua *= (FG_ADC_RR_FS_VOLTAGE_MV * FG_ADC_SCALE_MILLI_FACTOR);
+ ua = div64_s64(ua, (FG_MAX_ADC_READINGS * 1000));
+ *result_ua = ua;
+
+ return 0;
+}
+
static int rradc_post_process_die_temp(struct rradc_chip *chip,
struct rradc_chan_prop *prop, u16 adc_code,
int *result_millidegc)
@@ -591,13 +638,13 @@ static const struct rradc_channels rradc_chans[] = {
BIT(IIO_CHAN_INFO_RAW) | BIT(IIO_CHAN_INFO_PROCESSED),
FG_ADC_RR_SKIN_TEMP_LSB, FG_ADC_RR_SKIN_TEMP_MSB,
FG_ADC_RR_AUX_THERM_STS)
- RR_ADC_CHAN_CURRENT("usbin_i", &rradc_post_process_curr,
+ RR_ADC_CHAN_CURRENT("usbin_i", &rradc_post_process_usbin_curr,
FG_ADC_RR_USB_IN_I_LSB, FG_ADC_RR_USB_IN_I_MSB,
FG_ADC_RR_USB_IN_I_STS)
RR_ADC_CHAN_VOLT("usbin_v", &rradc_post_process_volt,
FG_ADC_RR_USB_IN_V_LSB, FG_ADC_RR_USB_IN_V_MSB,
FG_ADC_RR_USB_IN_V_STS)
- RR_ADC_CHAN_CURRENT("dcin_i", &rradc_post_process_curr,
+ RR_ADC_CHAN_CURRENT("dcin_i", &rradc_post_process_dcin_curr,
FG_ADC_RR_DC_IN_I_LSB, FG_ADC_RR_DC_IN_I_MSB,
FG_ADC_RR_DC_IN_I_STS)
RR_ADC_CHAN_VOLT("dcin_v", &rradc_post_process_volt,
@@ -955,6 +1002,21 @@ static int rradc_read_raw(struct iio_dev *indio_dev,
switch (mask) {
case IIO_CHAN_INFO_PROCESSED:
+ if (((chip->pmic_fab_id->tp_rev
+ >= FG_RR_TP_REV_VERSION1)
+ && (chip->pmic_fab_id->tp_rev
+ <= FG_RR_TP_REV_VERSION2))
+ || (chip->pmic_fab_id->tp_rev
+ >= FG_RR_TP_REV_VERSION3)) {
+ if (chan->address == RR_ADC_USBIN_I) {
+ prop = &chip->chan_props[RR_ADC_USBIN_V];
+ rc = rradc_do_conversion(chip, prop, &adc_code);
+ if (rc)
+ break;
+ prop->scale(chip, prop, adc_code, &chip->volt);
+ }
+ }
+
prop = &chip->chan_props[chan->address];
rc = rradc_do_conversion(chip, prop, &adc_code);
if (rc)
diff --git a/drivers/infiniband/core/cma.c b/drivers/infiniband/core/cma.c
index 3f5741a3e728..43d5166db4c6 100644
--- a/drivers/infiniband/core/cma.c
+++ b/drivers/infiniband/core/cma.c
@@ -857,6 +857,8 @@ int rdma_init_qp_attr(struct rdma_cm_id *id, struct ib_qp_attr *qp_attr,
} else
ret = iw_cm_init_qp_attr(id_priv->cm_id.iw, qp_attr,
qp_attr_mask);
+ qp_attr->port_num = id_priv->id.port_num;
+ *qp_attr_mask |= IB_QP_PORT;
} else
ret = -ENOSYS;
diff --git a/drivers/infiniband/core/uverbs_cmd.c b/drivers/infiniband/core/uverbs_cmd.c
index 9eca4b41fa0a..b7a73f1a8beb 100644
--- a/drivers/infiniband/core/uverbs_cmd.c
+++ b/drivers/infiniband/core/uverbs_cmd.c
@@ -2287,8 +2287,9 @@ ssize_t ib_uverbs_modify_qp(struct ib_uverbs_file *file,
if (copy_from_user(&cmd, buf, sizeof cmd))
return -EFAULT;
- if (cmd.port_num < rdma_start_port(ib_dev) ||
- cmd.port_num > rdma_end_port(ib_dev))
+ if ((cmd.attr_mask & IB_QP_PORT) &&
+ (cmd.port_num < rdma_start_port(ib_dev) ||
+ cmd.port_num > rdma_end_port(ib_dev)))
return -EINVAL;
INIT_UDATA(&udata, buf + sizeof cmd, NULL, in_len - sizeof cmd,
diff --git a/drivers/input/serio/i8042.c b/drivers/input/serio/i8042.c
index 89abfdb539ac..c84c685056b9 100644
--- a/drivers/input/serio/i8042.c
+++ b/drivers/input/serio/i8042.c
@@ -434,8 +434,10 @@ static int i8042_start(struct serio *serio)
{
struct i8042_port *port = serio->port_data;
+ spin_lock_irq(&i8042_lock);
port->exists = true;
- mb();
+ spin_unlock_irq(&i8042_lock);
+
return 0;
}
@@ -448,16 +450,20 @@ static void i8042_stop(struct serio *serio)
{
struct i8042_port *port = serio->port_data;
+ spin_lock_irq(&i8042_lock);
port->exists = false;
+ port->serio = NULL;
+ spin_unlock_irq(&i8042_lock);
/*
+ * We need to make sure that interrupt handler finishes using
+ * our serio port before we return from this function.
* We synchronize with both AUX and KBD IRQs because there is
* a (very unlikely) chance that AUX IRQ is raised for KBD port
* and vice versa.
*/
synchronize_irq(I8042_AUX_IRQ);
synchronize_irq(I8042_KBD_IRQ);
- port->serio = NULL;
}
/*
@@ -574,7 +580,7 @@ static irqreturn_t i8042_interrupt(int irq, void *dev_id)
spin_unlock_irqrestore(&i8042_lock, flags);
- if (likely(port->exists && !filtered))
+ if (likely(serio && !filtered))
serio_interrupt(serio, data, dfl);
out:
diff --git a/drivers/irqchip/irq-keystone.c b/drivers/irqchip/irq-keystone.c
index deb89d63a728..e684be1bb7c0 100644
--- a/drivers/irqchip/irq-keystone.c
+++ b/drivers/irqchip/irq-keystone.c
@@ -19,9 +19,9 @@
#include <linux/bitops.h>
#include <linux/module.h>
#include <linux/moduleparam.h>
+#include <linux/interrupt.h>
#include <linux/irqdomain.h>
#include <linux/irqchip.h>
-#include <linux/irqchip/chained_irq.h>
#include <linux/of.h>
#include <linux/of_platform.h>
#include <linux/mfd/syscon.h>
@@ -39,6 +39,7 @@ struct keystone_irq_device {
struct irq_domain *irqd;
struct regmap *devctrl_regs;
u32 devctrl_offset;
+ raw_spinlock_t wa_lock;
};
static inline u32 keystone_irq_readl(struct keystone_irq_device *kirq)
@@ -83,17 +84,15 @@ static void keystone_irq_ack(struct irq_data *d)
/* nothing to do here */
}
-static void keystone_irq_handler(struct irq_desc *desc)
+static irqreturn_t keystone_irq_handler(int irq, void *keystone_irq)
{
- unsigned int irq = irq_desc_get_irq(desc);
- struct keystone_irq_device *kirq = irq_desc_get_handler_data(desc);
+ struct keystone_irq_device *kirq = keystone_irq;
+ unsigned long wa_lock_flags;
unsigned long pending;
int src, virq;
dev_dbg(kirq->dev, "start irq %d\n", irq);
- chained_irq_enter(irq_desc_get_chip(desc), desc);
-
pending = keystone_irq_readl(kirq);
keystone_irq_writel(kirq, pending);
@@ -111,13 +110,15 @@ static void keystone_irq_handler(struct irq_desc *desc)
if (!virq)
dev_warn(kirq->dev, "sporious irq detected hwirq %d, virq %d\n",
src, virq);
+ raw_spin_lock_irqsave(&kirq->wa_lock, wa_lock_flags);
generic_handle_irq(virq);
+ raw_spin_unlock_irqrestore(&kirq->wa_lock,
+ wa_lock_flags);
}
}
- chained_irq_exit(irq_desc_get_chip(desc), desc);
-
dev_dbg(kirq->dev, "end irq %d\n", irq);
+ return IRQ_HANDLED;
}
static int keystone_irq_map(struct irq_domain *h, unsigned int virq,
@@ -182,9 +183,16 @@ static int keystone_irq_probe(struct platform_device *pdev)
return -ENODEV;
}
+ raw_spin_lock_init(&kirq->wa_lock);
+
platform_set_drvdata(pdev, kirq);
- irq_set_chained_handler_and_data(kirq->irq, keystone_irq_handler, kirq);
+ ret = request_irq(kirq->irq, keystone_irq_handler,
+ 0, dev_name(dev), kirq);
+ if (ret) {
+ irq_domain_remove(kirq->irqd);
+ return ret;
+ }
/* clear all source bits */
keystone_irq_writel(kirq, ~0x0);
@@ -199,6 +207,8 @@ static int keystone_irq_remove(struct platform_device *pdev)
struct keystone_irq_device *kirq = platform_get_drvdata(pdev);
int hwirq;
+ free_irq(kirq->irq, kirq);
+
for (hwirq = 0; hwirq < KEYSTONE_N_IRQ; hwirq++)
irq_dispose_mapping(irq_find_mapping(kirq->irqd, hwirq));
diff --git a/drivers/irqchip/irq-mxs.c b/drivers/irqchip/irq-mxs.c
index 17304705f2cf..05fa9f7af53c 100644
--- a/drivers/irqchip/irq-mxs.c
+++ b/drivers/irqchip/irq-mxs.c
@@ -131,12 +131,16 @@ static struct irq_chip mxs_icoll_chip = {
.irq_ack = icoll_ack_irq,
.irq_mask = icoll_mask_irq,
.irq_unmask = icoll_unmask_irq,
+ .flags = IRQCHIP_MASK_ON_SUSPEND |
+ IRQCHIP_SKIP_SET_WAKE,
};
static struct irq_chip asm9260_icoll_chip = {
.irq_ack = icoll_ack_irq,
.irq_mask = asm9260_mask_irq,
.irq_unmask = asm9260_unmask_irq,
+ .flags = IRQCHIP_MASK_ON_SUSPEND |
+ IRQCHIP_SKIP_SET_WAKE,
};
asmlinkage void __exception_irq_entry icoll_handle_irq(struct pt_regs *regs)
diff --git a/drivers/isdn/i4l/isdn_common.c b/drivers/isdn/i4l/isdn_common.c
index 9b856e1890d1..e4c43a17b333 100644
--- a/drivers/isdn/i4l/isdn_common.c
+++ b/drivers/isdn/i4l/isdn_common.c
@@ -1379,6 +1379,7 @@ isdn_ioctl(struct file *file, uint cmd, ulong arg)
if (arg) {
if (copy_from_user(bname, argp, sizeof(bname) - 1))
return -EFAULT;
+ bname[sizeof(bname)-1] = 0;
} else
return -EINVAL;
ret = mutex_lock_interruptible(&dev->mtx);
diff --git a/drivers/isdn/i4l/isdn_net.c b/drivers/isdn/i4l/isdn_net.c
index aa5dd5668528..dbad5c431bcb 100644
--- a/drivers/isdn/i4l/isdn_net.c
+++ b/drivers/isdn/i4l/isdn_net.c
@@ -2611,10 +2611,9 @@ isdn_net_newslave(char *parm)
char newname[10];
if (p) {
- /* Slave-Name MUST not be empty */
- if (!strlen(p + 1))
+ /* Slave-Name MUST not be empty or overflow 'newname' */
+ if (strscpy(newname, p + 1, sizeof(newname)) <= 0)
return NULL;
- strcpy(newname, p + 1);
*p = 0;
/* Master must already exist */
if (!(n = isdn_net_findif(parm)))
diff --git a/drivers/isdn/i4l/isdn_ppp.c b/drivers/isdn/i4l/isdn_ppp.c
index 9c1e8adaf4fc..bf3fbd00a091 100644
--- a/drivers/isdn/i4l/isdn_ppp.c
+++ b/drivers/isdn/i4l/isdn_ppp.c
@@ -2364,7 +2364,7 @@ static struct ippp_ccp_reset_state *isdn_ppp_ccp_reset_alloc_state(struct ippp_s
id);
return NULL;
} else {
- rs = kzalloc(sizeof(struct ippp_ccp_reset_state), GFP_KERNEL);
+ rs = kzalloc(sizeof(struct ippp_ccp_reset_state), GFP_ATOMIC);
if (!rs)
return NULL;
rs->state = CCPResetIdle;
diff --git a/drivers/leds/leds-qpnp.c b/drivers/leds/leds-qpnp.c
index ab0e4f99ebb9..e3cfffb5c563 100644
--- a/drivers/leds/leds-qpnp.c
+++ b/drivers/leds/leds-qpnp.c
@@ -875,6 +875,14 @@ static int qpnp_mpp_set(struct qpnp_led_data *led)
}
if (led->mpp_cfg->pwm_mode == PWM_MODE) {
/*config pwm for brightness scaling*/
+ rc = pwm_change_mode(led->mpp_cfg->pwm_cfg->pwm_dev,
+ PM_PWM_MODE_PWM);
+ if (rc < 0) {
+ dev_err(&led->pdev->dev,
+ "Failed to set PWM mode, rc = %d\n",
+ rc);
+ return rc;
+ }
period_us = led->mpp_cfg->pwm_cfg->pwm_period_us;
if (period_us > INT_MAX / NSEC_PER_USEC) {
duty_us = (period_us * led->cdev.brightness) /
@@ -1581,6 +1589,14 @@ static int qpnp_kpdbl_set(struct qpnp_led_data *led)
}
if (led->kpdbl_cfg->pwm_cfg->mode == PWM_MODE) {
+ rc = pwm_change_mode(led->kpdbl_cfg->pwm_cfg->pwm_dev,
+ PM_PWM_MODE_PWM);
+ if (rc < 0) {
+ dev_err(&led->pdev->dev,
+ "Failed to set PWM mode, rc = %d\n",
+ rc);
+ return rc;
+ }
period_us = led->kpdbl_cfg->pwm_cfg->pwm_period_us;
if (period_us > INT_MAX / NSEC_PER_USEC) {
duty_us = (period_us * led->cdev.brightness) /
@@ -1702,6 +1718,14 @@ static int qpnp_rgb_set(struct qpnp_led_data *led)
led->rgb_cfg->pwm_cfg->mode =
led->rgb_cfg->pwm_cfg->default_mode;
if (led->rgb_cfg->pwm_cfg->mode == PWM_MODE) {
+ rc = pwm_change_mode(led->rgb_cfg->pwm_cfg->pwm_dev,
+ PM_PWM_MODE_PWM);
+ if (rc < 0) {
+ dev_err(&led->pdev->dev,
+ "Failed to set PWM mode, rc = %d\n",
+ rc);
+ return rc;
+ }
period_us = led->rgb_cfg->pwm_cfg->pwm_period_us;
if (period_us > INT_MAX / NSEC_PER_USEC) {
duty_us = (period_us * led->cdev.brightness) /
@@ -2136,6 +2160,11 @@ static int qpnp_pwm_init(struct pwm_config_data *pwm_cfg,
dev_err(&pdev->dev, "Failed to configure pwm LUT\n");
return rc;
}
+ rc = pwm_change_mode(pwm_cfg->pwm_dev, PM_PWM_MODE_LPG);
+ if (rc < 0) {
+ dev_err(&pdev->dev, "Failed to set LPG mode\n");
+ return rc;
+ }
}
} else {
dev_err(&pdev->dev, "Invalid PWM device\n");
diff --git a/drivers/mailbox/mailbox.c b/drivers/mailbox/mailbox.c
index 6a4811f85705..9cf826df89b1 100644
--- a/drivers/mailbox/mailbox.c
+++ b/drivers/mailbox/mailbox.c
@@ -104,11 +104,14 @@ static void tx_tick(struct mbox_chan *chan, int r)
/* Submit next message */
msg_submit(chan);
+ if (!mssg)
+ return;
+
/* Notify the client */
- if (mssg && chan->cl->tx_done)
+ if (chan->cl->tx_done)
chan->cl->tx_done(chan->cl, mssg, r);
- if (chan->cl->tx_block)
+ if (r != -ETIME && chan->cl->tx_block)
complete(&chan->tx_complete);
}
@@ -261,7 +264,7 @@ int mbox_send_message(struct mbox_chan *chan, void *mssg)
msg_submit(chan);
- if (chan->cl->tx_block && chan->active_req) {
+ if (chan->cl->tx_block) {
unsigned long wait;
int ret;
@@ -272,8 +275,8 @@ int mbox_send_message(struct mbox_chan *chan, void *mssg)
ret = wait_for_completion_timeout(&chan->tx_complete, wait);
if (ret == 0) {
- t = -EIO;
- tx_tick(chan, -EIO);
+ t = -ETIME;
+ tx_tick(chan, t);
}
}
diff --git a/drivers/md/raid1.c b/drivers/md/raid1.c
index d81be5e471d0..f24a9e14021d 100644
--- a/drivers/md/raid1.c
+++ b/drivers/md/raid1.c
@@ -1088,7 +1088,7 @@ static void make_request(struct mddev *mddev, struct bio * bio)
*/
DEFINE_WAIT(w);
for (;;) {
- flush_signals(current);
+ sigset_t full, old;
prepare_to_wait(&conf->wait_barrier,
&w, TASK_INTERRUPTIBLE);
if (bio_end_sector(bio) <= mddev->suspend_lo ||
@@ -1097,7 +1097,10 @@ static void make_request(struct mddev *mddev, struct bio * bio)
!md_cluster_ops->area_resyncing(mddev, WRITE,
bio->bi_iter.bi_sector, bio_end_sector(bio))))
break;
+ sigfillset(&full);
+ sigprocmask(SIG_BLOCK, &full, &old);
schedule();
+ sigprocmask(SIG_SETMASK, &old, NULL);
}
finish_wait(&conf->wait_barrier, &w);
}
diff --git a/drivers/md/raid5.c b/drivers/md/raid5.c
index 4384b46cee1a..8f60520c8392 100644
--- a/drivers/md/raid5.c
+++ b/drivers/md/raid5.c
@@ -5279,12 +5279,15 @@ static void make_request(struct mddev *mddev, struct bio * bi)
* userspace, we want an interruptible
* wait.
*/
- flush_signals(current);
prepare_to_wait(&conf->wait_for_overlap,
&w, TASK_INTERRUPTIBLE);
if (logical_sector >= mddev->suspend_lo &&
logical_sector < mddev->suspend_hi) {
+ sigset_t full, old;
+ sigfillset(&full);
+ sigprocmask(SIG_BLOCK, &full, &old);
schedule();
+ sigprocmask(SIG_SETMASK, &old, NULL);
do_prepare = true;
}
goto retry;
@@ -5818,6 +5821,8 @@ static void raid5_do_work(struct work_struct *work)
pr_debug("%d stripes handled\n", handled);
spin_unlock_irq(&conf->device_lock);
+
+ async_tx_issue_pending_all();
blk_finish_plug(&plug);
pr_debug("--- raid5worker inactive\n");
@@ -7528,12 +7533,10 @@ static void end_reshape(struct r5conf *conf)
{
if (!test_bit(MD_RECOVERY_INTR, &conf->mddev->recovery)) {
- struct md_rdev *rdev;
spin_lock_irq(&conf->device_lock);
conf->previous_raid_disks = conf->raid_disks;
- rdev_for_each(rdev, conf->mddev)
- rdev->data_offset = rdev->new_data_offset;
+ md_finish_reshape(conf->mddev);
smp_wmb();
conf->reshape_progress = MaxSector;
conf->mddev->reshape_position = MaxSector;
diff --git a/drivers/media/i2c/s5c73m3/s5c73m3-ctrls.c b/drivers/media/i2c/s5c73m3/s5c73m3-ctrls.c
index 8001cde1db1e..503135a4f47a 100644
--- a/drivers/media/i2c/s5c73m3/s5c73m3-ctrls.c
+++ b/drivers/media/i2c/s5c73m3/s5c73m3-ctrls.c
@@ -211,7 +211,7 @@ static int s5c73m3_3a_lock(struct s5c73m3 *state, struct v4l2_ctrl *ctrl)
}
if ((ctrl->val ^ ctrl->cur.val) & V4L2_LOCK_FOCUS)
- ret = s5c73m3_af_run(state, ~af_lock);
+ ret = s5c73m3_af_run(state, !af_lock);
return ret;
}
diff --git a/drivers/media/pci/cx88/cx88-cards.c b/drivers/media/pci/cx88/cx88-cards.c
index 8f2556ec3971..61611d1682d1 100644
--- a/drivers/media/pci/cx88/cx88-cards.c
+++ b/drivers/media/pci/cx88/cx88-cards.c
@@ -3691,7 +3691,14 @@ struct cx88_core *cx88_core_create(struct pci_dev *pci, int nr)
core->nr = nr;
sprintf(core->name, "cx88[%d]", core->nr);
- core->tvnorm = V4L2_STD_NTSC_M;
+ /*
+ * Note: Setting initial standard here would cause first call to
+ * cx88_set_tvnorm() to return without programming any registers. Leave
+ * it blank for at this point and it will get set later in
+ * cx8800_initdev()
+ */
+ core->tvnorm = 0;
+
core->width = 320;
core->height = 240;
core->field = V4L2_FIELD_INTERLACED;
diff --git a/drivers/media/pci/cx88/cx88-video.c b/drivers/media/pci/cx88/cx88-video.c
index aef9acf351f6..abbf5b05b6f5 100644
--- a/drivers/media/pci/cx88/cx88-video.c
+++ b/drivers/media/pci/cx88/cx88-video.c
@@ -1429,7 +1429,7 @@ static int cx8800_initdev(struct pci_dev *pci_dev,
/* initial device configuration */
mutex_lock(&core->lock);
- cx88_set_tvnorm(core, core->tvnorm);
+ cx88_set_tvnorm(core, V4L2_STD_NTSC_M);
v4l2_ctrl_handler_setup(&core->video_hdl);
v4l2_ctrl_handler_setup(&core->audio_hdl);
cx88_video_mux(core, 0);
diff --git a/drivers/media/platform/msm/ais/fd/msm_fd_dev.c b/drivers/media/platform/msm/ais/fd/msm_fd_dev.c
index 4024748e6afa..d9e109938e7e 100644
--- a/drivers/media/platform/msm/ais/fd/msm_fd_dev.c
+++ b/drivers/media/platform/msm/ais/fd/msm_fd_dev.c
@@ -430,6 +430,7 @@ static int msm_fd_open(struct file *file)
ctx->vb2_q.type = V4L2_BUF_TYPE_VIDEO_OUTPUT;
ctx->vb2_q.io_modes = VB2_USERPTR;
ctx->vb2_q.timestamp_flags = V4L2_BUF_FLAG_TIMESTAMP_COPY;
+ mutex_init(&ctx->lock);
ret = vb2_queue_init(&ctx->vb2_q);
if (ret < 0) {
dev_err(device->dev, "Error queue init\n");
@@ -480,7 +481,9 @@ static int msm_fd_release(struct file *file)
msm_cpp_vbif_register_error_handler((void *)ctx,
VBIF_CLIENT_FD, NULL);
+ mutex_lock(&ctx->lock);
vb2_queue_release(&ctx->vb2_q);
+ mutex_unlock(&ctx->lock);
vfree(ctx->stats);
@@ -510,7 +513,9 @@ static unsigned int msm_fd_poll(struct file *file,
struct fd_ctx *ctx = msm_fd_ctx_from_fh(file->private_data);
unsigned int ret;
+ mutex_lock(&ctx->lock);
ret = vb2_poll(&ctx->vb2_q, file, wait);
+ mutex_unlock(&ctx->lock);
if (atomic_read(&ctx->subscribed_for_event)) {
poll_wait(file, &ctx->fh.wait, wait);
@@ -748,9 +753,9 @@ static int msm_fd_reqbufs(struct file *file,
int ret;
struct fd_ctx *ctx = msm_fd_ctx_from_fh(fh);
- mutex_lock(&ctx->fd_device->recovery_lock);
+ mutex_lock(&ctx->lock);
ret = vb2_reqbufs(&ctx->vb2_q, req);
- mutex_unlock(&ctx->fd_device->recovery_lock);
+ mutex_unlock(&ctx->lock);
return ret;
}
@@ -766,9 +771,9 @@ static int msm_fd_qbuf(struct file *file, void *fh,
int ret;
struct fd_ctx *ctx = msm_fd_ctx_from_fh(fh);
- mutex_lock(&ctx->fd_device->recovery_lock);
+ mutex_lock(&ctx->lock);
ret = vb2_qbuf(&ctx->vb2_q, pb);
- mutex_unlock(&ctx->fd_device->recovery_lock);
+ mutex_unlock(&ctx->lock);
return ret;
}
@@ -785,9 +790,9 @@ static int msm_fd_dqbuf(struct file *file,
int ret;
struct fd_ctx *ctx = msm_fd_ctx_from_fh(fh);
- mutex_lock(&ctx->fd_device->recovery_lock);
+ mutex_lock(&ctx->lock);
ret = vb2_dqbuf(&ctx->vb2_q, pb, file->f_flags & O_NONBLOCK);
- mutex_unlock(&ctx->fd_device->recovery_lock);
+ mutex_unlock(&ctx->lock);
return ret;
}
@@ -803,7 +808,9 @@ static int msm_fd_streamon(struct file *file,
struct fd_ctx *ctx = msm_fd_ctx_from_fh(fh);
int ret;
+ mutex_lock(&ctx->lock);
ret = vb2_streamon(&ctx->vb2_q, buf_type);
+ mutex_unlock(&ctx->lock);
if (ret < 0)
dev_err(ctx->fd_device->dev, "Stream on fails\n");
@@ -822,7 +829,9 @@ static int msm_fd_streamoff(struct file *file,
struct fd_ctx *ctx = msm_fd_ctx_from_fh(fh);
int ret;
+ mutex_lock(&ctx->lock);
ret = vb2_streamoff(&ctx->vb2_q, buf_type);
+ mutex_unlock(&ctx->lock);
if (ret < 0)
dev_err(ctx->fd_device->dev, "Stream off fails\n");
diff --git a/drivers/media/platform/msm/ais/fd/msm_fd_dev.h b/drivers/media/platform/msm/ais/fd/msm_fd_dev.h
index c15032256f4d..a7615a65d2fc 100644
--- a/drivers/media/platform/msm/ais/fd/msm_fd_dev.h
+++ b/drivers/media/platform/msm/ais/fd/msm_fd_dev.h
@@ -161,6 +161,7 @@ struct fd_ctx {
struct msm_fd_mem_pool mem_pool;
struct msm_fd_stats *stats;
struct msm_fd_buf_handle work_buf;
+ struct mutex lock;
};
/*
diff --git a/drivers/media/platform/msm/ais/sensor/cci/Makefile b/drivers/media/platform/msm/ais/sensor/cci/Makefile
index 3942508c0d66..b8b8c83bc6de 100644
--- a/drivers/media/platform/msm/ais/sensor/cci/Makefile
+++ b/drivers/media/platform/msm/ais/sensor/cci/Makefile
@@ -2,3 +2,4 @@ ccflags-y += -Idrivers/media/platform/msm/ais
ccflags-y += -Idrivers/media/platform/msm/ais/common
ccflags-y += -Idrivers/media/platform/msm/ais/sensor/io
obj-$(CONFIG_MSM_AIS) += msm_cci.o
+obj-$(CONFIG_MSM_AIS) += msm_early_cam.o
diff --git a/drivers/media/platform/msm/ais/sensor/cci/msm_early_cam.c b/drivers/media/platform/msm/ais/sensor/cci/msm_early_cam.c
new file mode 100644
index 000000000000..00ec613e7303
--- /dev/null
+++ b/drivers/media/platform/msm/ais/sensor/cci/msm_early_cam.c
@@ -0,0 +1,279 @@
+/* Copyright (c) 2017, The Linux Foundation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ */
+
+#include <linux/delay.h>
+#include <linux/clk.h>
+#include <linux/io.h>
+#include <linux/module.h>
+#include <linux/of.h>
+#include <linux/of_gpio.h>
+#include <linux/of_platform.h>
+#include "msm_sd.h"
+#include "msm_early_cam.h"
+#include "msm_cam_cci_hwreg.h"
+#include "msm_camera_io_util.h"
+#include "msm_camera_dt_util.h"
+#include "cam_hw_ops.h"
+
+#undef CDBG
+#define CDBG(fmt, args...) pr_debug(fmt, ##args)
+
+#undef EARLY_CAM_DBG
+#ifdef MSM_EARLY_CAM_DEBUG
+#define EARLY_CAM_DBG(fmt, args...) pr_err(fmt, ##args)
+#else
+#define EARLY_CAM_DBG(fmt, args...) pr_debug(fmt, ##args)
+#endif
+
+#define MSM_EARLY_CAM_DRV_NAME "msm_early_cam"
+static struct platform_driver msm_early_camera_driver;
+static struct early_cam_device *new_early_cam_dev;
+
+int msm_early_cam_disable_clocks(void)
+{
+ int rc = 0;
+
+ CDBG("%s:\n", __func__);
+ /* Vote OFF for clocks */
+ if (new_early_cam_dev == NULL) {
+ rc = -EINVAL;
+ pr_err("%s: clock structure uninitialised %d\n", __func__,
+ rc);
+ return rc;
+ }
+
+ if ((new_early_cam_dev->pdev == NULL) ||
+ (new_early_cam_dev->early_cam_clk_info == NULL) ||
+ (new_early_cam_dev->early_cam_clk == NULL) ||
+ (new_early_cam_dev->num_clk == 0)) {
+ rc = -EINVAL;
+ pr_err("%s: Clock details uninitialised %d\n", __func__,
+ rc);
+ return rc;
+ }
+
+ rc = msm_camera_clk_enable(&new_early_cam_dev->pdev->dev,
+ new_early_cam_dev->early_cam_clk_info,
+ new_early_cam_dev->early_cam_clk,
+ new_early_cam_dev->num_clk, false);
+ if (rc < 0) {
+ pr_err("%s: clk disable failed %d\n", __func__, rc);
+ return rc;
+ }
+
+ rc = cam_config_ahb_clk(NULL, 0, CAM_AHB_CLIENT_CSIPHY,
+ CAM_AHB_SUSPEND_VOTE);
+ if (rc < 0) {
+ pr_err("%s: failed to vote OFF AHB_CLIENT_CSIPHY %d\n",
+ __func__, rc);
+ return rc;
+ }
+
+ rc = cam_config_ahb_clk(NULL, 0, CAM_AHB_CLIENT_CSID,
+ CAM_AHB_SUSPEND_VOTE);
+ if (rc < 0) {
+ pr_err("%s: failed to vote OFF AHB_CLIENT_CSID %d\n",
+ __func__, rc);
+ return rc;
+ }
+
+ rc = cam_config_ahb_clk(NULL, 0, CAM_AHB_CLIENT_CCI,
+ CAM_AHB_SUSPEND_VOTE);
+ if (rc < 0) {
+ pr_err("%s: failed to vote OFF AHB_CLIENT_CCI %d\n",
+ __func__, rc);
+ return rc;
+ }
+
+ rc = cam_config_ahb_clk(NULL, 0, CAM_AHB_CLIENT_ISPIF,
+ CAM_AHB_SUSPEND_VOTE);
+ if (rc < 0) {
+ pr_err("%s: failed to vote OFF AHB_CLIENT_ISPIF %d\n",
+ __func__, rc);
+ return rc;
+ }
+
+ rc = cam_config_ahb_clk(NULL, 0, CAM_AHB_CLIENT_VFE0,
+ CAM_AHB_SUSPEND_VOTE);
+ if (rc < 0) {
+ pr_err("%s: failed to vote OFF AHB_CLIENT_VFE0 %d\n",
+ __func__, rc);
+ return rc;
+ }
+ pr_debug("Turned OFF camera clocks\n");
+ return 0;
+
+}
+static int msm_early_cam_probe(struct platform_device *pdev)
+{
+ int rc = 0;
+
+ CDBG("%s: pdev %pK device id = %d\n", __func__, pdev, pdev->id);
+
+ /* Vote for Early camera if enabled */
+ rc = cam_config_ahb_clk(NULL, 0, CAM_AHB_CLIENT_CSIPHY,
+ CAM_AHB_SVS_VOTE);
+ if (rc < 0) {
+ pr_err("%s: failed to vote for AHB\n", __func__);
+ return rc;
+ }
+
+ rc = cam_config_ahb_clk(NULL, 0, CAM_AHB_CLIENT_CSID,
+ CAM_AHB_SVS_VOTE);
+ if (rc < 0) {
+ pr_err("%s: failed to vote for AHB\n", __func__);
+ return rc;
+ }
+
+ rc = cam_config_ahb_clk(NULL, 0, CAM_AHB_CLIENT_CCI,
+ CAM_AHB_SVS_VOTE);
+ if (rc < 0) {
+ pr_err("%s: failed to vote for AHB\n", __func__);
+ return rc;
+ }
+
+ rc = cam_config_ahb_clk(NULL, 0, CAM_AHB_CLIENT_ISPIF,
+ CAM_AHB_SVS_VOTE);
+ if (rc < 0) {
+ pr_err("%s: failed to vote for AHB\n", __func__);
+ return rc;
+ }
+
+ rc = cam_config_ahb_clk(NULL, 0, CAM_AHB_CLIENT_VFE0,
+ CAM_AHB_SVS_VOTE);
+ if (rc < 0) {
+ pr_err("%s: failed to vote for AHB\n", __func__);
+ return rc;
+ }
+
+ new_early_cam_dev = kzalloc(sizeof(struct early_cam_device),
+ GFP_KERNEL);
+ if (!new_early_cam_dev)
+ return -ENOMEM;
+
+ if (pdev->dev.of_node)
+ of_property_read_u32((&pdev->dev)->of_node,
+ "cell-index", &pdev->id);
+
+ rc = msm_camera_get_clk_info_and_rates(pdev,
+ &new_early_cam_dev->early_cam_clk_info,
+ &new_early_cam_dev->early_cam_clk,
+ &new_early_cam_dev->early_cam_clk_rates,
+ &new_early_cam_dev->num_clk_cases,
+ &new_early_cam_dev->num_clk);
+ if (rc < 0) {
+ pr_err("%s: msm_early_cam_get_clk_info() failed", __func__);
+ kfree(new_early_cam_dev);
+ return -EFAULT;
+ }
+
+ new_early_cam_dev->ref_count = 0;
+ new_early_cam_dev->pdev = pdev;
+
+ rc = msm_camera_get_dt_vreg_data(
+ new_early_cam_dev->pdev->dev.of_node,
+ &(new_early_cam_dev->early_cam_vreg),
+ &(new_early_cam_dev->regulator_count));
+ if (rc < 0) {
+ pr_err("%s: msm_camera_get_dt_vreg_data fail\n", __func__);
+ rc = -EFAULT;
+ goto early_cam_release_mem;
+ }
+
+ if ((new_early_cam_dev->regulator_count < 0) ||
+ (new_early_cam_dev->regulator_count > MAX_REGULATOR)) {
+ pr_err("%s: invalid reg count = %d, max is %d\n", __func__,
+ new_early_cam_dev->regulator_count, MAX_REGULATOR);
+ rc = -EFAULT;
+ goto early_cam_invalid_vreg_data;
+ }
+
+ rc = msm_camera_config_vreg(&new_early_cam_dev->pdev->dev,
+ new_early_cam_dev->early_cam_vreg,
+ new_early_cam_dev->regulator_count,
+ NULL,
+ 0,
+ &new_early_cam_dev->early_cam_reg_ptr[0], 1);
+ if (rc < 0)
+ pr_err("%s:%d early_cam config_vreg failed\n", __func__,
+ __LINE__);
+
+ rc = msm_camera_enable_vreg(&new_early_cam_dev->pdev->dev,
+ new_early_cam_dev->early_cam_vreg,
+ new_early_cam_dev->regulator_count,
+ NULL,
+ 0,
+ &new_early_cam_dev->early_cam_reg_ptr[0], 1);
+ if (rc < 0)
+ pr_err("%s:%d early_cam enable_vreg failed\n", __func__,
+ __LINE__);
+
+ rc = msm_camera_clk_enable(&new_early_cam_dev->pdev->dev,
+ new_early_cam_dev->early_cam_clk_info,
+ new_early_cam_dev->early_cam_clk,
+ new_early_cam_dev->num_clk, true);
+
+ if (rc < 0) {
+ pr_err("%s: clk enable failed %d\n", __func__, rc);
+ rc = 0;
+ goto early_cam_release_mem;
+ }
+
+ platform_set_drvdata(pdev, new_early_cam_dev);
+
+ return 0;
+
+early_cam_invalid_vreg_data:
+ kfree(new_early_cam_dev->early_cam_vreg);
+early_cam_release_mem:
+ kfree(new_early_cam_dev);
+ new_early_cam_dev = NULL;
+ return rc;
+}
+
+static int msm_early_cam_exit(struct platform_device *pdev)
+{
+ return 0;
+}
+
+static int __init msm_early_cam_init_module(void)
+{
+ return platform_driver_register(&msm_early_camera_driver);
+}
+
+static void __exit msm_early_cam_exit_module(void)
+{
+ kfree(new_early_cam_dev);
+ platform_driver_unregister(&msm_early_camera_driver);
+}
+
+static const struct of_device_id msm_early_camera_match_table[] = {
+ { .compatible = "qcom,early-cam" },
+ {},
+};
+
+static struct platform_driver msm_early_camera_driver = {
+ .probe = msm_early_cam_probe,
+ .remove = msm_early_cam_exit,
+ .driver = {
+ .name = MSM_EARLY_CAM_DRV_NAME,
+ .owner = THIS_MODULE,
+ .of_match_table = msm_early_camera_match_table,
+ },
+};
+
+MODULE_DEVICE_TABLE(of, msm_early_camera_match_table);
+
+module_init(msm_early_cam_init_module);
+module_exit(msm_early_cam_exit_module);
+MODULE_DESCRIPTION("MSM early camera driver");
+MODULE_LICENSE("GPL v2");
diff --git a/drivers/media/platform/msm/ais/sensor/cci/msm_early_cam.h b/drivers/media/platform/msm/ais/sensor/cci/msm_early_cam.h
new file mode 100644
index 000000000000..a40ab2d1ebc3
--- /dev/null
+++ b/drivers/media/platform/msm/ais/sensor/cci/msm_early_cam.h
@@ -0,0 +1,53 @@
+/* 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
+ * 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_EARLY_CAM_H
+#define MSM_EARLY_CAM_H
+
+#include <linux/clk.h>
+#include <linux/io.h>
+#include <linux/platform_device.h>
+#include <media/v4l2-subdev.h>
+#include <linux/workqueue.h>
+#include <media/ais/msm_ais_sensor.h>
+#include <soc/qcom/ais.h>
+#include "msm_sd.h"
+#include "cam_soc_api.h"
+
+#define NUM_MASTERS 2
+#define NUM_QUEUES 2
+
+#define TRUE 1
+#define FALSE 0
+
+
+enum msm_early_cam_state_t {
+ STATE_DISABLED,
+ STATE_ENABLED,
+};
+
+struct early_cam_device {
+ struct platform_device *pdev;
+ uint8_t ref_count;
+ enum msm_early_cam_state_t early_cam_state;
+ size_t num_clk;
+ size_t num_clk_cases;
+ struct clk **early_cam_clk;
+ uint32_t **early_cam_clk_rates;
+ struct msm_cam_clk_info *early_cam_clk_info;
+ struct camera_vreg_t *early_cam_vreg;
+ struct regulator *early_cam_reg_ptr[MAX_REGULATOR];
+ int32_t regulator_count;
+};
+
+int msm_early_cam_disable_clocks(void);
+#endif
diff --git a/drivers/media/platform/msm/ais/sensor/msm_sensor_init.c b/drivers/media/platform/msm/ais/sensor/msm_sensor_init.c
index c3943be78226..ffbf963e819e 100644
--- a/drivers/media/platform/msm/ais/sensor/msm_sensor_init.c
+++ b/drivers/media/platform/msm/ais/sensor/msm_sensor_init.c
@@ -16,11 +16,17 @@
#include "msm_sensor_driver.h"
#include "msm_sensor.h"
#include "msm_sd.h"
+#include "msm_camera_io_util.h"
+#include "msm_early_cam.h"
/* Logging macro */
#undef CDBG
#define CDBG(fmt, args...) pr_debug(fmt, ##args)
+#define EARLY_CAMERA_SIGNAL_DONE 0xa5a5a5a5
+#define EARLY_CAMERA_SIGNAL_DISABLED 0
+
+static bool early_camera_clock_off;
static struct msm_sensor_init_t *s_init;
static int msm_sensor_wait_for_probe_done(struct msm_sensor_init_t *s_init)
@@ -42,10 +48,14 @@ static int msm_sensor_wait_for_probe_done(struct msm_sensor_init_t *s_init)
return rc;
}
+#define MMSS_A_VFE_0_SPARE 0xC84
+
/* Static function definition */
int32_t msm_sensor_driver_cmd(struct msm_sensor_init_t *s_init, void *arg)
{
int32_t rc = 0;
+ u32 val = 0;
+ void __iomem *base;
struct sensor_init_cfg_data *cfg = (struct sensor_init_cfg_data *)arg;
/* Validate input parameters */
@@ -68,6 +78,28 @@ int32_t msm_sensor_driver_cmd(struct msm_sensor_init_t *s_init, void *arg)
break;
case CFG_SINIT_PROBE_DONE:
+ if (early_camera_clock_off == false) {
+ base = ioremap(0x00A10000, 0x1000);
+ val = msm_camera_io_r_mb(base + MMSS_A_VFE_0_SPARE);
+ while (val != EARLY_CAMERA_SIGNAL_DONE) {
+ if (val == EARLY_CAMERA_SIGNAL_DISABLED)
+ break;
+ msleep(1000);
+ val = msm_camera_io_r_mb(
+ base + MMSS_A_VFE_0_SPARE);
+ pr_err("Waiting for signal from LK val = %u\n",
+ val);
+ }
+ rc = msm_early_cam_disable_clocks();
+ if (rc < 0) {
+ pr_err("Failed to disable early camera :%d\n",
+ rc);
+ } else {
+ early_camera_clock_off = true;
+ pr_debug("Voted OFF early camera clocks\n");
+ }
+ }
+
s_init->module_init_status = 1;
wake_up(&s_init->state_wait);
break;
@@ -99,6 +131,7 @@ static int __init msm_sensor_init_module(void)
mutex_init(&s_init->imutex);
init_waitqueue_head(&s_init->state_wait);
+ early_camera_clock_off = false;
return ret;
}
diff --git a/drivers/media/platform/msm/camera_v2/sensor/ois/msm_ois.c b/drivers/media/platform/msm/camera_v2/sensor/ois/msm_ois.c
index 84266691f9b8..302a7b16bc26 100644
--- a/drivers/media/platform/msm/camera_v2/sensor/ois/msm_ois.c
+++ b/drivers/media/platform/msm/camera_v2/sensor/ois/msm_ois.c
@@ -615,11 +615,13 @@ static long msm_ois_subdev_ioctl(struct v4l2_subdev *sd,
pr_err("o_ctrl->i2c_client.i2c_func_tbl NULL\n");
return -EINVAL;
}
+ mutex_lock(o_ctrl->ois_mutex);
rc = msm_ois_power_down(o_ctrl);
if (rc < 0) {
pr_err("%s:%d OIS Power down failed\n",
__func__, __LINE__);
}
+ mutex_unlock(o_ctrl->ois_mutex);
return msm_ois_close(sd, NULL);
default:
return -ENOIOCTLCMD;
diff --git a/drivers/media/platform/msm/vidc/msm_vidc.c b/drivers/media/platform/msm/vidc/msm_vidc.c
index de4705c3d2eb..3677bb6e32e6 100644
--- a/drivers/media/platform/msm/vidc/msm_vidc.c
+++ b/drivers/media/platform/msm/vidc/msm_vidc.c
@@ -533,11 +533,18 @@ static inline void save_v4l2_buffer(struct v4l2_buffer *b,
static int __map_and_update_binfo(struct msm_vidc_inst *inst,
struct buffer_info *binfo,
- struct v4l2_buffer *b, int i)
+ struct v4l2_buffer *b, u32 i)
{
int rc = 0;
struct msm_smem *same_fd_handle = NULL;
+ if (i >= VIDEO_MAX_PLANES) {
+ dprintk(VIDC_ERR, "Num planes exceeds max: %d, %d\n",
+ i, VIDEO_MAX_PLANES);
+ rc = -EINVAL;
+ goto exit;
+ }
+
same_fd_handle = get_same_fd_buffer(
inst, b->m.planes[i].reserved[0]);
@@ -558,6 +565,7 @@ static int __map_and_update_binfo(struct msm_vidc_inst *inst,
b->m.planes[i].m.userptr = binfo->device_addr[i];
}
+exit:
return rc;
}
@@ -565,7 +573,8 @@ static int __handle_fw_referenced_buffers(struct msm_vidc_inst *inst,
struct buffer_info *binfo,
struct v4l2_buffer *b)
{
- int i = 0, rc = 0;
+ int rc = 0;
+ u32 i = 0;
if (EXTRADATA_IDX(b->length)) {
i = EXTRADATA_IDX(b->length);
@@ -583,8 +592,8 @@ int map_and_register_buf(struct msm_vidc_inst *inst, struct v4l2_buffer *b)
{
struct buffer_info *binfo = NULL;
struct buffer_info *temp = NULL, *iterator = NULL;
- int plane = 0;
- int i = 0, rc = 0;
+ int plane = 0, rc = 0;
+ u32 i = 0;
if (!b || !inst) {
dprintk(VIDC_ERR, "%s: invalid input\n", __func__);
diff --git a/drivers/media/platform/s5p-jpeg/jpeg-core.c b/drivers/media/platform/s5p-jpeg/jpeg-core.c
index 4a608cbe0fdb..9c6fc09b88e0 100644
--- a/drivers/media/platform/s5p-jpeg/jpeg-core.c
+++ b/drivers/media/platform/s5p-jpeg/jpeg-core.c
@@ -1098,10 +1098,10 @@ static bool s5p_jpeg_parse_hdr(struct s5p_jpeg_q_data *result,
struct s5p_jpeg_ctx *ctx)
{
int c, components = 0, notfound, n_dht = 0, n_dqt = 0;
- unsigned int height, width, word, subsampling = 0, sos = 0, sof = 0,
- sof_len = 0;
- unsigned int dht[S5P_JPEG_MAX_MARKER], dht_len[S5P_JPEG_MAX_MARKER],
- dqt[S5P_JPEG_MAX_MARKER], dqt_len[S5P_JPEG_MAX_MARKER];
+ unsigned int height = 0, width = 0, word, subsampling = 0;
+ unsigned int sos = 0, sof = 0, sof_len = 0;
+ unsigned int dht[S5P_JPEG_MAX_MARKER], dht_len[S5P_JPEG_MAX_MARKER];
+ unsigned int dqt[S5P_JPEG_MAX_MARKER], dqt_len[S5P_JPEG_MAX_MARKER];
long length;
struct s5p_jpeg_buffer jpeg_buffer;
diff --git a/drivers/media/rc/imon.c b/drivers/media/rc/imon.c
index 65f80b8b9f7a..eb9e7feb9b13 100644
--- a/drivers/media/rc/imon.c
+++ b/drivers/media/rc/imon.c
@@ -1629,7 +1629,7 @@ static void imon_incoming_packet(struct imon_context *ictx,
if (kc == KEY_KEYBOARD && !ictx->release_code) {
ictx->last_keycode = kc;
if (!nomouse) {
- ictx->pad_mouse = ~(ictx->pad_mouse) & 0x1;
+ ictx->pad_mouse = !ictx->pad_mouse;
dev_dbg(dev, "toggling to %s mode\n",
ictx->pad_mouse ? "mouse" : "keyboard");
spin_unlock_irqrestore(&ictx->kc_lock, flags);
diff --git a/drivers/misc/enclosure.c b/drivers/misc/enclosure.c
index 65fed7146e9b..cc91f7b3d90c 100644
--- a/drivers/misc/enclosure.c
+++ b/drivers/misc/enclosure.c
@@ -375,6 +375,7 @@ int enclosure_add_device(struct enclosure_device *edev, int component,
struct device *dev)
{
struct enclosure_component *cdev;
+ int err;
if (!edev || component >= edev->components)
return -EINVAL;
@@ -384,12 +385,17 @@ int enclosure_add_device(struct enclosure_device *edev, int component,
if (cdev->dev == dev)
return -EEXIST;
- if (cdev->dev)
+ if (cdev->dev) {
enclosure_remove_links(cdev);
-
- put_device(cdev->dev);
+ put_device(cdev->dev);
+ }
cdev->dev = get_device(dev);
- return enclosure_add_links(cdev);
+ err = enclosure_add_links(cdev);
+ if (err) {
+ put_device(cdev->dev);
+ cdev->dev = NULL;
+ }
+ return err;
}
EXPORT_SYMBOL_GPL(enclosure_add_device);
diff --git a/drivers/net/can/spi/rh850.c b/drivers/net/can/spi/rh850.c
index a93f979da9ed..d2b6e8caa112 100644
--- a/drivers/net/can/spi/rh850.c
+++ b/drivers/net/can/spi/rh850.c
@@ -1020,6 +1020,8 @@ static int rh850_create_netdev(struct spi_device *spi,
return -ENOMEM;
}
+ netdev->mtu = CANFD_MTU;
+
netdev_priv_data = netdev_priv(netdev);
netdev_priv_data->rh850_can = priv_data;
netdev_priv_data->netdev_index = index;
diff --git a/drivers/net/ethernet/mellanox/mlx4/icm.c b/drivers/net/ethernet/mellanox/mlx4/icm.c
index 2a9dd460a95f..e1f9e7cebf8f 100644
--- a/drivers/net/ethernet/mellanox/mlx4/icm.c
+++ b/drivers/net/ethernet/mellanox/mlx4/icm.c
@@ -118,8 +118,13 @@ static int mlx4_alloc_icm_coherent(struct device *dev, struct scatterlist *mem,
if (!buf)
return -ENOMEM;
+ if (offset_in_page(buf)) {
+ dma_free_coherent(dev, PAGE_SIZE << order,
+ buf, sg_dma_address(mem));
+ return -ENOMEM;
+ }
+
sg_set_buf(mem, buf, PAGE_SIZE << order);
- BUG_ON(mem->offset);
sg_dma_len(mem) = PAGE_SIZE << order;
return 0;
}
diff --git a/drivers/net/ethernet/realtek/r8169.c b/drivers/net/ethernet/realtek/r8169.c
index 79ef799f88ab..c5ea1018cb47 100644
--- a/drivers/net/ethernet/realtek/r8169.c
+++ b/drivers/net/ethernet/realtek/r8169.c
@@ -326,6 +326,7 @@ enum cfg_version {
static const struct pci_device_id rtl8169_pci_tbl[] = {
{ PCI_DEVICE(PCI_VENDOR_ID_REALTEK, 0x8129), 0, 0, RTL_CFG_0 },
{ PCI_DEVICE(PCI_VENDOR_ID_REALTEK, 0x8136), 0, 0, RTL_CFG_2 },
+ { PCI_DEVICE(PCI_VENDOR_ID_REALTEK, 0x8161), 0, 0, RTL_CFG_1 },
{ PCI_DEVICE(PCI_VENDOR_ID_REALTEK, 0x8167), 0, 0, RTL_CFG_0 },
{ PCI_DEVICE(PCI_VENDOR_ID_REALTEK, 0x8168), 0, 0, RTL_CFG_1 },
{ PCI_DEVICE(PCI_VENDOR_ID_REALTEK, 0x8169), 0, 0, RTL_CFG_0 },
diff --git a/drivers/net/ethernet/renesas/sh_eth.c b/drivers/net/ethernet/renesas/sh_eth.c
index 480f3dae0780..4296066a7ad3 100644
--- a/drivers/net/ethernet/renesas/sh_eth.c
+++ b/drivers/net/ethernet/renesas/sh_eth.c
@@ -750,6 +750,7 @@ static struct sh_eth_cpu_data sh7734_data = {
.tsu = 1,
.hw_crc = 1,
.select_mii = 1,
+ .shift_rd0 = 1,
};
/* SH7763 */
diff --git a/drivers/net/phy/phy_device.c b/drivers/net/phy/phy_device.c
index 0bfbabad4431..1d1e5f7723ab 100644
--- a/drivers/net/phy/phy_device.c
+++ b/drivers/net/phy/phy_device.c
@@ -1442,7 +1442,7 @@ static struct phy_driver genphy_driver[] = {
.phy_id = 0xffffffff,
.phy_id_mask = 0xffffffff,
.name = "Generic PHY",
- .soft_reset = genphy_soft_reset,
+ .soft_reset = genphy_no_soft_reset,
.config_init = genphy_config_init,
.features = PHY_GBIT_FEATURES | SUPPORTED_MII |
SUPPORTED_AUI | SUPPORTED_FIBRE |
diff --git a/drivers/net/usb/kaweth.c b/drivers/net/usb/kaweth.c
index f64b25c221e8..cd93220c9b45 100644
--- a/drivers/net/usb/kaweth.c
+++ b/drivers/net/usb/kaweth.c
@@ -1009,6 +1009,7 @@ static int kaweth_probe(
struct net_device *netdev;
const eth_addr_t bcast_addr = { 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF };
int result = 0;
+ int rv = -EIO;
dev_dbg(dev,
"Kawasaki Device Probe (Device number:%d): 0x%4.4x:0x%4.4x:0x%4.4x\n",
@@ -1029,6 +1030,7 @@ static int kaweth_probe(
kaweth = netdev_priv(netdev);
kaweth->dev = udev;
kaweth->net = netdev;
+ kaweth->intf = intf;
spin_lock_init(&kaweth->device_lock);
init_waitqueue_head(&kaweth->term_wait);
@@ -1048,6 +1050,10 @@ static int kaweth_probe(
/* Download the firmware */
dev_info(dev, "Downloading firmware...\n");
kaweth->firmware_buf = (__u8 *)__get_free_page(GFP_KERNEL);
+ if (!kaweth->firmware_buf) {
+ rv = -ENOMEM;
+ goto err_free_netdev;
+ }
if ((result = kaweth_download_firmware(kaweth,
"kaweth/new_code.bin",
100,
@@ -1139,8 +1145,6 @@ err_fw:
dev_dbg(dev, "Initializing net device.\n");
- kaweth->intf = intf;
-
kaweth->tx_urb = usb_alloc_urb(0, GFP_KERNEL);
if (!kaweth->tx_urb)
goto err_free_netdev;
@@ -1204,7 +1208,7 @@ err_only_tx:
err_free_netdev:
free_netdev(netdev);
- return -EIO;
+ return rv;
}
/****************************************************************
diff --git a/drivers/net/wireless/ath/ath10k/debug.c b/drivers/net/wireless/ath/ath10k/debug.c
index cb152bb4a222..42aab9b86af3 100644
--- a/drivers/net/wireless/ath/ath10k/debug.c
+++ b/drivers/net/wireless/ath/ath10k/debug.c
@@ -2644,14 +2644,14 @@ static void ath10k_process_ieee_hdr(void *data)
dir = (wh->i_fc[1] & IEEE80211_FC1_DIR_MASK);
if (dir == IEEE80211_FC1_DIR_TODS)
- ath10k_extract_frame_header(&wh->i_addr1, &wh->i_addr2,
- &wh->i_addr3);
+ ath10k_extract_frame_header(wh->i_addr1, wh->i_addr2,
+ wh->i_addr3);
else if (dir == IEEE80211_FC1_DIR_FROMDS)
- ath10k_extract_frame_header(&wh->i_addr2, &wh->i_addr3,
- &wh->i_addr1);
+ ath10k_extract_frame_header(wh->i_addr2, wh->i_addr3,
+ wh->i_addr1);
else
- ath10k_extract_frame_header(&wh->i_addr3, &wh->i_addr2,
- &wh->i_addr1);
+ ath10k_extract_frame_header(wh->i_addr3, wh->i_addr2,
+ wh->i_addr1);
}
static void ath10k_pktlog_process_rx(struct ath10k *ar, struct sk_buff *skb)
@@ -2717,6 +2717,46 @@ static void ath10k_pktlog_process_rx(struct ath10k *ar, struct sk_buff *skb)
}
}
+int ath10k_rx_record_pktlog(struct ath10k *ar, struct sk_buff *skb)
+{
+ struct sk_buff *pktlog_skb;
+ struct ath_pktlog_hdr *pl_hdr;
+ struct ath_pktlog_rx_info *pktlog_rx_info;
+ struct htt_rx_desc *rx_desc = (void *)skb->data - sizeof(*rx_desc);
+
+ if (!ar->debug.pktlog_filter)
+ return 0;
+
+ pktlog_skb = dev_alloc_skb(sizeof(struct ath_pktlog_hdr) +
+ sizeof(struct htt_rx_desc) -
+ sizeof(struct htt_host_fw_desc_base));
+ if (!pktlog_skb)
+ return -ENOMEM;
+
+ pktlog_rx_info = (struct ath_pktlog_rx_info *)pktlog_skb->data;
+ pl_hdr = &pktlog_rx_info->pl_hdr;
+
+ pl_hdr->flags = (1 << ATH10K_PKTLOG_FLG_FRM_TYPE_REMOTE_S);
+ pl_hdr->missed_cnt = 0;
+ pl_hdr->mac_id = 0;
+ pl_hdr->log_type = ATH10K_PKTLOG_TYPE_RX_STAT;
+ pl_hdr->flags |= ATH10K_PKTLOG_HDR_SIZE_16;
+ pl_hdr->size = sizeof(*rx_desc) -
+ sizeof(struct htt_host_fw_desc_base);
+
+ pl_hdr->timestamp =
+ cpu_to_le32(rx_desc->ppdu_end.wcn3990.rx_pkt_end.phy_timestamp_1);
+
+ pl_hdr->type_specific_data = 0xDEADAA;
+ memcpy((void *)pktlog_rx_info + sizeof(struct ath_pktlog_hdr),
+ (void *)rx_desc + sizeof(struct htt_host_fw_desc_base),
+ pl_hdr->size);
+
+ ath10k_pktlog_process_rx(ar, pktlog_skb);
+ dev_kfree_skb_any(pktlog_skb);
+ return 0;
+}
+
static void ath10k_pktlog_htc_tx_complete(struct ath10k *ar,
struct sk_buff *skb)
{
diff --git a/drivers/net/wireless/ath/ath10k/debug.h b/drivers/net/wireless/ath/ath10k/debug.h
index f9e90e1227de..eb47720bbf91 100644
--- a/drivers/net/wireless/ath/ath10k/debug.h
+++ b/drivers/net/wireless/ath/ath10k/debug.h
@@ -84,7 +84,7 @@ struct ath_pktlog_hdr {
__le16 flags;
__le16 missed_cnt;
u8 log_type;
- u8 macId;
+ u8 mac_id;
__le16 size;
__le32 timestamp;
__le32 type_specific_data;
@@ -164,6 +164,7 @@ struct ath10k_fw_crash_data *
ath10k_debug_get_new_fw_crash_data(struct ath10k *ar);
void ath10k_debug_dbglog_add(struct ath10k *ar, u8 *buffer, int len);
+int ath10k_rx_record_pktlog(struct ath10k *ar, struct sk_buff *skb);
#define ATH10K_DFS_STAT_INC(ar, c) (ar->debug.dfs_stats.c++)
void ath10k_debug_get_et_strings(struct ieee80211_hw *hw,
@@ -221,6 +222,12 @@ static inline void ath10k_debug_dbglog_add(struct ath10k *ar, u8 *buffer,
{
}
+static inline int ath10k_rx_record_pktlog(struct ath10k *ar,
+ struct sk_buff *skb)
+{
+ return 0;
+}
+
static inline struct ath10k_fw_crash_data *
ath10k_debug_get_new_fw_crash_data(struct ath10k *ar)
{
diff --git a/drivers/net/wireless/ath/ath10k/htt.h b/drivers/net/wireless/ath/ath10k/htt.h
index 2df7fcb4a5ea..6377c4ef427c 100644
--- a/drivers/net/wireless/ath/ath10k/htt.h
+++ b/drivers/net/wireless/ath/ath10k/htt.h
@@ -1745,16 +1745,21 @@ struct ath10k_htt {
#define RX_HTT_HDR_STATUS_LEN 64
-/* This structure layout is programmed via rx ring setup
- * so that FW knows how to transfer the rx descriptor to the host.
- * Buffers like this are placed on the rx ring. */
-struct htt_rx_desc {
+struct htt_host_fw_desc_base {
union {
/* This field is filled on the host using the msdu buffer
* from htt_rx_indication */
struct fw_rx_desc_base fw_desc;
u32 pad;
} __packed;
+};
+
+/* This structure layout is programmed via rx ring setup
+ * so that FW knows how to transfer the rx descriptor to the host.
+ * Buffers like this are placed on the rx ring.
+ */
+struct htt_rx_desc {
+ struct htt_host_fw_desc_base fw_desc_base;
struct {
struct rx_attention attention;
struct rx_frag_info frag_info;
diff --git a/drivers/net/wireless/ath/ath10k/htt_rx.c b/drivers/net/wireless/ath/ath10k/htt_rx.c
index 437ea2c192b3..635b8281b055 100644
--- a/drivers/net/wireless/ath/ath10k/htt_rx.c
+++ b/drivers/net/wireless/ath/ath10k/htt_rx.c
@@ -969,6 +969,7 @@ static void ath10k_process_rx(struct ath10k *ar,
trace_ath10k_rx_hdr(ar, skb->data, skb->len);
trace_ath10k_rx_payload(ar, skb->data, skb->len);
+ ath10k_rx_record_pktlog(ar, skb);
ieee80211_rx_napi(ar->hw, NULL, skb, &ar->napi);
}
diff --git a/drivers/net/wireless/ath/ath10k/hw.h b/drivers/net/wireless/ath/ath10k/hw.h
index 3e1917a6a8e8..37479589b8e1 100644
--- a/drivers/net/wireless/ath/ath10k/hw.h
+++ b/drivers/net/wireless/ath/ath10k/hw.h
@@ -984,6 +984,16 @@ struct ath10k_shadow_reg_address {
extern struct ath10k_shadow_reg_value wcn3990_shadow_reg_value;
extern struct ath10k_shadow_reg_address wcn3990_shadow_reg_address;
+#define ATH10K_PKTLOG_HDR_SIZE_16 0x8000
+
+enum {
+ ATH10k_PKTLOG_FLG_FRM_TYPE_LOCAL_S = 0,
+ ATH10K_PKTLOG_FLG_FRM_TYPE_REMOTE_S,
+ ATH10K_PKTLOG_FLG_FRM_TYPE_CLONE_S,
+ ATH10K_PKTLOG_FLG_FRM_TYPE_CBF_S,
+ ATH10K_PKTLOG_FLG_FRM_TYPE_UNKNOWN_S
+};
+
enum ath10k_pktlog_type {
ATH10K_PKTLOG_TYPE_TX_CTRL = 1,
ATH10K_PKTLOG_TYPE_TX_STAT,
diff --git a/drivers/net/wireless/ath/ath10k/mac.c b/drivers/net/wireless/ath/ath10k/mac.c
index cce931e51d7e..ec86c837e60a 100644
--- a/drivers/net/wireless/ath/ath10k/mac.c
+++ b/drivers/net/wireless/ath/ath10k/mac.c
@@ -7822,10 +7822,6 @@ static const struct ieee80211_iface_limit ath10k_wcn3990_if_limit[] = {
BIT(NL80211_IFTYPE_P2P_CLIENT) |
BIT(NL80211_IFTYPE_P2P_GO),
},
- {
- .max = 1,
- .types = BIT(NL80211_IFTYPE_P2P_DEVICE),
- },
};
static const struct ieee80211_iface_limit ath10k_wcn3990_qcs_if_limit[] = {
@@ -7845,10 +7841,6 @@ static const struct ieee80211_iface_limit ath10k_wcn3990_qcs_if_limit[] = {
#endif
BIT(NL80211_IFTYPE_P2P_GO),
},
- {
- .max = 1,
- .types = BIT(NL80211_IFTYPE_P2P_DEVICE),
- },
};
static const struct ieee80211_iface_limit ath10k_wcn3990_if_limit_ibss[] = {
@@ -8022,6 +8014,10 @@ int ath10k_mac_register(struct ath10k *ar)
BIT(NL80211_IFTYPE_P2P_CLIENT) |
BIT(NL80211_IFTYPE_P2P_GO);
+ if (QCA_REV_WCN3990(ar))
+ ar->hw->wiphy->interface_modes &=
+ ~BIT(NL80211_IFTYPE_P2P_DEVICE);
+
ieee80211_hw_set(ar->hw, SIGNAL_DBM);
ieee80211_hw_set(ar->hw, SUPPORTS_PS);
ieee80211_hw_set(ar->hw, SUPPORTS_DYNAMIC_PS);
diff --git a/drivers/net/wireless/ath/ath10k/wmi-ops.h b/drivers/net/wireless/ath/ath10k/wmi-ops.h
index c3100fcd80f2..8bb01c1a35f7 100644
--- a/drivers/net/wireless/ath/ath10k/wmi-ops.h
+++ b/drivers/net/wireless/ath/ath10k/wmi-ops.h
@@ -681,6 +681,9 @@ ath10k_wmi_vdev_spectral_conf(struct ath10k *ar,
struct sk_buff *skb;
u32 cmd_id;
+ if (!ar->wmi.ops->gen_vdev_spectral_conf)
+ return -EOPNOTSUPP;
+
skb = ar->wmi.ops->gen_vdev_spectral_conf(ar, arg);
if (IS_ERR(skb))
return PTR_ERR(skb);
@@ -696,6 +699,9 @@ ath10k_wmi_vdev_spectral_enable(struct ath10k *ar, u32 vdev_id, u32 trigger,
struct sk_buff *skb;
u32 cmd_id;
+ if (!ar->wmi.ops->gen_vdev_spectral_enable)
+ return -EOPNOTSUPP;
+
skb = ar->wmi.ops->gen_vdev_spectral_enable(ar, vdev_id, trigger,
enable);
if (IS_ERR(skb))
diff --git a/drivers/net/wireless/ath/ath9k/ar9003_phy.c b/drivers/net/wireless/ath/ath9k/ar9003_phy.c
index 201425e7f9cb..fbc8c9a9014b 100644
--- a/drivers/net/wireless/ath/ath9k/ar9003_phy.c
+++ b/drivers/net/wireless/ath/ath9k/ar9003_phy.c
@@ -1815,8 +1815,6 @@ static void ar9003_hw_spectral_scan_wait(struct ath_hw *ah)
static void ar9003_hw_tx99_start(struct ath_hw *ah, u32 qnum)
{
REG_SET_BIT(ah, AR_PHY_TEST, PHY_AGC_CLR);
- REG_SET_BIT(ah, 0x9864, 0x7f000);
- REG_SET_BIT(ah, 0x9924, 0x7f00fe);
REG_CLR_BIT(ah, AR_DIAG_SW, AR_DIAG_RX_DIS);
REG_WRITE(ah, AR_CR, AR_CR_RXD);
REG_WRITE(ah, AR_DLCL_IFS(qnum), 0);
diff --git a/drivers/net/wireless/ath/ath9k/tx99.c b/drivers/net/wireless/ath/ath9k/tx99.c
index ac4781f37e78..b4e6304afd40 100644
--- a/drivers/net/wireless/ath/ath9k/tx99.c
+++ b/drivers/net/wireless/ath/ath9k/tx99.c
@@ -190,22 +190,27 @@ static ssize_t write_file_tx99(struct file *file, const char __user *user_buf,
if (strtobool(buf, &start))
return -EINVAL;
+ mutex_lock(&sc->mutex);
+
if (start == sc->tx99_state) {
if (!start)
- return count;
+ goto out;
ath_dbg(common, XMIT, "Resetting TX99\n");
ath9k_tx99_deinit(sc);
}
if (!start) {
ath9k_tx99_deinit(sc);
- return count;
+ goto out;
}
r = ath9k_tx99_init(sc);
- if (r)
+ if (r) {
+ mutex_unlock(&sc->mutex);
return r;
-
+ }
+out:
+ mutex_unlock(&sc->mutex);
return count;
}
diff --git a/drivers/net/wireless/cnss2/debug.c b/drivers/net/wireless/cnss2/debug.c
index c3bcb38f428f..c69f0a488c52 100644
--- a/drivers/net/wireless/cnss2/debug.c
+++ b/drivers/net/wireless/cnss2/debug.c
@@ -98,6 +98,10 @@ static int cnss_stats_show_state(struct seq_file *s,
continue;
case CNSS_DEV_ERR_NOTIFY:
seq_puts(s, "DEV_ERR");
+ continue;
+ case CNSS_DRIVER_DEBUG:
+ seq_puts(s, "DRIVER_DEBUG");
+ continue;
}
seq_printf(s, "UNKNOWN-%d", i);
@@ -149,10 +153,26 @@ static ssize_t cnss_dev_boot_debug_write(struct file *fp,
if (sysfs_streq(cmd, "on")) {
ret = cnss_power_on_device(plat_priv);
+ } else if (sysfs_streq(cmd, "off")) {
+ cnss_power_off_device(plat_priv);
} else if (sysfs_streq(cmd, "enumerate")) {
ret = cnss_pci_init(plat_priv);
} else if (sysfs_streq(cmd, "download")) {
ret = cnss_pci_start_mhi(plat_priv->bus_priv);
+ } else if (sysfs_streq(cmd, "linkup")) {
+ ret = cnss_resume_pci_link(plat_priv->bus_priv);
+ } else if (sysfs_streq(cmd, "linkdown")) {
+ ret = cnss_suspend_pci_link(plat_priv->bus_priv);
+ } else if (sysfs_streq(cmd, "powerup")) {
+ set_bit(CNSS_DRIVER_DEBUG, &plat_priv->driver_state);
+ ret = cnss_driver_event_post(plat_priv,
+ CNSS_DRIVER_EVENT_POWER_UP,
+ true, NULL);
+ } else if (sysfs_streq(cmd, "shutdown")) {
+ ret = cnss_driver_event_post(plat_priv,
+ CNSS_DRIVER_EVENT_POWER_DOWN,
+ true, NULL);
+ clear_bit(CNSS_DRIVER_DEBUG, &plat_priv->driver_state);
} else {
cnss_pr_err("Device boot debugfs command is invalid\n");
ret = -EINVAL;
@@ -169,8 +189,13 @@ static int cnss_dev_boot_debug_show(struct seq_file *s, void *data)
seq_puts(s, "\nUsage: echo <action> > <debugfs_path>/cnss/dev_boot\n");
seq_puts(s, "<action> can be one of below:\n");
seq_puts(s, "on: turn on device power, assert WLAN_EN\n");
+ seq_puts(s, "off: de-assert WLAN_EN, turn off device power\n");
seq_puts(s, "enumerate: de-assert PERST, enumerate PCIe\n");
seq_puts(s, "download: download FW and do QMI handshake with FW\n");
+ seq_puts(s, "linkup: bring up PCIe link\n");
+ seq_puts(s, "linkdown: bring down PCIe link\n");
+ seq_puts(s, "powerup: full power on sequence to boot device, download FW and do QMI handshake with FW\n");
+ seq_puts(s, "shutdown: full power off sequence to shutdown device\n");
return 0;
}
diff --git a/drivers/net/wireless/cnss2/main.c b/drivers/net/wireless/cnss2/main.c
index 8838a1319629..8277de861d63 100644
--- a/drivers/net/wireless/cnss2/main.c
+++ b/drivers/net/wireless/cnss2/main.c
@@ -1060,11 +1060,15 @@ static int cnss_qca6174_shutdown(struct cnss_plat_data *plat_priv)
if (!pci_priv)
return -ENODEV;
+ if (test_bit(CNSS_DRIVER_DEBUG, &plat_priv->driver_state))
+ goto skip_driver_remove;
+
if (!plat_priv->driver_ops)
return -EINVAL;
cnss_driver_call_remove(plat_priv);
+skip_driver_remove:
cnss_request_bus_bandwidth(CNSS_BUS_WIDTH_NONE);
cnss_pci_set_monitor_wake_intr(pci_priv, false);
cnss_pci_set_auto_suspended(pci_priv, 0);
@@ -1162,7 +1166,8 @@ static int cnss_qca6290_shutdown(struct cnss_plat_data *plat_priv)
return -ENODEV;
if (test_bit(CNSS_COLD_BOOT_CAL, &plat_priv->driver_state) ||
- test_bit(CNSS_FW_BOOT_RECOVERY, &plat_priv->driver_state))
+ test_bit(CNSS_FW_BOOT_RECOVERY, &plat_priv->driver_state) ||
+ test_bit(CNSS_DRIVER_DEBUG, &plat_priv->driver_state))
goto skip_driver_remove;
if (!plat_priv->driver_ops)
diff --git a/drivers/net/wireless/cnss2/main.h b/drivers/net/wireless/cnss2/main.h
index a2d9a02bde20..89ada0b2e1f0 100644
--- a/drivers/net/wireless/cnss2/main.h
+++ b/drivers/net/wireless/cnss2/main.h
@@ -142,6 +142,7 @@ enum cnss_driver_state {
CNSS_DRIVER_RECOVERY,
CNSS_FW_BOOT_RECOVERY,
CNSS_DEV_ERR_NOTIFY,
+ CNSS_DRIVER_DEBUG,
};
struct cnss_recovery_data {
diff --git a/drivers/net/wireless/ti/wlcore/spi.c b/drivers/net/wireless/ti/wlcore/spi.c
index 44f059f7f34e..9ebe00ea8f81 100644
--- a/drivers/net/wireless/ti/wlcore/spi.c
+++ b/drivers/net/wireless/ti/wlcore/spi.c
@@ -71,7 +71,7 @@
* only support SPI for 12xx - this code should be reworked when 18xx
* support is introduced
*/
-#define SPI_AGGR_BUFFER_SIZE (4 * PAGE_SIZE)
+#define SPI_AGGR_BUFFER_SIZE (4 * SZ_4K)
/* Maximum number of SPI write chunks */
#define WSPI_MAX_NUM_OF_CHUNKS \
diff --git a/drivers/net/wireless/wcnss/wcnss_vreg.c b/drivers/net/wireless/wcnss/wcnss_vreg.c
index d0a74744f70a..d94bd90f64da 100644
--- a/drivers/net/wireless/wcnss/wcnss_vreg.c
+++ b/drivers/net/wireless/wcnss/wcnss_vreg.c
@@ -71,23 +71,33 @@ static int is_power_on;
struct vregs_info {
const char * const name;
+ const char * const curr;
+ const char * const volt;
int state;
+ bool required;
struct regulator *regulator;
};
/* IRIS regulators for Pronto hardware */
-static struct vregs_info iris_vregs_pronto[] = {
- {"qcom,iris-vddxo", VREG_NULL_CONFIG, NULL},
- {"qcom,iris-vddrfa", VREG_NULL_CONFIG, NULL},
- {"qcom,iris-vddpa", VREG_NULL_CONFIG, NULL},
- {"qcom,iris-vdddig", VREG_NULL_CONFIG, NULL},
+static struct vregs_info iris_vregs[] = {
+ {"qcom,iris-vddxo", "qcom,iris-vddxo-current",
+ "qcom,iris-vddxo-voltage-level", VREG_NULL_CONFIG, true, NULL},
+ {"qcom,iris-vddrfa", "qcom,iris-vddrfa-current",
+ "qcom,iris-vddrfa-voltage-level", VREG_NULL_CONFIG, true, NULL},
+ {"qcom,iris-vddpa", "qcom,iris-vddpa-current",
+ "qcom,iris-vddpa-voltage-level", VREG_NULL_CONFIG, false, NULL},
+ {"qcom,iris-vdddig", "qcom,iris-vdddig-current",
+ "qcom,iris-vdddig-voltage-level", VREG_NULL_CONFIG, true, NULL},
};
/* WCNSS regulators for Pronto hardware */
static struct vregs_info pronto_vregs[] = {
- {"qcom,pronto-vddmx", VREG_NULL_CONFIG, NULL},
- {"qcom,pronto-vddcx", VREG_NULL_CONFIG, NULL},
- {"qcom,pronto-vddpx", VREG_NULL_CONFIG, NULL},
+ {"qcom,pronto-vddmx", "qcom,pronto-vddmx-current",
+ "qcom,vddmx-voltage-level", VREG_NULL_CONFIG, true, NULL},
+ {"qcom,pronto-vddcx", "qcom,pronto-vddcx-current",
+ "qcom,vddcx-voltage-level", VREG_NULL_CONFIG, true, NULL},
+ {"qcom,pronto-vddpx", "qcom,pronto-vddpx-current",
+ "qcom,vddpx-voltage-level", VREG_NULL_CONFIG, true, NULL},
};
struct host_driver {
@@ -184,6 +194,129 @@ int validate_iris_chip_id(u32 reg)
}
}
+static void wcnss_free_regulator(void)
+{
+ int vreg_i;
+
+ /* Free pronto voltage regulators from device node */
+ for (vreg_i = 0; vreg_i < PRONTO_REGULATORS; vreg_i++) {
+ if (pronto_vregs[vreg_i].state) {
+ regulator_put(pronto_vregs[vreg_i].regulator);
+ pronto_vregs[vreg_i].state = VREG_NULL_CONFIG;
+ }
+ }
+
+ /* Free IRIS voltage regulators from device node */
+ for (vreg_i = 0; vreg_i < IRIS_REGULATORS; vreg_i++) {
+ if (iris_vregs[vreg_i].state) {
+ regulator_put(iris_vregs[vreg_i].regulator);
+ iris_vregs[vreg_i].state = VREG_NULL_CONFIG;
+ }
+ }
+}
+
+static int
+wcnss_dt_parse_vreg_level(struct device *dev, int index,
+ const char *current_vreg_name, const char *vreg_name,
+ struct vregs_level *vlevel)
+{
+ int ret = 0;
+ /* array used to store nominal, low and high voltage values */
+ u32 voltage_levels[3], current_vreg;
+
+ ret = of_property_read_u32_array(dev->of_node, vreg_name,
+ voltage_levels,
+ ARRAY_SIZE(voltage_levels));
+ if (ret) {
+ dev_err(dev, "error reading %s property\n", vreg_name);
+ return ret;
+ }
+
+ vlevel[index].nominal_min = voltage_levels[0];
+ vlevel[index].low_power_min = voltage_levels[1];
+ vlevel[index].max_voltage = voltage_levels[2];
+
+ ret = of_property_read_u32(dev->of_node, current_vreg_name,
+ &current_vreg);
+ if (ret) {
+ dev_err(dev, "error reading %s property\n", current_vreg_name);
+ return ret;
+ }
+
+ vlevel[index].uA_load = current_vreg;
+
+ return ret;
+}
+
+int
+wcnss_parse_voltage_regulator(struct wcnss_wlan_config *wlan_config,
+ struct device *dev)
+{
+ int rc, vreg_i;
+
+ /* Parse pronto voltage regulators from device node */
+ for (vreg_i = 0; vreg_i < PRONTO_REGULATORS; vreg_i++) {
+ pronto_vregs[vreg_i].regulator =
+ regulator_get(dev, pronto_vregs[vreg_i].name);
+ if (IS_ERR(pronto_vregs[vreg_i].regulator)) {
+ if (pronto_vregs[vreg_i].required) {
+ rc = PTR_ERR(pronto_vregs[vreg_i].regulator);
+ dev_err(dev, "regulator get of %s failed (%d)\n",
+ pronto_vregs[vreg_i].name, rc);
+ goto wcnss_vreg_get_err;
+ } else {
+ dev_dbg(dev, "Skip optional regulator configuration: %s\n",
+ pronto_vregs[vreg_i].name);
+ continue;
+ }
+ }
+
+ pronto_vregs[vreg_i].state |= VREG_GET_REGULATOR_MASK;
+ rc = wcnss_dt_parse_vreg_level(dev, vreg_i,
+ pronto_vregs[vreg_i].curr,
+ pronto_vregs[vreg_i].volt,
+ wlan_config->pronto_vlevel);
+ if (rc) {
+ dev_err(dev, "error reading voltage-level property\n");
+ goto wcnss_vreg_get_err;
+ }
+ }
+
+ /* Parse iris voltage regulators from device node */
+ for (vreg_i = 0; vreg_i < IRIS_REGULATORS; vreg_i++) {
+ iris_vregs[vreg_i].regulator =
+ regulator_get(dev, iris_vregs[vreg_i].name);
+ if (IS_ERR(iris_vregs[vreg_i].regulator)) {
+ if (iris_vregs[vreg_i].required) {
+ rc = PTR_ERR(iris_vregs[vreg_i].regulator);
+ dev_err(dev, "regulator get of %s failed (%d)\n",
+ iris_vregs[vreg_i].name, rc);
+ goto wcnss_vreg_get_err;
+ } else {
+ dev_dbg(dev, "Skip optional regulator configuration: %s\n",
+ iris_vregs[vreg_i].name);
+ continue;
+ }
+ }
+
+ iris_vregs[vreg_i].state |= VREG_GET_REGULATOR_MASK;
+ rc = wcnss_dt_parse_vreg_level(dev, vreg_i,
+ iris_vregs[vreg_i].curr,
+ iris_vregs[vreg_i].volt,
+ wlan_config->iris_vlevel);
+ if (rc) {
+ dev_err(dev, "error reading voltage-level property\n");
+ goto wcnss_vreg_get_err;
+ }
+ }
+
+ return 0;
+
+wcnss_vreg_get_err:
+ wcnss_free_regulator();
+ return rc;
+}
+
void wcnss_iris_reset(u32 reg, void __iomem *pmu_conf_reg)
{
/* Reset IRIS */
@@ -417,11 +550,6 @@ static void wcnss_vregs_off(struct vregs_info regulators[], uint size,
if (regulators[i].state == VREG_NULL_CONFIG)
continue;
- if (cfg->wcn_external_gpio_support) {
- if (!memcmp(regulators[i].name, VDD_PA, sizeof(VDD_PA)))
- continue;
- }
-
/* Remove PWM mode */
if (regulators[i].state & VREG_OPTIMUM_MODE_MASK) {
rc = regulator_set_load(regulators[i].regulator, 0);
@@ -483,23 +611,10 @@ static int wcnss_vregs_on(struct device *dev,
}
for (i = 0; i < size; i++) {
- if (cfg->wcn_external_gpio_support) {
- if (!memcmp(regulators[i].name, VDD_PA, sizeof(VDD_PA)))
- continue;
- }
+ if (regulators[i].state == VREG_NULL_CONFIG)
+ continue;
- /* Get regulator source */
- regulators[i].regulator =
- regulator_get(dev, regulators[i].name);
- if (IS_ERR(regulators[i].regulator)) {
- rc = PTR_ERR(regulators[i].regulator);
- pr_err("regulator get of %s failed (%d)\n",
- regulators[i].name, rc);
- goto fail;
- }
- regulators[i].state |= VREG_GET_REGULATOR_MASK;
reg_cnt = regulator_count_voltages(regulators[i].regulator);
-
/* Set voltage to nominal. Exclude swtiches e.g. LVS */
if ((voltage_level[i].nominal_min ||
voltage_level[i].max_voltage) && (reg_cnt > 0)) {
@@ -561,8 +676,7 @@ static void wcnss_iris_vregs_off(enum wcnss_hw_type hw_type,
{
switch (hw_type) {
case WCNSS_PRONTO_HW:
- wcnss_vregs_off(iris_vregs_pronto,
- ARRAY_SIZE(iris_vregs_pronto),
+ wcnss_vregs_off(iris_vregs, ARRAY_SIZE(iris_vregs),
cfg->iris_vlevel);
break;
default:
@@ -579,8 +693,7 @@ static int wcnss_iris_vregs_on(struct device *dev,
switch (hw_type) {
case WCNSS_PRONTO_HW:
- ret = wcnss_vregs_on(dev, iris_vregs_pronto,
- ARRAY_SIZE(iris_vregs_pronto),
+ ret = wcnss_vregs_on(dev, iris_vregs, ARRAY_SIZE(iris_vregs),
cfg->iris_vlevel);
break;
default:
diff --git a/drivers/net/wireless/wcnss/wcnss_wlan.c b/drivers/net/wireless/wcnss/wcnss_wlan.c
index e99d46ca51b0..b604f61e1a05 100644
--- a/drivers/net/wireless/wcnss/wcnss_wlan.c
+++ b/drivers/net/wireless/wcnss/wcnss_wlan.c
@@ -37,6 +37,7 @@
#include <linux/pinctrl/consumer.h>
#include <linux/pm_qos.h>
#include <linux/bitops.h>
+#include <soc/qcom/socinfo.h>
#include <soc/qcom/subsystem_restart.h>
#include <soc/qcom/subsystem_notif.h>
@@ -63,6 +64,21 @@
#define WCNSS_CONFIG_UNSPECIFIED (-1)
#define UINT32_MAX (0xFFFFFFFFU)
+#define SUBSYS_NOTIF_MIN_INDEX 0
+#define SUBSYS_NOTIF_MAX_INDEX 9
+char *wcnss_subsys_notif_type[] = {
+ "SUBSYS_BEFORE_SHUTDOWN",
+ "SUBSYS_AFTER_SHUTDOWN",
+ "SUBSYS_BEFORE_POWERUP",
+ "SUBSYS_AFTER_POWERUP",
+ "SUBSYS_RAMDUMP_NOTIFICATION",
+ "SUBSYS_POWERUP_FAILURE",
+ "SUBSYS_PROXY_VOTE",
+ "SUBSYS_PROXY_UNVOTE",
+ "SUBSYS_SOC_RESET",
+ "SUBSYS_NOTIF_TYPE_COUNT"
+};
+
static int has_48mhz_xo = WCNSS_CONFIG_UNSPECIFIED;
module_param(has_48mhz_xo, int, S_IWUSR | S_IRUGO);
MODULE_PARM_DESC(has_48mhz_xo, "Is an external 48 MHz XO present");
@@ -187,11 +203,9 @@ static DEFINE_SPINLOCK(reg_spinlock);
#define WCNSS_MAX_BUILD_VER_LEN 256
#define WCNSS_MAX_CMD_LEN (128)
#define WCNSS_MIN_CMD_LEN (3)
-#define WCNSS_MIN_SERIAL_LEN (6)
/* control messages from userspace */
#define WCNSS_USR_CTRL_MSG_START 0x00000000
-#define WCNSS_USR_SERIAL_NUM (WCNSS_USR_CTRL_MSG_START + 1)
#define WCNSS_USR_HAS_CAL_DATA (WCNSS_USR_CTRL_MSG_START + 2)
#define WCNSS_USR_WLAN_MAC_ADDR (WCNSS_USR_CTRL_MSG_START + 3)
@@ -482,34 +496,6 @@ static ssize_t wcnss_wlan_macaddr_show(struct device *dev,
static DEVICE_ATTR(wcnss_mac_addr, S_IRUSR | S_IWUSR,
wcnss_wlan_macaddr_show, wcnss_wlan_macaddr_store);
-static ssize_t wcnss_serial_number_show(struct device *dev,
- struct device_attribute *attr, char *buf)
-{
- if (!penv)
- return -ENODEV;
-
- return scnprintf(buf, PAGE_SIZE, "%08X\n", penv->serial_number);
-}
-
-static ssize_t wcnss_serial_number_store(struct device *dev,
- struct device_attribute *attr, const char *buf, size_t count)
-{
- unsigned int value;
-
- if (!penv)
- return -ENODEV;
-
- if (sscanf(buf, "%08X", &value) != 1)
- return -EINVAL;
-
- penv->serial_number = value;
- return count;
-}
-
-static DEVICE_ATTR(serial_number, S_IRUSR | S_IWUSR,
- wcnss_serial_number_show, wcnss_serial_number_store);
-
-
static ssize_t wcnss_thermal_mitigation_show(struct device *dev,
struct device_attribute *attr, char *buf)
{
@@ -1178,13 +1164,9 @@ static int wcnss_create_sysfs(struct device *dev)
if (!dev)
return -ENODEV;
- ret = device_create_file(dev, &dev_attr_serial_number);
- if (ret)
- return ret;
-
ret = device_create_file(dev, &dev_attr_thermal_mitigation);
if (ret)
- goto remove_serial;
+ return ret;
ret = device_create_file(dev, &dev_attr_wcnss_version);
if (ret)
@@ -1200,8 +1182,6 @@ remove_version:
device_remove_file(dev, &dev_attr_wcnss_version);
remove_thermal:
device_remove_file(dev, &dev_attr_thermal_mitigation);
-remove_serial:
- device_remove_file(dev, &dev_attr_serial_number);
return ret;
}
@@ -1209,7 +1189,6 @@ remove_serial:
static void wcnss_remove_sysfs(struct device *dev)
{
if (dev) {
- device_remove_file(dev, &dev_attr_serial_number);
device_remove_file(dev, &dev_attr_thermal_mitigation);
device_remove_file(dev, &dev_attr_wcnss_version);
device_remove_file(dev, &dev_attr_wcnss_mac_addr);
@@ -1657,8 +1636,13 @@ EXPORT_SYMBOL(wcnss_unregister_thermal_mitigation);
unsigned int wcnss_get_serial_number(void)
{
- if (penv)
+ if (penv) {
+ penv->serial_number = socinfo_get_serial_number();
+ pr_info("%s: Device serial number: %u\n",
+ __func__, penv->serial_number);
return penv->serial_number;
+ }
+
return 0;
}
EXPORT_SYMBOL(wcnss_get_serial_number);
@@ -2648,15 +2632,6 @@ void process_usr_ctrl_cmd(u8 *buf, size_t len)
switch (cmd) {
- case WCNSS_USR_SERIAL_NUM:
- if (WCNSS_MIN_SERIAL_LEN > len) {
- pr_err("%s: Invalid serial number\n", __func__);
- return;
- }
- penv->serial_number = buf[2] << 24 | buf[3] << 16
- | buf[4] << 8 | buf[5];
- break;
-
case WCNSS_USR_HAS_CAL_DATA:
if (1 < buf[2])
pr_err("%s: Invalid data for cal %d\n", __func__,
@@ -2714,50 +2689,15 @@ static struct miscdevice wcnss_usr_ctrl = {
};
static int
-wcnss_dt_parse_vreg_level(struct device *dev, int index,
- const char *current_vreg_name, const char *vreg_name,
- struct vregs_level *vlevel)
-{
- int ret = 0;
- /* array used to store nominal, low and high voltage values
- */
- u32 voltage_levels[3], current_vreg;
-
- ret = of_property_read_u32_array(dev->of_node, vreg_name,
- voltage_levels,
- ARRAY_SIZE(voltage_levels));
- if (ret) {
- dev_err(dev, "error reading %s property\n", vreg_name);
- return ret;
- }
-
- vlevel[index].nominal_min = voltage_levels[0];
- vlevel[index].low_power_min = voltage_levels[1];
- vlevel[index].max_voltage = voltage_levels[2];
-
- ret = of_property_read_u32(dev->of_node, current_vreg_name,
- &current_vreg);
- if (ret) {
- dev_err(dev, "error reading %s property\n", current_vreg_name);
- return ret;
- }
-
- vlevel[index].uA_load = current_vreg;
-
- return ret;
-}
-
-static int
wcnss_trigger_config(struct platform_device *pdev)
{
int ret;
- int rc, index = 0;
+ int rc;
struct qcom_wcnss_opts *pdata;
struct resource *res;
int is_pronto_vadc;
int is_pronto_v3;
int pil_retry = 0;
- struct wcnss_wlan_config *wlan_cfg = &penv->wlan_config;
struct device_node *node = (&pdev->dev)->of_node;
int has_pronto_hw = of_property_read_bool(node, "qcom,has-pronto-hw");
@@ -2769,93 +2709,14 @@ wcnss_trigger_config(struct platform_device *pdev)
penv->is_a2xb_split_reg =
of_property_read_bool(node, "qcom,has-a2xb-split-reg");
- wlan_cfg->wcn_external_gpio_support =
- of_property_read_bool(node, "qcom,wcn-external-gpio-support");
-
if (of_property_read_u32(node, "qcom,wlan-rx-buff-count",
&penv->wlan_rx_buff_count)) {
penv->wlan_rx_buff_count = WCNSS_DEF_WLAN_RX_BUFF_COUNT;
}
- ret = wcnss_dt_parse_vreg_level(&pdev->dev, index,
- "qcom,pronto-vddmx-current",
- "qcom,vddmx-voltage-level",
- penv->wlan_config.pronto_vlevel);
-
- if (ret) {
- dev_err(&pdev->dev, "error reading voltage-level property\n");
- goto fail;
- }
-
- index++;
- ret = wcnss_dt_parse_vreg_level(&pdev->dev, index,
- "qcom,pronto-vddcx-current",
- "qcom,vddcx-voltage-level",
- penv->wlan_config.pronto_vlevel);
-
- if (ret) {
- dev_err(&pdev->dev, "error reading voltage-level property\n");
- goto fail;
- }
-
- index++;
- ret = wcnss_dt_parse_vreg_level(&pdev->dev, index,
- "qcom,pronto-vddpx-current",
- "qcom,vddpx-voltage-level",
- penv->wlan_config.pronto_vlevel);
-
- if (ret) {
- dev_err(&pdev->dev, "error reading voltage-level property\n");
- goto fail;
- }
-
- /* assign 0 to index now onwards, index variable re used to
- * represent iris regulator index
- */
- index = 0;
- ret = wcnss_dt_parse_vreg_level(&pdev->dev, index,
- "qcom,iris-vddxo-current",
- "qcom,iris-vddxo-voltage-level",
- penv->wlan_config.iris_vlevel);
-
- if (ret) {
- dev_err(&pdev->dev, "error reading voltage-level property\n");
- goto fail;
- }
-
- index++;
- ret = wcnss_dt_parse_vreg_level(&pdev->dev, index,
- "qcom,iris-vddrfa-current",
- "qcom,iris-vddrfa-voltage-level",
- penv->wlan_config.iris_vlevel);
-
- if (ret) {
- dev_err(&pdev->dev, "error reading voltage-level property\n");
- goto fail;
- }
-
- if (!wlan_cfg->wcn_external_gpio_support) {
- index++;
- ret = wcnss_dt_parse_vreg_level(
- &pdev->dev, index,
- "qcom,iris-vddpa-current",
- "qcom,iris-vddpa-voltage-level",
- penv->wlan_config.iris_vlevel);
- if (ret) {
- dev_err(&pdev->dev,
- "error reading voltage-level property\n");
- goto fail;
- }
- }
-
- index++;
- ret = wcnss_dt_parse_vreg_level(&pdev->dev, index,
- "qcom,iris-vdddig-current",
- "qcom,iris-vdddig-voltage-level",
- penv->wlan_config.iris_vlevel);
-
- if (ret) {
- dev_err(&pdev->dev, "error reading voltage-level property\n");
+ rc = wcnss_parse_voltage_regulator(&penv->wlan_config, &pdev->dev);
+ if (rc) {
+ dev_err(&pdev->dev, "Failed to parse voltage regulators\n");
goto fail;
}
@@ -3201,7 +3062,7 @@ wcnss_trigger_config(struct platform_device *pdev)
penv->vadc_dev = qpnp_get_vadc(&penv->pdev->dev, "wcnss");
if (IS_ERR(penv->vadc_dev)) {
- pr_err("%s: vadc get failed\n", __func__);
+ pr_debug("%s: vadc get failed\n", __func__);
penv->vadc_dev = NULL;
} else {
rc = wcnss_get_battery_volt(&penv->wlan_config.vbatt);
@@ -3477,7 +3338,15 @@ static int wcnss_notif_cb(struct notifier_block *this, unsigned long code,
struct notif_data *data = (struct notif_data *)ss_handle;
int ret, xo_mode;
- pr_info("%s: wcnss notification event: %lu\n", __func__, code);
+ if (!(code >= SUBSYS_NOTIF_MIN_INDEX) &&
+ (code <= SUBSYS_NOTIF_MAX_INDEX)) {
+ pr_debug("%s: Invaild subsystem notification code: %lu\n",
+ __func__, code);
+ return NOTIFY_DONE;
+ }
+
+ pr_debug("%s: wcnss notification event: %lu : %s\n",
+ __func__, code, wcnss_subsys_notif_type[code]);
if (code == SUBSYS_PROXY_VOTE) {
if (pdev && pwlanconfig) {
diff --git a/drivers/nfc/fdp/i2c.c b/drivers/nfc/fdp/i2c.c
index 532db28145c7..a5d7332dfce5 100644
--- a/drivers/nfc/fdp/i2c.c
+++ b/drivers/nfc/fdp/i2c.c
@@ -210,14 +210,14 @@ static irqreturn_t fdp_nci_i2c_irq_thread_fn(int irq, void *phy_id)
struct sk_buff *skb;
int r;
- client = phy->i2c_dev;
- dev_dbg(&client->dev, "%s\n", __func__);
-
if (!phy || irq != phy->i2c_dev->irq) {
WARN_ON_ONCE(1);
return IRQ_NONE;
}
+ client = phy->i2c_dev;
+ dev_dbg(&client->dev, "%s\n", __func__);
+
r = fdp_nci_i2c_read(phy, &skb);
if (r == -EREMOTEIO)
diff --git a/drivers/nfc/nfcmrvl/fw_dnld.c b/drivers/nfc/nfcmrvl/fw_dnld.c
index f8dcdf4b24f6..af62c4c854f3 100644
--- a/drivers/nfc/nfcmrvl/fw_dnld.c
+++ b/drivers/nfc/nfcmrvl/fw_dnld.c
@@ -459,7 +459,7 @@ int nfcmrvl_fw_dnld_init(struct nfcmrvl_private *priv)
INIT_WORK(&priv->fw_dnld.rx_work, fw_dnld_rx_work);
snprintf(name, sizeof(name), "%s_nfcmrvl_fw_dnld_rx_wq",
- dev_name(priv->dev));
+ dev_name(&priv->ndev->nfc_dev->dev));
priv->fw_dnld.rx_wq = create_singlethread_workqueue(name);
if (!priv->fw_dnld.rx_wq)
return -ENOMEM;
@@ -496,6 +496,7 @@ int nfcmrvl_fw_dnld_start(struct nci_dev *ndev, const char *firmware_name)
{
struct nfcmrvl_private *priv = nci_get_drvdata(ndev);
struct nfcmrvl_fw_dnld *fw_dnld = &priv->fw_dnld;
+ int res;
if (!priv->support_fw_dnld)
return -ENOTSUPP;
@@ -511,7 +512,9 @@ int nfcmrvl_fw_dnld_start(struct nci_dev *ndev, const char *firmware_name)
*/
/* Retrieve FW binary */
- if (request_firmware(&fw_dnld->fw, firmware_name, priv->dev) < 0) {
+ res = request_firmware(&fw_dnld->fw, firmware_name,
+ &ndev->nfc_dev->dev);
+ if (res < 0) {
nfc_err(priv->dev, "failed to retrieve FW %s", firmware_name);
return -ENOENT;
}
diff --git a/drivers/nfc/nfcmrvl/main.c b/drivers/nfc/nfcmrvl/main.c
index 51c8240a1672..a446590a71ca 100644
--- a/drivers/nfc/nfcmrvl/main.c
+++ b/drivers/nfc/nfcmrvl/main.c
@@ -124,12 +124,13 @@ struct nfcmrvl_private *nfcmrvl_nci_register_dev(enum nfcmrvl_phy phy,
memcpy(&priv->config, pdata, sizeof(*pdata));
if (priv->config.reset_n_io) {
- rc = devm_gpio_request_one(dev,
- priv->config.reset_n_io,
- GPIOF_OUT_INIT_LOW,
- "nfcmrvl_reset_n");
- if (rc < 0)
+ rc = gpio_request_one(priv->config.reset_n_io,
+ GPIOF_OUT_INIT_LOW,
+ "nfcmrvl_reset_n");
+ if (rc < 0) {
+ priv->config.reset_n_io = 0;
nfc_err(dev, "failed to request reset_n io\n");
+ }
}
if (phy == NFCMRVL_PHY_SPI) {
@@ -154,7 +155,13 @@ struct nfcmrvl_private *nfcmrvl_nci_register_dev(enum nfcmrvl_phy phy,
if (!priv->ndev) {
nfc_err(dev, "nci_allocate_device failed\n");
rc = -ENOMEM;
- goto error;
+ goto error_free_gpio;
+ }
+
+ rc = nfcmrvl_fw_dnld_init(priv);
+ if (rc) {
+ nfc_err(dev, "failed to initialize FW download %d\n", rc);
+ goto error_free_dev;
}
nci_set_drvdata(priv->ndev, priv);
@@ -162,24 +169,22 @@ struct nfcmrvl_private *nfcmrvl_nci_register_dev(enum nfcmrvl_phy phy,
rc = nci_register_device(priv->ndev);
if (rc) {
nfc_err(dev, "nci_register_device failed %d\n", rc);
- goto error_free_dev;
+ goto error_fw_dnld_deinit;
}
/* Ensure that controller is powered off */
nfcmrvl_chip_halt(priv);
- rc = nfcmrvl_fw_dnld_init(priv);
- if (rc) {
- nfc_err(dev, "failed to initialize FW download %d\n", rc);
- goto error_free_dev;
- }
-
nfc_info(dev, "registered with nci successfully\n");
return priv;
+error_fw_dnld_deinit:
+ nfcmrvl_fw_dnld_deinit(priv);
error_free_dev:
nci_free_device(priv->ndev);
-error:
+error_free_gpio:
+ if (priv->config.reset_n_io)
+ gpio_free(priv->config.reset_n_io);
kfree(priv);
return ERR_PTR(rc);
}
@@ -195,7 +200,7 @@ void nfcmrvl_nci_unregister_dev(struct nfcmrvl_private *priv)
nfcmrvl_fw_dnld_deinit(priv);
if (priv->config.reset_n_io)
- devm_gpio_free(priv->dev, priv->config.reset_n_io);
+ gpio_free(priv->config.reset_n_io);
nci_unregister_device(ndev);
nci_free_device(ndev);
diff --git a/drivers/nfc/nfcmrvl/uart.c b/drivers/nfc/nfcmrvl/uart.c
index 83a99e38e7bd..6c0c301611c4 100644
--- a/drivers/nfc/nfcmrvl/uart.c
+++ b/drivers/nfc/nfcmrvl/uart.c
@@ -109,6 +109,7 @@ static int nfcmrvl_nci_uart_open(struct nci_uart *nu)
struct nfcmrvl_private *priv;
struct nfcmrvl_platform_data *pdata = NULL;
struct nfcmrvl_platform_data config;
+ struct device *dev = nu->tty->dev;
/*
* Platform data cannot be used here since usually it is already used
@@ -116,9 +117,8 @@ static int nfcmrvl_nci_uart_open(struct nci_uart *nu)
* and check if DT entries were added.
*/
- if (nu->tty->dev->parent && nu->tty->dev->parent->of_node)
- if (nfcmrvl_uart_parse_dt(nu->tty->dev->parent->of_node,
- &config) == 0)
+ if (dev && dev->parent && dev->parent->of_node)
+ if (nfcmrvl_uart_parse_dt(dev->parent->of_node, &config) == 0)
pdata = &config;
if (!pdata) {
@@ -131,7 +131,7 @@ static int nfcmrvl_nci_uart_open(struct nci_uart *nu)
}
priv = nfcmrvl_nci_register_dev(NFCMRVL_PHY_UART, nu, &uart_ops,
- nu->tty->dev, pdata);
+ dev, pdata);
if (IS_ERR(priv))
return PTR_ERR(priv);
diff --git a/drivers/nvdimm/btt.c b/drivers/nvdimm/btt.c
index efb2c1ceef98..957234272ef7 100644
--- a/drivers/nvdimm/btt.c
+++ b/drivers/nvdimm/btt.c
@@ -1205,10 +1205,13 @@ static int btt_rw_page(struct block_device *bdev, sector_t sector,
struct page *page, int rw)
{
struct btt *btt = bdev->bd_disk->private_data;
+ int rc;
- btt_do_bvec(btt, NULL, page, PAGE_CACHE_SIZE, 0, rw, sector);
- page_endio(page, rw & WRITE, 0);
- return 0;
+ rc = btt_do_bvec(btt, NULL, page, PAGE_CACHE_SIZE, 0, rw, sector);
+ if (rc == 0)
+ page_endio(page, rw & WRITE, 0);
+
+ return rc;
}
diff --git a/drivers/nvmem/imx-ocotp.c b/drivers/nvmem/imx-ocotp.c
index b7971d410b60..74e5360c53f0 100644
--- a/drivers/nvmem/imx-ocotp.c
+++ b/drivers/nvmem/imx-ocotp.c
@@ -88,7 +88,7 @@ static struct nvmem_config imx_ocotp_nvmem_config = {
static const struct of_device_id imx_ocotp_dt_ids[] = {
{ .compatible = "fsl,imx6q-ocotp", (void *)128 },
- { .compatible = "fsl,imx6sl-ocotp", (void *)32 },
+ { .compatible = "fsl,imx6sl-ocotp", (void *)64 },
{ .compatible = "fsl,imx6sx-ocotp", (void *)128 },
{ },
};
diff --git a/drivers/of/device.c b/drivers/of/device.c
index e5f47cec75f3..97a280d50d6d 100644
--- a/drivers/of/device.c
+++ b/drivers/of/device.c
@@ -225,6 +225,7 @@ ssize_t of_device_get_modalias(struct device *dev, char *str, ssize_t len)
return tsize;
}
+EXPORT_SYMBOL_GPL(of_device_get_modalias);
/**
* of_device_uevent - Display OF related uevent information
@@ -287,3 +288,4 @@ int of_device_uevent_modalias(struct device *dev, struct kobj_uevent_env *env)
return 0;
}
+EXPORT_SYMBOL_GPL(of_device_uevent_modalias);
diff --git a/drivers/pci/host/pci-msm.c b/drivers/pci/host/pci-msm.c
index 8e66cd5770b5..a741c9c7d115 100644
--- a/drivers/pci/host/pci-msm.c
+++ b/drivers/pci/host/pci-msm.c
@@ -596,7 +596,6 @@ struct msm_pcie_dev_t {
bool cfg_access;
spinlock_t cfg_lock;
unsigned long irqsave_flags;
- struct mutex enumerate_lock;
struct mutex setup_lock;
struct irq_domain *irq_domain;
@@ -704,6 +703,9 @@ static u32 num_rc_on;
/* global lock for PCIe common PHY */
static struct mutex com_phy_lock;
+/* global lock for PCIe enumeration */
+static struct mutex enumerate_lock;
+
/* Table to track info of PCIe devices */
static struct msm_pcie_device_info
msm_pcie_dev_tbl[MAX_RC_NUM * MAX_DEVICE_NUM];
@@ -5050,7 +5052,7 @@ int msm_pcie_enumerate(u32 rc_idx)
int ret = 0, bus_ret = 0, scan_ret = 0;
struct msm_pcie_dev_t *dev = &msm_pcie_dev[rc_idx];
- mutex_lock(&dev->enumerate_lock);
+ mutex_lock(&enumerate_lock);
PCIE_DBG(dev, "Enumerate RC%d\n", rc_idx);
@@ -5169,7 +5171,7 @@ int msm_pcie_enumerate(u32 rc_idx)
}
out:
- mutex_unlock(&dev->enumerate_lock);
+ mutex_unlock(&enumerate_lock);
return ret;
}
@@ -6631,6 +6633,7 @@ int __init pcie_init(void)
pcie_drv.rc_num = 0;
mutex_init(&pcie_drv.drv_lock);
mutex_init(&com_phy_lock);
+ mutex_init(&enumerate_lock);
for (i = 0; i < MAX_RC_NUM; i++) {
snprintf(rc_name, MAX_RC_NAME_LEN, "pcie%d-short", i);
@@ -6665,7 +6668,6 @@ int __init pcie_init(void)
rc_name, i);
spin_lock_init(&msm_pcie_dev[i].cfg_lock);
msm_pcie_dev[i].cfg_access = true;
- mutex_init(&msm_pcie_dev[i].enumerate_lock);
mutex_init(&msm_pcie_dev[i].setup_lock);
mutex_init(&msm_pcie_dev[i].recovery_lock);
spin_lock_init(&msm_pcie_dev[i].linkdown_lock);
diff --git a/drivers/pci/pci-driver.c b/drivers/pci/pci-driver.c
index d7ffd66814bb..fca925543fae 100644
--- a/drivers/pci/pci-driver.c
+++ b/drivers/pci/pci-driver.c
@@ -945,6 +945,7 @@ static int pci_pm_thaw_noirq(struct device *dev)
return pci_legacy_resume_early(dev);
pci_update_current_state(pci_dev, PCI_D0);
+ pci_restore_state(pci_dev);
if (drv && drv->pm && drv->pm->thaw_noirq)
error = drv->pm->thaw_noirq(dev);
diff --git a/drivers/platform/msm/gsi/gsi.c b/drivers/platform/msm/gsi/gsi.c
index b111a5904952..2ae2438032b7 100644
--- a/drivers/platform/msm/gsi/gsi.c
+++ b/drivers/platform/msm/gsi/gsi.c
@@ -1901,6 +1901,20 @@ int gsi_stop_channel(unsigned long chan_hdl)
res = wait_for_completion_timeout(&ctx->compl,
msecs_to_jiffies(GSI_STOP_CMD_TIMEOUT_MS));
if (res == 0) {
+ /*
+ * check channel state here in case the channel is stopped but
+ * the interrupt was not handled yet.
+ */
+ val = gsi_readl(gsi_ctx->base +
+ GSI_EE_n_GSI_CH_k_CNTXT_0_OFFS(chan_hdl,
+ gsi_ctx->per.ee));
+ ctx->state = (val &
+ GSI_EE_n_GSI_CH_k_CNTXT_0_CHSTATE_BMSK) >>
+ GSI_EE_n_GSI_CH_k_CNTXT_0_CHSTATE_SHFT;
+ if (ctx->state == GSI_CHAN_STATE_STOPPED) {
+ res = GSI_STATUS_SUCCESS;
+ goto free_lock;
+ }
GSIDBG("chan_hdl=%lu timed out\n", chan_hdl);
res = -GSI_STATUS_TIMED_OUT;
goto free_lock;
diff --git a/drivers/platform/msm/ipa/ipa_v3/ipa.c b/drivers/platform/msm/ipa/ipa_v3/ipa.c
index 62e263a139cc..52f99c830b47 100644
--- a/drivers/platform/msm/ipa/ipa_v3/ipa.c
+++ b/drivers/platform/msm/ipa/ipa_v3/ipa.c
@@ -2248,7 +2248,6 @@ static int ipa3_q6_set_ex_path_to_apps(void)
struct ipahal_imm_cmd_register_write reg_write;
struct ipahal_imm_cmd_pyld *cmd_pyld;
int retval;
- struct ipahal_reg_valmask valmask;
desc = kcalloc(ipa3_ctx->ipa_num_pipes, sizeof(struct ipa3_desc),
GFP_KERNEL);
@@ -2263,40 +2262,10 @@ static int ipa3_q6_set_ex_path_to_apps(void)
if (ep_idx == -1)
continue;
- if (ipa3_ctx->ep[ep_idx].valid &&
- ipa3_ctx->ep[ep_idx].skip_ep_cfg) {
- BUG_ON(num_descs >= ipa3_ctx->ipa_num_pipes);
-
- reg_write.skip_pipeline_clear = false;
- reg_write.pipeline_clear_options =
- IPAHAL_HPS_CLEAR;
- reg_write.offset =
- ipahal_get_reg_n_ofst(IPA_ENDP_STATUS_n,
- ep_idx);
- ipahal_get_status_ep_valmask(
- ipa3_get_ep_mapping(IPA_CLIENT_APPS_LAN_CONS),
- &valmask);
- reg_write.value = valmask.val;
- reg_write.value_mask = valmask.mask;
- cmd_pyld = ipahal_construct_imm_cmd(
- IPA_IMM_CMD_REGISTER_WRITE, &reg_write, false);
- if (!cmd_pyld) {
- IPAERR("fail construct register_write cmd\n");
- BUG();
- }
-
- desc[num_descs].opcode = ipahal_imm_cmd_get_opcode(
- IPA_IMM_CMD_REGISTER_WRITE);
- desc[num_descs].type = IPA_IMM_CMD_DESC;
- desc[num_descs].callback = ipa3_destroy_imm;
- desc[num_descs].user1 = cmd_pyld;
- desc[num_descs].pyld = cmd_pyld->data;
- desc[num_descs].len = cmd_pyld->len;
- num_descs++;
- }
-
- /* disable statuses for modem producers */
- if (IPA_CLIENT_IS_Q6_PROD(client_idx)) {
+ /* disable statuses for all modem controlled prod pipes */
+ if (IPA_CLIENT_IS_Q6_PROD(client_idx) ||
+ (ipa3_ctx->ep[ep_idx].valid &&
+ ipa3_ctx->ep[ep_idx].skip_ep_cfg)) {
ipa_assert_on(num_descs >= ipa3_ctx->ipa_num_pipes);
reg_write.skip_pipeline_clear = false;
@@ -5473,6 +5442,10 @@ static int ipa3_smp2p_probe(struct device *dev)
struct device_node *node = dev->of_node;
int res;
+ if (ipa3_ctx == NULL) {
+ IPAERR("ipa3_ctx was not initialized\n");
+ return -ENXIO;
+ }
IPADBG("node->name=%s\n", node->name);
if (strcmp("qcom,smp2pgpio_map_ipa_1_out", node->name) == 0) {
res = of_get_gpio(node, 0);
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 594fd9bcfc02..d0aa42c81750 100644
--- a/drivers/platform/msm/ipa/ipa_v3/ipahal/ipahal_reg.c
+++ b/drivers/platform/msm/ipa/ipa_v3/ipahal/ipahal_reg.c
@@ -1612,20 +1612,3 @@ void ipahal_get_fltrt_hash_flush_valmask(
valmask->mask = valmask->val;
}
-
-void ipahal_get_status_ep_valmask(int pipe_num,
- struct ipahal_reg_valmask *valmask)
-{
- if (!valmask) {
- IPAHAL_ERR("Input error\n");
- return;
- }
-
- valmask->val =
- (pipe_num & IPA_ENDP_STATUS_n_STATUS_ENDP_BMSK) <<
- IPA_ENDP_STATUS_n_STATUS_ENDP_SHFT;
-
- valmask->mask =
- IPA_ENDP_STATUS_n_STATUS_ENDP_BMSK <<
- IPA_ENDP_STATUS_n_STATUS_ENDP_SHFT;
-}
diff --git a/drivers/platform/msm/ipa/ipa_v3/ipahal/ipahal_reg.h b/drivers/platform/msm/ipa/ipa_v3/ipahal/ipahal_reg.h
index 4db09475d5e2..9f32c071cb68 100644
--- a/drivers/platform/msm/ipa/ipa_v3/ipahal/ipahal_reg.h
+++ b/drivers/platform/msm/ipa/ipa_v3/ipahal/ipahal_reg.h
@@ -467,8 +467,6 @@ void ipahal_get_aggr_force_close_valmask(int ep_idx,
void ipahal_get_fltrt_hash_flush_valmask(
struct ipahal_reg_fltrt_hash_flush *flush,
struct ipahal_reg_valmask *valmask);
-void ipahal_get_status_ep_valmask(int pipe_num,
- struct ipahal_reg_valmask *valmask);
#endif /* _IPAHAL_REG_H_ */
diff --git a/drivers/platform/msm/qpnp-revid.c b/drivers/platform/msm/qpnp-revid.c
index 9ea0b40304eb..0fec8acde96c 100644
--- a/drivers/platform/msm/qpnp-revid.c
+++ b/drivers/platform/msm/qpnp-revid.c
@@ -27,6 +27,7 @@
#define REVID_SUBTYPE 0x5
#define REVID_STATUS1 0x8
#define REVID_SPARE_0 0x60
+#define REVID_TP_REV 0xf1
#define REVID_FAB_ID 0xf2
#define QPNP_REVID_DEV_NAME "qcom,qpnp-revid"
@@ -157,9 +158,9 @@ static size_t build_pmic_string(char *buf, size_t n, int sid,
static int qpnp_revid_probe(struct platform_device *pdev)
{
u8 rev1, rev2, rev3, rev4, pmic_type, pmic_subtype, pmic_status;
- u8 option1, option2, option3, option4, spare0, fab_id;
+ u8 option1, option2, option3, option4, spare0;
unsigned int base;
- int rc;
+ int rc, fab_id, tp_rev;
char pmic_string[PMIC_STRING_MAXLENGTH] = {'\0'};
struct revid_chip *revid_chip;
struct regmap *regmap;
@@ -207,6 +208,11 @@ static int qpnp_revid_probe(struct platform_device *pdev)
else
fab_id = -EINVAL;
+ if (of_property_read_bool(pdev->dev.of_node, "qcom,tp-rev-valid"))
+ tp_rev = qpnp_read_byte(regmap, base + REVID_TP_REV);
+ else
+ tp_rev = -EINVAL;
+
revid_chip = devm_kzalloc(&pdev->dev, sizeof(struct revid_chip),
GFP_KERNEL);
if (!revid_chip)
@@ -220,6 +226,7 @@ static int qpnp_revid_probe(struct platform_device *pdev)
revid_chip->data.pmic_subtype = pmic_subtype;
revid_chip->data.pmic_type = pmic_type;
revid_chip->data.fab_id = fab_id;
+ revid_chip->data.tp_rev = tp_rev;
if (pmic_subtype < ARRAY_SIZE(pmic_names))
revid_chip->data.pmic_name = pmic_names[pmic_subtype];
diff --git a/drivers/platform/msm/usb_bam.c b/drivers/platform/msm/usb_bam.c
index 48d31140834a..49e0666d0c23 100644
--- a/drivers/platform/msm/usb_bam.c
+++ b/drivers/platform/msm/usb_bam.c
@@ -103,7 +103,6 @@ struct usb_bam_sps_type {
struct usb_bam_ctx_type {
struct usb_bam_sps_type usb_bam_sps;
struct resource *io_res;
- void __iomem *regs;
int irq;
struct platform_device *usb_bam_pdev;
struct workqueue_struct *usb_bam_wq;
@@ -113,6 +112,7 @@ struct usb_bam_ctx_type {
u32 inactivity_timer_ms;
bool is_bam_inactivity;
struct usb_bam_pipe_connect *usb_bam_connections;
+ struct msm_usb_bam_data *usb_bam_data;
spinlock_t usb_bam_lock;
};
@@ -320,8 +320,6 @@ static int usb_bam_alloc_buffer(struct usb_bam_pipe_connect *pipe_connect)
{
int ret = 0;
struct usb_bam_ctx_type *ctx = &msm_usb_bam[pipe_connect->bam_type];
- struct msm_usb_bam_platform_data *pdata =
- ctx->usb_bam_pdev->dev.platform_data;
struct sps_mem_buffer *data_buf = &(pipe_connect->data_mem_buf);
struct sps_mem_buffer *desc_buf = &(pipe_connect->desc_mem_buf);
@@ -360,7 +358,7 @@ static int usb_bam_alloc_buffer(struct usb_bam_pipe_connect *pipe_connect)
}
data_buf->phys_base = pipe_connect->data_fifo_base_offset +
- pdata->usb_bam_fifo_baseaddr;
+ ctx->usb_bam_data->usb_bam_fifo_baseaddr;
data_buf->size = pipe_connect->data_fifo_size;
data_buf->base = ioremap(data_buf->phys_base, data_buf->size);
if (!data_buf->base) {
@@ -372,7 +370,7 @@ static int usb_bam_alloc_buffer(struct usb_bam_pipe_connect *pipe_connect)
memset_io(data_buf->base, 0, data_buf->size);
desc_buf->phys_base = pipe_connect->desc_fifo_base_offset +
- pdata->usb_bam_fifo_baseaddr;
+ ctx->usb_bam_data->usb_bam_fifo_baseaddr;
desc_buf->size = pipe_connect->desc_fifo_size;
desc_buf->base = ioremap(desc_buf->phys_base, desc_buf->size);
if (!desc_buf->base) {
@@ -1070,7 +1068,6 @@ int usb_bam_connect(enum usb_ctrl cur_bam, int idx, u32 *bam_pipe_idx)
struct usb_bam_pipe_connect *pipe_connect =
&ctx->usb_bam_connections[idx];
struct device *bam_dev = &ctx->usb_bam_pdev->dev;
- struct msm_usb_bam_platform_data *pdata = bam_dev->platform_data;
enum usb_bam_mode cur_mode;
if (pipe_connect->enabled) {
@@ -1096,7 +1093,7 @@ int usb_bam_connect(enum usb_ctrl cur_bam, int idx, u32 *bam_pipe_idx)
spin_lock(&ctx->usb_bam_lock);
/* Check if BAM requires RESET before connect and reset of first pipe */
- if ((pdata->reset_on_connect == true) &&
+ if ((ctx->usb_bam_data->reset_on_connect == true) &&
(ctx->pipes_enabled_per_bam == 0)) {
spin_unlock(&ctx->usb_bam_lock);
@@ -1596,8 +1593,6 @@ static int ss_usb_cons_release_resource(void)
static void usb_bam_ipa_create_resources(enum usb_ctrl cur_bam)
{
struct usb_bam_ctx_type *ctx = &msm_usb_bam[cur_bam];
- struct msm_usb_bam_platform_data *pdata =
- ctx->usb_bam_pdev->dev.platform_data;
struct ipa_rm_create_params usb_prod_create_params;
struct ipa_rm_create_params usb_cons_create_params;
int ret;
@@ -1606,7 +1601,8 @@ static void usb_bam_ipa_create_resources(enum usb_ctrl cur_bam)
memset(&usb_prod_create_params, 0, sizeof(usb_prod_create_params));
usb_prod_create_params.name = ipa_rm_resource_prod[cur_bam];
usb_prod_create_params.reg_params.notify_cb = usb_prod_notify_cb;
- usb_prod_create_params.reg_params.user_data = &pdata->bam_type;
+ usb_prod_create_params.reg_params.user_data
+ = &ctx->usb_bam_data->bam_type;
usb_prod_create_params.floor_voltage = IPA_VOLTAGE_SVS;
ret = ipa_rm_create_resource(&usb_prod_create_params);
if (ret) {
@@ -2136,16 +2132,14 @@ static int usb_bam_set_ipa_perf(enum usb_ctrl cur_bam,
int ret;
struct usb_bam_ctx_type *ctx = &msm_usb_bam[cur_bam];
struct ipa_rm_perf_profile ipa_rm_perf_prof;
- struct msm_usb_bam_platform_data *pdata =
- ctx->usb_bam_pdev->dev.platform_data;
if (usb_connection_speed == USB_SPEED_SUPER)
ipa_rm_perf_prof.max_supported_bandwidth_mbps =
- pdata->max_mbps_superspeed;
+ ctx->usb_bam_data->max_mbps_superspeed;
else
/* Bam2Bam is supported only for SS and HS (HW limitation) */
ipa_rm_perf_prof.max_supported_bandwidth_mbps =
- pdata->max_mbps_highspeed;
+ ctx->usb_bam_data->max_mbps_highspeed;
/*
* Having a max mbps property in dtsi file is a must
@@ -2182,7 +2176,6 @@ int usb_bam_connect_ipa(enum usb_ctrl cur_bam,
struct usb_bam_ctx_type *ctx = &msm_usb_bam[cur_bam];
struct usb_bam_pipe_connect *pipe_connect;
struct device *bam_dev = &ctx->usb_bam_pdev->dev;
- struct msm_usb_bam_platform_data *pdata = bam_dev->platform_data;
int ret;
bool bam2bam, is_dpl;
@@ -2260,7 +2253,8 @@ int usb_bam_connect_ipa(enum usb_ctrl cur_bam,
/* Check if BAM requires RESET before connect and reset first pipe */
spin_lock(&ctx->usb_bam_lock);
- if (pdata->reset_on_connect && !ctx->pipes_enabled_per_bam) {
+ if (ctx->usb_bam_data->reset_on_connect &&
+ !ctx->pipes_enabled_per_bam) {
spin_unlock(&ctx->usb_bam_lock);
if (cur_bam == CI_CTRL)
@@ -2610,8 +2604,6 @@ int usb_bam_disconnect_pipe(enum usb_ctrl bam_type, u8 idx)
struct usb_bam_pipe_connect *pipe_connect;
struct device *bam_dev = &ctx->usb_bam_pdev->dev;
int ret;
- struct msm_usb_bam_platform_data *pdata =
- ctx->usb_bam_pdev->dev.platform_data;
pipe_connect = &ctx->usb_bam_connections[idx];
@@ -2639,7 +2631,8 @@ int usb_bam_disconnect_pipe(enum usb_ctrl bam_type, u8 idx)
log_event_dbg("%s: success disconnecting pipe %d\n", __func__, idx);
- if (pdata->reset_on_disconnect && !ctx->pipes_enabled_per_bam) {
+ if (ctx->usb_bam_data->reset_on_disconnect
+ && !ctx->pipes_enabled_per_bam) {
if (bam_type == CI_CTRL)
msm_hw_bam_disable(1);
@@ -2807,10 +2800,10 @@ static void usb_bam_sps_events(enum sps_callback_case sps_cb_case, void *user)
}
}
-static struct msm_usb_bam_platform_data *usb_bam_dt_to_pdata(
+static struct msm_usb_bam_data *usb_bam_dt_to_data(
struct platform_device *pdev, u32 usb_addr)
{
- struct msm_usb_bam_platform_data *pdata;
+ struct msm_usb_bam_data *usb_bam_data;
struct device_node *node = pdev->dev.of_node;
int rc = 0;
u8 i = 0;
@@ -2819,10 +2812,10 @@ static struct msm_usb_bam_platform_data *usb_bam_dt_to_pdata(
u32 threshold, max_connections = 0;
static struct usb_bam_pipe_connect *usb_bam_connections;
- pdata = devm_kzalloc(&pdev->dev, sizeof(*pdata), GFP_KERNEL);
- if (!pdata) {
+ usb_bam_data = devm_kzalloc(&pdev->dev, sizeof(*usb_bam_data),
+ GFP_KERNEL);
+ if (!usb_bam_data)
return NULL;
- }
rc = of_property_read_u32(node, "qcom,bam-type", &bam);
if (rc) {
@@ -2835,7 +2828,7 @@ static struct msm_usb_bam_platform_data *usb_bam_dt_to_pdata(
__func__, bam);
return NULL;
}
- pdata->bam_type = bam;
+ usb_bam_data->bam_type = bam;
rc = of_property_read_u32(node, "qcom,bam-mode", &bam_mode);
if (rc) {
@@ -2845,49 +2838,49 @@ static struct msm_usb_bam_platform_data *usb_bam_dt_to_pdata(
bam_mode = USB_BAM_DEVICE;
}
- pdata->reset_on_connect = of_property_read_bool(node,
+ usb_bam_data->reset_on_connect = of_property_read_bool(node,
"qcom,reset-bam-on-connect");
- pdata->reset_on_disconnect = of_property_read_bool(node,
+ usb_bam_data->reset_on_disconnect = of_property_read_bool(node,
"qcom,reset-bam-on-disconnect");
rc = of_property_read_u32(node, "qcom,usb-bam-num-pipes",
- &pdata->usb_bam_num_pipes);
+ &usb_bam_data->usb_bam_num_pipes);
if (rc) {
log_event_err("Invalid usb bam num pipes property\n");
return NULL;
}
rc = of_property_read_u32(node, "qcom,usb-bam-max-mbps-highspeed",
- &pdata->max_mbps_highspeed);
+ &usb_bam_data->max_mbps_highspeed);
if (rc)
- pdata->max_mbps_highspeed = 0;
+ usb_bam_data->max_mbps_highspeed = 0;
rc = of_property_read_u32(node, "qcom,usb-bam-max-mbps-superspeed",
- &pdata->max_mbps_superspeed);
+ &usb_bam_data->max_mbps_superspeed);
if (rc)
- pdata->max_mbps_superspeed = 0;
+ usb_bam_data->max_mbps_superspeed = 0;
rc = of_property_read_u32(node, "qcom,usb-bam-fifo-baseaddr", &addr);
if (rc)
pr_debug("%s: Invalid usb base address property\n", __func__);
else
- pdata->usb_bam_fifo_baseaddr = addr;
+ usb_bam_data->usb_bam_fifo_baseaddr = addr;
- pdata->ignore_core_reset_ack = of_property_read_bool(node,
+ usb_bam_data->ignore_core_reset_ack = of_property_read_bool(node,
"qcom,ignore-core-reset-ack");
- pdata->disable_clk_gating = of_property_read_bool(node,
+ usb_bam_data->disable_clk_gating = of_property_read_bool(node,
"qcom,disable-clk-gating");
rc = of_property_read_u32(node, "qcom,usb-bam-override-threshold",
&threshold);
if (rc)
- pdata->override_threshold = USB_THRESHOLD;
+ usb_bam_data->override_threshold = USB_THRESHOLD;
else
- pdata->override_threshold = threshold;
+ usb_bam_data->override_threshold = threshold;
- pdata->enable_hsusb_bam_on_boot = of_property_read_bool(node,
+ usb_bam_data->enable_hsusb_bam_on_boot = of_property_read_bool(node,
"qcom,enable-hsusb-bam-on-boot");
for_each_child_of_node(pdev->dev.of_node, node)
@@ -2923,7 +2916,7 @@ static struct msm_usb_bam_platform_data *usb_bam_dt_to_pdata(
goto err;
if (usb_bam_connections[i].mem_type == OCI_MEM) {
- if (!pdata->usb_bam_fifo_baseaddr) {
+ if (!usb_bam_data->usb_bam_fifo_baseaddr) {
log_event_err("%s: base address is missing\n",
__func__);
goto err;
@@ -3007,7 +3000,7 @@ static struct msm_usb_bam_platform_data *usb_bam_dt_to_pdata(
msm_usb_bam[bam].usb_bam_connections = usb_bam_connections;
msm_usb_bam[bam].max_connections = max_connections;
- return pdata;
+ return usb_bam_data;
err:
log_event_err("%s: failed\n", __func__);
return NULL;
@@ -3016,9 +3009,8 @@ err:
static int usb_bam_init(struct platform_device *pdev)
{
int ret;
- struct msm_usb_bam_platform_data *pdata = pdev->dev.platform_data;
- enum usb_ctrl bam_type = pdata->bam_type;
- struct usb_bam_ctx_type *ctx = &msm_usb_bam[bam_type];
+ struct usb_bam_ctx_type *ctx = dev_get_drvdata(&pdev->dev);
+ enum usb_ctrl bam_type = ctx->usb_bam_data->bam_type;
struct sps_bam_props props;
memset(&props, 0, sizeof(props));
@@ -3027,12 +3019,11 @@ static int usb_bam_init(struct platform_device *pdev)
bam_enable_strings[bam_type]);
props.phys_addr = ctx->io_res->start;
- props.virt_addr = ctx->regs;
props.virt_size = resource_size(ctx->io_res);
props.irq = ctx->irq;
- props.summing_threshold = pdata->override_threshold;
- props.event_threshold = pdata->override_threshold;
- props.num_pipes = pdata->usb_bam_num_pipes;
+ props.summing_threshold = ctx->usb_bam_data->override_threshold;
+ props.event_threshold = ctx->usb_bam_data->override_threshold;
+ props.num_pipes = ctx->usb_bam_data->usb_bam_num_pipes;
props.callback = usb_bam_sps_events;
props.user = bam_enable_strings[bam_type];
@@ -3040,10 +3031,10 @@ static int usb_bam_init(struct platform_device *pdev)
* HSUSB and HSIC Cores don't support RESET ACK signal to BAMs
* Hence, let BAM to ignore acknowledge from USB while resetting PIPE
*/
- if (pdata->ignore_core_reset_ack && bam_type != DWC3_CTRL)
+ if (ctx->usb_bam_data->ignore_core_reset_ack && bam_type != DWC3_CTRL)
props.options = SPS_BAM_NO_EXT_P_RST;
- if (pdata->disable_clk_gating)
+ if (ctx->usb_bam_data->disable_clk_gating)
props.options |= SPS_BAM_NO_LOCAL_CLK_GATING;
/*
@@ -3051,7 +3042,8 @@ static int usb_bam_init(struct platform_device *pdev)
* starting peripheral controller to avoid switching USB core mode
* from legacy to BAM with ongoing data transfers.
*/
- if (pdata->enable_hsusb_bam_on_boot && bam_type == CI_CTRL) {
+ if (ctx->usb_bam_data->enable_hsusb_bam_on_boot
+ && bam_type == CI_CTRL) {
pr_debug("Register and enable HSUSB BAM\n");
props.options |= SPS_BAM_OPT_ENABLE_AT_BOOT;
}
@@ -3068,9 +3060,8 @@ static int usb_bam_init(struct platform_device *pdev)
static int enable_usb_bam(struct platform_device *pdev)
{
int ret;
- struct msm_usb_bam_platform_data *pdata = pdev->dev.platform_data;
- enum usb_ctrl bam_type = pdata->bam_type;
- struct usb_bam_ctx_type *ctx = &msm_usb_bam[bam_type];
+ struct usb_bam_ctx_type *ctx = dev_get_drvdata(&pdev->dev);
+ enum usb_ctrl bam_type = ctx->usb_bam_data->bam_type;
ret = usb_bam_init(pdev);
if (ret) {
@@ -3137,14 +3128,19 @@ void usb_bam_register_panic_hdlr(void)
&usb_bam_panic_blk);
}
+static void usb_bam_unregister_panic_hdlr(void)
+{
+ atomic_notifier_chain_unregister(&panic_notifier_list,
+ &usb_bam_panic_blk);
+}
+
static int usb_bam_probe(struct platform_device *pdev)
{
int ret, i, irq;
struct resource *io_res;
- void __iomem *regs;
enum usb_ctrl bam_type;
struct usb_bam_ctx_type *ctx;
- struct msm_usb_bam_platform_data *pdata;
+ struct msm_usb_bam_data *usb_bam_data;
dev_dbg(&pdev->dev, "usb_bam_probe\n");
@@ -3160,25 +3156,19 @@ static int usb_bam_probe(struct platform_device *pdev)
return irq;
}
- regs = devm_ioremap(&pdev->dev, io_res->start, resource_size(io_res));
- if (!regs) {
- log_event_err("%s: ioremap failed\n", __func__);
- return -ENOMEM;
- }
-
/* specify BAM physical address to be filled in BAM connections */
- pdata = usb_bam_dt_to_pdata(pdev, io_res->start);
- if (!pdata)
+ usb_bam_data = usb_bam_dt_to_data(pdev, io_res->start);
+ if (!usb_bam_data)
return -EINVAL;
- pdev->dev.platform_data = pdata;
- bam_type = pdata->bam_type;
+ bam_type = usb_bam_data->bam_type;
ctx = &msm_usb_bam[bam_type];
+ dev_set_drvdata(&pdev->dev, ctx);
ctx->usb_bam_pdev = pdev;
ctx->irq = irq;
- ctx->regs = regs;
ctx->io_res = io_res;
+ ctx->usb_bam_data = usb_bam_data;
for (i = 0; i < ctx->max_connections; i++) {
ctx->usb_bam_connections[i].enabled = 0;
@@ -3319,15 +3309,15 @@ EXPORT_SYMBOL(usb_bam_get_bam_type);
bool msm_usb_bam_enable(enum usb_ctrl bam, bool bam_enable)
{
- struct msm_usb_bam_platform_data *pdata;
+ struct msm_usb_bam_data *usb_bam_data;
struct usb_bam_ctx_type *ctx = &msm_usb_bam[bam];
if (!ctx->usb_bam_pdev)
return 0;
- pdata = ctx->usb_bam_pdev->dev.platform_data;
+ usb_bam_data = ctx->usb_bam_data;
if ((bam != CI_CTRL) || !(bam_enable ||
- pdata->enable_hsusb_bam_on_boot))
+ usb_bam_data->enable_hsusb_bam_on_boot))
return 0;
msm_hw_bam_disable(1);
@@ -3409,10 +3399,10 @@ EXPORT_SYMBOL(msm_bam_hsic_lpm_ok);
static int usb_bam_remove(struct platform_device *pdev)
{
- struct msm_usb_bam_platform_data *pdata = pdev->dev.platform_data;
- enum usb_ctrl bam_type = pdata->bam_type;
- struct usb_bam_ctx_type *ctx = &msm_usb_bam[bam_type];
+ struct usb_bam_ctx_type *ctx = dev_get_drvdata(&pdev->dev);
+ usb_bam_unregister_panic_hdlr();
+ sps_deregister_bam_device(ctx->h_bam);
destroy_workqueue(ctx->usb_bam_wq);
return 0;
diff --git a/drivers/power/power_supply_sysfs.c b/drivers/power/power_supply_sysfs.c
index 743972bb4b3c..a45a51490817 100644
--- a/drivers/power/power_supply_sysfs.c
+++ b/drivers/power/power_supply_sysfs.c
@@ -300,6 +300,9 @@ static struct device_attribute power_supply_attrs[] = {
POWER_SUPPLY_ATTR(cc_step),
POWER_SUPPLY_ATTR(cc_step_sel),
POWER_SUPPLY_ATTR(sw_jeita_enabled),
+ POWER_SUPPLY_ATTR(pd_voltage_max),
+ POWER_SUPPLY_ATTR(pd_voltage_min),
+ POWER_SUPPLY_ATTR(sdp_current_max),
/* Local extensions of type int64_t */
POWER_SUPPLY_ATTR(charge_counter_ext),
/* Properties of type `const char *' */
diff --git a/drivers/power/supply/qcom/pmic-voter.c b/drivers/power/supply/qcom/pmic-voter.c
index b99558ed2100..3d0a71844608 100644
--- a/drivers/power/supply/qcom/pmic-voter.c
+++ b/drivers/power/supply/qcom/pmic-voter.c
@@ -438,12 +438,14 @@ out:
int rerun_election(struct votable *votable)
{
int rc = 0;
+ int effective_result;
lock_votable(votable);
+ effective_result = get_effective_result_locked(votable);
if (votable->callback)
rc = votable->callback(votable,
- votable->data,
- votable->effective_result,
+ votable->data,
+ effective_result,
get_client_str(votable, votable->effective_client_id));
unlock_votable(votable);
return rc;
@@ -519,11 +521,10 @@ static int show_votable_clients(struct seq_file *m, void *data)
lock_votable(votable);
- seq_printf(m, "Votable %s:\n", votable->name);
- seq_puts(m, "clients:\n");
for (i = 0; i < votable->num_clients; i++) {
if (votable->client_strs[i]) {
- seq_printf(m, "%-15s:\t\ten=%d\t\tv=%d\n",
+ seq_printf(m, "%s: %s:\t\t\ten=%d v=%d\n",
+ votable->name,
votable->client_strs[i],
votable->votes[i].enabled,
votable->votes[i].value);
@@ -542,11 +543,11 @@ static int show_votable_clients(struct seq_file *m, void *data)
break;
}
- seq_printf(m, "type: %s\n", type_str);
- seq_puts(m, "Effective:\n");
effective_client_str = get_effective_client_locked(votable);
- seq_printf(m, "%-15s:\t\tv=%d\n",
+ seq_printf(m, "%s: effective=%s type=%s v=%d\n",
+ votable->name,
effective_client_str ? effective_client_str : "none",
+ type_str,
get_effective_result_locked(votable));
unlock_votable(votable);
diff --git a/drivers/power/supply/qcom/qpnp-smb2.c b/drivers/power/supply/qcom/qpnp-smb2.c
index b0a78758abd6..c085256a794a 100644
--- a/drivers/power/supply/qcom/qpnp-smb2.c
+++ b/drivers/power/supply/qcom/qpnp-smb2.c
@@ -330,7 +330,6 @@ static int smb2_parse_dt(struct smb2 *chip)
static enum power_supply_property smb2_usb_props[] = {
POWER_SUPPLY_PROP_PRESENT,
POWER_SUPPLY_PROP_ONLINE,
- POWER_SUPPLY_PROP_VOLTAGE_MIN,
POWER_SUPPLY_PROP_VOLTAGE_MAX,
POWER_SUPPLY_PROP_VOLTAGE_NOW,
POWER_SUPPLY_PROP_PD_CURRENT_MAX,
@@ -349,6 +348,9 @@ static enum power_supply_property smb2_usb_props[] = {
POWER_SUPPLY_PROP_HW_CURRENT_MAX,
POWER_SUPPLY_PROP_REAL_TYPE,
POWER_SUPPLY_PROP_PR_SWAP,
+ POWER_SUPPLY_PROP_PD_VOLTAGE_MAX,
+ POWER_SUPPLY_PROP_PD_VOLTAGE_MIN,
+ POWER_SUPPLY_PROP_SDP_CURRENT_MAX,
};
static int smb2_usb_get_prop(struct power_supply *psy,
@@ -380,20 +382,17 @@ static int smb2_usb_get_prop(struct power_supply *psy,
if (chg->real_charger_type == POWER_SUPPLY_TYPE_UNKNOWN)
val->intval = 0;
break;
- case POWER_SUPPLY_PROP_VOLTAGE_MIN:
- val->intval = chg->voltage_min_uv;
- break;
case POWER_SUPPLY_PROP_VOLTAGE_MAX:
- val->intval = chg->voltage_max_uv;
+ rc = smblib_get_prop_usb_voltage_max(chg, val);
break;
case POWER_SUPPLY_PROP_VOLTAGE_NOW:
rc = smblib_get_prop_usb_voltage_now(chg, val);
break;
case POWER_SUPPLY_PROP_PD_CURRENT_MAX:
- rc = smblib_get_prop_pd_current_max(chg, val);
+ val->intval = get_client_vote(chg->usb_icl_votable, PD_VOTER);
break;
case POWER_SUPPLY_PROP_CURRENT_MAX:
- rc = smblib_get_prop_usb_current_max(chg, val);
+ rc = smblib_get_prop_input_current_settled(chg, val);
break;
case POWER_SUPPLY_PROP_TYPE:
val->intval = POWER_SUPPLY_TYPE_USB_PD;
@@ -457,6 +456,16 @@ static int smb2_usb_get_prop(struct power_supply *psy,
case POWER_SUPPLY_PROP_PR_SWAP:
rc = smblib_get_prop_pr_swap_in_progress(chg, val);
break;
+ case POWER_SUPPLY_PROP_PD_VOLTAGE_MAX:
+ val->intval = chg->voltage_max_uv;
+ break;
+ case POWER_SUPPLY_PROP_PD_VOLTAGE_MIN:
+ val->intval = chg->voltage_min_uv;
+ break;
+ case POWER_SUPPLY_PROP_SDP_CURRENT_MAX:
+ val->intval = get_client_vote(chg->usb_icl_votable,
+ USB_PSY_VOTER);
+ break;
default:
pr_err("get prop %d is not supported in usb\n", psp);
rc = -EINVAL;
@@ -484,18 +493,9 @@ static int smb2_usb_set_prop(struct power_supply *psy,
}
switch (psp) {
- case POWER_SUPPLY_PROP_VOLTAGE_MIN:
- rc = smblib_set_prop_usb_voltage_min(chg, val);
- break;
- case POWER_SUPPLY_PROP_VOLTAGE_MAX:
- rc = smblib_set_prop_usb_voltage_max(chg, val);
- break;
case POWER_SUPPLY_PROP_PD_CURRENT_MAX:
rc = smblib_set_prop_pd_current_max(chg, val);
break;
- case POWER_SUPPLY_PROP_CURRENT_MAX:
- rc = smblib_set_prop_usb_current_max(chg, val);
- break;
case POWER_SUPPLY_PROP_TYPEC_POWER_ROLE:
rc = smblib_set_prop_typec_power_role(chg, val);
break;
@@ -518,6 +518,15 @@ static int smb2_usb_set_prop(struct power_supply *psy,
case POWER_SUPPLY_PROP_PR_SWAP:
rc = smblib_set_prop_pr_swap_in_progress(chg, val);
break;
+ case POWER_SUPPLY_PROP_PD_VOLTAGE_MAX:
+ rc = smblib_set_prop_pd_voltage_max(chg, val);
+ break;
+ case POWER_SUPPLY_PROP_PD_VOLTAGE_MIN:
+ rc = smblib_set_prop_pd_voltage_min(chg, val);
+ break;
+ case POWER_SUPPLY_PROP_SDP_CURRENT_MAX:
+ rc = smblib_set_prop_sdp_current_max(chg, val);
+ break;
default:
pr_err("set prop %d is not supported\n", psp);
rc = -EINVAL;
@@ -533,8 +542,6 @@ static int smb2_usb_prop_is_writeable(struct power_supply *psy,
enum power_supply_property psp)
{
switch (psp) {
- case POWER_SUPPLY_PROP_CURRENT_MAX:
- case POWER_SUPPLY_PROP_TYPEC_POWER_ROLE:
case POWER_SUPPLY_PROP_CTM_CURRENT_MAX:
return 1;
default:
@@ -576,6 +583,8 @@ static int smb2_init_usb_psy(struct smb2 *chip)
static enum power_supply_property smb2_usb_port_props[] = {
POWER_SUPPLY_PROP_TYPE,
POWER_SUPPLY_PROP_ONLINE,
+ POWER_SUPPLY_PROP_VOLTAGE_MAX,
+ POWER_SUPPLY_PROP_CURRENT_MAX,
};
static int smb2_usb_port_get_prop(struct power_supply *psy,
@@ -602,6 +611,12 @@ static int smb2_usb_port_get_prop(struct power_supply *psy,
else
val->intval = 0;
break;
+ case POWER_SUPPLY_PROP_VOLTAGE_MAX:
+ val->intval = 5000000;
+ break;
+ case POWER_SUPPLY_PROP_CURRENT_MAX:
+ rc = smblib_get_prop_input_current_settled(chg, val);
+ break;
default:
pr_err_ratelimited("Get prop %d is not supported in pc_port\n",
psp);
@@ -783,6 +798,7 @@ static enum power_supply_property smb2_dc_props[] = {
POWER_SUPPLY_PROP_PRESENT,
POWER_SUPPLY_PROP_ONLINE,
POWER_SUPPLY_PROP_CURRENT_MAX,
+ POWER_SUPPLY_PROP_REAL_TYPE,
};
static int smb2_dc_get_prop(struct power_supply *psy,
@@ -803,6 +819,9 @@ static int smb2_dc_get_prop(struct power_supply *psy,
case POWER_SUPPLY_PROP_CURRENT_MAX:
rc = smblib_get_prop_dc_current_max(chg, val);
break;
+ case POWER_SUPPLY_PROP_REAL_TYPE:
+ val->intval = POWER_SUPPLY_TYPE_WIPOWER;
+ break;
default:
return -EINVAL;
}
@@ -851,7 +870,7 @@ static int smb2_dc_prop_is_writeable(struct power_supply *psy,
static const struct power_supply_desc dc_psy_desc = {
.name = "dc",
- .type = POWER_SUPPLY_TYPE_WIPOWER,
+ .type = POWER_SUPPLY_TYPE_WIRELESS,
.properties = smb2_dc_props,
.num_properties = ARRAY_SIZE(smb2_dc_props),
.get_property = smb2_dc_get_prop,
@@ -908,6 +927,7 @@ static enum power_supply_property smb2_batt_props[] = {
POWER_SUPPLY_PROP_DIE_HEALTH,
POWER_SUPPLY_PROP_RERUN_AICL,
POWER_SUPPLY_PROP_DP_DM,
+ POWER_SUPPLY_PROP_CHARGE_COUNTER,
};
static int smb2_batt_get_prop(struct power_supply *psy,
@@ -1013,6 +1033,9 @@ static int smb2_batt_get_prop(struct power_supply *psy,
case POWER_SUPPLY_PROP_RERUN_AICL:
val->intval = 0;
break;
+ case POWER_SUPPLY_PROP_CHARGE_COUNTER:
+ rc = smblib_get_prop_batt_charge_counter(chg, val);
+ break;
default:
pr_err("batt power supply prop %d not supported\n", psp);
return -EINVAL;
@@ -1799,8 +1822,8 @@ static int smb2_chg_config_init(struct smb2 *chip)
chip->chg.wa_flags |= BOOST_BACK_WA | OTG_WA;
chg->param.freq_buck = pm660_params.freq_buck;
chg->param.freq_boost = pm660_params.freq_boost;
- chg->chg_freq.freq_5V = 600;
- chg->chg_freq.freq_6V_8V = 800;
+ chg->chg_freq.freq_5V = 650;
+ chg->chg_freq.freq_6V_8V = 850;
chg->chg_freq.freq_9V = 1050;
chg->chg_freq.freq_12V = 1200;
chg->chg_freq.freq_removal = 1050;
diff --git a/drivers/power/supply/qcom/smb-lib.c b/drivers/power/supply/qcom/smb-lib.c
index 825d49b2fe4f..f9d35ea7775b 100644
--- a/drivers/power/supply/qcom/smb-lib.c
+++ b/drivers/power/supply/qcom/smb-lib.c
@@ -420,19 +420,21 @@ static int smblib_set_adapter_allowance(struct smb_charger *chg,
{
int rc = 0;
- switch (allowed_voltage) {
- case USBIN_ADAPTER_ALLOW_12V:
- case USBIN_ADAPTER_ALLOW_5V_OR_12V:
- case USBIN_ADAPTER_ALLOW_9V_TO_12V:
- case USBIN_ADAPTER_ALLOW_5V_OR_9V_TO_12V:
- case USBIN_ADAPTER_ALLOW_5V_TO_12V:
- /* PM660 only support max. 9V */
- if (chg->smb_version == PM660_SUBTYPE) {
- smblib_dbg(chg, PR_MISC, "voltage not supported=%d\n",
- allowed_voltage);
+ /* PM660 only support max. 9V */
+ if (chg->smb_version == PM660_SUBTYPE) {
+ switch (allowed_voltage) {
+ case USBIN_ADAPTER_ALLOW_12V:
+ case USBIN_ADAPTER_ALLOW_9V_TO_12V:
+ allowed_voltage = USBIN_ADAPTER_ALLOW_9V;
+ break;
+ case USBIN_ADAPTER_ALLOW_5V_OR_12V:
+ case USBIN_ADAPTER_ALLOW_5V_OR_9V_TO_12V:
allowed_voltage = USBIN_ADAPTER_ALLOW_5V_OR_9V;
+ break;
+ case USBIN_ADAPTER_ALLOW_5V_TO_12V:
+ allowed_voltage = USBIN_ADAPTER_ALLOW_5V_TO_9V;
+ break;
}
- break;
}
rc = smblib_write(chg, USBIN_ADAPTER_ALLOW_CFG_REG, allowed_voltage);
@@ -1843,6 +1845,19 @@ int smblib_get_prop_charge_qnovo_enable(struct smb_charger *chg,
return 0;
}
+int smblib_get_prop_batt_charge_counter(struct smb_charger *chg,
+ union power_supply_propval *val)
+{
+ int rc;
+
+ if (!chg->bms_psy)
+ return -EINVAL;
+
+ rc = power_supply_get_property(chg->bms_psy,
+ POWER_SUPPLY_PROP_CHARGE_COUNTER, val);
+ return rc;
+}
+
/***********************
* BATTERY PSY SETTERS *
***********************/
@@ -2187,6 +2202,25 @@ int smblib_get_prop_usb_online(struct smb_charger *chg,
return rc;
}
+int smblib_get_prop_usb_voltage_max(struct smb_charger *chg,
+ union power_supply_propval *val)
+{
+ switch (chg->real_charger_type) {
+ case POWER_SUPPLY_TYPE_USB_HVDCP:
+ case POWER_SUPPLY_TYPE_USB_PD:
+ if (chg->smb_version == PM660_SUBTYPE)
+ val->intval = MICRO_9V;
+ else
+ val->intval = MICRO_12V;
+ break;
+ default:
+ val->intval = MICRO_5V;
+ break;
+ }
+
+ return 0;
+}
+
int smblib_get_prop_usb_voltage_now(struct smb_charger *chg,
union power_supply_propval *val)
{
@@ -2206,21 +2240,6 @@ int smblib_get_prop_usb_voltage_now(struct smb_charger *chg,
return iio_read_channel_processed(chg->iio.usbin_v_chan, &val->intval);
}
-int smblib_get_prop_pd_current_max(struct smb_charger *chg,
- union power_supply_propval *val)
-{
- val->intval = get_client_vote_locked(chg->usb_icl_votable, PD_VOTER);
- return 0;
-}
-
-int smblib_get_prop_usb_current_max(struct smb_charger *chg,
- union power_supply_propval *val)
-{
- val->intval = get_client_vote_locked(chg->usb_icl_votable,
- USB_PSY_VOTER);
- return 0;
-}
-
int smblib_get_prop_usb_current_now(struct smb_charger *chg,
union power_supply_propval *val)
{
@@ -2558,7 +2577,7 @@ static int smblib_handle_usb_current(struct smb_charger *chg,
return rc;
}
-int smblib_set_prop_usb_current_max(struct smb_charger *chg,
+int smblib_set_prop_sdp_current_max(struct smb_charger *chg,
const union power_supply_propval *val)
{
int rc = 0;
@@ -2645,7 +2664,7 @@ int smblib_set_prop_typec_power_role(struct smb_charger *chg,
return rc;
}
-int smblib_set_prop_usb_voltage_min(struct smb_charger *chg,
+int smblib_set_prop_pd_voltage_min(struct smb_charger *chg,
const union power_supply_propval *val)
{
int rc, min_uv;
@@ -2664,7 +2683,7 @@ int smblib_set_prop_usb_voltage_min(struct smb_charger *chg,
return rc;
}
-int smblib_set_prop_usb_voltage_max(struct smb_charger *chg,
+int smblib_set_prop_pd_voltage_max(struct smb_charger *chg,
const union power_supply_propval *val)
{
int rc, max_uv;
@@ -3597,6 +3616,32 @@ static void smblib_force_legacy_icl(struct smb_charger *chg, int pst)
}
}
+static void smblib_notify_extcon_props(struct smb_charger *chg)
+{
+ union power_supply_propval val;
+
+ smblib_get_prop_typec_cc_orientation(chg, &val);
+ extcon_set_cable_state_(chg->extcon, EXTCON_USB_CC,
+ (val.intval == 2) ? 1 : 0);
+ extcon_set_cable_state_(chg->extcon, EXTCON_USB_SPEED, true);
+}
+
+static void smblib_notify_device_mode(struct smb_charger *chg, bool enable)
+{
+ if (enable)
+ smblib_notify_extcon_props(chg);
+
+ extcon_set_cable_state_(chg->extcon, EXTCON_USB, enable);
+}
+
+static void smblib_notify_usb_host(struct smb_charger *chg, bool enable)
+{
+ if (enable)
+ smblib_notify_extcon_props(chg);
+
+ extcon_set_cable_state_(chg->extcon, EXTCON_USB_HOST, enable);
+}
+
#define HVDCP_DET_MS 2500
static void smblib_handle_apsd_done(struct smb_charger *chg, bool rising)
{
@@ -3616,6 +3661,8 @@ static void smblib_handle_apsd_done(struct smb_charger *chg, bool rising)
if (chg->micro_usb_mode)
extcon_set_cable_state_(chg->extcon, EXTCON_USB,
true);
+ if (chg->use_extcon)
+ smblib_notify_device_mode(chg, true);
case OCP_CHARGER_BIT:
case FLOAT_CHARGER_BIT:
/* if not DCP then no hvdcp timeout happens, Enable pd here. */
@@ -3700,6 +3747,10 @@ static void typec_sink_insertion(struct smb_charger *chg)
*/
vote(chg->pd_disallowed_votable_indirect, HVDCP_TIMEOUT_VOTER,
false, 0);
+ if (chg->use_extcon) {
+ smblib_notify_usb_host(chg, true);
+ chg->otg_present = true;
+ }
}
static void typec_sink_removal(struct smb_charger *chg)
@@ -3848,6 +3899,14 @@ unlock:
typec_sink_removal(chg);
smblib_update_usb_type(chg);
+
+ if (chg->use_extcon) {
+ if (chg->otg_present)
+ smblib_notify_usb_host(chg, false);
+ else
+ smblib_notify_device_mode(chg, false);
+ }
+ chg->otg_present = false;
}
static void smblib_handle_typec_insertion(struct smb_charger *chg)
diff --git a/drivers/power/supply/qcom/smb-lib.h b/drivers/power/supply/qcom/smb-lib.h
index 0bb1ae03d101..a89d09711ec8 100644
--- a/drivers/power/supply/qcom/smb-lib.h
+++ b/drivers/power/supply/qcom/smb-lib.h
@@ -139,9 +139,14 @@ struct smb_irq_info {
static const unsigned int smblib_extcon_cable[] = {
EXTCON_USB,
EXTCON_USB_HOST,
+ EXTCON_USB_CC,
+ EXTCON_USB_SPEED,
EXTCON_NONE,
};
+/* EXTCON_USB and EXTCON_USB_HOST are mutually exclusive */
+static const u32 smblib_extcon_exclusive[] = {0x3, 0};
+
struct smb_regulator {
struct regulator_dev *rdev;
struct regulator_desc rdesc;
@@ -328,6 +333,8 @@ struct smb_charger {
int usb_icl_change_irq_enabled;
u32 jeita_status;
u8 float_cfg;
+ bool use_extcon;
+ bool otg_present;
/* workaround flag */
u32 wa_flags;
@@ -419,6 +426,8 @@ int smblib_get_prop_batt_current_now(struct smb_charger *chg,
union power_supply_propval *val);
int smblib_get_prop_batt_temp(struct smb_charger *chg,
union power_supply_propval *val);
+int smblib_get_prop_batt_charge_counter(struct smb_charger *chg,
+ union power_supply_propval *val);
int smblib_set_prop_input_suspend(struct smb_charger *chg,
const union power_supply_propval *val);
int smblib_set_prop_batt_capacity(struct smb_charger *chg,
@@ -443,11 +452,9 @@ int smblib_get_prop_usb_online(struct smb_charger *chg,
union power_supply_propval *val);
int smblib_get_prop_usb_suspend(struct smb_charger *chg,
union power_supply_propval *val);
-int smblib_get_prop_usb_voltage_now(struct smb_charger *chg,
+int smblib_get_prop_usb_voltage_max(struct smb_charger *chg,
union power_supply_propval *val);
-int smblib_get_prop_pd_current_max(struct smb_charger *chg,
- union power_supply_propval *val);
-int smblib_get_prop_usb_current_max(struct smb_charger *chg,
+int smblib_get_prop_usb_voltage_now(struct smb_charger *chg,
union power_supply_propval *val);
int smblib_get_prop_usb_current_now(struct smb_charger *chg,
union power_supply_propval *val);
@@ -475,11 +482,11 @@ int smblib_get_prop_charge_qnovo_enable(struct smb_charger *chg,
union power_supply_propval *val);
int smblib_set_prop_pd_current_max(struct smb_charger *chg,
const union power_supply_propval *val);
-int smblib_set_prop_usb_current_max(struct smb_charger *chg,
+int smblib_set_prop_sdp_current_max(struct smb_charger *chg,
const union power_supply_propval *val);
-int smblib_set_prop_usb_voltage_min(struct smb_charger *chg,
+int smblib_set_prop_pd_voltage_max(struct smb_charger *chg,
const union power_supply_propval *val);
-int smblib_set_prop_usb_voltage_max(struct smb_charger *chg,
+int smblib_set_prop_pd_voltage_min(struct smb_charger *chg,
const union power_supply_propval *val);
int smblib_set_prop_boost_current(struct smb_charger *chg,
const union power_supply_propval *val);
diff --git a/drivers/power/supply/qcom/smb138x-charger.c b/drivers/power/supply/qcom/smb138x-charger.c
index ec74e3825dd5..e7ca1e3fb108 100644
--- a/drivers/power/supply/qcom/smb138x-charger.c
+++ b/drivers/power/supply/qcom/smb138x-charger.c
@@ -215,6 +215,7 @@ static enum power_supply_property smb138x_usb_props[] = {
POWER_SUPPLY_PROP_TYPEC_MODE,
POWER_SUPPLY_PROP_TYPEC_POWER_ROLE,
POWER_SUPPLY_PROP_TYPEC_CC_ORIENTATION,
+ POWER_SUPPLY_PROP_SDP_CURRENT_MAX,
};
static int smb138x_usb_get_prop(struct power_supply *psy,
@@ -242,7 +243,7 @@ static int smb138x_usb_get_prop(struct power_supply *psy,
rc = smblib_get_prop_usb_voltage_now(chg, val);
break;
case POWER_SUPPLY_PROP_CURRENT_MAX:
- rc = smblib_get_prop_usb_current_max(chg, val);
+ val->intval = get_effective_result(chg->usb_icl_votable);
break;
case POWER_SUPPLY_PROP_TYPE:
val->intval = chg->usb_psy_desc.type;
@@ -256,6 +257,10 @@ static int smb138x_usb_get_prop(struct power_supply *psy,
case POWER_SUPPLY_PROP_TYPEC_CC_ORIENTATION:
rc = smblib_get_prop_typec_cc_orientation(chg, val);
break;
+ case POWER_SUPPLY_PROP_SDP_CURRENT_MAX:
+ val->intval = get_client_vote(chg->usb_icl_votable,
+ USB_PSY_VOTER);
+ break;
default:
pr_err("get prop %d is not supported\n", prop);
return -EINVAL;
@@ -278,18 +283,12 @@ static int smb138x_usb_set_prop(struct power_supply *psy,
int rc = 0;
switch (prop) {
- case POWER_SUPPLY_PROP_VOLTAGE_MIN:
- rc = smblib_set_prop_usb_voltage_min(chg, val);
- break;
- case POWER_SUPPLY_PROP_VOLTAGE_MAX:
- rc = smblib_set_prop_usb_voltage_max(chg, val);
- break;
- case POWER_SUPPLY_PROP_CURRENT_MAX:
- rc = smblib_set_prop_usb_current_max(chg, val);
- break;
case POWER_SUPPLY_PROP_TYPEC_POWER_ROLE:
rc = smblib_set_prop_typec_power_role(chg, val);
break;
+ case POWER_SUPPLY_PROP_SDP_CURRENT_MAX:
+ rc = smblib_set_prop_sdp_current_max(chg, val);
+ break;
default:
pr_err("set prop %d is not supported\n", prop);
return -EINVAL;
@@ -301,13 +300,6 @@ static int smb138x_usb_set_prop(struct power_supply *psy,
static int smb138x_usb_prop_is_writeable(struct power_supply *psy,
enum power_supply_property prop)
{
- switch (prop) {
- case POWER_SUPPLY_PROP_TYPEC_POWER_ROLE:
- return 1;
- default:
- break;
- }
-
return 0;
}
@@ -871,6 +863,13 @@ static int smb138x_init_slave_hw(struct smb138x *chip)
return rc;
}
+ /* Disable OTG */
+ rc = smblib_masked_write(chg, CMD_OTG_REG, OTG_EN_BIT, 0);
+ if (rc < 0) {
+ pr_err("Couldn't disable OTG rc=%d\n", rc);
+ return rc;
+ }
+
/* suspend parallel charging */
rc = smb138x_set_parallel_suspend(chip, true);
if (rc < 0) {
@@ -968,6 +967,20 @@ static int smb138x_init_hw(struct smb138x *chip)
chg->dcp_icl_ua = chip->dt.usb_icl_ua;
+ /* Disable OTG */
+ rc = smblib_masked_write(chg, CMD_OTG_REG, OTG_EN_BIT, 0);
+ if (rc < 0) {
+ pr_err("Couldn't disable OTG rc=%d\n", rc);
+ return rc;
+ }
+
+ /* Unsuspend USB input */
+ rc = smblib_masked_write(chg, USBIN_CMD_IL_REG, USBIN_SUSPEND_BIT, 0);
+ if (rc < 0) {
+ pr_err("Couldn't unsuspend USB, rc=%d\n", rc);
+ return rc;
+ }
+
/* configure to a fixed 700khz freq to avoid tdie errors */
rc = smblib_set_charge_param(chg, &chg->param.freq_buck, 700);
if (rc < 0) {
@@ -1608,14 +1621,33 @@ static int smb138x_remove(struct platform_device *pdev)
return 0;
}
+static void smb138x_shutdown(struct platform_device *pdev)
+{
+ struct smb138x *chip = platform_get_drvdata(pdev);
+ struct smb_charger *chg = &chip->chg;
+ int rc;
+
+ /* Suspend charging */
+ rc = smb138x_set_parallel_suspend(chip, true);
+ if (rc < 0)
+ pr_err("Couldn't suspend charging rc=%d\n", rc);
+
+ /* Disable OTG */
+ rc = smblib_masked_write(chg, CMD_OTG_REG, OTG_EN_BIT, 0);
+ if (rc < 0)
+ pr_err("Couldn't disable OTG rc=%d\n", rc);
+
+}
+
static struct platform_driver smb138x_driver = {
.driver = {
.name = "qcom,smb138x-charger",
.owner = THIS_MODULE,
.of_match_table = match_table,
},
- .probe = smb138x_probe,
- .remove = smb138x_remove,
+ .probe = smb138x_probe,
+ .remove = smb138x_remove,
+ .shutdown = smb138x_shutdown,
};
module_platform_driver(smb138x_driver);
diff --git a/drivers/pwm/pwm-qpnp.c b/drivers/pwm/pwm-qpnp.c
index e46b1d583f40..2531b74b4588 100644
--- a/drivers/pwm/pwm-qpnp.c
+++ b/drivers/pwm/pwm-qpnp.c
@@ -328,6 +328,7 @@ struct qpnp_pwm_chip {
bool enabled;
struct _qpnp_pwm_config pwm_config;
struct qpnp_lpg_config lpg_config;
+ enum pm_pwm_mode pwm_mode;
spinlock_t lpg_lock;
enum qpnp_lpg_revision revision;
u8 sub_type;
@@ -1314,12 +1315,10 @@ after_table_write:
return rc;
}
+/* lpg_lock should be held while calling _pwm_enable() */
static int _pwm_enable(struct qpnp_pwm_chip *chip)
{
int rc = 0;
- unsigned long flags;
-
- spin_lock_irqsave(&chip->lpg_lock, flags);
if (QPNP_IS_PWM_CONFIG_SELECTED(
chip->qpnp_lpg_registers[QPNP_ENABLE_CONTROL]) ||
@@ -1332,8 +1331,21 @@ static int _pwm_enable(struct qpnp_pwm_chip *chip)
if (!rc)
chip->enabled = true;
- spin_unlock_irqrestore(&chip->lpg_lock, flags);
+ return rc;
+}
+
+/* lpg_lock should be held while calling _pwm_change_mode() */
+static int _pwm_change_mode(struct qpnp_pwm_chip *chip, enum pm_pwm_mode mode)
+{
+ int rc;
+ if (mode == PM_PWM_MODE_LPG)
+ rc = qpnp_configure_lpg_control(chip);
+ else
+ rc = qpnp_configure_pwm_control(chip);
+
+ if (rc)
+ pr_err("Failed to change the mode\n");
return rc;
}
@@ -1410,11 +1422,15 @@ static int qpnp_pwm_enable(struct pwm_chip *pwm_chip,
{
int rc;
struct qpnp_pwm_chip *chip = qpnp_pwm_from_pwm_chip(pwm_chip);
+ unsigned long flags;
+ spin_lock_irqsave(&chip->lpg_lock, flags);
rc = _pwm_enable(chip);
if (rc)
pr_err("Failed to enable PWM channel: %d\n", chip->channel_id);
+ spin_unlock_irqrestore(&chip->lpg_lock, flags);
+
return rc;
}
@@ -1452,20 +1468,6 @@ static void qpnp_pwm_disable(struct pwm_chip *pwm_chip,
chip->channel_id);
}
-static int _pwm_change_mode(struct qpnp_pwm_chip *chip, enum pm_pwm_mode mode)
-{
- int rc;
-
- if (mode)
- rc = qpnp_configure_lpg_control(chip);
- else
- rc = qpnp_configure_pwm_control(chip);
-
- if (rc)
- pr_err("Failed to change the mode\n");
- return rc;
-}
-
/**
* pwm_change_mode - Change the PWM mode configuration
* @pwm: the PWM device
@@ -1490,7 +1492,22 @@ int pwm_change_mode(struct pwm_device *pwm, enum pm_pwm_mode mode)
chip = qpnp_pwm_from_pwm_dev(pwm);
spin_lock_irqsave(&chip->lpg_lock, flags);
- rc = _pwm_change_mode(chip, mode);
+ if (chip->pwm_mode != mode) {
+ rc = _pwm_change_mode(chip, mode);
+ if (rc) {
+ pr_err("Failed to change mode: %d, rc=%d\n", mode, rc);
+ goto unlock;
+ }
+ chip->pwm_mode = mode;
+ if (chip->enabled) {
+ rc = _pwm_enable(chip);
+ if (rc) {
+ pr_err("Failed to enable PWM, rc=%d\n", rc);
+ goto unlock;
+ }
+ }
+ }
+unlock:
spin_unlock_irqrestore(&chip->lpg_lock, flags);
return rc;
@@ -1894,7 +1911,7 @@ out:
static int qpnp_parse_dt_config(struct platform_device *pdev,
struct qpnp_pwm_chip *chip)
{
- int rc, enable, lut_entry_size, list_size, i;
+ int rc, mode, lut_entry_size, list_size, i;
const char *label;
const __be32 *prop;
u32 size;
@@ -2078,18 +2095,20 @@ static int qpnp_parse_dt_config(struct platform_device *pdev,
}
}
- rc = of_property_read_u32(of_node, "qcom,mode-select", &enable);
+ rc = of_property_read_u32(of_node, "qcom,mode-select", &mode);
if (rc)
goto read_opt_props;
- if ((enable == PM_PWM_MODE_PWM && found_pwm_subnode == 0) ||
- (enable == PM_PWM_MODE_LPG && found_lpg_subnode == 0)) {
+ if (mode > PM_PWM_MODE_LPG ||
+ (mode == PM_PWM_MODE_PWM && found_pwm_subnode == 0) ||
+ (mode == PM_PWM_MODE_LPG && found_lpg_subnode == 0)) {
dev_err(&pdev->dev, "%s: Invalid mode select\n", __func__);
rc = -EINVAL;
goto out;
}
- _pwm_change_mode(chip, enable);
+ chip->pwm_mode = mode;
+ _pwm_change_mode(chip, mode);
_pwm_enable(chip);
read_opt_props:
diff --git a/drivers/regulator/qpnp-lcdb-regulator.c b/drivers/regulator/qpnp-lcdb-regulator.c
index 724e8a4c00da..27f2d9851c2a 100644
--- a/drivers/regulator/qpnp-lcdb-regulator.c
+++ b/drivers/regulator/qpnp-lcdb-regulator.c
@@ -147,6 +147,8 @@
#define MIN_SOFT_START_US 0
#define MAX_SOFT_START_US 2000
+#define BST_HEADROOM_DEFAULT_MV 200
+
struct ldo_regulator {
struct regulator_desc rdesc;
struct regulator_dev *rdev;
@@ -187,6 +189,7 @@ struct bst_params {
int soft_start_us;
int vreg_ok_dbc_us;
int voltage_mv;
+ u16 headroom_mv;
};
struct qpnp_lcdb {
@@ -853,28 +856,40 @@ irq_handled:
#define VOLTAGE_STEP_50_MV 50
#define VOLTAGE_STEP_50MV_OFFSET 0xA
static int qpnp_lcdb_set_bst_voltage(struct qpnp_lcdb *lcdb,
- int voltage_mv)
+ int voltage_mv, u8 type)
{
int rc = 0;
u8 val = 0;
+ int bst_voltage_mv;
+ struct ldo_regulator *ldo = &lcdb->ldo;
+ struct ncp_regulator *ncp = &lcdb->ncp;
+ struct bst_params *bst = &lcdb->bst;
+
+ /* Vout_Boost = headroom_mv + max( Vout_LDO, abs (Vout_NCP)) */
+ bst_voltage_mv = max(voltage_mv, max(ldo->voltage_mv, ncp->voltage_mv));
+ bst_voltage_mv += bst->headroom_mv;
+
+ if (bst_voltage_mv < MIN_BST_VOLTAGE_MV)
+ bst_voltage_mv = MIN_BST_VOLTAGE_MV;
+ else if (bst_voltage_mv > MAX_BST_VOLTAGE_MV)
+ bst_voltage_mv = MAX_BST_VOLTAGE_MV;
+
+ if (bst_voltage_mv != bst->voltage_mv) {
+ val = DIV_ROUND_UP(bst_voltage_mv - MIN_BST_VOLTAGE_MV,
+ VOLTAGE_STEP_50_MV);
- if (voltage_mv < MIN_BST_VOLTAGE_MV)
- voltage_mv = MIN_BST_VOLTAGE_MV;
- else if (voltage_mv > MAX_BST_VOLTAGE_MV)
- voltage_mv = MAX_BST_VOLTAGE_MV;
-
- val = DIV_ROUND_UP(voltage_mv - MIN_BST_VOLTAGE_MV,
- VOLTAGE_STEP_50_MV);
-
- rc = qpnp_lcdb_masked_write(lcdb, lcdb->base +
- LCDB_BST_OUTPUT_VOLTAGE_REG,
- SET_OUTPUT_VOLTAGE_MASK, val);
- if (rc < 0)
- pr_err("Failed to set boost voltage %d mv rc=%d\n",
- voltage_mv, rc);
- else
- pr_debug("Boost voltage set = %d mv (0x%02x = 0x%02x)\n",
- voltage_mv, LCDB_BST_OUTPUT_VOLTAGE_REG, val);
+ rc = qpnp_lcdb_masked_write(lcdb, lcdb->base +
+ LCDB_BST_OUTPUT_VOLTAGE_REG,
+ SET_OUTPUT_VOLTAGE_MASK, val);
+ if (rc < 0) {
+ pr_err("Failed to set boost voltage %d mv rc=%d\n",
+ bst_voltage_mv, rc);
+ } else {
+ pr_debug("Boost voltage set = %d mv (0x%02x = 0x%02x)\n",
+ bst_voltage_mv, LCDB_BST_OUTPUT_VOLTAGE_REG, val);
+ bst->voltage_mv = bst_voltage_mv;
+ }
+ }
return rc;
}
@@ -905,25 +920,16 @@ static int qpnp_lcdb_set_voltage(struct qpnp_lcdb *lcdb,
u16 offset = LCDB_LDO_OUTPUT_VOLTAGE_REG;
u8 val = 0;
- if (type == BST)
- return qpnp_lcdb_set_bst_voltage(lcdb, voltage_mv);
-
- if (type == NCP)
- offset = LCDB_NCP_OUTPUT_VOLTAGE_REG;
-
if (!is_between(voltage_mv, MIN_VOLTAGE_MV, MAX_VOLTAGE_MV)) {
pr_err("Invalid voltage %dmv (min=%d max=%d)\n",
voltage_mv, MIN_VOLTAGE_MV, MAX_VOLTAGE_MV);
return -EINVAL;
}
- /* Change the BST voltage to LDO + 100mV */
- if (type == LDO) {
- rc = qpnp_lcdb_set_bst_voltage(lcdb, voltage_mv + 100);
- if (rc < 0) {
- pr_err("Failed to set boost voltage rc=%d\n", rc);
- return rc;
- }
+ rc = qpnp_lcdb_set_bst_voltage(lcdb, voltage_mv, type);
+ if (rc < 0) {
+ pr_err("Failed to set boost voltage rc=%d\n", rc);
+ return rc;
}
/* Below logic is only valid for LDO and NCP type */
@@ -936,6 +942,9 @@ static int qpnp_lcdb_set_voltage(struct qpnp_lcdb *lcdb,
val += VOLTAGE_STEP_50MV_OFFSET;
}
+ if (type == NCP)
+ offset = LCDB_NCP_OUTPUT_VOLTAGE_REG;
+
rc = qpnp_lcdb_masked_write(lcdb, lcdb->base + offset,
SET_OUTPUT_VOLTAGE_MASK, val);
if (rc < 0)
@@ -1058,6 +1067,8 @@ static int qpnp_lcdb_ldo_regulator_set_voltage(struct regulator_dev *rdev,
rc = qpnp_lcdb_set_voltage(lcdb, min_uV / 1000, LDO);
if (rc < 0)
pr_err("Failed to set LDO voltage rc=%c\n", rc);
+ else
+ lcdb->ldo.voltage_mv = min_uV / 1000;
return rc;
}
@@ -1129,6 +1140,8 @@ static int qpnp_lcdb_ncp_regulator_set_voltage(struct regulator_dev *rdev,
rc = qpnp_lcdb_set_voltage(lcdb, min_uV / 1000, NCP);
if (rc < 0)
pr_err("Failed to set LDO voltage rc=%c\n", rc);
+ else
+ lcdb->ncp.voltage_mv = min_uV / 1000;
return rc;
}
@@ -1389,6 +1402,12 @@ static int qpnp_lcdb_bst_dt_init(struct qpnp_lcdb *lcdb)
return -EINVAL;
}
+ /* Boost head room configuration */
+ of_property_read_u16(node, "qcom,bst-headroom-mv",
+ &lcdb->bst.headroom_mv);
+ if (lcdb->bst.headroom_mv < BST_HEADROOM_DEFAULT_MV)
+ lcdb->bst.headroom_mv = BST_HEADROOM_DEFAULT_MV;
+
return 0;
}
@@ -1695,6 +1714,9 @@ static int qpnp_lcdb_init_bst(struct qpnp_lcdb *lcdb)
}
lcdb->bst.soft_start_us = (val & SOFT_START_MASK) * 200 + 200;
+ if (!lcdb->bst.headroom_mv)
+ lcdb->bst.headroom_mv = BST_HEADROOM_DEFAULT_MV;
+
return 0;
}
diff --git a/drivers/scsi/fnic/fnic.h b/drivers/scsi/fnic/fnic.h
index ce129e595b55..5c935847599c 100644
--- a/drivers/scsi/fnic/fnic.h
+++ b/drivers/scsi/fnic/fnic.h
@@ -248,6 +248,7 @@ struct fnic {
struct completion *remove_wait; /* device remove thread blocks */
atomic_t in_flight; /* io counter */
+ bool internal_reset_inprogress;
u32 _reserved; /* fill hole */
unsigned long state_flags; /* protected by host lock */
enum fnic_state state;
diff --git a/drivers/scsi/fnic/fnic_scsi.c b/drivers/scsi/fnic/fnic_scsi.c
index 266b909fe854..82e4bc8c11c5 100644
--- a/drivers/scsi/fnic/fnic_scsi.c
+++ b/drivers/scsi/fnic/fnic_scsi.c
@@ -2533,6 +2533,19 @@ int fnic_host_reset(struct scsi_cmnd *sc)
unsigned long wait_host_tmo;
struct Scsi_Host *shost = sc->device->host;
struct fc_lport *lp = shost_priv(shost);
+ struct fnic *fnic = lport_priv(lp);
+ unsigned long flags;
+
+ spin_lock_irqsave(&fnic->fnic_lock, flags);
+ if (fnic->internal_reset_inprogress == 0) {
+ fnic->internal_reset_inprogress = 1;
+ } else {
+ spin_unlock_irqrestore(&fnic->fnic_lock, flags);
+ FNIC_SCSI_DBG(KERN_DEBUG, fnic->lport->host,
+ "host reset in progress skipping another host reset\n");
+ return SUCCESS;
+ }
+ spin_unlock_irqrestore(&fnic->fnic_lock, flags);
/*
* If fnic_reset is successful, wait for fabric login to complete
@@ -2553,6 +2566,9 @@ int fnic_host_reset(struct scsi_cmnd *sc)
}
}
+ spin_lock_irqsave(&fnic->fnic_lock, flags);
+ fnic->internal_reset_inprogress = 0;
+ spin_unlock_irqrestore(&fnic->fnic_lock, flags);
return ret;
}
diff --git a/drivers/scsi/mpt3sas/mpt3sas_base.c b/drivers/scsi/mpt3sas/mpt3sas_base.c
index 5b2c37f1e908..9b5367294116 100644
--- a/drivers/scsi/mpt3sas/mpt3sas_base.c
+++ b/drivers/scsi/mpt3sas/mpt3sas_base.c
@@ -4981,15 +4981,14 @@ _base_make_ioc_ready(struct MPT3SAS_ADAPTER *ioc, int sleep_flag,
static int
_base_make_ioc_operational(struct MPT3SAS_ADAPTER *ioc, int sleep_flag)
{
- int r, i;
+ int r, i, index;
unsigned long flags;
u32 reply_address;
u16 smid;
struct _tr_list *delayed_tr, *delayed_tr_next;
u8 hide_flag;
struct adapter_reply_queue *reply_q;
- long reply_post_free;
- u32 reply_post_free_sz, index = 0;
+ Mpi2ReplyDescriptorsUnion_t *reply_post_free_contig;
dinitprintk(ioc, pr_info(MPT3SAS_FMT "%s\n", ioc->name,
__func__));
@@ -5061,27 +5060,27 @@ _base_make_ioc_operational(struct MPT3SAS_ADAPTER *ioc, int sleep_flag)
_base_assign_reply_queues(ioc);
/* initialize Reply Post Free Queue */
- reply_post_free_sz = ioc->reply_post_queue_depth *
- sizeof(Mpi2DefaultReplyDescriptor_t);
- reply_post_free = (long)ioc->reply_post[index].reply_post_free;
+ index = 0;
+ reply_post_free_contig = ioc->reply_post[0].reply_post_free;
list_for_each_entry(reply_q, &ioc->reply_queue_list, list) {
+ /*
+ * If RDPQ is enabled, switch to the next allocation.
+ * Otherwise advance within the contiguous region.
+ */
+ if (ioc->rdpq_array_enable) {
+ reply_q->reply_post_free =
+ ioc->reply_post[index++].reply_post_free;
+ } else {
+ reply_q->reply_post_free = reply_post_free_contig;
+ reply_post_free_contig += ioc->reply_post_queue_depth;
+ }
+
reply_q->reply_post_host_index = 0;
- reply_q->reply_post_free = (Mpi2ReplyDescriptorsUnion_t *)
- reply_post_free;
for (i = 0; i < ioc->reply_post_queue_depth; i++)
reply_q->reply_post_free[i].Words =
cpu_to_le64(ULLONG_MAX);
if (!_base_is_controller_msix_enabled(ioc))
goto skip_init_reply_post_free_queue;
- /*
- * If RDPQ is enabled, switch to the next allocation.
- * Otherwise advance within the contiguous region.
- */
- if (ioc->rdpq_array_enable)
- reply_post_free = (long)
- ioc->reply_post[++index].reply_post_free;
- else
- reply_post_free += reply_post_free_sz;
}
skip_init_reply_post_free_queue:
diff --git a/drivers/scsi/snic/snic_main.c b/drivers/scsi/snic/snic_main.c
index 2b3c25371d76..8175f997e82c 100644
--- a/drivers/scsi/snic/snic_main.c
+++ b/drivers/scsi/snic/snic_main.c
@@ -584,6 +584,7 @@ snic_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
if (!pool) {
SNIC_HOST_ERR(shost, "dflt sgl pool creation failed\n");
+ ret = -ENOMEM;
goto err_free_res;
}
@@ -594,6 +595,7 @@ snic_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
if (!pool) {
SNIC_HOST_ERR(shost, "max sgl pool creation failed\n");
+ ret = -ENOMEM;
goto err_free_dflt_sgl_pool;
}
@@ -604,6 +606,7 @@ snic_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
if (!pool) {
SNIC_HOST_ERR(shost, "snic tmreq info pool creation failed.\n");
+ ret = -ENOMEM;
goto err_free_max_sgl_pool;
}
diff --git a/drivers/soc/qcom/glink_smem_native_xprt.c b/drivers/soc/qcom/glink_smem_native_xprt.c
index 37193bbb23b7..042108d4035b 100644
--- a/drivers/soc/qcom/glink_smem_native_xprt.c
+++ b/drivers/soc/qcom/glink_smem_native_xprt.c
@@ -2242,6 +2242,7 @@ static int parse_qos_dt_params(struct device_node *node,
einfo->ramp_time_us[i] = arr32[i];
rc = 0;
+ kfree(arr32);
return rc;
invalid_key:
diff --git a/drivers/soc/qcom/icnss.c b/drivers/soc/qcom/icnss.c
index 39e76072f596..7f2e4cc42e51 100644
--- a/drivers/soc/qcom/icnss.c
+++ b/drivers/soc/qcom/icnss.c
@@ -152,6 +152,8 @@ bool ignore_qmi_timeout;
#define ICNSS_QMI_ASSERT() do { } while (0)
#endif
+#define QMI_ERR_PLAT_CCPM_CLK_INIT_FAILED 0x77
+
enum icnss_debug_quirks {
HW_ALWAYS_ON,
HW_DEBUG_ENABLE,
@@ -733,7 +735,7 @@ static int wlfw_vbatt_send_sync_msg(struct icnss_priv *priv,
if (resp.resp.result != QMI_RESULT_SUCCESS_V01) {
icnss_pr_err("QMI vbatt request rejected, result:%d error:%d\n",
resp.resp.result, resp.resp.error);
- ret = resp.resp.result;
+ ret = -resp.resp.result;
goto out;
}
priv->stats.vbatt_resp++;
@@ -1217,7 +1219,7 @@ static int wlfw_msa_mem_info_send_sync_msg(void)
if (resp.resp.result != QMI_RESULT_SUCCESS_V01) {
icnss_pr_err("QMI MSA Mem info request rejected, result:%d error:%d\n",
resp.resp.result, resp.resp.error);
- ret = resp.resp.result;
+ ret = -resp.resp.result;
goto out;
}
@@ -1289,7 +1291,7 @@ static int wlfw_msa_ready_send_sync_msg(void)
if (resp.resp.result != QMI_RESULT_SUCCESS_V01) {
icnss_pr_err("QMI MSA ready request rejected: result:%d error:%d\n",
resp.resp.result, resp.resp.error);
- ret = resp.resp.result;
+ ret = -resp.resp.result;
goto out;
}
penv->stats.msa_ready_resp++;
@@ -1352,7 +1354,7 @@ static int wlfw_ind_register_send_sync_msg(void)
if (resp.resp.result != QMI_RESULT_SUCCESS_V01) {
icnss_pr_err("QMI indication register request rejected, resut:%d error:%d\n",
resp.resp.result, resp.resp.error);
- ret = resp.resp.result;
+ ret = -resp.resp.result;
goto out;
}
penv->stats.ind_register_resp++;
@@ -1399,7 +1401,9 @@ static int wlfw_cap_send_sync_msg(void)
if (resp.resp.result != QMI_RESULT_SUCCESS_V01) {
icnss_pr_err("QMI capability request rejected, result:%d error:%d\n",
resp.resp.result, resp.resp.error);
- ret = resp.resp.result;
+ ret = -resp.resp.result;
+ if (resp.resp.error == QMI_ERR_PLAT_CCPM_CLK_INIT_FAILED)
+ icnss_pr_err("RF card Not present");
goto out;
}
@@ -1482,7 +1486,7 @@ static int wlfw_wlan_mode_send_sync_msg(enum wlfw_driver_mode_enum_v01 mode)
if (resp.resp.result != QMI_RESULT_SUCCESS_V01) {
icnss_pr_err("QMI mode request rejected, mode:%d result:%d error:%d\n",
mode, resp.resp.result, resp.resp.error);
- ret = resp.resp.result;
+ ret = -resp.resp.result;
goto out;
}
penv->stats.mode_resp++;
@@ -1532,7 +1536,7 @@ static int wlfw_wlan_cfg_send_sync_msg(struct wlfw_wlan_cfg_req_msg_v01 *data)
if (resp.resp.result != QMI_RESULT_SUCCESS_V01) {
icnss_pr_err("QMI config request rejected, result:%d error:%d\n",
resp.resp.result, resp.resp.error);
- ret = resp.resp.result;
+ ret = -resp.resp.result;
goto out;
}
penv->stats.cfg_resp++;
@@ -1585,7 +1589,7 @@ static int wlfw_ini_send_sync_msg(uint8_t fw_log_mode)
if (resp.resp.result != QMI_RESULT_SUCCESS_V01) {
icnss_pr_err("QMI INI request rejected, fw_log_mode:%d result:%d error:%d\n",
fw_log_mode, resp.resp.result, resp.resp.error);
- ret = resp.resp.result;
+ ret = -resp.resp.result;
goto out;
}
penv->stats.ini_resp++;
@@ -1645,7 +1649,7 @@ static int wlfw_athdiag_read_send_sync_msg(struct icnss_priv *priv,
if (resp->resp.result != QMI_RESULT_SUCCESS_V01) {
icnss_pr_err("QMI athdiag read request rejected, result:%d error:%d\n",
resp->resp.result, resp->resp.error);
- ret = resp->resp.result;
+ ret = -resp->resp.result;
goto out;
}
@@ -1711,7 +1715,7 @@ static int wlfw_athdiag_write_send_sync_msg(struct icnss_priv *priv,
if (resp.resp.result != QMI_RESULT_SUCCESS_V01) {
icnss_pr_err("QMI athdiag write request rejected, result:%d error:%d\n",
resp.resp.result, resp.resp.error);
- ret = resp.resp.result;
+ ret = -resp.resp.result;
goto out;
}
out:
@@ -1806,7 +1810,7 @@ static int wlfw_rejuvenate_ack_send_sync_msg(struct icnss_priv *priv)
if (resp.resp.result != QMI_RESULT_SUCCESS_V01) {
icnss_pr_err("QMI rejuvenate ack request rejected, result:%d error %d\n",
resp.resp.result, resp.resp.error);
- ret = resp.resp.result;
+ ret = -resp.resp.result;
goto out;
}
priv->stats.rejuvenate_ack_resp++;
@@ -1867,7 +1871,7 @@ static int wlfw_dynamic_feature_mask_send_sync_msg(struct icnss_priv *priv,
if (resp.resp.result != QMI_RESULT_SUCCESS_V01) {
icnss_pr_err("QMI dynamic feature mask request rejected, result:%d error %d\n",
resp.resp.result, resp.resp.error);
- ret = resp.resp.result;
+ ret = -resp.resp.result;
goto out;
}
diff --git a/drivers/soc/qcom/qbt1000.c b/drivers/soc/qcom/qbt1000.c
index d14e82415c5a..7a62c2e36da8 100644
--- a/drivers/soc/qcom/qbt1000.c
+++ b/drivers/soc/qcom/qbt1000.c
@@ -12,6 +12,7 @@
#define pr_fmt(fmt) "qbt1000:%s: " fmt, __func__
+#include <linux/delay.h>
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/fs.h>
@@ -105,10 +106,14 @@ struct qbt1000_drvdata {
*/
struct fw_ipc_cmd {
uint32_t status;
+ uint32_t numMsgs;
+ uint8_t msg_data[FW_MAX_IPC_MSG_DATA_SIZE];
+};
+
+struct fw_ipc_header {
uint32_t msg_type;
uint32_t msg_len;
uint32_t resp_needed;
- uint8_t msg_data[FW_MAX_IPC_MSG_DATA_SIZE];
};
/*
@@ -352,7 +357,14 @@ static int qbt1000_open(struct inode *inode, struct file *file)
*/
static int qbt1000_release(struct inode *inode, struct file *file)
{
- struct qbt1000_drvdata *drvdata = file->private_data;
+ struct qbt1000_drvdata *drvdata;
+
+ if (!file->private_data) {
+ pr_err("Null pointer passed in file->private_data");
+ return -EINVAL;
+ }
+
+ drvdata = file->private_data;
atomic_inc(&drvdata->available);
return 0;
@@ -374,6 +386,11 @@ static long qbt1000_ioctl(struct file *file, unsigned cmd, unsigned long arg)
void __user *priv_arg = (void __user *)arg;
struct qbt1000_drvdata *drvdata;
+ if (!file->private_data) {
+ pr_err("Null pointer passed in file->private_data");
+ return -EINVAL;
+ }
+
drvdata = file->private_data;
if (IS_ERR(priv_arg)) {
@@ -789,6 +806,8 @@ static int qbt1000_create_input_device(struct qbt1000_drvdata *drvdata)
BIT_MASK(KEY_HOMEPAGE);
drvdata->in_dev->keybit[BIT_WORD(KEY_CAMERA)] |=
BIT_MASK(KEY_CAMERA);
+ drvdata->in_dev->keybit[BIT_WORD(KEY_VOLUMEDOWN)] |=
+ BIT_MASK(KEY_VOLUMEDOWN);
drvdata->in_dev->keybit[BIT_WORD(KEY_POWER)] |=
BIT_MASK(KEY_POWER);
@@ -917,11 +936,14 @@ static irqreturn_t qbt1000_gpio_isr(int irq, void *dev_id)
*/
static irqreturn_t qbt1000_ipc_irq_handler(int irq, void *dev_id)
{
+ uint8_t *msg_buffer;
struct fw_ipc_cmd *rx_cmd;
- int i;
+ struct fw_ipc_header *header;
+ int i, j;
uint32_t rxipc = FP_APP_CMD_RX_IPC;
struct qbt1000_drvdata *drvdata = (struct qbt1000_drvdata *)dev_id;
int rc = 0;
+ uint32_t retry_count = 10;
pm_stay_awake(drvdata->dev);
@@ -933,18 +955,25 @@ static irqreturn_t qbt1000_ipc_irq_handler(int irq, void *dev_id)
goto end;
}
- pr_debug("firmware interrupt received (irq %d)\n", irq);
-
if (!drvdata->fp_app_handle)
goto end;
- /*
- * send the TZ command to fetch the message from firmware
- * TZ will process the message if it can
- */
- rc = send_tz_cmd(drvdata, drvdata->fp_app_handle, 0,
- &rxipc, sizeof(rxipc),
- (void *)&rx_cmd, sizeof(*rx_cmd));
+ while (retry_count > 0) {
+ /*
+ * send the TZ command to fetch the message from firmware
+ * TZ will process the message if it can
+ */
+ rc = send_tz_cmd(drvdata, drvdata->fp_app_handle, 0,
+ &rxipc, sizeof(rxipc),
+ (void *)&rx_cmd, sizeof(*rx_cmd));
+ if (rc < 0) {
+ msleep(50); /* sleep for 50ms before retry */
+ retry_count -= 1;
+ continue;
+ } else {
+ break;
+ }
+ }
if (rc < 0) {
pr_err("failure sending tz cmd %d\n", rxipc);
@@ -956,29 +985,35 @@ static irqreturn_t qbt1000_ipc_irq_handler(int irq, void *dev_id)
goto end;
}
- /*
- * given the IPC message type, search for a corresponding event for the
- * driver client. If found, add to the events FIFO
- */
- for (i = 0; i < ARRAY_SIZE(g_msg_to_event); i++) {
- if (g_msg_to_event[i].msg_type == rx_cmd->msg_type) {
- enum qbt1000_fw_event ev = g_msg_to_event[i].fw_event;
- struct fw_event_desc fw_ev_desc;
-
- mutex_lock(&drvdata->fw_events_mutex);
- pr_debug("fw events: add %d\n", (int) ev);
- fw_ev_desc.ev = ev;
-
- if (!kfifo_put(&drvdata->fw_events, fw_ev_desc))
- pr_err("fw events: fifo full, drop event %d\n",
- (int) ev);
-
- mutex_unlock(&drvdata->fw_events_mutex);
- wake_up_interruptible(&drvdata->read_wait_queue);
- break;
+ msg_buffer = rx_cmd->msg_data;
+
+ for (j = 0; j < rx_cmd->numMsgs; j++) {
+ header = (struct fw_ipc_header *) msg_buffer;
+ /*
+ * given the IPC message type, search for a corresponding event
+ * for the driver client. If found, add to the events FIFO
+ */
+ for (i = 0; i < ARRAY_SIZE(g_msg_to_event); i++) {
+ if (g_msg_to_event[i].msg_type == header->msg_type) {
+ enum qbt1000_fw_event ev =
+ g_msg_to_event[i].fw_event;
+ struct fw_event_desc fw_ev_desc;
+
+ mutex_lock(&drvdata->fw_events_mutex);
+ pr_debug("fw events: add %d\n", (int) ev);
+ fw_ev_desc.ev = ev;
+
+ if (!kfifo_put(&drvdata->fw_events, fw_ev_desc))
+ pr_err("fw events: fifo full, drop event %d\n",
+ (int) ev);
+
+ mutex_unlock(&drvdata->fw_events_mutex);
+ break;
+ }
}
+ msg_buffer += sizeof(*header) + header->msg_len;
}
-
+ wake_up_interruptible(&drvdata->read_wait_queue);
end:
mutex_unlock(&drvdata->mutex);
pm_relax(drvdata->dev);
diff --git a/drivers/soc/qcom/scm_qcpe.c b/drivers/soc/qcom/scm_qcpe.c
index 0263350ae931..1e369c73e34b 100644
--- a/drivers/soc/qcom/scm_qcpe.c
+++ b/drivers/soc/qcom/scm_qcpe.c
@@ -27,7 +27,7 @@
#define CREATE_TRACE_POINTS
#include <trace/events/scm.h>
-#include <uapi/linux/habmm.h>
+#include <linux/habmm.h>
#define SCM_ENOMEM (-5)
#define SCM_EOPNOTSUPP (-4)
@@ -218,7 +218,7 @@ static int scm_call_qcpe(u32 fn_id, struct scm_desc *desc)
if (!opened) {
ret = habmm_socket_open(&handle, MM_QCPE_VM1, 0, 0);
- if (ret != HAB_OK) {
+ if (ret) {
pr_err("scm_call_qcpe: habmm_socket_open failed with ret = %d",
ret);
return ret;
@@ -235,14 +235,14 @@ static int scm_call_qcpe(u32 fn_id, struct scm_desc *desc)
smc_params.sid = 0;
ret = habmm_socket_send(handle, &smc_params, sizeof(smc_params), 0);
- if (ret != HAB_OK)
+ if (ret)
return ret;
size_bytes = sizeof(smc_params);
memset(&smc_params, 0x0, sizeof(smc_params));
ret = habmm_socket_recv(handle, &smc_params, &size_bytes, 0, 0);
- if (ret != HAB_OK)
+ if (ret)
return ret;
if (size_bytes != sizeof(smc_params)) {
diff --git a/drivers/spi/spi-dw.c b/drivers/spi/spi-dw.c
index 882cd6618cd5..87a0e47eeae6 100644
--- a/drivers/spi/spi-dw.c
+++ b/drivers/spi/spi-dw.c
@@ -107,7 +107,10 @@ static const struct file_operations dw_spi_regs_ops = {
static int dw_spi_debugfs_init(struct dw_spi *dws)
{
- dws->debugfs = debugfs_create_dir("dw_spi", NULL);
+ char name[128];
+
+ snprintf(name, 128, "dw_spi-%s", dev_name(&dws->master->dev));
+ dws->debugfs = debugfs_create_dir(name, NULL);
if (!dws->debugfs)
return -ENOMEM;
diff --git a/drivers/spmi/spmi.c b/drivers/spmi/spmi.c
index b43e5656598a..a62ae9061f27 100644
--- a/drivers/spmi/spmi.c
+++ b/drivers/spmi/spmi.c
@@ -364,11 +364,23 @@ static int spmi_drv_remove(struct device *dev)
return 0;
}
+static int spmi_drv_uevent(struct device *dev, struct kobj_uevent_env *env)
+{
+ int ret;
+
+ ret = of_device_uevent_modalias(dev, env);
+ if (ret != -ENODEV)
+ return ret;
+
+ return 0;
+}
+
static struct bus_type spmi_bus_type = {
.name = "spmi",
.match = spmi_device_match,
.probe = spmi_drv_probe,
.remove = spmi_drv_remove,
+ .uevent = spmi_drv_uevent,
};
/**
diff --git a/drivers/staging/android/ion/ion.c b/drivers/staging/android/ion/ion.c
index 07fc21797f0f..067cd58375a4 100644
--- a/drivers/staging/android/ion/ion.c
+++ b/drivers/staging/android/ion/ion.c
@@ -264,7 +264,7 @@ static struct ion_buffer *ion_buffer_create(struct ion_heap *heap,
mutex_lock(&dev->buffer_lock);
ion_buffer_add(dev, buffer);
mutex_unlock(&dev->buffer_lock);
- atomic_add(len, &heap->total_allocated);
+ atomic_long_add(len, &heap->total_allocated);
return buffer;
err:
@@ -282,7 +282,7 @@ void ion_buffer_destroy(struct ion_buffer *buffer)
buffer->heap->ops->unmap_kernel(buffer->heap, buffer);
buffer->heap->ops->unmap_dma(buffer->heap, buffer);
- atomic_sub(buffer->size, &buffer->heap->total_allocated);
+ atomic_long_sub(buffer->size, &buffer->heap->total_allocated);
buffer->heap->ops->free(buffer);
vfree(buffer->pages);
kfree(buffer);
@@ -320,7 +320,7 @@ static void ion_buffer_add_to_handle(struct ion_buffer *buffer)
{
mutex_lock(&buffer->lock);
if (buffer->handle_count == 0)
- atomic_add(buffer->size, &buffer->heap->total_handles);
+ atomic_long_add(buffer->size, &buffer->heap->total_handles);
buffer->handle_count++;
mutex_unlock(&buffer->lock);
@@ -346,7 +346,7 @@ static void ion_buffer_remove_from_handle(struct ion_buffer *buffer)
task = current->group_leader;
get_task_comm(buffer->task_comm, task);
buffer->pid = task_pid_nr(task);
- atomic_sub(buffer->size, &buffer->heap->total_handles);
+ atomic_long_sub(buffer->size, &buffer->heap->total_handles);
}
mutex_unlock(&buffer->lock);
}
@@ -1951,10 +1951,10 @@ void show_ion_usage(struct ion_device *dev)
"Total orphaned size");
pr_info("---------------------------------\n");
plist_for_each_entry(heap, &dev->heaps, node) {
- pr_info("%16.s 0x%16.x 0x%16.x\n",
- heap->name, atomic_read(&heap->total_allocated),
- atomic_read(&heap->total_allocated) -
- atomic_read(&heap->total_handles));
+ pr_info("%16.s 0x%16.lx 0x%16.lx\n",
+ heap->name, atomic_long_read(&heap->total_allocated),
+ atomic_long_read(&heap->total_allocated) -
+ atomic_long_read(&heap->total_handles));
if (heap->debug_show)
heap->debug_show(heap, NULL, 0);
diff --git a/drivers/staging/android/ion/ion_priv.h b/drivers/staging/android/ion/ion_priv.h
index b687675be02f..f2f2ca11c3fa 100644
--- a/drivers/staging/android/ion/ion_priv.h
+++ b/drivers/staging/android/ion/ion_priv.h
@@ -2,7 +2,7 @@
* drivers/staging/android/ion/ion_priv.h
*
* 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
@@ -200,8 +200,8 @@ struct ion_heap {
struct task_struct *task;
int (*debug_show)(struct ion_heap *heap, struct seq_file *, void *);
- atomic_t total_allocated;
- atomic_t total_handles;
+ atomic_long_t total_allocated;
+ atomic_long_t total_handles;
};
/**
diff --git a/drivers/staging/android/lowmemorykiller.c b/drivers/staging/android/lowmemorykiller.c
index 8deee007218b..9e12b2ce3272 100644
--- a/drivers/staging/android/lowmemorykiller.c
+++ b/drivers/staging/android/lowmemorykiller.c
@@ -537,7 +537,7 @@ static unsigned long lowmem_scan(struct shrinker *s, struct shrink_control *sc)
cache_limit = minfree * (long)(PAGE_SIZE / 1024);
free = other_free * (long)(PAGE_SIZE / 1024);
trace_lowmemory_kill(selected, cache_size, cache_limit, free);
- lowmem_print(1, "Killing '%s' (%d), adj %hd,\n" \
+ lowmem_print(1, "Killing '%s' (%d) (tgid %d), adj %hd,\n" \
" to free %ldkB on behalf of '%s' (%d) because\n" \
" cache %ldkB is below limit %ldkB for oom_score_adj %hd\n" \
" Free memory is %ldkB above reserved.\n" \
@@ -547,7 +547,7 @@ static unsigned long lowmem_scan(struct shrinker *s, struct shrink_control *sc)
" Total file cache is %ldkB\n" \
" Total zcache is %ldkB\n" \
" GFP mask is 0x%x\n",
- selected->comm, selected->pid,
+ selected->comm, selected->pid, selected->tgid,
selected_oom_score_adj,
selected_tasksize * (long)(PAGE_SIZE / 1024),
current->comm, current->pid,
diff --git a/drivers/staging/comedi/comedi_fops.c b/drivers/staging/comedi/comedi_fops.c
index 8fed55342b0f..b831f08e2769 100644
--- a/drivers/staging/comedi/comedi_fops.c
+++ b/drivers/staging/comedi/comedi_fops.c
@@ -2901,9 +2901,6 @@ static int __init comedi_init(void)
comedi_class->dev_groups = comedi_dev_groups;
- /* XXX requires /proc interface */
- comedi_proc_init();
-
/* create devices files for legacy/manual use */
for (i = 0; i < comedi_num_legacy_minors; i++) {
struct comedi_device *dev;
@@ -2921,6 +2918,9 @@ static int __init comedi_init(void)
mutex_unlock(&dev->mutex);
}
+ /* XXX requires /proc interface */
+ comedi_proc_init();
+
return 0;
}
module_init(comedi_init);
diff --git a/drivers/staging/rtl8188eu/os_dep/usb_intf.c b/drivers/staging/rtl8188eu/os_dep/usb_intf.c
index 82a7c27c517f..02c3feef4e36 100644
--- a/drivers/staging/rtl8188eu/os_dep/usb_intf.c
+++ b/drivers/staging/rtl8188eu/os_dep/usb_intf.c
@@ -47,6 +47,7 @@ static struct usb_device_id rtw_usb_id_tbl[] = {
{USB_DEVICE(0x2001, 0x330F)}, /* DLink DWA-125 REV D1 */
{USB_DEVICE(0x2001, 0x3310)}, /* Dlink DWA-123 REV D1 */
{USB_DEVICE(0x2001, 0x3311)}, /* DLink GO-USB-N150 REV B1 */
+ {USB_DEVICE(0x2357, 0x010c)}, /* TP-Link TL-WN722N v2 */
{USB_DEVICE(0x0df6, 0x0076)}, /* Sitecom N150 v2 */
{} /* Terminating entry */
};
diff --git a/drivers/target/iscsi/iscsi_target_configfs.c b/drivers/target/iscsi/iscsi_target_configfs.c
index dc1bd1f1bdfe..634ad3662ed6 100644
--- a/drivers/target/iscsi/iscsi_target_configfs.c
+++ b/drivers/target/iscsi/iscsi_target_configfs.c
@@ -868,6 +868,7 @@ DEF_TPG_ATTRIB(default_erl);
DEF_TPG_ATTRIB(t10_pi);
DEF_TPG_ATTRIB(fabric_prot_type);
DEF_TPG_ATTRIB(tpg_enabled_sendtargets);
+DEF_TPG_ATTRIB(login_keys_workaround);
static struct configfs_attribute *lio_target_tpg_attrib_attrs[] = {
&iscsi_tpg_attrib_attr_authentication,
@@ -883,6 +884,7 @@ static struct configfs_attribute *lio_target_tpg_attrib_attrs[] = {
&iscsi_tpg_attrib_attr_t10_pi,
&iscsi_tpg_attrib_attr_fabric_prot_type,
&iscsi_tpg_attrib_attr_tpg_enabled_sendtargets,
+ &iscsi_tpg_attrib_attr_login_keys_workaround,
NULL,
};
diff --git a/drivers/target/iscsi/iscsi_target_nego.c b/drivers/target/iscsi/iscsi_target_nego.c
index 9fc9117d0f22..549a2bbbf4df 100644
--- a/drivers/target/iscsi/iscsi_target_nego.c
+++ b/drivers/target/iscsi/iscsi_target_nego.c
@@ -818,7 +818,8 @@ static int iscsi_target_handle_csg_zero(
SENDER_TARGET,
login->rsp_buf,
&login->rsp_length,
- conn->param_list);
+ conn->param_list,
+ conn->tpg->tpg_attrib.login_keys_workaround);
if (ret < 0)
return -1;
@@ -888,7 +889,8 @@ static int iscsi_target_handle_csg_one(struct iscsi_conn *conn, struct iscsi_log
SENDER_TARGET,
login->rsp_buf,
&login->rsp_length,
- conn->param_list);
+ conn->param_list,
+ conn->tpg->tpg_attrib.login_keys_workaround);
if (ret < 0) {
iscsit_tx_login_rsp(conn, ISCSI_STATUS_CLS_INITIATOR_ERR,
ISCSI_LOGIN_STATUS_INIT_ERR);
diff --git a/drivers/target/iscsi/iscsi_target_parameters.c b/drivers/target/iscsi/iscsi_target_parameters.c
index 6d1b0acbc5b3..76bde76edad1 100644
--- a/drivers/target/iscsi/iscsi_target_parameters.c
+++ b/drivers/target/iscsi/iscsi_target_parameters.c
@@ -764,7 +764,8 @@ static int iscsi_check_for_auth_key(char *key)
return 0;
}
-static void iscsi_check_proposer_for_optional_reply(struct iscsi_param *param)
+static void iscsi_check_proposer_for_optional_reply(struct iscsi_param *param,
+ bool keys_workaround)
{
if (IS_TYPE_BOOL_AND(param)) {
if (!strcmp(param->value, NO))
@@ -772,19 +773,31 @@ static void iscsi_check_proposer_for_optional_reply(struct iscsi_param *param)
} else if (IS_TYPE_BOOL_OR(param)) {
if (!strcmp(param->value, YES))
SET_PSTATE_REPLY_OPTIONAL(param);
- /*
- * Required for gPXE iSCSI boot client
- */
- if (!strcmp(param->name, IMMEDIATEDATA))
- SET_PSTATE_REPLY_OPTIONAL(param);
+
+ if (keys_workaround) {
+ /*
+ * Required for gPXE iSCSI boot client
+ */
+ if (!strcmp(param->name, IMMEDIATEDATA))
+ SET_PSTATE_REPLY_OPTIONAL(param);
+ }
} else if (IS_TYPE_NUMBER(param)) {
if (!strcmp(param->name, MAXRECVDATASEGMENTLENGTH))
SET_PSTATE_REPLY_OPTIONAL(param);
- /*
- * Required for gPXE iSCSI boot client
- */
- if (!strcmp(param->name, MAXCONNECTIONS))
- SET_PSTATE_REPLY_OPTIONAL(param);
+
+ if (keys_workaround) {
+ /*
+ * Required for Mellanox Flexboot PXE boot ROM
+ */
+ if (!strcmp(param->name, FIRSTBURSTLENGTH))
+ SET_PSTATE_REPLY_OPTIONAL(param);
+
+ /*
+ * Required for gPXE iSCSI boot client
+ */
+ if (!strcmp(param->name, MAXCONNECTIONS))
+ SET_PSTATE_REPLY_OPTIONAL(param);
+ }
} else if (IS_PHASE_DECLARATIVE(param))
SET_PSTATE_REPLY_OPTIONAL(param);
}
@@ -1421,7 +1434,8 @@ int iscsi_encode_text_output(
u8 sender,
char *textbuf,
u32 *length,
- struct iscsi_param_list *param_list)
+ struct iscsi_param_list *param_list,
+ bool keys_workaround)
{
char *output_buf = NULL;
struct iscsi_extra_response *er;
@@ -1457,7 +1471,8 @@ int iscsi_encode_text_output(
*length += 1;
output_buf = textbuf + *length;
SET_PSTATE_PROPOSER(param);
- iscsi_check_proposer_for_optional_reply(param);
+ iscsi_check_proposer_for_optional_reply(param,
+ keys_workaround);
pr_debug("Sending key: %s=%s\n",
param->name, param->value);
}
diff --git a/drivers/target/iscsi/iscsi_target_parameters.h b/drivers/target/iscsi/iscsi_target_parameters.h
index a0751e3f0813..17a58c2913f2 100644
--- a/drivers/target/iscsi/iscsi_target_parameters.h
+++ b/drivers/target/iscsi/iscsi_target_parameters.h
@@ -40,7 +40,7 @@ extern int iscsi_extract_key_value(char *, char **, char **);
extern int iscsi_update_param_value(struct iscsi_param *, char *);
extern int iscsi_decode_text_input(u8, u8, char *, u32, struct iscsi_conn *);
extern int iscsi_encode_text_output(u8, u8, char *, u32 *,
- struct iscsi_param_list *);
+ struct iscsi_param_list *, bool);
extern int iscsi_check_negotiated_keys(struct iscsi_param_list *);
extern void iscsi_set_connection_parameters(struct iscsi_conn_ops *,
struct iscsi_param_list *);
diff --git a/drivers/target/iscsi/iscsi_target_tpg.c b/drivers/target/iscsi/iscsi_target_tpg.c
index 205a509b0dfb..63e1dcc5914d 100644
--- a/drivers/target/iscsi/iscsi_target_tpg.c
+++ b/drivers/target/iscsi/iscsi_target_tpg.c
@@ -227,6 +227,7 @@ static void iscsit_set_default_tpg_attribs(struct iscsi_portal_group *tpg)
a->t10_pi = TA_DEFAULT_T10_PI;
a->fabric_prot_type = TA_DEFAULT_FABRIC_PROT_TYPE;
a->tpg_enabled_sendtargets = TA_DEFAULT_TPG_ENABLED_SENDTARGETS;
+ a->login_keys_workaround = TA_DEFAULT_LOGIN_KEYS_WORKAROUND;
}
int iscsit_tpg_add_portal_group(struct iscsi_tiqn *tiqn, struct iscsi_portal_group *tpg)
@@ -899,3 +900,21 @@ int iscsit_ta_tpg_enabled_sendtargets(
return 0;
}
+
+int iscsit_ta_login_keys_workaround(
+ struct iscsi_portal_group *tpg,
+ u32 flag)
+{
+ struct iscsi_tpg_attrib *a = &tpg->tpg_attrib;
+
+ if ((flag != 0) && (flag != 1)) {
+ pr_err("Illegal value %d\n", flag);
+ return -EINVAL;
+ }
+
+ a->login_keys_workaround = flag;
+ pr_debug("iSCSI_TPG[%hu] - TPG enabled bit for login keys workaround: %s ",
+ tpg->tpgt, (a->login_keys_workaround) ? "ON" : "OFF");
+
+ return 0;
+}
diff --git a/drivers/target/iscsi/iscsi_target_tpg.h b/drivers/target/iscsi/iscsi_target_tpg.h
index 2da211920c18..901a712180f0 100644
--- a/drivers/target/iscsi/iscsi_target_tpg.h
+++ b/drivers/target/iscsi/iscsi_target_tpg.h
@@ -39,5 +39,6 @@ extern int iscsit_ta_default_erl(struct iscsi_portal_group *, u32);
extern int iscsit_ta_t10_pi(struct iscsi_portal_group *, u32);
extern int iscsit_ta_fabric_prot_type(struct iscsi_portal_group *, u32);
extern int iscsit_ta_tpg_enabled_sendtargets(struct iscsi_portal_group *, u32);
+extern int iscsit_ta_login_keys_workaround(struct iscsi_portal_group *, u32);
#endif /* ISCSI_TARGET_TPG_H */
diff --git a/drivers/target/target_core_transport.c b/drivers/target/target_core_transport.c
index 37c77db6e737..f71bedea973a 100644
--- a/drivers/target/target_core_transport.c
+++ b/drivers/target/target_core_transport.c
@@ -728,6 +728,15 @@ void target_complete_cmd(struct se_cmd *cmd, u8 scsi_status)
if (cmd->transport_state & CMD_T_ABORTED ||
cmd->transport_state & CMD_T_STOP) {
spin_unlock_irqrestore(&cmd->t_state_lock, flags);
+ /*
+ * If COMPARE_AND_WRITE was stopped by __transport_wait_for_tasks(),
+ * release se_device->caw_sem obtained by sbc_compare_and_write()
+ * since target_complete_ok_work() or target_complete_failure_work()
+ * won't be called to invoke the normal CAW completion callbacks.
+ */
+ if (cmd->se_cmd_flags & SCF_COMPARE_AND_WRITE) {
+ up(&dev->caw_sem);
+ }
complete_all(&cmd->t_transport_stop_comp);
return;
} else if (!success) {
diff --git a/drivers/thermal/cpu_cooling.c b/drivers/thermal/cpu_cooling.c
index 65c7033e0df0..632fa8c1260b 100644
--- a/drivers/thermal/cpu_cooling.c
+++ b/drivers/thermal/cpu_cooling.c
@@ -192,8 +192,10 @@ unsigned long cpufreq_cooling_get_level(unsigned int cpu, unsigned int freq)
mutex_lock(&cooling_list_lock);
list_for_each_entry(cpufreq_dev, &cpufreq_dev_list, node) {
if (cpumask_test_cpu(cpu, &cpufreq_dev->allowed_cpus)) {
+ unsigned long level = get_level(cpufreq_dev, freq);
+
mutex_unlock(&cooling_list_lock);
- return get_level(cpufreq_dev, freq);
+ return level;
}
}
mutex_unlock(&cooling_list_lock);
diff --git a/drivers/usb/class/cdc-acm.c b/drivers/usb/class/cdc-acm.c
index 0b7194086c5a..df96f5f88c15 100644
--- a/drivers/usb/class/cdc-acm.c
+++ b/drivers/usb/class/cdc-acm.c
@@ -1759,6 +1759,9 @@ static const struct usb_device_id acm_ids[] = {
{ USB_DEVICE(0x1576, 0x03b1), /* Maretron USB100 */
.driver_info = NO_UNION_NORMAL, /* reports zero length descriptor */
},
+ { USB_DEVICE(0xfff0, 0x0100), /* DATECS FP-2000 */
+ .driver_info = NO_UNION_NORMAL, /* reports zero length descriptor */
+ },
{ USB_DEVICE(0x2912, 0x0001), /* ATOL FPrint */
.driver_info = CLEAR_HALT_CONDITIONS,
diff --git a/drivers/usb/dwc3/dwc3-msm.c b/drivers/usb/dwc3/dwc3-msm.c
index 70db070b05d8..c5fc77eae894 100644
--- a/drivers/usb/dwc3/dwc3-msm.c
+++ b/drivers/usb/dwc3/dwc3-msm.c
@@ -2898,7 +2898,7 @@ static int dwc3_msm_probe(struct platform_device *pdev)
ret = dwc3_msm_get_clk_gdsc(mdwc);
if (ret) {
dev_err(&pdev->dev, "error getting clock or gdsc.\n");
- return ret;
+ goto err;
}
mdwc->id_state = DWC3_ID_FLOAT;
@@ -2945,8 +2945,9 @@ static int dwc3_msm_probe(struct platform_device *pdev)
ret = devm_request_threaded_irq(&pdev->dev, mdwc->ss_phy_irq,
msm_dwc3_pwr_irq,
msm_dwc3_pwr_irq_thread,
- IRQF_TRIGGER_RISING | IRQF_EARLY_RESUME
- | IRQF_ONESHOT, "ss_phy_irq", mdwc);
+ IRQF_TRIGGER_HIGH | IRQ_TYPE_LEVEL_HIGH
+ | IRQF_EARLY_RESUME | IRQF_ONESHOT,
+ "ss_phy_irq", mdwc);
if (ret) {
dev_err(&pdev->dev, "irqreq ss_phy_irq failed: %d\n",
ret);
@@ -3206,19 +3207,14 @@ static int dwc3_msm_probe(struct platform_device *pdev)
return 0;
put_dwc3:
- platform_device_put(mdwc->dwc3);
if (mdwc->bus_perf_client)
msm_bus_scale_unregister_client(mdwc->bus_perf_client);
+ of_platform_depopulate(&pdev->dev);
err:
+ destroy_workqueue(mdwc->dwc3_wq);
return ret;
}
-static int dwc3_msm_remove_children(struct device *dev, void *data)
-{
- device_unregister(dev);
- return 0;
-}
-
static int dwc3_msm_remove(struct platform_device *pdev)
{
struct dwc3_msm *mdwc = platform_get_drvdata(pdev);
@@ -3255,8 +3251,7 @@ static int dwc3_msm_remove(struct platform_device *pdev)
if (mdwc->hs_phy)
mdwc->hs_phy->flags &= ~PHY_HOST_MODE;
- platform_device_put(mdwc->dwc3);
- device_for_each_child(&pdev->dev, NULL, dwc3_msm_remove_children);
+ of_platform_depopulate(&pdev->dev);
dbg_event(0xFF, "Remov put", 0);
pm_runtime_disable(mdwc->dev);
@@ -3439,13 +3434,16 @@ static int dwc3_otg_start_host(struct dwc3_msm *mdwc, int on)
dev_dbg(mdwc->dev, "%s: turn on host\n", __func__);
mdwc->hs_phy->flags |= PHY_HOST_MODE;
- if (dwc->maximum_speed == USB_SPEED_SUPER)
+ if (dwc->maximum_speed == USB_SPEED_SUPER) {
mdwc->ss_phy->flags |= PHY_HOST_MODE;
+ usb_phy_notify_connect(mdwc->ss_phy,
+ USB_SPEED_SUPER);
+ }
+ usb_phy_notify_connect(mdwc->hs_phy, USB_SPEED_HIGH);
pm_runtime_get_sync(mdwc->dev);
dbg_event(0xFF, "StrtHost gync",
atomic_read(&mdwc->dev->power.usage_count));
- usb_phy_notify_connect(mdwc->hs_phy, USB_SPEED_HIGH);
if (!IS_ERR(mdwc->vbus_reg))
ret = regulator_enable(mdwc->vbus_reg);
if (ret) {
@@ -3553,8 +3551,13 @@ static int dwc3_otg_start_host(struct dwc3_msm *mdwc, int on)
dbg_event(0xFF, "StopHost gsync",
atomic_read(&mdwc->dev->power.usage_count));
usb_phy_notify_disconnect(mdwc->hs_phy, USB_SPEED_HIGH);
+ if (mdwc->ss_phy->flags & PHY_HOST_MODE) {
+ usb_phy_notify_disconnect(mdwc->ss_phy,
+ USB_SPEED_SUPER);
+ mdwc->ss_phy->flags &= ~PHY_HOST_MODE;
+ }
+
mdwc->hs_phy->flags &= ~PHY_HOST_MODE;
- mdwc->ss_phy->flags &= ~PHY_HOST_MODE;
platform_device_del(dwc->xhci);
usb_unregister_notify(&mdwc->host_nb);
@@ -3702,7 +3705,7 @@ static int dwc3_msm_gadget_vbus_draw(struct dwc3_msm *mdwc, unsigned mA)
}
ret = power_supply_set_property(mdwc->usb_psy,
- POWER_SUPPLY_PROP_CURRENT_MAX, &pval);
+ POWER_SUPPLY_PROP_SDP_CURRENT_MAX, &pval);
if (ret) {
dev_dbg(mdwc->dev, "power supply error when setting property\n");
return ret;
diff --git a/drivers/usb/gadget/function/f_hid.c b/drivers/usb/gadget/function/f_hid.c
index 99285b416308..ee579ba2b59e 100644
--- a/drivers/usb/gadget/function/f_hid.c
+++ b/drivers/usb/gadget/function/f_hid.c
@@ -539,7 +539,7 @@ static int hidg_set_alt(struct usb_function *f, unsigned intf, unsigned alt)
}
status = usb_ep_enable(hidg->out_ep);
if (status < 0) {
- ERROR(cdev, "Enable IN endpoint FAILED!\n");
+ ERROR(cdev, "Enable OUT endpoint FAILED!\n");
goto fail;
}
hidg->out_ep->driver_data = hidg;
diff --git a/drivers/usb/host/xhci-hub.c b/drivers/usb/host/xhci-hub.c
index 9dbd7595a7a3..fae1222d4bc8 100644
--- a/drivers/usb/host/xhci-hub.c
+++ b/drivers/usb/host/xhci-hub.c
@@ -783,6 +783,9 @@ static u32 xhci_get_port_status(struct usb_hcd *hcd,
clear_bit(wIndex, &bus_state->resuming_ports);
set_bit(wIndex, &bus_state->rexit_ports);
+
+ xhci_test_and_clear_bit(xhci, port_array, wIndex,
+ PORT_PLC);
xhci_set_link_state(xhci, port_array, wIndex,
XDEV_U0);
diff --git a/drivers/usb/host/xhci-ring.c b/drivers/usb/host/xhci-ring.c
index 12e38cf022ff..5bfe47816ac3 100644
--- a/drivers/usb/host/xhci-ring.c
+++ b/drivers/usb/host/xhci-ring.c
@@ -856,13 +856,16 @@ static void xhci_kill_endpoint_urbs(struct xhci_hcd *xhci,
(ep->ep_state & EP_GETTING_NO_STREAMS)) {
int stream_id;
- for (stream_id = 0; stream_id < ep->stream_info->num_streams;
+ for (stream_id = 1; stream_id < ep->stream_info->num_streams;
stream_id++) {
+ ring = ep->stream_info->stream_rings[stream_id];
+ if (!ring)
+ continue;
+
xhci_dbg_trace(xhci, trace_xhci_dbg_cancel_urb,
"Killing URBs for slot ID %u, ep index %u, stream %u",
- slot_id, ep_index, stream_id + 1);
- xhci_kill_ring_urbs(xhci,
- ep->stream_info->stream_rings[stream_id]);
+ slot_id, ep_index, stream_id);
+ xhci_kill_ring_urbs(xhci, ring);
}
} else {
ring = ep->ring;
diff --git a/drivers/usb/pd/policy_engine.c b/drivers/usb/pd/policy_engine.c
index 0cbe95304417..f9f47da8a88b 100644
--- a/drivers/usb/pd/policy_engine.c
+++ b/drivers/usb/pd/policy_engine.c
@@ -481,21 +481,18 @@ static inline void pd_reset_protocol(struct usbpd *pd)
pd->send_dr_swap = false;
}
-static int pd_send_msg(struct usbpd *pd, u8 hdr_type, const u32 *data,
- size_t num_data, enum pd_msg_type type)
+static int pd_send_msg(struct usbpd *pd, u8 msg_type, const u32 *data,
+ size_t num_data, enum pd_sop_type sop)
{
int ret;
u16 hdr;
- hdr = PD_MSG_HDR(hdr_type, pd->current_dr, pd->current_pr,
+ hdr = PD_MSG_HDR(msg_type, pd->current_dr, pd->current_pr,
pd->tx_msgid, num_data, pd->spec_rev);
- ret = pd_phy_write(hdr, (u8 *)data, num_data * sizeof(u32), type, 15);
- /* TODO figure out timeout. based on tReceive=1.1ms x nRetryCount? */
- if (ret < 0)
+ ret = pd_phy_write(hdr, (u8 *)data, num_data * sizeof(u32), sop);
+ if (ret)
return ret;
- else if (ret != num_data * sizeof(u32))
- return -EIO;
pd->tx_msgid = (pd->tx_msgid + 1) & PD_MAX_MSG_ID;
return 0;
@@ -596,7 +593,7 @@ static void pd_send_hard_reset(struct usbpd *pd)
/* Force CC logic to source/sink to keep Rp/Rd unchanged */
set_power_role(pd, pd->current_pr);
pd->hard_reset_count++;
- pd_phy_signal(HARD_RESET_SIG, 5); /* tHardResetComplete */
+ pd_phy_signal(HARD_RESET_SIG);
pd->in_pr_swap = false;
power_supply_set_property(pd->usb_psy, POWER_SUPPLY_PROP_PR_SWAP, &val);
}
@@ -612,12 +609,12 @@ static void kick_sm(struct usbpd *pd, int ms)
queue_work(pd->wq, &pd->sm_work);
}
-static void phy_sig_received(struct usbpd *pd, enum pd_sig_type type)
+static void phy_sig_received(struct usbpd *pd, enum pd_sig_type sig)
{
union power_supply_propval val = {1};
- if (type != HARD_RESET_SIG) {
- usbpd_err(&pd->dev, "invalid signal (%d) received\n", type);
+ if (sig != HARD_RESET_SIG) {
+ usbpd_err(&pd->dev, "invalid signal (%d) received\n", sig);
return;
}
@@ -632,16 +629,16 @@ static void phy_sig_received(struct usbpd *pd, enum pd_sig_type type)
kick_sm(pd, 0);
}
-static void phy_msg_received(struct usbpd *pd, enum pd_msg_type type,
+static void phy_msg_received(struct usbpd *pd, enum pd_sop_type sop,
u8 *buf, size_t len)
{
struct rx_msg *rx_msg;
unsigned long flags;
u16 header;
- if (type != SOP_MSG) {
+ if (sop != SOP_MSG) {
usbpd_err(&pd->dev, "invalid msg type (%d) received; only SOP supported\n",
- type);
+ sop);
return;
}
@@ -964,7 +961,7 @@ static void usbpd_set_state(struct usbpd *pd, enum usbpd_state next_state)
pd->current_voltage = pd->requested_voltage = 5000000;
val.intval = pd->requested_voltage; /* set max range to 5V */
power_supply_set_property(pd->usb_psy,
- POWER_SUPPLY_PROP_VOLTAGE_MAX, &val);
+ POWER_SUPPLY_PROP_PD_VOLTAGE_MAX, &val);
if (!pd->vbus_present) {
pd->current_state = PE_SNK_DISCOVERY;
@@ -1617,7 +1614,6 @@ static void usbpd_sm(struct work_struct *w)
else if (pd->current_dr == DR_DFP)
stop_usb_host(pd);
- pd->current_pr = PR_NONE;
pd->current_dr = DR_NONE;
reset_vdm_state(pd);
@@ -1663,7 +1659,7 @@ static void usbpd_sm(struct work_struct *w)
pd->requested_voltage = 5000000;
val.intval = pd->requested_voltage;
power_supply_set_property(pd->usb_psy,
- POWER_SUPPLY_PROP_VOLTAGE_MIN, &val);
+ POWER_SUPPLY_PROP_PD_VOLTAGE_MIN, &val);
pd->in_pr_swap = false;
val.intval = 0;
@@ -1982,8 +1978,8 @@ static void usbpd_sm(struct work_struct *w)
val.intval = pd->requested_voltage;
power_supply_set_property(pd->usb_psy,
pd->requested_voltage >= pd->current_voltage ?
- POWER_SUPPLY_PROP_VOLTAGE_MAX :
- POWER_SUPPLY_PROP_VOLTAGE_MIN,
+ POWER_SUPPLY_PROP_PD_VOLTAGE_MAX :
+ POWER_SUPPLY_PROP_PD_VOLTAGE_MIN,
&val);
/*
@@ -2034,8 +2030,8 @@ static void usbpd_sm(struct work_struct *w)
val.intval = pd->requested_voltage;
power_supply_set_property(pd->usb_psy,
pd->requested_voltage >= pd->current_voltage ?
- POWER_SUPPLY_PROP_VOLTAGE_MIN :
- POWER_SUPPLY_PROP_VOLTAGE_MAX, &val);
+ POWER_SUPPLY_PROP_PD_VOLTAGE_MIN :
+ POWER_SUPPLY_PROP_PD_VOLTAGE_MAX, &val);
pd->current_voltage = pd->requested_voltage;
/* resume charging */
@@ -2217,7 +2213,7 @@ static void usbpd_sm(struct work_struct *w)
val.intval = pd->requested_voltage;
power_supply_set_property(pd->usb_psy,
- POWER_SUPPLY_PROP_VOLTAGE_MIN, &val);
+ POWER_SUPPLY_PROP_PD_VOLTAGE_MIN, &val);
pd_send_hard_reset(pd);
pd->in_explicit_contract = false;
@@ -2480,6 +2476,16 @@ static int psy_changed(struct notifier_block *nb, unsigned long evt, void *ptr)
if (pd->current_pr == PR_SINK)
return 0;
+ /*
+ * Unexpected if not in PR swap; need to force disconnect from
+ * source so we can turn off VBUS, Vconn, PD PHY etc.
+ */
+ if (pd->current_pr == PR_SRC) {
+ usbpd_info(&pd->dev, "Forcing disconnect from source mode\n");
+ pd->current_pr = PR_NONE;
+ break;
+ }
+
pd->current_pr = PR_SINK;
break;
diff --git a/drivers/usb/pd/qpnp-pdphy.c b/drivers/usb/pd/qpnp-pdphy.c
index e200c25bc23a..b454442e2471 100644
--- a/drivers/usb/pd/qpnp-pdphy.c
+++ b/drivers/usb/pd/qpnp-pdphy.c
@@ -80,6 +80,10 @@
#define VDD_PDPHY_VOL_MAX 3300000 /* uV */
#define VDD_PDPHY_HPM_LOAD 3000 /* uA */
+/* timers */
+#define RECEIVER_RESPONSE_TIME 15 /* tReceiverResponse */
+#define HARD_RESET_COMPLETE_TIME 5 /* tHardResetComplete */
+
struct usb_pdphy {
struct device *dev;
struct regmap *regmap;
@@ -96,8 +100,8 @@ struct usb_pdphy {
int msg_tx_discarded_irq;
int msg_rx_discarded_irq;
- void (*signal_cb)(struct usbpd *pd, enum pd_sig_type type);
- void (*msg_rx_cb)(struct usbpd *pd, enum pd_msg_type type,
+ void (*signal_cb)(struct usbpd *pd, enum pd_sig_type sig);
+ void (*msg_rx_cb)(struct usbpd *pd, enum pd_sop_type sop,
u8 *buf, size_t len);
void (*shutdown_cb)(struct usbpd *pd);
@@ -401,14 +405,13 @@ int pd_phy_open(struct pd_phy_params *params)
}
EXPORT_SYMBOL(pd_phy_open);
-int pd_phy_signal(enum pd_sig_type type, unsigned int timeout_ms)
+int pd_phy_signal(enum pd_sig_type sig)
{
u8 val;
int ret;
struct usb_pdphy *pdphy = __pdphy;
- dev_dbg(pdphy->dev, "%s: type %d timeout %u\n", __func__, type,
- timeout_ms);
+ dev_dbg(pdphy->dev, "%s: type %d\n", __func__, sig);
if (!pdphy) {
pr_err("%s: pdphy not found\n", __func__);
@@ -428,7 +431,7 @@ int pd_phy_signal(enum pd_sig_type type, unsigned int timeout_ms)
usleep_range(2, 3);
- val = (type == CABLE_RESET_SIG ? TX_CONTROL_FRAME_TYPE_CABLE_RESET : 0)
+ val = (sig == CABLE_RESET_SIG ? TX_CONTROL_FRAME_TYPE_CABLE_RESET : 0)
| TX_CONTROL_SEND_SIGNAL;
ret = pdphy_reg_write(pdphy, USB_PDPHY_TX_CONTROL, val);
@@ -436,7 +439,8 @@ int pd_phy_signal(enum pd_sig_type type, unsigned int timeout_ms)
return ret;
ret = wait_event_interruptible_timeout(pdphy->tx_waitq,
- pdphy->tx_status != -EINPROGRESS, msecs_to_jiffies(timeout_ms));
+ pdphy->tx_status != -EINPROGRESS,
+ msecs_to_jiffies(HARD_RESET_COMPLETE_TIME));
if (ret <= 0) {
dev_err(pdphy->dev, "%s: failed ret %d", __func__, ret);
return ret ? ret : -ETIMEDOUT;
@@ -447,7 +451,7 @@ int pd_phy_signal(enum pd_sig_type type, unsigned int timeout_ms)
if (pdphy->tx_status)
return pdphy->tx_status;
- if (type == HARD_RESET_SIG)
+ if (sig == HARD_RESET_SIG)
/* Frame filter is reconfigured in pd_phy_open() */
return pdphy_reg_write(pdphy, USB_PDPHY_FRAME_FILTER, 0);
@@ -455,16 +459,15 @@ int pd_phy_signal(enum pd_sig_type type, unsigned int timeout_ms)
}
EXPORT_SYMBOL(pd_phy_signal);
-int pd_phy_write(u16 hdr, const u8 *data, size_t data_len,
- enum pd_msg_type type, unsigned int timeout_ms)
+int pd_phy_write(u16 hdr, const u8 *data, size_t data_len, enum pd_sop_type sop)
{
u8 val;
int ret;
size_t total_len = data_len + USB_PDPHY_MSG_HDR_LEN;
struct usb_pdphy *pdphy = __pdphy;
- dev_dbg(pdphy->dev, "%s: hdr %x frame type %d timeout %u\n",
- __func__, hdr, type, timeout_ms);
+ dev_dbg(pdphy->dev, "%s: hdr %x frame sop_type %d\n",
+ __func__, hdr, sop);
if (data && data_len)
print_hex_dump_debug("tx data obj:", DUMP_PREFIX_NONE, 32, 4,
@@ -518,14 +521,15 @@ int pd_phy_write(u16 hdr, const u8 *data, size_t data_len,
usleep_range(2, 3);
- val = TX_CONTROL_RETRY_COUNT | (type << 2) | TX_CONTROL_SEND_MSG;
+ val = TX_CONTROL_RETRY_COUNT | (sop << 2) | TX_CONTROL_SEND_MSG;
ret = pdphy_reg_write(pdphy, USB_PDPHY_TX_CONTROL, val);
if (ret)
return ret;
ret = wait_event_interruptible_timeout(pdphy->tx_waitq,
- pdphy->tx_status != -EINPROGRESS, msecs_to_jiffies(timeout_ms));
+ pdphy->tx_status != -EINPROGRESS,
+ msecs_to_jiffies(RECEIVER_RESPONSE_TIME));
if (ret <= 0) {
dev_err(pdphy->dev, "%s: failed ret %d", __func__, ret);
return ret ? ret : -ETIMEDOUT;
@@ -534,7 +538,7 @@ int pd_phy_write(u16 hdr, const u8 *data, size_t data_len,
if (hdr && !pdphy->tx_status)
pdphy->tx_bytes += data_len + USB_PDPHY_MSG_HDR_LEN;
- return pdphy->tx_status ? pdphy->tx_status : data_len;
+ return pdphy->tx_status ? pdphy->tx_status : 0;
}
EXPORT_SYMBOL(pd_phy_write);
diff --git a/drivers/usb/pd/usbpd.h b/drivers/usb/pd/usbpd.h
index 108701739f89..9b6053e940e9 100644
--- a/drivers/usb/pd/usbpd.h
+++ b/drivers/usb/pd/usbpd.h
@@ -45,7 +45,7 @@ enum pd_sig_type {
CABLE_RESET_SIG,
};
-enum pd_msg_type {
+enum pd_sop_type {
SOP_MSG = 0,
SOPI_MSG,
SOPII_MSG,
@@ -61,8 +61,8 @@ enum pd_spec_rev {
#define FRAME_FILTER_EN_HARD_RESET BIT(5)
struct pd_phy_params {
- void (*signal_cb)(struct usbpd *pd, enum pd_sig_type type);
- void (*msg_rx_cb)(struct usbpd *pd, enum pd_msg_type type,
+ void (*signal_cb)(struct usbpd *pd, enum pd_sig_type sig);
+ void (*msg_rx_cb)(struct usbpd *pd, enum pd_sop_type sop,
u8 *buf, size_t len);
void (*shutdown_cb)(struct usbpd *pd);
enum data_role data_role;
@@ -72,9 +72,9 @@ struct pd_phy_params {
#if IS_ENABLED(CONFIG_QPNP_USB_PDPHY)
int pd_phy_open(struct pd_phy_params *params);
-int pd_phy_signal(enum pd_sig_type type, unsigned int timeout_ms);
+int pd_phy_signal(enum pd_sig_type sig);
int pd_phy_write(u16 hdr, const u8 *data, size_t data_len,
- enum pd_msg_type type, unsigned int timeout_ms);
+ enum pd_sop_type sop);
int pd_phy_update_roles(enum data_role dr, enum power_role pr);
void pd_phy_close(void);
#else
@@ -83,13 +83,13 @@ static inline int pd_phy_open(struct pd_phy_params *params)
return -ENODEV;
}
-static inline int pd_phy_signal(enum pd_sig_type type, unsigned int timeout_ms)
+static inline int pd_phy_signal(enum pd_sig_type type)
{
return -ENODEV;
}
static inline int pd_phy_write(u16 hdr, const u8 *data, size_t data_len,
- enum pd_msg_type type, unsigned int timeout_ms)
+ enum pd_sop_type sop)
{
return -ENODEV;
}
diff --git a/drivers/usb/phy/phy-msm-ssusb-qmp.c b/drivers/usb/phy/phy-msm-ssusb-qmp.c
index 6ba742076baa..2bc3c6fa417a 100644
--- a/drivers/usb/phy/phy-msm-ssusb-qmp.c
+++ b/drivers/usb/phy/phy-msm-ssusb-qmp.c
@@ -149,15 +149,17 @@ static void msm_ssusb_qmp_enable_autonomous(struct msm_ssphy_qmp *phy,
if (enable) {
msm_ssusb_qmp_clr_lfps_rxterm_int(phy);
+ val = readb_relaxed(phy->base + autonomous_mode_offset);
+ val |= ARCVR_DTCT_EN;
if (phy->phy.flags & DEVICE_IN_SS_MODE) {
- val =
- readb_relaxed(phy->base + autonomous_mode_offset);
- val |= ARCVR_DTCT_EN;
val |= ALFPS_DTCT_EN;
val &= ~ARCVR_DTCT_EVENT_SEL;
- writeb_relaxed(val, phy->base + autonomous_mode_offset);
+ } else {
+ val &= ~ALFPS_DTCT_EN;
+ val |= ARCVR_DTCT_EVENT_SEL;
}
+ writeb_relaxed(val, phy->base + autonomous_mode_offset);
/* clamp phy level shifter to perform autonomous detection */
writel_relaxed(0x1, phy->vls_clamp_reg);
} else {
diff --git a/drivers/usb/renesas_usbhs/common.c b/drivers/usb/renesas_usbhs/common.c
index d82fa36c3465..005da0866836 100644
--- a/drivers/usb/renesas_usbhs/common.c
+++ b/drivers/usb/renesas_usbhs/common.c
@@ -733,8 +733,10 @@ static int usbhsc_resume(struct device *dev)
struct usbhs_priv *priv = dev_get_drvdata(dev);
struct platform_device *pdev = usbhs_priv_to_pdev(priv);
- if (!usbhsc_flags_has(priv, USBHSF_RUNTIME_PWCTRL))
+ if (!usbhsc_flags_has(priv, USBHSF_RUNTIME_PWCTRL)) {
usbhsc_power_ctrl(priv, 1);
+ usbhs_mod_autonomy_mode(priv);
+ }
usbhs_platform_call(priv, phy_reset, pdev);
diff --git a/drivers/usb/renesas_usbhs/mod_gadget.c b/drivers/usb/renesas_usbhs/mod_gadget.c
index efc4fae123a4..8647d2c2a8c4 100644
--- a/drivers/usb/renesas_usbhs/mod_gadget.c
+++ b/drivers/usb/renesas_usbhs/mod_gadget.c
@@ -37,6 +37,7 @@ struct usbhsg_gpriv;
struct usbhsg_uep {
struct usb_ep ep;
struct usbhs_pipe *pipe;
+ spinlock_t lock; /* protect the pipe */
char ep_name[EP_NAME_SIZE];
@@ -638,10 +639,16 @@ usbhsg_ep_enable_end:
static int usbhsg_ep_disable(struct usb_ep *ep)
{
struct usbhsg_uep *uep = usbhsg_ep_to_uep(ep);
- struct usbhs_pipe *pipe = usbhsg_uep_to_pipe(uep);
+ struct usbhs_pipe *pipe;
+ unsigned long flags;
+ int ret = 0;
- if (!pipe)
- return -EINVAL;
+ spin_lock_irqsave(&uep->lock, flags);
+ pipe = usbhsg_uep_to_pipe(uep);
+ if (!pipe) {
+ ret = -EINVAL;
+ goto out;
+ }
usbhsg_pipe_disable(uep);
usbhs_pipe_free(pipe);
@@ -649,6 +656,9 @@ static int usbhsg_ep_disable(struct usb_ep *ep)
uep->pipe->mod_private = NULL;
uep->pipe = NULL;
+out:
+ spin_unlock_irqrestore(&uep->lock, flags);
+
return 0;
}
@@ -698,8 +708,11 @@ static int usbhsg_ep_dequeue(struct usb_ep *ep, struct usb_request *req)
{
struct usbhsg_uep *uep = usbhsg_ep_to_uep(ep);
struct usbhsg_request *ureq = usbhsg_req_to_ureq(req);
- struct usbhs_pipe *pipe = usbhsg_uep_to_pipe(uep);
+ struct usbhs_pipe *pipe;
+ unsigned long flags;
+ spin_lock_irqsave(&uep->lock, flags);
+ pipe = usbhsg_uep_to_pipe(uep);
if (pipe)
usbhs_pkt_pop(pipe, usbhsg_ureq_to_pkt(ureq));
@@ -708,6 +721,7 @@ static int usbhsg_ep_dequeue(struct usb_ep *ep, struct usb_request *req)
* even if the pipe is NULL.
*/
usbhsg_queue_pop(uep, ureq, -ECONNRESET);
+ spin_unlock_irqrestore(&uep->lock, flags);
return 0;
}
@@ -854,10 +868,10 @@ static int usbhsg_try_stop(struct usbhs_priv *priv, u32 status)
{
struct usbhsg_gpriv *gpriv = usbhsg_priv_to_gpriv(priv);
struct usbhs_mod *mod = usbhs_mod_get_current(priv);
- struct usbhsg_uep *dcp = usbhsg_gpriv_to_dcp(gpriv);
+ struct usbhsg_uep *uep;
struct device *dev = usbhs_priv_to_dev(priv);
unsigned long flags;
- int ret = 0;
+ int ret = 0, i;
/******************** spin lock ********************/
usbhs_lock(priv, flags);
@@ -889,7 +903,9 @@ static int usbhsg_try_stop(struct usbhs_priv *priv, u32 status)
usbhs_sys_set_test_mode(priv, 0);
usbhs_sys_function_ctrl(priv, 0);
- usbhsg_ep_disable(&dcp->ep);
+ /* disable all eps */
+ usbhsg_for_each_uep_with_dcp(uep, gpriv, i)
+ usbhsg_ep_disable(&uep->ep);
dev_dbg(dev, "stop gadget\n");
@@ -1072,6 +1088,7 @@ int usbhs_mod_gadget_probe(struct usbhs_priv *priv)
ret = -ENOMEM;
goto usbhs_mod_gadget_probe_err_gpriv;
}
+ spin_lock_init(&uep->lock);
gpriv->transceiver = usb_get_phy(USB_PHY_TYPE_UNDEFINED);
dev_info(dev, "%stransceiver found\n",
diff --git a/drivers/usb/storage/isd200.c b/drivers/usb/storage/isd200.c
index 39afd7045c43..7bb5f8da5357 100644
--- a/drivers/usb/storage/isd200.c
+++ b/drivers/usb/storage/isd200.c
@@ -1520,8 +1520,11 @@ static void isd200_ata_command(struct scsi_cmnd *srb, struct us_data *us)
/* Make sure driver was initialized */
- if (us->extra == NULL)
+ if (us->extra == NULL) {
usb_stor_dbg(us, "ERROR Driver not initialized\n");
+ srb->result = DID_ERROR << 16;
+ return;
+ }
scsi_set_resid(srb, 0);
/* scsi_bufflen might change in protocol translation to ata */
diff --git a/drivers/vfio/pci/vfio_pci.c b/drivers/vfio/pci/vfio_pci.c
index 830e2fd47642..b31b84f56e8f 100644
--- a/drivers/vfio/pci/vfio_pci.c
+++ b/drivers/vfio/pci/vfio_pci.c
@@ -902,6 +902,10 @@ static int vfio_pci_mmap(void *device_data, struct vm_area_struct *vma)
return ret;
vdev->barmap[index] = pci_iomap(pdev, index, 0);
+ if (!vdev->barmap[index]) {
+ pci_release_selected_regions(pdev, 1 << index);
+ return -ENOMEM;
+ }
}
vma->vm_private_data = vdev;
diff --git a/drivers/vfio/pci/vfio_pci_rdwr.c b/drivers/vfio/pci/vfio_pci_rdwr.c
index 210db24d2204..4d39f7959adf 100644
--- a/drivers/vfio/pci/vfio_pci_rdwr.c
+++ b/drivers/vfio/pci/vfio_pci_rdwr.c
@@ -190,7 +190,10 @@ ssize_t vfio_pci_vga_rw(struct vfio_pci_device *vdev, char __user *buf,
if (!vdev->has_vga)
return -EINVAL;
- switch (pos) {
+ if (pos > 0xbfffful)
+ return -EINVAL;
+
+ switch ((u32)pos) {
case 0xa0000 ... 0xbffff:
count = min(count, (size_t)(0xc0000 - pos));
iomem = ioremap_nocache(0xa0000, 0xbffff - 0xa0000 + 1);
diff --git a/drivers/vfio/vfio.c b/drivers/vfio/vfio.c
index 6070b793cbcb..1e01e28f40f3 100644
--- a/drivers/vfio/vfio.c
+++ b/drivers/vfio/vfio.c
@@ -296,6 +296,34 @@ static void vfio_group_put(struct vfio_group *group)
kref_put_mutex(&group->kref, vfio_group_release, &vfio.group_lock);
}
+struct vfio_group_put_work {
+ struct work_struct work;
+ struct vfio_group *group;
+};
+
+static void vfio_group_put_bg(struct work_struct *work)
+{
+ struct vfio_group_put_work *do_work;
+
+ do_work = container_of(work, struct vfio_group_put_work, work);
+
+ vfio_group_put(do_work->group);
+ kfree(do_work);
+}
+
+static void vfio_group_schedule_put(struct vfio_group *group)
+{
+ struct vfio_group_put_work *do_work;
+
+ do_work = kmalloc(sizeof(*do_work), GFP_KERNEL);
+ if (WARN_ON(!do_work))
+ return;
+
+ INIT_WORK(&do_work->work, vfio_group_put_bg);
+ do_work->group = group;
+ schedule_work(&do_work->work);
+}
+
/* Assume group_lock or group reference is held */
static void vfio_group_get(struct vfio_group *group)
{
@@ -620,7 +648,14 @@ static int vfio_iommu_group_notifier(struct notifier_block *nb,
break;
}
- vfio_group_put(group);
+ /*
+ * If we're the last reference to the group, the group will be
+ * released, which includes unregistering the iommu group notifier.
+ * We hold a read-lock on that notifier list, unregistering needs
+ * a write-lock... deadlock. Release our reference asynchronously
+ * to avoid that situation.
+ */
+ vfio_group_schedule_put(group);
return NOTIFY_OK;
}
@@ -1552,6 +1587,15 @@ void vfio_group_put_external_user(struct vfio_group *group)
}
EXPORT_SYMBOL_GPL(vfio_group_put_external_user);
+bool vfio_external_group_match_file(struct vfio_group *test_group,
+ struct file *filep)
+{
+ struct vfio_group *group = filep->private_data;
+
+ return (filep->f_op == &vfio_group_fops) && (group == test_group);
+}
+EXPORT_SYMBOL_GPL(vfio_external_group_match_file);
+
int vfio_external_user_iommu_id(struct vfio_group *group)
{
return iommu_group_id(group->iommu_group);
diff --git a/drivers/video/fbdev/cobalt_lcdfb.c b/drivers/video/fbdev/cobalt_lcdfb.c
index 07675d6f323e..d4530b54479c 100644
--- a/drivers/video/fbdev/cobalt_lcdfb.c
+++ b/drivers/video/fbdev/cobalt_lcdfb.c
@@ -350,6 +350,11 @@ static int cobalt_lcdfb_probe(struct platform_device *dev)
info->screen_size = resource_size(res);
info->screen_base = devm_ioremap(&dev->dev, res->start,
info->screen_size);
+ if (!info->screen_base) {
+ framebuffer_release(info);
+ return -ENOMEM;
+ }
+
info->fbops = &cobalt_lcd_fbops;
info->fix = cobalt_lcdfb_fix;
info->fix.smem_start = res->start;
diff --git a/drivers/video/fbdev/msm/mdss_hdmi_tx.c b/drivers/video/fbdev/msm/mdss_hdmi_tx.c
index bda93bf0558a..837147dc5036 100644
--- a/drivers/video/fbdev/msm/mdss_hdmi_tx.c
+++ b/drivers/video/fbdev/msm/mdss_hdmi_tx.c
@@ -2179,6 +2179,7 @@ static int hdmi_tx_read_sink_info(struct hdmi_tx_ctrl *hdmi_ctrl)
int status = 0;
void *data;
struct dss_io_data *io;
+ u32 sink_max_pclk;
if (!hdmi_ctrl) {
DEV_ERR("%s: invalid input\n", __func__);
@@ -2218,16 +2219,22 @@ static int hdmi_tx_read_sink_info(struct hdmi_tx_ctrl *hdmi_ctrl)
/* parse edid if a valid edid buffer is present */
if (hdmi_ctrl->custom_edid || !hdmi_ctrl->sim_mode) {
status = hdmi_edid_parser(data);
- if (status)
+ if (status) {
DEV_ERR("%s: edid parse failed\n", __func__);
- else
+ } else {
/*
- * Updata HDMI max supported TMDS clock, consider
- * both sink and source capicity.
+ * Update HDMI max supported TMDS clock, consider
+ * both sink and source capacity. For DVI sink,
+ * could not get max TMDS clock from EDID, so just
+ * use source capacity.
*/
- hdmi_edid_set_max_pclk_rate(data,
- min(hdmi_edid_get_sink_caps_max_tmds_clk(data) / 1000,
- hdmi_ctrl->max_pclk_khz));
+ sink_max_pclk =
+ hdmi_edid_get_sink_caps_max_tmds_clk(data);
+ if (sink_max_pclk != 0)
+ hdmi_edid_set_max_pclk_rate(data,
+ min(sink_max_pclk / 1000,
+ hdmi_ctrl->max_pclk_khz));
+ }
}
bail:
if (hdmi_tx_enable_power(hdmi_ctrl, HDMI_TX_DDC_PM, false))
diff --git a/fs/btrfs/inode.c b/fs/btrfs/inode.c
index a61926cb01c0..bebd6517355d 100644
--- a/fs/btrfs/inode.c
+++ b/fs/btrfs/inode.c
@@ -7521,11 +7521,18 @@ static void adjust_dio_outstanding_extents(struct inode *inode,
* within our reservation, otherwise we need to adjust our inode
* counter appropriately.
*/
- if (dio_data->outstanding_extents) {
+ if (dio_data->outstanding_extents >= num_extents) {
dio_data->outstanding_extents -= num_extents;
} else {
+ /*
+ * If dio write length has been split due to no large enough
+ * contiguous space, we need to compensate our inode counter
+ * appropriately.
+ */
+ u64 num_needed = num_extents - dio_data->outstanding_extents;
+
spin_lock(&BTRFS_I(inode)->lock);
- BTRFS_I(inode)->outstanding_extents += num_extents;
+ BTRFS_I(inode)->outstanding_extents += num_needed;
spin_unlock(&BTRFS_I(inode)->lock);
}
}
diff --git a/fs/ceph/dir.c b/fs/ceph/dir.c
index 9314b4ea2375..be7d187d53fd 100644
--- a/fs/ceph/dir.c
+++ b/fs/ceph/dir.c
@@ -247,6 +247,11 @@ static int __dcache_readdir(struct file *file, struct dir_context *ctx,
if (ret < 0)
err = ret;
dput(last);
+ /* last_name no longer match cache index */
+ if (fi->readdir_cache_idx >= 0) {
+ fi->readdir_cache_idx = -1;
+ fi->dir_release_count = 0;
+ }
}
return err;
}
diff --git a/fs/dcache.c b/fs/dcache.c
index 4c07a84d1317..ba56a39a3b74 100644
--- a/fs/dcache.c
+++ b/fs/dcache.c
@@ -269,6 +269,33 @@ static inline int dname_external(const struct dentry *dentry)
return dentry->d_name.name != dentry->d_iname;
}
+void take_dentry_name_snapshot(struct name_snapshot *name, struct dentry *dentry)
+{
+ spin_lock(&dentry->d_lock);
+ if (unlikely(dname_external(dentry))) {
+ struct external_name *p = external_name(dentry);
+ atomic_inc(&p->u.count);
+ spin_unlock(&dentry->d_lock);
+ name->name = p->name;
+ } else {
+ memcpy(name->inline_name, dentry->d_iname, DNAME_INLINE_LEN);
+ spin_unlock(&dentry->d_lock);
+ name->name = name->inline_name;
+ }
+}
+EXPORT_SYMBOL(take_dentry_name_snapshot);
+
+void release_dentry_name_snapshot(struct name_snapshot *name)
+{
+ if (unlikely(name->name != name->inline_name)) {
+ struct external_name *p;
+ p = container_of(name->name, struct external_name, name[0]);
+ if (unlikely(atomic_dec_and_test(&p->u.count)))
+ kfree_rcu(p, u.head);
+ }
+}
+EXPORT_SYMBOL(release_dentry_name_snapshot);
+
static inline void __d_set_inode_and_type(struct dentry *dentry,
struct inode *inode,
unsigned type_flags)
diff --git a/fs/debugfs/inode.c b/fs/debugfs/inode.c
index 0f5d05bf2131..e49ba072bd64 100644
--- a/fs/debugfs/inode.c
+++ b/fs/debugfs/inode.c
@@ -669,7 +669,7 @@ struct dentry *debugfs_rename(struct dentry *old_dir, struct dentry *old_dentry,
{
int error;
struct dentry *dentry = NULL, *trap;
- const char *old_name;
+ struct name_snapshot old_name;
trap = lock_rename(new_dir, old_dir);
/* Source or destination directories don't exist? */
@@ -684,19 +684,19 @@ struct dentry *debugfs_rename(struct dentry *old_dir, struct dentry *old_dentry,
if (IS_ERR(dentry) || dentry == trap || d_really_is_positive(dentry))
goto exit;
- old_name = fsnotify_oldname_init(old_dentry->d_name.name);
+ take_dentry_name_snapshot(&old_name, old_dentry);
error = simple_rename(d_inode(old_dir), old_dentry, d_inode(new_dir),
dentry);
if (error) {
- fsnotify_oldname_free(old_name);
+ release_dentry_name_snapshot(&old_name);
goto exit;
}
d_move(old_dentry, dentry);
- fsnotify_move(d_inode(old_dir), d_inode(new_dir), old_name,
+ fsnotify_move(d_inode(old_dir), d_inode(new_dir), old_name.name,
d_is_dir(old_dentry),
NULL, old_dentry);
- fsnotify_oldname_free(old_name);
+ release_dentry_name_snapshot(&old_name);
unlock_rename(new_dir, old_dir);
dput(dentry);
return old_dentry;
diff --git a/fs/f2fs/acl.c b/fs/f2fs/acl.c
index e9a8d676c6bc..83dcf7bfd7b8 100644
--- a/fs/f2fs/acl.c
+++ b/fs/f2fs/acl.c
@@ -213,7 +213,7 @@ static int __f2fs_set_acl(struct inode *inode, int type,
switch (type) {
case ACL_TYPE_ACCESS:
name_index = F2FS_XATTR_INDEX_POSIX_ACL_ACCESS;
- if (acl) {
+ if (acl && !ipage) {
error = posix_acl_update_mode(inode, &inode->i_mode, &acl);
if (error)
return error;
diff --git a/fs/namei.c b/fs/namei.c
index b5dfe2c5b51e..3b2b5c8e0ec7 100644
--- a/fs/namei.c
+++ b/fs/namei.c
@@ -4264,11 +4264,11 @@ int vfs_rename2(struct vfsmount *mnt,
{
int error;
bool is_dir = d_is_dir(old_dentry);
- const unsigned char *old_name;
struct inode *source = old_dentry->d_inode;
struct inode *target = new_dentry->d_inode;
bool new_is_dir = false;
unsigned max_links = new_dir->i_sb->s_max_links;
+ struct name_snapshot old_name;
/*
* Check source == target.
@@ -4322,7 +4322,7 @@ int vfs_rename2(struct vfsmount *mnt,
if (error)
return error;
- old_name = fsnotify_oldname_init(old_dentry->d_name.name);
+ take_dentry_name_snapshot(&old_name, old_dentry);
dget(new_dentry);
if (!is_dir || (flags & RENAME_EXCHANGE))
lock_two_nondirectories(source, target);
@@ -4383,14 +4383,14 @@ out:
mutex_unlock(&target->i_mutex);
dput(new_dentry);
if (!error) {
- fsnotify_move(old_dir, new_dir, old_name, is_dir,
+ fsnotify_move(old_dir, new_dir, old_name.name, is_dir,
!(flags & RENAME_EXCHANGE) ? target : NULL, old_dentry);
if (flags & RENAME_EXCHANGE) {
fsnotify_move(new_dir, old_dir, old_dentry->d_name.name,
new_is_dir, NULL, new_dentry);
}
}
- fsnotify_oldname_free(old_name);
+ release_dentry_name_snapshot(&old_name);
return error;
}
diff --git a/fs/nfs/dir.c b/fs/nfs/dir.c
index 5b21b1ca2341..348e0a05bd18 100644
--- a/fs/nfs/dir.c
+++ b/fs/nfs/dir.c
@@ -1135,11 +1135,13 @@ static int nfs_lookup_revalidate(struct dentry *dentry, unsigned int flags)
/* Force a full look up iff the parent directory has changed */
if (!nfs_is_exclusive_create(dir, flags) &&
nfs_check_verifier(dir, dentry, flags & LOOKUP_RCU)) {
-
- if (nfs_lookup_verify_inode(inode, flags)) {
+ error = nfs_lookup_verify_inode(inode, flags);
+ if (error) {
if (flags & LOOKUP_RCU)
return -ECHILD;
- goto out_zap_parent;
+ if (error == -ESTALE)
+ goto out_zap_parent;
+ goto out_error;
}
goto out_valid;
}
@@ -1163,8 +1165,10 @@ static int nfs_lookup_revalidate(struct dentry *dentry, unsigned int flags)
trace_nfs_lookup_revalidate_enter(dir, dentry, flags);
error = NFS_PROTO(dir)->lookup(dir, &dentry->d_name, fhandle, fattr, label);
trace_nfs_lookup_revalidate_exit(dir, dentry, flags, error);
- if (error)
+ if (error == -ESTALE || error == -ENOENT)
goto out_bad;
+ if (error)
+ goto out_error;
if (nfs_compare_fh(NFS_FH(inode), fhandle))
goto out_bad;
if ((error = nfs_refresh_inode(inode, fattr)) != 0)
diff --git a/fs/nfs/inode.c b/fs/nfs/inode.c
index f714b98cfd74..668ac19af58f 100644
--- a/fs/nfs/inode.c
+++ b/fs/nfs/inode.c
@@ -1241,9 +1241,9 @@ static int nfs_check_inode_attributes(struct inode *inode, struct nfs_fattr *fat
return 0;
/* Has the inode gone and changed behind our back? */
if ((fattr->valid & NFS_ATTR_FATTR_FILEID) && nfsi->fileid != fattr->fileid)
- return -EIO;
+ return -ESTALE;
if ((fattr->valid & NFS_ATTR_FATTR_TYPE) && (inode->i_mode & S_IFMT) != (fattr->mode & S_IFMT))
- return -EIO;
+ return -ESTALE;
if ((fattr->valid & NFS_ATTR_FATTR_CHANGE) != 0 &&
inode->i_version != fattr->change_attr)
diff --git a/fs/notify/fsnotify.c b/fs/notify/fsnotify.c
index db39de2dd4cb..a64adc2fced9 100644
--- a/fs/notify/fsnotify.c
+++ b/fs/notify/fsnotify.c
@@ -104,16 +104,20 @@ int __fsnotify_parent(struct path *path, struct dentry *dentry, __u32 mask)
if (unlikely(!fsnotify_inode_watches_children(p_inode)))
__fsnotify_update_child_dentry_flags(p_inode);
else if (p_inode->i_fsnotify_mask & mask) {
+ struct name_snapshot name;
+
/* we are notifying a parent so come up with the new mask which
* specifies these are events which came from a child. */
mask |= FS_EVENT_ON_CHILD;
+ take_dentry_name_snapshot(&name, dentry);
if (path)
ret = fsnotify(p_inode, mask, path, FSNOTIFY_EVENT_PATH,
- dentry->d_name.name, 0);
+ name.name, 0);
else
ret = fsnotify(p_inode, mask, dentry->d_inode, FSNOTIFY_EVENT_INODE,
- dentry->d_name.name, 0);
+ name.name, 0);
+ release_dentry_name_snapshot(&name);
}
dput(parent);
diff --git a/fs/pstore/ram.c b/fs/pstore/ram.c
index 8d1e5e2db6a1..c9e4bc47c79d 100644
--- a/fs/pstore/ram.c
+++ b/fs/pstore/ram.c
@@ -434,7 +434,7 @@ static int ramoops_init_przs(struct device *dev, struct ramoops_context *cxt,
for (i = 0; i < cxt->max_dump_cnt; i++) {
cxt->przs[i] = persistent_ram_new(*paddr, cxt->record_size, 0,
&cxt->ecc_info,
- cxt->memtype);
+ cxt->memtype, 0);
if (IS_ERR(cxt->przs[i])) {
err = PTR_ERR(cxt->przs[i]);
dev_err(dev, "failed to request mem region (0x%zx@0x%llx): %d\n",
@@ -471,7 +471,8 @@ static int ramoops_init_prz(struct device *dev, struct ramoops_context *cxt,
return -ENOMEM;
}
- *prz = persistent_ram_new(*paddr, sz, sig, &cxt->ecc_info, cxt->memtype);
+ *prz = persistent_ram_new(*paddr, sz, sig, &cxt->ecc_info,
+ cxt->memtype, 0);
if (IS_ERR(*prz)) {
int err = PTR_ERR(*prz);
diff --git a/fs/pstore/ram_core.c b/fs/pstore/ram_core.c
index 3975deec02f8..e11672aa4575 100644
--- a/fs/pstore/ram_core.c
+++ b/fs/pstore/ram_core.c
@@ -48,16 +48,15 @@ static inline size_t buffer_start(struct persistent_ram_zone *prz)
return atomic_read(&prz->buffer->start);
}
-static DEFINE_RAW_SPINLOCK(buffer_lock);
-
/* increase and wrap the start pointer, returning the old value */
static size_t buffer_start_add(struct persistent_ram_zone *prz, size_t a)
{
int old;
int new;
- unsigned long flags;
+ unsigned long flags = 0;
- raw_spin_lock_irqsave(&buffer_lock, flags);
+ if (!(prz->flags & PRZ_FLAG_NO_LOCK))
+ raw_spin_lock_irqsave(&prz->buffer_lock, flags);
old = atomic_read(&prz->buffer->start);
new = old + a;
@@ -65,7 +64,8 @@ static size_t buffer_start_add(struct persistent_ram_zone *prz, size_t a)
new -= prz->buffer_size;
atomic_set(&prz->buffer->start, new);
- raw_spin_unlock_irqrestore(&buffer_lock, flags);
+ if (!(prz->flags & PRZ_FLAG_NO_LOCK))
+ raw_spin_unlock_irqrestore(&prz->buffer_lock, flags);
return old;
}
@@ -75,9 +75,10 @@ static void buffer_size_add(struct persistent_ram_zone *prz, size_t a)
{
size_t old;
size_t new;
- unsigned long flags;
+ unsigned long flags = 0;
- raw_spin_lock_irqsave(&buffer_lock, flags);
+ if (!(prz->flags & PRZ_FLAG_NO_LOCK))
+ raw_spin_lock_irqsave(&prz->buffer_lock, flags);
old = atomic_read(&prz->buffer->size);
if (old == prz->buffer_size)
@@ -89,7 +90,8 @@ static void buffer_size_add(struct persistent_ram_zone *prz, size_t a)
atomic_set(&prz->buffer->size, new);
exit:
- raw_spin_unlock_irqrestore(&buffer_lock, flags);
+ if (!(prz->flags & PRZ_FLAG_NO_LOCK))
+ raw_spin_unlock_irqrestore(&prz->buffer_lock, flags);
}
static void notrace persistent_ram_encode_rs8(struct persistent_ram_zone *prz,
@@ -491,6 +493,7 @@ static int persistent_ram_post_init(struct persistent_ram_zone *prz, u32 sig,
prz->buffer->sig);
}
+ /* Rewind missing or invalid memory area. */
prz->buffer->sig = sig;
persistent_ram_zap(prz);
@@ -517,7 +520,7 @@ void persistent_ram_free(struct persistent_ram_zone *prz)
struct persistent_ram_zone *persistent_ram_new(phys_addr_t start, size_t size,
u32 sig, struct persistent_ram_ecc_info *ecc_info,
- unsigned int memtype)
+ unsigned int memtype, u32 flags)
{
struct persistent_ram_zone *prz;
int ret = -ENOMEM;
@@ -528,6 +531,10 @@ struct persistent_ram_zone *persistent_ram_new(phys_addr_t start, size_t size,
goto err;
}
+ /* Initialize general buffer state. */
+ raw_spin_lock_init(&prz->buffer_lock);
+ prz->flags = flags;
+
ret = persistent_ram_buffer_map(start, size, prz, memtype);
if (ret)
goto err;
diff --git a/fs/seq_file.c b/fs/seq_file.c
index d672e2fec459..6dc4296eed62 100644
--- a/fs/seq_file.c
+++ b/fs/seq_file.c
@@ -72,9 +72,10 @@ int seq_open(struct file *file, const struct seq_operations *op)
mutex_init(&p->lock);
p->op = op;
-#ifdef CONFIG_USER_NS
- p->user_ns = file->f_cred->user_ns;
-#endif
+
+ // No refcounting: the lifetime of 'p' is constrained
+ // to the lifetime of the file.
+ p->file = file;
/*
* Wrappers around seq_open(e.g. swaps_open) need to be
diff --git a/fs/udf/inode.c b/fs/udf/inode.c
index 7be3166ba553..0e659d9c69a1 100644
--- a/fs/udf/inode.c
+++ b/fs/udf/inode.c
@@ -1235,8 +1235,8 @@ int udf_setsize(struct inode *inode, loff_t newsize)
return err;
}
set_size:
- truncate_setsize(inode, newsize);
up_write(&iinfo->i_data_sem);
+ truncate_setsize(inode, newsize);
} else {
if (iinfo->i_alloc_type == ICBTAG_FLAG_AD_IN_ICB) {
down_write(&iinfo->i_data_sem);
@@ -1253,9 +1253,9 @@ set_size:
udf_get_block);
if (err)
return err;
+ truncate_setsize(inode, newsize);
down_write(&iinfo->i_data_sem);
udf_clear_extent_cache(inode);
- truncate_setsize(inode, newsize);
udf_truncate_extents(inode);
up_write(&iinfo->i_data_sem);
}
diff --git a/fs/xfs/xfs_aops.c b/fs/xfs/xfs_aops.c
index 187b80267ff9..a9063ac50c4e 100644
--- a/fs/xfs/xfs_aops.c
+++ b/fs/xfs/xfs_aops.c
@@ -1426,6 +1426,26 @@ __xfs_get_blocks(
if (error)
goto out_unlock;
+ /*
+ * The only time we can ever safely find delalloc blocks on direct I/O
+ * is a dio write to post-eof speculative preallocation. All other
+ * scenarios are indicative of a problem or misuse (such as mixing
+ * direct and mapped I/O).
+ *
+ * The file may be unmapped by the time we get here so we cannot
+ * reliably fail the I/O based on mapping. Instead, fail the I/O if this
+ * is a read or a write within eof. Otherwise, carry on but warn as a
+ * precuation if the file happens to be mapped.
+ */
+ if (direct && imap.br_startblock == DELAYSTARTBLOCK) {
+ if (!create || offset < i_size_read(VFS_I(ip))) {
+ WARN_ON_ONCE(1);
+ error = -EIO;
+ goto out_unlock;
+ }
+ WARN_ON_ONCE(mapping_mapped(VFS_I(ip)->i_mapping));
+ }
+
/* for DAX, we convert unwritten extents directly */
if (create &&
(!nimaps ||
@@ -1525,7 +1545,6 @@ __xfs_get_blocks(
set_buffer_new(bh_result);
if (imap.br_startblock == DELAYSTARTBLOCK) {
- BUG_ON(direct);
if (create) {
set_buffer_uptodate(bh_result);
set_buffer_mapped(bh_result);
diff --git a/include/linux/dcache.h b/include/linux/dcache.h
index 2043af2141c1..01448e01b40d 100644
--- a/include/linux/dcache.h
+++ b/include/linux/dcache.h
@@ -616,5 +616,11 @@ static inline struct inode *d_real_inode(struct dentry *dentry)
return d_backing_inode(d_real(dentry));
}
+struct name_snapshot {
+ const char *name;
+ char inline_name[DNAME_INLINE_LEN];
+};
+void take_dentry_name_snapshot(struct name_snapshot *, struct dentry *);
+void release_dentry_name_snapshot(struct name_snapshot *);
#endif /* __LINUX_DCACHE_H */
diff --git a/include/linux/fsnotify.h b/include/linux/fsnotify.h
index 7ee1774edee5..a7789559078b 100644
--- a/include/linux/fsnotify.h
+++ b/include/linux/fsnotify.h
@@ -310,35 +310,4 @@ static inline void fsnotify_change(struct dentry *dentry, unsigned int ia_valid)
}
}
-#if defined(CONFIG_FSNOTIFY) /* notify helpers */
-
-/*
- * fsnotify_oldname_init - save off the old filename before we change it
- */
-static inline const unsigned char *fsnotify_oldname_init(const unsigned char *name)
-{
- return kstrdup(name, GFP_KERNEL);
-}
-
-/*
- * fsnotify_oldname_free - free the name we got from fsnotify_oldname_init
- */
-static inline void fsnotify_oldname_free(const unsigned char *old_name)
-{
- kfree(old_name);
-}
-
-#else /* CONFIG_FSNOTIFY */
-
-static inline const char *fsnotify_oldname_init(const unsigned char *name)
-{
- return NULL;
-}
-
-static inline void fsnotify_oldname_free(const unsigned char *old_name)
-{
-}
-
-#endif /* CONFIG_FSNOTIFY */
-
#endif /* _LINUX_FS_NOTIFY_H */
diff --git a/include/linux/phy.h b/include/linux/phy.h
index 05fde31b6dc6..b64825d6ad26 100644
--- a/include/linux/phy.h
+++ b/include/linux/phy.h
@@ -785,6 +785,10 @@ int genphy_read_status(struct phy_device *phydev);
int genphy_suspend(struct phy_device *phydev);
int genphy_resume(struct phy_device *phydev);
int genphy_soft_reset(struct phy_device *phydev);
+static inline int genphy_no_soft_reset(struct phy_device *phydev)
+{
+ return 0;
+}
void phy_driver_unregister(struct phy_driver *drv);
void phy_drivers_unregister(struct phy_driver *drv, int n);
int phy_driver_register(struct phy_driver *new_driver);
diff --git a/include/linux/power_supply.h b/include/linux/power_supply.h
index 93efe2b916ea..982b93ccfbe4 100644
--- a/include/linux/power_supply.h
+++ b/include/linux/power_supply.h
@@ -252,6 +252,9 @@ enum power_supply_property {
POWER_SUPPLY_PROP_CC_STEP,
POWER_SUPPLY_PROP_CC_STEP_SEL,
POWER_SUPPLY_PROP_SW_JEITA_ENABLED,
+ POWER_SUPPLY_PROP_PD_VOLTAGE_MAX,
+ POWER_SUPPLY_PROP_PD_VOLTAGE_MIN,
+ POWER_SUPPLY_PROP_SDP_CURRENT_MAX,
/* Local extensions of type int64_t */
POWER_SUPPLY_PROP_CHARGE_COUNTER_EXT,
/* Properties of type `const char *' */
diff --git a/include/linux/pstore_ram.h b/include/linux/pstore_ram.h
index 45ac5a0d29ee..7097a45dbc25 100644
--- a/include/linux/pstore_ram.h
+++ b/include/linux/pstore_ram.h
@@ -24,6 +24,13 @@
#include <linux/list.h>
#include <linux/types.h>
+/*
+ * Choose whether access to the RAM zone requires locking or not. If a zone
+ * can be written to from different CPUs like with ftrace for example, then
+ * PRZ_FLAG_NO_LOCK is used. For all other cases, locking is required.
+ */
+#define PRZ_FLAG_NO_LOCK BIT(0)
+
struct persistent_ram_buffer;
struct rs_control;
@@ -40,6 +47,8 @@ struct persistent_ram_zone {
void *vaddr;
struct persistent_ram_buffer *buffer;
size_t buffer_size;
+ u32 flags;
+ raw_spinlock_t buffer_lock;
/* ECC correction */
char *par_buffer;
@@ -55,7 +64,7 @@ struct persistent_ram_zone {
struct persistent_ram_zone *persistent_ram_new(phys_addr_t start, size_t size,
u32 sig, struct persistent_ram_ecc_info *ecc_info,
- unsigned int memtype);
+ unsigned int memtype, u32 flags);
void persistent_ram_free(struct persistent_ram_zone *prz);
void persistent_ram_zap(struct persistent_ram_zone *prz);
diff --git a/include/linux/qpnp/qpnp-revid.h b/include/linux/qpnp/qpnp-revid.h
index b025df568259..bbc4625a2d39 100644
--- a/include/linux/qpnp/qpnp-revid.h
+++ b/include/linux/qpnp/qpnp-revid.h
@@ -252,6 +252,7 @@ struct pmic_revid_data {
u8 pmic_subtype;
const char *pmic_name;
int fab_id;
+ int tp_rev;
};
#ifdef CONFIG_QPNP_REVID
diff --git a/include/linux/seq_file.h b/include/linux/seq_file.h
index dde00defbaa5..f3d45dd42695 100644
--- a/include/linux/seq_file.h
+++ b/include/linux/seq_file.h
@@ -7,13 +7,10 @@
#include <linux/mutex.h>
#include <linux/cpumask.h>
#include <linux/nodemask.h>
+#include <linux/fs.h>
+#include <linux/cred.h>
struct seq_operations;
-struct file;
-struct path;
-struct inode;
-struct dentry;
-struct user_namespace;
struct seq_file {
char *buf;
@@ -27,9 +24,7 @@ struct seq_file {
struct mutex lock;
const struct seq_operations *op;
int poll_event;
-#ifdef CONFIG_USER_NS
- struct user_namespace *user_ns;
-#endif
+ const struct file *file;
void *private;
};
@@ -147,7 +142,7 @@ int seq_release_private(struct inode *, struct file *);
static inline struct user_namespace *seq_user_ns(struct seq_file *seq)
{
#ifdef CONFIG_USER_NS
- return seq->user_ns;
+ return seq->file->f_cred->user_ns;
#else
extern struct user_namespace init_user_ns;
return &init_user_ns;
diff --git a/include/linux/usb_bam.h b/include/linux/usb_bam.h
index e65fb12c1410..b5b9edaab783 100644
--- a/include/linux/usb_bam.h
+++ b/include/linux/usb_bam.h
@@ -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
@@ -191,7 +191,7 @@ struct usb_bam_pipe_connect {
};
/**
- * struct msm_usb_bam_platform_data: pipe connection information
+ * struct msm_usb_bam_data: pipe connection information
* between USB/HSIC BAM and another BAM. USB/HSIC BAM can be
* either src BAM or dst BAM
* @usb_bam_num_pipes: max number of pipes to use.
@@ -211,7 +211,7 @@ struct usb_bam_pipe_connect {
* can work at in bam2bam mode when connected to SS host.
* @enable_hsusb_bam_on_boot: Enable HSUSB BAM (non-NDP) on bootup itself
*/
-struct msm_usb_bam_platform_data {
+struct msm_usb_bam_data {
u8 max_connections;
int usb_bam_num_pipes;
phys_addr_t usb_bam_fifo_baseaddr;
diff --git a/include/linux/vfio.h b/include/linux/vfio.h
index ddb440975382..34851bf2e2c8 100644
--- a/include/linux/vfio.h
+++ b/include/linux/vfio.h
@@ -85,6 +85,8 @@ extern void vfio_unregister_iommu_driver(
*/
extern struct vfio_group *vfio_group_get_external_user(struct file *filep);
extern void vfio_group_put_external_user(struct vfio_group *group);
+extern bool vfio_external_group_match_file(struct vfio_group *group,
+ struct file *filep);
extern int vfio_external_user_iommu_id(struct vfio_group *group);
extern long vfio_external_check_extension(struct vfio_group *group,
unsigned long arg);
diff --git a/include/linux/wcnss_wlan.h b/include/linux/wcnss_wlan.h
index e0c47f8b06bf..bc838936d2c9 100644
--- a/include/linux/wcnss_wlan.h
+++ b/include/linux/wcnss_wlan.h
@@ -38,7 +38,6 @@ struct vregs_level {
};
struct wcnss_wlan_config {
- bool wcn_external_gpio_support;
int use_48mhz_xo;
int is_pronto_vadc;
int is_pronto_v3;
@@ -143,6 +142,8 @@ void wcnss_init_delayed_work(struct delayed_work *dwork , void *callbackptr);
int wcnss_get_iris_name(char *iris_version);
void wcnss_dump_stack(struct task_struct *task);
void wcnss_snoc_vote(bool clk_chk_en);
+int wcnss_parse_voltage_regulator(struct wcnss_wlan_config *wlan_config,
+ struct device *dev);
#ifdef CONFIG_WCNSS_REGISTER_DUMP_ON_BITE
void wcnss_log_debug_regs_on_bite(void);
diff --git a/include/sound/apr_audio-v2.h b/include/sound/apr_audio-v2.h
index 2680a13721c2..21b30bf7c74c 100644
--- a/include/sound/apr_audio-v2.h
+++ b/include/sound/apr_audio-v2.h
@@ -4012,7 +4012,7 @@ struct asm_stream_pan_ctrl_params {
uint16_t num_input_channels;
uint16_t output_channel_map[8];
uint16_t input_channel_map[8];
- uint16_t gain[64];
+ uint32_t gain[64];
} __packed;
#define ASM_END_POINT_DEVICE_MATRIX 0
diff --git a/include/sound/q6asm-v2.h b/include/sound/q6asm-v2.h
index dcf7dcb4f6e4..2ff0a2b02d4a 100644
--- a/include/sound/q6asm-v2.h
+++ b/include/sound/q6asm-v2.h
@@ -99,7 +99,7 @@
#define SOFT_PAUSE_ENABLE 1
#define SOFT_PAUSE_DISABLE 0
-#define ASM_ACTIVE_STREAMS_ALLOWED 0x8
+#define ASM_ACTIVE_STREAMS_ALLOWED 0x9
/* Control session is used for mapping calibration memory */
#define ASM_CONTROL_SESSION (ASM_ACTIVE_STREAMS_ALLOWED + 1)
diff --git a/include/target/iscsi/iscsi_target_core.h b/include/target/iscsi/iscsi_target_core.h
index 373d3342002b..e0efe3fcf739 100644
--- a/include/target/iscsi/iscsi_target_core.h
+++ b/include/target/iscsi/iscsi_target_core.h
@@ -64,6 +64,14 @@
#define TA_DEFAULT_FABRIC_PROT_TYPE 0
/* TPG status needs to be enabled to return sendtargets discovery endpoint info */
#define TA_DEFAULT_TPG_ENABLED_SENDTARGETS 1
+/*
+ * Used to control the sending of keys with optional to respond state bit,
+ * as a workaround for non RFC compliant initiators,that do not propose,
+ * nor respond to specific keys required for login to complete.
+ *
+ * See iscsi_check_proposer_for_optional_reply() for more details.
+ */
+#define TA_DEFAULT_LOGIN_KEYS_WORKAROUND 1
#define ISCSI_IOV_DATA_BUFFER 5
@@ -765,6 +773,7 @@ struct iscsi_tpg_attrib {
u8 t10_pi;
u32 fabric_prot_type;
u32 tpg_enabled_sendtargets;
+ u32 login_keys_workaround;
struct iscsi_portal_group *tpg;
};
diff --git a/include/trace/events/sched.h b/include/trace/events/sched.h
index 84f7f2139a91..feffec7b489a 100644
--- a/include/trace/events/sched.h
+++ b/include/trace/events/sched.h
@@ -1698,6 +1698,48 @@ TRACE_EVENT(sched_boost_task,
);
/*
+ * Tracepoint for find_best_target
+ */
+TRACE_EVENT(sched_find_best_target,
+
+ TP_PROTO(struct task_struct *tsk, bool prefer_idle,
+ unsigned long min_util, int start_cpu,
+ int best_idle, int best_active, int target),
+
+ TP_ARGS(tsk, prefer_idle, min_util, start_cpu,
+ best_idle, best_active, target),
+
+ TP_STRUCT__entry(
+ __array( char, comm, TASK_COMM_LEN )
+ __field( pid_t, pid )
+ __field( unsigned long, min_util )
+ __field( bool, prefer_idle )
+ __field( int, start_cpu )
+ __field( int, best_idle )
+ __field( int, best_active )
+ __field( int, target )
+ ),
+
+ TP_fast_assign(
+ memcpy(__entry->comm, tsk->comm, TASK_COMM_LEN);
+ __entry->pid = tsk->pid;
+ __entry->min_util = min_util;
+ __entry->prefer_idle = prefer_idle;
+ __entry->start_cpu = start_cpu;
+ __entry->best_idle = best_idle;
+ __entry->best_active = best_active;
+ __entry->target = target;
+ ),
+
+ TP_printk("pid=%d comm=%s prefer_idle=%d start_cpu=%d "
+ "best_idle=%d best_active=%d target=%d",
+ __entry->pid, __entry->comm,
+ __entry->prefer_idle, __entry->start_cpu,
+ __entry->best_idle, __entry->best_active,
+ __entry->target)
+);
+
+/*
* Tracepoint for accounting sched group energy
*/
TRACE_EVENT(sched_energy_diff,
diff --git a/include/uapi/drm/msm_drm.h b/include/uapi/drm/msm_drm.h
index 8b51873e7b08..a852f2a3701f 100644
--- a/include/uapi/drm/msm_drm.h
+++ b/include/uapi/drm/msm_drm.h
@@ -234,7 +234,7 @@ struct drm_msm_gem_submit_cmd {
__u32 size; /* in, cmdstream size */
__u32 pad;
__u32 nr_relocs; /* in, number of submit_reloc's */
- __u64 __user relocs; /* in, ptr to array of submit_reloc's */
+ __u64 relocs; /* in, ptr to array of submit_reloc's */
};
/* Each buffer referenced elsewhere in the cmdstream submit (ie. the
@@ -274,8 +274,8 @@ struct drm_msm_gem_submit {
__u32 fence; /* out */
__u32 nr_bos; /* in, number of submit_bo's */
__u32 nr_cmds; /* in, number of submit_cmd's */
- __u64 __user bos; /* in, ptr to array of submit_bo's */
- __u64 __user cmds; /* in, ptr to array of submit_cmd's */
+ __u64 bos; /* in, ptr to array of submit_bo's */
+ __u64 cmds; /* in, ptr to array of submit_cmd's */
__s32 fence_fd; /* gap for the fence_fd which is upstream */
__u32 queueid; /* in, submitqueue id */
};
diff --git a/include/uapi/sound/compress_offload.h b/include/uapi/sound/compress_offload.h
index 866ec3d2af69..7845fdd556fa 100644
--- a/include/uapi/sound/compress_offload.h
+++ b/include/uapi/sound/compress_offload.h
@@ -138,6 +138,11 @@ struct snd_compr_audio_info {
#define SNDRV_COMPRESS_CLK_REC_MODE_NONE 0
#define SNDRV_COMPRESS_CLK_REC_MODE_AUTO 1
+enum sndrv_compress_latency_mode {
+ SNDRV_COMPRESS_LEGACY_LATENCY_MODE = 0,
+ SNDRV_COMPRESS_LOW_LATENCY_MODE = 1,
+};
+
/**
* enum sndrv_compress_encoder
* @SNDRV_COMPRESS_ENCODER_PADDING: no of samples appended by the encoder at the
@@ -164,6 +169,7 @@ enum sndrv_compress_encoder {
SNDRV_COMPRESS_START_DELAY = 9,
SNDRV_COMPRESS_ENABLE_ADJUST_SESSION_CLOCK = 10,
SNDRV_COMPRESS_ADJUST_SESSION_CLOCK = 11,
+ SNDRV_COMPRESS_LATENCY_MODE = 12,
};
#define SNDRV_COMPRESS_PATH_DELAY SNDRV_COMPRESS_PATH_DELAY
@@ -174,6 +180,7 @@ enum sndrv_compress_encoder {
#define SNDRV_COMPRESS_ENABLE_ADJUST_SESSION_CLOCK \
SNDRV_COMPRESS_ENABLE_ADJUST_SESSION_CLOCK
#define SNDRV_COMPRESS_ADJUST_SESSION_CLOCK SNDRV_COMPRESS_ADJUST_SESSION_CLOCK
+#define SNDRV_COMPRESS_LATENCY_MODE SNDRV_COMPRESS_LATENCY_MODE
/**
* struct snd_compr_metadata - compressed stream metadata
diff --git a/kernel/events/core.c b/kernel/events/core.c
index 69f8f683138a..87f5d841f796 100644
--- a/kernel/events/core.c
+++ b/kernel/events/core.c
@@ -6600,21 +6600,6 @@ static void perf_log_itrace_start(struct perf_event *event)
perf_output_end(&handle);
}
-static bool sample_is_allowed(struct perf_event *event, struct pt_regs *regs)
-{
- /*
- * Due to interrupt latency (AKA "skid"), we may enter the
- * kernel before taking an overflow, even if the PMU is only
- * counting user events.
- * To avoid leaking information to userspace, we must always
- * reject kernel samples when exclude_kernel is set.
- */
- if (event->attr.exclude_kernel && !user_mode(regs))
- return false;
-
- return true;
-}
-
/*
* Generic event overflow handling, sampling.
*/
@@ -6662,12 +6647,6 @@ static int __perf_event_overflow(struct perf_event *event,
}
/*
- * For security, drop the skid kernel samples if necessary.
- */
- if (!sample_is_allowed(event, regs))
- return ret;
-
- /*
* XXX event_limit might not quite work as expected on inherited
* events
*/
diff --git a/kernel/fork.c b/kernel/fork.c
index 246b8a57a32d..fef4df444f47 100644
--- a/kernel/fork.c
+++ b/kernel/fork.c
@@ -832,8 +832,7 @@ struct mm_struct *mm_access(struct task_struct *task, unsigned int mode)
mm = get_task_mm(task);
if (mm && mm != current->mm &&
- !ptrace_may_access(task, mode) &&
- !capable(CAP_SYS_RESOURCE)) {
+ !ptrace_may_access(task, mode)) {
mmput(mm);
mm = ERR_PTR(-EACCES);
}
diff --git a/kernel/resource.c b/kernel/resource.c
index 4c9835c09dcd..c09d484f7b5f 100644
--- a/kernel/resource.c
+++ b/kernel/resource.c
@@ -105,16 +105,25 @@ static int r_show(struct seq_file *m, void *v)
{
struct resource *root = m->private;
struct resource *r = v, *p;
+ unsigned long long start, end;
int width = root->end < 0x10000 ? 4 : 8;
int depth;
for (depth = 0, p = r; depth < MAX_IORES_LEVEL; depth++, p = p->parent)
if (p->parent == root)
break;
+
+ if (file_ns_capable(m->file, &init_user_ns, CAP_SYS_ADMIN)) {
+ start = r->start;
+ end = r->end;
+ } else {
+ start = end = 0;
+ }
+
seq_printf(m, "%*s%0*llx-%0*llx : %s\n",
depth * 2, "",
- width, (unsigned long long) r->start,
- width, (unsigned long long) r->end,
+ width, start,
+ width, end,
r->name ? r->name : "<BAD>");
return 0;
}
diff --git a/kernel/sched/core.c b/kernel/sched/core.c
index 18f4fb65cd1d..4ecca604e64b 100644
--- a/kernel/sched/core.c
+++ b/kernel/sched/core.c
@@ -9232,11 +9232,20 @@ cpu_cgroup_css_alloc(struct cgroup_subsys_state *parent_css)
if (IS_ERR(tg))
return ERR_PTR(-ENOMEM);
- sched_online_group(tg, parent);
-
return &tg->css;
}
+/* Expose task group only after completing cgroup initialization */
+static int cpu_cgroup_css_online(struct cgroup_subsys_state *css)
+{
+ struct task_group *tg = css_tg(css);
+ struct task_group *parent = css_tg(css->parent);
+
+ if (parent)
+ sched_online_group(tg, parent);
+ return 0;
+}
+
static void cpu_cgroup_css_released(struct cgroup_subsys_state *css)
{
struct task_group *tg = css_tg(css);
@@ -9618,6 +9627,7 @@ static struct cftype cpu_files[] = {
struct cgroup_subsys cpu_cgrp_subsys = {
.css_alloc = cpu_cgroup_css_alloc,
+ .css_online = cpu_cgroup_css_online,
.css_released = cpu_cgroup_css_released,
.css_free = cpu_cgroup_css_free,
.fork = cpu_cgroup_fork,
diff --git a/kernel/sched/fair.c b/kernel/sched/fair.c
index 422438d43d90..853064319b0d 100644
--- a/kernel/sched/fair.c
+++ b/kernel/sched/fair.c
@@ -35,6 +35,8 @@
#include "sched.h"
#include <trace/events/sched.h>
#include "tune.h"
+#include "walt.h"
+
/*
* Targeted preemption latency for CPU-bound tasks:
* (default: 6ms * (1 + ilog(ncpus)), units: nanoseconds)
@@ -6548,9 +6550,11 @@ static int find_new_capacity(struct energy_env *eenv,
return idx;
}
-static int group_idle_state(struct sched_group *sg)
+static int group_idle_state(struct energy_env *eenv, struct sched_group *sg)
{
int i, state = INT_MAX;
+ int src_in_grp, dst_in_grp;
+ long grp_util = 0;
/* Find the shallowest idle state in the sched group. */
for_each_cpu(i, sched_group_cpus(sg))
@@ -6559,6 +6563,54 @@ static int group_idle_state(struct sched_group *sg)
/* Take non-cpuidle idling into account (active idle/arch_cpu_idle()) */
state++;
+ /*
+ * Try to estimate if a deeper idle state is
+ * achievable when we move the task.
+ */
+ for_each_cpu(i, sched_group_cpus(sg))
+ grp_util += cpu_util(i);
+
+ src_in_grp = cpumask_test_cpu(eenv->src_cpu, sched_group_cpus(sg));
+ dst_in_grp = cpumask_test_cpu(eenv->dst_cpu, sched_group_cpus(sg));
+ if (src_in_grp == dst_in_grp) {
+ /* both CPUs under consideration are in the same group or not in
+ * either group, migration should leave idle state the same.
+ */
+ goto end;
+ }
+ /* add or remove util as appropriate to indicate what group util
+ * will be (worst case - no concurrent execution) after moving the task
+ */
+ grp_util += src_in_grp ? -eenv->util_delta : eenv->util_delta;
+
+ if (grp_util <=
+ ((long)sg->sgc->max_capacity * (int)sg->group_weight)) {
+ /* after moving, this group is at most partly
+ * occupied, so it should have some idle time.
+ */
+ int max_idle_state_idx = sg->sge->nr_idle_states - 2;
+ int new_state = grp_util * max_idle_state_idx;
+ if (grp_util <= 0)
+ /* group will have no util, use lowest state */
+ new_state = max_idle_state_idx + 1;
+ else {
+ /* for partially idle, linearly map util to idle
+ * states, excluding the lowest one. This does not
+ * correspond to the state we expect to enter in
+ * reality, but an indication of what might happen.
+ */
+ new_state = min(max_idle_state_idx, (int)
+ (new_state / sg->sgc->max_capacity));
+ new_state = max_idle_state_idx - new_state;
+ }
+ state = new_state;
+ } else {
+ /* After moving, the group will be fully occupied
+ * so assume it will not be idle at all.
+ */
+ state = 0;
+ }
+end:
return state;
}
@@ -6631,8 +6683,9 @@ static int sched_group_energy(struct energy_env *eenv)
}
}
- idle_idx = group_idle_state(sg);
+ idle_idx = group_idle_state(eenv, sg);
group_util = group_norm_util(eenv, sg);
+
sg_busy_energy = (group_util * sg->sge->cap_states[cap_idx].power)
>> SCHED_CAPACITY_SHIFT;
sg_idle_energy = ((SCHED_LOAD_SCALE-group_util)
@@ -7337,48 +7390,59 @@ static int start_cpu(bool boosted)
return boosted ? rd->max_cap_orig_cpu : rd->min_cap_orig_cpu;
}
-static inline int find_best_target(struct task_struct *p, bool boosted, bool prefer_idle)
+static inline int find_best_target(struct task_struct *p, int *backup_cpu,
+ bool boosted, bool prefer_idle)
{
- int target_cpu = -1;
- unsigned long target_util = prefer_idle ? ULONG_MAX : 0;
- unsigned long backup_capacity = ULONG_MAX;
- int best_idle_cpu = -1;
- int best_idle_cstate = INT_MAX;
- int backup_cpu = -1;
+ unsigned long best_idle_min_cap_orig = ULONG_MAX;
unsigned long min_util = boosted_task_util(p);
+ unsigned long target_capacity = ULONG_MAX;
+ unsigned long min_wake_util = ULONG_MAX;
+ unsigned long target_max_spare_cap = 0;
+ unsigned long target_util = ULONG_MAX;
+ unsigned long best_active_util = ULONG_MAX;
+ int best_idle_cstate = INT_MAX;
struct sched_domain *sd;
struct sched_group *sg;
- int cpu = start_cpu(boosted);
+ int best_active_cpu = -1;
+ int best_idle_cpu = -1;
+ int target_cpu = -1;
+ int cpu, i;
+
+ *backup_cpu = -1;
schedstat_inc(p, se.statistics.nr_wakeups_fbt_attempts);
schedstat_inc(this_rq(), eas_stats.fbt_attempts);
+ /* Find start CPU based on boost value */
+ cpu = start_cpu(boosted);
if (cpu < 0) {
schedstat_inc(p, se.statistics.nr_wakeups_fbt_no_cpu);
schedstat_inc(this_rq(), eas_stats.fbt_no_cpu);
- return target_cpu;
+ return -1;
}
+ /* Find SD for the start CPU */
sd = rcu_dereference(per_cpu(sd_ea, cpu));
-
if (!sd) {
schedstat_inc(p, se.statistics.nr_wakeups_fbt_no_sd);
schedstat_inc(this_rq(), eas_stats.fbt_no_sd);
- return target_cpu;
+ return -1;
}
+ /* Scan CPUs in all SDs */
sg = sd->groups;
-
do {
- int i;
-
for_each_cpu_and(i, tsk_cpus_allowed(p), sched_group_cpus(sg)) {
- unsigned long cur_capacity, new_util, wake_util;
- unsigned long min_wake_util = ULONG_MAX;
+ unsigned long capacity_curr = capacity_curr_of(i);
+ unsigned long capacity_orig = capacity_orig_of(i);
+ unsigned long wake_util, new_util;
if (!cpu_online(i))
continue;
+ if (walt_cpu_high_irqload(i))
+ continue;
+
/*
* p's blocked utilization is still accounted for on prev_cpu
* so prev_cpu will receive a negative bias due to the double
@@ -7393,65 +7457,204 @@ static inline int find_best_target(struct task_struct *p, bool boosted, bool pre
* than the one required to boost the task.
*/
new_util = max(min_util, new_util);
-
- if (new_util > capacity_orig_of(i))
+ if (new_util > capacity_orig)
continue;
/*
- * Unconditionally favoring tasks that prefer idle cpus to
+ * Case A) Latency sensitive tasks
+ *
+ * Unconditionally favoring tasks that prefer idle CPU to
* improve latency.
+ *
+ * Looking for:
+ * - an idle CPU, whatever its idle_state is, since
+ * the first CPUs we explore are more likely to be
+ * reserved for latency sensitive tasks.
+ * - a non idle CPU where the task fits in its current
+ * capacity and has the maximum spare capacity.
+ * - a non idle CPU with lower contention from other
+ * tasks and running at the lowest possible OPP.
+ *
+ * The last two goals tries to favor a non idle CPU
+ * where the task can run as if it is "almost alone".
+ * A maximum spare capacity CPU is favoured since
+ * the task already fits into that CPU's capacity
+ * without waiting for an OPP chance.
+ *
+ * The following code path is the only one in the CPUs
+ * exploration loop which is always used by
+ * prefer_idle tasks. It exits the loop with wither a
+ * best_active_cpu or a target_cpu which should
+ * represent an optimal choice for latency sensitive
+ * tasks.
*/
- if (idle_cpu(i) && prefer_idle) {
- schedstat_inc(p, se.statistics.nr_wakeups_fbt_pref_idle);
- schedstat_inc(this_rq(), eas_stats.fbt_pref_idle);
- return i;
- }
+ if (prefer_idle) {
- cur_capacity = capacity_curr_of(i);
-
- if (new_util < cur_capacity) {
- if (cpu_rq(i)->nr_running) {
- /*
- * Find a target cpu with the lowest/highest
- * utilization if prefer_idle/!prefer_idle.
- */
- if (prefer_idle) {
- /* Favor the CPU that last ran the task */
- if (new_util > target_util ||
- wake_util > min_wake_util)
- continue;
- min_wake_util = wake_util;
- target_util = new_util;
- target_cpu = i;
- } else if (target_util < new_util) {
- target_util = new_util;
- target_cpu = i;
- }
- } else if (!prefer_idle) {
- int idle_idx = idle_get_state_idx(cpu_rq(i));
+ /*
+ * Case A.1: IDLE CPU
+ * Return the first IDLE CPU we find.
+ */
+ if (idle_cpu(i)) {
+ schedstat_inc(p, se.statistics.nr_wakeups_fbt_pref_idle);
+ schedstat_inc(this_rq(), eas_stats.fbt_pref_idle);
- if (best_idle_cpu < 0 ||
- (sysctl_sched_cstate_aware &&
- best_idle_cstate > idle_idx)) {
- best_idle_cstate = idle_idx;
- best_idle_cpu = i;
- }
+ trace_sched_find_best_target(p,
+ prefer_idle, min_util,
+ cpu, best_idle_cpu,
+ best_active_cpu, i);
+
+ return i;
}
- } else if (backup_capacity > cur_capacity) {
- /* Find a backup cpu with least capacity. */
- backup_capacity = cur_capacity;
- backup_cpu = i;
+
+ /*
+ * Case A.2: Target ACTIVE CPU
+ * Favor CPUs with max spare capacity.
+ */
+ if ((capacity_curr > new_util) &&
+ (capacity_orig - new_util > target_max_spare_cap)) {
+ target_max_spare_cap = capacity_orig - new_util;
+ target_cpu = i;
+ continue;
+ }
+ if (target_cpu != -1)
+ continue;
+
+
+ /*
+ * Case A.3: Backup ACTIVE CPU
+ * Favor CPUs with:
+ * - lower utilization due to other tasks
+ * - lower utilization with the task in
+ */
+ if (wake_util > min_wake_util)
+ continue;
+ if (new_util > best_active_util)
+ continue;
+ min_wake_util = wake_util;
+ best_active_util = new_util;
+ best_active_cpu = i;
+ continue;
}
+
+ /*
+ * Case B) Non latency sensitive tasks on IDLE CPUs.
+ *
+ * Find an optimal backup IDLE CPU for non latency
+ * sensitive tasks.
+ *
+ * Looking for:
+ * - minimizing the capacity_orig,
+ * i.e. preferring LITTLE CPUs
+ * - favoring shallowest idle states
+ * i.e. avoid to wakeup deep-idle CPUs
+ *
+ * The following code path is used by non latency
+ * sensitive tasks if IDLE CPUs are available. If at
+ * least one of such CPUs are available it sets the
+ * best_idle_cpu to the most suitable idle CPU to be
+ * selected.
+ *
+ * If idle CPUs are available, favour these CPUs to
+ * improve performances by spreading tasks.
+ * Indeed, the energy_diff() computed by the caller
+ * will take care to ensure the minimization of energy
+ * consumptions without affecting performance.
+ */
+ if (idle_cpu(i)) {
+ int idle_idx = idle_get_state_idx(cpu_rq(i));
+
+ /* Select idle CPU with lower cap_orig */
+ if (capacity_orig > best_idle_min_cap_orig)
+ continue;
+
+ /*
+ * Skip CPUs in deeper idle state, but only
+ * if they are also less energy efficient.
+ * IOW, prefer a deep IDLE LITTLE CPU vs a
+ * shallow idle big CPU.
+ */
+ if (sysctl_sched_cstate_aware &&
+ best_idle_cstate <= idle_idx)
+ continue;
+
+ /* Keep track of best idle CPU */
+ best_idle_min_cap_orig = capacity_orig;
+ best_idle_cstate = idle_idx;
+ best_idle_cpu = i;
+ continue;
+ }
+
+ /*
+ * Case C) Non latency sensitive tasks on ACTIVE CPUs.
+ *
+ * Pack tasks in the most energy efficient capacities.
+ *
+ * This task packing strategy prefers more energy
+ * efficient CPUs (i.e. pack on smaller maximum
+ * capacity CPUs) while also trying to spread tasks to
+ * run them all at the lower OPP.
+ *
+ * This assumes for example that it's more energy
+ * efficient to run two tasks on two CPUs at a lower
+ * OPP than packing both on a single CPU but running
+ * that CPU at an higher OPP.
+ *
+ * Thus, this case keep track of the CPU with the
+ * smallest maximum capacity and highest spare maximum
+ * capacity.
+ */
+
+ /* Favor CPUs with smaller capacity */
+ if (capacity_orig > target_capacity)
+ continue;
+
+ /* Favor CPUs with maximum spare capacity */
+ if ((capacity_orig - new_util) < target_max_spare_cap)
+ continue;
+
+ target_max_spare_cap = capacity_orig - new_util;
+ target_capacity = capacity_orig;
+ target_util = new_util;
+ target_cpu = i;
}
+
} while (sg = sg->next, sg != sd->groups);
- if (target_cpu < 0)
- target_cpu = best_idle_cpu >= 0 ? best_idle_cpu : backup_cpu;
+ /*
+ * For non latency sensitive tasks, cases B and C in the previous loop,
+ * we pick the best IDLE CPU only if we was not able to find a target
+ * ACTIVE CPU.
+ *
+ * Policies priorities:
+ *
+ * - prefer_idle tasks:
+ *
+ * a) IDLE CPU available, we return immediately
+ * b) ACTIVE CPU where task fits and has the bigger maximum spare
+ * capacity (i.e. target_cpu)
+ * c) ACTIVE CPU with less contention due to other tasks
+ * (i.e. best_active_cpu)
+ *
+ * - NON prefer_idle tasks:
+ *
+ * a) ACTIVE CPU: target_cpu
+ * b) IDLE CPU: best_idle_cpu
+ */
+ if (target_cpu == -1)
+ target_cpu = prefer_idle
+ ? best_active_cpu
+ : best_idle_cpu;
+ else
+ *backup_cpu = prefer_idle
+ ? best_active_cpu
+ : best_idle_cpu;
- if (target_cpu >= 0) {
- schedstat_inc(p, se.statistics.nr_wakeups_fbt_count);
- schedstat_inc(this_rq(), eas_stats.fbt_count);
- }
+ trace_sched_find_best_target(p, prefer_idle, min_util, cpu,
+ best_idle_cpu, best_active_cpu,
+ target_cpu);
+
+ schedstat_inc(p, se.statistics.nr_wakeups_fbt_count);
+ schedstat_inc(this_rq(), eas_stats.fbt_count);
return target_cpu;
}
@@ -7483,7 +7686,7 @@ static int wake_cap(struct task_struct *p, int cpu, int prev_cpu)
static int select_energy_cpu_brute(struct task_struct *p, int prev_cpu, int sync)
{
struct sched_domain *sd;
- int target_cpu = prev_cpu, tmp_target;
+ int target_cpu = prev_cpu, tmp_target, tmp_backup;
bool boosted, prefer_idle;
schedstat_inc(p, se.statistics.nr_wakeups_secb_attempts);
@@ -7508,9 +7711,11 @@ static int select_energy_cpu_brute(struct task_struct *p, int prev_cpu, int sync
prefer_idle = 0;
#endif
+ sync_entity_load_avg(&p->se);
+
sd = rcu_dereference(per_cpu(sd_ea, prev_cpu));
/* Find a cpu with sufficient capacity */
- tmp_target = find_best_target(p, boosted, prefer_idle);
+ tmp_target = find_best_target(p, &tmp_backup, boosted, prefer_idle);
if (!sd)
goto unlock;
@@ -7539,10 +7744,15 @@ static int select_energy_cpu_brute(struct task_struct *p, int prev_cpu, int sync
}
if (energy_diff(&eenv) >= 0) {
- schedstat_inc(p, se.statistics.nr_wakeups_secb_no_nrg_sav);
- schedstat_inc(this_rq(), eas_stats.secb_no_nrg_sav);
- target_cpu = prev_cpu;
- goto unlock;
+ /* No energy saving for target_cpu, try backup */
+ target_cpu = tmp_backup;
+ eenv.dst_cpu = target_cpu;
+ if (tmp_backup < 0 || energy_diff(&eenv) >= 0) {
+ schedstat_inc(p, se.statistics.nr_wakeups_secb_no_nrg_sav);
+ schedstat_inc(this_rq(), eas_stats.secb_no_nrg_sav);
+ target_cpu = prev_cpu;
+ goto unlock;
+ }
}
schedstat_inc(p, se.statistics.nr_wakeups_secb_nrg_sav);
@@ -7584,16 +7794,9 @@ select_task_rq_fair(struct task_struct *p, int prev_cpu, int sd_flag, int wake_f
return select_best_cpu(p, prev_cpu, 0, sync);
#endif
- if (sd_flag & SD_BALANCE_WAKE) {
- /*
- * do wake_cap unconditionally as it causes task and cpu
- * utilization to be synced, and we need that for energy
- * aware wakeups
- */
- int _wake_cap = wake_cap(p, cpu, prev_cpu);
- want_affine = !wake_wide(p) && !_wake_cap
+ if (sd_flag & SD_BALANCE_WAKE)
+ want_affine = !wake_wide(p) && !wake_cap(p, cpu, prev_cpu)
&& cpumask_test_cpu(cpu, tsk_cpus_allowed(p));
- }
if (energy_aware() && !(cpu_rq(prev_cpu)->rd->overutilized))
return select_energy_cpu_brute(p, prev_cpu, sync);
@@ -9189,6 +9392,38 @@ group_type group_classify(struct sched_group *group,
return group_other;
}
+#ifdef CONFIG_NO_HZ_COMMON
+/*
+ * idle load balancing data
+ * - used by the nohz balance, but we want it available here
+ * so that we can see which CPUs have no tick.
+ */
+static struct {
+ cpumask_var_t idle_cpus_mask;
+ atomic_t nr_cpus;
+ unsigned long next_balance; /* in jiffy units */
+} nohz ____cacheline_aligned;
+
+static inline void update_cpu_stats_if_tickless(struct rq *rq)
+{
+ /* only called from update_sg_lb_stats when irqs are disabled */
+ if (cpumask_test_cpu(rq->cpu, nohz.idle_cpus_mask)) {
+ /* rate limit updates to once-per-jiffie at most */
+ if (READ_ONCE(jiffies) <= rq->last_load_update_tick)
+ return;
+
+ raw_spin_lock(&rq->lock);
+ update_rq_clock(rq);
+ update_idle_cpu_load(rq);
+ update_cfs_rq_load_avg(rq->clock_task, &rq->cfs, false);
+ raw_spin_unlock(&rq->lock);
+ }
+}
+
+#else
+static inline void update_cpu_stats_if_tickless(struct rq *rq) { }
+#endif
+
/**
* update_sg_lb_stats - Update sched_group's statistics for load balancing.
* @env: The load balancing environment.
@@ -9220,6 +9455,12 @@ static inline void update_sg_lb_stats(struct lb_env *env,
if (cpu_isolated(i))
continue;
+ /* if we are entering idle and there are CPUs with
+ * their tick stopped, do an update for them
+ */
+ if (env->idle == CPU_NEWLY_IDLE)
+ update_cpu_stats_if_tickless(rq);
+
/* Bias balancing toward cpus of our domain */
if (local_group)
load = target_load(i, load_idx);
@@ -10680,11 +10921,6 @@ static inline int on_null_domain(struct rq *rq)
* needed, they will kick the idle load balancer, which then does idle
* load balancing for all the idle CPUs.
*/
-static struct {
- cpumask_var_t idle_cpus_mask;
- atomic_t nr_cpus;
- unsigned long next_balance; /* in jiffy units */
-} nohz ____cacheline_aligned;
#ifdef CONFIG_SCHED_HMP
static inline int find_new_hmp_ilb(int type)
@@ -11111,6 +11347,10 @@ static inline int _nohz_kick_needed(struct rq *rq, int cpu, int *type)
(!energy_aware() || cpu_overutilized(cpu)))
return true;
+ /* Do idle load balance if there have misfit task */
+ if (energy_aware() && rq->misfit_task)
+ return 1;
+
return (rq->nr_running >= 2);
}
diff --git a/kernel/sched/walt.h b/kernel/sched/walt.h
index e181c87a928d..f56c4da16d0b 100644
--- a/kernel/sched/walt.h
+++ b/kernel/sched/walt.h
@@ -55,6 +55,8 @@ static inline void walt_migrate_sync_cpu(int cpu) { }
static inline void walt_init_cpu_efficiency(void) { }
static inline u64 walt_ktime_clock(void) { return 0; }
+#define walt_cpu_high_irqload(cpu) false
+
#endif /* CONFIG_SCHED_WALT */
extern unsigned int walt_disabled;
diff --git a/kernel/time/alarmtimer.c b/kernel/time/alarmtimer.c
index 1a4de0022cc5..ceec77c652b5 100644
--- a/kernel/time/alarmtimer.c
+++ b/kernel/time/alarmtimer.c
@@ -848,7 +848,8 @@ static int alarm_timer_set(struct k_itimer *timr, int flags,
* Rate limit to the tick as a hot fix to prevent DOS. Will be
* mopped up later.
*/
- if (ktime_to_ns(timr->it.alarm.interval) < TICK_NSEC)
+ if (timr->it.alarm.interval.tv64 &&
+ ktime_to_ns(timr->it.alarm.interval) < TICK_NSEC)
timr->it.alarm.interval = ktime_set(0, TICK_NSEC);
exp = timespec_to_ktime(new_setting->it_value);
diff --git a/kernel/trace/ftrace.c b/kernel/trace/ftrace.c
index 34b2a0d5cf1a..eba904bae48c 100644
--- a/kernel/trace/ftrace.c
+++ b/kernel/trace/ftrace.c
@@ -3535,7 +3535,7 @@ match_records(struct ftrace_hash *hash, char *func, int len, char *mod)
int exclude_mod = 0;
int found = 0;
int ret;
- int clear_filter;
+ int clear_filter = 0;
if (func) {
func_g.type = filter_parse_regex(func, len, &func_g.search,
diff --git a/kernel/trace/trace.c b/kernel/trace/trace.c
index ed700960e7e0..930f68598e9c 100644
--- a/kernel/trace/trace.c
+++ b/kernel/trace/trace.c
@@ -6836,6 +6836,7 @@ static int instance_rmdir(const char *name)
}
kfree(tr->topts);
+ free_cpumask_var(tr->tracing_cpumask);
kfree(tr->name);
kfree(tr);
diff --git a/net/8021q/vlan.c b/net/8021q/vlan.c
index e20ae2d3c498..5e4199d5a388 100644
--- a/net/8021q/vlan.c
+++ b/net/8021q/vlan.c
@@ -292,6 +292,10 @@ static void vlan_sync_address(struct net_device *dev,
if (ether_addr_equal(vlan->real_dev_addr, dev->dev_addr))
return;
+ /* vlan continues to inherit address of lower device */
+ if (vlan_dev_inherit_address(vlandev, dev))
+ goto out;
+
/* vlan address was different from the old address and is equal to
* the new address */
if (!ether_addr_equal(vlandev->dev_addr, vlan->real_dev_addr) &&
@@ -304,6 +308,7 @@ static void vlan_sync_address(struct net_device *dev,
!ether_addr_equal(vlandev->dev_addr, dev->dev_addr))
dev_uc_add(dev, vlandev->dev_addr);
+out:
ether_addr_copy(vlan->real_dev_addr, dev->dev_addr);
}
diff --git a/net/8021q/vlan.h b/net/8021q/vlan.h
index 9d010a09ab98..cc1557978066 100644
--- a/net/8021q/vlan.h
+++ b/net/8021q/vlan.h
@@ -109,6 +109,8 @@ int vlan_check_real_dev(struct net_device *real_dev,
void vlan_setup(struct net_device *dev);
int register_vlan_dev(struct net_device *dev);
void unregister_vlan_dev(struct net_device *dev, struct list_head *head);
+bool vlan_dev_inherit_address(struct net_device *dev,
+ struct net_device *real_dev);
static inline u32 vlan_get_ingress_priority(struct net_device *dev,
u16 vlan_tci)
diff --git a/net/8021q/vlan_dev.c b/net/8021q/vlan_dev.c
index fded86508117..ca4dc9031073 100644
--- a/net/8021q/vlan_dev.c
+++ b/net/8021q/vlan_dev.c
@@ -244,6 +244,17 @@ void vlan_dev_get_realdev_name(const struct net_device *dev, char *result)
strncpy(result, vlan_dev_priv(dev)->real_dev->name, 23);
}
+bool vlan_dev_inherit_address(struct net_device *dev,
+ struct net_device *real_dev)
+{
+ if (dev->addr_assign_type != NET_ADDR_STOLEN)
+ return false;
+
+ ether_addr_copy(dev->dev_addr, real_dev->dev_addr);
+ call_netdevice_notifiers(NETDEV_CHANGEADDR, dev);
+ return true;
+}
+
static int vlan_dev_open(struct net_device *dev)
{
struct vlan_dev_priv *vlan = vlan_dev_priv(dev);
@@ -254,7 +265,8 @@ static int vlan_dev_open(struct net_device *dev)
!(vlan->flags & VLAN_FLAG_LOOSE_BINDING))
return -ENETDOWN;
- if (!ether_addr_equal(dev->dev_addr, real_dev->dev_addr)) {
+ if (!ether_addr_equal(dev->dev_addr, real_dev->dev_addr) &&
+ !vlan_dev_inherit_address(dev, real_dev)) {
err = dev_uc_add(real_dev, dev->dev_addr);
if (err < 0)
goto out;
@@ -558,8 +570,10 @@ static int vlan_dev_init(struct net_device *dev)
/* ipv6 shared card related stuff */
dev->dev_id = real_dev->dev_id;
- if (is_zero_ether_addr(dev->dev_addr))
- eth_hw_addr_inherit(dev, real_dev);
+ if (is_zero_ether_addr(dev->dev_addr)) {
+ ether_addr_copy(dev->dev_addr, real_dev->dev_addr);
+ dev->addr_assign_type = NET_ADDR_STOLEN;
+ }
if (is_zero_ether_addr(dev->broadcast))
memcpy(dev->broadcast, real_dev->broadcast, dev->addr_len);
diff --git a/net/bluetooth/smp.c b/net/bluetooth/smp.c
index 6f2c704e41ab..b166b3e441a5 100644
--- a/net/bluetooth/smp.c
+++ b/net/bluetooth/smp.c
@@ -23,6 +23,7 @@
#include <linux/debugfs.h>
#include <linux/crypto.h>
#include <linux/scatterlist.h>
+#include <crypto/algapi.h>
#include <crypto/b128ops.h>
#include <net/bluetooth/bluetooth.h>
@@ -524,7 +525,7 @@ bool smp_irk_matches(struct hci_dev *hdev, const u8 irk[16],
if (err)
return false;
- return !memcmp(bdaddr->b, hash, 3);
+ return !crypto_memneq(bdaddr->b, hash, 3);
}
int smp_generate_rpa(struct hci_dev *hdev, const u8 irk[16], bdaddr_t *rpa)
@@ -577,7 +578,7 @@ int smp_generate_oob(struct hci_dev *hdev, u8 hash[16], u8 rand[16])
/* This is unlikely, but we need to check that
* we didn't accidentially generate a debug key.
*/
- if (memcmp(smp->local_sk, debug_sk, 32))
+ if (crypto_memneq(smp->local_sk, debug_sk, 32))
break;
}
smp->debug_key = false;
@@ -991,7 +992,7 @@ static u8 smp_random(struct smp_chan *smp)
if (ret)
return SMP_UNSPECIFIED;
- if (memcmp(smp->pcnf, confirm, sizeof(smp->pcnf)) != 0) {
+ if (crypto_memneq(smp->pcnf, confirm, sizeof(smp->pcnf))) {
BT_ERR("Pairing failed (confirmation values mismatch)");
return SMP_CONFIRM_FAILED;
}
@@ -1491,7 +1492,7 @@ static u8 sc_passkey_round(struct smp_chan *smp, u8 smp_op)
smp->rrnd, r, cfm))
return SMP_UNSPECIFIED;
- if (memcmp(smp->pcnf, cfm, 16))
+ if (crypto_memneq(smp->pcnf, cfm, 16))
return SMP_CONFIRM_FAILED;
smp->passkey_round++;
@@ -1875,7 +1876,7 @@ static u8 sc_send_public_key(struct smp_chan *smp)
/* This is unlikely, but we need to check that
* we didn't accidentially generate a debug key.
*/
- if (memcmp(smp->local_sk, debug_sk, 32))
+ if (crypto_memneq(smp->local_sk, debug_sk, 32))
break;
}
}
@@ -2140,7 +2141,7 @@ static u8 smp_cmd_pairing_random(struct l2cap_conn *conn, struct sk_buff *skb)
if (err)
return SMP_UNSPECIFIED;
- if (memcmp(smp->pcnf, cfm, 16))
+ if (crypto_memneq(smp->pcnf, cfm, 16))
return SMP_CONFIRM_FAILED;
} else {
smp_send_cmd(conn, SMP_CMD_PAIRING_RANDOM, sizeof(smp->prnd),
@@ -2621,7 +2622,7 @@ static int smp_cmd_public_key(struct l2cap_conn *conn, struct sk_buff *skb)
if (err)
return SMP_UNSPECIFIED;
- if (memcmp(cfm.confirm_val, smp->pcnf, 16))
+ if (crypto_memneq(cfm.confirm_val, smp->pcnf, 16))
return SMP_CONFIRM_FAILED;
}
@@ -2654,7 +2655,7 @@ static int smp_cmd_public_key(struct l2cap_conn *conn, struct sk_buff *skb)
else
hcon->pending_sec_level = BT_SECURITY_FIPS;
- if (!memcmp(debug_pk, smp->remote_pk, 64))
+ if (!crypto_memneq(debug_pk, smp->remote_pk, 64))
set_bit(SMP_FLAG_DEBUG_KEY, &smp->flags);
if (smp->method == DSP_PASSKEY) {
@@ -2753,7 +2754,7 @@ static int smp_cmd_dhkey_check(struct l2cap_conn *conn, struct sk_buff *skb)
if (err)
return SMP_UNSPECIFIED;
- if (memcmp(check->e, e, 16))
+ if (crypto_memneq(check->e, e, 16))
return SMP_DHKEY_CHECK_FAILED;
if (!hcon->out) {
@@ -3463,7 +3464,7 @@ static int __init test_ah(struct crypto_blkcipher *tfm_aes)
if (err)
return err;
- if (memcmp(res, exp, 3))
+ if (crypto_memneq(res, exp, 3))
return -EINVAL;
return 0;
@@ -3493,7 +3494,7 @@ static int __init test_c1(struct crypto_blkcipher *tfm_aes)
if (err)
return err;
- if (memcmp(res, exp, 16))
+ if (crypto_memneq(res, exp, 16))
return -EINVAL;
return 0;
@@ -3518,7 +3519,7 @@ static int __init test_s1(struct crypto_blkcipher *tfm_aes)
if (err)
return err;
- if (memcmp(res, exp, 16))
+ if (crypto_memneq(res, exp, 16))
return -EINVAL;
return 0;
@@ -3550,7 +3551,7 @@ static int __init test_f4(struct crypto_hash *tfm_cmac)
if (err)
return err;
- if (memcmp(res, exp, 16))
+ if (crypto_memneq(res, exp, 16))
return -EINVAL;
return 0;
@@ -3584,10 +3585,10 @@ static int __init test_f5(struct crypto_hash *tfm_cmac)
if (err)
return err;
- if (memcmp(mackey, exp_mackey, 16))
+ if (crypto_memneq(mackey, exp_mackey, 16))
return -EINVAL;
- if (memcmp(ltk, exp_ltk, 16))
+ if (crypto_memneq(ltk, exp_ltk, 16))
return -EINVAL;
return 0;
@@ -3620,7 +3621,7 @@ static int __init test_f6(struct crypto_hash *tfm_cmac)
if (err)
return err;
- if (memcmp(res, exp, 16))
+ if (crypto_memneq(res, exp, 16))
return -EINVAL;
return 0;
@@ -3674,7 +3675,7 @@ static int __init test_h6(struct crypto_hash *tfm_cmac)
if (err)
return err;
- if (memcmp(res, exp, 16))
+ if (crypto_memneq(res, exp, 16))
return -EINVAL;
return 0;
diff --git a/net/core/dev.c b/net/core/dev.c
index 1b7fb54d5d9a..1ce844e41eaf 100644
--- a/net/core/dev.c
+++ b/net/core/dev.c
@@ -2552,9 +2552,10 @@ EXPORT_SYMBOL(skb_mac_gso_segment);
static inline bool skb_needs_check(struct sk_buff *skb, bool tx_path)
{
if (tx_path)
- return skb->ip_summed != CHECKSUM_PARTIAL;
- else
- return skb->ip_summed == CHECKSUM_NONE;
+ return skb->ip_summed != CHECKSUM_PARTIAL &&
+ skb->ip_summed != CHECKSUM_NONE;
+
+ return skb->ip_summed == CHECKSUM_NONE;
}
/**
@@ -2573,11 +2574,12 @@ static inline bool skb_needs_check(struct sk_buff *skb, bool tx_path)
struct sk_buff *__skb_gso_segment(struct sk_buff *skb,
netdev_features_t features, bool tx_path)
{
+ struct sk_buff *segs;
+
if (unlikely(skb_needs_check(skb, tx_path))) {
int err;
- skb_warn_bad_offload(skb);
-
+ /* We're going to init ->check field in TCP or UDP header */
err = skb_cow_head(skb, 0);
if (err < 0)
return ERR_PTR(err);
@@ -2592,7 +2594,12 @@ struct sk_buff *__skb_gso_segment(struct sk_buff *skb,
skb_reset_mac_header(skb);
skb_reset_mac_len(skb);
- return skb_mac_gso_segment(skb, features);
+ segs = skb_mac_gso_segment(skb, features);
+
+ if (unlikely(skb_needs_check(skb, tx_path)))
+ skb_warn_bad_offload(skb);
+
+ return segs;
}
EXPORT_SYMBOL(__skb_gso_segment);
diff --git a/net/ipv6/ip6_output.c b/net/ipv6/ip6_output.c
index 72b53b83a720..6177acdf60ac 100644
--- a/net/ipv6/ip6_output.c
+++ b/net/ipv6/ip6_output.c
@@ -1360,7 +1360,7 @@ emsgsize:
*/
cork->length += length;
- if (((length > mtu) ||
+ if ((((length + fragheaderlen) > mtu) ||
(skb && skb_is_gso(skb))) &&
(sk->sk_protocol == IPPROTO_UDP) &&
(rt->dst.dev->features & NETIF_F_UFO) &&
diff --git a/net/key/af_key.c b/net/key/af_key.c
index e67c28e614b9..2e1050ec2cf0 100644
--- a/net/key/af_key.c
+++ b/net/key/af_key.c
@@ -63,8 +63,13 @@ struct pfkey_sock {
} u;
struct sk_buff *skb;
} dump;
+ struct mutex dump_lock;
};
+static int parse_sockaddr_pair(struct sockaddr *sa, int ext_len,
+ xfrm_address_t *saddr, xfrm_address_t *daddr,
+ u16 *family);
+
static inline struct pfkey_sock *pfkey_sk(struct sock *sk)
{
return (struct pfkey_sock *)sk;
@@ -139,6 +144,7 @@ static int pfkey_create(struct net *net, struct socket *sock, int protocol,
{
struct netns_pfkey *net_pfkey = net_generic(net, pfkey_net_id);
struct sock *sk;
+ struct pfkey_sock *pfk;
int err;
if (!ns_capable(net->user_ns, CAP_NET_ADMIN))
@@ -153,6 +159,9 @@ static int pfkey_create(struct net *net, struct socket *sock, int protocol,
if (sk == NULL)
goto out;
+ pfk = pfkey_sk(sk);
+ mutex_init(&pfk->dump_lock);
+
sock->ops = &pfkey_ops;
sock_init_data(sock, sk);
@@ -281,13 +290,23 @@ static int pfkey_do_dump(struct pfkey_sock *pfk)
struct sadb_msg *hdr;
int rc;
+ mutex_lock(&pfk->dump_lock);
+ if (!pfk->dump.dump) {
+ rc = 0;
+ goto out;
+ }
+
rc = pfk->dump.dump(pfk);
- if (rc == -ENOBUFS)
- return 0;
+ if (rc == -ENOBUFS) {
+ rc = 0;
+ goto out;
+ }
if (pfk->dump.skb) {
- if (!pfkey_can_dump(&pfk->sk))
- return 0;
+ if (!pfkey_can_dump(&pfk->sk)) {
+ rc = 0;
+ goto out;
+ }
hdr = (struct sadb_msg *) pfk->dump.skb->data;
hdr->sadb_msg_seq = 0;
@@ -298,6 +317,9 @@ static int pfkey_do_dump(struct pfkey_sock *pfk)
}
pfkey_terminate_dump(pfk);
+
+out:
+ mutex_unlock(&pfk->dump_lock);
return rc;
}
@@ -1802,19 +1824,26 @@ static int pfkey_dump(struct sock *sk, struct sk_buff *skb, const struct sadb_ms
struct xfrm_address_filter *filter = NULL;
struct pfkey_sock *pfk = pfkey_sk(sk);
- if (pfk->dump.dump != NULL)
+ mutex_lock(&pfk->dump_lock);
+ if (pfk->dump.dump != NULL) {
+ mutex_unlock(&pfk->dump_lock);
return -EBUSY;
+ }
proto = pfkey_satype2proto(hdr->sadb_msg_satype);
- if (proto == 0)
+ if (proto == 0) {
+ mutex_unlock(&pfk->dump_lock);
return -EINVAL;
+ }
if (ext_hdrs[SADB_X_EXT_FILTER - 1]) {
struct sadb_x_filter *xfilter = ext_hdrs[SADB_X_EXT_FILTER - 1];
filter = kmalloc(sizeof(*filter), GFP_KERNEL);
- if (filter == NULL)
+ if (filter == NULL) {
+ mutex_unlock(&pfk->dump_lock);
return -ENOMEM;
+ }
memcpy(&filter->saddr, &xfilter->sadb_x_filter_saddr,
sizeof(xfrm_address_t));
@@ -1830,6 +1859,7 @@ static int pfkey_dump(struct sock *sk, struct sk_buff *skb, const struct sadb_ms
pfk->dump.dump = pfkey_dump_sa;
pfk->dump.done = pfkey_dump_sa_done;
xfrm_state_walk_init(&pfk->dump.u.state, proto, filter);
+ mutex_unlock(&pfk->dump_lock);
return pfkey_do_dump(pfk);
}
@@ -1922,19 +1952,14 @@ parse_ipsecrequest(struct xfrm_policy *xp, struct sadb_x_ipsecrequest *rq)
/* addresses present only in tunnel mode */
if (t->mode == XFRM_MODE_TUNNEL) {
- u8 *sa = (u8 *) (rq + 1);
- int family, socklen;
+ int err;
- family = pfkey_sockaddr_extract((struct sockaddr *)sa,
- &t->saddr);
- if (!family)
- return -EINVAL;
-
- socklen = pfkey_sockaddr_len(family);
- if (pfkey_sockaddr_extract((struct sockaddr *)(sa + socklen),
- &t->id.daddr) != family)
- return -EINVAL;
- t->encap_family = family;
+ err = parse_sockaddr_pair(
+ (struct sockaddr *)(rq + 1),
+ rq->sadb_x_ipsecrequest_len - sizeof(*rq),
+ &t->saddr, &t->id.daddr, &t->encap_family);
+ if (err)
+ return err;
} else
t->encap_family = xp->family;
@@ -1954,7 +1979,11 @@ parse_ipsecrequests(struct xfrm_policy *xp, struct sadb_x_policy *pol)
if (pol->sadb_x_policy_len * 8 < sizeof(struct sadb_x_policy))
return -EINVAL;
- while (len >= sizeof(struct sadb_x_ipsecrequest)) {
+ while (len >= sizeof(*rq)) {
+ if (len < rq->sadb_x_ipsecrequest_len ||
+ rq->sadb_x_ipsecrequest_len < sizeof(*rq))
+ return -EINVAL;
+
if ((err = parse_ipsecrequest(xp, rq)) < 0)
return err;
len -= rq->sadb_x_ipsecrequest_len;
@@ -2417,7 +2446,6 @@ out:
return err;
}
-#ifdef CONFIG_NET_KEY_MIGRATE
static int pfkey_sockaddr_pair_size(sa_family_t family)
{
return PFKEY_ALIGN8(pfkey_sockaddr_len(family) * 2);
@@ -2429,7 +2457,7 @@ static int parse_sockaddr_pair(struct sockaddr *sa, int ext_len,
{
int af, socklen;
- if (ext_len < pfkey_sockaddr_pair_size(sa->sa_family))
+ if (ext_len < 2 || ext_len < pfkey_sockaddr_pair_size(sa->sa_family))
return -EINVAL;
af = pfkey_sockaddr_extract(sa, saddr);
@@ -2445,6 +2473,7 @@ static int parse_sockaddr_pair(struct sockaddr *sa, int ext_len,
return 0;
}
+#ifdef CONFIG_NET_KEY_MIGRATE
static int ipsecrequests_to_migrate(struct sadb_x_ipsecrequest *rq1, int len,
struct xfrm_migrate *m)
{
@@ -2452,13 +2481,14 @@ static int ipsecrequests_to_migrate(struct sadb_x_ipsecrequest *rq1, int len,
struct sadb_x_ipsecrequest *rq2;
int mode;
- if (len <= sizeof(struct sadb_x_ipsecrequest) ||
- len < rq1->sadb_x_ipsecrequest_len)
+ if (len < sizeof(*rq1) ||
+ len < rq1->sadb_x_ipsecrequest_len ||
+ rq1->sadb_x_ipsecrequest_len < sizeof(*rq1))
return -EINVAL;
/* old endoints */
err = parse_sockaddr_pair((struct sockaddr *)(rq1 + 1),
- rq1->sadb_x_ipsecrequest_len,
+ rq1->sadb_x_ipsecrequest_len - sizeof(*rq1),
&m->old_saddr, &m->old_daddr,
&m->old_family);
if (err)
@@ -2467,13 +2497,14 @@ static int ipsecrequests_to_migrate(struct sadb_x_ipsecrequest *rq1, int len,
rq2 = (struct sadb_x_ipsecrequest *)((u8 *)rq1 + rq1->sadb_x_ipsecrequest_len);
len -= rq1->sadb_x_ipsecrequest_len;
- if (len <= sizeof(struct sadb_x_ipsecrequest) ||
- len < rq2->sadb_x_ipsecrequest_len)
+ if (len <= sizeof(*rq2) ||
+ len < rq2->sadb_x_ipsecrequest_len ||
+ rq2->sadb_x_ipsecrequest_len < sizeof(*rq2))
return -EINVAL;
/* new endpoints */
err = parse_sockaddr_pair((struct sockaddr *)(rq2 + 1),
- rq2->sadb_x_ipsecrequest_len,
+ rq2->sadb_x_ipsecrequest_len - sizeof(*rq2),
&m->new_saddr, &m->new_daddr,
&m->new_family);
if (err)
@@ -2688,14 +2719,18 @@ static int pfkey_spddump(struct sock *sk, struct sk_buff *skb, const struct sadb
{
struct pfkey_sock *pfk = pfkey_sk(sk);
- if (pfk->dump.dump != NULL)
+ mutex_lock(&pfk->dump_lock);
+ if (pfk->dump.dump != NULL) {
+ mutex_unlock(&pfk->dump_lock);
return -EBUSY;
+ }
pfk->dump.msg_version = hdr->sadb_msg_version;
pfk->dump.msg_portid = hdr->sadb_msg_pid;
pfk->dump.dump = pfkey_dump_sp;
pfk->dump.done = pfkey_dump_sp_done;
xfrm_policy_walk_init(&pfk->dump.u.policy, XFRM_POLICY_TYPE_MAIN);
+ mutex_unlock(&pfk->dump_lock);
return pfkey_do_dump(pfk);
}
diff --git a/net/netfilter/ipvs/ip_vs_core.c b/net/netfilter/ipvs/ip_vs_core.c
index 4da560005b0e..dd1649caa2b2 100644
--- a/net/netfilter/ipvs/ip_vs_core.c
+++ b/net/netfilter/ipvs/ip_vs_core.c
@@ -845,10 +845,8 @@ static int handle_response_icmp(int af, struct sk_buff *skb,
{
unsigned int verdict = NF_DROP;
- if (IP_VS_FWD_METHOD(cp) != 0) {
- pr_err("shouldn't reach here, because the box is on the "
- "half connection in the tun/dr module.\n");
- }
+ if (IP_VS_FWD_METHOD(cp) != IP_VS_CONN_F_MASQ)
+ goto ignore_cp;
/* Ensure the checksum is correct */
if (!skb_csum_unnecessary(skb) && ip_vs_checksum_complete(skb, ihl)) {
@@ -882,6 +880,8 @@ static int handle_response_icmp(int af, struct sk_buff *skb,
ip_vs_notrack(skb);
else
ip_vs_update_conntrack(skb, cp, 0);
+
+ignore_cp:
verdict = NF_ACCEPT;
out:
@@ -1242,8 +1242,11 @@ ip_vs_out(struct netns_ipvs *ipvs, unsigned int hooknum, struct sk_buff *skb, in
*/
cp = pp->conn_out_get(ipvs, af, skb, &iph);
- if (likely(cp))
+ if (likely(cp)) {
+ if (IP_VS_FWD_METHOD(cp) != IP_VS_CONN_F_MASQ)
+ goto ignore_cp;
return handle_response(af, skb, pd, cp, &iph, hooknum);
+ }
if (sysctl_nat_icmp_send(ipvs) &&
(pp->protocol == IPPROTO_TCP ||
pp->protocol == IPPROTO_UDP ||
@@ -1285,9 +1288,15 @@ ip_vs_out(struct netns_ipvs *ipvs, unsigned int hooknum, struct sk_buff *skb, in
}
}
}
+
+out:
IP_VS_DBG_PKT(12, af, pp, skb, iph.off,
"ip_vs_out: packet continues traversal as normal");
return NF_ACCEPT;
+
+ignore_cp:
+ __ip_vs_conn_put(cp);
+ goto out;
}
/*
diff --git a/net/nfc/core.c b/net/nfc/core.c
index 1fe3d3b362c0..c5a2c7e733b3 100644
--- a/net/nfc/core.c
+++ b/net/nfc/core.c
@@ -969,6 +969,8 @@ static void nfc_release(struct device *d)
kfree(se);
}
+ ida_simple_remove(&nfc_index_ida, dev->idx);
+
kfree(dev);
}
@@ -1043,6 +1045,7 @@ struct nfc_dev *nfc_allocate_device(struct nfc_ops *ops,
int tx_headroom, int tx_tailroom)
{
struct nfc_dev *dev;
+ int rc;
if (!ops->start_poll || !ops->stop_poll || !ops->activate_target ||
!ops->deactivate_target || !ops->im_transceive)
@@ -1055,6 +1058,15 @@ struct nfc_dev *nfc_allocate_device(struct nfc_ops *ops,
if (!dev)
return NULL;
+ rc = ida_simple_get(&nfc_index_ida, 0, 0, GFP_KERNEL);
+ if (rc < 0)
+ goto err_free_dev;
+ dev->idx = rc;
+
+ dev->dev.class = &nfc_class;
+ dev_set_name(&dev->dev, "nfc%d", dev->idx);
+ device_initialize(&dev->dev);
+
dev->ops = ops;
dev->supported_protocols = supported_protocols;
dev->tx_headroom = tx_headroom;
@@ -1077,6 +1089,11 @@ struct nfc_dev *nfc_allocate_device(struct nfc_ops *ops,
}
return dev;
+
+err_free_dev:
+ kfree(dev);
+
+ return ERR_PTR(rc);
}
EXPORT_SYMBOL(nfc_allocate_device);
@@ -1091,14 +1108,6 @@ int nfc_register_device(struct nfc_dev *dev)
pr_debug("dev_name=%s\n", dev_name(&dev->dev));
- dev->idx = ida_simple_get(&nfc_index_ida, 0, 0, GFP_KERNEL);
- if (dev->idx < 0)
- return dev->idx;
-
- dev->dev.class = &nfc_class;
- dev_set_name(&dev->dev, "nfc%d", dev->idx);
- device_initialize(&dev->dev);
-
mutex_lock(&nfc_devlist_mutex);
nfc_devlist_generation++;
rc = device_add(&dev->dev);
@@ -1136,12 +1145,10 @@ EXPORT_SYMBOL(nfc_register_device);
*/
void nfc_unregister_device(struct nfc_dev *dev)
{
- int rc, id;
+ int rc;
pr_debug("dev_name=%s\n", dev_name(&dev->dev));
- id = dev->idx;
-
if (dev->rfkill) {
rfkill_unregister(dev->rfkill);
rfkill_destroy(dev->rfkill);
@@ -1166,8 +1173,6 @@ void nfc_unregister_device(struct nfc_dev *dev)
nfc_devlist_generation++;
device_del(&dev->dev);
mutex_unlock(&nfc_devlist_mutex);
-
- ida_simple_remove(&nfc_index_ida, id);
}
EXPORT_SYMBOL(nfc_unregister_device);
diff --git a/net/nfc/llcp_sock.c b/net/nfc/llcp_sock.c
index ecf0a0196f18..9c222a106c7f 100644
--- a/net/nfc/llcp_sock.c
+++ b/net/nfc/llcp_sock.c
@@ -76,7 +76,8 @@ static int llcp_sock_bind(struct socket *sock, struct sockaddr *addr, int alen)
struct sockaddr_nfc_llcp llcp_addr;
int len, ret = 0;
- if (!addr || addr->sa_family != AF_NFC)
+ if (!addr || alen < offsetofend(struct sockaddr, sa_family) ||
+ addr->sa_family != AF_NFC)
return -EINVAL;
pr_debug("sk %p addr %p family %d\n", sk, addr, addr->sa_family);
@@ -150,7 +151,8 @@ static int llcp_raw_sock_bind(struct socket *sock, struct sockaddr *addr,
struct sockaddr_nfc_llcp llcp_addr;
int len, ret = 0;
- if (!addr || addr->sa_family != AF_NFC)
+ if (!addr || alen < offsetofend(struct sockaddr, sa_family) ||
+ addr->sa_family != AF_NFC)
return -EINVAL;
pr_debug("sk %p addr %p family %d\n", sk, addr, addr->sa_family);
@@ -655,8 +657,7 @@ static int llcp_sock_connect(struct socket *sock, struct sockaddr *_addr,
pr_debug("sock %p sk %p flags 0x%x\n", sock, sk, flags);
- if (!addr || len < sizeof(struct sockaddr_nfc) ||
- addr->sa_family != AF_NFC)
+ if (!addr || len < sizeof(*addr) || addr->sa_family != AF_NFC)
return -EINVAL;
if (addr->service_name_len == 0 && addr->dsap == 0)
diff --git a/net/nfc/nci/core.c b/net/nfc/nci/core.c
index 10c99a578421..67583ad7f610 100644
--- a/net/nfc/nci/core.c
+++ b/net/nfc/nci/core.c
@@ -1084,8 +1084,7 @@ struct nci_dev *nci_allocate_device(struct nci_ops *ops,
return ndev;
free_nfc:
- kfree(ndev->nfc_dev);
-
+ nfc_free_device(ndev->nfc_dev);
free_nci:
kfree(ndev);
return NULL;
diff --git a/net/nfc/netlink.c b/net/nfc/netlink.c
index f58c1fba1026..12dfb457275d 100644
--- a/net/nfc/netlink.c
+++ b/net/nfc/netlink.c
@@ -873,7 +873,9 @@ static int nfc_genl_activate_target(struct sk_buff *skb, struct genl_info *info)
u32 device_idx, target_idx, protocol;
int rc;
- if (!info->attrs[NFC_ATTR_DEVICE_INDEX])
+ if (!info->attrs[NFC_ATTR_DEVICE_INDEX] ||
+ !info->attrs[NFC_ATTR_TARGET_INDEX] ||
+ !info->attrs[NFC_ATTR_PROTOCOLS])
return -EINVAL;
device_idx = nla_get_u32(info->attrs[NFC_ATTR_DEVICE_INDEX]);
diff --git a/net/xfrm/xfrm_policy.c b/net/xfrm/xfrm_policy.c
index 0f45e1a3a7d1..c8700399d7fd 100644
--- a/net/xfrm/xfrm_policy.c
+++ b/net/xfrm/xfrm_policy.c
@@ -1214,7 +1214,7 @@ static inline int policy_to_flow_dir(int dir)
}
static struct xfrm_policy *xfrm_sk_policy_lookup(const struct sock *sk, int dir,
- const struct flowi *fl)
+ const struct flowi *fl, u16 family)
{
struct xfrm_policy *pol;
struct net *net = sock_net(sk);
@@ -1223,8 +1223,7 @@ static struct xfrm_policy *xfrm_sk_policy_lookup(const struct sock *sk, int dir,
read_lock_bh(&net->xfrm.xfrm_policy_lock);
pol = rcu_dereference(sk->sk_policy[dir]);
if (pol != NULL) {
- bool match = xfrm_selector_match(&pol->selector, fl,
- sk->sk_family);
+ bool match = xfrm_selector_match(&pol->selector, fl, family);
int err = 0;
if (match) {
@@ -2171,7 +2170,7 @@ struct dst_entry *xfrm_lookup(struct net *net, struct dst_entry *dst_orig,
sk = sk_const_to_full_sk(sk);
if (sk && sk->sk_policy[XFRM_POLICY_OUT]) {
num_pols = 1;
- pols[0] = xfrm_sk_policy_lookup(sk, XFRM_POLICY_OUT, fl);
+ pols[0] = xfrm_sk_policy_lookup(sk, XFRM_POLICY_OUT, fl, family);
err = xfrm_expand_policies(fl, family, pols,
&num_pols, &num_xfrms);
if (err < 0)
@@ -2450,7 +2449,7 @@ int __xfrm_policy_check(struct sock *sk, int dir, struct sk_buff *skb,
pol = NULL;
sk = sk_to_full_sk(sk);
if (sk && sk->sk_policy[dir]) {
- pol = xfrm_sk_policy_lookup(sk, dir, &fl);
+ pol = xfrm_sk_policy_lookup(sk, dir, &fl, family);
if (IS_ERR(pol)) {
XFRM_INC_STATS(net, LINUX_MIB_XFRMINPOLERROR);
return 0;
diff --git a/sound/soc/codecs/nau8825.c b/sound/soc/codecs/nau8825.c
index c1b87c5800b1..b3fddba4c084 100644
--- a/sound/soc/codecs/nau8825.c
+++ b/sound/soc/codecs/nau8825.c
@@ -936,7 +936,8 @@ static void nau8825_fll_apply(struct nau8825 *nau8825,
NAU8825_FLL_INTEGER_MASK, fll_param->fll_int);
/* FLL pre-scaler */
regmap_update_bits(nau8825->regmap, NAU8825_REG_FLL4,
- NAU8825_FLL_REF_DIV_MASK, fll_param->clk_ref_div);
+ NAU8825_FLL_REF_DIV_MASK,
+ fll_param->clk_ref_div << NAU8825_FLL_REF_DIV_SFT);
/* select divided VCO input */
regmap_update_bits(nau8825->regmap, NAU8825_REG_FLL5,
NAU8825_FLL_FILTER_SW_MASK, 0x0000);
diff --git a/sound/soc/codecs/nau8825.h b/sound/soc/codecs/nau8825.h
index dff8edb83bfd..a0b220726a63 100644
--- a/sound/soc/codecs/nau8825.h
+++ b/sound/soc/codecs/nau8825.h
@@ -114,7 +114,8 @@
#define NAU8825_FLL_INTEGER_MASK (0x3ff << 0)
/* FLL4 (0x07) */
-#define NAU8825_FLL_REF_DIV_MASK (0x3 << 10)
+#define NAU8825_FLL_REF_DIV_SFT 10
+#define NAU8825_FLL_REF_DIV_MASK (0x3 << NAU8825_FLL_REF_DIV_SFT)
/* FLL5 (0x08) */
#define NAU8825_FLL_FILTER_SW_MASK (0x1 << 14)
diff --git a/sound/soc/codecs/tlv320aic3x.c b/sound/soc/codecs/tlv320aic3x.c
index a564759845f9..5a3f544bb3a8 100644
--- a/sound/soc/codecs/tlv320aic3x.c
+++ b/sound/soc/codecs/tlv320aic3x.c
@@ -126,6 +126,16 @@ static const struct reg_default aic3x_reg[] = {
{ 108, 0x00 }, { 109, 0x00 },
};
+static bool aic3x_volatile_reg(struct device *dev, unsigned int reg)
+{
+ switch (reg) {
+ case AIC3X_RESET:
+ return true;
+ default:
+ return false;
+ }
+}
+
static const struct regmap_config aic3x_regmap = {
.reg_bits = 8,
.val_bits = 8,
@@ -133,6 +143,9 @@ static const struct regmap_config aic3x_regmap = {
.max_register = DAC_ICC_ADJ,
.reg_defaults = aic3x_reg,
.num_reg_defaults = ARRAY_SIZE(aic3x_reg),
+
+ .volatile_reg = aic3x_volatile_reg,
+
.cache_type = REGCACHE_RBTREE,
};
diff --git a/sound/soc/codecs/wcd-dsp-mgr.c b/sound/soc/codecs/wcd-dsp-mgr.c
index 9b1c8c98946c..1613c5baa9c7 100644
--- a/sound/soc/codecs/wcd-dsp-mgr.c
+++ b/sound/soc/codecs/wcd-dsp-mgr.c
@@ -415,22 +415,24 @@ static int wdsp_download_segments(struct wdsp_mgr_priv *wdsp,
/* Go through the list of segments and download one by one */
list_for_each_entry(seg, wdsp->seg_list, list) {
ret = wdsp_load_each_segment(wdsp, seg);
- if (IS_ERR_VALUE(ret)) {
- wdsp_broadcast_event_downseq(wdsp,
- WDSP_EVENT_DLOAD_FAILED,
- NULL);
+ if (ret)
goto dload_error;
- }
}
+ /* Flush the list before setting status and notifying components */
+ wdsp_flush_segment_list(wdsp->seg_list);
+
WDSP_SET_STATUS(wdsp, status);
/* Notify all components that image is downloaded */
wdsp_broadcast_event_downseq(wdsp, post, NULL);
+done:
+ return ret;
dload_error:
wdsp_flush_segment_list(wdsp->seg_list);
-done:
+ wdsp_broadcast_event_downseq(wdsp, WDSP_EVENT_DLOAD_FAILED, NULL);
+
return ret;
}
@@ -484,10 +486,14 @@ static int wdsp_enable_dsp(struct wdsp_mgr_priv *wdsp)
/* Make sure wdsp is in good state */
if (!WDSP_STATUS_IS_SET(wdsp, WDSP_STATUS_CODE_DLOADED)) {
WDSP_ERR(wdsp, "WDSP in invalid state 0x%x", wdsp->status);
- ret = -EINVAL;
- goto done;
+ return -EINVAL;
}
+ /*
+ * Acquire SSR mutex lock to make sure enablement of DSP
+ * does not race with SSR handling.
+ */
+ WDSP_MGR_MUTEX_LOCK(wdsp, wdsp->ssr_mutex);
/* Download the read-write sections of image */
ret = wdsp_download_segments(wdsp, WDSP_ELF_FLAG_WRITE);
if (IS_ERR_VALUE(ret)) {
@@ -508,6 +514,7 @@ static int wdsp_enable_dsp(struct wdsp_mgr_priv *wdsp)
wdsp_broadcast_event_downseq(wdsp, WDSP_EVENT_POST_BOOTUP, NULL);
WDSP_SET_STATUS(wdsp, WDSP_STATUS_BOOTED);
done:
+ WDSP_MGR_MUTEX_UNLOCK(wdsp, wdsp->ssr_mutex);
return ret;
}
diff --git a/sound/soc/codecs/wcd934x/wcd934x-dsp-cntl.c b/sound/soc/codecs/wcd934x/wcd934x-dsp-cntl.c
index e791bf07ec67..29c218013a07 100644
--- a/sound/soc/codecs/wcd934x/wcd934x-dsp-cntl.c
+++ b/sound/soc/codecs/wcd934x/wcd934x-dsp-cntl.c
@@ -763,10 +763,6 @@ static int wcd_control_handler(struct device *dev, void *priv_data,
case WDSP_EVENT_DLOAD_FAILED:
case WDSP_EVENT_POST_SHUTDOWN:
- if (event == WDSP_EVENT_POST_DLOAD_CODE)
- /* Mark DSP online since code download is complete */
- wcd_cntl_change_online_state(cntl, 1);
-
/* Disable CPAR */
wcd_cntl_cpar_ctrl(cntl, false);
/* Disable all the clocks */
@@ -775,6 +771,11 @@ static int wcd_control_handler(struct device *dev, void *priv_data,
dev_err(codec->dev,
"%s: Failed to disable clocks, err = %d\n",
__func__, ret);
+
+ if (event == WDSP_EVENT_POST_DLOAD_CODE)
+ /* Mark DSP online since code download is complete */
+ wcd_cntl_change_online_state(cntl, 1);
+
break;
case WDSP_EVENT_PRE_DLOAD_DATA:
diff --git a/sound/soc/msm/msm8998.c b/sound/soc/msm/msm8998.c
index b8bd32e046a3..9159ea642816 100644
--- a/sound/soc/msm/msm8998.c
+++ b/sound/soc/msm/msm8998.c
@@ -434,7 +434,8 @@ static char const *tdm_sample_rate_text[] = {"KHZ_8", "KHZ_16", "KHZ_32",
static const char *const auxpcm_rate_text[] = {"KHZ_8", "KHZ_16"};
static char const *mi2s_rate_text[] = {"KHZ_8", "KHZ_16",
"KHZ_32", "KHZ_44P1", "KHZ_48",
- "KHZ_96", "KHZ_192"};
+ "KHZ_88P2", "KHZ_96", "KHZ_176P4",
+ "KHZ_192"};
static const char *const mi2s_ch_text[] = {"One", "Two", "Three", "Four",
"Five", "Six", "Seven",
"Eight"};
@@ -2228,12 +2229,18 @@ static int mi2s_get_sample_rate_val(int sample_rate)
case SAMPLING_RATE_48KHZ:
sample_rate_val = 4;
break;
- case SAMPLING_RATE_96KHZ:
+ case SAMPLING_RATE_88P2KHZ:
sample_rate_val = 5;
break;
- case SAMPLING_RATE_192KHZ:
+ case SAMPLING_RATE_96KHZ:
sample_rate_val = 6;
break;
+ case SAMPLING_RATE_176P4KHZ:
+ sample_rate_val = 7;
+ break;
+ case SAMPLING_RATE_192KHZ:
+ sample_rate_val = 8;
+ break;
default:
sample_rate_val = 4;
break;
@@ -2262,9 +2269,15 @@ static int mi2s_get_sample_rate(int value)
sample_rate = SAMPLING_RATE_48KHZ;
break;
case 5:
- sample_rate = SAMPLING_RATE_96KHZ;
+ sample_rate = SAMPLING_RATE_88P2KHZ;
break;
case 6:
+ sample_rate = SAMPLING_RATE_96KHZ;
+ break;
+ case 7:
+ sample_rate = SAMPLING_RATE_176P4KHZ;
+ break;
+ case 8:
sample_rate = SAMPLING_RATE_192KHZ;
break;
default:
diff --git a/sound/soc/msm/qdsp6v2/msm-dai-q6-v2.c b/sound/soc/msm/qdsp6v2/msm-dai-q6-v2.c
index 3610901addea..292b3d04f7d5 100644
--- a/sound/soc/msm/qdsp6v2/msm-dai-q6-v2.c
+++ b/sound/soc/msm/qdsp6v2/msm-dai-q6-v2.c
@@ -4152,7 +4152,8 @@ static struct snd_soc_dai_driver msm_dai_q6_mi2s_dai[] = {
.rates = SNDRV_PCM_RATE_8000 | SNDRV_PCM_RATE_11025 |
SNDRV_PCM_RATE_16000 | SNDRV_PCM_RATE_22050 |
SNDRV_PCM_RATE_32000 | SNDRV_PCM_RATE_44100 |
- SNDRV_PCM_RATE_48000 | SNDRV_PCM_RATE_96000 |
+ SNDRV_PCM_RATE_48000 | SNDRV_PCM_RATE_88200 |
+ SNDRV_PCM_RATE_96000 | SNDRV_PCM_RATE_176400 |
SNDRV_PCM_RATE_192000,
.formats = SNDRV_PCM_FMTBIT_S16_LE,
.rate_min = 8000,
diff --git a/sound/soc/msm/qdsp6v2/msm-pcm-q6-v2.c b/sound/soc/msm/qdsp6v2/msm-pcm-q6-v2.c
index de769e8b806c..b94eb6fbfeea 100644
--- a/sound/soc/msm/qdsp6v2/msm-pcm-q6-v2.c
+++ b/sound/soc/msm/qdsp6v2/msm-pcm-q6-v2.c
@@ -1668,7 +1668,7 @@ static int msm_pcm_playback_pan_scale_ctl_put(struct snd_kcontrol *kcontrol,
for (i = 0; i < pan_param.num_output_channels *
pan_param.num_input_channels; i++) {
pan_param.gain[i] =
- !(ucontrol->value.integer.value[len++] > 0) ?
+ !(ucontrol->value.integer.value[len++] > 0) ?
0 : 2 << 13;
}
}
@@ -1679,8 +1679,12 @@ static int msm_pcm_playback_pan_scale_ctl_put(struct snd_kcontrol *kcontrol,
pan_param.num_input_channels;
for (i = 0; i < pan_param.num_output_channels *
pan_param.num_input_channels; i++) {
+ /*
+ * The data userspace passes is already in Q14 format.
+ * For volume gain is in Q28.
+ */
pan_param.gain[i] =
- ucontrol->value.integer.value[len++];
+ ucontrol->value.integer.value[len++] << 14;
}
ret = q6asm_set_vol_ctrl_gain_pair(prtd->audio_client,
&pan_param);
@@ -1753,7 +1757,7 @@ static int msm_pcm_playback_dnmix_ctl_put(struct snd_kcontrol *kcontrol,
struct msm_audio *prtd;
struct asm_stream_pan_ctrl_params dnmix_param;
- int be_id = ucontrol->value.integer.value[len];
+ int be_id = ucontrol->value.integer.value[len++];
int stream_id = 0;
if (!usr_info) {
@@ -1809,7 +1813,7 @@ static int msm_pcm_playback_dnmix_ctl_put(struct snd_kcontrol *kcontrol,
for (i = 0; i < dnmix_param.num_output_channels *
dnmix_param.num_input_channels; i++) {
dnmix_param.gain[i] =
- ucontrol->value.integer.value[len++];
+ ucontrol->value.integer.value[len++];
}
}
msm_routing_set_downmix_control_data(be_id,
diff --git a/sound/soc/msm/qdsp6v2/msm-pcm-routing-v2.c b/sound/soc/msm/qdsp6v2/msm-pcm-routing-v2.c
index 38937612dcce..7326e658c947 100644
--- a/sound/soc/msm/qdsp6v2/msm-pcm-routing-v2.c
+++ b/sound/soc/msm/qdsp6v2/msm-pcm-routing-v2.c
@@ -15659,10 +15659,6 @@ static int msm_pcm_routing_close(struct snd_pcm_substream *substream)
bedai->active = 0;
bedai->sample_rate = 0;
bedai->channel = 0;
- for (i = 0; i < MSM_FRONTEND_DAI_MAX; i++) {
- if (bedai->passthr_mode[i] != LISTEN)
- bedai->passthr_mode[i] = LEGACY_PCM;
- }
mutex_unlock(&routing_lock);
return 0;
@@ -16201,6 +16197,8 @@ int msm_routing_set_downmix_control_data(int be_id, int session_id,
char *adm_params = NULL;
int port_id, copp_idx = 0;
uint32_t params_length = 0;
+ uint16_t ii;
+ uint16_t *dst_gain_ptr = NULL;
if (be_id >= MSM_BACKEND_DAI_MAX) {
rc = -EINVAL;
@@ -16213,7 +16211,7 @@ int msm_routing_set_downmix_control_data(int be_id, int session_id,
variable_payload = dnmix_param->num_output_channels * sizeof(uint16_t)+
dnmix_param->num_input_channels * sizeof(uint16_t) +
- dnmix_param->num_output_channels * sizeof(uint16_t) *
+ dnmix_param->num_output_channels *
dnmix_param->num_input_channels * sizeof(uint16_t);
i = (variable_payload % sizeof(uint32_t));
variable_payload += (i == 0) ? 0 : sizeof(uint32_t) - i;
@@ -16252,14 +16250,15 @@ int msm_routing_set_downmix_control_data(int be_id, int session_id,
dnmix_param->num_output_channels * sizeof(uint16_t)),
dnmix_param->input_channel_map,
dnmix_param->num_input_channels * sizeof(uint16_t));
- memcpy(((u8 *)adm_params +
+
+ dst_gain_ptr = (uint16_t *) ((u8 *)adm_params +
sizeof(struct adm_pspd_param_data_t) +
sizeof(struct audproc_chmixer_param_coeff) +
(dnmix_param->num_output_channels * sizeof(uint16_t)) +
- (dnmix_param->num_input_channels * sizeof(uint16_t))),
- dnmix_param->gain,
- (dnmix_param->num_output_channels * sizeof(uint16_t)) *
(dnmix_param->num_input_channels * sizeof(uint16_t)));
+ for (ii = 0; ii < dnmix_param->num_output_channels *
+ dnmix_param->num_input_channels; ii++)
+ dst_gain_ptr[ii] = (uint16_t) dnmix_param->gain[ii];
if (params_length) {
rc = adm_set_pspd_matrix_params(port_id,
diff --git a/sound/soc/msm/qdsp6v2/msm-transcode-loopback-q6-v2.c b/sound/soc/msm/qdsp6v2/msm-transcode-loopback-q6-v2.c
index a75de6d1d7c0..fdeb8a15ffee 100644
--- a/sound/soc/msm/qdsp6v2/msm-transcode-loopback-q6-v2.c
+++ b/sound/soc/msm/qdsp6v2/msm-transcode-loopback-q6-v2.c
@@ -28,6 +28,7 @@
#include <sound/control.h>
#include <sound/q6asm-v2.h>
#include <sound/q6core.h>
+#include <sound/q6audio-v2.h>
#include <sound/pcm_params.h>
#include <sound/timer.h>
#include <sound/tlv.h>
@@ -41,12 +42,21 @@
#include "msm-qti-pp-config.h"
#define LOOPBACK_SESSION_MAX_NUM_STREAMS 2
+/* Max volume corresponding to 24dB */
+#define TRANSCODE_LR_VOL_MAX_STEPS 0xFFFF
+
+#define APP_TYPE_CONFIG_IDX_APP_TYPE 0
+#define APP_TYPE_CONFIG_IDX_ACDB_ID 1
+#define APP_TYPE_CONFIG_IDX_SAMPLE_RATE 2
+#define APP_TYPE_CONFIG_IDX_BE_ID 3
static DEFINE_MUTEX(transcode_loopback_session_lock);
struct trans_loopback_pdata {
struct snd_compr_stream *cstream[MSM_FRONTEND_DAI_MAX];
int32_t ion_fd[MSM_FRONTEND_DAI_MAX];
+ uint32_t master_gain;
+ int perf_mode;
};
struct loopback_stream {
@@ -398,6 +408,8 @@ static int msm_transcode_loopback_set_params(struct snd_compr_stream *cstream,
struct msm_transcode_loopback *trans = runtime->private_data;
struct snd_soc_pcm_runtime *soc_pcm_rx;
struct snd_soc_pcm_runtime *soc_pcm_tx;
+ struct snd_soc_pcm_runtime *rtd;
+ struct trans_loopback_pdata *pdata;
uint32_t bit_width = 16;
int ret = 0;
@@ -408,6 +420,9 @@ static int msm_transcode_loopback_set_params(struct snd_compr_stream *cstream,
mutex_lock(&trans->lock);
+ rtd = snd_pcm_substream_chip(cstream);
+ pdata = snd_soc_platform_get_drvdata(rtd->platform);
+
if (cstream->direction == SND_COMPRESS_PLAYBACK) {
if (codec_param->codec.id == SND_AUDIOCODEC_PCM) {
trans->sink.codec_format =
@@ -489,7 +504,7 @@ static int msm_transcode_loopback_set_params(struct snd_compr_stream *cstream,
pr_debug("%s: ASM client allocated, callback %pK\n", __func__,
loopback_event_handler);
trans->session_id = trans->audio_client->session;
- trans->audio_client->perf_mode = false;
+ trans->audio_client->perf_mode = pdata->perf_mode;
ret = q6asm_open_transcode_loopback(trans->audio_client,
bit_width,
trans->source.codec_format,
@@ -508,7 +523,7 @@ static int msm_transcode_loopback_set_params(struct snd_compr_stream *cstream,
if (trans->source.codec_format != FORMAT_LINEAR_PCM)
msm_pcm_routing_reg_phy_compr_stream(
soc_pcm_tx->dai_link->be_id,
- trans->audio_client->perf_mode,
+ false,
trans->session_id,
SNDRV_PCM_STREAM_CAPTURE,
COMPRESSED_PASSTHROUGH_GEN);
@@ -521,7 +536,7 @@ static int msm_transcode_loopback_set_params(struct snd_compr_stream *cstream,
/* Opening Rx ADM in LOW_LATENCY mode by default */
msm_pcm_routing_reg_phy_stream(
soc_pcm_rx->dai_link->be_id,
- true,
+ trans->audio_client->perf_mode,
trans->session_id,
SNDRV_PCM_STREAM_PLAYBACK);
pr_debug("%s: Successfully opened ADM sessions\n", __func__);
@@ -554,6 +569,46 @@ static int msm_transcode_loopback_get_caps(struct snd_compr_stream *cstream,
return 0;
}
+static int msm_transcode_loopback_set_metadata(struct snd_compr_stream *cstream,
+ struct snd_compr_metadata *metadata)
+{
+ struct snd_soc_pcm_runtime *rtd;
+ struct trans_loopback_pdata *pdata;
+
+ if (!metadata || !cstream) {
+ pr_err("%s: Invalid arguments\n", __func__);
+ return -EINVAL;
+ }
+
+ rtd = snd_pcm_substream_chip(cstream);
+ pdata = snd_soc_platform_get_drvdata(rtd->platform);
+
+ switch (metadata->key) {
+ case SNDRV_COMPRESS_LATENCY_MODE:
+ {
+ switch (metadata->value[0]) {
+ case SNDRV_COMPRESS_LEGACY_LATENCY_MODE:
+ pdata->perf_mode = LEGACY_PCM_MODE;
+ break;
+ case SNDRV_COMPRESS_LOW_LATENCY_MODE:
+ pdata->perf_mode = LOW_LATENCY_PCM_MODE;
+ break;
+ default:
+ pr_debug("%s: Unsupported latency mode %d, default to Legacy\n",
+ __func__, metadata->value[0]);
+ pdata->perf_mode = LEGACY_PCM_MODE;
+ break;
+ }
+ }
+ break;
+ default:
+ pr_debug("%s: Unsupported metadata %d\n",
+ __func__, metadata->key);
+ break;
+ }
+ return 0;
+}
+
static int msm_transcode_stream_cmd_put(struct snd_kcontrol *kcontrol,
struct snd_ctl_elem_value *ucontrol)
{
@@ -747,6 +802,141 @@ done:
return ret;
}
+static int msm_transcode_playback_app_type_cfg_put(
+ struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
+{
+ u64 fe_id = kcontrol->private_value;
+ int session_type = SESSION_TYPE_RX;
+ int be_id = ucontrol->value.integer.value[APP_TYPE_CONFIG_IDX_BE_ID];
+ struct msm_pcm_stream_app_type_cfg cfg_data = {0, 0, 48000};
+ int ret = 0;
+
+ cfg_data.app_type = ucontrol->value.integer.value[
+ APP_TYPE_CONFIG_IDX_APP_TYPE];
+ cfg_data.acdb_dev_id = ucontrol->value.integer.value[
+ APP_TYPE_CONFIG_IDX_ACDB_ID];
+ if (ucontrol->value.integer.value[APP_TYPE_CONFIG_IDX_SAMPLE_RATE] != 0)
+ cfg_data.sample_rate = ucontrol->value.integer.value[
+ APP_TYPE_CONFIG_IDX_SAMPLE_RATE];
+ pr_debug("%s: fe_id %llu session_type %d be_id %d app_type %d acdb_dev_id %d sample_rate- %d\n",
+ __func__, fe_id, session_type, be_id,
+ cfg_data.app_type, cfg_data.acdb_dev_id, cfg_data.sample_rate);
+ ret = msm_pcm_routing_reg_stream_app_type_cfg(fe_id, session_type,
+ be_id, &cfg_data);
+ if (ret < 0)
+ pr_err("%s: msm_transcode_playback_stream_app_type_cfg set failed returned %d\n",
+ __func__, ret);
+
+ return ret;
+}
+
+static int msm_transcode_playback_app_type_cfg_get(
+ struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
+{
+ u64 fe_id = kcontrol->private_value;
+ int session_type = SESSION_TYPE_RX;
+ int be_id = 0;
+ struct msm_pcm_stream_app_type_cfg cfg_data = {0};
+ int ret = 0;
+
+ ret = msm_pcm_routing_get_stream_app_type_cfg(fe_id, session_type,
+ &be_id, &cfg_data);
+ if (ret < 0) {
+ pr_err("%s: msm_transcode_playback_stream_app_type_cfg get failed returned %d\n",
+ __func__, ret);
+ goto done;
+ }
+
+ ucontrol->value.integer.value[APP_TYPE_CONFIG_IDX_APP_TYPE] =
+ cfg_data.app_type;
+ ucontrol->value.integer.value[APP_TYPE_CONFIG_IDX_ACDB_ID] =
+ cfg_data.acdb_dev_id;
+ ucontrol->value.integer.value[APP_TYPE_CONFIG_IDX_SAMPLE_RATE] =
+ cfg_data.sample_rate;
+ ucontrol->value.integer.value[APP_TYPE_CONFIG_IDX_BE_ID] = be_id;
+ pr_debug("%s: fedai_id %llu, session_type %d, be_id %d, app_type %d, acdb_dev_id %d, sample_rate %d\n",
+ __func__, fe_id, session_type, be_id,
+ cfg_data.app_type, cfg_data.acdb_dev_id, cfg_data.sample_rate);
+done:
+ return ret;
+}
+
+static int msm_transcode_set_volume(struct snd_compr_stream *cstream,
+ uint32_t master_gain)
+{
+ int rc = 0;
+ struct msm_transcode_loopback *prtd;
+ struct snd_soc_pcm_runtime *rtd;
+
+ pr_debug("%s: master_gain %d\n", __func__, master_gain);
+ if (!cstream || !cstream->runtime) {
+ pr_err("%s: session not active\n", __func__);
+ return -EPERM;
+ }
+ rtd = cstream->private_data;
+ prtd = cstream->runtime->private_data;
+
+ if (!rtd || !rtd->platform || !prtd || !prtd->audio_client) {
+ pr_err("%s: invalid rtd, prtd or audio client", __func__);
+ return -EINVAL;
+ }
+
+ rc = q6asm_set_volume(prtd->audio_client, master_gain);
+ if (rc < 0)
+ pr_err("%s: Send vol gain command failed rc=%d\n",
+ __func__, rc);
+
+ return rc;
+}
+
+static int msm_transcode_volume_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 trans_loopback_pdata *pdata = (struct trans_loopback_pdata *)
+ snd_soc_component_get_drvdata(comp);
+ struct snd_compr_stream *cstream = NULL;
+ uint32_t ret = 0;
+
+ if (fe_id >= MSM_FRONTEND_DAI_MAX) {
+ pr_err("%s Received out of bounds fe_id %lu\n",
+ __func__, fe_id);
+ return -EINVAL;
+ }
+
+ cstream = pdata->cstream[fe_id];
+ pdata->master_gain = ucontrol->value.integer.value[0];
+
+ pr_debug("%s: fe_id %lu master_gain %d\n",
+ __func__, fe_id, pdata->master_gain);
+ if (cstream)
+ ret = msm_transcode_set_volume(cstream, pdata->master_gain);
+ return ret;
+}
+
+static int msm_transcode_volume_get(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 trans_loopback_pdata *pdata = (struct trans_loopback_pdata *)
+ snd_soc_component_get_drvdata(comp);
+
+ if (fe_id >= MSM_FRONTEND_DAI_MAX) {
+ pr_err("%s Received out of bound fe_id %lu\n", __func__, fe_id);
+ return -EINVAL;
+ }
+
+ pr_debug("%s: fe_id %lu\n", __func__, fe_id);
+ ucontrol->value.integer.value[0] = pdata->master_gain;
+
+ return 0;
+}
+
static int msm_transcode_stream_cmd_control(
struct snd_soc_pcm_runtime *rtd)
{
@@ -995,6 +1185,99 @@ done:
return ret;
}
+static int msm_transcode_app_type_cfg_info(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_info *uinfo)
+{
+ uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
+ uinfo->count = 5;
+ uinfo->value.integer.min = 0;
+ uinfo->value.integer.max = 0xFFFFFFFF;
+ return 0;
+}
+
+static int msm_transcode_add_app_type_cfg_control(
+ struct snd_soc_pcm_runtime *rtd)
+{
+ char mixer_str[32];
+ int rc = 0;
+ struct snd_kcontrol_new fe_app_type_cfg_control[1] = {
+ {
+ .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
+ .access = SNDRV_CTL_ELEM_ACCESS_READWRITE,
+ .info = msm_transcode_app_type_cfg_info,
+ .put = msm_transcode_playback_app_type_cfg_put,
+ .get = msm_transcode_playback_app_type_cfg_get,
+ .private_value = 0,
+ }
+ };
+
+ if (!rtd) {
+ pr_err("%s NULL rtd\n", __func__);
+
+ return -EINVAL;
+ }
+
+ if (rtd->compr->direction == SND_COMPRESS_PLAYBACK) {
+
+ snprintf(mixer_str, sizeof(mixer_str),
+ "Audio Stream %d App Type Cfg",
+ rtd->pcm->device);
+
+ fe_app_type_cfg_control[0].name = mixer_str;
+ fe_app_type_cfg_control[0].private_value = rtd->dai_link->be_id;
+
+ fe_app_type_cfg_control[0].put =
+ msm_transcode_playback_app_type_cfg_put;
+ fe_app_type_cfg_control[0].get =
+ msm_transcode_playback_app_type_cfg_get;
+
+ pr_debug("Registering new mixer ctl %s", mixer_str);
+ snd_soc_add_platform_controls(rtd->platform,
+ fe_app_type_cfg_control,
+ ARRAY_SIZE(fe_app_type_cfg_control));
+ }
+
+ return rc;
+}
+static int msm_transcode_volume_info(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_info *uinfo)
+{
+ uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
+ uinfo->count = 1;
+ uinfo->value.integer.min = 0;
+ uinfo->value.integer.max = TRANSCODE_LR_VOL_MAX_STEPS;
+ return 0;
+}
+
+static int msm_transcode_add_volume_control(struct snd_soc_pcm_runtime *rtd)
+{
+ struct snd_kcontrol_new fe_volume_control[1] = {
+ {
+ .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
+ .name = "Transcode Loopback Rx Volume",
+ .access = SNDRV_CTL_ELEM_ACCESS_TLV_READ |
+ SNDRV_CTL_ELEM_ACCESS_READWRITE,
+ .info = msm_transcode_volume_info,
+ .get = msm_transcode_volume_get,
+ .put = msm_transcode_volume_put,
+ .private_value = 0,
+ }
+ };
+
+ if (!rtd) {
+ pr_err("%s NULL rtd\n", __func__);
+ return -EINVAL;
+ }
+ if (rtd->compr->direction == SND_COMPRESS_PLAYBACK) {
+ fe_volume_control[0].private_value = rtd->dai_link->be_id;
+ pr_debug("Registering new mixer ctl %s",
+ fe_volume_control[0].name);
+ snd_soc_add_platform_controls(rtd->platform, fe_volume_control,
+ ARRAY_SIZE(fe_volume_control));
+ }
+ return 0;
+}
+
static int msm_transcode_loopback_new(struct snd_soc_pcm_runtime *rtd)
{
int rc;
@@ -1023,6 +1306,16 @@ static int msm_transcode_loopback_new(struct snd_soc_pcm_runtime *rtd)
pr_err("%s: Could not add transcode event ack Control\n",
__func__);
+ rc = msm_transcode_add_app_type_cfg_control(rtd);
+ if (rc)
+ pr_err("%s: Could not add Compr App Type Cfg Control\n",
+ __func__);
+
+ rc = msm_transcode_add_volume_control(rtd);
+ if (rc)
+ pr_err("%s: Could not add transcode volume Control\n",
+ __func__);
+
return 0;
}
@@ -1032,6 +1325,7 @@ static struct snd_compr_ops msm_transcode_loopback_ops = {
.trigger = msm_transcode_loopback_trigger,
.set_params = msm_transcode_loopback_set_params,
.get_caps = msm_transcode_loopback_get_caps,
+ .set_metadata = msm_transcode_loopback_set_metadata,
};
@@ -1046,6 +1340,7 @@ static int msm_transcode_loopback_probe(struct snd_soc_platform *platform)
if (!pdata)
return -ENOMEM;
+ pdata->perf_mode = LOW_LATENCY_PCM_MODE;
snd_soc_platform_set_drvdata(platform, pdata);
return 0;
}
diff --git a/sound/soc/msm/qdsp6v2/q6asm.c b/sound/soc/msm/qdsp6v2/q6asm.c
index d297acd62665..609ae8cd82ac 100644
--- a/sound/soc/msm/qdsp6v2/q6asm.c
+++ b/sound/soc/msm/qdsp6v2/q6asm.c
@@ -7543,7 +7543,9 @@ int q6asm_set_mfc_panning_params(struct audio_client *ac,
struct asm_stream_param_data_v2 data;
struct audproc_chmixer_param_coeff pan_cfg;
uint16_t variable_payload = 0;
- uint16_t *asm_params = NULL;
+ char *asm_params = NULL;
+ uint16_t ii;
+ uint16_t *dst_gain_ptr = NULL;
sz = rc = i = 0;
if (ac == NULL) {
@@ -7604,7 +7606,7 @@ int q6asm_set_mfc_panning_params(struct audio_client *ac,
variable_payload = pan_param->num_output_channels * sizeof(uint16_t)+
pan_param->num_input_channels * sizeof(uint16_t) +
- pan_param->num_output_channels * sizeof(uint16_t) *
+ pan_param->num_output_channels *
pan_param->num_input_channels * sizeof(uint16_t);
i = (variable_payload % sizeof(uint32_t));
variable_payload += (i == 0) ? 0 : sizeof(uint32_t) - i;
@@ -7664,15 +7666,16 @@ int q6asm_set_mfc_panning_params(struct audio_client *ac,
pan_param->num_output_channels * sizeof(uint16_t)),
pan_param->input_channel_map,
pan_param->num_input_channels * sizeof(uint16_t));
- memcpy(((u8 *)asm_params + sizeof(struct apr_hdr) +
+
+ dst_gain_ptr = (uint16_t *) ((u8 *)asm_params + sizeof(struct apr_hdr) +
sizeof(struct asm_stream_cmd_set_pp_params_v2) +
sizeof(struct asm_stream_param_data_v2) +
sizeof(struct audproc_chmixer_param_coeff) +
(pan_param->num_output_channels * sizeof(uint16_t)) +
- (pan_param->num_input_channels * sizeof(uint16_t))),
- pan_param->gain,
- (pan_param->num_output_channels * sizeof(uint16_t)) *
(pan_param->num_input_channels * sizeof(uint16_t)));
+ for (ii = 0; ii < pan_param->num_output_channels *
+ pan_param->num_input_channels; ii++)
+ dst_gain_ptr[ii] = (uint16_t) pan_param->gain[ii];
rc = apr_send_pkt(ac->apr, (uint32_t *) asm_params);
if (rc < 0) {
diff --git a/sound/usb/endpoint.c b/sound/usb/endpoint.c
index 2bba7dbc35f9..61f64dcd5374 100644
--- a/sound/usb/endpoint.c
+++ b/sound/usb/endpoint.c
@@ -384,6 +384,9 @@ static void snd_complete_urb(struct urb *urb)
if (unlikely(atomic_read(&ep->chip->shutdown)))
goto exit_clear;
+ if (unlikely(!test_bit(EP_FLAG_RUNNING, &ep->flags)))
+ goto exit_clear;
+
if (usb_pipeout(ep->pipe)) {
retire_outbound_urb(ep, ctx);
/* can be stopped during retire callback */
diff --git a/tools/lib/traceevent/plugin_sched_switch.c b/tools/lib/traceevent/plugin_sched_switch.c
index f1ce60065258..ec30c2fcbac0 100644
--- a/tools/lib/traceevent/plugin_sched_switch.c
+++ b/tools/lib/traceevent/plugin_sched_switch.c
@@ -111,7 +111,7 @@ static int sched_switch_handler(struct trace_seq *s,
trace_seq_printf(s, "%lld ", val);
if (pevent_get_field_val(s, event, "prev_prio", record, &val, 0) == 0)
- trace_seq_printf(s, "[%lld] ", val);
+ trace_seq_printf(s, "[%d] ", (int) val);
if (pevent_get_field_val(s, event, "prev_state", record, &val, 0) == 0)
write_state(s, val);
@@ -129,7 +129,7 @@ static int sched_switch_handler(struct trace_seq *s,
trace_seq_printf(s, "%lld", val);
if (pevent_get_field_val(s, event, "next_prio", record, &val, 0) == 0)
- trace_seq_printf(s, " [%lld]", val);
+ trace_seq_printf(s, " [%d]", (int) val);
return 0;
}
diff --git a/tools/perf/Makefile.perf b/tools/perf/Makefile.perf
index 74c265e0ffa0..fb1c9ddc3478 100644
--- a/tools/perf/Makefile.perf
+++ b/tools/perf/Makefile.perf
@@ -566,9 +566,9 @@ install-tests: all install-gtk
$(INSTALL) -d -m 755 '$(DESTDIR_SQ)$(perfexec_instdir_SQ)/tests/attr'; \
$(INSTALL) tests/attr/* '$(DESTDIR_SQ)$(perfexec_instdir_SQ)/tests/attr'
-install-bin: install-tools install-tests
+install-bin: install-tools install-tests install-traceevent-plugins
-install: install-bin try-install-man install-traceevent-plugins
+install: install-bin try-install-man
install-python_ext:
$(PYTHON_WORD) util/setup.py --quiet install --root='/$(DESTDIR_SQ)'
diff --git a/tools/perf/ui/browser.c b/tools/perf/ui/browser.c
index e9703c0829f1..07b5f5951b25 100644
--- a/tools/perf/ui/browser.c
+++ b/tools/perf/ui/browser.c
@@ -702,7 +702,7 @@ static void __ui_browser__line_arrow_down(struct ui_browser *browser,
ui_browser__gotorc(browser, row, column + 1);
SLsmg_draw_hline(2);
- if (row++ == 0)
+ if (++row == 0)
goto out;
} else
row = 0;
diff --git a/tools/perf/util/intel-pt-decoder/intel-pt-decoder.c b/tools/perf/util/intel-pt-decoder/intel-pt-decoder.c
index 933a509a90f8..eeeae0629ad3 100644
--- a/tools/perf/util/intel-pt-decoder/intel-pt-decoder.c
+++ b/tools/perf/util/intel-pt-decoder/intel-pt-decoder.c
@@ -64,6 +64,25 @@ enum intel_pt_pkt_state {
INTEL_PT_STATE_FUP_NO_TIP,
};
+static inline bool intel_pt_sample_time(enum intel_pt_pkt_state pkt_state)
+{
+ switch (pkt_state) {
+ case INTEL_PT_STATE_NO_PSB:
+ case INTEL_PT_STATE_NO_IP:
+ case INTEL_PT_STATE_ERR_RESYNC:
+ case INTEL_PT_STATE_IN_SYNC:
+ case INTEL_PT_STATE_TNT:
+ return true;
+ case INTEL_PT_STATE_TIP:
+ case INTEL_PT_STATE_TIP_PGD:
+ case INTEL_PT_STATE_FUP:
+ case INTEL_PT_STATE_FUP_NO_TIP:
+ return false;
+ default:
+ return true;
+ };
+}
+
#ifdef INTEL_PT_STRICT
#define INTEL_PT_STATE_ERR1 INTEL_PT_STATE_NO_PSB
#define INTEL_PT_STATE_ERR2 INTEL_PT_STATE_NO_PSB
@@ -91,6 +110,7 @@ struct intel_pt_decoder {
bool have_tma;
bool have_cyc;
bool fixup_last_mtc;
+ bool have_last_ip;
uint64_t pos;
uint64_t last_ip;
uint64_t ip;
@@ -98,6 +118,7 @@ struct intel_pt_decoder {
uint64_t timestamp;
uint64_t tsc_timestamp;
uint64_t ref_timestamp;
+ uint64_t sample_timestamp;
uint64_t ret_addr;
uint64_t ctc_timestamp;
uint64_t ctc_delta;
@@ -125,8 +146,6 @@ struct intel_pt_decoder {
bool have_calc_cyc_to_tsc;
int exec_mode;
unsigned int insn_bytes;
- uint64_t sign_bit;
- uint64_t sign_bits;
uint64_t period;
enum intel_pt_period_type period_type;
uint64_t tot_insn_cnt;
@@ -140,6 +159,7 @@ struct intel_pt_decoder {
unsigned int fup_tx_flags;
unsigned int tx_flags;
uint64_t timestamp_insn_cnt;
+ uint64_t sample_insn_cnt;
uint64_t stuck_ip;
int no_progress;
int stuck_ip_prd;
@@ -193,9 +213,6 @@ struct intel_pt_decoder *intel_pt_decoder_new(struct intel_pt_params *params)
decoder->data = params->data;
decoder->return_compression = params->return_compression;
- decoder->sign_bit = (uint64_t)1 << 47;
- decoder->sign_bits = ~(((uint64_t)1 << 48) - 1);
-
decoder->period = params->period;
decoder->period_type = params->period_type;
@@ -364,21 +381,30 @@ int intel_pt__strerror(int code, char *buf, size_t buflen)
return 0;
}
-static uint64_t intel_pt_calc_ip(struct intel_pt_decoder *decoder,
- const struct intel_pt_pkt *packet,
+static uint64_t intel_pt_calc_ip(const struct intel_pt_pkt *packet,
uint64_t last_ip)
{
uint64_t ip;
switch (packet->count) {
- case 2:
+ case 1:
ip = (last_ip & (uint64_t)0xffffffffffff0000ULL) |
packet->payload;
break;
- case 4:
+ case 2:
ip = (last_ip & (uint64_t)0xffffffff00000000ULL) |
packet->payload;
break;
+ case 3:
+ ip = packet->payload;
+ /* Sign-extend 6-byte ip */
+ if (ip & (uint64_t)0x800000000000ULL)
+ ip |= (uint64_t)0xffff000000000000ULL;
+ break;
+ case 4:
+ ip = (last_ip & (uint64_t)0xffff000000000000ULL) |
+ packet->payload;
+ break;
case 6:
ip = packet->payload;
break;
@@ -386,16 +412,13 @@ static uint64_t intel_pt_calc_ip(struct intel_pt_decoder *decoder,
return 0;
}
- if (ip & decoder->sign_bit)
- return ip | decoder->sign_bits;
-
return ip;
}
static inline void intel_pt_set_last_ip(struct intel_pt_decoder *decoder)
{
- decoder->last_ip = intel_pt_calc_ip(decoder, &decoder->packet,
- decoder->last_ip);
+ decoder->last_ip = intel_pt_calc_ip(&decoder->packet, decoder->last_ip);
+ decoder->have_last_ip = true;
}
static inline void intel_pt_set_ip(struct intel_pt_decoder *decoder)
@@ -896,6 +919,7 @@ static int intel_pt_walk_insn(struct intel_pt_decoder *decoder,
decoder->tot_insn_cnt += insn_cnt;
decoder->timestamp_insn_cnt += insn_cnt;
+ decoder->sample_insn_cnt += insn_cnt;
decoder->period_insn_cnt += insn_cnt;
if (err) {
@@ -1414,7 +1438,8 @@ static int intel_pt_walk_psbend(struct intel_pt_decoder *decoder)
case INTEL_PT_FUP:
decoder->pge = true;
- intel_pt_set_last_ip(decoder);
+ if (decoder->packet.count)
+ intel_pt_set_last_ip(decoder);
break;
case INTEL_PT_MODE_TSX:
@@ -1618,6 +1643,8 @@ next:
break;
case INTEL_PT_PSB:
+ decoder->last_ip = 0;
+ decoder->have_last_ip = true;
intel_pt_clear_stack(&decoder->stack);
err = intel_pt_walk_psbend(decoder);
if (err == -EAGAIN)
@@ -1696,6 +1723,13 @@ next:
}
}
+static inline bool intel_pt_have_ip(struct intel_pt_decoder *decoder)
+{
+ return decoder->packet.count &&
+ (decoder->have_last_ip || decoder->packet.count == 3 ||
+ decoder->packet.count == 6);
+}
+
/* Walk PSB+ packets to get in sync. */
static int intel_pt_walk_psb(struct intel_pt_decoder *decoder)
{
@@ -1717,8 +1751,7 @@ static int intel_pt_walk_psb(struct intel_pt_decoder *decoder)
case INTEL_PT_FUP:
decoder->pge = true;
- if (decoder->last_ip || decoder->packet.count == 6 ||
- decoder->packet.count == 0) {
+ if (intel_pt_have_ip(decoder)) {
uint64_t current_ip = decoder->ip;
intel_pt_set_ip(decoder);
@@ -1810,24 +1843,17 @@ static int intel_pt_walk_to_ip(struct intel_pt_decoder *decoder)
case INTEL_PT_TIP_PGE:
case INTEL_PT_TIP:
decoder->pge = decoder->packet.type != INTEL_PT_TIP_PGD;
- if (decoder->last_ip || decoder->packet.count == 6 ||
- decoder->packet.count == 0)
+ if (intel_pt_have_ip(decoder))
intel_pt_set_ip(decoder);
if (decoder->ip)
return 0;
break;
case INTEL_PT_FUP:
- if (decoder->overflow) {
- if (decoder->last_ip ||
- decoder->packet.count == 6 ||
- decoder->packet.count == 0)
- intel_pt_set_ip(decoder);
- if (decoder->ip)
- return 0;
- }
- if (decoder->packet.count)
- intel_pt_set_last_ip(decoder);
+ if (intel_pt_have_ip(decoder))
+ intel_pt_set_ip(decoder);
+ if (decoder->ip)
+ return 0;
break;
case INTEL_PT_MTC:
@@ -1876,6 +1902,9 @@ static int intel_pt_walk_to_ip(struct intel_pt_decoder *decoder)
break;
case INTEL_PT_PSB:
+ decoder->last_ip = 0;
+ decoder->have_last_ip = true;
+ intel_pt_clear_stack(&decoder->stack);
err = intel_pt_walk_psb(decoder);
if (err)
return err;
@@ -1901,6 +1930,8 @@ static int intel_pt_sync_ip(struct intel_pt_decoder *decoder)
{
int err;
+ decoder->set_fup_tx_flags = false;
+
intel_pt_log("Scanning for full IP\n");
err = intel_pt_walk_to_ip(decoder);
if (err)
@@ -2009,6 +2040,7 @@ static int intel_pt_sync(struct intel_pt_decoder *decoder)
decoder->pge = false;
decoder->continuous_period = false;
+ decoder->have_last_ip = false;
decoder->last_ip = 0;
decoder->ip = 0;
intel_pt_clear_stack(&decoder->stack);
@@ -2017,6 +2049,7 @@ static int intel_pt_sync(struct intel_pt_decoder *decoder)
if (err)
return err;
+ decoder->have_last_ip = true;
decoder->pkt_state = INTEL_PT_STATE_NO_IP;
err = intel_pt_walk_psb(decoder);
@@ -2035,7 +2068,7 @@ static int intel_pt_sync(struct intel_pt_decoder *decoder)
static uint64_t intel_pt_est_timestamp(struct intel_pt_decoder *decoder)
{
- uint64_t est = decoder->timestamp_insn_cnt << 1;
+ uint64_t est = decoder->sample_insn_cnt << 1;
if (!decoder->cbr || !decoder->max_non_turbo_ratio)
goto out;
@@ -2043,7 +2076,7 @@ static uint64_t intel_pt_est_timestamp(struct intel_pt_decoder *decoder)
est *= decoder->max_non_turbo_ratio;
est /= decoder->cbr;
out:
- return decoder->timestamp + est;
+ return decoder->sample_timestamp + est;
}
const struct intel_pt_state *intel_pt_decode(struct intel_pt_decoder *decoder)
@@ -2059,7 +2092,9 @@ const struct intel_pt_state *intel_pt_decode(struct intel_pt_decoder *decoder)
err = intel_pt_sync(decoder);
break;
case INTEL_PT_STATE_NO_IP:
+ decoder->have_last_ip = false;
decoder->last_ip = 0;
+ decoder->ip = 0;
/* Fall through */
case INTEL_PT_STATE_ERR_RESYNC:
err = intel_pt_sync_ip(decoder);
@@ -2096,15 +2131,24 @@ const struct intel_pt_state *intel_pt_decode(struct intel_pt_decoder *decoder)
}
} while (err == -ENOLINK);
- decoder->state.err = err ? intel_pt_ext_err(err) : 0;
- decoder->state.timestamp = decoder->timestamp;
+ if (err) {
+ decoder->state.err = intel_pt_ext_err(err);
+ decoder->state.from_ip = decoder->ip;
+ decoder->sample_timestamp = decoder->timestamp;
+ decoder->sample_insn_cnt = decoder->timestamp_insn_cnt;
+ } else {
+ decoder->state.err = 0;
+ if (intel_pt_sample_time(decoder->pkt_state)) {
+ decoder->sample_timestamp = decoder->timestamp;
+ decoder->sample_insn_cnt = decoder->timestamp_insn_cnt;
+ }
+ }
+
+ decoder->state.timestamp = decoder->sample_timestamp;
decoder->state.est_timestamp = intel_pt_est_timestamp(decoder);
decoder->state.cr3 = decoder->cr3;
decoder->state.tot_insn_cnt = decoder->tot_insn_cnt;
- if (err)
- decoder->state.from_ip = decoder->ip;
-
return &decoder->state;
}
diff --git a/tools/perf/util/intel-pt-decoder/intel-pt-pkt-decoder.c b/tools/perf/util/intel-pt-decoder/intel-pt-pkt-decoder.c
index 9b2fce25162b..7528ae4f7e28 100644
--- a/tools/perf/util/intel-pt-decoder/intel-pt-pkt-decoder.c
+++ b/tools/perf/util/intel-pt-decoder/intel-pt-pkt-decoder.c
@@ -293,36 +293,46 @@ static int intel_pt_get_ip(enum intel_pt_pkt_type type, unsigned int byte,
const unsigned char *buf, size_t len,
struct intel_pt_pkt *packet)
{
- switch (byte >> 5) {
+ int ip_len;
+
+ packet->count = byte >> 5;
+
+ switch (packet->count) {
case 0:
- packet->count = 0;
+ ip_len = 0;
break;
case 1:
if (len < 3)
return INTEL_PT_NEED_MORE_BYTES;
- packet->count = 2;
+ ip_len = 2;
packet->payload = le16_to_cpu(*(uint16_t *)(buf + 1));
break;
case 2:
if (len < 5)
return INTEL_PT_NEED_MORE_BYTES;
- packet->count = 4;
+ ip_len = 4;
packet->payload = le32_to_cpu(*(uint32_t *)(buf + 1));
break;
case 3:
- case 6:
+ case 4:
if (len < 7)
return INTEL_PT_NEED_MORE_BYTES;
- packet->count = 6;
+ ip_len = 6;
memcpy_le64(&packet->payload, buf + 1, 6);
break;
+ case 6:
+ if (len < 9)
+ return INTEL_PT_NEED_MORE_BYTES;
+ ip_len = 8;
+ packet->payload = le64_to_cpu(*(uint64_t *)(buf + 1));
+ break;
default:
return INTEL_PT_BAD_PACKET;
}
packet->type = type;
- return packet->count + 1;
+ return ip_len + 1;
}
static int intel_pt_get_mode(const unsigned char *buf, size_t len,
diff --git a/tools/perf/util/symbol-elf.c b/tools/perf/util/symbol-elf.c
index 27ae382feb2d..7c97ecaeae48 100644
--- a/tools/perf/util/symbol-elf.c
+++ b/tools/perf/util/symbol-elf.c
@@ -488,6 +488,12 @@ int sysfs__read_build_id(const char *filename, void *build_id, size_t size)
break;
} else {
int n = namesz + descsz;
+
+ if (n > (int)sizeof(bf)) {
+ n = sizeof(bf);
+ pr_debug("%s: truncating reading of build id in sysfs file %s: n_namesz=%u, n_descsz=%u.\n",
+ __func__, filename, nhdr.n_namesz, nhdr.n_descsz);
+ }
if (read(fd, bf, n) != n)
break;
}
diff --git a/virt/kvm/vfio.c b/virt/kvm/vfio.c
index 1dd087da6f31..111e09c3f4bf 100644
--- a/virt/kvm/vfio.c
+++ b/virt/kvm/vfio.c
@@ -47,6 +47,22 @@ static struct vfio_group *kvm_vfio_group_get_external_user(struct file *filep)
return vfio_group;
}
+static bool kvm_vfio_external_group_match_file(struct vfio_group *group,
+ struct file *filep)
+{
+ bool ret, (*fn)(struct vfio_group *, struct file *);
+
+ fn = symbol_get(vfio_external_group_match_file);
+ if (!fn)
+ return false;
+
+ ret = fn(group, filep);
+
+ symbol_put(vfio_external_group_match_file);
+
+ return ret;
+}
+
static void kvm_vfio_group_put_external_user(struct vfio_group *vfio_group)
{
void (*fn)(struct vfio_group *);
@@ -171,18 +187,13 @@ static int kvm_vfio_set_group(struct kvm_device *dev, long attr, u64 arg)
if (!f.file)
return -EBADF;
- vfio_group = kvm_vfio_group_get_external_user(f.file);
- fdput(f);
-
- if (IS_ERR(vfio_group))
- return PTR_ERR(vfio_group);
-
ret = -ENOENT;
mutex_lock(&kv->lock);
list_for_each_entry(kvg, &kv->group_list, node) {
- if (kvg->vfio_group != vfio_group)
+ if (!kvm_vfio_external_group_match_file(kvg->vfio_group,
+ f.file))
continue;
list_del(&kvg->node);
@@ -196,7 +207,7 @@ static int kvm_vfio_set_group(struct kvm_device *dev, long attr, u64 arg)
mutex_unlock(&kv->lock);
- kvm_vfio_group_put_external_user(vfio_group);
+ fdput(f);
kvm_vfio_update_coherency(dev);