summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--Makefile2
-rw-r--r--arch/arc/configs/axs101_defconfig1
-rw-r--r--arch/arc/configs/axs103_defconfig1
-rw-r--r--arch/arc/configs/axs103_smp_defconfig1
-rw-r--r--arch/arm/boot/dts/qcom/apq8016-sbc.dtsi2
-rw-r--r--arch/arm/boot/dts/qcom/dsi-panel-lgd-incell-sw49106-fhd-video.dtsi2
-rw-r--r--arch/arm/boot/dts/qcom/msm8996-cv2x.dtsi132
-rw-r--r--arch/arm/boot/dts/qcom/sdm455.dtsi14
-rw-r--r--arch/arm/boot/dts/qcom/sdm630-cdp.dtsi9
-rw-r--r--arch/arm/boot/dts/qcom/sdm630-mdss-panels.dtsi13
-rw-r--r--arch/arm/boot/dts/qcom/sdm630-mtp.dtsi9
-rw-r--r--arch/arm/boot/dts/qcom/sdm630-qrd.dtsi12
-rw-r--r--arch/arm/boot/dts/qcom/sdm660-pinctrl.dtsi46
-rw-r--r--arch/arm/boot/dts/qcom/sdm660.dtsi4
-rw-r--r--arch/arm/boot/dts/qcom/vplatform-lfv-msm8996-ivi-la.dts4
-rw-r--r--arch/arm/boot/dts/qcom/vplatform-lfv-msm8996-ivi.dts21
-rw-r--r--arch/arm/configs/imx_v6_v7_defconfig2
-rw-r--r--arch/arm/include/asm/arch_gicv3.h1
-rw-r--r--arch/arm/kernel/entry-common.S10
-rw-r--r--arch/arm/kernel/signal.c7
-rw-r--r--arch/arm/mach-exynos/suspend.c1
-rw-r--r--arch/arm/mach-hisi/hotplug.c41
-rw-r--r--arch/arm64/configs/msm-auto-perf_defconfig1
-rw-r--r--arch/arm64/configs/msm-auto_defconfig1
-rw-r--r--arch/arm64/include/asm/thread_info.h5
-rw-r--r--arch/arm64/include/asm/uaccess.h3
-rw-r--r--arch/arm64/kernel/signal.c4
-rw-r--r--arch/mips/ath79/setup.c1
-rw-r--r--arch/mips/cavium-octeon/octeon-platform.c2
-rw-r--r--arch/mips/include/asm/io.h8
-rw-r--r--arch/mips/include/asm/mach-ath79/ath79.h1
-rw-r--r--arch/mips/jz4740/Platform2
-rw-r--r--arch/mips/kernel/process.c1
-rw-r--r--arch/mips/kernel/vdso.c20
-rw-r--r--arch/mips/loongson64/common/cs5536/cs5536_ohci.c2
-rw-r--r--arch/mips/mm/c-r4k.c6
-rw-r--r--arch/openrisc/kernel/process.c2
-rw-r--r--arch/powerpc/platforms/powernv/opal.c2
-rw-r--r--arch/powerpc/platforms/pseries/ras.c2
-rw-r--r--arch/powerpc/sysdev/mpic_msgr.c2
-rw-r--r--arch/s390/lib/mem.S9
-rw-r--r--arch/x86/entry/common.c3
-rw-r--r--arch/x86/include/asm/pgtable-3level.h7
-rw-r--r--arch/x86/include/asm/pgtable.h2
-rw-r--r--arch/x86/include/asm/processor.h4
-rw-r--r--arch/x86/include/asm/thread_info.h4
-rw-r--r--arch/x86/include/asm/uaccess.h7
-rw-r--r--arch/x86/kernel/cpu/bugs.c47
-rw-r--r--arch/x86/kernel/cpu/common.c2
-rw-r--r--arch/x86/mm/fault.c2
-rw-r--r--block/blk-cgroup.c9
-rw-r--r--block/cfq-iosched.c6
-rw-r--r--block/partitions/aix.c13
-rw-r--r--drivers/android/binder.c55
-rw-r--r--drivers/ata/libahci.c2
-rw-r--r--drivers/bluetooth/Kconfig1
-rw-r--r--drivers/clk/imx/clk-imx6ul.c1
-rw-r--r--drivers/clk/qcom/mdss/mdss-pll-util.c18
-rw-r--r--drivers/crypto/msm/qce50.c5
-rw-r--r--drivers/crypto/sahara.c4
-rw-r--r--drivers/crypto/vmx/aes_cbc.c30
-rw-r--r--drivers/dma/pl330.c5
-rw-r--r--drivers/gpio/gpio-ml-ioh.c3
-rw-r--r--drivers/gpio/gpio-tegra.c2
-rw-r--r--drivers/gpio/gpiolib.h2
-rw-r--r--drivers/gpu/drm/amd/amdkfd/kfd_process.c2
-rw-r--r--drivers/gpu/drm/msm/hdmi-staging/sde_hdmi.c45
-rw-r--r--drivers/gpu/drm/msm/hdmi-staging/sde_hdmi.h2
-rw-r--r--drivers/gpu/drm/msm/hdmi-staging/sde_hdmi_bridge.c11
-rw-r--r--drivers/gpu/drm/msm/hdmi-staging/sde_hdmi_util.c112
-rw-r--r--drivers/gpu/drm/msm/hdmi-staging/sde_hdmi_util.h8
-rw-r--r--drivers/gpu/drm/msm/sde/sde_connector.c11
-rw-r--r--drivers/gpu/drm/nouveau/nvkm/engine/device/tegra.c13
-rw-r--r--drivers/gpu/drm/panel/panel-samsung-s6e8aa0.c2
-rw-r--r--drivers/gpu/msm/kgsl.c39
-rw-r--r--drivers/hwtracing/coresight/coresight-tpiu.c7
-rw-r--r--drivers/hwtracing/coresight/coresight.c7
-rw-r--r--drivers/i2c/busses/i2c-i801.c7
-rw-r--r--drivers/i2c/busses/i2c-msm-v2.c6
-rw-r--r--drivers/i2c/busses/i2c-xiic.c4
-rw-r--r--drivers/infiniband/core/cma.c25
-rw-r--r--drivers/infiniband/ulp/ipoib/ipoib_cm.c2
-rw-r--r--drivers/input/touchscreen/atmel_mxt_ts.c7
-rw-r--r--drivers/iommu/arm-smmu-v3.c1
-rw-r--r--drivers/iommu/iommu-debug.c2
-rw-r--r--drivers/iommu/ipmmu-vmsa.c9
-rw-r--r--drivers/irqchip/irq-bcm7038-l1.c4
-rw-r--r--drivers/irqchip/irq-gic-v3-its.c34
-rw-r--r--drivers/irqchip/irq-gic.c2
-rw-r--r--drivers/macintosh/via-pmu.c9
-rw-r--r--drivers/md/dm-kcopyd.c2
-rw-r--r--drivers/md/raid5.c6
-rw-r--r--drivers/media/platform/msm/camera_v2/msm_buf_mgr/msm_generic_buf_mgr.c8
-rw-r--r--drivers/media/platform/msm/vidc/msm_vidc.c9
-rw-r--r--drivers/media/platform/msm/vidc/msm_vidc_common.c21
-rw-r--r--drivers/media/platform/msm/vidc/msm_vidc_internal.h9
-rw-r--r--drivers/media/v4l2-core/videobuf2-core.c5
-rw-r--r--drivers/mfd/sm501.c1
-rw-r--r--drivers/mfd/ti_am335x_tscadc.c3
-rw-r--r--drivers/misc/hmc6352.c2
-rw-r--r--drivers/misc/lkdtm.c82
-rw-r--r--drivers/misc/mei/bus-fixup.c2
-rw-r--r--drivers/misc/mei/pci-me.c5
-rw-r--r--drivers/misc/mic/scif/scif_api.c20
-rw-r--r--drivers/misc/ti-st/st_kim.c4
-rw-r--r--drivers/misc/vmw_balloon.c1
-rw-r--r--drivers/mtd/maps/solutionengine.c6
-rw-r--r--drivers/mtd/mtdchar.c10
-rw-r--r--drivers/mtd/ubi/wl.c8
-rw-r--r--drivers/net/ethernet/broadcom/genet/bcmgenet.h3
-rw-r--r--drivers/net/ethernet/broadcom/genet/bcmmii.c10
-rw-r--r--drivers/net/ethernet/cisco/enic/enic_main.c2
-rw-r--r--drivers/net/ethernet/marvell/mvneta.c1
-rw-r--r--drivers/net/ethernet/qlogic/qlge/qlge_main.c23
-rw-r--r--drivers/net/ethernet/ti/cpsw.c49
-rw-r--r--drivers/net/ethernet/ti/cpsw.h1
-rw-r--r--drivers/net/ethernet/ti/davinci_emac.c1
-rw-r--r--drivers/net/wireless/ath/ath10k/mac.c7
-rw-r--r--drivers/net/wireless/cnss2/bus.c1
-rw-r--r--drivers/net/wireless/cnss2/bus.h2
-rw-r--r--drivers/net/wireless/cnss2/main.c53
-rw-r--r--drivers/net/wireless/cnss2/pci.c93
-rw-r--r--drivers/net/wireless/cnss2/wlan_firmware_service_v01.c101
-rw-r--r--drivers/net/wireless/cnss2/wlan_firmware_service_v01.h15
-rw-r--r--drivers/net/wireless/wcnss/wcnss_wlan.c6
-rw-r--r--drivers/net/xen-netfront.c30
-rw-r--r--drivers/parport/parport_sunbpp.c8
-rw-r--r--drivers/pci/host/pci-mvebu.c2
-rw-r--r--drivers/pinctrl/qcom/pinctrl-sdm660.c30
-rw-r--r--drivers/pinctrl/qcom/pinctrl-spmi-gpio.c32
-rw-r--r--drivers/platform/msm/ipa/ipa_v3/ipa_rt.c22
-rw-r--r--drivers/platform/x86/asus-nb-wmi.c1
-rw-r--r--drivers/platform/x86/toshiba_acpi.c3
-rw-r--r--drivers/rtc/rtc-bq4802.c4
-rw-r--r--drivers/s390/block/dasd_eckd.c7
-rw-r--r--drivers/s390/net/qeth_core_main.c3
-rw-r--r--drivers/s390/net/qeth_core_sys.c1
-rw-r--r--drivers/scsi/3w-9xxx.c6
-rw-r--r--drivers/scsi/3w-sas.c3
-rw-r--r--drivers/scsi/3w-xxxx.c2
-rw-r--r--drivers/scsi/aic94xx/aic94xx_init.c4
-rw-r--r--drivers/soc/qcom/hab/hab.c22
-rw-r--r--drivers/soc/qcom/hab/hab_mem_linux.c462
-rw-r--r--drivers/soc/qcom/hab/hab_mimex.c12
-rw-r--r--drivers/soc/qcom/hab/hab_msg.c1
-rw-r--r--drivers/soc/qcom/hab/hab_vchan.c22
-rw-r--r--drivers/soc/qcom/qdsp6v2/audio-anc-dev-mgr.c69
-rw-r--r--drivers/soc/qcom/qdsp6v2/audio_anc.c17
-rw-r--r--drivers/soc/qcom/qdsp6v2/sdsp-anc.c243
-rw-r--r--drivers/soc/qcom/subsystem_notif_virt.c7
-rw-r--r--drivers/soc/qcom/wcd-dsp-glink.c84
-rw-r--r--[-rwxr-xr-x]drivers/soundwire/soundwire.c4
-rw-r--r--drivers/soundwire/swr-wcd-ctrl.c4
-rw-r--r--drivers/staging/android/ion/ion.c48
-rw-r--r--drivers/staging/android/ion/ion_cma_heap.c27
-rw-r--r--drivers/staging/android/ion/ion_system_heap.c12
-rw-r--r--drivers/staging/android/ion/ion_system_secure_heap.c10
-rw-r--r--drivers/staging/android/ion/msm/msm_ion.c15
-rw-r--r--drivers/staging/android/ion/msm/msm_ion.h9
-rw-r--r--drivers/staging/comedi/drivers/ni_mio_common.c3
-rw-r--r--drivers/staging/rts5208/rtsx_scsi.c2
-rw-r--r--drivers/staging/rts5208/xd.c2
-rw-r--r--drivers/target/target_core_transport.c5
-rw-r--r--drivers/tty/rocket.c2
-rw-r--r--drivers/uio/uio.c3
-rw-r--r--drivers/usb/class/cdc-wdm.c2
-rw-r--r--drivers/usb/core/hcd-pci.c2
-rw-r--r--drivers/usb/core/message.c11
-rw-r--r--drivers/usb/core/quirks.c7
-rw-r--r--drivers/usb/dwc3/core.h8
-rw-r--r--drivers/usb/dwc3/dwc3-msm.c17
-rw-r--r--drivers/usb/dwc3/ep0.c37
-rw-r--r--drivers/usb/dwc3/gadget.c142
-rw-r--r--drivers/usb/gadget/udc/net2280.c16
-rw-r--r--drivers/usb/host/u132-hcd.c2
-rw-r--r--drivers/usb/host/xhci.c3
-rw-r--r--drivers/usb/misc/Kconfig15
-rw-r--r--drivers/usb/misc/uss720.c4
-rw-r--r--drivers/usb/misc/yurex.c5
-rw-r--r--drivers/usb/serial/io_ti.h2
-rw-r--r--drivers/usb/serial/ti_usb_3410_5052.h2
-rw-r--r--drivers/usb/storage/scsiglue.c9
-rw-r--r--drivers/usb/storage/unusual_devs.h7
-rw-r--r--drivers/video/fbdev/core/modedb.c41
-rw-r--r--drivers/video/fbdev/goldfishfb.c1
-rw-r--r--drivers/video/fbdev/msm/mdss_debug.c41
-rw-r--r--drivers/video/fbdev/msm/mdss_dsi_panel.c14
-rw-r--r--drivers/video/fbdev/msm/mdss_mdp_ctl.c7
-rw-r--r--drivers/video/fbdev/msm/mdss_mdp_intf_cmd.c10
-rw-r--r--drivers/video/fbdev/msm/msm_dba/adv7533.c21
-rw-r--r--drivers/video/fbdev/omap/omapfb_main.c2
-rw-r--r--drivers/video/fbdev/via/viafbdev.c3
-rw-r--r--fs/autofs4/autofs_i.h4
-rw-r--r--fs/autofs4/inode.c1
-rw-r--r--fs/binfmt_elf.c2
-rw-r--r--fs/btrfs/dev-replace.c6
-rw-r--r--fs/btrfs/disk-io.c10
-rw-r--r--fs/btrfs/extent-tree.c2
-rw-r--r--fs/btrfs/relocation.c23
-rw-r--r--fs/cifs/cifs_debug.c8
-rw-r--r--fs/cifs/file.c8
-rw-r--r--fs/cifs/readdir.c11
-rw-r--r--fs/cifs/smb2misc.c7
-rw-r--r--fs/cifs/smb2pdu.c27
-rw-r--r--fs/dcache.c3
-rw-r--r--fs/f2fs/segment.h3
-rw-r--r--fs/f2fs/super.c21
-rw-r--r--fs/fat/cache.c19
-rw-r--r--fs/fat/fat.h5
-rw-r--r--fs/fat/fatent.c6
-rw-r--r--fs/gfs2/bmap.c2
-rw-r--r--fs/hfs/brec.c7
-rw-r--r--fs/hfsplus/dir.c4
-rw-r--r--fs/hfsplus/super.c4
-rw-r--r--fs/nfs/callback_xdr.c11
-rw-r--r--fs/overlayfs/copy_up.c26
-rw-r--r--fs/overlayfs/dir.c67
-rw-r--r--fs/overlayfs/overlayfs.h3
-rw-r--r--fs/overlayfs/readdir.c93
-rw-r--r--fs/overlayfs/super.c20
-rw-r--r--fs/pstore/ram_core.c17
-rw-r--r--fs/reiserfs/reiserfs.h2
-rw-r--r--fs/sdcardfs/main.c2
-rw-r--r--fs/sdcardfs/super.c2
-rw-r--r--include/linux/bug.h19
-rw-r--r--include/linux/list.h37
-rw-r--r--include/linux/mm_types.h2
-rw-r--r--include/linux/mmdebug.h6
-rw-r--r--include/linux/page-flags.h211
-rw-r--r--include/linux/pagemap.h25
-rw-r--r--include/linux/qdsp6v2/audio-anc-dev-mgr.h2
-rw-r--r--include/linux/qdsp6v2/sdsp_anc.h97
-rw-r--r--include/linux/rculist.h8
-rw-r--r--include/linux/sched.h2
-rw-r--r--include/linux/syscalls.h20
-rw-r--r--include/linux/vm_event_item.h1
-rw-r--r--include/linux/vmacache.h5
-rw-r--r--include/net/cnss2.h3
-rw-r--r--include/uapi/drm/msm_drm.h9
-rw-r--r--include/uapi/linux/android/binder.h10
-rw-r--r--include/uapi/linux/ethtool.h4
-rw-r--r--include/uapi/linux/msm_audio_anc.h17
-rw-r--r--include/uapi/linux/msm_kgsl.h2
-rw-r--r--kernel/audit_watch.c12
-rw-r--r--kernel/fork.c19
-rw-r--r--kernel/irq/chip.c8
-rw-r--r--kernel/locking/rwsem-xadd.c56
-rw-r--r--lib/Kconfig.debug18
-rw-r--r--lib/debugobjects.c7
-rw-r--r--lib/list_debug.c116
-rw-r--r--mm/debug.c4
-rw-r--r--mm/fadvise.c8
-rw-r--r--mm/filemap.c15
-rw-r--r--mm/huge_memory.c2
-rw-r--r--mm/ksm.c2
-rw-r--r--mm/memory-failure.c2
-rw-r--r--mm/migrate.c2
-rw-r--r--mm/shmem.c4
-rw-r--r--mm/slub.c2
-rw-r--r--mm/swap_state.c4
-rw-r--r--mm/vmacache.c38
-rw-r--r--mm/vmscan.c2
-rw-r--r--net/9p/trans_virtio.c3
-rw-r--r--net/bluetooth/hidp/core.c2
-rw-r--r--net/dcb/dcbnl.c11
-rw-r--r--net/ipv4/tcp_minisocks.c3
-rw-r--r--net/ipv6/ip6_vti.c2
-rw-r--r--net/irda/af_irda.c13
-rw-r--r--net/mac80211/cfg.c2
-rw-r--r--net/mac80211/key.c24
-rw-r--r--net/netfilter/ipvs/ip_vs_core.c15
-rw-r--r--net/netfilter/x_tables.c4
-rw-r--r--net/sched/sch_hhf.c3
-rw-r--r--net/sched/sch_htb.c5
-rw-r--r--net/sched/sch_multiq.c9
-rw-r--r--net/sched/sch_netem.c4
-rw-r--r--net/sched/sch_tbf.c5
-rw-r--r--net/xfrm/xfrm_policy.c5
-rw-r--r--scripts/Kbuild.include3
-rwxr-xr-xscripts/depmod.sh4
-rw-r--r--scripts/mod/modpost.c8
-rw-r--r--security/selinux/avc.c14
-rw-r--r--sound/core/pcm_lib.c14
-rw-r--r--sound/isa/msnd/msnd_pinnacle.c4
-rw-r--r--sound/pci/hda/hda_codec.c3
-rw-r--r--sound/soc/codecs/wm8994.c1
-rw-r--r--sound/soc/codecs/wsa881x.c43
-rw-r--r--sound/usb/quirks-table.h3
-rw-r--r--tools/hv/hv_kvp_daemon.c2
-rw-r--r--tools/perf/arch/powerpc/util/skip-callchain-idx.c10
-rw-r--r--tools/perf/perf.h2
-rw-r--r--tools/testing/selftests/powerpc/harness.c18
-rw-r--r--tools/testing/selftests/timers/raw_skew.c5
293 files changed, 3103 insertions, 1628 deletions
diff --git a/Makefile b/Makefile
index b00095469841..50f15f7bf3c3 100644
--- a/Makefile
+++ b/Makefile
@@ -1,6 +1,6 @@
VERSION = 4
PATCHLEVEL = 4
-SUBLEVEL = 155
+SUBLEVEL = 158
EXTRAVERSION =
NAME = Blurry Fish Butt
diff --git a/arch/arc/configs/axs101_defconfig b/arch/arc/configs/axs101_defconfig
index f1ac9818b751..dbee1934dfc6 100644
--- a/arch/arc/configs/axs101_defconfig
+++ b/arch/arc/configs/axs101_defconfig
@@ -1,6 +1,5 @@
CONFIG_CROSS_COMPILE="arc-linux-"
CONFIG_DEFAULT_HOSTNAME="ARCLinux"
-# CONFIG_SWAP is not set
CONFIG_SYSVIPC=y
CONFIG_POSIX_MQUEUE=y
# CONFIG_CROSS_MEMORY_ATTACH is not set
diff --git a/arch/arc/configs/axs103_defconfig b/arch/arc/configs/axs103_defconfig
index 323486d6ee83..561eac854cc3 100644
--- a/arch/arc/configs/axs103_defconfig
+++ b/arch/arc/configs/axs103_defconfig
@@ -1,6 +1,5 @@
CONFIG_CROSS_COMPILE="arc-linux-"
CONFIG_DEFAULT_HOSTNAME="ARCLinux"
-# CONFIG_SWAP is not set
CONFIG_SYSVIPC=y
CONFIG_POSIX_MQUEUE=y
# CONFIG_CROSS_MEMORY_ATTACH is not set
diff --git a/arch/arc/configs/axs103_smp_defconfig b/arch/arc/configs/axs103_smp_defconfig
index 66191cd0447e..aa4f261b6508 100644
--- a/arch/arc/configs/axs103_smp_defconfig
+++ b/arch/arc/configs/axs103_smp_defconfig
@@ -1,6 +1,5 @@
CONFIG_CROSS_COMPILE="arc-linux-"
CONFIG_DEFAULT_HOSTNAME="ARCLinux"
-# CONFIG_SWAP is not set
CONFIG_SYSVIPC=y
CONFIG_POSIX_MQUEUE=y
# CONFIG_CROSS_MEMORY_ATTACH is not set
diff --git a/arch/arm/boot/dts/qcom/apq8016-sbc.dtsi b/arch/arm/boot/dts/qcom/apq8016-sbc.dtsi
index 6b8abbe68746..3011c88bd2f3 100644
--- a/arch/arm/boot/dts/qcom/apq8016-sbc.dtsi
+++ b/arch/arm/boot/dts/qcom/apq8016-sbc.dtsi
@@ -105,7 +105,7 @@
led@6 {
label = "apq8016-sbc:blue:bt";
gpios = <&pm8916_mpps 3 GPIO_ACTIVE_HIGH>;
- linux,default-trigger = "bt";
+ linux,default-trigger = "bluetooth-power";
default-state = "off";
};
};
diff --git a/arch/arm/boot/dts/qcom/dsi-panel-lgd-incell-sw49106-fhd-video.dtsi b/arch/arm/boot/dts/qcom/dsi-panel-lgd-incell-sw49106-fhd-video.dtsi
index 8db5317f2106..7eb677d14814 100644
--- a/arch/arm/boot/dts/qcom/dsi-panel-lgd-incell-sw49106-fhd-video.dtsi
+++ b/arch/arm/boot/dts/qcom/dsi-panel-lgd-incell-sw49106-fhd-video.dtsi
@@ -108,7 +108,7 @@
qcom,mdss-dsi-on-command-state = "dsi_lp_mode";
qcom,mdss-dsi-off-command-state = "dsi_lp_mode";
qcom,mdss-dsi-bl-pmic-control-type = "bl_ctrl_wled";
- qcom,mdss-dsi-reset-sequence = <1 200>, <0 200>, <1 200>;
+ qcom,mdss-dsi-reset-sequence = <1 400>, <0 400>, <1 400>;
qcom,mdss-dsi-tx-eot-append;
qcom,mdss-dsi-post-init-delay = <1>;
};
diff --git a/arch/arm/boot/dts/qcom/msm8996-cv2x.dtsi b/arch/arm/boot/dts/qcom/msm8996-cv2x.dtsi
index 8be20b4d2413..5a266cd9cf62 100644
--- a/arch/arm/boot/dts/qcom/msm8996-cv2x.dtsi
+++ b/arch/arm/boot/dts/qcom/msm8996-cv2x.dtsi
@@ -21,13 +21,6 @@
};
};
- aliases {
- mhi_rmnet0 = &mhi_rmnet_0;
- mhi_rmnet1 = &mhi_rmnet_1;
- mhi_uci0 = &mhi_uci;
- mhi0 = &mhi;
- };
-
gpio-leds {
compatible = "gpio-leds";
@@ -146,52 +139,6 @@
gpio = <&tlmm 125 0>;
};
- mhi_rmnet_0: qcom,mhi-rmnet@0 {
- compatible = "qcom,mhi-rmnet";
- cell-index = <0>;
- qcom,mhi = <&mhi>;
- qcom,mhi-rx-channel = <101>;
- qcom,mhi-tx-channel = <100>;
- qcom,mhi-mru = <0x4000>;
- status = "okay";
- };
-
- mhi_rmnet_1: qcom,mhi-rmnet@1 {
- compatible = "qcom,mhi-rmnet";
- cell-index = <1>;
- qcom,mhi = <&mhi>;
- qcom,mhi-rx-channel = <47>;
- qcom,mhi-tx-channel = <46>;
- qcom,mhi-mru = <0x4000>;
- qcom,interface-name = "mhi_swip";
- status = "okay";
- };
-
- mhi_uci: qcom,mhi-uci {
- compatible = "qcom,mhi-uci";
- qcom,mhi-uci-channels = <0 0xffff>,
- <1 0x1000>,
- <2 0xffff>,
- <3 0xffff>,
- <10 0xffff>,
- <11 0x1000>,
- <14 0xffff>,
- <15 0x1000>,
- <16 0xffff>,
- <17 0x1000>,
- <18 0xffff>,
- <19 0x1000>,
- <22 0xffff>,
- <23 0x1000>,
- <24 0xffff>,
- <25 0x1000>,
- <32 0xffff>,
- <33 0x1000>;
- qcom,mhi-uci-ctrlchan = <18>;
- qcom,mhi = <&mhi>;
- status = "okay";
- };
-
qcom,diagfwd-usb {
compatible = "qcom,diagfwd-usb";
status = "okay";
@@ -362,85 +309,6 @@
/delete-property/ qcom,l1ss-supported;
};
-&mdm3 {
- pinctrl-names = "mdm_active", "mdm_suspend";
- pinctrl-0 = <&ap2mdm_active &mdm2ap_active>;
- pinctrl-1 = <&ap2mdm_sleep &mdm2ap_sleep>;
- interrupt-map = <0 &tlmm 108 0x3
- 1 &tlmm 106 0x3
- 2 &tlmm 112 0x3>;
- qcom,mdm2ap-errfatal-gpio = <&tlmm 108 0x00>;
- qcom,ap2mdm-errfatal-gpio = <&tlmm 109 0x00>;
- qcom,mdm2ap-status-gpio = <&tlmm 106 0x00>;
- qcom,ap2mdm-status-gpio = <&tlmm 107 0x00>;
- qcom,ap2mdm-soft-reset-gpio = <&pm8994_mpps 2 0x00>;
- qcom,ap2mdm-vddmin-gpio = <&tlmm 111 0x00>;
- qcom,mdm2ap-vddmin-gpio = <&tlmm 112 0x00>;
- qcom,mdm-auto-boot;
- qcom,ignore-ssr-failure;
- qcom,mdm-link-info = "0302_02.01.00";
- qcom,mdm-statusline-not-a-powersource;
- qcom,mdm-userspace-handle-shutdown;
- qcom,pil-force-shutdown;
- qcom,shutdown-timeout-ms = <30000>;
- qcom,reset-time-ms = <16203>;
- status = "okay";
-};
-
-&mhi {
- qcom,mhi-address-window = <0x0 0x80000000 0x1 0xffffffff>;
- qcom,pci-dev_id = <0x0302>;
- qcom,pci-domain = <2>;
- qcom,pci-bus = <1>;
- qcom,pci-slot = <0>;
- esoc-names = "mdm";
- esoc-0 = <&mdm3>;
- qcom,msm-bus,name = "mhi";
- qcom,msm-bus,num-cases = <2>;
- qcom,msm-bus,num-paths = <1>;
- qcom,msm-bus,vectors-KBps =
- <100 512 0 0>,
- <100 512 1200000000 650000000>;
- mhi-chan-cfg-0 = <0x0 0x80 0x2 0x92>;
- mhi-chan-cfg-1 = <0x1 0x80 0x2 0xa2>;
- mhi-chan-cfg-2 = <0x2 0x80 0x1 0x91>;
- mhi-chan-cfg-3 = <0x3 0x80 0x1 0xa1>;
- mhi-chan-cfg-4 = <0x4 0x80 0x2 0x92>;
- mhi-chan-cfg-5 = <0x5 0x80 0x2 0xa2>;
- mhi-chan-cfg-6 = <0x6 0xa 0x2 0x92>;
- mhi-chan-cfg-7 = <0x7 0xa 0x2 0xa2>;
- mhi-chan-cfg-10 = <0xa 0x80 0x1 0x92>;
- mhi-chan-cfg-11 = <0xb 0x80 0x1 0xa2>;
- mhi-chan-cfg-14 = <0xe 0x40 0x1 0x92>;
- mhi-chan-cfg-15 = <0xf 0x40 0x1 0xa2>;
- mhi-chan-cfg-16 = <0x10 0x40 0x1 0x92>;
- mhi-chan-cfg-17 = <0x11 0x40 0x1 0xa2>;
- mhi-chan-cfg-18 = <0x12 0x40 0x1 0x92>;
- mhi-chan-cfg-19 = <0x13 0x40 0x1 0xa2>;
- mhi-chan-cfg-20 = <0x14 0xa 0x2 0x92>;
- mhi-chan-cfg-21 = <0x15 0xa 0x2 0xa2>;
- mhi-chan-cfg-22 = <0x16 0x40 0x2 0x92>;
- mhi-chan-cfg-23 = <0x17 0x40 0x2 0xa2>;
- mhi-chan-cfg-24 = <0x18 0xa 0x1 0x91>;
- mhi-chan-cfg-25 = <0x19 0xa 0x1 0xa1>;
- mhi-chan-cfg-32 = <0x20 0x80 0x2 0x92>;
- mhi-chan-cfg-33 = <0x21 0x80 0x2 0xa2>;
- mhi-chan-cfg-34 = <0x22 0x80 0x2 0x92>;
- mhi-chan-cfg-35 = <0x23 0x80 0x2 0xa2>;
- mhi-chan-cfg-46 = <0x2e 0x80 0x2 0x412>;
- mhi-chan-cfg-47 = <0x2f 0x80 0x3 0x422>;
- mhi-chan-cfg-100 = <0x64 0x80 0x4 0x652>;
- mhi-chan-cfg-101 = <0x65 0x80 0x5 0x762>;
- mhi-event-rings = <6>;
- mhi-event-cfg-0 = <0x80 0x0 0x1 0 1 0x11>;
- mhi-event-cfg-1 = <0x80 0x1 0x1 0 1 0x11>;
- mhi-event-cfg-2 = <0x80 0x2 0x5 0 2 0x11>;
- mhi-event-cfg-3 = <0x100 0x3 0x1 47 1 0x48>;
- mhi-event-cfg-4 = <0x100 0x4 0x1 100 1 0x69>;
- mhi-event-cfg-5 = <0x100 0x5 0x1 101 1 0x68>;
- status = "okay";
-};
-
&pm8994_gpios {
gpio@c700 { /* GPIO 8 - WLAN_EN */
qcom,mode = <1>; /* Digital output*/
diff --git a/arch/arm/boot/dts/qcom/sdm455.dtsi b/arch/arm/boot/dts/qcom/sdm455.dtsi
index e37416783b30..1f3e406f5f12 100644
--- a/arch/arm/boot/dts/qcom/sdm455.dtsi
+++ b/arch/arm/boot/dts/qcom/sdm455.dtsi
@@ -43,3 +43,17 @@
/delete-property/ qcom,mdss-dest-scaler-lut-off;
};
};
+
+&soc {
+ /delete-node/ devfreq_memlat_0;
+ devfreq_memlat_0: qcom,arm-memlat-mon-0 {
+ compatible = "qcom,arm-memlat-mon";
+ qcom,cpulist = <&CPU0 &CPU1 &CPU2 &CPU3>;
+ qcom,target-dev = <&memlat_cpu0>;
+ qcom,core-dev-table =
+ < 1113600 762 >,
+ < 1344000 2086 >,
+ < 1670400 4943 >,
+ < 2016000 5163 >;
+ };
+};
diff --git a/arch/arm/boot/dts/qcom/sdm630-cdp.dtsi b/arch/arm/boot/dts/qcom/sdm630-cdp.dtsi
index fd109450ad81..6b409c091527 100644
--- a/arch/arm/boot/dts/qcom/sdm630-cdp.dtsi
+++ b/arch/arm/boot/dts/qcom/sdm630-cdp.dtsi
@@ -1,4 +1,4 @@
-/* Copyright (c) 2017, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2017-2018, 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
@@ -193,6 +193,13 @@
qcom,panel-roi-alignment = <2 2 4 2 1080 2>;
};
+&dsi_lgd_incell_sw49106_fhd_video {
+ qcom,mdss-dsi-bl-pmic-control-type = "bl_ctrl_wled";
+ qcom,mdss-dsi-bl-min-level = <1>;
+ qcom,mdss-dsi-bl-max-level = <4095>;
+ qcom,panel-supply-entries = <&dsi_panel_pwr_supply>;
+};
+
&pm660l_pwm_4 {
qcom,dtest-line = <2>; /* DTEST2 */
qcom,dtest-output = <2>; /* OUTPUT PWM */
diff --git a/arch/arm/boot/dts/qcom/sdm630-mdss-panels.dtsi b/arch/arm/boot/dts/qcom/sdm630-mdss-panels.dtsi
index 4e3ebd445814..16cfbd0e97bc 100644
--- a/arch/arm/boot/dts/qcom/sdm630-mdss-panels.dtsi
+++ b/arch/arm/boot/dts/qcom/sdm630-mdss-panels.dtsi
@@ -1,4 +1,4 @@
-/* Copyright (c) 2017, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2017-2018, The Linux Foundation. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 and
@@ -17,6 +17,7 @@
#include "dsi-panel-truly-1080p-video.dtsi"
#include "dsi-panel-rm67195-amoled-fhd-cmd.dtsi"
#include "dsi-panel-sharp-split-link-wuxga-video.dtsi"
+#include "dsi-panel-lgd-incell-sw49106-fhd-video.dtsi"
&soc {
dsi_panel_pwr_supply: dsi_panel_pwr_supply {
@@ -243,3 +244,13 @@
qcom,mdss-dsi-pan-enable-dynamic-fps;
qcom,mdss-dsi-pan-fps-update = "dfps_immediate_porch_mode_vfp";
};
+
+&dsi_lgd_incell_sw49106_fhd_video {
+ qcom,mdss-dsi-panel-timings-phy-v2 = [24 1f 08 09 05 03 04 a0
+ 24 1f 08 09 05 03 04 a0
+ 24 1f 08 09 05 03 04 a0
+ 24 1f 08 09 05 03 04 a0
+ 24 1b 08 09 05 03 04 a0];
+ qcom,mdss-dsi-t-clk-post = <0x0d>;
+ qcom,mdss-dsi-t-clk-pre = <0x30>;
+};
diff --git a/arch/arm/boot/dts/qcom/sdm630-mtp.dtsi b/arch/arm/boot/dts/qcom/sdm630-mtp.dtsi
index fd7cc8a7c5c2..19d1cb4d2210 100644
--- a/arch/arm/boot/dts/qcom/sdm630-mtp.dtsi
+++ b/arch/arm/boot/dts/qcom/sdm630-mtp.dtsi
@@ -1,4 +1,4 @@
-/* Copyright (c) 2017, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2017-2018, 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
@@ -216,3 +216,10 @@
&dsi_rm67195_amoled_fhd_cmd {
qcom,panel-supply-entries = <&dsi_panel_pwr_supply_labibb_amoled>;
};
+
+&dsi_lgd_incell_sw49106_fhd_video {
+ qcom,mdss-dsi-bl-pmic-control-type = "bl_ctrl_wled";
+ qcom,mdss-dsi-bl-min-level = <1>;
+ qcom,mdss-dsi-bl-max-level = <4095>;
+ qcom,panel-supply-entries = <&dsi_panel_pwr_supply>;
+};
diff --git a/arch/arm/boot/dts/qcom/sdm630-qrd.dtsi b/arch/arm/boot/dts/qcom/sdm630-qrd.dtsi
index 384e24d221c4..82e80891e05d 100644
--- a/arch/arm/boot/dts/qcom/sdm630-qrd.dtsi
+++ b/arch/arm/boot/dts/qcom/sdm630-qrd.dtsi
@@ -1,4 +1,4 @@
-/* Copyright (c) 2017, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2017-2018, 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
@@ -366,16 +366,6 @@
gpio-key,wakeup;
debounce-interval = <15>;
};
-
- home {
- label = "home";
- gpios = <&pm660_gpios 11 0x1>;
- linux,input-type = <1>;
- linux,code = <102>;
- gpio-key,wakeup;
- debounce-interval = <15>;
- };
-
};
hbtp {
diff --git a/arch/arm/boot/dts/qcom/sdm660-pinctrl.dtsi b/arch/arm/boot/dts/qcom/sdm660-pinctrl.dtsi
index 5b97aea1c013..eaab6fd3e1aa 100644
--- a/arch/arm/boot/dts/qcom/sdm660-pinctrl.dtsi
+++ b/arch/arm/boot/dts/qcom/sdm660-pinctrl.dtsi
@@ -75,6 +75,52 @@
};
};
+ ufs_dev_reset_assert: ufs_dev_reset_assert {
+ config {
+ pins = "ufs_reset";
+ bias-pull-down; /* default: pull down */
+ /*
+ * UFS_RESET driver strengths are having
+ * different values/steps compared to typical
+ * GPIO drive strengths.
+ *
+ * Following table clarifies:
+ *
+ * HDRV value | UFS_RESET | Typical GPIO
+ * (dec) | (mA) | (mA)
+ * 0 | 0.8 | 2
+ * 1 | 1.55 | 4
+ * 2 | 2.35 | 6
+ * 3 | 3.1 | 8
+ * 4 | 3.9 | 10
+ * 5 | 4.65 | 12
+ * 6 | 5.4 | 14
+ * 7 | 6.15 | 16
+ *
+ * POR value for UFS_RESET HDRV is 3 which means
+ * 3.1mA and we want to use that. Hence just
+ * specify 8mA to "drive-strength" binding and
+ * that should result into writing 3 to HDRV
+ * field.
+ */
+ drive-strength = <8>; /* default: 3.1 mA */
+ output-low; /* active low reset */
+ };
+ };
+
+ ufs_dev_reset_deassert: ufs_dev_reset_deassert {
+ config {
+ pins = "ufs_reset";
+ bias-pull-down; /* default: pull down */
+ /*
+ * default: 3.1 mA
+ * check comments under ufs_dev_reset_assert
+ */
+ drive-strength = <8>;
+ output-high; /* active low reset */
+ };
+ };
+
/* SDC pin type */
sdc1_clk_on: sdc1_clk_on {
config {
diff --git a/arch/arm/boot/dts/qcom/sdm660.dtsi b/arch/arm/boot/dts/qcom/sdm660.dtsi
index e8f32390704e..27bc0cebfc2a 100644
--- a/arch/arm/boot/dts/qcom/sdm660.dtsi
+++ b/arch/arm/boot/dts/qcom/sdm660.dtsi
@@ -2412,6 +2412,10 @@
"HS_RB_G1_L1", "HS_RB_G2_L1", "HS_RB_G3_L1",
"MAX";
+ pinctrl-names = "dev-reset-assert", "dev-reset-deassert";
+ pinctrl-0 = <&ufs_dev_reset_assert>;
+ pinctrl-1 = <&ufs_dev_reset_deassert>;
+
resets = <&clock_gcc GCC_UFS_BCR>;
reset-names = "core_reset";
diff --git a/arch/arm/boot/dts/qcom/vplatform-lfv-msm8996-ivi-la.dts b/arch/arm/boot/dts/qcom/vplatform-lfv-msm8996-ivi-la.dts
index 40595275b63a..3434514df69c 100644
--- a/arch/arm/boot/dts/qcom/vplatform-lfv-msm8996-ivi-la.dts
+++ b/arch/arm/boot/dts/qcom/vplatform-lfv-msm8996-ivi-la.dts
@@ -170,9 +170,7 @@
};
wlan {
subsys-name = "AR6320";
- interrupts = <0 43 0>;
- interrupt-names = "state-irq";
- type = "virtual";
+ type = "native";
offset = <512>;
};
diff --git a/arch/arm/boot/dts/qcom/vplatform-lfv-msm8996-ivi.dts b/arch/arm/boot/dts/qcom/vplatform-lfv-msm8996-ivi.dts
index 5f622b41fecd..ae2ec051d50e 100644
--- a/arch/arm/boot/dts/qcom/vplatform-lfv-msm8996-ivi.dts
+++ b/arch/arm/boot/dts/qcom/vplatform-lfv-msm8996-ivi.dts
@@ -20,14 +20,29 @@
qcom,msm-id = <246 0x0>;
};
+&ion {
+ /delete-node/ qcom,ion-heap@25;
+
+ system_heap: qcom,ion-heap@25 {
+ reg = <25>;
+ qcom,ion-heap-type = "SYSTEM";
+ };
+
+ audio_heap: qcom,ion-heap@28 {
+ reg = <28>;
+ memory-region = <&ion_audio>;
+ qcom,ion-heap-type = "CARVEOUT";
+ };
+};
+
&reserved_memory {
pmem_shared: pmem_shared_region@1154ca000 {
reg = <0x1 0x154ca000 0x0 0x154ca000>;
label = "pmem_shared_mem";
};
- ion_system: ion_system_region@12a994000 {
- reg = <0x1 0x2a994000 0x0 0x154ca000>;
- label = "ion_system_mem";
+ ion_audio: ion_audio_region {
+ reg = <0 0xf0000000 0 0x00400000>;
+ label = "ion_audio_mem";
};
};
diff --git a/arch/arm/configs/imx_v6_v7_defconfig b/arch/arm/configs/imx_v6_v7_defconfig
index b3490c1c49d1..4187f69f6630 100644
--- a/arch/arm/configs/imx_v6_v7_defconfig
+++ b/arch/arm/configs/imx_v6_v7_defconfig
@@ -261,7 +261,6 @@ CONFIG_USB_STORAGE=y
CONFIG_USB_CHIPIDEA=y
CONFIG_USB_CHIPIDEA_UDC=y
CONFIG_USB_CHIPIDEA_HOST=y
-CONFIG_USB_CHIPIDEA_ULPI=y
CONFIG_USB_SERIAL=m
CONFIG_USB_SERIAL_GENERIC=y
CONFIG_USB_SERIAL_FTDI_SIO=m
@@ -288,7 +287,6 @@ CONFIG_USB_G_NCM=m
CONFIG_USB_GADGETFS=m
CONFIG_USB_MASS_STORAGE=m
CONFIG_USB_G_SERIAL=m
-CONFIG_USB_ULPI_BUS=y
CONFIG_MMC=y
CONFIG_MMC_SDHCI=y
CONFIG_MMC_SDHCI_PLTFM=y
diff --git a/arch/arm/include/asm/arch_gicv3.h b/arch/arm/include/asm/arch_gicv3.h
index 7da5503c0591..e08d15184056 100644
--- a/arch/arm/include/asm/arch_gicv3.h
+++ b/arch/arm/include/asm/arch_gicv3.h
@@ -117,6 +117,7 @@ static inline u32 gic_read_iar(void)
u32 irqstat;
asm volatile("mrc " __stringify(ICC_IAR1) : "=r" (irqstat));
+ dsb(sy);
return irqstat;
}
diff --git a/arch/arm/kernel/entry-common.S b/arch/arm/kernel/entry-common.S
index 30a7228eaceb..9440b320a8a3 100644
--- a/arch/arm/kernel/entry-common.S
+++ b/arch/arm/kernel/entry-common.S
@@ -12,6 +12,7 @@
#include <asm/unistd.h>
#include <asm/ftrace.h>
#include <asm/unwind.h>
+#include <asm/memory.h>
#ifdef CONFIG_NEED_RET_TO_USER
#include <mach/entry-macro.S>
@@ -35,6 +36,9 @@ ret_fast_syscall:
UNWIND(.fnstart )
UNWIND(.cantunwind )
disable_irq_notrace @ disable interrupts
+ ldr r2, [tsk, #TI_ADDR_LIMIT]
+ cmp r2, #TASK_SIZE
+ blne addr_limit_check_failed
ldr r1, [tsk, #TI_FLAGS] @ re-check for syscall tracing
tst r1, #_TIF_SYSCALL_WORK | _TIF_WORK_MASK
bne fast_work_pending
@@ -61,6 +65,9 @@ ret_fast_syscall:
UNWIND(.cantunwind )
str r0, [sp, #S_R0 + S_OFF]! @ save returned r0
disable_irq_notrace @ disable interrupts
+ ldr r2, [tsk, #TI_ADDR_LIMIT]
+ cmp r2, #TASK_SIZE
+ blne addr_limit_check_failed
ldr r1, [tsk, #TI_FLAGS] @ re-check for syscall tracing
tst r1, #_TIF_SYSCALL_WORK | _TIF_WORK_MASK
beq no_work_pending
@@ -93,6 +100,9 @@ ENTRY(ret_to_user)
ret_slow_syscall:
disable_irq_notrace @ disable interrupts
ENTRY(ret_to_user_from_irq)
+ ldr r2, [tsk, #TI_ADDR_LIMIT]
+ cmp r2, #TASK_SIZE
+ blne addr_limit_check_failed
ldr r1, [tsk, #TI_FLAGS]
tst r1, #_TIF_WORK_MASK
bne slow_work_pending
diff --git a/arch/arm/kernel/signal.c b/arch/arm/kernel/signal.c
index 7b8f2141427b..304e68408f9c 100644
--- a/arch/arm/kernel/signal.c
+++ b/arch/arm/kernel/signal.c
@@ -14,6 +14,7 @@
#include <linux/uaccess.h>
#include <linux/tracehook.h>
#include <linux/uprobes.h>
+#include <linux/syscalls.h>
#include <asm/elf.h>
#include <asm/cacheflush.h>
@@ -631,3 +632,9 @@ struct page *get_signal_page(void)
return page;
}
+
+/* Defer to generic check */
+asmlinkage void addr_limit_check_failed(void)
+{
+ addr_limit_user_check();
+}
diff --git a/arch/arm/mach-exynos/suspend.c b/arch/arm/mach-exynos/suspend.c
index c169cc3049aa..e8adb428dddb 100644
--- a/arch/arm/mach-exynos/suspend.c
+++ b/arch/arm/mach-exynos/suspend.c
@@ -260,6 +260,7 @@ static int __init exynos_pmu_irq_init(struct device_node *node,
NULL);
if (!domain) {
iounmap(pmu_base_addr);
+ pmu_base_addr = NULL;
return -ENOMEM;
}
diff --git a/arch/arm/mach-hisi/hotplug.c b/arch/arm/mach-hisi/hotplug.c
index a129aae72602..909bb2493781 100644
--- a/arch/arm/mach-hisi/hotplug.c
+++ b/arch/arm/mach-hisi/hotplug.c
@@ -148,13 +148,20 @@ static int hi3xxx_hotplug_init(void)
struct device_node *node;
node = of_find_compatible_node(NULL, NULL, "hisilicon,sysctrl");
- if (node) {
- ctrl_base = of_iomap(node, 0);
- id = HI3620_CTRL;
- return 0;
+ if (!node) {
+ id = ERROR_CTRL;
+ return -ENOENT;
}
- id = ERROR_CTRL;
- return -ENOENT;
+
+ ctrl_base = of_iomap(node, 0);
+ of_node_put(node);
+ if (!ctrl_base) {
+ id = ERROR_CTRL;
+ return -ENOMEM;
+ }
+
+ id = HI3620_CTRL;
+ return 0;
}
void hi3xxx_set_cpu(int cpu, bool enable)
@@ -173,11 +180,15 @@ static bool hix5hd2_hotplug_init(void)
struct device_node *np;
np = of_find_compatible_node(NULL, NULL, "hisilicon,cpuctrl");
- if (np) {
- ctrl_base = of_iomap(np, 0);
- return true;
- }
- return false;
+ if (!np)
+ return false;
+
+ ctrl_base = of_iomap(np, 0);
+ of_node_put(np);
+ if (!ctrl_base)
+ return false;
+
+ return true;
}
void hix5hd2_set_cpu(int cpu, bool enable)
@@ -219,10 +230,10 @@ void hip01_set_cpu(int cpu, bool enable)
if (!ctrl_base) {
np = of_find_compatible_node(NULL, NULL, "hisilicon,hip01-sysctrl");
- if (np)
- ctrl_base = of_iomap(np, 0);
- else
- BUG();
+ BUG_ON(!np);
+ ctrl_base = of_iomap(np, 0);
+ of_node_put(np);
+ BUG_ON(!ctrl_base);
}
if (enable) {
diff --git a/arch/arm64/configs/msm-auto-perf_defconfig b/arch/arm64/configs/msm-auto-perf_defconfig
index 475fa24aba88..0f624b69649d 100644
--- a/arch/arm64/configs/msm-auto-perf_defconfig
+++ b/arch/arm64/configs/msm-auto-perf_defconfig
@@ -511,7 +511,6 @@ CONFIG_REMOTE_SPINLOCK_MSM=y
CONFIG_IOMMU_IO_PGTABLE_FAST=y
CONFIG_ARM_SMMU=y
CONFIG_IOMMU_DEBUG=y
-CONFIG_IOMMU_TESTS=y
CONFIG_MSM_PASR=y
CONFIG_MSM_SMEM=y
CONFIG_QPNP_HAPTIC=y
diff --git a/arch/arm64/configs/msm-auto_defconfig b/arch/arm64/configs/msm-auto_defconfig
index 49416b31c24b..39a9b67d36b0 100644
--- a/arch/arm64/configs/msm-auto_defconfig
+++ b/arch/arm64/configs/msm-auto_defconfig
@@ -519,7 +519,6 @@ CONFIG_IOMMU_IO_PGTABLE_FAST_SELFTEST=y
CONFIG_ARM_SMMU=y
CONFIG_IOMMU_DEBUG=y
CONFIG_IOMMU_DEBUG_TRACKING=y
-CONFIG_IOMMU_TESTS=y
CONFIG_MSM_PASR=y
CONFIG_MSM_SMEM=y
CONFIG_QPNP_HAPTIC=y
diff --git a/arch/arm64/include/asm/thread_info.h b/arch/arm64/include/asm/thread_info.h
index db6d058ab0f3..70c11c25d3e4 100644
--- a/arch/arm64/include/asm/thread_info.h
+++ b/arch/arm64/include/asm/thread_info.h
@@ -120,6 +120,7 @@ static inline struct thread_info *current_thread_info(void)
#define TIF_NEED_RESCHED 1
#define TIF_NOTIFY_RESUME 2 /* callback before returning to user */
#define TIF_FOREIGN_FPSTATE 3 /* CPU's FP state is not current's */
+#define TIF_FSCHECK 4 /* Check FS is USER_DS on return */
#define TIF_NOHZ 7
#define TIF_SYSCALL_TRACE 8
#define TIF_SYSCALL_AUDIT 9
@@ -141,10 +142,12 @@ static inline struct thread_info *current_thread_info(void)
#define _TIF_SYSCALL_AUDIT (1 << TIF_SYSCALL_AUDIT)
#define _TIF_SYSCALL_TRACEPOINT (1 << TIF_SYSCALL_TRACEPOINT)
#define _TIF_SECCOMP (1 << TIF_SECCOMP)
+#define _TIF_FSCHECK (1 << TIF_FSCHECK)
#define _TIF_32BIT (1 << TIF_32BIT)
#define _TIF_WORK_MASK (_TIF_NEED_RESCHED | _TIF_SIGPENDING | \
- _TIF_NOTIFY_RESUME | _TIF_FOREIGN_FPSTATE)
+ _TIF_NOTIFY_RESUME | _TIF_FOREIGN_FPSTATE | \
+ _TIF_FSCHECK)
#define _TIF_SYSCALL_WORK (_TIF_SYSCALL_TRACE | _TIF_SYSCALL_AUDIT | \
_TIF_SYSCALL_TRACEPOINT | _TIF_SECCOMP | \
diff --git a/arch/arm64/include/asm/uaccess.h b/arch/arm64/include/asm/uaccess.h
index d39d8bde42d7..d0919bcb1953 100644
--- a/arch/arm64/include/asm/uaccess.h
+++ b/arch/arm64/include/asm/uaccess.h
@@ -73,6 +73,9 @@ static inline void set_fs(mm_segment_t fs)
{
current_thread_info()->addr_limit = fs;
+ /* On user-mode return, check fs is correct */
+ set_thread_flag(TIF_FSCHECK);
+
/*
* Enable/disable UAO so that copy_to_user() etc can access
* kernel memory with the unprivileged instructions.
diff --git a/arch/arm64/kernel/signal.c b/arch/arm64/kernel/signal.c
index a8eafdbc7cb8..0bed9a899850 100644
--- a/arch/arm64/kernel/signal.c
+++ b/arch/arm64/kernel/signal.c
@@ -25,6 +25,7 @@
#include <linux/uaccess.h>
#include <linux/tracehook.h>
#include <linux/ratelimit.h>
+#include <linux/syscalls.h>
#include <asm/debug-monitors.h>
#include <asm/elf.h>
@@ -402,6 +403,9 @@ static void do_signal(struct pt_regs *regs)
asmlinkage void do_notify_resume(struct pt_regs *regs,
unsigned int thread_flags)
{
+ /* Check valid user FS if needed */
+ addr_limit_user_check();
+
if (thread_flags & _TIF_SIGPENDING)
do_signal(regs);
diff --git a/arch/mips/ath79/setup.c b/arch/mips/ath79/setup.c
index 8755d618e116..961c393c0f55 100644
--- a/arch/mips/ath79/setup.c
+++ b/arch/mips/ath79/setup.c
@@ -44,6 +44,7 @@ static char ath79_sys_type[ATH79_SYS_TYPE_LEN];
static void ath79_restart(char *command)
{
+ local_irq_disable();
ath79_device_reset_set(AR71XX_RESET_FULL_CHIP);
for (;;)
if (cpu_wait)
diff --git a/arch/mips/cavium-octeon/octeon-platform.c b/arch/mips/cavium-octeon/octeon-platform.c
index d113c8ded6e2..6df3a4ea77fc 100644
--- a/arch/mips/cavium-octeon/octeon-platform.c
+++ b/arch/mips/cavium-octeon/octeon-platform.c
@@ -349,6 +349,7 @@ static int __init octeon_ehci_device_init(void)
return 0;
pd = of_find_device_by_node(ehci_node);
+ of_node_put(ehci_node);
if (!pd)
return 0;
@@ -411,6 +412,7 @@ static int __init octeon_ohci_device_init(void)
return 0;
pd = of_find_device_by_node(ohci_node);
+ of_node_put(ohci_node);
if (!pd)
return 0;
diff --git a/arch/mips/include/asm/io.h b/arch/mips/include/asm/io.h
index 75fa296836fc..ab1df19b0957 100644
--- a/arch/mips/include/asm/io.h
+++ b/arch/mips/include/asm/io.h
@@ -141,14 +141,14 @@ static inline void * phys_to_virt(unsigned long address)
/*
* ISA I/O bus memory addresses are 1:1 with the physical address.
*/
-static inline unsigned long isa_virt_to_bus(volatile void * address)
+static inline unsigned long isa_virt_to_bus(volatile void *address)
{
- return (unsigned long)address - PAGE_OFFSET;
+ return virt_to_phys(address);
}
-static inline void * isa_bus_to_virt(unsigned long address)
+static inline void *isa_bus_to_virt(unsigned long address)
{
- return (void *)(address + PAGE_OFFSET);
+ return phys_to_virt(address);
}
#define isa_page_to_bus page_to_phys
diff --git a/arch/mips/include/asm/mach-ath79/ath79.h b/arch/mips/include/asm/mach-ath79/ath79.h
index 4eee221b0cf0..d2be8e4f7a35 100644
--- a/arch/mips/include/asm/mach-ath79/ath79.h
+++ b/arch/mips/include/asm/mach-ath79/ath79.h
@@ -133,6 +133,7 @@ static inline u32 ath79_pll_rr(unsigned reg)
static inline void ath79_reset_wr(unsigned reg, u32 val)
{
__raw_writel(val, ath79_reset_base + reg);
+ (void) __raw_readl(ath79_reset_base + reg); /* flush */
}
static inline u32 ath79_reset_rr(unsigned reg)
diff --git a/arch/mips/jz4740/Platform b/arch/mips/jz4740/Platform
index 28448d358c10..a2a5a85ea1f9 100644
--- a/arch/mips/jz4740/Platform
+++ b/arch/mips/jz4740/Platform
@@ -1,4 +1,4 @@
platform-$(CONFIG_MACH_INGENIC) += jz4740/
cflags-$(CONFIG_MACH_INGENIC) += -I$(srctree)/arch/mips/include/asm/mach-jz4740
load-$(CONFIG_MACH_INGENIC) += 0xffffffff80010000
-zload-$(CONFIG_MACH_INGENIC) += 0xffffffff80600000
+zload-$(CONFIG_MACH_INGENIC) += 0xffffffff81000000
diff --git a/arch/mips/kernel/process.c b/arch/mips/kernel/process.c
index 9684a0d22d97..dd92540fbc75 100644
--- a/arch/mips/kernel/process.c
+++ b/arch/mips/kernel/process.c
@@ -117,7 +117,6 @@ int copy_thread(unsigned long clone_flags, unsigned long usp,
struct thread_info *ti = task_thread_info(p);
struct pt_regs *childregs, *regs = current_pt_regs();
unsigned long childksp;
- p->set_child_tid = p->clear_child_tid = NULL;
childksp = (unsigned long)task_stack_page(p) + THREAD_SIZE - 32;
diff --git a/arch/mips/kernel/vdso.c b/arch/mips/kernel/vdso.c
index 3fcc833b316d..cf2882fd0c17 100644
--- a/arch/mips/kernel/vdso.c
+++ b/arch/mips/kernel/vdso.c
@@ -14,12 +14,14 @@
#include <linux/init.h>
#include <linux/ioport.h>
#include <linux/irqchip/mips-gic.h>
+#include <linux/kernel.h>
#include <linux/mm.h>
#include <linux/sched.h>
#include <linux/slab.h>
#include <linux/timekeeper_internal.h>
#include <asm/abi.h>
+#include <asm/page.h>
#include <asm/vdso.h>
/* Kernel-provided data used by the VDSO. */
@@ -128,12 +130,30 @@ int arch_setup_additional_pages(struct linux_binprm *bprm, int uses_interp)
vvar_size = gic_size + PAGE_SIZE;
size = vvar_size + image->size;
+ /*
+ * Find a region that's large enough for us to perform the
+ * colour-matching alignment below.
+ */
+ if (cpu_has_dc_aliases)
+ size += shm_align_mask + 1;
+
base = get_unmapped_area(NULL, 0, size, 0, 0);
if (IS_ERR_VALUE(base)) {
ret = base;
goto out;
}
+ /*
+ * If we suffer from dcache aliasing, ensure that the VDSO data page
+ * mapping is coloured the same as the kernel's mapping of that memory.
+ * This ensures that when the kernel updates the VDSO data userland
+ * will observe it without requiring cache invalidations.
+ */
+ if (cpu_has_dc_aliases) {
+ base = __ALIGN_MASK(base, shm_align_mask);
+ base += ((unsigned long)&vdso_data - gic_size) & shm_align_mask;
+ }
+
data_addr = base + gic_size;
vdso_addr = data_addr + PAGE_SIZE;
diff --git a/arch/mips/loongson64/common/cs5536/cs5536_ohci.c b/arch/mips/loongson64/common/cs5536/cs5536_ohci.c
index f7c905e50dc4..92dc6bafc127 100644
--- a/arch/mips/loongson64/common/cs5536/cs5536_ohci.c
+++ b/arch/mips/loongson64/common/cs5536/cs5536_ohci.c
@@ -138,7 +138,7 @@ u32 pci_ohci_read_reg(int reg)
break;
case PCI_OHCI_INT_REG:
_rdmsr(DIVIL_MSR_REG(PIC_YSEL_LOW), &hi, &lo);
- if ((lo & 0x00000f00) == CS5536_USB_INTR)
+ if (((lo >> PIC_YSEL_LOW_USB_SHIFT) & 0xf) == CS5536_USB_INTR)
conf_data = 1;
break;
default:
diff --git a/arch/mips/mm/c-r4k.c b/arch/mips/mm/c-r4k.c
index d66a61efb143..52cb3e09d172 100644
--- a/arch/mips/mm/c-r4k.c
+++ b/arch/mips/mm/c-r4k.c
@@ -712,7 +712,8 @@ static void r4k_flush_icache_range(unsigned long start, unsigned long end)
static void r4k_dma_cache_wback_inv(unsigned long addr, unsigned long size)
{
/* Catch bad driver code */
- BUG_ON(size == 0);
+ if (WARN_ON(size == 0))
+ return;
preempt_disable();
if (cpu_has_inclusive_pcaches) {
@@ -745,7 +746,8 @@ static void r4k_dma_cache_wback_inv(unsigned long addr, unsigned long size)
static void r4k_dma_cache_inv(unsigned long addr, unsigned long size)
{
/* Catch bad driver code */
- BUG_ON(size == 0);
+ if (WARN_ON(size == 0))
+ return;
preempt_disable();
if (cpu_has_inclusive_pcaches) {
diff --git a/arch/openrisc/kernel/process.c b/arch/openrisc/kernel/process.c
index 7095dfe7666b..962372143fda 100644
--- a/arch/openrisc/kernel/process.c
+++ b/arch/openrisc/kernel/process.c
@@ -152,8 +152,6 @@ copy_thread(unsigned long clone_flags, unsigned long usp,
top_of_kernel_stack = sp;
- p->set_child_tid = p->clear_child_tid = NULL;
-
/* Locate userspace context on stack... */
sp -= STACK_FRAME_OVERHEAD; /* redzone */
sp -= sizeof(struct pt_regs);
diff --git a/arch/powerpc/platforms/powernv/opal.c b/arch/powerpc/platforms/powernv/opal.c
index e48826aa314c..b40606051efe 100644
--- a/arch/powerpc/platforms/powernv/opal.c
+++ b/arch/powerpc/platforms/powernv/opal.c
@@ -371,7 +371,7 @@ int opal_put_chars(uint32_t vtermno, const char *data, int total_len)
/* Closed or other error drop */
if (rc != OPAL_SUCCESS && rc != OPAL_BUSY &&
rc != OPAL_BUSY_EVENT) {
- written = total_len;
+ written += total_len;
break;
}
if (rc == OPAL_SUCCESS) {
diff --git a/arch/powerpc/platforms/pseries/ras.c b/arch/powerpc/platforms/pseries/ras.c
index f5313a78e5d6..9795e52bab3d 100644
--- a/arch/powerpc/platforms/pseries/ras.c
+++ b/arch/powerpc/platforms/pseries/ras.c
@@ -311,7 +311,7 @@ static struct rtas_error_log *fwnmi_get_errinfo(struct pt_regs *regs)
int len, error_log_length;
error_log_length = 8 + rtas_error_extended_log_length(h);
- len = max_t(int, error_log_length, RTAS_ERROR_LOG_MAX);
+ len = min_t(int, error_log_length, RTAS_ERROR_LOG_MAX);
memset(global_mce_data_buf, 0, RTAS_ERROR_LOG_MAX);
memcpy(global_mce_data_buf, h, len);
errhdr = (struct rtas_error_log *)global_mce_data_buf;
diff --git a/arch/powerpc/sysdev/mpic_msgr.c b/arch/powerpc/sysdev/mpic_msgr.c
index 3f165d972a0e..994fe73c2ed0 100644
--- a/arch/powerpc/sysdev/mpic_msgr.c
+++ b/arch/powerpc/sysdev/mpic_msgr.c
@@ -196,7 +196,7 @@ static int mpic_msgr_probe(struct platform_device *dev)
/* IO map the message register block. */
of_address_to_resource(np, 0, &rsrc);
- msgr_block_addr = ioremap(rsrc.start, rsrc.end - rsrc.start);
+ msgr_block_addr = ioremap(rsrc.start, resource_size(&rsrc));
if (!msgr_block_addr) {
dev_err(&dev->dev, "Failed to iomap MPIC message registers");
return -EFAULT;
diff --git a/arch/s390/lib/mem.S b/arch/s390/lib/mem.S
index 16c5998b9792..4254c477e8e0 100644
--- a/arch/s390/lib/mem.S
+++ b/arch/s390/lib/mem.S
@@ -26,7 +26,7 @@
*/
ENTRY(memset)
ltgr %r4,%r4
- bzr %r14
+ jz .Lmemset_exit
ltgr %r3,%r3
jnz .Lmemset_fill
aghi %r4,-1
@@ -41,12 +41,13 @@ ENTRY(memset)
.Lmemset_clear_rest:
larl %r3,.Lmemset_xc
ex %r4,0(%r3)
+.Lmemset_exit:
BR_EX %r14
.Lmemset_fill:
stc %r3,0(%r2)
cghi %r4,1
lgr %r1,%r2
- ber %r14
+ je .Lmemset_fill_exit
aghi %r4,-2
srlg %r3,%r4,8
ltgr %r3,%r3
@@ -58,6 +59,7 @@ ENTRY(memset)
.Lmemset_fill_rest:
larl %r3,.Lmemset_mvc
ex %r4,0(%r3)
+.Lmemset_fill_exit:
BR_EX %r14
.Lmemset_xc:
xc 0(1,%r1),0(%r1)
@@ -71,7 +73,7 @@ ENTRY(memset)
*/
ENTRY(memcpy)
ltgr %r4,%r4
- bzr %r14
+ jz .Lmemcpy_exit
aghi %r4,-1
srlg %r5,%r4,8
ltgr %r5,%r5
@@ -80,6 +82,7 @@ ENTRY(memcpy)
.Lmemcpy_rest:
larl %r5,.Lmemcpy_mvc
ex %r4,0(%r5)
+.Lmemcpy_exit:
BR_EX %r14
.Lmemcpy_loop:
mvc 0(256,%r1),0(%r3)
diff --git a/arch/x86/entry/common.c b/arch/x86/entry/common.c
index 071582a3b5c0..a9e501303e15 100644
--- a/arch/x86/entry/common.c
+++ b/arch/x86/entry/common.c
@@ -22,6 +22,7 @@
#include <linux/user-return-notifier.h>
#include <linux/nospec.h>
#include <linux/uprobes.h>
+#include <linux/syscalls.h>
#include <asm/desc.h>
#include <asm/traps.h>
@@ -273,6 +274,8 @@ __visible inline void prepare_exit_to_usermode(struct pt_regs *regs)
struct thread_info *ti = pt_regs_to_thread_info(regs);
u32 cached_flags;
+ addr_limit_user_check();
+
if (IS_ENABLED(CONFIG_PROVE_LOCKING) && WARN_ON(!irqs_disabled()))
local_irq_disable();
diff --git a/arch/x86/include/asm/pgtable-3level.h b/arch/x86/include/asm/pgtable-3level.h
index 5c686382d84b..095dbc25122a 100644
--- a/arch/x86/include/asm/pgtable-3level.h
+++ b/arch/x86/include/asm/pgtable-3level.h
@@ -1,6 +1,8 @@
#ifndef _ASM_X86_PGTABLE_3LEVEL_H
#define _ASM_X86_PGTABLE_3LEVEL_H
+#include <asm/atomic64_32.h>
+
/*
* Intel Physical Address Extension (PAE) Mode - three-level page
* tables on PPro+ CPUs.
@@ -142,10 +144,7 @@ static inline pte_t native_ptep_get_and_clear(pte_t *ptep)
{
pte_t res;
- /* xchg acts as a barrier before the setting of the high bits */
- res.pte_low = xchg(&ptep->pte_low, 0);
- res.pte_high = ptep->pte_high;
- ptep->pte_high = 0;
+ res.pte = (pteval_t)atomic64_xchg((atomic64_t *)ptep, 0);
return res;
}
diff --git a/arch/x86/include/asm/pgtable.h b/arch/x86/include/asm/pgtable.h
index 68a55273ce0f..a67d7f210b7c 100644
--- a/arch/x86/include/asm/pgtable.h
+++ b/arch/x86/include/asm/pgtable.h
@@ -385,7 +385,7 @@ static inline pmd_t pfn_pmd(unsigned long page_nr, pgprot_t pgprot)
static inline pud_t pfn_pud(unsigned long page_nr, pgprot_t pgprot)
{
- phys_addr_t pfn = page_nr << PAGE_SHIFT;
+ phys_addr_t pfn = (phys_addr_t)page_nr << PAGE_SHIFT;
pfn ^= protnone_mask(pgprot_val(pgprot));
pfn &= PHYSICAL_PUD_PAGE_MASK;
return __pud(pfn | massage_pgprot(pgprot));
diff --git a/arch/x86/include/asm/processor.h b/arch/x86/include/asm/processor.h
index 337c52192278..440a948c4feb 100644
--- a/arch/x86/include/asm/processor.h
+++ b/arch/x86/include/asm/processor.h
@@ -104,6 +104,8 @@ struct cpuinfo_x86 {
__u8 x86_phys_bits;
/* CPUID returned core id bits: */
__u8 x86_coreid_bits;
+
+ __u8 x86_cache_bits;
/* Max extended CPUID function supported: */
__u32 extended_cpuid_level;
/* Maximum supported CPUID level, -1=no CPUID: */
@@ -174,7 +176,7 @@ extern void cpu_detect(struct cpuinfo_x86 *c);
static inline unsigned long long l1tf_pfn_limit(void)
{
- return BIT_ULL(boot_cpu_data.x86_phys_bits - 1 - PAGE_SHIFT);
+ return BIT_ULL(boot_cpu_data.x86_cache_bits - 1 - PAGE_SHIFT);
}
extern void early_cpu_init(void);
diff --git a/arch/x86/include/asm/thread_info.h b/arch/x86/include/asm/thread_info.h
index e8d453732823..c14f699f5c36 100644
--- a/arch/x86/include/asm/thread_info.h
+++ b/arch/x86/include/asm/thread_info.h
@@ -111,6 +111,7 @@ struct thread_info {
#define TIF_SYSCALL_TRACEPOINT 28 /* syscall tracepoint instrumentation */
#define TIF_ADDR32 29 /* 32-bit address space on 64 bits */
#define TIF_X32 30 /* 32-bit native x86-64 binary */
+#define TIF_FSCHECK 31 /* Check FS is USER_DS on return */
#define _TIF_SYSCALL_TRACE (1 << TIF_SYSCALL_TRACE)
#define _TIF_NOTIFY_RESUME (1 << TIF_NOTIFY_RESUME)
@@ -135,6 +136,7 @@ struct thread_info {
#define _TIF_SYSCALL_TRACEPOINT (1 << TIF_SYSCALL_TRACEPOINT)
#define _TIF_ADDR32 (1 << TIF_ADDR32)
#define _TIF_X32 (1 << TIF_X32)
+#define _TIF_FSCHECK (1 << TIF_FSCHECK)
/* work to do in syscall_trace_enter() */
#define _TIF_WORK_SYSCALL_ENTRY \
@@ -145,7 +147,7 @@ struct thread_info {
/* work to do on any return to user space */
#define _TIF_ALLWORK_MASK \
((0x0000FFFF & ~_TIF_SECCOMP) | _TIF_SYSCALL_TRACEPOINT | \
- _TIF_NOHZ)
+ _TIF_NOHZ | _TIF_FSCHECK)
/* flags to check in __switch_to() */
#define _TIF_WORK_CTXSW \
diff --git a/arch/x86/include/asm/uaccess.h b/arch/x86/include/asm/uaccess.h
index 6a07c05956a6..8857f6f4daa9 100644
--- a/arch/x86/include/asm/uaccess.h
+++ b/arch/x86/include/asm/uaccess.h
@@ -30,7 +30,12 @@
#define get_ds() (KERNEL_DS)
#define get_fs() (current_thread_info()->addr_limit)
-#define set_fs(x) (current_thread_info()->addr_limit = (x))
+static inline void set_fs(mm_segment_t fs)
+{
+ current_thread_info()->addr_limit = fs;
+ /* On user-mode return, check fs is correct */
+ set_thread_flag(TIF_FSCHECK);
+}
#define segment_eq(a, b) ((a).seg == (b).seg)
diff --git a/arch/x86/kernel/cpu/bugs.c b/arch/x86/kernel/cpu/bugs.c
index b9e6b60df148..621bc6561189 100644
--- a/arch/x86/kernel/cpu/bugs.c
+++ b/arch/x86/kernel/cpu/bugs.c
@@ -634,6 +634,46 @@ void x86_spec_ctrl_setup_ap(void)
#undef pr_fmt
#define pr_fmt(fmt) "L1TF: " fmt
+
+/*
+ * These CPUs all support 44bits physical address space internally in the
+ * cache but CPUID can report a smaller number of physical address bits.
+ *
+ * The L1TF mitigation uses the top most address bit for the inversion of
+ * non present PTEs. When the installed memory reaches into the top most
+ * address bit due to memory holes, which has been observed on machines
+ * which report 36bits physical address bits and have 32G RAM installed,
+ * then the mitigation range check in l1tf_select_mitigation() triggers.
+ * This is a false positive because the mitigation is still possible due to
+ * the fact that the cache uses 44bit internally. Use the cache bits
+ * instead of the reported physical bits and adjust them on the affected
+ * machines to 44bit if the reported bits are less than 44.
+ */
+static void override_cache_bits(struct cpuinfo_x86 *c)
+{
+ if (c->x86 != 6)
+ return;
+
+ switch (c->x86_model) {
+ case INTEL_FAM6_NEHALEM:
+ case INTEL_FAM6_WESTMERE:
+ case INTEL_FAM6_SANDYBRIDGE:
+ case INTEL_FAM6_IVYBRIDGE:
+ case INTEL_FAM6_HASWELL_CORE:
+ case INTEL_FAM6_HASWELL_ULT:
+ case INTEL_FAM6_HASWELL_GT3E:
+ case INTEL_FAM6_BROADWELL_CORE:
+ case INTEL_FAM6_BROADWELL_GT3E:
+ case INTEL_FAM6_SKYLAKE_MOBILE:
+ case INTEL_FAM6_SKYLAKE_DESKTOP:
+ case INTEL_FAM6_KABYLAKE_MOBILE:
+ case INTEL_FAM6_KABYLAKE_DESKTOP:
+ if (c->x86_cache_bits < 44)
+ c->x86_cache_bits = 44;
+ break;
+ }
+}
+
static void __init l1tf_select_mitigation(void)
{
u64 half_pa;
@@ -641,16 +681,13 @@ static void __init l1tf_select_mitigation(void)
if (!boot_cpu_has_bug(X86_BUG_L1TF))
return;
+ override_cache_bits(&boot_cpu_data);
+
#if CONFIG_PGTABLE_LEVELS == 2
pr_warn("Kernel not compiled for PAE. No mitigation for L1TF\n");
return;
#endif
- /*
- * This is extremely unlikely to happen because almost all
- * systems have far more MAX_PA/2 than RAM can be fit into
- * DIMM slots.
- */
half_pa = (u64)l1tf_pfn_limit() << PAGE_SHIFT;
if (e820_any_mapped(half_pa, ULLONG_MAX - half_pa, E820_RAM)) {
pr_warn("System has more than MAX_PA/2 memory. L1TF mitigation not effective.\n");
diff --git a/arch/x86/kernel/cpu/common.c b/arch/x86/kernel/cpu/common.c
index 4d3fa79c0f09..b12c0287d6cf 100644
--- a/arch/x86/kernel/cpu/common.c
+++ b/arch/x86/kernel/cpu/common.c
@@ -798,6 +798,8 @@ void get_cpu_cap(struct cpuinfo_x86 *c)
c->x86_phys_bits = 36;
#endif
+ c->x86_cache_bits = c->x86_phys_bits;
+
if (c->extended_cpuid_level >= 0x8000000a)
c->x86_capability[CPUID_8000_000A_EDX] = cpuid_edx(0x8000000a);
diff --git a/arch/x86/mm/fault.c b/arch/x86/mm/fault.c
index e0a34b0d381e..c4dffae5d939 100644
--- a/arch/x86/mm/fault.c
+++ b/arch/x86/mm/fault.c
@@ -273,8 +273,6 @@ static noinline int vmalloc_fault(unsigned long address)
if (!(address >= VMALLOC_START && address < VMALLOC_END))
return -1;
- WARN_ON_ONCE(in_nmi());
-
/*
* Synchronize this task's top level page-table
* with the 'reference' page table.
diff --git a/block/blk-cgroup.c b/block/blk-cgroup.c
index 9075f08b392a..aa84a3c1d418 100644
--- a/block/blk-cgroup.c
+++ b/block/blk-cgroup.c
@@ -185,7 +185,8 @@ static struct blkcg_gq *blkg_create(struct blkcg *blkcg,
}
wb_congested = wb_congested_get_create(q->backing_dev_info,
- blkcg->css.id, GFP_NOWAIT);
+ blkcg->css.id,
+ GFP_NOWAIT | __GFP_NOWARN);
if (!wb_congested) {
ret = -ENOMEM;
goto err_put_css;
@@ -193,7 +194,7 @@ static struct blkcg_gq *blkg_create(struct blkcg *blkcg,
/* allocate */
if (!new_blkg) {
- new_blkg = blkg_alloc(blkcg, q, GFP_NOWAIT);
+ new_blkg = blkg_alloc(blkcg, q, GFP_NOWAIT | __GFP_NOWARN);
if (unlikely(!new_blkg)) {
ret = -ENOMEM;
goto err_put_congested;
@@ -1022,7 +1023,7 @@ blkcg_css_alloc(struct cgroup_subsys_state *parent_css)
}
spin_lock_init(&blkcg->lock);
- INIT_RADIX_TREE(&blkcg->blkg_tree, GFP_NOWAIT);
+ INIT_RADIX_TREE(&blkcg->blkg_tree, GFP_NOWAIT | __GFP_NOWARN);
INIT_HLIST_HEAD(&blkcg->blkg_list);
#ifdef CONFIG_CGROUP_WRITEBACK
INIT_LIST_HEAD(&blkcg->cgwb_list);
@@ -1238,7 +1239,7 @@ pd_prealloc:
if (blkg->pd[pol->plid])
continue;
- pd = pol->pd_alloc_fn(GFP_NOWAIT, q->node);
+ pd = pol->pd_alloc_fn(GFP_NOWAIT | __GFP_NOWARN, q->node);
if (!pd)
swap(pd, pd_prealloc);
if (!pd) {
diff --git a/block/cfq-iosched.c b/block/cfq-iosched.c
index e04a7b8492cf..4e1f49434bbe 100644
--- a/block/cfq-iosched.c
+++ b/block/cfq-iosched.c
@@ -2905,7 +2905,8 @@ static void cfq_arm_slice_timer(struct cfq_data *cfqd)
* for devices that support queuing, otherwise we still have a problem
* with sync vs async workloads.
*/
- if (blk_queue_nonrot(cfqd->queue) && cfqd->hw_tag)
+ if (blk_queue_nonrot(cfqd->queue) && cfqd->hw_tag &&
+ !cfqd->cfq_group_idle)
return;
WARN_ON(!RB_EMPTY_ROOT(&cfqq->sort_list));
@@ -3810,7 +3811,8 @@ cfq_get_queue(struct cfq_data *cfqd, bool is_sync, struct cfq_io_cq *cic,
goto out;
}
- cfqq = kmem_cache_alloc_node(cfq_pool, GFP_NOWAIT | __GFP_ZERO,
+ cfqq = kmem_cache_alloc_node(cfq_pool,
+ GFP_NOWAIT | __GFP_ZERO | __GFP_NOWARN,
cfqd->queue->node);
if (!cfqq) {
cfqq = &cfqd->oom_cfqq;
diff --git a/block/partitions/aix.c b/block/partitions/aix.c
index f3ed7b2d89bf..8e7d358e0226 100644
--- a/block/partitions/aix.c
+++ b/block/partitions/aix.c
@@ -177,7 +177,7 @@ int aix_partition(struct parsed_partitions *state)
u32 vgda_sector = 0;
u32 vgda_len = 0;
int numlvs = 0;
- struct pvd *pvd;
+ struct pvd *pvd = NULL;
struct lv_info {
unsigned short pps_per_lv;
unsigned short pps_found;
@@ -231,10 +231,11 @@ int aix_partition(struct parsed_partitions *state)
if (lvip[i].pps_per_lv)
foundlvs += 1;
}
+ /* pvd loops depend on n[].name and lvip[].pps_per_lv */
+ pvd = alloc_pvd(state, vgda_sector + 17);
}
put_dev_sector(sect);
}
- pvd = alloc_pvd(state, vgda_sector + 17);
if (pvd) {
int numpps = be16_to_cpu(pvd->pp_count);
int psn_part1 = be32_to_cpu(pvd->psn_part1);
@@ -281,10 +282,14 @@ int aix_partition(struct parsed_partitions *state)
next_lp_ix += 1;
}
for (i = 0; i < state->limit; i += 1)
- if (lvip[i].pps_found && !lvip[i].lv_is_contiguous)
+ if (lvip[i].pps_found && !lvip[i].lv_is_contiguous) {
+ char tmp[sizeof(n[i].name) + 1]; // null char
+
+ snprintf(tmp, sizeof(tmp), "%s", n[i].name);
pr_warn("partition %s (%u pp's found) is "
"not contiguous\n",
- n[i].name, lvip[i].pps_found);
+ tmp, lvip[i].pps_found);
+ }
kfree(pvd);
}
kfree(n);
diff --git a/drivers/android/binder.c b/drivers/android/binder.c
index 623094457788..644b9abcc67f 100644
--- a/drivers/android/binder.c
+++ b/drivers/android/binder.c
@@ -4714,6 +4714,42 @@ out:
return ret;
}
+static int binder_ioctl_get_node_info_for_ref(struct binder_proc *proc,
+ struct binder_node_info_for_ref *info)
+{
+ struct binder_node *node;
+ struct binder_context *context = proc->context;
+ __u32 handle = info->handle;
+
+ if (info->strong_count || info->weak_count || info->reserved1 ||
+ info->reserved2 || info->reserved3) {
+ binder_user_error("%d BINDER_GET_NODE_INFO_FOR_REF: only handle may be non-zero.",
+ proc->pid);
+ return -EINVAL;
+ }
+
+ /* This ioctl may only be used by the context manager */
+ mutex_lock(&context->context_mgr_node_lock);
+ if (!context->binder_context_mgr_node ||
+ context->binder_context_mgr_node->proc != proc) {
+ mutex_unlock(&context->context_mgr_node_lock);
+ return -EPERM;
+ }
+ mutex_unlock(&context->context_mgr_node_lock);
+
+ node = binder_get_node_from_ref(proc, handle, true, NULL);
+ if (!node)
+ return -EINVAL;
+
+ info->strong_count = node->local_strong_refs +
+ node->internal_strong_refs;
+ info->weak_count = node->local_weak_refs;
+
+ binder_put_node(node);
+
+ return 0;
+}
+
static int binder_ioctl_get_node_debug_info(struct binder_proc *proc,
struct binder_node_debug_info *info) {
struct rb_node *n;
@@ -4807,6 +4843,25 @@ static long binder_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)
}
break;
}
+ case BINDER_GET_NODE_INFO_FOR_REF: {
+ struct binder_node_info_for_ref info;
+
+ if (copy_from_user(&info, ubuf, sizeof(info))) {
+ ret = -EFAULT;
+ goto err;
+ }
+
+ ret = binder_ioctl_get_node_info_for_ref(proc, &info);
+ if (ret < 0)
+ goto err;
+
+ if (copy_to_user(ubuf, &info, sizeof(info))) {
+ ret = -EFAULT;
+ goto err;
+ }
+
+ break;
+ }
case BINDER_GET_NODE_DEBUG_INFO: {
struct binder_node_debug_info info;
diff --git a/drivers/ata/libahci.c b/drivers/ata/libahci.c
index 9628fa131757..8116cb2fef2d 100644
--- a/drivers/ata/libahci.c
+++ b/drivers/ata/libahci.c
@@ -2113,6 +2113,8 @@ static void ahci_set_aggressive_devslp(struct ata_port *ap, bool sleep)
deto = 20;
}
+ /* Make dito, mdat, deto bits to 0s */
+ devslp &= ~GENMASK_ULL(24, 2);
devslp |= ((dito << PORT_DEVSLP_DITO_OFFSET) |
(mdat << PORT_DEVSLP_MDAT_OFFSET) |
(deto << PORT_DEVSLP_DETO_OFFSET) |
diff --git a/drivers/bluetooth/Kconfig b/drivers/bluetooth/Kconfig
index 57b60eeb11c6..b6281e523bf3 100644
--- a/drivers/bluetooth/Kconfig
+++ b/drivers/bluetooth/Kconfig
@@ -125,6 +125,7 @@ config BT_HCIUART_LL
config BT_HCIUART_3WIRE
bool "Three-wire UART (H5) protocol support"
depends on BT_HCIUART
+ depends on BT_HCIUART_SERDEV
help
The HCI Three-wire UART Transport Layer makes it possible to
user the Bluetooth HCI over a serial port interface. The HCI
diff --git a/drivers/clk/imx/clk-imx6ul.c b/drivers/clk/imx/clk-imx6ul.c
index 01718d05e952..9e8f0e255de2 100644
--- a/drivers/clk/imx/clk-imx6ul.c
+++ b/drivers/clk/imx/clk-imx6ul.c
@@ -120,6 +120,7 @@ static void __init imx6ul_clocks_init(struct device_node *ccm_node)
np = of_find_compatible_node(NULL, NULL, "fsl,imx6ul-anatop");
base = of_iomap(np, 0);
+ of_node_put(np);
WARN_ON(!base);
clks[IMX6UL_PLL1_BYPASS_SRC] = imx_clk_mux("pll1_bypass_src", base + 0x00, 14, 1, pll_bypass_src_sels, ARRAY_SIZE(pll_bypass_src_sels));
diff --git a/drivers/clk/qcom/mdss/mdss-pll-util.c b/drivers/clk/qcom/mdss/mdss-pll-util.c
index 881c973ec1b6..d6a148eee68c 100644
--- a/drivers/clk/qcom/mdss/mdss-pll-util.c
+++ b/drivers/clk/qcom/mdss/mdss-pll-util.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2013-2016, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2013-2016, 2018, 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
@@ -327,16 +327,6 @@ clk_err:
return rc;
}
-static void mdss_pll_free_bootmem(u32 mem_addr, u32 size)
-{
- unsigned long pfn_start, pfn_end, pfn_idx;
-
- pfn_start = mem_addr >> PAGE_SHIFT;
- pfn_end = (mem_addr + size) >> PAGE_SHIFT;
- for (pfn_idx = pfn_start; pfn_idx < pfn_end; pfn_idx++)
- free_reserved_page(pfn_to_page(pfn_idx));
-}
-
static int mdss_pll_util_parse_dt_dfps(struct platform_device *pdev,
struct mdss_pll_resources *pll_res)
{
@@ -367,7 +357,7 @@ static int mdss_pll_util_parse_dt_dfps(struct platform_device *pdev,
area = get_vm_area(offsets[1], VM_IOREMAP);
if (!area) {
rc = -ENOMEM;
- goto dfps_mem_err;
+ goto pnode_err;
}
virt_add = (unsigned long)area->addr;
@@ -394,10 +384,6 @@ addr_err:
ioremap_err:
if (area)
vfree(area->addr);
-dfps_mem_err:
- /* free the dfps memory here */
- memblock_free(offsets[0], offsets[1]);
- mdss_pll_free_bootmem(offsets[0], offsets[1]);
pnode_err:
if (pnode)
of_node_put(pnode);
diff --git a/drivers/crypto/msm/qce50.c b/drivers/crypto/msm/qce50.c
index b44f926a6ba0..598b1aa0f4d7 100644
--- a/drivers/crypto/msm/qce50.c
+++ b/drivers/crypto/msm/qce50.c
@@ -1,6 +1,6 @@
/* Qualcomm Crypto Engine driver.
*
- * Copyright (c) 2012-2017, The Linux Foundation. All rights reserved.
+ * Copyright (c) 2012-2018, 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
@@ -2440,6 +2440,9 @@ static int _qce_sps_add_sg_data(struct qce_device *pce_dev,
struct sps_iovec *iovec = sps_bam_pipe->iovec +
sps_bam_pipe->iovec_count;
+ if (!sg_src)
+ return -ENOENT;
+
while (nbytes > 0) {
len = min(nbytes, sg_dma_len(sg_src));
nbytes -= len;
diff --git a/drivers/crypto/sahara.c b/drivers/crypto/sahara.c
index f68c24a98277..dedfc96acc66 100644
--- a/drivers/crypto/sahara.c
+++ b/drivers/crypto/sahara.c
@@ -1363,7 +1363,7 @@ err_sha_v4_algs:
err_sha_v3_algs:
for (j = 0; j < k; j++)
- crypto_unregister_ahash(&sha_v4_algs[j]);
+ crypto_unregister_ahash(&sha_v3_algs[j]);
err_aes_algs:
for (j = 0; j < i; j++)
@@ -1379,7 +1379,7 @@ static void sahara_unregister_algs(struct sahara_dev *dev)
for (i = 0; i < ARRAY_SIZE(aes_algs); i++)
crypto_unregister_alg(&aes_algs[i]);
- for (i = 0; i < ARRAY_SIZE(sha_v4_algs); i++)
+ for (i = 0; i < ARRAY_SIZE(sha_v3_algs); i++)
crypto_unregister_ahash(&sha_v3_algs[i]);
if (dev->version > SAHARA_VERSION_3)
diff --git a/drivers/crypto/vmx/aes_cbc.c b/drivers/crypto/vmx/aes_cbc.c
index 9506e8693c81..d8ef1147b344 100644
--- a/drivers/crypto/vmx/aes_cbc.c
+++ b/drivers/crypto/vmx/aes_cbc.c
@@ -111,24 +111,23 @@ static int p8_aes_cbc_encrypt(struct blkcipher_desc *desc,
ret = crypto_blkcipher_encrypt(&fallback_desc, dst, src,
nbytes);
} else {
- preempt_disable();
- pagefault_disable();
- enable_kernel_altivec();
- enable_kernel_vsx();
-
blkcipher_walk_init(&walk, dst, src, nbytes);
ret = blkcipher_walk_virt(desc, &walk);
while ((nbytes = walk.nbytes)) {
+ preempt_disable();
+ pagefault_disable();
+ enable_kernel_vsx();
+ enable_kernel_altivec();
aes_p8_cbc_encrypt(walk.src.virt.addr,
walk.dst.virt.addr,
nbytes & AES_BLOCK_MASK,
&ctx->enc_key, walk.iv, 1);
+ pagefault_enable();
+ preempt_enable();
+
nbytes &= AES_BLOCK_SIZE - 1;
ret = blkcipher_walk_done(desc, &walk, nbytes);
}
-
- pagefault_enable();
- preempt_enable();
}
return ret;
@@ -152,24 +151,23 @@ static int p8_aes_cbc_decrypt(struct blkcipher_desc *desc,
ret = crypto_blkcipher_decrypt(&fallback_desc, dst, src,
nbytes);
} else {
- preempt_disable();
- pagefault_disable();
- enable_kernel_altivec();
- enable_kernel_vsx();
-
blkcipher_walk_init(&walk, dst, src, nbytes);
ret = blkcipher_walk_virt(desc, &walk);
while ((nbytes = walk.nbytes)) {
+ preempt_disable();
+ pagefault_disable();
+ enable_kernel_vsx();
+ enable_kernel_altivec();
aes_p8_cbc_encrypt(walk.src.virt.addr,
walk.dst.virt.addr,
nbytes & AES_BLOCK_MASK,
&ctx->dec_key, walk.iv, 0);
+ pagefault_enable();
+ preempt_enable();
+
nbytes &= AES_BLOCK_SIZE - 1;
ret = blkcipher_walk_done(desc, &walk, nbytes);
}
-
- pagefault_enable();
- preempt_enable();
}
return ret;
diff --git a/drivers/dma/pl330.c b/drivers/dma/pl330.c
index 8db791ef2027..95619ee33112 100644
--- a/drivers/dma/pl330.c
+++ b/drivers/dma/pl330.c
@@ -2132,13 +2132,14 @@ static int pl330_terminate_all(struct dma_chan *chan)
pm_runtime_get_sync(pl330->ddma.dev);
spin_lock_irqsave(&pch->lock, flags);
+
spin_lock(&pl330->lock);
_stop(pch->thread);
- spin_unlock(&pl330->lock);
-
pch->thread->req[0].desc = NULL;
pch->thread->req[1].desc = NULL;
pch->thread->req_running = -1;
+ spin_unlock(&pl330->lock);
+
power_down = pch->active;
pch->active = false;
diff --git a/drivers/gpio/gpio-ml-ioh.c b/drivers/gpio/gpio-ml-ioh.c
index 5536108aa9db..fe21734bbe5c 100644
--- a/drivers/gpio/gpio-ml-ioh.c
+++ b/drivers/gpio/gpio-ml-ioh.c
@@ -495,9 +495,10 @@ err_irq_alloc_descs:
chip = chip_save;
err_gpiochip_add:
+ chip = chip_save;
while (--i >= 0) {
- chip--;
gpiochip_remove(&chip->gpio);
+ chip++;
}
kfree(chip_save);
diff --git a/drivers/gpio/gpio-tegra.c b/drivers/gpio/gpio-tegra.c
index 896bf29776b0..fb2c1df4f588 100644
--- a/drivers/gpio/gpio-tegra.c
+++ b/drivers/gpio/gpio-tegra.c
@@ -591,4 +591,4 @@ static int __init tegra_gpio_init(void)
{
return platform_driver_register(&tegra_gpio_driver);
}
-postcore_initcall(tegra_gpio_init);
+subsys_initcall(tegra_gpio_init);
diff --git a/drivers/gpio/gpiolib.h b/drivers/gpio/gpiolib.h
index 98ab08c0aa2d..07541c5670e6 100644
--- a/drivers/gpio/gpiolib.h
+++ b/drivers/gpio/gpiolib.h
@@ -30,7 +30,7 @@ struct acpi_gpio_info {
};
/* gpio suffixes used for ACPI and device tree lookup */
-static const char * const gpio_suffixes[] = { "gpios", "gpio" };
+static __maybe_unused const char * const gpio_suffixes[] = { "gpios", "gpio" };
#ifdef CONFIG_ACPI
void acpi_gpiochip_add(struct gpio_chip *chip);
diff --git a/drivers/gpu/drm/amd/amdkfd/kfd_process.c b/drivers/gpu/drm/amd/amdkfd/kfd_process.c
index eb1da83c9902..8cdd505784ed 100644
--- a/drivers/gpu/drm/amd/amdkfd/kfd_process.c
+++ b/drivers/gpu/drm/amd/amdkfd/kfd_process.c
@@ -125,6 +125,8 @@ struct kfd_process *kfd_get_process(const struct task_struct *thread)
return ERR_PTR(-EINVAL);
process = find_process(thread);
+ if (!process)
+ return ERR_PTR(-EINVAL);
return process;
}
diff --git a/drivers/gpu/drm/msm/hdmi-staging/sde_hdmi.c b/drivers/gpu/drm/msm/hdmi-staging/sde_hdmi.c
index 83141aaa48d3..48bddbf0e871 100644
--- a/drivers/gpu/drm/msm/hdmi-staging/sde_hdmi.c
+++ b/drivers/gpu/drm/msm/hdmi-staging/sde_hdmi.c
@@ -2009,6 +2009,7 @@ struct drm_msm_ext_panel_hdr_metadata *hdr_meta)
u32 const version = 0x01;
u32 const length = 0x1a;
u32 const descriptor_id = 0x00;
+ u8 checksum;
struct hdmi *hdmi;
struct drm_connector *connector;
@@ -2025,11 +2026,33 @@ struct drm_msm_ext_panel_hdr_metadata *hdr_meta)
return;
}
+ /* Setup the line number to send the packet on */
+ packet_control = hdmi_read(hdmi, HDMI_GEN_PKT_CTRL);
+ packet_control |= BIT(16);
+ hdmi_write(hdmi, HDMI_GEN_PKT_CTRL, packet_control);
+
+ /* Setup the packet to be sent every frame */
+ packet_control = hdmi_read(hdmi, HDMI_GEN_PKT_CTRL);
+ packet_control |= BIT(1);
+ hdmi_write(hdmi, HDMI_GEN_PKT_CTRL, packet_control);
+
/* Setup Packet header and payload */
packet_header = type_code | (version << 8) | (length << 16);
hdmi_write(hdmi, HDMI_GENERIC0_HDR, packet_header);
- packet_payload = (hdr_meta->eotf << 8);
+ /**
+ * Checksum is not a mandatory field for
+ * the HDR infoframe as per CEA-861-3 specification.
+ * However some HDMI sinks still expect a
+ * valid checksum to be included as part of
+ * the infoframe. Hence compute and add
+ * the checksum to improve sink interoperability
+ * for our HDR solution on HDMI.
+ */
+ checksum = sde_hdmi_hdr_set_chksum(hdr_meta);
+
+ packet_payload = (hdr_meta->eotf << 8) | checksum;
+
if (connector->hdr_metadata_type_one) {
packet_payload |= (descriptor_id << 16)
| (HDMI_GET_LSB(hdr_meta->display_primaries_x[0])
@@ -2083,14 +2106,20 @@ struct drm_msm_ext_panel_hdr_metadata *hdr_meta)
hdmi_write(hdmi, HDMI_GENERIC0_6, packet_payload);
enable_packet_control:
- /*
- * GENERIC0_LINE | GENERIC0_CONT | GENERIC0_SEND
- * Setup HDMI TX generic packet control
- * Enable this packet to transmit every frame
- * Enable HDMI TX engine to transmit Generic packet 1
- */
+
+ /* Flush the contents to the register */
+ packet_control = hdmi_read(hdmi, HDMI_GEN_PKT_CTRL);
+ packet_control |= BIT(2);
+ hdmi_write(hdmi, HDMI_GEN_PKT_CTRL, packet_control);
+
+ /* Clear the flush bit of the register */
+ packet_control = hdmi_read(hdmi, HDMI_GEN_PKT_CTRL);
+ packet_control &= ~BIT(2);
+ hdmi_write(hdmi, HDMI_GEN_PKT_CTRL, packet_control);
+
+ /* Start sending the packets*/
packet_control = hdmi_read(hdmi, HDMI_GEN_PKT_CTRL);
- packet_control |= BIT(0) | BIT(1) | BIT(2) | BIT(16);
+ packet_control |= BIT(0);
hdmi_write(hdmi, HDMI_GEN_PKT_CTRL, packet_control);
}
diff --git a/drivers/gpu/drm/msm/hdmi-staging/sde_hdmi.h b/drivers/gpu/drm/msm/hdmi-staging/sde_hdmi.h
index 2aa8d9496c5b..9a15f40bb32c 100644
--- a/drivers/gpu/drm/msm/hdmi-staging/sde_hdmi.h
+++ b/drivers/gpu/drm/msm/hdmi-staging/sde_hdmi.h
@@ -224,7 +224,7 @@ enum hdmi_tx_scdc_access_type {
#define HDMI_YUV420_24BPP_PCLK_TMDS_CH_RATE_RATIO 2
#define HDMI_RGB_24BPP_PCLK_TMDS_CH_RATE_RATIO 1
-#define HDMI_GEN_PKT_CTRL_CLR_MASK 0x7
+#define HDMI_GEN_PKT_CTRL_CLR_MASK 0x3f0007
/* for AVI program */
#define HDMI_AVI_INFOFRAME_BUFFER_SIZE \
diff --git a/drivers/gpu/drm/msm/hdmi-staging/sde_hdmi_bridge.c b/drivers/gpu/drm/msm/hdmi-staging/sde_hdmi_bridge.c
index ecf93f2c07ac..4df6c0af1707 100644
--- a/drivers/gpu/drm/msm/hdmi-staging/sde_hdmi_bridge.c
+++ b/drivers/gpu/drm/msm/hdmi-staging/sde_hdmi_bridge.c
@@ -125,6 +125,15 @@ static void sde_hdmi_clear_hdr_info(struct drm_bridge *bridge)
connector->hdr_supported = false;
}
+static void sde_hdmi_clear_colorimetry(struct drm_bridge *bridge)
+{
+ struct sde_hdmi_bridge *sde_hdmi_bridge = to_hdmi_bridge(bridge);
+ struct hdmi *hdmi = sde_hdmi_bridge->hdmi;
+ struct drm_connector *connector = hdmi->connector;
+
+ connector->color_enc_fmt = 0;
+}
+
static void sde_hdmi_clear_vsdb_info(struct drm_bridge *bridge)
{
struct sde_hdmi_bridge *sde_hdmi_bridge = to_hdmi_bridge(bridge);
@@ -676,6 +685,8 @@ static void _sde_hdmi_bridge_disable(struct drm_bridge *bridge)
sde_hdmi_clear_vsdbs(bridge);
/* Clear HDMI VCDB block info */
sde_hdmi_clear_vcdb_info(bridge);
+ /* Clear HDMI colorimetry data block info */
+ sde_hdmi_clear_colorimetry(bridge);
mutex_unlock(&display->display_lock);
}
diff --git a/drivers/gpu/drm/msm/hdmi-staging/sde_hdmi_util.c b/drivers/gpu/drm/msm/hdmi-staging/sde_hdmi_util.c
index 8ce90b9bc162..5600f24bd438 100644
--- a/drivers/gpu/drm/msm/hdmi-staging/sde_hdmi_util.c
+++ b/drivers/gpu/drm/msm/hdmi-staging/sde_hdmi_util.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2017, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2017-2018, 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
@@ -73,10 +73,101 @@ static const char *sde_hdmi_hdr_sname(enum sde_hdmi_hdr_state hdr_state)
switch (hdr_state) {
case HDR_DISABLE: return "HDR_DISABLE";
case HDR_ENABLE: return "HDR_ENABLE";
+ case HDR_RESET: return "HDR_RESET";
default: return "HDR_INVALID_STATE";
}
}
+static u8 sde_hdmi_infoframe_checksum(u8 *ptr, size_t size)
+{
+ u8 csum = 0;
+ size_t i;
+
+ /* compute checksum */
+ for (i = 0; i < size; i++)
+ csum += ptr[i];
+
+ return 256 - csum;
+}
+
+u8 sde_hdmi_hdr_set_chksum(struct drm_msm_ext_panel_hdr_metadata *hdr_meta)
+{
+ u8 *buff;
+ u8 *ptr;
+ u32 length;
+ u32 size;
+ u32 chksum = 0;
+ u32 const type_code = 0x87;
+ u32 const version = 0x01;
+ u32 const descriptor_id = 0x00;
+
+ /* length of metadata is 26 bytes */
+ length = 0x1a;
+ /* add 4 bytes for the header */
+ size = length + HDMI_INFOFRAME_HEADER_SIZE;
+
+ buff = kzalloc(size, GFP_KERNEL);
+
+ if (!buff) {
+ SDE_ERROR("invalid buff\n");
+ goto err_alloc;
+ }
+
+ ptr = buff;
+
+ buff[0] = type_code;
+ buff[1] = version;
+ buff[2] = length;
+ buff[3] = 0;
+ /* start infoframe payload */
+ buff += HDMI_INFOFRAME_HEADER_SIZE;
+
+ buff[0] = hdr_meta->eotf;
+ buff[1] = descriptor_id;
+
+ buff[2] = hdr_meta->display_primaries_x[0] & 0xff;
+ buff[3] = hdr_meta->display_primaries_x[0] >> 8;
+
+ buff[4] = hdr_meta->display_primaries_x[1] & 0xff;
+ buff[5] = hdr_meta->display_primaries_x[1] >> 8;
+
+ buff[6] = hdr_meta->display_primaries_x[2] & 0xff;
+ buff[7] = hdr_meta->display_primaries_x[2] >> 8;
+
+ buff[8] = hdr_meta->display_primaries_y[0] & 0xff;
+ buff[9] = hdr_meta->display_primaries_y[0] >> 8;
+
+ buff[10] = hdr_meta->display_primaries_y[1] & 0xff;
+ buff[11] = hdr_meta->display_primaries_y[1] >> 8;
+
+ buff[12] = hdr_meta->display_primaries_y[2] & 0xff;
+ buff[13] = hdr_meta->display_primaries_y[2] >> 8;
+
+ buff[14] = hdr_meta->white_point_x & 0xff;
+ buff[15] = hdr_meta->white_point_x >> 8;
+ buff[16] = hdr_meta->white_point_y & 0xff;
+ buff[17] = hdr_meta->white_point_y >> 8;
+
+ buff[18] = hdr_meta->max_luminance & 0xff;
+ buff[19] = hdr_meta->max_luminance >> 8;
+
+ buff[20] = hdr_meta->min_luminance & 0xff;
+ buff[21] = hdr_meta->min_luminance >> 8;
+
+ buff[22] = hdr_meta->max_content_light_level & 0xff;
+ buff[23] = hdr_meta->max_content_light_level >> 8;
+
+ buff[24] = hdr_meta->max_average_light_level & 0xff;
+ buff[25] = hdr_meta->max_average_light_level >> 8;
+
+ chksum = sde_hdmi_infoframe_checksum(ptr, size);
+
+ kfree(ptr);
+
+err_alloc:
+ return chksum;
+}
+
/**
* sde_hdmi_dump_regs - utility to dump HDMI regs
* @hdmi_display: Pointer to private display handle
@@ -984,18 +1075,23 @@ u8 sde_hdmi_hdr_get_ops(u8 curr_state,
u8 new_state)
{
- /** There could be 3 valid state transitions:
+ /** There could be 4 valid state transitions:
* 1. HDR_DISABLE -> HDR_ENABLE
*
* In this transition, we shall start sending
* HDR metadata with metadata from the HDR clip
*
- * 2. HDR_ENABLE -> HDR_ENABLE
+ * 2. HDR_ENABLE -> HDR_RESET
*
* In this transition, we will keep sending
* HDR metadata but with EOTF and metadata as 0
*
- * 3. HDR_ENABLE -> HDR_DISABLE
+ * 3. HDR_RESET -> HDR_ENABLE
+ *
+ * In this transition, we will start sending
+ * HDR metadata with metadata from the HDR clip
+ *
+ * 4. HDR_RESET -> HDR_DISABLE
*
* In this transition, we will stop sending
* metadata to the sink and clear PKT_CTRL register
@@ -1009,12 +1105,18 @@ u8 sde_hdmi_hdr_get_ops(u8 curr_state,
sde_hdmi_hdr_sname(new_state));
return HDR_SEND_INFO;
} else if ((curr_state == HDR_ENABLE)
+ && (new_state == HDR_RESET)) {
+ HDMI_UTIL_DEBUG("State changed %s ---> %s\n",
+ sde_hdmi_hdr_sname(curr_state),
+ sde_hdmi_hdr_sname(new_state));
+ return HDR_SEND_INFO;
+ } else if ((curr_state == HDR_RESET)
&& (new_state == HDR_ENABLE)) {
HDMI_UTIL_DEBUG("State changed %s ---> %s\n",
sde_hdmi_hdr_sname(curr_state),
sde_hdmi_hdr_sname(new_state));
return HDR_SEND_INFO;
- } else if ((curr_state == HDR_ENABLE)
+ } else if ((curr_state == HDR_RESET)
&& (new_state == HDR_DISABLE)) {
HDMI_UTIL_DEBUG("State changed %s ---> %s\n",
sde_hdmi_hdr_sname(curr_state),
diff --git a/drivers/gpu/drm/msm/hdmi-staging/sde_hdmi_util.h b/drivers/gpu/drm/msm/hdmi-staging/sde_hdmi_util.h
index 340e665f2c28..985d8c3e605c 100644
--- a/drivers/gpu/drm/msm/hdmi-staging/sde_hdmi_util.h
+++ b/drivers/gpu/drm/msm/hdmi-staging/sde_hdmi_util.h
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2017, The Linux Foundation. All rights reserved.
+ * Copyright (c) 2017-2018, 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
@@ -141,8 +141,9 @@ enum sde_hdmi_tx_hdcp2p2_rxstatus_intr_mask {
};
enum sde_hdmi_hdr_state {
- HDR_DISABLE,
- HDR_ENABLE
+ HDR_DISABLE = DRM_MSM_HDR_DISABLE,
+ HDR_ENABLE = DRM_MSM_HDR_ENABLE,
+ HDR_RESET = DRM_MSM_HDR_RESET
};
enum sde_hdmi_hdr_op {
@@ -200,5 +201,6 @@ u8 sde_hdmi_hdr_get_ops(u8 curr_state,
u8 new_state);
void sde_hdmi_ctrl_reset(struct hdmi *hdmi);
void sde_hdmi_ctrl_cfg(struct hdmi *hdmi, bool power_on);
+u8 sde_hdmi_hdr_set_chksum(struct drm_msm_ext_panel_hdr_metadata *hdr_meta);
#endif /* _SDE_HDMI_UTIL_H_ */
diff --git a/drivers/gpu/drm/msm/sde/sde_connector.c b/drivers/gpu/drm/msm/sde/sde_connector.c
index a986f5db2c41..5f6b93931c35 100644
--- a/drivers/gpu/drm/msm/sde/sde_connector.c
+++ b/drivers/gpu/drm/msm/sde/sde_connector.c
@@ -19,6 +19,8 @@
#include "sde_splash.h"
#include <linux/workqueue.h>
#include <linux/atomic.h>
+#include <linux/cpu.h>
+#include <linux/device.h>
#define SDE_DEBUG_CONN(c, fmt, ...) SDE_DEBUG("conn%d " fmt,\
(c) ? (c)->base.base.id : -1, ##__VA_ARGS__)
@@ -574,7 +576,14 @@ void sde_connector_prepare_fence(struct drm_connector *connector)
static void wake_up_cpu(struct work_struct *work)
{
- if (!cpu_up(1))
+ struct device *cpu_dev = NULL;
+
+ cpu_dev = get_cpu_device(1);
+ if (!cpu_dev) {
+ pr_err("Could not get cpu1 device\n");
+ return;
+ }
+ if (!device_online(cpu_dev))
pr_info("cpu1 is online\n");
}
diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/device/tegra.c b/drivers/gpu/drm/nouveau/nvkm/engine/device/tegra.c
index e7e581d6a8ff..1bfc4807ce5b 100644
--- a/drivers/gpu/drm/nouveau/nvkm/engine/device/tegra.c
+++ b/drivers/gpu/drm/nouveau/nvkm/engine/device/tegra.c
@@ -23,6 +23,10 @@
#ifdef CONFIG_NOUVEAU_PLATFORM_DRIVER
#include "priv.h"
+#if IS_ENABLED(CONFIG_ARM_DMA_USE_IOMMU)
+#include <asm/dma-iommu.h>
+#endif
+
static int
nvkm_device_tegra_power_up(struct nvkm_device_tegra *tdev)
{
@@ -85,6 +89,15 @@ nvkm_device_tegra_probe_iommu(struct nvkm_device_tegra *tdev)
unsigned long pgsize_bitmap;
int ret;
+#if IS_ENABLED(CONFIG_ARM_DMA_USE_IOMMU)
+ if (dev->archdata.mapping) {
+ struct dma_iommu_mapping *mapping = to_dma_iommu_mapping(dev);
+
+ arm_iommu_detach_device(dev);
+ arm_iommu_release_mapping(mapping);
+ }
+#endif
+
if (!tdev->func->iommu_bit)
return;
diff --git a/drivers/gpu/drm/panel/panel-samsung-s6e8aa0.c b/drivers/gpu/drm/panel/panel-samsung-s6e8aa0.c
index a188a3959f1a..6ad827b93ae1 100644
--- a/drivers/gpu/drm/panel/panel-samsung-s6e8aa0.c
+++ b/drivers/gpu/drm/panel/panel-samsung-s6e8aa0.c
@@ -823,7 +823,7 @@ static void s6e8aa0_read_mtp_id(struct s6e8aa0 *ctx)
int ret, i;
ret = s6e8aa0_dcs_read(ctx, 0xd1, id, ARRAY_SIZE(id));
- if (ret < ARRAY_SIZE(id) || id[0] == 0x00) {
+ if (ret < 0 || ret < ARRAY_SIZE(id) || id[0] == 0x00) {
dev_err(ctx->dev, "read id failed\n");
ctx->error = -EIO;
return;
diff --git a/drivers/gpu/msm/kgsl.c b/drivers/gpu/msm/kgsl.c
index 02f0cb7eb16c..55ebc0a8e26c 100644
--- a/drivers/gpu/msm/kgsl.c
+++ b/drivers/gpu/msm/kgsl.c
@@ -1403,6 +1403,45 @@ long kgsl_ioctl_device_getproperty(struct kgsl_device_private *dev_priv,
kgsl_context_put(context);
break;
}
+ case KGSL_PROP_SECURE_BUFFER_ALIGNMENT:
+ {
+ unsigned int align;
+
+ if (param->sizebytes != sizeof(unsigned int)) {
+ result = -EINVAL;
+ break;
+ }
+ /*
+ * XPUv2 impose the constraint of 1MB memory alignment,
+ * on the other hand Hypervisor does not have such
+ * constraints. So driver should fulfill such
+ * requirements when allocating secure memory.
+ */
+ align = MMU_FEATURE(&dev_priv->device->mmu,
+ KGSL_MMU_HYP_SECURE_ALLOC) ? PAGE_SIZE : SZ_1M;
+
+ if (copy_to_user(param->value, &align, sizeof(align)))
+ result = -EFAULT;
+
+ break;
+ }
+ case KGSL_PROP_SECURE_CTXT_SUPPORT:
+ {
+ unsigned int secure_ctxt;
+
+ if (param->sizebytes != sizeof(unsigned int)) {
+ result = -EINVAL;
+ break;
+ }
+
+ secure_ctxt = dev_priv->device->mmu.secured ? 1 : 0;
+
+ if (copy_to_user(param->value, &secure_ctxt,
+ sizeof(secure_ctxt)))
+ result = -EFAULT;
+
+ break;
+ }
default:
if (is_compat_task())
result = dev_priv->device->ftbl->getproperty_compat(
diff --git a/drivers/hwtracing/coresight/coresight-tpiu.c b/drivers/hwtracing/coresight/coresight-tpiu.c
index 0da9adc49574..6ddda6232203 100644
--- a/drivers/hwtracing/coresight/coresight-tpiu.c
+++ b/drivers/hwtracing/coresight/coresight-tpiu.c
@@ -46,8 +46,9 @@
/** register definition **/
/* FFSR - 0x300 */
-#define FFSR_FT_STOPPED BIT(1)
+#define FFSR_FT_STOPPED_BIT 1
/* FFCR - 0x304 */
+#define FFCR_FON_MAN_BIT 6
#define FFCR_FON_MAN BIT(6)
#define FFCR_STOP_FI BIT(12)
@@ -93,9 +94,9 @@ static void tpiu_disable_hw(struct tpiu_drvdata *drvdata)
/* Generate manual flush */
writel_relaxed(FFCR_STOP_FI | FFCR_FON_MAN, drvdata->base + TPIU_FFCR);
/* Wait for flush to complete */
- coresight_timeout(drvdata->base, TPIU_FFCR, FFCR_FON_MAN, 0);
+ coresight_timeout(drvdata->base, TPIU_FFCR, FFCR_FON_MAN_BIT, 0);
/* Wait for formatter to stop */
- coresight_timeout(drvdata->base, TPIU_FFSR, FFSR_FT_STOPPED, 1);
+ coresight_timeout(drvdata->base, TPIU_FFSR, FFSR_FT_STOPPED_BIT, 1);
CS_LOCK(drvdata->base);
}
diff --git a/drivers/hwtracing/coresight/coresight.c b/drivers/hwtracing/coresight/coresight.c
index 9b0cc7baca73..24677cdb1bf5 100644
--- a/drivers/hwtracing/coresight/coresight.c
+++ b/drivers/hwtracing/coresight/coresight.c
@@ -87,7 +87,7 @@ static int coresight_find_link_inport(struct coresight_device *csdev)
dev_err(&csdev->dev, "couldn't find inport, parent: %s, child: %s\n",
dev_name(&parent->dev), dev_name(&csdev->dev));
- return 0;
+ return -ENODEV;
}
static int coresight_find_link_outport(struct coresight_device *csdev)
@@ -108,7 +108,7 @@ static int coresight_find_link_outport(struct coresight_device *csdev)
dev_err(&csdev->dev, "couldn't find outport, parent: %s, child: %s\n",
dev_name(&csdev->dev), dev_name(&child->dev));
- return 0;
+ return -ENODEV;
}
static int coresight_enable_sink(struct coresight_device *csdev)
@@ -156,6 +156,9 @@ static int coresight_enable_link(struct coresight_device *csdev)
else
refport = 0;
+ if (refport < 0)
+ return refport;
+
if (atomic_inc_return(&csdev->refcnt[refport]) == 1) {
if (link_ops(csdev)->enable) {
ret = link_ops(csdev)->enable(csdev, inport, outport);
diff --git a/drivers/i2c/busses/i2c-i801.c b/drivers/i2c/busses/i2c-i801.c
index 85f39cc3e276..47581c32b1e1 100644
--- a/drivers/i2c/busses/i2c-i801.c
+++ b/drivers/i2c/busses/i2c-i801.c
@@ -128,6 +128,7 @@
#define SBREG_BAR 0x10
#define SBREG_SMBCTRL 0xc6000c
+#define SBREG_SMBCTRL_DNV 0xcf000c
/* Host status bits for SMBPCISTS */
#define SMBPCISTS_INTS 0x08
@@ -1251,7 +1252,11 @@ static void i801_add_tco(struct i801_priv *priv)
spin_unlock(&p2sb_spinlock);
res = &tco_res[ICH_RES_MEM_OFF];
- res->start = (resource_size_t)base64_addr + SBREG_SMBCTRL;
+ if (pci_dev->device == PCI_DEVICE_ID_INTEL_DNV_SMBUS)
+ res->start = (resource_size_t)base64_addr + SBREG_SMBCTRL_DNV;
+ else
+ res->start = (resource_size_t)base64_addr + SBREG_SMBCTRL;
+
res->end = res->start + 3;
res->flags = IORESOURCE_MEM;
diff --git a/drivers/i2c/busses/i2c-msm-v2.c b/drivers/i2c/busses/i2c-msm-v2.c
index d72953f2df23..198e55829226 100644
--- a/drivers/i2c/busses/i2c-msm-v2.c
+++ b/drivers/i2c/busses/i2c-msm-v2.c
@@ -2330,6 +2330,12 @@ i2c_msm_frmwrk_xfer(struct i2c_adapter *adap, struct i2c_msg msgs[], int num)
struct i2c_msm_ctrl *ctrl = i2c_get_adapdata(adap);
struct i2c_msm_xfer *xfer = &ctrl->xfer;
+ if (num < 1) {
+ dev_err(ctrl->dev,
+ "error on number of msgs(%d) received\n", num);
+ return -EINVAL;
+ }
+
if (IS_ERR_OR_NULL(msgs)) {
dev_err(ctrl->dev, " error on msgs Accessing invalid pointer location\n");
return PTR_ERR(msgs);
diff --git a/drivers/i2c/busses/i2c-xiic.c b/drivers/i2c/busses/i2c-xiic.c
index 0b20449e48cf..da9acec1a029 100644
--- a/drivers/i2c/busses/i2c-xiic.c
+++ b/drivers/i2c/busses/i2c-xiic.c
@@ -533,6 +533,7 @@ static void xiic_start_recv(struct xiic_i2c *i2c)
{
u8 rx_watermark;
struct i2c_msg *msg = i2c->rx_msg = i2c->tx_msg;
+ unsigned long flags;
/* Clear and enable Rx full interrupt. */
xiic_irq_clr_en(i2c, XIIC_INTR_RX_FULL_MASK | XIIC_INTR_TX_ERROR_MASK);
@@ -548,6 +549,7 @@ static void xiic_start_recv(struct xiic_i2c *i2c)
rx_watermark = IIC_RX_FIFO_DEPTH;
xiic_setreg8(i2c, XIIC_RFD_REG_OFFSET, rx_watermark - 1);
+ local_irq_save(flags);
if (!(msg->flags & I2C_M_NOSTART))
/* write the address */
xiic_setreg16(i2c, XIIC_DTR_REG_OFFSET,
@@ -558,6 +560,8 @@ static void xiic_start_recv(struct xiic_i2c *i2c)
xiic_setreg16(i2c, XIIC_DTR_REG_OFFSET,
msg->len | ((i2c->nmsgs == 1) ? XIIC_TX_DYN_STOP_MASK : 0));
+ local_irq_restore(flags);
+
if (i2c->nmsgs == 1)
/* very last, enable bus not busy as well */
xiic_irq_clr_en(i2c, XIIC_INTR_BNB_MASK);
diff --git a/drivers/infiniband/core/cma.c b/drivers/infiniband/core/cma.c
index d57a78ec7425..1454290078de 100644
--- a/drivers/infiniband/core/cma.c
+++ b/drivers/infiniband/core/cma.c
@@ -544,6 +544,7 @@ static int cma_resolve_ib_dev(struct rdma_id_private *id_priv)
dgid = (union ib_gid *) &addr->sib_addr;
pkey = ntohs(addr->sib_pkey);
+ mutex_lock(&lock);
list_for_each_entry(cur_dev, &dev_list, list) {
for (p = 1; p <= cur_dev->device->phys_port_cnt; ++p) {
if (!rdma_cap_af_ib(cur_dev->device, p))
@@ -567,18 +568,19 @@ static int cma_resolve_ib_dev(struct rdma_id_private *id_priv)
cma_dev = cur_dev;
sgid = gid;
id_priv->id.port_num = p;
+ goto found;
}
}
}
}
-
- if (!cma_dev)
- return -ENODEV;
+ mutex_unlock(&lock);
+ return -ENODEV;
found:
cma_attach_to_dev(id_priv, cma_dev);
- addr = (struct sockaddr_ib *) cma_src_addr(id_priv);
- memcpy(&addr->sib_addr, &sgid, sizeof sgid);
+ mutex_unlock(&lock);
+ addr = (struct sockaddr_ib *)cma_src_addr(id_priv);
+ memcpy(&addr->sib_addr, &sgid, sizeof(sgid));
cma_translate_ib(addr, &id_priv->id.route.addr.dev_addr);
return 0;
}
@@ -1280,9 +1282,16 @@ static bool cma_match_net_dev(const struct rdma_cm_id *id,
(addr->src_addr.ss_family == AF_IB ||
cma_protocol_roce_dev_port(id->device, port_num));
- return !addr->dev_addr.bound_dev_if ||
- (net_eq(dev_net(net_dev), addr->dev_addr.net) &&
- addr->dev_addr.bound_dev_if == net_dev->ifindex);
+ /*
+ * Net namespaces must match, and if the listner is listening
+ * on a specific netdevice than netdevice must match as well.
+ */
+ if (net_eq(dev_net(net_dev), addr->dev_addr.net) &&
+ (!!addr->dev_addr.bound_dev_if ==
+ (addr->dev_addr.bound_dev_if == net_dev->ifindex)))
+ return true;
+ else
+ return false;
}
static struct rdma_id_private *cma_find_listener(
diff --git a/drivers/infiniband/ulp/ipoib/ipoib_cm.c b/drivers/infiniband/ulp/ipoib/ipoib_cm.c
index f74b11542603..a338e60836ee 100644
--- a/drivers/infiniband/ulp/ipoib/ipoib_cm.c
+++ b/drivers/infiniband/ulp/ipoib/ipoib_cm.c
@@ -992,12 +992,14 @@ static int ipoib_cm_rep_handler(struct ib_cm_id *cm_id, struct ib_cm_event *even
skb_queue_head_init(&skqueue);
+ netif_tx_lock_bh(p->dev);
spin_lock_irq(&priv->lock);
set_bit(IPOIB_FLAG_OPER_UP, &p->flags);
if (p->neigh)
while ((skb = __skb_dequeue(&p->neigh->queue)))
__skb_queue_tail(&skqueue, skb);
spin_unlock_irq(&priv->lock);
+ netif_tx_unlock_bh(p->dev);
while ((skb = __skb_dequeue(&skqueue))) {
skb->dev = p->dev;
diff --git a/drivers/input/touchscreen/atmel_mxt_ts.c b/drivers/input/touchscreen/atmel_mxt_ts.c
index 88dfe3008cf4..be2f2521c1c5 100644
--- a/drivers/input/touchscreen/atmel_mxt_ts.c
+++ b/drivers/input/touchscreen/atmel_mxt_ts.c
@@ -1593,10 +1593,11 @@ static int mxt_get_object_table(struct mxt_data *data)
break;
case MXT_TOUCH_MULTI_T9:
data->multitouch = MXT_TOUCH_MULTI_T9;
+ /* Only handle messages from first T9 instance */
data->T9_reportid_min = min_id;
- data->T9_reportid_max = max_id;
- data->num_touchids = object->num_report_ids
- * mxt_obj_instances(object);
+ data->T9_reportid_max = min_id +
+ object->num_report_ids - 1;
+ data->num_touchids = object->num_report_ids;
break;
case MXT_SPT_MESSAGECOUNT_T44:
data->T44_address = object->start_address;
diff --git a/drivers/iommu/arm-smmu-v3.c b/drivers/iommu/arm-smmu-v3.c
index 347aaaa5a7ea..fc6eb752ab35 100644
--- a/drivers/iommu/arm-smmu-v3.c
+++ b/drivers/iommu/arm-smmu-v3.c
@@ -1219,6 +1219,7 @@ static irqreturn_t arm_smmu_priq_thread(int irq, void *dev)
/* Sync our overflow flag, as we believe we're up to speed */
q->cons = Q_OVF(q, q->prod) | Q_WRP(q, q->cons) | Q_IDX(q, q->cons);
+ writel(q->cons, q->cons_reg);
return IRQ_HANDLED;
}
diff --git a/drivers/iommu/iommu-debug.c b/drivers/iommu/iommu-debug.c
index 566572ae051e..e44253426b28 100644
--- a/drivers/iommu/iommu-debug.c
+++ b/drivers/iommu/iommu-debug.c
@@ -30,7 +30,7 @@
#include <asm/dma-iommu.h>
#include "iommu-debug.h"
-#if defined(CONFIG_IOMMU_DEBUG_TRACKING) || defined(CONFIG_IOMMU_TESTS)
+#if defined(CONFIG_IOMMU_TESTS)
static const char *iommu_debug_attr_to_string(enum iommu_attr attr)
{
diff --git a/drivers/iommu/ipmmu-vmsa.c b/drivers/iommu/ipmmu-vmsa.c
index dfb868e2d129..624e7ff76166 100644
--- a/drivers/iommu/ipmmu-vmsa.c
+++ b/drivers/iommu/ipmmu-vmsa.c
@@ -44,7 +44,7 @@ struct ipmmu_vmsa_domain {
struct io_pgtable_ops *iop;
unsigned int context_id;
- spinlock_t lock; /* Protects mappings */
+ struct mutex mutex; /* Protects mappings */
};
struct ipmmu_vmsa_archdata {
@@ -464,7 +464,7 @@ static struct iommu_domain *ipmmu_domain_alloc(unsigned type)
if (!domain)
return NULL;
- spin_lock_init(&domain->lock);
+ mutex_init(&domain->mutex);
return &domain->io_domain;
}
@@ -488,7 +488,6 @@ static int ipmmu_attach_device(struct iommu_domain *io_domain,
struct ipmmu_vmsa_archdata *archdata = dev->archdata.iommu;
struct ipmmu_vmsa_device *mmu = archdata->mmu;
struct ipmmu_vmsa_domain *domain = to_vmsa_domain(io_domain);
- unsigned long flags;
unsigned int i;
int ret = 0;
@@ -497,7 +496,7 @@ static int ipmmu_attach_device(struct iommu_domain *io_domain,
return -ENXIO;
}
- spin_lock_irqsave(&domain->lock, flags);
+ mutex_lock(&domain->mutex);
if (!domain->mmu) {
/* The domain hasn't been used yet, initialize it. */
@@ -513,7 +512,7 @@ static int ipmmu_attach_device(struct iommu_domain *io_domain,
ret = -EINVAL;
}
- spin_unlock_irqrestore(&domain->lock, flags);
+ mutex_unlock(&domain->mutex);
if (ret < 0)
return ret;
diff --git a/drivers/irqchip/irq-bcm7038-l1.c b/drivers/irqchip/irq-bcm7038-l1.c
index d7af88534971..6fb34bf0f352 100644
--- a/drivers/irqchip/irq-bcm7038-l1.c
+++ b/drivers/irqchip/irq-bcm7038-l1.c
@@ -216,6 +216,7 @@ static int bcm7038_l1_set_affinity(struct irq_data *d,
return 0;
}
+#ifdef CONFIG_SMP
static void bcm7038_l1_cpu_offline(struct irq_data *d)
{
struct cpumask *mask = irq_data_get_affinity_mask(d);
@@ -240,6 +241,7 @@ static void bcm7038_l1_cpu_offline(struct irq_data *d)
}
irq_set_affinity_locked(d, &new_affinity, false);
}
+#endif
static int __init bcm7038_l1_init_one(struct device_node *dn,
unsigned int idx,
@@ -292,7 +294,9 @@ static struct irq_chip bcm7038_l1_irq_chip = {
.irq_mask = bcm7038_l1_mask,
.irq_unmask = bcm7038_l1_unmask,
.irq_set_affinity = bcm7038_l1_set_affinity,
+#ifdef CONFIG_SMP
.irq_cpu_offline = bcm7038_l1_cpu_offline,
+#endif
};
static int bcm7038_l1_map(struct irq_domain *d, unsigned int virq,
diff --git a/drivers/irqchip/irq-gic-v3-its.c b/drivers/irqchip/irq-gic-v3-its.c
index 82e00e3ad0e0..c3d7a1461043 100644
--- a/drivers/irqchip/irq-gic-v3-its.c
+++ b/drivers/irqchip/irq-gic-v3-its.c
@@ -67,7 +67,10 @@ struct its_node {
unsigned long phys_base;
struct its_cmd_block *cmd_base;
struct its_cmd_block *cmd_write;
- void *tables[GITS_BASER_NR_REGS];
+ struct {
+ void *base;
+ u32 order;
+ } tables[GITS_BASER_NR_REGS];
struct its_collection *collections;
struct list_head its_device_list;
u64 flags;
@@ -77,6 +80,9 @@ struct its_node {
#define ITS_ITT_ALIGN SZ_256
+/* Convert page order to size in bytes */
+#define PAGE_ORDER_TO_SIZE(o) (PAGE_SIZE << (o))
+
struct event_lpi_map {
unsigned long *lpi_map;
u16 *col_map;
@@ -816,9 +822,10 @@ static void its_free_tables(struct its_node *its)
int i;
for (i = 0; i < GITS_BASER_NR_REGS; i++) {
- if (its->tables[i]) {
- free_page((unsigned long)its->tables[i]);
- its->tables[i] = NULL;
+ if (its->tables[i].base) {
+ free_pages((unsigned long)its->tables[i].base,
+ its->tables[i].order);
+ its->tables[i].base = NULL;
}
}
}
@@ -851,7 +858,6 @@ static int its_alloc_tables(const char *node_name, struct its_node *its)
u64 type = GITS_BASER_TYPE(val);
u64 entry_size = GITS_BASER_ENTRY_SIZE(val);
int order = get_order(psz);
- int alloc_size;
int alloc_pages;
u64 tmp;
void *base;
@@ -883,8 +889,8 @@ static int its_alloc_tables(const char *node_name, struct its_node *its)
}
}
- alloc_size = (1 << order) * PAGE_SIZE;
- alloc_pages = (alloc_size / psz);
+retry_alloc_baser:
+ alloc_pages = (PAGE_ORDER_TO_SIZE(order) / psz);
if (alloc_pages > GITS_BASER_PAGES_MAX) {
alloc_pages = GITS_BASER_PAGES_MAX;
order = get_order(GITS_BASER_PAGES_MAX * psz);
@@ -898,7 +904,8 @@ static int its_alloc_tables(const char *node_name, struct its_node *its)
goto out_free;
}
- its->tables[i] = base;
+ its->tables[i].base = base;
+ its->tables[i].order = order;
retry_baser:
val = (virt_to_phys(base) |
@@ -936,7 +943,7 @@ retry_baser:
shr = tmp & GITS_BASER_SHAREABILITY_MASK;
if (!shr) {
cache = GITS_BASER_nC;
- __flush_dcache_area(base, alloc_size);
+ __flush_dcache_area(base, PAGE_ORDER_TO_SIZE(order));
}
goto retry_baser;
}
@@ -947,13 +954,16 @@ retry_baser:
* size and retry. If we reach 4K, then
* something is horribly wrong...
*/
+ free_pages((unsigned long)base, order);
+ its->tables[i].base = NULL;
+
switch (psz) {
case SZ_16K:
psz = SZ_4K;
- goto retry_baser;
+ goto retry_alloc_baser;
case SZ_64K:
psz = SZ_16K;
- goto retry_baser;
+ goto retry_alloc_baser;
}
}
@@ -966,7 +976,7 @@ retry_baser:
}
pr_info("ITS: allocated %d %s @%lx (psz %dK, shr %d)\n",
- (int)(alloc_size / entry_size),
+ (int)(PAGE_ORDER_TO_SIZE(order) / entry_size),
its_base_type_string[type],
(unsigned long)virt_to_phys(base),
psz / SZ_1K, (int)shr >> GITS_BASER_SHAREABILITY_SHIFT);
diff --git a/drivers/irqchip/irq-gic.c b/drivers/irqchip/irq-gic.c
index b0b534622734..25b5a2427705 100644
--- a/drivers/irqchip/irq-gic.c
+++ b/drivers/irqchip/irq-gic.c
@@ -517,7 +517,7 @@ static void __exception_irq_entry gic_handle_irq(struct pt_regs *regs)
irqstat = readl_relaxed(cpu_base + GIC_CPU_INTACK);
irqnr = irqstat & GICC_IAR_INT_ID_MASK;
- if (likely(irqnr > 15 && irqnr < 1021)) {
+ if (likely(irqnr > 15 && irqnr < 1020)) {
if (static_key_true(&supports_deactivate))
writel_relaxed(irqstat, cpu_base + GIC_CPU_EOI);
handle_domain_irq(gic->domain, irqnr, regs);
diff --git a/drivers/macintosh/via-pmu.c b/drivers/macintosh/via-pmu.c
index f9512bfa6c3c..0a41132ffba7 100644
--- a/drivers/macintosh/via-pmu.c
+++ b/drivers/macintosh/via-pmu.c
@@ -530,8 +530,9 @@ init_pmu(void)
int timeout;
struct adb_request req;
- out_8(&via[B], via[B] | TREQ); /* negate TREQ */
- out_8(&via[DIRB], (via[DIRB] | TREQ) & ~TACK); /* TACK in, TREQ out */
+ /* Negate TREQ. Set TACK to input and TREQ to output. */
+ out_8(&via[B], in_8(&via[B]) | TREQ);
+ out_8(&via[DIRB], (in_8(&via[DIRB]) | TREQ) & ~TACK);
pmu_request(&req, NULL, 2, PMU_SET_INTR_MASK, pmu_intr_mask);
timeout = 100000;
@@ -1453,8 +1454,8 @@ pmu_sr_intr(void)
struct adb_request *req;
int bite = 0;
- if (via[B] & TREQ) {
- printk(KERN_ERR "PMU: spurious SR intr (%x)\n", via[B]);
+ if (in_8(&via[B]) & TREQ) {
+ printk(KERN_ERR "PMU: spurious SR intr (%x)\n", in_8(&via[B]));
out_8(&via[IFR], SR_INT);
return NULL;
}
diff --git a/drivers/md/dm-kcopyd.c b/drivers/md/dm-kcopyd.c
index 1452ed9aacb4..54c308e6704f 100644
--- a/drivers/md/dm-kcopyd.c
+++ b/drivers/md/dm-kcopyd.c
@@ -454,6 +454,8 @@ static int run_complete_job(struct kcopyd_job *job)
if (atomic_dec_and_test(&kc->nr_jobs))
wake_up(&kc->destroyq);
+ cond_resched();
+
return 0;
}
diff --git a/drivers/md/raid5.c b/drivers/md/raid5.c
index bb77d20f2ef2..dfe19d74c119 100644
--- a/drivers/md/raid5.c
+++ b/drivers/md/raid5.c
@@ -4190,6 +4190,12 @@ static void analyse_stripe(struct stripe_head *sh, struct stripe_head_state *s)
s->failed++;
if (rdev && !test_bit(Faulty, &rdev->flags))
do_recovery = 1;
+ else if (!rdev) {
+ rdev = rcu_dereference(
+ conf->disks[i].replacement);
+ if (rdev && !test_bit(Faulty, &rdev->flags))
+ do_recovery = 1;
+ }
}
}
if (test_bit(STRIPE_SYNCING, &sh->state)) {
diff --git a/drivers/media/platform/msm/camera_v2/msm_buf_mgr/msm_generic_buf_mgr.c b/drivers/media/platform/msm/camera_v2/msm_buf_mgr/msm_generic_buf_mgr.c
index 58bfdb77a492..bf5296e6d071 100644
--- a/drivers/media/platform/msm/camera_v2/msm_buf_mgr/msm_generic_buf_mgr.c
+++ b/drivers/media/platform/msm/camera_v2/msm_buf_mgr/msm_generic_buf_mgr.c
@@ -570,15 +570,13 @@ static long msm_buf_mngr_subdev_ioctl(struct v4l2_subdev *sd,
k_ioctl = *ptr;
switch (k_ioctl.id) {
case MSM_CAMERA_BUF_MNGR_IOCTL_ID_GET_BUF_BY_IDX: {
+ struct msm_buf_mngr_info buf_info, *tmp = NULL;
if (k_ioctl.size != sizeof(struct msm_buf_mngr_info))
return -EINVAL;
if (!k_ioctl.ioctl_ptr)
return -EINVAL;
-#ifndef CONFIG_COMPAT
- {
- struct msm_buf_mngr_info buf_info, *tmp = NULL;
-
+ if (!is_compat_task()) {
MSM_CAM_GET_IOCTL_ARG_PTR(&tmp,
&k_ioctl.ioctl_ptr, sizeof(tmp));
if (copy_from_user(&buf_info, tmp,
@@ -587,7 +585,7 @@ static long msm_buf_mngr_subdev_ioctl(struct v4l2_subdev *sd,
}
k_ioctl.ioctl_ptr = (uintptr_t)&buf_info;
}
-#endif
+
argp = &k_ioctl;
rc = msm_cam_buf_mgr_ops(cmd, argp);
}
diff --git a/drivers/media/platform/msm/vidc/msm_vidc.c b/drivers/media/platform/msm/vidc/msm_vidc.c
index c288568edfbd..81ce5813cec4 100644
--- a/drivers/media/platform/msm/vidc/msm_vidc.c
+++ b/drivers/media/platform/msm/vidc/msm_vidc.c
@@ -1091,6 +1091,15 @@ int msm_vidc_dqbuf(void *instance, struct v4l2_buffer *b)
b->m.planes[i].m.userptr = buffer_info->uvaddr[i];
b->m.planes[i].reserved[0] = buffer_info->fd[i];
b->m.planes[i].reserved[1] = buffer_info->buff_off[i];
+
+ b->m.planes[i].reserved[2] = buffer_info->crop_data.nLeft;
+ b->m.planes[i].reserved[3] = buffer_info->crop_data.nTop;
+ b->m.planes[i].reserved[4] = buffer_info->crop_data.nWidth;
+ b->m.planes[i].reserved[5] = buffer_info->crop_data.nHeight;
+ b->m.planes[i].reserved[6] =
+ buffer_info->crop_data.width_height[0];
+ b->m.planes[i].reserved[7] =
+ buffer_info->crop_data.width_height[1];
if (!(inst->flags & VIDC_SECURE) && !b->m.planes[i].m.userptr) {
dprintk(VIDC_ERR,
"%s: Failed to find user virtual address, %#lx, %d, %d\n",
diff --git a/drivers/media/platform/msm/vidc/msm_vidc_common.c b/drivers/media/platform/msm/vidc/msm_vidc_common.c
index ee3cfb88855c..610ed9c6fed9 100644
--- a/drivers/media/platform/msm/vidc/msm_vidc_common.c
+++ b/drivers/media/platform/msm/vidc/msm_vidc_common.c
@@ -2061,6 +2061,7 @@ static void handle_fbd(enum hal_command_response cmd, void *data)
int extra_idx = 0;
int64_t time_usec = 0;
struct vb2_v4l2_buffer *vbuf = NULL;
+ struct buffer_info *buffer_info = NULL;
if (!response) {
dprintk(VIDC_ERR, "Invalid response from vidc_hal\n");
@@ -2102,6 +2103,26 @@ static void handle_fbd(enum hal_command_response cmd, void *data)
"fbd:Overflow bytesused = %d; length = %d\n",
vb->planes[0].bytesused,
vb->planes[0].length);
+
+ buffer_info = device_to_uvaddr(&inst->registeredbufs,
+ fill_buf_done->packet_buffer1);
+
+ if (!buffer_info) {
+ dprintk(VIDC_ERR,
+ "%s buffer not found in registered list\n",
+ __func__);
+ return;
+ }
+
+ buffer_info->crop_data.nLeft = fill_buf_done->start_x_coord;
+ buffer_info->crop_data.nTop = fill_buf_done->start_y_coord;
+ buffer_info->crop_data.nWidth = fill_buf_done->frame_width;
+ buffer_info->crop_data.nHeight = fill_buf_done->frame_height;
+ buffer_info->crop_data.width_height[0] =
+ inst->prop.width[CAPTURE_PORT];
+ buffer_info->crop_data.width_height[1] =
+ inst->prop.height[CAPTURE_PORT];
+
if (!(fill_buf_done->flags1 &
HAL_BUFFERFLAG_TIMESTAMPINVALID)) {
time_usec = fill_buf_done->timestamp_hi;
diff --git a/drivers/media/platform/msm/vidc/msm_vidc_internal.h b/drivers/media/platform/msm/vidc/msm_vidc_internal.h
index 2a4033598bd2..08dad912bd57 100644
--- a/drivers/media/platform/msm/vidc/msm_vidc_internal.h
+++ b/drivers/media/platform/msm/vidc/msm_vidc_internal.h
@@ -329,6 +329,14 @@ int msm_vidc_check_session_supported(struct msm_vidc_inst *inst);
int msm_vidc_check_scaling_supported(struct msm_vidc_inst *inst);
void msm_vidc_queue_v4l2_event(struct msm_vidc_inst *inst, int event_type);
+struct crop_info {
+ u32 nLeft;
+ u32 nTop;
+ u32 nWidth;
+ u32 nHeight;
+ u32 width_height[MAX_PORT_NUM];
+};
+
struct buffer_info {
struct list_head list;
int type;
@@ -348,6 +356,7 @@ struct buffer_info {
bool mapped[VIDEO_MAX_PLANES];
int same_fd_ref[VIDEO_MAX_PLANES];
struct timeval timestamp;
+ struct crop_info crop_data;
};
struct buffer_info *device_to_uvaddr(struct msm_vidc_list *buf_list,
diff --git a/drivers/media/v4l2-core/videobuf2-core.c b/drivers/media/v4l2-core/videobuf2-core.c
index 0c1a42bf27fd..1c37d5a78822 100644
--- a/drivers/media/v4l2-core/videobuf2-core.c
+++ b/drivers/media/v4l2-core/videobuf2-core.c
@@ -1366,6 +1366,11 @@ int vb2_core_qbuf(struct vb2_queue *q, unsigned int index, void *pb)
struct vb2_buffer *vb;
int ret;
+ if (q->error) {
+ dprintk(1, "fatal error occurred on queue\n");
+ return -EIO;
+ }
+
vb = q->bufs[index];
switch (vb->state) {
diff --git a/drivers/mfd/sm501.c b/drivers/mfd/sm501.c
index c646784c5a7d..fbec711c4195 100644
--- a/drivers/mfd/sm501.c
+++ b/drivers/mfd/sm501.c
@@ -714,6 +714,7 @@ sm501_create_subdev(struct sm501_devdata *sm, char *name,
smdev->pdev.name = name;
smdev->pdev.id = sm->pdev_id;
smdev->pdev.dev.parent = sm->dev;
+ smdev->pdev.dev.coherent_dma_mask = 0xffffffff;
if (res_count) {
smdev->pdev.resource = (struct resource *)(smdev+1);
diff --git a/drivers/mfd/ti_am335x_tscadc.c b/drivers/mfd/ti_am335x_tscadc.c
index e4e4b22eebc9..4a0f076c91ba 100644
--- a/drivers/mfd/ti_am335x_tscadc.c
+++ b/drivers/mfd/ti_am335x_tscadc.c
@@ -224,14 +224,13 @@ static int ti_tscadc_probe(struct platform_device *pdev)
* The TSC_ADC_SS controller design assumes the OCP clock is
* at least 6x faster than the ADC clock.
*/
- clk = clk_get(&pdev->dev, "adc_tsc_fck");
+ clk = devm_clk_get(&pdev->dev, "adc_tsc_fck");
if (IS_ERR(clk)) {
dev_err(&pdev->dev, "failed to get TSC fck\n");
err = PTR_ERR(clk);
goto err_disable_clk;
}
clock_rate = clk_get_rate(clk);
- clk_put(clk);
tscadc->clk_div = clock_rate / ADC_CLK;
/* TSCADC_CLKDIV needs to be configured to the value minus 1 */
diff --git a/drivers/misc/hmc6352.c b/drivers/misc/hmc6352.c
index 90520d76633f..9cde4c5bfba4 100644
--- a/drivers/misc/hmc6352.c
+++ b/drivers/misc/hmc6352.c
@@ -27,6 +27,7 @@
#include <linux/err.h>
#include <linux/delay.h>
#include <linux/sysfs.h>
+#include <linux/nospec.h>
static DEFINE_MUTEX(compass_mutex);
@@ -50,6 +51,7 @@ static int compass_store(struct device *dev, const char *buf, size_t count,
return ret;
if (val >= strlen(map))
return -EINVAL;
+ val = array_index_nospec(val, strlen(map));
mutex_lock(&compass_mutex);
ret = compass_command(c, map[val]);
mutex_unlock(&compass_mutex);
diff --git a/drivers/misc/lkdtm.c b/drivers/misc/lkdtm.c
index 2a6eaf1122b4..8e06e1020ad9 100644
--- a/drivers/misc/lkdtm.c
+++ b/drivers/misc/lkdtm.c
@@ -47,11 +47,18 @@
#include <linux/vmalloc.h>
#include <linux/mman.h>
#include <asm/cacheflush.h>
+#include <linux/list.h>
+#include <linux/sched.h>
+#include <linux/uaccess.h>
#ifdef CONFIG_IDE
#include <linux/ide.h>
#endif
+struct lkdtm_list {
+ struct list_head node;
+};
+
/*
* Make sure our attempts to over run the kernel stack doesn't trigger
* a compiler warning when CONFIG_FRAME_WARN is set. Then make sure we
@@ -88,6 +95,9 @@ enum ctype {
CT_EXCEPTION,
CT_LOOP,
CT_OVERFLOW,
+ CT_CORRUPT_LIST_ADD,
+ CT_CORRUPT_LIST_DEL,
+ CT_CORRUPT_USER_DS,
CT_CORRUPT_STACK,
CT_UNALIGNED_LOAD_STORE_WRITE,
CT_OVERWRITE_ALLOCATION,
@@ -126,6 +136,9 @@ static char* cp_type[] = {
"EXCEPTION",
"LOOP",
"OVERFLOW",
+ "CORRUPT_LIST_ADD",
+ "CORRUPT_LIST_DEL",
+ "CORRUPT_USER_DS",
"CORRUPT_STACK",
"UNALIGNED_LOAD_STORE_WRITE",
"OVERWRITE_ALLOCATION",
@@ -548,6 +561,75 @@ static void lkdtm_do_action(enum ctype which)
do_overwritten();
break;
}
+ case CT_CORRUPT_LIST_ADD: {
+ /*
+ * Initially, an empty list via LIST_HEAD:
+ * test_head.next = &test_head
+ * test_head.prev = &test_head
+ */
+ LIST_HEAD(test_head);
+ struct lkdtm_list good, bad;
+ void *target[2] = { };
+ void *redirection = &target;
+
+ pr_info("attempting good list addition\n");
+
+ /*
+ * Adding to the list performs these actions:
+ * test_head.next->prev = &good.node
+ * good.node.next = test_head.next
+ * good.node.prev = test_head
+ * test_head.next = good.node
+ */
+ list_add(&good.node, &test_head);
+
+ pr_info("attempting corrupted list addition\n");
+ /*
+ * In simulating this "write what where" primitive, the "what" is
+ * the address of &bad.node, and the "where" is the address held
+ * by "redirection".
+ */
+ test_head.next = redirection;
+ list_add(&bad.node, &test_head);
+
+ if (target[0] == NULL && target[1] == NULL)
+ pr_err("Overwrite did not happen, but no BUG?!\n");
+ else
+ pr_err("list_add() corruption not detected!\n");
+ break;
+ }
+ case CT_CORRUPT_LIST_DEL: {
+ LIST_HEAD(test_head);
+ struct lkdtm_list item;
+ void *target[2] = { };
+ void *redirection = &target;
+
+ list_add(&item.node, &test_head);
+
+ pr_info("attempting good list removal\n");
+ list_del(&item.node);
+
+ pr_info("attempting corrupted list removal\n");
+ list_add(&item.node, &test_head);
+
+ /* As with the list_add() test above, this corrupts "next". */
+ item.node.next = redirection;
+ list_del(&item.node);
+
+ if (target[0] == NULL && target[1] == NULL)
+ pr_err("Overwrite did not happen, but no BUG?!\n");
+ else
+ pr_err("list_del() corruption not detected!\n");
+ break;
+ }
+ case CT_CORRUPT_USER_DS: {
+ pr_info("setting bad task size limit\n");
+ set_fs(KERNEL_DS);
+
+ /* Make sure we do not keep running with a KERNEL_DS! */
+ force_sig(SIGKILL, current);
+ break;
+ }
case CT_NONE:
default:
break;
diff --git a/drivers/misc/mei/bus-fixup.c b/drivers/misc/mei/bus-fixup.c
index bdc7fcd80eca..9dcdc6f41ceb 100644
--- a/drivers/misc/mei/bus-fixup.c
+++ b/drivers/misc/mei/bus-fixup.c
@@ -151,7 +151,7 @@ static int mei_nfc_if_version(struct mei_cl *cl,
ret = 0;
bytes_recv = __mei_cl_recv(cl, (u8 *)reply, if_version_length);
- if (bytes_recv < if_version_length) {
+ if (bytes_recv < 0 || bytes_recv < if_version_length) {
dev_err(bus->dev, "Could not read IF version\n");
ret = -EIO;
goto err;
diff --git a/drivers/misc/mei/pci-me.c b/drivers/misc/mei/pci-me.c
index adab5bbb642a..d5b84d68f988 100644
--- a/drivers/misc/mei/pci-me.c
+++ b/drivers/misc/mei/pci-me.c
@@ -230,8 +230,11 @@ static int mei_me_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
if (!pci_dev_run_wake(pdev))
mei_me_set_pm_domain(dev);
- if (mei_pg_is_enabled(dev))
+ if (mei_pg_is_enabled(dev)) {
pm_runtime_put_noidle(&pdev->dev);
+ if (hw->d0i3_supported)
+ pm_runtime_allow(&pdev->dev);
+ }
dev_dbg(&pdev->dev, "initialization successful.\n");
diff --git a/drivers/misc/mic/scif/scif_api.c b/drivers/misc/mic/scif/scif_api.c
index ddc9e4b08b5c..56efa9d18a9a 100644
--- a/drivers/misc/mic/scif/scif_api.c
+++ b/drivers/misc/mic/scif/scif_api.c
@@ -370,11 +370,10 @@ int scif_bind(scif_epd_t epd, u16 pn)
goto scif_bind_exit;
}
} else {
- pn = scif_get_new_port();
- if (!pn) {
- ret = -ENOSPC;
+ ret = scif_get_new_port();
+ if (ret < 0)
goto scif_bind_exit;
- }
+ pn = ret;
}
ep->state = SCIFEP_BOUND;
@@ -648,13 +647,12 @@ int __scif_connect(scif_epd_t epd, struct scif_port_id *dst, bool non_block)
err = -EISCONN;
break;
case SCIFEP_UNBOUND:
- ep->port.port = scif_get_new_port();
- if (!ep->port.port) {
- err = -ENOSPC;
- } else {
- ep->port.node = scif_info.nodeid;
- ep->conn_async_state = ASYNC_CONN_IDLE;
- }
+ err = scif_get_new_port();
+ if (err < 0)
+ break;
+ ep->port.port = err;
+ ep->port.node = scif_info.nodeid;
+ ep->conn_async_state = ASYNC_CONN_IDLE;
/* Fall through */
case SCIFEP_BOUND:
/*
diff --git a/drivers/misc/ti-st/st_kim.c b/drivers/misc/ti-st/st_kim.c
index 71b64550b591..a1bca836e506 100644
--- a/drivers/misc/ti-st/st_kim.c
+++ b/drivers/misc/ti-st/st_kim.c
@@ -757,14 +757,14 @@ static int kim_probe(struct platform_device *pdev)
err = gpio_request(kim_gdata->nshutdown, "kim");
if (unlikely(err)) {
pr_err(" gpio %d request failed ", kim_gdata->nshutdown);
- return err;
+ goto err_sysfs_group;
}
/* Configure nShutdown GPIO as output=0 */
err = gpio_direction_output(kim_gdata->nshutdown, 0);
if (unlikely(err)) {
pr_err(" unable to configure gpio %d", kim_gdata->nshutdown);
- return err;
+ goto err_sysfs_group;
}
/* get reference of pdev for request_firmware
*/
diff --git a/drivers/misc/vmw_balloon.c b/drivers/misc/vmw_balloon.c
index 518e2dec2aa2..5e9122cd3898 100644
--- a/drivers/misc/vmw_balloon.c
+++ b/drivers/misc/vmw_balloon.c
@@ -45,6 +45,7 @@
#include <linux/seq_file.h>
#include <linux/vmw_vmci_defs.h>
#include <linux/vmw_vmci_api.h>
+#include <linux/io.h>
#include <asm/hypervisor.h>
MODULE_AUTHOR("VMware, Inc.");
diff --git a/drivers/mtd/maps/solutionengine.c b/drivers/mtd/maps/solutionengine.c
index bb580bc16445..c07f21b20463 100644
--- a/drivers/mtd/maps/solutionengine.c
+++ b/drivers/mtd/maps/solutionengine.c
@@ -59,9 +59,9 @@ static int __init init_soleng_maps(void)
return -ENXIO;
}
}
- printk(KERN_NOTICE "Solution Engine: Flash at 0x%08lx, EPROM at 0x%08lx\n",
- soleng_flash_map.phys & 0x1fffffff,
- soleng_eprom_map.phys & 0x1fffffff);
+ printk(KERN_NOTICE "Solution Engine: Flash at 0x%pap, EPROM at 0x%pap\n",
+ &soleng_flash_map.phys,
+ &soleng_eprom_map.phys);
flash_mtd->owner = THIS_MODULE;
eprom_mtd = do_map_probe("map_rom", &soleng_eprom_map);
diff --git a/drivers/mtd/mtdchar.c b/drivers/mtd/mtdchar.c
index 6d19835b80a9..0d244dac1ccb 100644
--- a/drivers/mtd/mtdchar.c
+++ b/drivers/mtd/mtdchar.c
@@ -160,8 +160,12 @@ static ssize_t mtdchar_read(struct file *file, char __user *buf, size_t count,
pr_debug("MTD_read\n");
- if (*ppos + count > mtd->size)
- count = mtd->size - *ppos;
+ if (*ppos + count > mtd->size) {
+ if (*ppos < mtd->size)
+ count = mtd->size - *ppos;
+ else
+ count = 0;
+ }
if (!count)
return 0;
@@ -246,7 +250,7 @@ static ssize_t mtdchar_write(struct file *file, const char __user *buf, size_t c
pr_debug("MTD_write\n");
- if (*ppos == mtd->size)
+ if (*ppos >= mtd->size)
return -ENOSPC;
if (*ppos + count > mtd->size)
diff --git a/drivers/mtd/ubi/wl.c b/drivers/mtd/ubi/wl.c
index ffcb64bc2bf8..16ca37e18512 100644
--- a/drivers/mtd/ubi/wl.c
+++ b/drivers/mtd/ubi/wl.c
@@ -1849,8 +1849,10 @@ int ubi_wl_init(struct ubi_device *ubi, struct ubi_attach_info *ai)
cond_resched();
e = kmem_cache_alloc(ubi_wl_entry_slab, GFP_KERNEL);
- if (!e)
+ if (!e) {
+ err = -ENOMEM;
goto out_free;
+ }
e->pnum = aeb->pnum;
e->ec = aeb->ec;
@@ -1871,8 +1873,10 @@ int ubi_wl_init(struct ubi_device *ubi, struct ubi_attach_info *ai)
cond_resched();
e = kmem_cache_alloc(ubi_wl_entry_slab, GFP_KERNEL);
- if (!e)
+ if (!e) {
+ err = -ENOMEM;
goto out_free;
+ }
e->pnum = aeb->pnum;
e->ec = aeb->ec;
diff --git a/drivers/net/ethernet/broadcom/genet/bcmgenet.h b/drivers/net/ethernet/broadcom/genet/bcmgenet.h
index cef53f2d9854..ce20bc939b38 100644
--- a/drivers/net/ethernet/broadcom/genet/bcmgenet.h
+++ b/drivers/net/ethernet/broadcom/genet/bcmgenet.h
@@ -185,6 +185,9 @@ struct bcmgenet_mib_counters {
#define UMAC_MAC1 0x010
#define UMAC_MAX_FRAME_LEN 0x014
+#define UMAC_MODE 0x44
+#define MODE_LINK_STATUS (1 << 5)
+
#define UMAC_EEE_CTRL 0x064
#define EN_LPI_RX_PAUSE (1 << 0)
#define EN_LPI_TX_PFC (1 << 1)
diff --git a/drivers/net/ethernet/broadcom/genet/bcmmii.c b/drivers/net/ethernet/broadcom/genet/bcmmii.c
index e96d1f95bb47..4c73feca4842 100644
--- a/drivers/net/ethernet/broadcom/genet/bcmmii.c
+++ b/drivers/net/ethernet/broadcom/genet/bcmmii.c
@@ -167,8 +167,14 @@ void bcmgenet_mii_setup(struct net_device *dev)
static int bcmgenet_fixed_phy_link_update(struct net_device *dev,
struct fixed_phy_status *status)
{
- if (dev && dev->phydev && status)
- status->link = dev->phydev->link;
+ struct bcmgenet_priv *priv;
+ u32 reg;
+
+ if (dev && dev->phydev && status) {
+ priv = netdev_priv(dev);
+ reg = bcmgenet_umac_readl(priv, UMAC_MODE);
+ status->link = !!(reg & MODE_LINK_STATUS);
+ }
return 0;
}
diff --git a/drivers/net/ethernet/cisco/enic/enic_main.c b/drivers/net/ethernet/cisco/enic/enic_main.c
index b20bce2c7da1..0433fdebda25 100644
--- a/drivers/net/ethernet/cisco/enic/enic_main.c
+++ b/drivers/net/ethernet/cisco/enic/enic_main.c
@@ -2683,7 +2683,6 @@ static int enic_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
*/
enic->port_mtu = enic->config.mtu;
- (void)enic_change_mtu(netdev, enic->port_mtu);
err = enic_set_mac_addr(netdev, enic->mac_addr);
if (err) {
@@ -2732,6 +2731,7 @@ static int enic_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
netdev->features |= NETIF_F_HIGHDMA;
netdev->priv_flags |= IFF_UNICAST_FLT;
+ netdev->mtu = enic->port_mtu;
err = register_netdev(netdev);
if (err) {
diff --git a/drivers/net/ethernet/marvell/mvneta.c b/drivers/net/ethernet/marvell/mvneta.c
index ea693bbf56d8..1c300259d70a 100644
--- a/drivers/net/ethernet/marvell/mvneta.c
+++ b/drivers/net/ethernet/marvell/mvneta.c
@@ -2569,7 +2569,6 @@ static int mvneta_change_mtu(struct net_device *dev, int mtu)
}
mvneta_start_dev(pp);
- mvneta_port_up(pp);
netdev_update_features(dev);
diff --git a/drivers/net/ethernet/qlogic/qlge/qlge_main.c b/drivers/net/ethernet/qlogic/qlge/qlge_main.c
index b28e73ea2c25..f39ad0e66637 100644
--- a/drivers/net/ethernet/qlogic/qlge/qlge_main.c
+++ b/drivers/net/ethernet/qlogic/qlge/qlge_main.c
@@ -2388,26 +2388,20 @@ static int qlge_update_hw_vlan_features(struct net_device *ndev,
return status;
}
-static netdev_features_t qlge_fix_features(struct net_device *ndev,
- netdev_features_t features)
-{
- int err;
-
- /* Update the behavior of vlan accel in the adapter */
- err = qlge_update_hw_vlan_features(ndev, features);
- if (err)
- return err;
-
- return features;
-}
-
static int qlge_set_features(struct net_device *ndev,
netdev_features_t features)
{
netdev_features_t changed = ndev->features ^ features;
+ int err;
+
+ if (changed & NETIF_F_HW_VLAN_CTAG_RX) {
+ /* Update the behavior of vlan accel in the adapter */
+ err = qlge_update_hw_vlan_features(ndev, features);
+ if (err)
+ return err;
- if (changed & NETIF_F_HW_VLAN_CTAG_RX)
qlge_vlan_mode(ndev, features);
+ }
return 0;
}
@@ -4720,7 +4714,6 @@ static const struct net_device_ops qlge_netdev_ops = {
.ndo_set_mac_address = qlge_set_mac_address,
.ndo_validate_addr = eth_validate_addr,
.ndo_tx_timeout = qlge_tx_timeout,
- .ndo_fix_features = qlge_fix_features,
.ndo_set_features = qlge_set_features,
.ndo_vlan_rx_add_vid = qlge_vlan_rx_add_vid,
.ndo_vlan_rx_kill_vid = qlge_vlan_rx_kill_vid,
diff --git a/drivers/net/ethernet/ti/cpsw.c b/drivers/net/ethernet/ti/cpsw.c
index c69b0bdd891d..c1217a87d535 100644
--- a/drivers/net/ethernet/ti/cpsw.c
+++ b/drivers/net/ethernet/ti/cpsw.c
@@ -371,7 +371,6 @@ struct cpsw_priv {
spinlock_t lock;
struct platform_device *pdev;
struct net_device *ndev;
- struct device_node *phy_node;
struct napi_struct napi_rx;
struct napi_struct napi_tx;
struct device *dev;
@@ -1165,25 +1164,34 @@ static void cpsw_slave_open(struct cpsw_slave *slave, struct cpsw_priv *priv)
cpsw_ale_add_mcast(priv->ale, priv->ndev->broadcast,
1 << slave_port, 0, 0, ALE_MCAST_FWD_2);
- if (priv->phy_node)
- slave->phy = of_phy_connect(priv->ndev, priv->phy_node,
+ if (slave->data->phy_node) {
+ slave->phy = of_phy_connect(priv->ndev, slave->data->phy_node,
&cpsw_adjust_link, 0, slave->data->phy_if);
- else
+ if (!slave->phy) {
+ dev_err(priv->dev, "phy \"%s\" not found on slave %d\n",
+ slave->data->phy_node->full_name,
+ slave->slave_num);
+ return;
+ }
+ } else {
slave->phy = phy_connect(priv->ndev, slave->data->phy_id,
&cpsw_adjust_link, slave->data->phy_if);
- if (IS_ERR(slave->phy)) {
- dev_err(priv->dev, "phy %s not found on slave %d\n",
- slave->data->phy_id, slave->slave_num);
- slave->phy = NULL;
- } else {
- dev_info(priv->dev, "phy found : id is : 0x%x\n",
- slave->phy->phy_id);
- phy_start(slave->phy);
-
- /* Configure GMII_SEL register */
- cpsw_phy_sel(&priv->pdev->dev, slave->phy->interface,
- slave->slave_num);
+ if (IS_ERR(slave->phy)) {
+ dev_err(priv->dev,
+ "phy \"%s\" not found on slave %d, err %ld\n",
+ slave->data->phy_id, slave->slave_num,
+ PTR_ERR(slave->phy));
+ slave->phy = NULL;
+ return;
+ }
}
+
+ dev_info(priv->dev, "phy found : id is : 0x%x\n", slave->phy->phy_id);
+
+ phy_start(slave->phy);
+
+ /* Configure GMII_SEL register */
+ cpsw_phy_sel(&priv->pdev->dev, slave->phy->interface, slave->slave_num);
}
static inline void cpsw_add_default_vlan(struct cpsw_priv *priv)
@@ -1957,12 +1965,11 @@ static void cpsw_slave_init(struct cpsw_slave *slave, struct cpsw_priv *priv,
slave->port_vlan = data->dual_emac_res_vlan;
}
-static int cpsw_probe_dt(struct cpsw_priv *priv,
+static int cpsw_probe_dt(struct cpsw_platform_data *data,
struct platform_device *pdev)
{
struct device_node *node = pdev->dev.of_node;
struct device_node *slave_node;
- struct cpsw_platform_data *data = &priv->data;
int i = 0, ret;
u32 prop;
@@ -2050,7 +2057,8 @@ static int cpsw_probe_dt(struct cpsw_priv *priv,
if (strcmp(slave_node->name, "slave"))
continue;
- priv->phy_node = of_parse_phandle(slave_node, "phy-handle", 0);
+ slave_data->phy_node = of_parse_phandle(slave_node,
+ "phy-handle", 0);
parp = of_get_property(slave_node, "phy_id", &lenp);
if (of_phy_is_fixed_link(slave_node)) {
struct device_node *phy_node;
@@ -2087,6 +2095,7 @@ static int cpsw_probe_dt(struct cpsw_priv *priv,
}
snprintf(slave_data->phy_id, sizeof(slave_data->phy_id),
PHY_ID_FMT, mdio->name, phyid);
+ put_device(&mdio->dev);
} else {
dev_err(&pdev->dev, "No slave[%d] phy_id or fixed-link property\n", i);
goto no_phy_slave;
@@ -2291,7 +2300,7 @@ static int cpsw_probe(struct platform_device *pdev)
/* Select default pin state */
pinctrl_pm_select_default_state(&pdev->dev);
- if (cpsw_probe_dt(priv, pdev)) {
+ if (cpsw_probe_dt(&priv->data, pdev)) {
dev_err(&pdev->dev, "cpsw: platform data missing\n");
ret = -ENODEV;
goto clean_runtime_disable_ret;
diff --git a/drivers/net/ethernet/ti/cpsw.h b/drivers/net/ethernet/ti/cpsw.h
index 442a7038e660..e50afd1b2eda 100644
--- a/drivers/net/ethernet/ti/cpsw.h
+++ b/drivers/net/ethernet/ti/cpsw.h
@@ -18,6 +18,7 @@
#include <linux/phy.h>
struct cpsw_slave_data {
+ struct device_node *phy_node;
char phy_id[MII_BUS_ID_SIZE];
int phy_if;
u8 mac_addr[ETH_ALEN];
diff --git a/drivers/net/ethernet/ti/davinci_emac.c b/drivers/net/ethernet/ti/davinci_emac.c
index 6be315303d61..8ecb24186b7f 100644
--- a/drivers/net/ethernet/ti/davinci_emac.c
+++ b/drivers/net/ethernet/ti/davinci_emac.c
@@ -2108,6 +2108,7 @@ static int davinci_emac_remove(struct platform_device *pdev)
cpdma_ctlr_destroy(priv->dma);
unregister_netdev(ndev);
+ of_node_put(priv->phy_node);
free_netdev(ndev);
return 0;
diff --git a/drivers/net/wireless/ath/ath10k/mac.c b/drivers/net/wireless/ath/ath10k/mac.c
index 187b60c8a672..db0476c44b41 100644
--- a/drivers/net/wireless/ath/ath10k/mac.c
+++ b/drivers/net/wireless/ath/ath10k/mac.c
@@ -3024,6 +3024,13 @@ static int ath10k_update_channel_list(struct ath10k *ar)
passive = channel->flags & IEEE80211_CHAN_NO_IR;
ch->passive = passive;
+ /* the firmware is ignoring the "radar" flag of the
+ * channel and is scanning actively using Probe Requests
+ * on "Radar detection"/DFS channels which are not
+ * marked as "available"
+ */
+ ch->passive |= ch->chan_radar;
+
ch->freq = channel->center_freq;
ch->band_center_freq1 = channel->center_freq;
ch->min_power = 0;
diff --git a/drivers/net/wireless/cnss2/bus.c b/drivers/net/wireless/cnss2/bus.c
index 0d46b4f6b6a4..c0810df81bfc 100644
--- a/drivers/net/wireless/cnss2/bus.c
+++ b/drivers/net/wireless/cnss2/bus.c
@@ -34,6 +34,7 @@ enum cnss_dev_bus_type cnss_get_bus_type(unsigned long device_id)
case QCA6174_DEVICE_ID:
case QCA6290_EMULATION_DEVICE_ID:
case QCA6290_DEVICE_ID:
+ case QCN7605_DEVICE_ID:
return CNSS_BUS_PCI;
default:
cnss_pr_err("Unknown device_id: 0x%lx\n", device_id);
diff --git a/drivers/net/wireless/cnss2/bus.h b/drivers/net/wireless/cnss2/bus.h
index 4e3d1500bd76..bd32a94e5146 100644
--- a/drivers/net/wireless/cnss2/bus.h
+++ b/drivers/net/wireless/cnss2/bus.h
@@ -24,6 +24,8 @@
#define QCA6290_DEVICE_ID 0x1100
#define QCA6290_EMULATION_VENDOR_ID 0x168C
#define QCA6290_EMULATION_DEVICE_ID 0xABCD
+#define QCN7605_VENDOR_ID 0x17CB
+#define QCN7605_DEVICE_ID 0x1102
enum cnss_dev_bus_type cnss_get_dev_bus_type(struct device *dev);
enum cnss_dev_bus_type cnss_get_bus_type(unsigned long device_id);
diff --git a/drivers/net/wireless/cnss2/main.c b/drivers/net/wireless/cnss2/main.c
index acf65e4904d6..ac9d8e7d08ad 100644
--- a/drivers/net/wireless/cnss2/main.c
+++ b/drivers/net/wireless/cnss2/main.c
@@ -37,6 +37,7 @@
#define FW_READY_TIMEOUT 20000
#define FW_ASSERT_TIMEOUT 5000
#define CNSS_EVENT_PENDING 2989
+#define CE_MSI_NAME "CE"
static struct cnss_plat_data *plat_env;
@@ -249,7 +250,7 @@ int cnss_wlan_enable(struct device *dev,
{
struct cnss_plat_data *plat_priv = cnss_bus_dev_to_plat_priv(dev);
struct wlfw_wlan_cfg_req_msg_v01 req;
- u32 i;
+ u32 i, ce_id, num_vectors, user_base_data, base_vector;
int ret = 0;
if (plat_priv->device_id == QCA6174_DEVICE_ID)
@@ -299,6 +300,19 @@ int cnss_wlan_enable(struct device *dev,
req.svc_cfg[i].pipe_num = config->ce_svc_cfg[i].pipe_num;
}
+ if (config->num_shadow_reg_cfg) {
+ req.shadow_reg_valid = 1;
+
+ if (config->num_shadow_reg_cfg >
+ QMI_WLFW_MAX_NUM_SHADOW_REG_V01)
+ req.shadow_reg_len = QMI_WLFW_MAX_NUM_SHADOW_REG_V01;
+ else
+ req.shadow_reg_len = config->num_shadow_reg_cfg;
+ memcpy(req.shadow_reg, config->shadow_reg_cfg,
+ sizeof(struct wlfw_shadow_reg_cfg_s_v01)
+ * req.shadow_reg_len);
+ }
+
req.shadow_reg_v2_valid = 1;
if (config->num_shadow_reg_v2_cfg >
QMI_WLFW_MAX_NUM_SHADOW_REG_V2_V01)
@@ -310,6 +324,30 @@ int cnss_wlan_enable(struct device *dev,
sizeof(struct wlfw_shadow_reg_v2_cfg_s_v01)
* req.shadow_reg_v2_len);
+ if (config->rri_over_ddr_cfg_valid) {
+ req.rri_over_ddr_cfg_valid = 1;
+ req.rri_over_ddr_cfg.base_addr_low =
+ config->rri_over_ddr_cfg.base_addr_low;
+ req.rri_over_ddr_cfg.base_addr_high =
+ config->rri_over_ddr_cfg.base_addr_high;
+ }
+
+ if (plat_priv->device_id == QCN7605_DEVICE_ID) {
+ ret = cnss_get_user_msi_assignment(dev, CE_MSI_NAME,
+ &num_vectors,
+ &user_base_data,
+ &base_vector);
+ if (!ret) {
+ req.msi_cfg_valid = 1;
+ req.msi_cfg_len = QMI_WLFW_MAX_NUM_CE_V01;
+ for (ce_id = 0; ce_id < QMI_WLFW_MAX_NUM_CE_V01;
+ ce_id++) {
+ req.msi_cfg[ce_id].ce_id = ce_id;
+ req.msi_cfg[ce_id].msi_vector =
+ (ce_id % num_vectors) + base_vector;
+ }
+ }
+ }
ret = cnss_wlfw_wlan_cfg_send_sync(plat_priv, &req);
if (ret)
goto out;
@@ -461,6 +499,8 @@ static int cnss_fw_mem_ready_hdlr(struct cnss_plat_data *plat_priv)
if (ret)
goto out;
+ if (plat_priv->device_id == QCN7605_DEVICE_ID)
+ goto skip_m3_dnld;
ret = cnss_bus_load_m3(plat_priv);
if (ret)
goto out;
@@ -468,7 +508,7 @@ static int cnss_fw_mem_ready_hdlr(struct cnss_plat_data *plat_priv)
ret = cnss_wlfw_m3_dnld_send_sync(plat_priv);
if (ret)
goto out;
-
+skip_m3_dnld:
return 0;
out:
return ret;
@@ -1103,7 +1143,10 @@ static int cnss_cold_boot_cal_done_hdlr(struct cnss_plat_data *plat_priv)
{
plat_priv->cal_done = true;
cnss_wlfw_wlan_mode_send_sync(plat_priv, QMI_WLFW_OFF_V01);
+ if (plat_priv->device_id == QCN7605_DEVICE_ID)
+ goto skip_shutdown;
cnss_bus_dev_shutdown(plat_priv);
+skip_shutdown:
clear_bit(CNSS_COLD_BOOT_CAL, &plat_priv->driver_state);
return 0;
@@ -1234,6 +1277,9 @@ int cnss_register_subsys(struct cnss_plat_data *plat_priv)
case QCA6290_DEVICE_ID:
subsys_info->subsys_desc.name = "QCA6290";
break;
+ case QCN7605_DEVICE_ID:
+ subsys_info->subsys_desc.name = "QCN7605";
+ break;
default:
cnss_pr_err("Unknown device ID: 0x%lx\n", plat_priv->device_id);
ret = -ENODEV;
@@ -1449,6 +1495,7 @@ int cnss_register_ramdump(struct cnss_plat_data *plat_priv)
break;
case QCA6290_EMULATION_DEVICE_ID:
case QCA6290_DEVICE_ID:
+ case QCN7605_DEVICE_ID:
ret = cnss_register_ramdump_v2(plat_priv);
break;
default:
@@ -1537,6 +1584,7 @@ static ssize_t cnss_fs_ready_store(struct device *dev,
switch (plat_priv->device_id) {
case QCA6290_EMULATION_DEVICE_ID:
case QCA6290_DEVICE_ID:
+ case QCN7605_DEVICE_ID:
break;
default:
cnss_pr_err("Not supported for device ID 0x%lx\n",
@@ -1599,6 +1647,7 @@ static void cnss_event_work_deinit(struct cnss_plat_data *plat_priv)
static const struct platform_device_id cnss_platform_id_table[] = {
{ .name = "qca6174", .driver_data = QCA6174_DEVICE_ID, },
{ .name = "qca6290", .driver_data = QCA6290_DEVICE_ID, },
+ { .name = "qcn7605", .driver_data = QCN7605_DEVICE_ID, },
};
static const struct of_device_id cnss_of_match_table[] = {
diff --git a/drivers/net/wireless/cnss2/pci.c b/drivers/net/wireless/cnss2/pci.c
index 8f9bc213cac3..427b42c871f3 100644
--- a/drivers/net/wireless/cnss2/pci.c
+++ b/drivers/net/wireless/cnss2/pci.c
@@ -619,6 +619,7 @@ int cnss_pci_dev_powerup(struct cnss_pci_data *pci_priv)
break;
case QCA6290_EMULATION_DEVICE_ID:
case QCA6290_DEVICE_ID:
+ case QCN7605_DEVICE_ID:
ret = cnss_qca6290_powerup(pci_priv);
break;
default:
@@ -645,6 +646,7 @@ int cnss_pci_dev_shutdown(struct cnss_pci_data *pci_priv)
break;
case QCA6290_EMULATION_DEVICE_ID:
case QCA6290_DEVICE_ID:
+ case QCN7605_DEVICE_ID:
ret = cnss_qca6290_shutdown(pci_priv);
break;
default:
@@ -1295,6 +1297,94 @@ int cnss_pm_request_resume(struct cnss_pci_data *pci_priv)
return pm_request_resume(&pci_dev->dev);
}
+#ifdef CONFIG_CNSS_QCA6390
+int cnss_pci_force_wake_request(struct device *dev)
+{
+ struct pci_dev *pci_dev = to_pci_dev(dev);
+ struct cnss_pci_data *pci_priv = cnss_get_pci_priv(pci_dev);
+ struct mhi_controller *mhi_ctrl;
+
+ if (!pci_priv)
+ return -ENODEV;
+
+ if (pci_priv->device_id != QCA6390_DEVICE_ID)
+ return 0;
+
+ mhi_ctrl = pci_priv->mhi_ctrl;
+ if (!mhi_ctrl)
+ return -EINVAL;
+
+ read_lock_bh(&mhi_ctrl->pm_lock);
+ mhi_ctrl->wake_get(mhi_ctrl, true);
+ read_unlock_bh(&mhi_ctrl->pm_lock);
+
+ return 0;
+}
+EXPORT_SYMBOL(cnss_pci_force_wake_request);
+
+int cnss_pci_is_device_awake(struct device *dev)
+{
+ struct pci_dev *pci_dev = to_pci_dev(dev);
+ struct cnss_pci_data *pci_priv = cnss_get_pci_priv(pci_dev);
+ struct mhi_controller *mhi_ctrl;
+
+ if (!pci_priv)
+ return -ENODEV;
+
+ if (pci_priv->device_id != QCA6390_DEVICE_ID)
+ return true;
+
+ mhi_ctrl = pci_priv->mhi_ctrl;
+ if (!mhi_ctrl)
+ return -EINVAL;
+
+ return mhi_ctrl->dev_state == MHI_STATE_M0 ? true : false;
+}
+EXPORT_SYMBOL(cnss_pci_is_device_awake);
+
+int cnss_pci_force_wake_release(struct device *dev)
+{
+ struct pci_dev *pci_dev = to_pci_dev(dev);
+ struct cnss_pci_data *pci_priv = cnss_get_pci_priv(pci_dev);
+ struct mhi_controller *mhi_ctrl;
+
+ if (!pci_priv)
+ return -ENODEV;
+
+ if (pci_priv->device_id != QCA6390_DEVICE_ID)
+ return 0;
+
+ mhi_ctrl = pci_priv->mhi_ctrl;
+ if (!mhi_ctrl)
+ return -EINVAL;
+
+ read_lock_bh(&mhi_ctrl->pm_lock);
+ mhi_ctrl->wake_put(mhi_ctrl, false);
+ read_unlock_bh(&mhi_ctrl->pm_lock);
+
+ return 0;
+}
+EXPORT_SYMBOL(cnss_pci_force_wake_release);
+#else
+int cnss_pci_force_wake_request(struct device *dev)
+{
+ return 0;
+}
+EXPORT_SYMBOL(cnss_pci_force_wake_request);
+
+int cnss_pci_is_device_awake(struct device *dev)
+{
+ return true;
+}
+EXPORT_SYMBOL(cnss_pci_is_device_awake);
+
+int cnss_pci_force_wake_release(struct device *dev)
+{
+ return 0;
+}
+EXPORT_SYMBOL(cnss_pci_force_wake_release);
+#endif
+
int cnss_pci_alloc_fw_mem(struct cnss_pci_data *pci_priv)
{
struct cnss_plat_data *plat_priv = pci_priv->plat_priv;
@@ -2162,6 +2252,7 @@ static int cnss_pci_probe(struct pci_dev *pci_dev,
switch (pci_dev->device) {
case QCA6290_EMULATION_DEVICE_ID:
case QCA6290_DEVICE_ID:
+ case QCN7605_DEVICE_ID:
if (!mhi_is_device_ready(&plat_priv->plat_dev->dev,
MHI_NODE_NAME)) {
cnss_pr_err("MHI driver is not ready, defer PCI probe!\n");
@@ -2249,6 +2340,7 @@ static int cnss_pci_probe(struct pci_dev *pci_dev,
break;
case QCA6290_EMULATION_DEVICE_ID:
case QCA6290_DEVICE_ID:
+ case QCN7605_DEVICE_ID:
ret = cnss_pci_enable_msi(pci_priv);
if (ret)
goto disable_bus;
@@ -2324,6 +2416,7 @@ static const struct pci_device_id cnss_pci_id_table[] = {
{ QCA6290_EMULATION_VENDOR_ID, QCA6290_EMULATION_DEVICE_ID,
PCI_ANY_ID, PCI_ANY_ID },
{ QCA6290_VENDOR_ID, QCA6290_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID },
+ {QCN7605_VENDOR_ID, QCN7605_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID},
{ 0 }
};
MODULE_DEVICE_TABLE(pci, cnss_pci_id_table);
diff --git a/drivers/net/wireless/cnss2/wlan_firmware_service_v01.c b/drivers/net/wireless/cnss2/wlan_firmware_service_v01.c
index bbf707b869bd..8f2637c3eaf9 100644
--- a/drivers/net/wireless/cnss2/wlan_firmware_service_v01.c
+++ b/drivers/net/wireless/cnss2/wlan_firmware_service_v01.c
@@ -144,6 +144,60 @@ static struct elem_info wlfw_shadow_reg_v2_cfg_s_v01_ei[] = {
},
};
+static struct elem_info wlfw_rri_over_ddr_cfg_s_v01_ei[] = {
+ {
+ .data_type = QMI_UNSIGNED_4_BYTE,
+ .elem_len = 1,
+ .elem_size = sizeof(u32),
+ .is_array = NO_ARRAY,
+ .tlv_type = 0,
+ .offset = offsetof(struct
+ wlfw_rri_over_ddr_cfg_s_v01,
+ base_addr_low),
+ },
+ {
+ .data_type = QMI_UNSIGNED_4_BYTE,
+ .elem_len = 1,
+ .elem_size = sizeof(u32),
+ .is_array = NO_ARRAY,
+ .tlv_type = 0,
+ .offset = offsetof(struct
+ wlfw_rri_over_ddr_cfg_s_v01,
+ base_addr_high),
+ },
+ {
+ .data_type = QMI_EOTI,
+ .is_array = NO_ARRAY,
+ .tlv_type = QMI_COMMON_TLV_TYPE,
+ },
+};
+
+static struct elem_info wlfw_msi_cfg_s_v01_ei[] = {
+ {
+ .data_type = QMI_UNSIGNED_2_BYTE,
+ .elem_len = 1,
+ .elem_size = sizeof(u16),
+ .is_array = NO_ARRAY,
+ .tlv_type = 0,
+ .offset = offsetof(struct wlfw_msi_cfg_s_v01,
+ ce_id),
+ },
+ {
+ .data_type = QMI_UNSIGNED_2_BYTE,
+ .elem_len = 1,
+ .elem_size = sizeof(u16),
+ .is_array = NO_ARRAY,
+ .tlv_type = 0,
+ .offset = offsetof(struct wlfw_msi_cfg_s_v01,
+ msi_vector),
+ },
+ {
+ .data_type = QMI_EOTI,
+ .is_array = NO_ARRAY,
+ .tlv_type = QMI_COMMON_TLV_TYPE,
+ },
+};
+
static struct elem_info wlfw_memory_region_info_s_v01_ei[] = {
{
.data_type = QMI_UNSIGNED_8_BYTE,
@@ -922,6 +976,53 @@ struct elem_info wlfw_wlan_cfg_req_msg_v01_ei[] = {
.ei_array = wlfw_shadow_reg_v2_cfg_s_v01_ei,
},
{
+ .data_type = QMI_OPT_FLAG,
+ .elem_len = 1,
+ .elem_size = sizeof(u8),
+ .is_array = NO_ARRAY,
+ .tlv_type = 0x15,
+ .offset = offsetof(struct wlfw_wlan_cfg_req_msg_v01,
+ rri_over_ddr_cfg_valid),
+ },
+ {
+ .data_type = QMI_STRUCT,
+ .elem_len = 1,
+ .elem_size = sizeof(struct wlfw_rri_over_ddr_cfg_s_v01),
+ .is_array = NO_ARRAY,
+ .tlv_type = 0x15,
+ .offset = offsetof(struct wlfw_wlan_cfg_req_msg_v01,
+ rri_over_ddr_cfg),
+ .ei_array = wlfw_rri_over_ddr_cfg_s_v01_ei,
+ },
+ {
+ .data_type = QMI_OPT_FLAG,
+ .elem_len = 1,
+ .elem_size = sizeof(u8),
+ .is_array = NO_ARRAY,
+ .tlv_type = 0x16,
+ .offset = offsetof(struct wlfw_wlan_cfg_req_msg_v01,
+ msi_cfg_valid),
+ },
+ {
+ .data_type = QMI_DATA_LEN,
+ .elem_len = 1,
+ .elem_size = sizeof(u8),
+ .is_array = NO_ARRAY,
+ .tlv_type = 0x16,
+ .offset = offsetof(struct wlfw_wlan_cfg_req_msg_v01,
+ msi_cfg_len),
+ },
+ {
+ .data_type = QMI_STRUCT,
+ .elem_len = QMI_WLFW_MAX_NUM_CE_V01,
+ .elem_size = sizeof(struct wlfw_msi_cfg_s_v01),
+ .is_array = VAR_LEN_ARRAY,
+ .tlv_type = 0x16,
+ .offset = offsetof(struct wlfw_wlan_cfg_req_msg_v01,
+ msi_cfg),
+ .ei_array = wlfw_msi_cfg_s_v01_ei,
+ },
+ {
.data_type = QMI_EOTI,
.is_array = NO_ARRAY,
.tlv_type = QMI_COMMON_TLV_TYPE,
diff --git a/drivers/net/wireless/cnss2/wlan_firmware_service_v01.h b/drivers/net/wireless/cnss2/wlan_firmware_service_v01.h
index 00a873d11d14..964c1e56dbdd 100644
--- a/drivers/net/wireless/cnss2/wlan_firmware_service_v01.h
+++ b/drivers/net/wireless/cnss2/wlan_firmware_service_v01.h
@@ -170,6 +170,16 @@ struct wlfw_shadow_reg_v2_cfg_s_v01 {
u32 addr;
};
+struct wlfw_rri_over_ddr_cfg_s_v01 {
+ u32 base_addr_low;
+ u32 base_addr_high;
+};
+
+struct wlfw_msi_cfg_s_v01 {
+ u16 ce_id;
+ u16 msi_vector;
+};
+
struct wlfw_memory_region_info_s_v01 {
u64 region_addr;
u32 size;
@@ -312,6 +322,11 @@ struct wlfw_wlan_cfg_req_msg_v01 {
u32 shadow_reg_v2_len;
struct wlfw_shadow_reg_v2_cfg_s_v01
shadow_reg_v2[QMI_WLFW_MAX_NUM_SHADOW_REG_V2_V01];
+ u8 rri_over_ddr_cfg_valid;
+ struct wlfw_rri_over_ddr_cfg_s_v01 rri_over_ddr_cfg;
+ u8 msi_cfg_valid;
+ u32 msi_cfg_len;
+ struct wlfw_msi_cfg_s_v01 msi_cfg[QMI_WLFW_MAX_NUM_CE_V01];
};
#define WLFW_WLAN_CFG_REQ_MSG_V01_MAX_MSG_LEN 803
diff --git a/drivers/net/wireless/wcnss/wcnss_wlan.c b/drivers/net/wireless/wcnss/wcnss_wlan.c
index 13ae5c3c2471..b97e550cba5d 100644
--- a/drivers/net/wireless/wcnss/wcnss_wlan.c
+++ b/drivers/net/wireless/wcnss/wcnss_wlan.c
@@ -2368,6 +2368,12 @@ static void wcnss_nvbin_dnld(void)
goto out;
}
+ if (nv->size <= 4) {
+ pr_err("wcnss: %s: request_firmware failed for %s (file size = %zu)\n",
+ __func__, NVBIN_FILE, nv->size);
+ goto out;
+ }
+
/* First 4 bytes in nv blob is validity bitmap.
* We cannot validate nv, so skip those 4 bytes.
*/
diff --git a/drivers/net/xen-netfront.c b/drivers/net/xen-netfront.c
index 68d0a5c9d437..3270b4333668 100644
--- a/drivers/net/xen-netfront.c
+++ b/drivers/net/xen-netfront.c
@@ -86,8 +86,7 @@ struct netfront_cb {
/* IRQ name is queue name with "-tx" or "-rx" appended */
#define IRQ_NAME_SIZE (QUEUE_NAME_SIZE + 3)
-static DECLARE_WAIT_QUEUE_HEAD(module_load_q);
-static DECLARE_WAIT_QUEUE_HEAD(module_unload_q);
+static DECLARE_WAIT_QUEUE_HEAD(module_wq);
struct netfront_stats {
u64 packets;
@@ -1336,11 +1335,11 @@ static struct net_device *xennet_create_dev(struct xenbus_device *dev)
netif_carrier_off(netdev);
xenbus_switch_state(dev, XenbusStateInitialising);
- wait_event(module_load_q,
- xenbus_read_driver_state(dev->otherend) !=
- XenbusStateClosed &&
- xenbus_read_driver_state(dev->otherend) !=
- XenbusStateUnknown);
+ wait_event(module_wq,
+ xenbus_read_driver_state(dev->otherend) !=
+ XenbusStateClosed &&
+ xenbus_read_driver_state(dev->otherend) !=
+ XenbusStateUnknown);
return netdev;
exit:
@@ -1608,6 +1607,7 @@ static int xennet_init_queue(struct netfront_queue *queue)
{
unsigned short i;
int err = 0;
+ char *devid;
spin_lock_init(&queue->tx_lock);
spin_lock_init(&queue->rx_lock);
@@ -1615,8 +1615,9 @@ static int xennet_init_queue(struct netfront_queue *queue)
setup_timer(&queue->rx_refill_timer, rx_refill_timeout,
(unsigned long)queue);
- snprintf(queue->name, sizeof(queue->name), "%s-q%u",
- queue->info->netdev->name, queue->id);
+ devid = strrchr(queue->info->xbdev->nodename, '/') + 1;
+ snprintf(queue->name, sizeof(queue->name), "vif%s-q%u",
+ devid, queue->id);
/* Initialise tx_skbs as a free chain containing every entry. */
queue->tx_skb_freelist = 0;
@@ -2023,15 +2024,14 @@ static void netback_changed(struct xenbus_device *dev,
dev_dbg(&dev->dev, "%s\n", xenbus_strstate(backend_state));
+ wake_up_all(&module_wq);
+
switch (backend_state) {
case XenbusStateInitialising:
case XenbusStateInitialised:
case XenbusStateReconfiguring:
case XenbusStateReconfigured:
- break;
-
case XenbusStateUnknown:
- wake_up_all(&module_unload_q);
break;
case XenbusStateInitWait:
@@ -2047,12 +2047,10 @@ static void netback_changed(struct xenbus_device *dev,
break;
case XenbusStateClosed:
- wake_up_all(&module_unload_q);
if (dev->state == XenbusStateClosed)
break;
/* Missed the backend's CLOSING state -- fallthrough */
case XenbusStateClosing:
- wake_up_all(&module_unload_q);
xenbus_frontend_closed(dev);
break;
}
@@ -2160,14 +2158,14 @@ static int xennet_remove(struct xenbus_device *dev)
if (xenbus_read_driver_state(dev->otherend) != XenbusStateClosed) {
xenbus_switch_state(dev, XenbusStateClosing);
- wait_event(module_unload_q,
+ wait_event(module_wq,
xenbus_read_driver_state(dev->otherend) ==
XenbusStateClosing ||
xenbus_read_driver_state(dev->otherend) ==
XenbusStateUnknown);
xenbus_switch_state(dev, XenbusStateClosed);
- wait_event(module_unload_q,
+ wait_event(module_wq,
xenbus_read_driver_state(dev->otherend) ==
XenbusStateClosed ||
xenbus_read_driver_state(dev->otherend) ==
diff --git a/drivers/parport/parport_sunbpp.c b/drivers/parport/parport_sunbpp.c
index 01cf1c1a841a..8de329546b82 100644
--- a/drivers/parport/parport_sunbpp.c
+++ b/drivers/parport/parport_sunbpp.c
@@ -286,12 +286,16 @@ static int bpp_probe(struct platform_device *op)
ops = kmemdup(&parport_sunbpp_ops, sizeof(struct parport_operations),
GFP_KERNEL);
- if (!ops)
+ if (!ops) {
+ err = -ENOMEM;
goto out_unmap;
+ }
dprintk(("register_port\n"));
- if (!(p = parport_register_port((unsigned long)base, irq, dma, ops)))
+ if (!(p = parport_register_port((unsigned long)base, irq, dma, ops))) {
+ err = -ENOMEM;
goto out_free_ops;
+ }
p->size = size;
p->dev = &op->dev;
diff --git a/drivers/pci/host/pci-mvebu.c b/drivers/pci/host/pci-mvebu.c
index 379d08f76146..d0a4652bb9ac 100644
--- a/drivers/pci/host/pci-mvebu.c
+++ b/drivers/pci/host/pci-mvebu.c
@@ -1235,7 +1235,7 @@ static int mvebu_pcie_probe(struct platform_device *pdev)
pcie->realio.start = PCIBIOS_MIN_IO;
pcie->realio.end = min_t(resource_size_t,
IO_SPACE_LIMIT,
- resource_size(&pcie->io));
+ resource_size(&pcie->io) - 1);
} else
pcie->realio = pcie->io;
diff --git a/drivers/pinctrl/qcom/pinctrl-sdm660.c b/drivers/pinctrl/qcom/pinctrl-sdm660.c
index 4dbb4cae2fae..9796bdc7534e 100644
--- a/drivers/pinctrl/qcom/pinctrl-sdm660.c
+++ b/drivers/pinctrl/qcom/pinctrl-sdm660.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2016, The Linux Foundation. All rights reserved.
+ * Copyright (c) 2016, 2018, 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
@@ -92,6 +92,31 @@
.intr_detection_bit = -1, \
.intr_detection_width = -1, \
}
+
+#define UFS_RESET(pg_name, offset) \
+ { \
+ .name = #pg_name, \
+ .pins = pg_name##_pins, \
+ .npins = (unsigned int)ARRAY_SIZE(pg_name##_pins), \
+ .ctl_reg = offset, \
+ .io_reg = offset + 0x4, \
+ .intr_cfg_reg = 0, \
+ .intr_status_reg = 0, \
+ .intr_target_reg = 0, \
+ .mux_bit = -1, \
+ .pull_bit = 3, \
+ .drv_bit = 0, \
+ .oe_bit = -1, \
+ .in_bit = -1, \
+ .out_bit = 0, \
+ .intr_enable_bit = -1, \
+ .intr_status_bit = -1, \
+ .intr_target_bit = -1, \
+ .intr_raw_status_bit = -1, \
+ .intr_polarity_bit = -1, \
+ .intr_detection_bit = -1, \
+ .intr_detection_width = -1, \
+ }
static const struct pinctrl_pin_desc sdm660_pins[] = {
PINCTRL_PIN(0, "GPIO_0"),
PINCTRL_PIN(1, "GPIO_1"),
@@ -214,6 +239,7 @@ static const struct pinctrl_pin_desc sdm660_pins[] = {
PINCTRL_PIN(118, "SDC2_CMD"),
PINCTRL_PIN(119, "SDC2_DATA"),
PINCTRL_PIN(120, "SDC1_RCLK"),
+ PINCTRL_PIN(121, "UFS_RESET"),
};
#define DECLARE_MSM_GPIO_PINS(pin) \
@@ -340,6 +366,7 @@ static const unsigned int sdc2_clk_pins[] = { 117 };
static const unsigned int sdc2_cmd_pins[] = { 118 };
static const unsigned int sdc2_data_pins[] = { 119 };
static const unsigned int sdc1_rclk_pins[] = { 120 };
+static const unsigned int ufs_reset_pins[] = { 121 };
enum sdm660_functions {
msm_mux_blsp_spi1,
@@ -1673,6 +1700,7 @@ static const struct msm_pingroup sdm660_groups[] = {
SDC_QDSD_PINGROUP(sdc2_cmd, 0x99b000, 11, 3),
SDC_QDSD_PINGROUP(sdc2_data, 0x99b000, 9, 0),
SDC_QDSD_PINGROUP(sdc1_rclk, 0x99a000, 15, 0),
+ UFS_RESET(ufs_reset, 0x9a3000),
};
static const struct msm_pinctrl_soc_data sdm660_pinctrl = {
diff --git a/drivers/pinctrl/qcom/pinctrl-spmi-gpio.c b/drivers/pinctrl/qcom/pinctrl-spmi-gpio.c
index 9753fbb596cf..069d167ab410 100644
--- a/drivers/pinctrl/qcom/pinctrl-spmi-gpio.c
+++ b/drivers/pinctrl/qcom/pinctrl-spmi-gpio.c
@@ -411,31 +411,47 @@ static int pmic_gpio_config_get(struct pinctrl_dev *pctldev,
switch (param) {
case PIN_CONFIG_DRIVE_PUSH_PULL:
- arg = pad->buffer_type == PMIC_GPIO_OUT_BUF_CMOS;
+ if (pad->buffer_type != PMIC_GPIO_OUT_BUF_CMOS)
+ return -EINVAL;
+ arg = 1;
break;
case PIN_CONFIG_DRIVE_OPEN_DRAIN:
- arg = pad->buffer_type == PMIC_GPIO_OUT_BUF_OPEN_DRAIN_NMOS;
+ if (pad->buffer_type != PMIC_GPIO_OUT_BUF_OPEN_DRAIN_NMOS)
+ return -EINVAL;
+ arg = 1;
break;
case PIN_CONFIG_DRIVE_OPEN_SOURCE:
- arg = pad->buffer_type == PMIC_GPIO_OUT_BUF_OPEN_DRAIN_PMOS;
+ if (pad->buffer_type != PMIC_GPIO_OUT_BUF_OPEN_DRAIN_PMOS)
+ return -EINVAL;
+ arg = 1;
break;
case PIN_CONFIG_BIAS_PULL_DOWN:
- arg = pad->pullup == PMIC_GPIO_PULL_DOWN;
+ if (pad->pullup != PMIC_GPIO_PULL_DOWN)
+ return -EINVAL;
+ arg = 1;
break;
case PIN_CONFIG_BIAS_DISABLE:
- arg = pad->pullup = PMIC_GPIO_PULL_DISABLE;
+ if (pad->pullup != PMIC_GPIO_PULL_DISABLE)
+ return -EINVAL;
+ arg = 1;
break;
case PIN_CONFIG_BIAS_PULL_UP:
- arg = pad->pullup == PMIC_GPIO_PULL_UP_30;
+ if (pad->pullup != PMIC_GPIO_PULL_UP_30)
+ return -EINVAL;
+ arg = 1;
break;
case PIN_CONFIG_BIAS_HIGH_IMPEDANCE:
- arg = !pad->is_enabled;
+ if (pad->is_enabled)
+ return -EINVAL;
+ arg = 1;
break;
case PIN_CONFIG_POWER_SOURCE:
arg = pad->power_source;
break;
case PIN_CONFIG_INPUT_ENABLE:
- arg = pad->input_enabled;
+ if (!pad->input_enabled)
+ return -EINVAL;
+ arg = 1;
break;
case PIN_CONFIG_OUTPUT:
arg = pad->out_value;
diff --git a/drivers/platform/msm/ipa/ipa_v3/ipa_rt.c b/drivers/platform/msm/ipa/ipa_v3/ipa_rt.c
index a260dbe010f3..8f6024c51e1d 100644
--- a/drivers/platform/msm/ipa/ipa_v3/ipa_rt.c
+++ b/drivers/platform/msm/ipa/ipa_v3/ipa_rt.c
@@ -1047,13 +1047,12 @@ static int __ipa_add_rt_rule(enum ipa_ip_type ip, const char *name,
goto error;
}
/*
- * do not allow any rules to be added at end of the "default" routing
- * tables
+ * do not allow any rule to be added at "default" routing
+ * table
*/
if (!strcmp(tbl->name, IPA_DFLT_RT_TBL_NAME) &&
- (tbl->rule_cnt > 0) && (at_rear != 0)) {
- IPAERR_RL("cannot add rule at end of tbl rule_cnt=%d at_rear=%d"
- , tbl->rule_cnt, at_rear);
+ (tbl->rule_cnt > 0)) {
+ IPAERR_RL("cannot add rules to default rt table\n");
goto error;
}
@@ -1275,13 +1274,12 @@ int ipa3_add_rt_rule_after(struct ipa_ioc_add_rt_rule_after *rules)
}
/*
- * do not allow any rules to be added at end of the "default" routing
- * tables
+ * do not allow any rule to be added at "default" routing
+ * table
*/
if (!strcmp(tbl->name, IPA_DFLT_RT_TBL_NAME) &&
- (&entry->link == tbl->head_rt_rule_list.prev)) {
- IPAERR_RL("cannot add rule at end of tbl rule_cnt=%d\n",
- tbl->rule_cnt);
+ (tbl->rule_cnt > 0)) {
+ IPAERR_RL("cannot add rules to default rt table\n");
ret = -EINVAL;
goto bail;
}
@@ -1740,6 +1738,10 @@ static int __ipa_mdfy_rt_rule(struct ipa_rt_rule_mdfy *rtrule)
goto error;
}
+ if (!strcmp(entry->tbl->name, IPA_DFLT_RT_TBL_NAME)) {
+ IPAERR_RL("Default tbl rule cannot be modified\n");
+ return -EINVAL;
+ }
/* Adding check to confirm still
* header entry present in header table or not
*/
diff --git a/drivers/platform/x86/asus-nb-wmi.c b/drivers/platform/x86/asus-nb-wmi.c
index 0e0403e024c5..852d2de7f69f 100644
--- a/drivers/platform/x86/asus-nb-wmi.c
+++ b/drivers/platform/x86/asus-nb-wmi.c
@@ -392,6 +392,7 @@ static const struct key_entry asus_nb_wmi_keymap[] = {
{ KE_KEY, 0xC4, { KEY_KBDILLUMUP } },
{ KE_KEY, 0xC5, { KEY_KBDILLUMDOWN } },
{ KE_IGNORE, 0xC6, }, /* Ambient Light Sensor notification */
+ { KE_KEY, 0xFA, { KEY_PROG2 } }, /* Lid flip action */
{ KE_END, 0},
};
diff --git a/drivers/platform/x86/toshiba_acpi.c b/drivers/platform/x86/toshiba_acpi.c
index f774cb576ffa..1ff95b5a429d 100644
--- a/drivers/platform/x86/toshiba_acpi.c
+++ b/drivers/platform/x86/toshiba_acpi.c
@@ -34,6 +34,7 @@
#define TOSHIBA_ACPI_VERSION "0.23"
#define PROC_INTERFACE_VERSION 1
+#include <linux/compiler.h>
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/init.h>
@@ -1472,7 +1473,7 @@ static const struct file_operations keys_proc_fops = {
.write = keys_proc_write,
};
-static int version_proc_show(struct seq_file *m, void *v)
+static int __maybe_unused version_proc_show(struct seq_file *m, void *v)
{
seq_printf(m, "driver: %s\n", TOSHIBA_ACPI_VERSION);
seq_printf(m, "proc_interface: %d\n", PROC_INTERFACE_VERSION);
diff --git a/drivers/rtc/rtc-bq4802.c b/drivers/rtc/rtc-bq4802.c
index bd170cb3361c..5747a54cbd42 100644
--- a/drivers/rtc/rtc-bq4802.c
+++ b/drivers/rtc/rtc-bq4802.c
@@ -164,6 +164,10 @@ static int bq4802_probe(struct platform_device *pdev)
} else if (p->r->flags & IORESOURCE_MEM) {
p->regs = devm_ioremap(&pdev->dev, p->r->start,
resource_size(p->r));
+ if (!p->regs){
+ err = -ENOMEM;
+ goto out;
+ }
p->read = bq4802_read_mem;
p->write = bq4802_write_mem;
} else {
diff --git a/drivers/s390/block/dasd_eckd.c b/drivers/s390/block/dasd_eckd.c
index 21d174e9ebdb..dac2f6883e28 100644
--- a/drivers/s390/block/dasd_eckd.c
+++ b/drivers/s390/block/dasd_eckd.c
@@ -2101,8 +2101,11 @@ static int dasd_eckd_basic_to_ready(struct dasd_device *device)
static int dasd_eckd_online_to_ready(struct dasd_device *device)
{
- cancel_work_sync(&device->reload_device);
- cancel_work_sync(&device->kick_validate);
+ if (cancel_work_sync(&device->reload_device))
+ dasd_put_device(device);
+ if (cancel_work_sync(&device->kick_validate))
+ dasd_put_device(device);
+
return 0;
};
diff --git a/drivers/s390/net/qeth_core_main.c b/drivers/s390/net/qeth_core_main.c
index 95c631125a20..09ac56317f1b 100644
--- a/drivers/s390/net/qeth_core_main.c
+++ b/drivers/s390/net/qeth_core_main.c
@@ -3505,13 +3505,14 @@ static void qeth_flush_buffers(struct qeth_qdio_out_q *queue, int index,
qdio_flags = QDIO_FLAG_SYNC_OUTPUT;
if (atomic_read(&queue->set_pci_flags_count))
qdio_flags |= QDIO_FLAG_PCI_OUT;
+ atomic_add(count, &queue->used_buffers);
+
rc = do_QDIO(CARD_DDEV(queue->card), qdio_flags,
queue->queue_no, index, count);
if (queue->card->options.performance_stats)
queue->card->perf_stats.outbound_do_qdio_time +=
qeth_get_micros() -
queue->card->perf_stats.outbound_do_qdio_start_time;
- atomic_add(count, &queue->used_buffers);
if (rc) {
queue->card->stats.tx_errors += count;
/* ignore temporary SIGA errors without busy condition */
diff --git a/drivers/s390/net/qeth_core_sys.c b/drivers/s390/net/qeth_core_sys.c
index fa844b0ff847..7bcf0dae3a65 100644
--- a/drivers/s390/net/qeth_core_sys.c
+++ b/drivers/s390/net/qeth_core_sys.c
@@ -419,6 +419,7 @@ static ssize_t qeth_dev_layer2_store(struct device *dev,
if (card->discipline) {
card->discipline->remove(card->gdev);
qeth_core_free_discipline(card);
+ card->options.layer2 = -1;
}
rc = qeth_core_load_discipline(card, newdis);
diff --git a/drivers/scsi/3w-9xxx.c b/drivers/scsi/3w-9xxx.c
index 5466246c69b4..b78a2f3745f2 100644
--- a/drivers/scsi/3w-9xxx.c
+++ b/drivers/scsi/3w-9xxx.c
@@ -2045,6 +2045,7 @@ static int twa_probe(struct pci_dev *pdev, const struct pci_device_id *dev_id)
if (twa_initialize_device_extension(tw_dev)) {
TW_PRINTK(tw_dev->host, TW_DRIVER, 0x25, "Failed to initialize device extension");
+ retval = -ENOMEM;
goto out_free_device_extension;
}
@@ -2067,6 +2068,7 @@ static int twa_probe(struct pci_dev *pdev, const struct pci_device_id *dev_id)
tw_dev->base_addr = ioremap(mem_addr, mem_len);
if (!tw_dev->base_addr) {
TW_PRINTK(tw_dev->host, TW_DRIVER, 0x35, "Failed to ioremap");
+ retval = -ENOMEM;
goto out_release_mem_region;
}
@@ -2074,8 +2076,10 @@ static int twa_probe(struct pci_dev *pdev, const struct pci_device_id *dev_id)
TW_DISABLE_INTERRUPTS(tw_dev);
/* Initialize the card */
- if (twa_reset_sequence(tw_dev, 0))
+ if (twa_reset_sequence(tw_dev, 0)) {
+ retval = -ENOMEM;
goto out_iounmap;
+ }
/* Set host specific parameters */
if ((pdev->device == PCI_DEVICE_ID_3WARE_9650SE) ||
diff --git a/drivers/scsi/3w-sas.c b/drivers/scsi/3w-sas.c
index f8374850f714..f0a5536a9ff5 100644
--- a/drivers/scsi/3w-sas.c
+++ b/drivers/scsi/3w-sas.c
@@ -1600,6 +1600,7 @@ static int twl_probe(struct pci_dev *pdev, const struct pci_device_id *dev_id)
if (twl_initialize_device_extension(tw_dev)) {
TW_PRINTK(tw_dev->host, TW_DRIVER, 0x1a, "Failed to initialize device extension");
+ retval = -ENOMEM;
goto out_free_device_extension;
}
@@ -1614,6 +1615,7 @@ static int twl_probe(struct pci_dev *pdev, const struct pci_device_id *dev_id)
tw_dev->base_addr = pci_iomap(pdev, 1, 0);
if (!tw_dev->base_addr) {
TW_PRINTK(tw_dev->host, TW_DRIVER, 0x1c, "Failed to ioremap");
+ retval = -ENOMEM;
goto out_release_mem_region;
}
@@ -1623,6 +1625,7 @@ static int twl_probe(struct pci_dev *pdev, const struct pci_device_id *dev_id)
/* Initialize the card */
if (twl_reset_sequence(tw_dev, 0)) {
TW_PRINTK(tw_dev->host, TW_DRIVER, 0x1d, "Controller reset failed during probe");
+ retval = -ENOMEM;
goto out_iounmap;
}
diff --git a/drivers/scsi/3w-xxxx.c b/drivers/scsi/3w-xxxx.c
index 14af38036287..308a4206b636 100644
--- a/drivers/scsi/3w-xxxx.c
+++ b/drivers/scsi/3w-xxxx.c
@@ -2278,6 +2278,7 @@ static int tw_probe(struct pci_dev *pdev, const struct pci_device_id *dev_id)
if (tw_initialize_device_extension(tw_dev)) {
printk(KERN_WARNING "3w-xxxx: Failed to initialize device extension.");
+ retval = -ENOMEM;
goto out_free_device_extension;
}
@@ -2292,6 +2293,7 @@ static int tw_probe(struct pci_dev *pdev, const struct pci_device_id *dev_id)
tw_dev->base_addr = pci_resource_start(pdev, 0);
if (!tw_dev->base_addr) {
printk(KERN_WARNING "3w-xxxx: Failed to get io address.");
+ retval = -ENOMEM;
goto out_release_mem_region;
}
diff --git a/drivers/scsi/aic94xx/aic94xx_init.c b/drivers/scsi/aic94xx/aic94xx_init.c
index 662b2321d1b0..913ebb6d0d29 100644
--- a/drivers/scsi/aic94xx/aic94xx_init.c
+++ b/drivers/scsi/aic94xx/aic94xx_init.c
@@ -1031,8 +1031,10 @@ static int __init aic94xx_init(void)
aic94xx_transport_template =
sas_domain_attach_transport(&aic94xx_transport_functions);
- if (!aic94xx_transport_template)
+ if (!aic94xx_transport_template) {
+ err = -ENOMEM;
goto out_destroy_caches;
+ }
err = pci_register_driver(&aic94xx_pci_driver);
if (err)
diff --git a/drivers/soc/qcom/hab/hab.c b/drivers/soc/qcom/hab/hab.c
index 65935f6eb48f..5b84a57423b9 100644
--- a/drivers/soc/qcom/hab/hab.c
+++ b/drivers/soc/qcom/hab/hab.c
@@ -117,7 +117,7 @@ void hab_ctx_free(struct kref *ref)
struct export_desc *exp, *exp_tmp;
/* garbage-collect exp/imp buffers */
- write_lock(&ctx->exp_lock);
+ write_lock_bh(&ctx->exp_lock);
list_for_each_entry_safe(exp, exp_tmp, &ctx->exp_whse, node) {
list_del(&exp->node);
pr_debug("potential leak exp %d vcid %X recovered\n",
@@ -125,7 +125,7 @@ void hab_ctx_free(struct kref *ref)
habmem_hyp_revoke(exp->payload, exp->payload_count);
habmem_remove_export(exp);
}
- write_unlock(&ctx->exp_lock);
+ write_unlock_bh(&ctx->exp_lock);
spin_lock_bh(&ctx->imp_lock);
list_for_each_entry_safe(exp, exp_tmp, &ctx->imp_whse, node) {
@@ -159,27 +159,27 @@ void hab_ctx_free(struct kref *ref)
ctx->kernel, ctx->closing, ctx->owner);
/* check vchans in this ctx */
- write_lock(&ctx->ctx_lock);
+ write_lock_bh(&ctx->ctx_lock);
list_for_each_entry(vchan, &ctx->vchannels, node) {
pr_warn("leak vchan id %X cnt %X remote %d in ctx\n",
vchan->id, get_refcnt(vchan->refcount),
vchan->otherend_id);
}
- write_unlock(&ctx->ctx_lock);
+ write_unlock_bh(&ctx->ctx_lock);
/* check pending open */
if (ctx->pending_cnt)
pr_warn("potential leak of pendin_open nodes %d\n",
ctx->pending_cnt);
- write_lock(&ctx->ctx_lock);
+ write_lock_bh(&ctx->ctx_lock);
list_for_each_entry(node, &ctx->pending_open, node) {
pr_warn("leak pending open vcid %X type %d subid %d openid %d\n",
node->request.xdata.vchan_id, node->request.type,
node->request.xdata.sub_id,
node->request.xdata.open_id);
}
- write_unlock(&ctx->ctx_lock);
+ write_unlock_bh(&ctx->ctx_lock);
/* check vchans belong to this ctx in all hab/mmid devices */
for (i = 0; i < hab_driver.ndevices; i++) {
@@ -218,7 +218,15 @@ struct virtual_channel *hab_get_vchan_fromvcid(int32_t vcid,
read_lock(&ctx->ctx_lock);
list_for_each_entry(vchan, &ctx->vchannels, node) {
if (vcid == vchan->id) {
- kref_get(&vchan->refcount);
+ if (vchan->otherend_closed || vchan->closed ||
+ !kref_get_unless_zero(&vchan->refcount)) {
+ pr_debug("failed to inc vcid %x remote %x session %d refcnt %d close_flg remote %d local %d\n",
+ vchan->id, vchan->otherend_id,
+ vchan->session_id,
+ get_refcnt(vchan->refcount),
+ vchan->otherend_closed, vchan->closed);
+ vchan = NULL;
+ }
read_unlock(&ctx->ctx_lock);
return vchan;
}
diff --git a/drivers/soc/qcom/hab/hab_mem_linux.c b/drivers/soc/qcom/hab/hab_mem_linux.c
index da41536205a5..60156c6b00f0 100644
--- a/drivers/soc/qcom/hab/hab_mem_linux.c
+++ b/drivers/soc/qcom/hab/hab_mem_linux.c
@@ -21,17 +21,14 @@ struct pages_list {
struct page **pages;
long npages;
uint64_t index; /* for mmap first call */
- int kernel;
void *kva;
- void *uva;
- int refcntk;
- int refcntu;
uint32_t userflags;
struct file *filp_owner;
struct file *filp_mapper;
- struct dma_buf *dmabuf;
int32_t export_id;
int32_t vcid;
+ struct physical_channel *pchan;
+ struct kref refcount;
};
struct importer_context {
@@ -41,6 +38,118 @@ struct importer_context {
rwlock_t implist_lock;
};
+static struct pages_list *pages_list_create(
+ void *imp_ctx,
+ struct export_desc *exp,
+ uint32_t userflags)
+{
+ struct page **pages;
+ struct compressed_pfns *pfn_table =
+ (struct compressed_pfns *)exp->payload;
+ struct pages_list *pglist;
+ unsigned long pfn;
+ int i, j, k = 0, size;
+
+ if (!pfn_table)
+ return ERR_PTR(-EINVAL);
+
+ size = exp->payload_count * sizeof(struct page *);
+ pages = kmalloc(size, GFP_KERNEL);
+ if (!pages)
+ return ERR_PTR(-ENOMEM);
+
+ pglist = kzalloc(sizeof(*pglist), GFP_KERNEL);
+ if (!pglist) {
+ kfree(pages);
+ return ERR_PTR(-ENOMEM);
+ }
+
+ pfn = pfn_table->first_pfn;
+ for (i = 0; i < pfn_table->nregions; i++) {
+ for (j = 0; j < pfn_table->region[i].size; j++) {
+ pages[k] = pfn_to_page(pfn+j);
+ k++;
+ }
+ pfn += pfn_table->region[i].size + pfn_table->region[i].space;
+ }
+
+ pglist->pages = pages;
+ pglist->npages = exp->payload_count;
+ pglist->userflags = userflags;
+ pglist->export_id = exp->export_id;
+ pglist->vcid = exp->vcid_remote;
+ pglist->pchan = exp->pchan;
+
+ kref_init(&pglist->refcount);
+
+ return pglist;
+}
+
+static void pages_list_destroy(struct kref *refcount)
+{
+ struct pages_list *pglist = container_of(refcount,
+ struct pages_list, refcount);
+
+ if (pglist->kva)
+ vunmap(pglist->kva);
+
+ kfree(pglist->pages);
+
+ kfree(pglist);
+}
+
+static void pages_list_get(struct pages_list *pglist)
+{
+ kref_get(&pglist->refcount);
+}
+
+static int pages_list_put(struct pages_list *pglist)
+{
+ return kref_put(&pglist->refcount, pages_list_destroy);
+}
+
+static struct pages_list *pages_list_lookup(
+ struct importer_context *imp_ctx,
+ uint32_t export_id, struct physical_channel *pchan)
+{
+ struct pages_list *pglist, *tmp;
+
+ read_lock(&imp_ctx->implist_lock);
+ list_for_each_entry_safe(pglist, tmp, &imp_ctx->imp_list, list) {
+ if (pglist->export_id == export_id &&
+ pglist->pchan == pchan) {
+ pages_list_get(pglist);
+ read_unlock(&imp_ctx->implist_lock);
+ return pglist;
+ }
+ }
+ read_unlock(&imp_ctx->implist_lock);
+
+ return NULL;
+}
+
+static void pages_list_add(struct importer_context *imp_ctx,
+ struct pages_list *pglist)
+{
+ pages_list_get(pglist);
+
+ write_lock(&imp_ctx->implist_lock);
+ list_add_tail(&pglist->list, &imp_ctx->imp_list);
+ imp_ctx->cnt++;
+ write_unlock(&imp_ctx->implist_lock);
+}
+
+static void pages_list_remove(struct importer_context *imp_ctx,
+ struct pages_list *pglist)
+{
+ write_lock(&imp_ctx->implist_lock);
+ list_del(&pglist->list);
+ imp_ctx->cnt--;
+ write_unlock(&imp_ctx->implist_lock);
+
+ pages_list_put(pglist);
+}
+
void *habmm_hyp_allocate_grantable(int page_count,
uint32_t *sizebytes)
{
@@ -79,6 +188,7 @@ static int habmem_get_dma_pages_from_va(unsigned long address,
vma = find_vma(current->mm, address);
if (!vma || !vma->vm_file) {
pr_err("cannot find vma\n");
+ rc = -EBADF;
goto err;
}
@@ -86,6 +196,7 @@ static int habmem_get_dma_pages_from_va(unsigned long address,
fd = iterate_fd(current->files, 0, match_file, vma->vm_file);
if (fd == 0) {
pr_err("iterate_fd failed\n");
+ rc = -EBADF;
goto err;
}
@@ -93,10 +204,16 @@ static int habmem_get_dma_pages_from_va(unsigned long address,
page_offset = offset/PAGE_SIZE;
dmabuf = dma_buf_get(fd - 1);
+ if (IS_ERR_OR_NULL(dmabuf)) {
+ pr_err("dma_buf_get failed fd %d ret %pK\n", fd, dmabuf);
+ rc = -EBADF;
+ goto err;
+ }
attach = dma_buf_attach(dmabuf, hab_driver.dev);
if (IS_ERR_OR_NULL(attach)) {
pr_err("dma_buf_attach failed\n");
+ rc = -EBADF;
goto err;
}
@@ -104,6 +221,7 @@ static int habmem_get_dma_pages_from_va(unsigned long address,
if (IS_ERR_OR_NULL(sg_table)) {
pr_err("dma_buf_map_attachment failed\n");
+ rc = -EBADF;
goto err;
}
@@ -154,12 +272,16 @@ static int habmem_get_dma_pages_from_fd(int32_t fd,
int i, j, rc = 0;
dmabuf = dma_buf_get(fd);
- if (IS_ERR(dmabuf))
- return PTR_ERR(dmabuf);
+ if (IS_ERR_OR_NULL(dmabuf)) {
+ pr_err("dma_buf_get failed fd %d ret %pK\n", fd, dmabuf);
+ rc = -EBADF;
+ goto err;
+ }
attach = dma_buf_attach(dmabuf, hab_driver.dev);
if (IS_ERR_OR_NULL(attach)) {
pr_err("dma_buf_attach failed\n");
+ rc = -EBADF;
goto err;
}
@@ -167,6 +289,7 @@ static int habmem_get_dma_pages_from_fd(int32_t fd,
if (IS_ERR_OR_NULL(sg_table)) {
pr_err("dma_buf_map_attachment failed\n");
+ rc = -EBADF;
goto err;
}
@@ -177,9 +300,12 @@ static int habmem_get_dma_pages_from_fd(int32_t fd,
for (j = 0; j < (s->length >> PAGE_SHIFT); j++) {
pages[rc] = nth_page(page, j);
rc++;
- if (WARN_ON(rc >= page_count))
+ if (rc >= page_count)
break;
}
+
+ if (rc >= page_count)
+ break;
}
err:
@@ -305,16 +431,8 @@ void habmem_imp_hyp_close(void *imp_ctx, int kernel)
if (!priv)
return;
- list_for_each_entry_safe(pglist, pglist_tmp, &priv->imp_list, list) {
- if (kernel && pglist->kva)
- vunmap(pglist->kva);
-
- list_del(&pglist->list);
- priv->cnt--;
-
- kfree(pglist->pages);
- kfree(pglist);
- }
+ list_for_each_entry_safe(pglist, pglist_tmp, &priv->imp_list, list)
+ pages_list_remove(priv, pglist);
kfree(priv);
}
@@ -391,10 +509,19 @@ static int hab_map_fault(struct vm_area_struct *vma, struct vm_fault *vmf)
static void hab_map_open(struct vm_area_struct *vma)
{
+ struct pages_list *pglist =
+ (struct pages_list *)vma->vm_private_data;
+
+ pages_list_get(pglist);
}
static void hab_map_close(struct vm_area_struct *vma)
{
+ struct pages_list *pglist =
+ (struct pages_list *)vma->vm_private_data;
+
+ pages_list_put(pglist);
+ vma->vm_private_data = NULL;
}
static const struct vm_operations_struct habmem_vm_ops = {
@@ -403,6 +530,51 @@ static const struct vm_operations_struct habmem_vm_ops = {
.close = hab_map_close,
};
+static int hab_buffer_fault(struct vm_area_struct *vma, struct vm_fault *vmf)
+{
+ struct pages_list *pglist = vma->vm_private_data;
+ pgoff_t page_offset;
+ int ret;
+
+ page_offset = ((unsigned long)vmf->virtual_address - vma->vm_start) >>
+ PAGE_SHIFT;
+
+ if (page_offset > pglist->npages)
+ return VM_FAULT_SIGBUS;
+
+ ret = vm_insert_page(vma, (unsigned long)vmf->virtual_address,
+ pglist->pages[page_offset]);
+
+ switch (ret) {
+ case 0:
+ return VM_FAULT_NOPAGE;
+ case -ENOMEM:
+ return VM_FAULT_OOM;
+ case -EBUSY:
+ return VM_FAULT_RETRY;
+ case -EFAULT:
+ case -EINVAL:
+ return VM_FAULT_SIGBUS;
+ default:
+ WARN_ON(1);
+ return VM_FAULT_SIGBUS;
+ }
+}
+
+static void hab_buffer_open(struct vm_area_struct *vma)
+{
+}
+
+static void hab_buffer_close(struct vm_area_struct *vma)
+{
+}
+
+static const struct vm_operations_struct hab_buffer_vm_ops = {
+ .fault = hab_buffer_fault,
+ .open = hab_buffer_open,
+ .close = hab_buffer_close,
+};
+
static int hab_mem_mmap(struct dma_buf *dmabuf, struct vm_area_struct *vma)
{
struct pages_list *pglist = dmabuf->priv;
@@ -416,7 +588,7 @@ static int hab_mem_mmap(struct dma_buf *dmabuf, struct vm_area_struct *vma)
return -EINVAL;
vma->vm_flags |= VM_IO | VM_PFNMAP | VM_DONTEXPAND | VM_DONTDUMP;
- vma->vm_ops = &habmem_vm_ops;
+ vma->vm_ops = &hab_buffer_vm_ops;
vma->vm_private_data = pglist;
vma->vm_flags |= VM_MIXEDMAP;
@@ -425,6 +597,9 @@ static int hab_mem_mmap(struct dma_buf *dmabuf, struct vm_area_struct *vma)
static void hab_mem_dma_buf_release(struct dma_buf *dmabuf)
{
+ struct pages_list *pglist = dmabuf->priv;
+
+ pages_list_put(pglist);
}
static void *hab_mem_dma_buf_kmap(struct dma_buf *dmabuf,
@@ -455,81 +630,50 @@ static int habmem_imp_hyp_map_fd(void *imp_ctx,
uint32_t userflags,
int32_t *pfd)
{
- struct page **pages;
- struct compressed_pfns *pfn_table =
- (struct compressed_pfns *)exp->payload;
struct pages_list *pglist;
struct importer_context *priv = imp_ctx;
- unsigned long pfn;
- int i, j, k = 0;
- pgprot_t prot = PAGE_KERNEL;
- int32_t fd, size;
+ int32_t fd = -1;
int ret;
+ struct dma_buf *dmabuf;
DEFINE_DMA_BUF_EXPORT_INFO(exp_info);
- if (!pfn_table || !priv)
+ if (!priv)
return -EINVAL;
- size = exp->payload_count * sizeof(struct page *);
- pages = kmalloc(size, GFP_KERNEL);
- if (!pages)
- return -ENOMEM;
-
- pglist = kzalloc(sizeof(*pglist), GFP_KERNEL);
- if (!pglist) {
- kfree(pages);
- return -ENOMEM;
- }
- pfn = pfn_table->first_pfn;
- for (i = 0; i < pfn_table->nregions; i++) {
- for (j = 0; j < pfn_table->region[i].size; j++) {
- pages[k] = pfn_to_page(pfn+j);
- k++;
- }
- pfn += pfn_table->region[i].size + pfn_table->region[i].space;
- }
+ pglist = pages_list_lookup(priv, exp->export_id, exp->pchan);
+ if (pglist)
+ goto buffer_ready;
- pglist->pages = pages;
- pglist->npages = exp->payload_count;
- pglist->kernel = 0;
- pglist->index = 0;
- pglist->refcntk = pglist->refcntu = 0;
- pglist->userflags = userflags;
- pglist->export_id = exp->export_id;
- pglist->vcid = exp->vcid_remote;
+ pglist = pages_list_create(imp_ctx, exp, userflags);
+ if (IS_ERR(pglist))
+ return PTR_ERR(pglist);
- if (!(userflags & HABMM_IMPORT_FLAGS_CACHED))
- prot = pgprot_writecombine(prot);
+ pages_list_add(priv, pglist);
+buffer_ready:
exp_info.ops = &dma_buf_ops;
- exp_info.size = exp->payload_count << PAGE_SHIFT;
+ exp_info.size = pglist->npages << PAGE_SHIFT;
exp_info.flags = O_RDWR;
exp_info.priv = pglist;
- pglist->dmabuf = dma_buf_export(&exp_info);
- if (IS_ERR(pglist->dmabuf)) {
- ret = PTR_ERR(pglist->dmabuf);
- kfree(pages);
- kfree(pglist);
- return ret;
+ dmabuf = dma_buf_export(&exp_info);
+ if (IS_ERR(dmabuf)) {
+ pr_err("export to dmabuf failed\n");
+ ret = PTR_ERR(dmabuf);
+ goto proc_end;
}
+ pages_list_get(pglist);
- fd = dma_buf_fd(pglist->dmabuf, O_CLOEXEC);
+ fd = dma_buf_fd(dmabuf, O_CLOEXEC);
if (fd < 0) {
- dma_buf_put(pglist->dmabuf);
- kfree(pages);
- kfree(pglist);
- return -EINVAL;
+ pr_err("dma buf to fd failed\n");
+ dma_buf_put(dmabuf);
+ ret = -EINVAL;
+ goto proc_end;
}
- pglist->refcntk++;
-
- write_lock(&priv->implist_lock);
- list_add_tail(&pglist->list, &priv->imp_list);
- priv->cnt++;
- write_unlock(&priv->implist_lock);
-
+proc_end:
*pfd = fd;
-
+ pages_list_put(pglist);
return 0;
}
@@ -538,67 +682,45 @@ static int habmem_imp_hyp_map_kva(void *imp_ctx,
uint32_t userflags,
void **pkva)
{
- struct page **pages;
- struct compressed_pfns *pfn_table =
- (struct compressed_pfns *)exp->payload;
struct pages_list *pglist;
struct importer_context *priv = imp_ctx;
- unsigned long pfn;
- int i, j, k = 0, size;
pgprot_t prot = PAGE_KERNEL;
- if (!pfn_table || !priv)
+ if (!priv)
return -EINVAL;
- size = exp->payload_count * sizeof(struct page *);
- pages = kmalloc(size, GFP_KERNEL);
- if (!pages)
- return -ENOMEM;
- pglist = kzalloc(sizeof(*pglist), GFP_KERNEL);
- if (!pglist) {
- kfree(pages);
- return -ENOMEM;
- }
- pfn = pfn_table->first_pfn;
- for (i = 0; i < pfn_table->nregions; i++) {
- for (j = 0; j < pfn_table->region[i].size; j++) {
- pages[k] = pfn_to_page(pfn+j);
- k++;
- }
- pfn += pfn_table->region[i].size + pfn_table->region[i].space;
- }
+ pglist = pages_list_lookup(priv, exp->export_id, exp->pchan);
+ if (pglist)
+ goto buffer_ready;
- pglist->pages = pages;
- pglist->npages = exp->payload_count;
- pglist->kernel = 1;
- pglist->refcntk = pglist->refcntu = 0;
- pglist->userflags = userflags;
- pglist->export_id = exp->export_id;
- pglist->vcid = exp->vcid_remote;
+ pglist = pages_list_create(imp_ctx, exp, userflags);
+ if (IS_ERR(pglist))
+ return PTR_ERR(pglist);
+
+ pages_list_add(priv, pglist);
+
+buffer_ready:
+ if (pglist->kva)
+ goto pro_end;
+
+ if (pglist->userflags != userflags) {
+ pr_info("exp %d: userflags: 0x%x -> 0x%x\n",
+ exp->export_id, pglist->userflags, userflags);
+ pglist->userflags = userflags;
+ }
if (!(userflags & HABMM_IMPORT_FLAGS_CACHED))
prot = pgprot_writecombine(prot);
pglist->kva = vmap(pglist->pages, pglist->npages, VM_MAP, prot);
if (pglist->kva == NULL) {
- kfree(pages);
pr_err("%ld pages vmap failed\n", pglist->npages);
- kfree(pglist);
return -ENOMEM;
}
- pr_debug("%ld pages vmap pass, return %p\n",
- pglist->npages, pglist->kva);
-
- pglist->refcntk++;
-
- write_lock(&priv->implist_lock);
- list_add_tail(&pglist->list, &priv->imp_list);
- priv->cnt++;
- write_unlock(&priv->implist_lock);
-
+pro_end:
*pkva = pglist->kva;
-
+ pages_list_put(pglist);
return 0;
}
@@ -607,51 +729,31 @@ static int habmem_imp_hyp_map_uva(void *imp_ctx,
uint32_t userflags,
uint64_t *index)
{
- struct page **pages;
- struct compressed_pfns *pfn_table =
- (struct compressed_pfns *)exp->payload;
struct pages_list *pglist;
struct importer_context *priv = imp_ctx;
- unsigned long pfn;
- int i, j, k = 0, size;
- if (!pfn_table || !priv)
+ if (!priv)
return -EINVAL;
- size = exp->payload_count * sizeof(struct page *);
- pages = kmalloc(size, GFP_KERNEL);
- if (!pages)
- return -ENOMEM;
- pglist = kzalloc(sizeof(*pglist), GFP_KERNEL);
- if (!pglist) {
- kfree(pages);
- return -ENOMEM;
- }
+ pglist = pages_list_lookup(priv, exp->export_id, exp->pchan);
+ if (pglist)
+ goto buffer_ready;
- pfn = pfn_table->first_pfn;
- for (i = 0; i < pfn_table->nregions; i++) {
- for (j = 0; j < pfn_table->region[i].size; j++) {
- pages[k] = pfn_to_page(pfn+j);
- k++;
- }
- pfn += pfn_table->region[i].size + pfn_table->region[i].space;
- }
+ pglist = pages_list_create(imp_ctx, exp, userflags);
+ if (IS_ERR(pglist))
+ return PTR_ERR(pglist);
- pglist->pages = pages;
- pglist->npages = exp->payload_count;
- pglist->index = page_to_phys(pages[0]) >> PAGE_SHIFT;
- pglist->refcntk = pglist->refcntu = 0;
- pglist->userflags = userflags;
- pglist->export_id = exp->export_id;
- pglist->vcid = exp->vcid_remote;
+ pages_list_add(priv, pglist);
- write_lock(&priv->implist_lock);
- list_add_tail(&pglist->list, &priv->imp_list);
- priv->cnt++;
- write_unlock(&priv->implist_lock);
+buffer_ready:
+ if (pglist->index)
+ goto proc_end;
- *index = pglist->index << PAGE_SHIFT;
+ pglist->index = page_to_phys(pglist->pages[0]) >> PAGE_SHIFT;
+proc_end:
+ *index = pglist->index << PAGE_SHIFT;
+ pages_list_put(pglist);
return 0;
}
@@ -679,37 +781,17 @@ int habmem_imp_hyp_map(void *imp_ctx, struct hab_import *param,
int habmm_imp_hyp_unmap(void *imp_ctx, struct export_desc *exp, int kernel)
{
struct importer_context *priv = imp_ctx;
- struct pages_list *pglist, *tmp;
- int found = 0;
-
- write_lock(&priv->implist_lock);
- list_for_each_entry_safe(pglist, tmp, &priv->imp_list, list) {
- if (pglist->export_id == exp->export_id &&
- pglist->vcid == exp->vcid_remote) {
- found = 1;
- list_del(&pglist->list);
- priv->cnt--;
- break;
- }
- }
- write_unlock(&priv->implist_lock);
+ struct pages_list *pglist;
- if (!found) {
+ pglist = pages_list_lookup(priv, exp->export_id, exp->pchan);
+ if (!pglist) {
pr_err("failed to find export id %u\n", exp->export_id);
return -EINVAL;
}
- pr_debug("detach pglist %p, kernel %d, list cnt %d\n",
- pglist, pglist->kernel, priv->cnt);
+ pages_list_remove(priv, pglist);
- if (pglist->kva)
- vunmap(pglist->kva);
-
- if (pglist->dmabuf)
- dma_buf_put(pglist->dmabuf);
-
- kfree(pglist->pages);
- kfree(pglist);
+ pages_list_put(pglist);
return 0;
}
@@ -721,11 +803,14 @@ int habmem_imp_hyp_mmap(struct file *filp, struct vm_area_struct *vma)
long length = vma->vm_end - vma->vm_start;
struct pages_list *pglist;
int bfound = 0;
+ int ret = 0;
read_lock(&imp_ctx->implist_lock);
list_for_each_entry(pglist, &imp_ctx->imp_list, list) {
- if (pglist->index == vma->vm_pgoff) {
+ if ((pglist->index == vma->vm_pgoff) &&
+ ((length <= pglist->npages * PAGE_SIZE))) {
bfound = 1;
+ pages_list_get(pglist);
break;
}
}
@@ -739,7 +824,8 @@ int habmem_imp_hyp_mmap(struct file *filp, struct vm_area_struct *vma)
if (length > pglist->npages * PAGE_SIZE) {
pr_err("Error vma length %ld not matching page list %ld\n",
length, pglist->npages * PAGE_SIZE);
- return -EINVAL;
+ ret = -EINVAL;
+ goto proc_end;
}
vma->vm_ops = &habmem_vm_ops;
@@ -750,6 +836,10 @@ int habmem_imp_hyp_mmap(struct file *filp, struct vm_area_struct *vma)
vma->vm_page_prot = pgprot_writecombine(vma->vm_page_prot);
return 0;
+
+proc_end:
+ pages_list_put(pglist);
+ return ret;
}
int habmm_imp_hyp_map_check(void *imp_ctx, struct export_desc *exp)
@@ -758,15 +848,11 @@ int habmm_imp_hyp_map_check(void *imp_ctx, struct export_desc *exp)
struct pages_list *pglist;
int found = 0;
- read_lock(&priv->implist_lock);
- list_for_each_entry(pglist, &priv->imp_list, list) {
- if (pglist->export_id == exp->export_id &&
- pglist->vcid == exp->vcid_remote) {
- found = 1;
- break;
- }
+ pglist = pages_list_lookup(priv, exp->export_id, exp->pchan);
+ if (pglist) {
+ found = 1;
+ pages_list_put(pglist);
}
- read_unlock(&priv->implist_lock);
return found;
}
diff --git a/drivers/soc/qcom/hab/hab_mimex.c b/drivers/soc/qcom/hab/hab_mimex.c
index 23087680c690..d5786170f0f3 100644
--- a/drivers/soc/qcom/hab/hab_mimex.c
+++ b/drivers/soc/qcom/hab/hab_mimex.c
@@ -319,8 +319,7 @@ int hab_mem_unexport(struct uhab_context *ctx,
write_lock(&ctx->exp_lock);
list_for_each_entry_safe(exp, tmp, &ctx->exp_whse, node) {
if (param->exportid == exp->export_id &&
- param->vcid == exp->vcid_local) {
- /* same vchan guarantees the pchan for idr */
+ vchan->pchan == exp->pchan) {
list_del(&exp->node);
found = 1;
break;
@@ -367,10 +366,7 @@ int hab_mem_import(struct uhab_context *ctx,
spin_lock_bh(&ctx->imp_lock);
list_for_each_entry(exp, &ctx->imp_whse, node) {
if ((exp->export_id == param->exportid) &&
- (param->vcid == exp->vcid_remote)) {
- /* only allow import on the vchan recevied from
- * remote
- */
+ (exp->pchan == vchan->pchan)) {
found = 1;
break;
}
@@ -424,8 +420,8 @@ int hab_mem_unimport(struct uhab_context *ctx,
spin_lock_bh(&ctx->imp_lock);
list_for_each_entry_safe(exp, exp_tmp, &ctx->imp_whse, node) {
if (exp->export_id == param->exportid &&
- param->vcid == exp->vcid_remote) {
- /* same vchan is expected here */
+ exp->pchan == vchan->pchan) {
+ /* same pchan is expected here */
list_del(&exp->node);
ctx->import_total--;
found = 1;
diff --git a/drivers/soc/qcom/hab/hab_msg.c b/drivers/soc/qcom/hab/hab_msg.c
index 9d5ee134c94e..3765623d3190 100644
--- a/drivers/soc/qcom/hab/hab_msg.c
+++ b/drivers/soc/qcom/hab/hab_msg.c
@@ -282,6 +282,7 @@ int hab_msg_recv(struct physical_channel *pchan,
}
exp_desc->domid_local = pchan->dom_id;
+ exp_desc->pchan = pchan;
hab_export_enqueue(vchan, exp_desc);
hab_send_export_ack(vchan, pchan, exp_desc);
diff --git a/drivers/soc/qcom/hab/hab_vchan.c b/drivers/soc/qcom/hab/hab_vchan.c
index e7b46df3f97e..d572e4c8a34b 100644
--- a/drivers/soc/qcom/hab/hab_vchan.c
+++ b/drivers/soc/qcom/hab/hab_vchan.c
@@ -90,7 +90,7 @@ hab_vchan_free(struct kref *ref)
vchan->ctx = NULL;
/* release vchan from pchan. no more msg for this vchan */
- write_lock(&pchan->vchans_lock);
+ write_lock_bh(&pchan->vchans_lock);
list_for_each_entry_safe(vc, vc_tmp, &pchan->vchannels, pnode) {
if (vchan == vc) {
list_del(&vc->pnode);
@@ -99,7 +99,7 @@ hab_vchan_free(struct kref *ref)
break;
}
}
- write_unlock(&pchan->vchans_lock);
+ write_unlock_bh(&pchan->vchans_lock);
/* release idr at the last so same idr will not be used early */
spin_lock_bh(&pchan->vid_lock);
@@ -144,6 +144,13 @@ hab_vchan_get(struct physical_channel *pchan, struct hab_header *header)
get_refcnt(vchan->refcount),
payload_type, sizebytes);
vchan = NULL;
+ } else if (vchan->otherend_closed || vchan->closed) {
+ pr_err("closed already remote %d local %d vcid %x remote %x session %d refcnt %d header %x session %d type %d sz %zd\n",
+ vchan->otherend_closed, vchan->closed,
+ vchan->id, vchan->otherend_id,
+ vchan->session_id, get_refcnt(vchan->refcount),
+ vchan_id, session_id, payload_type, sizebytes);
+ vchan = NULL;
} else if (!kref_get_unless_zero(&vchan->refcount)) {
/*
* this happens when refcnt is already zero
@@ -154,13 +161,6 @@ hab_vchan_get(struct physical_channel *pchan, struct hab_header *header)
vchan->session_id, get_refcnt(vchan->refcount),
vchan_id, session_id, payload_type, sizebytes);
vchan = NULL;
- } else if (vchan->otherend_closed || vchan->closed) {
- pr_err("closed already remote %d local %d vcid %x remote %x session %d refcnt %d header %x session %d type %d sz %zd\n",
- vchan->otherend_closed, vchan->closed,
- vchan->id, vchan->otherend_id,
- vchan->session_id, get_refcnt(vchan->refcount),
- vchan_id, session_id, payload_type, sizebytes);
- vchan = NULL;
}
}
spin_unlock_bh(&pchan->vid_lock);
@@ -262,7 +262,7 @@ static void hab_vchan_schedule_free(struct kref *ref)
* similar logic is in ctx free. if ctx free runs first,
* this is skipped
*/
- write_lock(&ctx->ctx_lock);
+ write_lock_bh(&ctx->ctx_lock);
list_for_each_entry_safe(vchan, tmp, &ctx->vchannels, node) {
if (vchan == vchanin) {
pr_debug("vchan free refcnt = %d\n",
@@ -273,7 +273,7 @@ static void hab_vchan_schedule_free(struct kref *ref)
break;
}
}
- write_unlock(&ctx->ctx_lock);
+ write_unlock_bh(&ctx->ctx_lock);
if (bnotify)
hab_vchan_stop_notify(vchan);
diff --git a/drivers/soc/qcom/qdsp6v2/audio-anc-dev-mgr.c b/drivers/soc/qcom/qdsp6v2/audio-anc-dev-mgr.c
index 75b114e6905c..95562d2cbfad 100644
--- a/drivers/soc/qcom/qdsp6v2/audio-anc-dev-mgr.c
+++ b/drivers/soc/qcom/qdsp6v2/audio-anc-dev-mgr.c
@@ -53,8 +53,6 @@ struct anc_tdm_group_set_info {
struct anc_dev_drv_info {
uint32_t state;
- uint32_t rpm;
- uint32_t bypass_mode;
uint32_t algo_module_id;
};
@@ -311,52 +309,68 @@ static int anc_dev_port_stop(int32_t which_port)
int msm_anc_dev_set_info(void *info_p, int32_t anc_cmd)
{
- int rc = 0;
+ int rc = -EINVAL;
switch (anc_cmd) {
- case ANC_CMD_RPM: {
- struct audio_anc_rpm_info *rpm_info_p =
- (struct audio_anc_rpm_info *)info_p;
+ case ANC_CMD_ALGO_MODULE: {
+ struct audio_anc_algo_module_info *module_info_p =
+ (struct audio_anc_algo_module_info *)info_p;
+
+ rc = 0;
if (this_anc_dev_info.state)
- rc = anc_if_set_rpm(
+ rc = anc_if_set_algo_module_id(
anc_port_cfg[ANC_DEV_PORT_ANC_SPKR].port_id,
- rpm_info_p->rpm);
+ module_info_p->module_id);
else
- this_anc_dev_info.rpm = 0;
+ this_anc_dev_info.algo_module_id =
+ module_info_p->module_id;
break;
}
- case ANC_CMD_BYPASS_MODE: {
- struct audio_anc_bypass_mode *bypass_mode_p =
- (struct audio_anc_bypass_mode *)info_p;
-
+ case ANC_CMD_ALGO_CALIBRATION: {
+ rc = -EINVAL;
if (this_anc_dev_info.state)
- rc = anc_if_set_bypass_mode(
+ rc = anc_if_set_algo_module_cali_data(
anc_port_cfg[ANC_DEV_PORT_ANC_SPKR].port_id,
- bypass_mode_p->mode);
+ info_p);
else
- this_anc_dev_info.bypass_mode = bypass_mode_p->mode;
+ pr_err("%s: ANC is not running yet\n",
+ __func__);
+ break;
+ }
+ default:
+ pr_err("%s: ANC cmd wrong\n",
+ __func__);
break;
}
- case ANC_CMD_ALGO_MODULE: {
- struct audio_anc_algo_module_info *module_info_p =
- (struct audio_anc_algo_module_info *)info_p;
+ return rc;
+}
+
+int msm_anc_dev_get_info(void *info_p, int32_t anc_cmd)
+{
+ int rc = -EINVAL;
+
+ switch (anc_cmd) {
+ case ANC_CMD_ALGO_CALIBRATION: {
if (this_anc_dev_info.state)
- rc = anc_if_set_algo_module_id(
+ rc = anc_if_get_algo_module_cali_data(
anc_port_cfg[ANC_DEV_PORT_ANC_SPKR].port_id,
- module_info_p->module_id);
+ info_p);
else
- this_anc_dev_info.algo_module_id =
- module_info_p->module_id;
+ pr_err("%s: ANC is not running yet\n",
+ __func__);
break;
}
+ default:
+ pr_err("%s: ANC cmd wrong\n",
+ __func__);
+ break;
}
return rc;
}
-
int msm_anc_dev_start(void)
{
int rc = 0;
@@ -514,11 +528,6 @@ int msm_anc_dev_start(void)
anc_port_cfg[ANC_DEV_PORT_ANC_SPKR].port_id,
this_anc_dev_info.algo_module_id);
- if (this_anc_dev_info.bypass_mode != 0)
- rc = anc_if_set_bypass_mode(
- anc_port_cfg[ANC_DEV_PORT_ANC_SPKR].port_id,
- this_anc_dev_info.bypass_mode);
-
group_id = get_group_id_from_port_id(
anc_port_cfg[ANC_DEV_PORT_ANC_SPKR].port_id);
@@ -612,8 +621,6 @@ int msm_anc_dev_stop(void)
this_anc_dev_info.state = 0;
this_anc_dev_info.algo_module_id = 0;
- this_anc_dev_info.rpm = 0;
- this_anc_dev_info.bypass_mode = 0;
pr_debug("%s: ANC devices stop successfully!\n", __func__);
diff --git a/drivers/soc/qcom/qdsp6v2/audio_anc.c b/drivers/soc/qcom/qdsp6v2/audio_anc.c
index 65c585886453..50cc255043df 100644
--- a/drivers/soc/qcom/qdsp6v2/audio_anc.c
+++ b/drivers/soc/qcom/qdsp6v2/audio_anc.c
@@ -44,17 +44,11 @@ static size_t get_user_anc_cmd_size(int32_t anc_cmd)
case ANC_CMD_STOP:
size = 0;
break;
- case ANC_CMD_RPM:
- size = sizeof(struct audio_anc_rpm_info);
- break;
- case ANC_CMD_BYPASS_MODE:
- size = sizeof(struct audio_anc_bypass_mode);
- break;
case ANC_CMD_ALGO_MODULE:
size = sizeof(struct audio_anc_algo_module_info);
break;
case ANC_CMD_ALGO_CALIBRATION:
- size = sizeof(struct audio_anc_algo_calibration_info);
+ size = sizeof(struct audio_anc_algo_calibration_header);
break;
default:
pr_err("%s:Invalid anc cmd %d!",
@@ -77,8 +71,6 @@ static int call_set_anc(int32_t anc_cmd,
case ANC_CMD_STOP:
ret = msm_anc_dev_stop();
break;
- case ANC_CMD_RPM:
- case ANC_CMD_BYPASS_MODE:
case ANC_CMD_ALGO_MODULE:
case ANC_CMD_ALGO_CALIBRATION:
ret = msm_anc_dev_set_info(data, anc_cmd);
@@ -98,7 +90,8 @@ static int call_get_anc(int32_t anc_cmd,
int ret = 0;
switch (anc_cmd) {
- case ANC_CMD_RPM:
+ case ANC_CMD_ALGO_CALIBRATION:
+ ret = msm_anc_dev_get_info(data, anc_cmd);
break;
default:
break;
@@ -146,9 +139,9 @@ static long audio_anc_shared_ioctl(struct file *file, unsigned int cmd,
pr_err("%s: Could not copy size value from user\n", __func__);
ret = -EFAULT;
goto done;
- } else if (size < sizeof(struct audio_anc_packet)) {
+ } else if (size < sizeof(struct audio_anc_header)) {
pr_err("%s: Invalid size sent to driver: %d, min size is %zd\n",
- __func__, size, sizeof(struct audio_anc_packet));
+ __func__, size, sizeof(struct audio_anc_header));
ret = -EINVAL;
goto done;
}
diff --git a/drivers/soc/qcom/qdsp6v2/sdsp-anc.c b/drivers/soc/qcom/qdsp6v2/sdsp-anc.c
index 9294485f7ff2..4e75bc89aa8f 100644
--- a/drivers/soc/qcom/qdsp6v2/sdsp-anc.c
+++ b/drivers/soc/qcom/qdsp6v2/sdsp-anc.c
@@ -38,7 +38,7 @@ struct anc_if_ctl {
atomic_t status;
wait_queue_head_t wait[AFE_MAX_PORTS];
struct task_struct *task;
- struct anc_get_rpm_resp rpm_calib_data;
+ struct anc_get_algo_module_cali_data_resp cali_data_resp;
uint32_t mmap_handle;
struct mutex afe_cmd_lock;
};
@@ -48,33 +48,23 @@ static struct anc_if_ctl this_anc_if;
static int32_t anc_get_param_callback(uint32_t *payload,
uint32_t payload_size)
{
- u32 param_id;
- struct anc_get_rpm_resp *resp =
- (struct anc_get_rpm_resp *) payload;
-
- if (!(&(resp->pdata))) {
- pr_err("%s: Error: resp pdata is NULL\n", __func__);
+ if ((payload_size < (sizeof(uint32_t) +
+ sizeof(this_anc_if.cali_data_resp.pdata))) ||
+ (payload_size > sizeof(this_anc_if.cali_data_resp))) {
+ pr_err("%s: Error: received size %d, calib_data size %zu\n",
+ __func__, payload_size,
+ sizeof(this_anc_if.cali_data_resp));
return -EINVAL;
}
- param_id = resp->pdata.param_id;
- if (param_id == AUD_MSVC_PARAM_ID_PORT_ANC_ALGO_RPM) {
- if (payload_size < sizeof(this_anc_if.rpm_calib_data)) {
- pr_err("%s: Error: received size %d, calib_data size %zu\n",
- __func__, payload_size,
- sizeof(this_anc_if.rpm_calib_data));
- return -EINVAL;
- }
-
- memcpy(&this_anc_if.rpm_calib_data, payload,
- sizeof(this_anc_if.rpm_calib_data));
- if (!this_anc_if.rpm_calib_data.status) {
- atomic_set(&this_anc_if.state, 0);
- } else {
- pr_debug("%s: calib resp status: %d", __func__,
- this_anc_if.rpm_calib_data.status);
- atomic_set(&this_anc_if.state, -1);
- }
+ memcpy(&this_anc_if.cali_data_resp, payload,
+ payload_size);
+ if (!this_anc_if.cali_data_resp.status) {
+ atomic_set(&this_anc_if.state, 0);
+ } else {
+ pr_debug("%s: calib resp status: %d", __func__,
+ this_anc_if.cali_data_resp.status);
+ atomic_set(&this_anc_if.state, -1);
}
return 0;
@@ -465,7 +455,7 @@ int anc_if_tdm_port_stop(u16 port_id)
return anc_if_send_cmd_port_stop(port_id);
}
-int anc_if_set_rpm(u16 port_id, u32 rpm)
+int anc_if_set_algo_module_id(u16 port_id, u32 module_id)
{
int ret = 0;
int index;
@@ -479,7 +469,7 @@ int anc_if_set_rpm(u16 port_id, u32 rpm)
index = q6audio_get_port_index(port_id);
{
- struct anc_set_rpm_command config;
+ struct anc_set_algo_module_id_command config;
memset(&config, 0, sizeof(config));
config.hdr.hdr_field = APR_HDR_FIELD(APR_MSG_TYPE_SEQ_CMD,
@@ -496,16 +486,16 @@ int anc_if_set_rpm(u16 port_id, u32 rpm)
config.param.payload_address_lsw = 0x00;
config.param.payload_address_msw = 0x00;
config.param.mem_map_handle = 0x00;
- config.pdata.module_id = AUD_MSVC_MODULE_AUDIO_DEV_ANC_ALGO;
- config.pdata.param_id = AUD_MSVC_PARAM_ID_PORT_ANC_ALGO_RPM;
- config.pdata.param_size = sizeof(config.set_rpm);
- config.set_rpm.minor_version =
- AUD_MSVC_API_VERSION_DEV_ANC_ALGO_RPM;
- config.set_rpm.rpm = rpm;
+ config.pdata.module_id = AFE_MODULE_AUDIO_DEV_INTERFACE;
+ config.pdata.param_id =
+ AUD_MSVC_PARAM_ID_PORT_ANC_ALGO_MODULE_ID;
+ config.pdata.param_size = sizeof(config.set_algo_module_id);
+ config.set_algo_module_id.minor_version = 1;
+ config.set_algo_module_id.module_id = module_id;
ret = anc_if_apr_send_pkt(&config, &this_anc_if.wait[index]);
if (ret) {
- pr_err("%s: share resource for port 0x%x failed ret = %d\n",
+ pr_err("%s: anc algo module ID for port 0x%x failed ret = %d\n",
__func__, port_id, ret);
}
}
@@ -513,10 +503,10 @@ int anc_if_set_rpm(u16 port_id, u32 rpm)
return ret;
}
-int anc_if_set_bypass_mode(u16 port_id, u32 bypass_mode)
+int anc_if_set_anc_mic_spkr_layout(u16 port_id,
+struct aud_msvc_param_id_dev_anc_mic_spkr_layout_info *set_mic_spkr_layout_p)
{
int ret = 0;
-
int index;
ret = anc_sdsp_interface_prepare();
@@ -528,7 +518,7 @@ int anc_if_set_bypass_mode(u16 port_id, u32 bypass_mode)
index = q6audio_get_port_index(port_id);
{
- struct anc_set_bypass_mode_command config;
+ struct anc_set_mic_spkr_layout_info_command config;
memset(&config, 0, sizeof(config));
config.hdr.hdr_field = APR_HDR_FIELD(APR_MSG_TYPE_SEQ_CMD,
@@ -545,17 +535,16 @@ int anc_if_set_bypass_mode(u16 port_id, u32 bypass_mode)
config.param.payload_address_lsw = 0x00;
config.param.payload_address_msw = 0x00;
config.param.mem_map_handle = 0x00;
- config.pdata.module_id = AUD_MSVC_MODULE_AUDIO_DEV_ANC_ALGO;
+ config.pdata.module_id = AFE_MODULE_AUDIO_DEV_INTERFACE;
config.pdata.param_id =
- AUD_MSVC_PARAM_ID_PORT_ANC_ALGO_BYPASS_MODE;
- config.pdata.param_size = sizeof(config.set_bypass_mode);
- config.set_bypass_mode.minor_version =
- AUD_MSVC_API_VERSION_DEV_ANC_ALGO_BYPASS_MODE;
- config.set_bypass_mode.bypass_mode = bypass_mode;
+ AUD_MSVC_PARAM_ID_PORT_ANC_MIC_SPKR_LAYOUT_INFO;
+ config.pdata.param_size = sizeof(config.set_mic_spkr_layout);
+ memcpy(&config.set_mic_spkr_layout, set_mic_spkr_layout_p,
+ sizeof(config.set_mic_spkr_layout));
ret = anc_if_apr_send_pkt(&config, &this_anc_if.wait[index]);
if (ret) {
- pr_err("%s: share resource for port 0x%x failed ret = %d\n",
+ pr_err("%s: anc algo module ID for port 0x%x failed ret = %d\n",
__func__, port_id, ret);
}
}
@@ -563,10 +552,10 @@ int anc_if_set_bypass_mode(u16 port_id, u32 bypass_mode)
return ret;
}
-int anc_if_set_algo_module_id(u16 port_id, u32 module_id)
+
+int anc_if_set_algo_module_cali_data(u16 port_id, void *data_p)
{
int ret = 0;
-
int index;
ret = anc_sdsp_interface_prepare();
@@ -578,45 +567,67 @@ int anc_if_set_algo_module_id(u16 port_id, u32 module_id)
index = q6audio_get_port_index(port_id);
{
- struct anc_set_algo_module_id_command config;
+ struct anc_set_algo_module_cali_data_command *cali_data_cfg_p;
+ void *config_p = NULL;
+ int cmd_size = 0;
+ void *out_payload_p = NULL;
+ uint32_t *in_payload_p = (uint32_t *)data_p;
+
+ uint32_t module_id = *in_payload_p;
+ uint32_t param_id = *(in_payload_p + 1);
+ uint32_t payload_size = *(in_payload_p + 2);
+
+ cmd_size = sizeof(struct anc_set_algo_module_cali_data_command)
+ + payload_size;
+ config_p = kzalloc(cmd_size, GFP_KERNEL);
+ if (!config_p) {
+ ret = -ENOMEM;
+ return ret;
+ }
- memset(&config, 0, sizeof(config));
- config.hdr.hdr_field = APR_HDR_FIELD(APR_MSG_TYPE_SEQ_CMD,
+ memset(config_p, 0, cmd_size);
+ out_payload_p = config_p
+ + sizeof(struct anc_set_algo_module_cali_data_command);
+
+ cali_data_cfg_p =
+ (struct anc_set_algo_module_cali_data_command *)config_p;
+
+ cali_data_cfg_p->hdr.hdr_field =
+ APR_HDR_FIELD(APR_MSG_TYPE_SEQ_CMD,
APR_HDR_LEN(APR_HDR_SIZE), APR_PKT_VER);
- config.hdr.pkt_size = sizeof(config);
- config.hdr.src_port = 0;
- config.hdr.dest_port = 0;
- config.hdr.token = index;
- config.hdr.opcode = AFE_PORT_CMD_SET_PARAM_V2;
- config.param.port_id = q6audio_get_port_id(port_id);
- config.param.payload_size = sizeof(config) -
+ cali_data_cfg_p->hdr.pkt_size = cmd_size;
+ cali_data_cfg_p->hdr.src_port = 0;
+ cali_data_cfg_p->hdr.dest_port = 0;
+ cali_data_cfg_p->hdr.token = index;
+ cali_data_cfg_p->hdr.opcode = AFE_PORT_CMD_SET_PARAM_V2;
+ cali_data_cfg_p->param.port_id = q6audio_get_port_id(port_id);
+ cali_data_cfg_p->param.payload_size = cmd_size -
sizeof(struct apr_hdr) -
- sizeof(config.param);
- config.param.payload_address_lsw = 0x00;
- config.param.payload_address_msw = 0x00;
- config.param.mem_map_handle = 0x00;
- config.pdata.module_id = AUD_MSVC_MODULE_AUDIO_DEV_ANC_ALGO;
- config.pdata.param_id =
- AUD_MSVC_PARAM_ID_PORT_ANC_ALGO_MODULE_ID;
- config.pdata.param_size = sizeof(config.set_algo_module_id);
- config.set_algo_module_id.minor_version = 1;
- config.set_algo_module_id.module_id = module_id;
+ sizeof(struct aud_msvc_port_cmd_set_param_v2);
+ cali_data_cfg_p->param.payload_address_lsw = 0x00;
+ cali_data_cfg_p->param.payload_address_msw = 0x00;
+ cali_data_cfg_p->param.mem_map_handle = 0x00;
+ cali_data_cfg_p->pdata.module_id = module_id;
+ cali_data_cfg_p->pdata.param_id = param_id;
+ cali_data_cfg_p->pdata.param_size = payload_size;
+
+ memcpy(out_payload_p, (in_payload_p + 3), payload_size);
+
+ ret = anc_if_apr_send_pkt(cali_data_cfg_p,
+ &this_anc_if.wait[index]);
+ if (ret)
+ pr_err("%s: anc algo module calibration data for port 0x%x failed ret = %d\n",
+ __func__, port_id, ret);
- ret = anc_if_apr_send_pkt(&config, &this_anc_if.wait[index]);
- if (ret) {
- pr_err("%s: anc algo module ID for port 0x%x failed ret = %d\n",
- __func__, port_id, ret);
- }
+ kfree(config_p);
}
return ret;
}
-int anc_if_set_anc_mic_spkr_layout(u16 port_id,
-struct aud_msvc_param_id_dev_anc_mic_spkr_layout_info *set_mic_spkr_layout_p)
+int anc_if_get_algo_module_cali_data(u16 port_id, void *data_p)
{
int ret = 0;
-
int index;
ret = anc_sdsp_interface_prepare();
@@ -628,35 +639,68 @@ struct aud_msvc_param_id_dev_anc_mic_spkr_layout_info *set_mic_spkr_layout_p)
index = q6audio_get_port_index(port_id);
{
- struct anc_set_mic_spkr_layout_info_command config;
+ struct anc_get_algo_module_cali_data_command *cali_data_cfg_p;
+ void *config_p = NULL;
+ int cmd_size = 0;
+ void *out_payload_p = NULL;
+ uint32_t *in_payload_p = (uint32_t *)data_p;
+
+ uint32_t module_id = *in_payload_p;
+ uint32_t param_id = *(in_payload_p + 1);
+ uint32_t payload_size = *(in_payload_p + 2);
+
+ cmd_size = sizeof(struct anc_get_algo_module_cali_data_command)
+ + payload_size;
+ config_p = kzalloc(cmd_size, GFP_KERNEL);
+ if (!config_p) {
+ ret = -ENOMEM;
+ return ret;
+ }
- memset(&config, 0, sizeof(config));
- config.hdr.hdr_field = APR_HDR_FIELD(APR_MSG_TYPE_SEQ_CMD,
+ memset(config_p, 0, cmd_size);
+ out_payload_p = config_p +
+ sizeof(struct anc_set_algo_module_cali_data_command);
+
+ cali_data_cfg_p =
+ (struct anc_get_algo_module_cali_data_command *)config_p;
+
+ cali_data_cfg_p->hdr.hdr_field =
+ APR_HDR_FIELD(APR_MSG_TYPE_SEQ_CMD,
APR_HDR_LEN(APR_HDR_SIZE), APR_PKT_VER);
- config.hdr.pkt_size = sizeof(config);
- config.hdr.src_port = 0;
- config.hdr.dest_port = 0;
- config.hdr.token = index;
- config.hdr.opcode = AFE_PORT_CMD_SET_PARAM_V2;
- config.param.port_id = q6audio_get_port_id(port_id);
- config.param.payload_size = sizeof(config) -
+ cali_data_cfg_p->hdr.pkt_size = cmd_size;
+ cali_data_cfg_p->hdr.src_port = 0;
+ cali_data_cfg_p->hdr.dest_port = 0;
+ cali_data_cfg_p->hdr.token = index;
+ cali_data_cfg_p->hdr.opcode = AFE_PORT_CMD_GET_PARAM_V2;
+ cali_data_cfg_p->param.port_id = q6audio_get_port_id(port_id);
+ cali_data_cfg_p->param.payload_size = cmd_size -
sizeof(struct apr_hdr) -
- sizeof(config.param);
- config.param.payload_address_lsw = 0x00;
- config.param.payload_address_msw = 0x00;
- config.param.mem_map_handle = 0x00;
- config.pdata.module_id = AUD_MSVC_MODULE_AUDIO_DEV_ANC_ALGO;
- config.pdata.param_id =
- AUD_MSVC_PARAM_ID_PORT_ANC_MIC_SPKR_LAYOUT_INFO;
- config.pdata.param_size = sizeof(config.set_mic_spkr_layout);
-
- memcpy(&config.set_mic_spkr_layout, set_mic_spkr_layout_p,
- sizeof(config.set_mic_spkr_layout));
- ret = anc_if_apr_send_pkt(&config, &this_anc_if.wait[index]);
- if (ret) {
- pr_err("%s: anc algo module ID for port 0x%x failed ret = %d\n",
+ sizeof(struct aud_msvc_port_cmd_get_param_v2);
+ cali_data_cfg_p->param.payload_address_lsw = 0x00;
+ cali_data_cfg_p->param.payload_address_msw = 0x00;
+ cali_data_cfg_p->param.mem_map_handle = 0x00;
+ cali_data_cfg_p->param.module_id = module_id;
+ cali_data_cfg_p->param.param_id = param_id;
+ cali_data_cfg_p->pdata.param_size = 0;
+ cali_data_cfg_p->pdata.module_id = 0;
+ cali_data_cfg_p->pdata.param_id = 0;
+
+ ret = anc_if_apr_send_pkt(cali_data_cfg_p,
+ &this_anc_if.wait[index]);
+ if (ret)
+ pr_err("%s: anc algo module calibration data for port 0x%x failed ret = %d\n",
__func__, port_id, ret);
- }
+
+ memcpy((in_payload_p + 3),
+ &this_anc_if.cali_data_resp.payload[0], payload_size);
+
+ *in_payload_p = this_anc_if.cali_data_resp.pdata.module_id;
+ *(in_payload_p + 1) =
+ this_anc_if.cali_data_resp.pdata.param_id;
+ *(in_payload_p + 2) =
+ this_anc_if.cali_data_resp.pdata.param_size;
+
+ kfree(config_p);
}
return ret;
@@ -700,7 +744,6 @@ int anc_if_cmd_memory_map(int port_id, phys_addr_t dma_addr_p,
mmap_region_cmd = kzalloc(cmd_size, GFP_KERNEL);
if (!mmap_region_cmd) {
ret = -ENOMEM;
- pr_err("%s: allocate mmap_region_cmd failed\n", __func__);
return ret;
}
diff --git a/drivers/soc/qcom/subsystem_notif_virt.c b/drivers/soc/qcom/subsystem_notif_virt.c
index f8ce53cfa9f7..5c9acf7e4563 100644
--- a/drivers/soc/qcom/subsystem_notif_virt.c
+++ b/drivers/soc/qcom/subsystem_notif_virt.c
@@ -43,7 +43,7 @@ struct subsystem_descriptor {
enum subsystem_type type;
struct notifier_block nb;
void *handle;
- unsigned int ssr_irq;
+ int ssr_irq;
struct list_head subsystem_list;
struct work_struct work;
};
@@ -91,7 +91,7 @@ static int subsys_notif_virt_probe(struct platform_device *pdev)
struct device_node *child = NULL;
const char *ss_type;
struct resource *res;
- struct subsystem_descriptor *subsystem;
+ struct subsystem_descriptor *subsystem = NULL;
int ret = 0;
if (!pdev) {
@@ -193,7 +193,8 @@ static int subsys_notif_virt_probe(struct platform_device *pdev)
}
}
- INIT_WORK(&subsystem->work, subsystem_notif_wq_func);
+ if (subsystem)
+ INIT_WORK(&subsystem->work, subsystem_notif_wq_func);
return 0;
err:
destroy_workqueue(ssr_wq);
diff --git a/drivers/soc/qcom/wcd-dsp-glink.c b/drivers/soc/qcom/wcd-dsp-glink.c
index ee88a8aaf850..50cef91ad5a4 100644
--- a/drivers/soc/qcom/wcd-dsp-glink.c
+++ b/drivers/soc/qcom/wcd-dsp-glink.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2016-2017, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2016-2018, 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
@@ -89,6 +89,9 @@ struct wdsp_glink_ch {
/* Wait for ch connect state before sending any command */
wait_queue_head_t ch_connect_wait;
+ /* Wait for ch local and remote disconnect before channel free */
+ wait_queue_head_t ch_free_wait;
+
/*
* Glink channel configuration. This has to be the last
* member of the strucuture as it has variable size
@@ -338,7 +341,7 @@ static void wdsp_glink_notify_state(void *handle, const void *priv,
mutex_lock(&ch->mutex);
ch->channel_state = event;
if (event == GLINK_CONNECTED) {
- dev_dbg(wpriv->dev, "%s: glink channel: %s connected\n",
+ dev_info(wpriv->dev, "%s: glink channel: %s connected\n",
__func__, ch->ch_cfg.name);
for (i = 0; i < ch->ch_cfg.no_of_intents; i++) {
@@ -360,31 +363,29 @@ static void wdsp_glink_notify_state(void *handle, const void *priv,
ch->ch_cfg.name);
wake_up(&ch->ch_connect_wait);
- mutex_unlock(&ch->mutex);
} else if (event == GLINK_LOCAL_DISCONNECTED) {
/*
* Don't use dev_dbg here as dev may not be valid if channel
* closed from driver close.
*/
- pr_debug("%s: channel: %s disconnected locally\n",
+ pr_info("%s: channel: %s disconnected locally\n",
__func__, ch->ch_cfg.name);
mutex_unlock(&ch->mutex);
-
- if (ch->free_mem) {
- kfree(ch);
- ch = NULL;
- }
+ ch->free_mem = true;
+ wake_up(&ch->ch_free_wait);
+ return;
} else if (event == GLINK_REMOTE_DISCONNECTED) {
- dev_dbg(wpriv->dev, "%s: remote channel: %s disconnected remotely\n",
+ pr_info("%s: remote channel: %s disconnected remotely\n",
__func__, ch->ch_cfg.name);
- mutex_unlock(&ch->mutex);
/*
* If remote disconnect happens, local side also has
* to close the channel as per glink design in a
* separate work_queue.
*/
- queue_work(wpriv->work_queue, &ch->lcl_ch_cls_wrk);
+ if (wpriv && wpriv->work_queue != NULL)
+ queue_work(wpriv->work_queue, &ch->lcl_ch_cls_wrk);
}
+ mutex_unlock(&ch->mutex);
}
/*
@@ -399,11 +400,11 @@ static int wdsp_glink_close_ch(struct wdsp_glink_ch *ch)
mutex_lock(&wpriv->glink_mutex);
if (ch->handle) {
ret = glink_close(ch->handle);
+ ch->handle = NULL;
if (IS_ERR_VALUE(ret)) {
dev_err(wpriv->dev, "%s: glink_close is failed, ret = %d\n",
__func__, ret);
} else {
- ch->handle = NULL;
dev_dbg(wpriv->dev, "%s: ch %s is closed\n", __func__,
ch->ch_cfg.name);
}
@@ -451,6 +452,7 @@ static int wdsp_glink_open_ch(struct wdsp_glink_ch *ch)
ch->handle = NULL;
ret = -EINVAL;
}
+ ch->free_mem = false;
} else {
dev_err(wpriv->dev, "%s: ch %s is already opened\n", __func__,
ch->ch_cfg.name);
@@ -492,7 +494,7 @@ static int wdsp_glink_open_all_ch(struct wdsp_glink_priv *wpriv)
err_open:
for (j = 0; j < i; j++)
- if (wpriv->ch[i])
+ if (wpriv->ch[j])
wdsp_glink_close_ch(wpriv->ch[j]);
done:
@@ -631,6 +633,7 @@ static int wdsp_glink_ch_info_init(struct wdsp_glink_priv *wpriv,
goto err_ch_mem;
}
ch[i]->channel_state = GLINK_LOCAL_DISCONNECTED;
+ ch[i]->free_mem = true;
memcpy(&ch[i]->ch_cfg, payload, ch_cfg_size);
payload += ch_cfg_size;
@@ -654,6 +657,7 @@ static int wdsp_glink_ch_info_init(struct wdsp_glink_priv *wpriv,
INIT_WORK(&ch[i]->lcl_ch_open_wrk, wdsp_glink_lcl_ch_open_wrk);
INIT_WORK(&ch[i]->lcl_ch_cls_wrk, wdsp_glink_lcl_ch_cls_wrk);
init_waitqueue_head(&ch[i]->ch_connect_wait);
+ init_waitqueue_head(&ch[i]->ch_free_wait);
}
INIT_WORK(&wpriv->ch_open_cls_wrk, wdsp_glink_ch_open_cls_wrk);
@@ -1060,36 +1064,48 @@ static int wdsp_glink_release(struct inode *inode, struct file *file)
goto done;
}
+ dev_info(wpriv->dev, "%s: closing wdsp_glink driver\n", __func__);
if (wpriv->glink_state.handle)
glink_unregister_link_state_cb(wpriv->glink_state.handle);
flush_workqueue(wpriv->work_queue);
- destroy_workqueue(wpriv->work_queue);
-
/*
- * Clean up glink channel memory in channel state
- * callback only if close channels are called from here.
+ * Wait for channel local and remote disconnect state notifications
+ * before freeing channel memory.
*/
- if (wpriv->ch) {
- for (i = 0; i < wpriv->no_of_channels; i++) {
- if (wpriv->ch[i]) {
- wpriv->ch[i]->free_mem = true;
- /*
- * Channel handle NULL means channel is already
- * closed. Free the channel memory here itself.
- */
- if (!wpriv->ch[i]->handle) {
- kfree(wpriv->ch[i]);
- wpriv->ch[i] = NULL;
- } else {
- wdsp_glink_close_ch(wpriv->ch[i]);
- }
+ for (i = 0; i < wpriv->no_of_channels; i++) {
+ if (wpriv->ch && wpriv->ch[i]) {
+ /*
+ * Only close glink channel from here if REMOTE has
+ * not already disconnected it
+ */
+ wdsp_glink_close_ch(wpriv->ch[i]);
+
+ ret = wait_event_timeout(wpriv->ch[i]->ch_free_wait,
+ (wpriv->ch[i]->free_mem == true),
+ msecs_to_jiffies(TIMEOUT_MS));
+ if (!ret) {
+ pr_err("%s: glink ch %s failed to notify states properly %d\n",
+ __func__, wpriv->ch[i]->ch_cfg.name,
+ wpriv->ch[i]->channel_state);
+ ret = -EINVAL;
+ goto done;
}
}
+ }
- kfree(wpriv->ch);
- wpriv->ch = NULL;
+ flush_workqueue(wpriv->work_queue);
+ destroy_workqueue(wpriv->work_queue);
+ wpriv->work_queue = NULL;
+
+ for (i = 0; i < wpriv->no_of_channels; i++) {
+ if (wpriv->ch && wpriv->ch[i]) {
+ kfree(wpriv->ch[i]);
+ wpriv->ch[i] = NULL;
+ }
}
+ kfree(wpriv->ch);
+ wpriv->ch = NULL;
mutex_destroy(&wpriv->glink_mutex);
mutex_destroy(&wpriv->rsp_mutex);
diff --git a/drivers/soundwire/soundwire.c b/drivers/soundwire/soundwire.c
index 63545651fe43..0e8cc399204e 100755..100644
--- a/drivers/soundwire/soundwire.c
+++ b/drivers/soundwire/soundwire.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2015-2017, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2015-2018, 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
@@ -241,7 +241,7 @@ int swr_remove_from_group(struct swr_device *dev, u8 dev_num)
if (!dev->group_id)
return 0;
- if (master->gr_sid == dev_num)
+ if (master->gr_sid != dev_num)
return 0;
if (master->remove_from_group && master->remove_from_group(master))
diff --git a/drivers/soundwire/swr-wcd-ctrl.c b/drivers/soundwire/swr-wcd-ctrl.c
index 1dcaba2e79f6..a8458b9b6e3a 100644
--- a/drivers/soundwire/swr-wcd-ctrl.c
+++ b/drivers/soundwire/swr-wcd-ctrl.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2015-2017, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2015-2018, 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
@@ -1727,6 +1727,8 @@ int swrm_wcd_notify(struct platform_device *pdev, u32 id, void *data)
(swrm->state == SWR_MSTR_UP)) {
dev_dbg(swrm->dev, "%s: SWR master is already UP: %d\n",
__func__, swrm->state);
+ list_for_each_entry(swr_dev, &mstr->devices, dev_list)
+ swr_reset_device(swr_dev);
} else {
pm_runtime_mark_last_busy(&pdev->dev);
mutex_unlock(&swrm->reslock);
diff --git a/drivers/staging/android/ion/ion.c b/drivers/staging/android/ion/ion.c
index 77903dbdd2d9..65e34250cab2 100644
--- a/drivers/staging/android/ion/ion.c
+++ b/drivers/staging/android/ion/ion.c
@@ -1417,24 +1417,28 @@ static struct dma_buf_ops dma_buf_ops = {
.kunmap = ion_dma_buf_kunmap,
};
-struct dma_buf *ion_share_dma_buf(struct ion_client *client,
- struct ion_handle *handle)
+static struct dma_buf *__ion_share_dma_buf(struct ion_client *client,
+ struct ion_handle *handle,
+ bool lock_client)
{
DEFINE_DMA_BUF_EXPORT_INFO(exp_info);
struct ion_buffer *buffer;
struct dma_buf *dmabuf;
bool valid_handle;
- mutex_lock(&client->lock);
+ if (lock_client)
+ mutex_lock(&client->lock);
valid_handle = ion_handle_validate(client, handle);
if (!valid_handle) {
WARN(1, "%s: invalid handle passed to share.\n", __func__);
- mutex_unlock(&client->lock);
+ if (lock_client)
+ mutex_unlock(&client->lock);
return ERR_PTR(-EINVAL);
}
buffer = handle->buffer;
ion_buffer_get(buffer);
- mutex_unlock(&client->lock);
+ if (lock_client)
+ mutex_unlock(&client->lock);
exp_info.ops = &dma_buf_ops;
exp_info.size = buffer->size;
@@ -1449,14 +1453,21 @@ struct dma_buf *ion_share_dma_buf(struct ion_client *client,
return dmabuf;
}
+
+struct dma_buf *ion_share_dma_buf(struct ion_client *client,
+ struct ion_handle *handle)
+{
+ return __ion_share_dma_buf(client, handle, true);
+}
EXPORT_SYMBOL(ion_share_dma_buf);
-int ion_share_dma_buf_fd(struct ion_client *client, struct ion_handle *handle)
+static int __ion_share_dma_buf_fd(struct ion_client *client,
+ struct ion_handle *handle, bool lock_client)
{
struct dma_buf *dmabuf;
int fd;
- dmabuf = ion_share_dma_buf(client, handle);
+ dmabuf = __ion_share_dma_buf(client, handle, lock_client);
if (IS_ERR(dmabuf))
return PTR_ERR(dmabuf);
@@ -1465,6 +1476,11 @@ int ion_share_dma_buf_fd(struct ion_client *client, struct ion_handle *handle)
dma_buf_put(dmabuf);
return fd;
}
+
+int ion_share_dma_buf_fd(struct ion_client *client, struct ion_handle *handle)
+{
+ return __ion_share_dma_buf_fd(client, handle, true);
+}
EXPORT_SYMBOL(ion_share_dma_buf_fd);
bool ion_dma_buf_is_secure(struct dma_buf *dmabuf)
@@ -1489,6 +1505,12 @@ bool ion_dma_buf_is_secure(struct dma_buf *dmabuf)
}
EXPORT_SYMBOL(ion_dma_buf_is_secure);
+static int ion_share_dma_buf_fd_nolock(struct ion_client *client,
+ struct ion_handle *handle)
+{
+ return __ion_share_dma_buf_fd(client, handle, false);
+}
+
struct ion_handle *ion_import_dma_buf(struct ion_client *client, int fd)
{
struct dma_buf *dmabuf;
@@ -1640,11 +1662,15 @@ static long ion_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)
{
struct ion_handle *handle;
- handle = ion_handle_get_by_id(client, data.handle.handle);
- if (IS_ERR(handle))
+ mutex_lock(&client->lock);
+ handle = ion_handle_get_by_id_nolock(client, data.handle.handle);
+ if (IS_ERR(handle)) {
+ mutex_unlock(&client->lock);
return PTR_ERR(handle);
- data.fd.fd = ion_share_dma_buf_fd(client, handle);
- ion_handle_put(handle);
+ }
+ data.fd.fd = ion_share_dma_buf_fd_nolock(client, handle);
+ ion_handle_put_nolock(handle);
+ mutex_unlock(&client->lock);
if (data.fd.fd < 0)
ret = data.fd.fd;
break;
diff --git a/drivers/staging/android/ion/ion_cma_heap.c b/drivers/staging/android/ion/ion_cma_heap.c
index 77bc25dfd562..bd481af4035c 100644
--- a/drivers/staging/android/ion/ion_cma_heap.c
+++ b/drivers/staging/android/ion/ion_cma_heap.c
@@ -313,14 +313,37 @@ err:
return ret;
}
+static void *ion_secure_cma_map_kernel(struct ion_heap *heap,
+ struct ion_buffer *buffer)
+{
+ if (!is_buffer_hlos_assigned(buffer)) {
+ pr_info("%s: Mapping non-HLOS accessible buffer disallowed\n",
+ __func__);
+ return NULL;
+ }
+ return ion_cma_map_kernel(heap, buffer);
+}
+
+static int ion_secure_cma_map_user(struct ion_heap *mapper,
+ struct ion_buffer *buffer,
+ struct vm_area_struct *vma)
+{
+ if (!is_buffer_hlos_assigned(buffer)) {
+ pr_info("%s: Mapping non-HLOS accessible buffer disallowed\n",
+ __func__);
+ return -EINVAL;
+ }
+ return ion_cma_mmap(mapper, buffer, vma);
+}
+
static struct ion_heap_ops ion_secure_cma_ops = {
.allocate = ion_secure_cma_allocate,
.free = ion_secure_cma_free,
.map_dma = ion_cma_heap_map_dma,
.unmap_dma = ion_cma_heap_unmap_dma,
.phys = ion_cma_phys,
- .map_user = ion_cma_mmap,
- .map_kernel = ion_cma_map_kernel,
+ .map_user = ion_secure_cma_map_user,
+ .map_kernel = ion_secure_cma_map_kernel,
.unmap_kernel = ion_cma_unmap_kernel,
.print_debug = ion_cma_print_debug,
};
diff --git a/drivers/staging/android/ion/ion_system_heap.c b/drivers/staging/android/ion/ion_system_heap.c
index a2ead280ac4e..403dadea5bb2 100644
--- a/drivers/staging/android/ion/ion_system_heap.c
+++ b/drivers/staging/android/ion/ion_system_heap.c
@@ -99,6 +99,11 @@ size_t ion_system_heap_secure_page_pool_total(struct ion_heap *heap,
return total << PAGE_SHIFT;
}
+static int ion_heap_is_system_heap_type(enum ion_heap_type type)
+{
+ return type == ((enum ion_heap_type)ION_HEAP_TYPE_SYSTEM);
+}
+
static struct page *alloc_buffer_page(struct ion_system_heap *heap,
struct ion_buffer *buffer,
unsigned long order,
@@ -352,6 +357,13 @@ static int ion_system_heap_allocate(struct ion_heap *heap,
int vmid = get_secure_vmid(buffer->flags);
struct device *dev = heap->priv;
+ if (ion_heap_is_system_heap_type(buffer->heap->type) &&
+ is_secure_vmid_valid(vmid)) {
+ pr_info("%s: System heap doesn't support secure allocations\n",
+ __func__);
+ return -EINVAL;
+ }
+
if (align > PAGE_SIZE)
return -EINVAL;
diff --git a/drivers/staging/android/ion/ion_system_secure_heap.c b/drivers/staging/android/ion/ion_system_secure_heap.c
index 803811597f37..c7585118a41c 100644
--- a/drivers/staging/android/ion/ion_system_secure_heap.c
+++ b/drivers/staging/android/ion/ion_system_secure_heap.c
@@ -1,6 +1,6 @@
/*
*
- * Copyright (c) 2014-2017, The Linux Foundation. All rights reserved.
+ * Copyright (c) 2014-2018 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
@@ -170,14 +170,15 @@ out:
sys_heap->ops->free(&buffer);
}
-static void process_one_shrink(struct ion_heap *sys_heap,
+static void process_one_shrink(struct ion_system_secure_heap *secure_heap,
+ struct ion_heap *sys_heap,
struct prefetch_info *info)
{
struct ion_buffer buffer;
size_t pool_size, size;
int ret;
- buffer.heap = sys_heap;
+ buffer.heap = &secure_heap->heap;
buffer.flags = info->vmid;
pool_size = ion_system_heap_secure_page_pool_total(sys_heap,
@@ -192,6 +193,7 @@ static void process_one_shrink(struct ion_heap *sys_heap,
}
buffer.private_flags = ION_PRIV_FLAG_SHRINKER_FREE;
+ buffer.heap = sys_heap;
sys_heap->ops->free(&buffer);
}
@@ -211,7 +213,7 @@ static void ion_system_secure_heap_prefetch_work(struct work_struct *work)
spin_unlock_irqrestore(&secure_heap->work_lock, flags);
if (info->shrink)
- process_one_shrink(sys_heap, info);
+ process_one_shrink(secure_heap, sys_heap, info);
else
process_one_prefetch(sys_heap, info);
diff --git a/drivers/staging/android/ion/msm/msm_ion.c b/drivers/staging/android/ion/msm/msm_ion.c
index 7326aa46a8f6..116a6fecaac5 100644
--- a/drivers/staging/android/ion/msm/msm_ion.c
+++ b/drivers/staging/android/ion/msm/msm_ion.c
@@ -678,6 +678,21 @@ int get_secure_vmid(unsigned long flags)
return VMID_CP_SPSS_SP_SHARED;
return -EINVAL;
}
+
+bool is_buffer_hlos_assigned(struct ion_buffer *buffer)
+{
+ bool is_hlos = false;
+
+ if (buffer->heap->type == (enum ion_heap_type)ION_HEAP_TYPE_HYP_CMA &&
+ (buffer->flags & ION_FLAG_CP_HLOS))
+ is_hlos = true;
+
+ if (get_secure_vmid(buffer->flags) <= 0)
+ is_hlos = true;
+
+ return is_hlos;
+}
+
/* fix up the cases where the ioctl direction bits are incorrect */
static unsigned int msm_ion_ioctl_dir(unsigned int cmd)
{
diff --git a/drivers/staging/android/ion/msm/msm_ion.h b/drivers/staging/android/ion/msm/msm_ion.h
index 098104d56fdb..f0f01f92c05c 100644
--- a/drivers/staging/android/ion/msm/msm_ion.h
+++ b/drivers/staging/android/ion/msm/msm_ion.h
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2016, The Linux Foundation. All rights reserved.
+ * Copyright (c) 2016, 2018, 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
@@ -175,6 +175,8 @@ int msm_ion_do_cache_offset_op(
void *vaddr, unsigned int offset, unsigned long len,
unsigned int cmd);
+bool is_buffer_hlos_assigned(struct ion_buffer *buffer);
+
#else
static inline struct ion_client *msm_ion_client_create(const char *name)
{
@@ -202,6 +204,11 @@ int msm_ion_do_cache_offset_op(
return -ENODEV;
}
+static bool is_buffer_hlos_assigned(struct ion_buffer *buffer)
+{
+ return true;
+}
+
#endif /* CONFIG_ION */
#endif
diff --git a/drivers/staging/comedi/drivers/ni_mio_common.c b/drivers/staging/comedi/drivers/ni_mio_common.c
index 8f181caffca3..619c989c5f37 100644
--- a/drivers/staging/comedi/drivers/ni_mio_common.c
+++ b/drivers/staging/comedi/drivers/ni_mio_common.c
@@ -5275,11 +5275,11 @@ static int ni_E_init(struct comedi_device *dev,
/* Digital I/O (PFI) subdevice */
s = &dev->subdevices[NI_PFI_DIO_SUBDEV];
s->type = COMEDI_SUBD_DIO;
- s->subdev_flags = SDF_READABLE | SDF_WRITABLE | SDF_INTERNAL;
s->maxdata = 1;
if (devpriv->is_m_series) {
s->n_chan = 16;
s->insn_bits = ni_pfi_insn_bits;
+ s->subdev_flags = SDF_READABLE | SDF_WRITABLE | SDF_INTERNAL;
ni_writew(dev, s->state, NI_M_PFI_DO_REG);
for (i = 0; i < NUM_PFI_OUTPUT_SELECT_REGS; ++i) {
@@ -5288,6 +5288,7 @@ static int ni_E_init(struct comedi_device *dev,
}
} else {
s->n_chan = 10;
+ s->subdev_flags = SDF_INTERNAL;
}
s->insn_config = ni_pfi_insn_config;
diff --git a/drivers/staging/rts5208/rtsx_scsi.c b/drivers/staging/rts5208/rtsx_scsi.c
index 12a3893b98fd..ade29c4295b7 100644
--- a/drivers/staging/rts5208/rtsx_scsi.c
+++ b/drivers/staging/rts5208/rtsx_scsi.c
@@ -536,7 +536,7 @@ static int inquiry(struct scsi_cmnd *srb, struct rtsx_chip *chip)
if (sendbytes > 8) {
memcpy(buf, inquiry_buf, 8);
- memcpy(buf + 8, inquiry_string, sendbytes - 8);
+ strncpy(buf + 8, inquiry_string, sendbytes - 8);
if (pro_formatter_flag) {
/* Additional Length */
buf[4] = 0x33;
diff --git a/drivers/staging/rts5208/xd.c b/drivers/staging/rts5208/xd.c
index 10fea7bb8f30..3db4a2570b19 100644
--- a/drivers/staging/rts5208/xd.c
+++ b/drivers/staging/rts5208/xd.c
@@ -1252,7 +1252,7 @@ static int xd_copy_page(struct rtsx_chip *chip, u32 old_blk, u32 new_blk,
reg = 0;
rtsx_read_register(chip, XD_CTL, &reg);
if (reg & (XD_ECC1_ERROR | XD_ECC2_ERROR)) {
- wait_timeout(100);
+ mdelay(100);
if (detect_card_cd(chip,
XD_CARD) != STATUS_SUCCESS) {
diff --git a/drivers/target/target_core_transport.c b/drivers/target/target_core_transport.c
index 21f888ac550e..7199bac67333 100644
--- a/drivers/target/target_core_transport.c
+++ b/drivers/target/target_core_transport.c
@@ -306,6 +306,7 @@ void __transport_register_session(
{
const struct target_core_fabric_ops *tfo = se_tpg->se_tpg_tfo;
unsigned char buf[PR_REG_ISID_LEN];
+ unsigned long flags;
se_sess->se_tpg = se_tpg;
se_sess->fabric_sess_ptr = fabric_sess_ptr;
@@ -342,7 +343,7 @@ void __transport_register_session(
se_sess->sess_bin_isid = get_unaligned_be64(&buf[0]);
}
- spin_lock_irq(&se_nacl->nacl_sess_lock);
+ spin_lock_irqsave(&se_nacl->nacl_sess_lock, flags);
/*
* The se_nacl->nacl_sess pointer will be set to the
* last active I_T Nexus for each struct se_node_acl.
@@ -351,7 +352,7 @@ void __transport_register_session(
list_add_tail(&se_sess->sess_acl_list,
&se_nacl->acl_sess_list);
- spin_unlock_irq(&se_nacl->nacl_sess_lock);
+ spin_unlock_irqrestore(&se_nacl->nacl_sess_lock, flags);
}
list_add_tail(&se_sess->sess_list, &se_tpg->tpg_sess_list);
diff --git a/drivers/tty/rocket.c b/drivers/tty/rocket.c
index 802eac7e561b..2b8f2e0a4224 100644
--- a/drivers/tty/rocket.c
+++ b/drivers/tty/rocket.c
@@ -1915,7 +1915,7 @@ static __init int register_PCI(int i, struct pci_dev *dev)
ByteIO_t UPCIRingInd = 0;
if (!dev || !pci_match_id(rocket_pci_ids, dev) ||
- pci_enable_device(dev))
+ pci_enable_device(dev) || i >= NUM_BOARDS)
return 0;
rcktpt_io_addr[i] = pci_resource_start(dev, 0);
diff --git a/drivers/uio/uio.c b/drivers/uio/uio.c
index bcc1fc027311..b9823eb9c195 100644
--- a/drivers/uio/uio.c
+++ b/drivers/uio/uio.c
@@ -833,8 +833,6 @@ int __uio_register_device(struct module *owner,
if (ret)
goto err_uio_dev_add_attributes;
- info->uio_dev = idev;
-
if (info->irq && (info->irq != UIO_IRQ_CUSTOM)) {
/*
* Note that we deliberately don't use devm_request_irq
@@ -850,6 +848,7 @@ int __uio_register_device(struct module *owner,
goto err_request_irq;
}
+ info->uio_dev = idev;
return 0;
err_request_irq:
diff --git a/drivers/usb/class/cdc-wdm.c b/drivers/usb/class/cdc-wdm.c
index 61ea87917433..4380e4f600ab 100644
--- a/drivers/usb/class/cdc-wdm.c
+++ b/drivers/usb/class/cdc-wdm.c
@@ -453,7 +453,7 @@ static int clear_wdm_read_flag(struct wdm_device *desc)
set_bit(WDM_RESPONDING, &desc->flags);
spin_unlock_irq(&desc->iuspin);
- rv = usb_submit_urb(desc->response, GFP_KERNEL);
+ rv = usb_submit_urb(desc->response, GFP_ATOMIC);
spin_lock_irq(&desc->iuspin);
if (rv) {
dev_err(&desc->intf->dev,
diff --git a/drivers/usb/core/hcd-pci.c b/drivers/usb/core/hcd-pci.c
index 40378487e023..a5e3e410db4e 100644
--- a/drivers/usb/core/hcd-pci.c
+++ b/drivers/usb/core/hcd-pci.c
@@ -529,8 +529,6 @@ static int resume_common(struct device *dev, int event)
event == PM_EVENT_RESTORE);
if (retval) {
dev_err(dev, "PCI post-resume error %d!\n", retval);
- if (hcd->shared_hcd)
- usb_hc_died(hcd->shared_hcd);
usb_hc_died(hcd);
}
}
diff --git a/drivers/usb/core/message.c b/drivers/usb/core/message.c
index 7855b3e9a97f..530817c6783d 100644
--- a/drivers/usb/core/message.c
+++ b/drivers/usb/core/message.c
@@ -1283,6 +1283,11 @@ void usb_enable_interface(struct usb_device *dev,
* is submitted that needs that bandwidth. Some other operating systems
* allocate bandwidth early, when a configuration is chosen.
*
+ * xHCI reserves bandwidth and configures the alternate setting in
+ * usb_hcd_alloc_bandwidth(). If it fails the original interface altsetting
+ * may be disabled. Drivers cannot rely on any particular alternate
+ * setting being in effect after a failure.
+ *
* This call is synchronous, and may not be used in an interrupt context.
* Also, drivers must not change altsettings while urbs are scheduled for
* endpoints in that interface; all such urbs must first be completed
@@ -1318,6 +1323,12 @@ int usb_set_interface(struct usb_device *dev, int interface, int alternate)
alternate);
return -EINVAL;
}
+ /*
+ * usb3 hosts configure the interface in usb_hcd_alloc_bandwidth,
+ * including freeing dropped endpoint ring buffers.
+ * Make sure the interface endpoints are flushed before that
+ */
+ usb_disable_interface(dev, iface, false);
/* Make sure we have enough bandwidth for this alternate interface.
* Remove the current alt setting and add the new alt setting.
diff --git a/drivers/usb/core/quirks.c b/drivers/usb/core/quirks.c
index 99f67764765f..37a5e07b3488 100644
--- a/drivers/usb/core/quirks.c
+++ b/drivers/usb/core/quirks.c
@@ -37,6 +37,10 @@ static const struct usb_device_id usb_quirk_list[] = {
/* CBM - Flash disk */
{ USB_DEVICE(0x0204, 0x6025), .driver_info = USB_QUIRK_RESET_RESUME },
+ /* WORLDE Controller KS49 or Prodipe MIDI 49C USB controller */
+ { USB_DEVICE(0x0218, 0x0201), .driver_info =
+ USB_QUIRK_CONFIG_INTF_STRINGS },
+
/* WORLDE easy key (easykey.25) MIDI controller */
{ USB_DEVICE(0x0218, 0x0401), .driver_info =
USB_QUIRK_CONFIG_INTF_STRINGS },
@@ -259,6 +263,9 @@ static const struct usb_device_id usb_quirk_list[] = {
{ USB_DEVICE(0x2040, 0x7200), .driver_info =
USB_QUIRK_CONFIG_INTF_STRINGS },
+ /* DJI CineSSD */
+ { USB_DEVICE(0x2ca3, 0x0031), .driver_info = USB_QUIRK_NO_LPM },
+
/* INTEL VALUE SSD */
{ USB_DEVICE(0x8086, 0xf1a5), .driver_info = USB_QUIRK_RESET_RESUME },
diff --git a/drivers/usb/dwc3/core.h b/drivers/usb/dwc3/core.h
index 9f73ec68a23b..2e56d167ba05 100644
--- a/drivers/usb/dwc3/core.h
+++ b/drivers/usb/dwc3/core.h
@@ -543,6 +543,7 @@ struct dwc3_ep_events {
* @dbg_ep_events: different events counter for endpoint
* @dbg_ep_events_diff: differential events counter for endpoint
* @dbg_ep_events_ts: timestamp for previous event counters
+ * @fifo_depth: allocated TXFIFO depth
*/
struct dwc3_ep {
struct usb_ep endpoint;
@@ -583,6 +584,7 @@ struct dwc3_ep {
struct dwc3_ep_events dbg_ep_events;
struct dwc3_ep_events dbg_ep_events_diff;
struct timespec dbg_ep_events_ts;
+ int fifo_depth;
};
enum dwc3_phy {
@@ -813,7 +815,6 @@ struct dwc3_scratchpad_array {
* @is_fpga: true when we are using the FPGA board
* @needs_fifo_resize: not all users might want fifo resizing, flag it
* @pullups_connected: true when Run/Stop bit is set
- * @resize_fifos: tells us it's ok to reconfigure our TxFIFO sizes.
* @setup_packet_pending: true when there's a Setup Packet in FIFO. Workaround
* @start_config_issued: true when StartConfig command has been issued
* @three_stage_setup: set if we perform a three phase setup
@@ -853,6 +854,7 @@ struct dwc3_scratchpad_array {
* @imod_interval: set the interrupt moderation interval in 250ns
* increments or 0 to disable.
* @create_reg_debugfs: create debugfs entry to allow dwc3 register dump
+ * @last_fifo_depth: total TXFIFO depth of all enabled USB IN/INT endpoints
*/
struct dwc3 {
struct usb_ctrlrequest *ctrl_req;
@@ -988,7 +990,6 @@ struct dwc3 {
unsigned is_fpga:1;
unsigned needs_fifo_resize:1;
unsigned pullups_connected:1;
- unsigned resize_fifos:1;
unsigned setup_packet_pending:1;
unsigned three_stage_setup:1;
unsigned usb3_lpm_capable:1;
@@ -1050,6 +1051,7 @@ struct dwc3 {
wait_queue_head_t wait_linkstate;
bool create_reg_debugfs;
+ int last_fifo_depth;
};
/* -------------------------------------------------------------------------- */
@@ -1199,7 +1201,7 @@ struct dwc3_gadget_ep_cmd_params {
/* prototypes */
void dwc3_set_mode(struct dwc3 *dwc, u32 mode);
-int dwc3_gadget_resize_tx_fifos(struct dwc3 *dwc);
+int dwc3_gadget_resize_tx_fifos(struct dwc3 *dwc, struct dwc3_ep *dep);
/* check whether we are on the DWC_usb3 core */
static inline bool dwc3_is_usb3(struct dwc3 *dwc)
diff --git a/drivers/usb/dwc3/dwc3-msm.c b/drivers/usb/dwc3/dwc3-msm.c
index dc06f4818e39..1e23738e20b3 100644
--- a/drivers/usb/dwc3/dwc3-msm.c
+++ b/drivers/usb/dwc3/dwc3-msm.c
@@ -1132,7 +1132,8 @@ static void gsi_configure_ep(struct usb_ep *ep, struct usb_gsi_request *request)
struct dwc3_gadget_ep_cmd_params params;
const struct usb_endpoint_descriptor *desc = ep->desc;
const struct usb_ss_ep_comp_descriptor *comp_desc = ep->comp_desc;
- u32 reg;
+ u32 reg;
+ int ret;
memset(&params, 0x00, sizeof(params));
@@ -1181,6 +1182,10 @@ static void gsi_configure_ep(struct usb_ep *ep, struct usb_gsi_request *request)
/* Set XferRsc Index for GSI EP */
if (!(dep->flags & DWC3_EP_ENABLED)) {
+ ret = dwc3_gadget_resize_tx_fifos(dwc, dep);
+ if (ret)
+ return;
+
memset(&params, 0x00, sizeof(params));
params.param0 = DWC3_DEPXFERCFG_NUM_XFER_RES(1);
dwc3_send_gadget_ep_cmd(dwc, dep->number,
@@ -3969,7 +3974,10 @@ static void dwc3_otg_sm_work(struct work_struct *w)
mdwc->otg_state = OTG_STATE_A_IDLE;
goto ret;
}
- pm_wakeup_event(mdwc->dev, DWC3_WAKEUP_SRC_TIMEOUT);
+ if (mdwc->no_wakeup_src_in_hostmode) {
+ pm_wakeup_event(mdwc->dev,
+ DWC3_WAKEUP_SRC_TIMEOUT);
+ }
}
break;
@@ -3987,7 +3995,10 @@ static void dwc3_otg_sm_work(struct work_struct *w)
dbg_event(0xFF, "XHCIResume", 0);
if (dwc)
pm_runtime_resume(&dwc->xhci->dev);
- pm_wakeup_event(mdwc->dev, DWC3_WAKEUP_SRC_TIMEOUT);
+ if (mdwc->no_wakeup_src_in_hostmode) {
+ pm_wakeup_event(mdwc->dev,
+ DWC3_WAKEUP_SRC_TIMEOUT);
+ }
}
break;
diff --git a/drivers/usb/dwc3/ep0.c b/drivers/usb/dwc3/ep0.c
index 24ecbc469eb6..1633807aee36 100644
--- a/drivers/usb/dwc3/ep0.c
+++ b/drivers/usb/dwc3/ep0.c
@@ -601,8 +601,9 @@ static int dwc3_ep0_set_config(struct dwc3 *dwc, struct usb_ctrlrequest *ctrl)
{
enum usb_device_state state = dwc->gadget.state;
u32 cfg;
- int ret;
+ int ret, num;
u32 reg;
+ struct dwc3_ep *dep;
cfg = le16_to_cpu(ctrl->wValue);
@@ -611,6 +612,32 @@ static int dwc3_ep0_set_config(struct dwc3 *dwc, struct usb_ctrlrequest *ctrl)
return -EINVAL;
case USB_STATE_ADDRESS:
+ /*
+ * If tx-fifo-resize flag is not set for the controller, then
+ * do not clear existing allocated TXFIFO since we do not
+ * allocate it again in dwc3_gadget_resize_tx_fifos
+ */
+ if (dwc->needs_fifo_resize) {
+ /* Read ep0IN related TXFIFO size */
+ dwc->last_fifo_depth = (dwc3_readl(dwc->regs,
+ DWC3_GTXFIFOSIZ(0)) & 0xFFFF);
+ /* Clear existing TXFIFO for all IN eps except ep0 */
+ for (num = 0; num < dwc->num_in_eps; num++) {
+ dep = dwc->eps[(num << 1) | 1];
+ if (num) {
+ dwc3_writel(dwc->regs,
+ DWC3_GTXFIFOSIZ(num), 0);
+ dep->fifo_depth = 0;
+ } else {
+ dep->fifo_depth = dwc->last_fifo_depth;
+ }
+
+ dev_dbg(dwc->dev, "%s(): %s fifo_depth:%x\n",
+ __func__, dep->name, dep->fifo_depth);
+ dbg_event(0xFF, "fifo_reset", dep->number);
+ }
+ }
+
ret = dwc3_ep0_delegate_req(dwc, ctrl);
/* if the cfg matches and the cfg is non zero */
if (cfg && (!ret || (ret == USB_GADGET_DELAYED_STATUS))) {
@@ -635,9 +662,6 @@ static int dwc3_ep0_set_config(struct dwc3 *dwc, struct usb_ctrlrequest *ctrl)
DWC3_DCTL_ACCEPTU2ENA);
dwc3_writel(dwc->regs, DWC3_DCTL, reg);
}
-
- dwc->resize_fifos = true;
- dwc3_trace(trace_dwc3_ep0, "resize FIFOs flag SET");
}
break;
@@ -1085,11 +1109,6 @@ static int dwc3_ep0_start_control_status(struct dwc3_ep *dep)
static void __dwc3_ep0_do_control_status(struct dwc3 *dwc, struct dwc3_ep *dep)
{
int ret;
- if (dwc->resize_fifos) {
- dwc3_trace(trace_dwc3_ep0, "Resizing FIFOs");
- dwc3_gadget_resize_tx_fifos(dwc);
- dwc->resize_fifos = 0;
- }
ret = dwc3_ep0_start_control_status(dep);
if (WARN_ON_ONCE(ret))
diff --git a/drivers/usb/dwc3/gadget.c b/drivers/usb/dwc3/gadget.c
index f6117ac0e301..48bfe2aaef1a 100644
--- a/drivers/usb/dwc3/gadget.c
+++ b/drivers/usb/dwc3/gadget.c
@@ -172,88 +172,65 @@ int dwc3_gadget_set_link_state(struct dwc3 *dwc, enum dwc3_link_state state)
*
* Unfortunately, due to many variables that's not always the case.
*/
-int dwc3_gadget_resize_tx_fifos(struct dwc3 *dwc)
-{
- int last_fifo_depth = 0;
- int ram1_depth;
- int fifo_size;
- int mdwidth;
- int num;
- int num_eps;
- int max_packet = 1024;
- struct usb_composite_dev *cdev = get_gadget_data(&dwc->gadget);
-
- if (!(cdev && cdev->config) || !dwc->needs_fifo_resize)
+int dwc3_gadget_resize_tx_fifos(struct dwc3 *dwc, struct dwc3_ep *dep)
+{
+ int fifo_size, mdwidth, max_packet = 1024;
+ int tmp, mult = 1;
+
+ if (!dwc->needs_fifo_resize)
return 0;
- num_eps = dwc->num_in_eps;
- ram1_depth = DWC3_RAM1_DEPTH(dwc->hwparams.hwparams7);
- mdwidth = DWC3_MDWIDTH(dwc->hwparams.hwparams0);
+ /* resize IN endpoints excepts ep0 */
+ if (!usb_endpoint_dir_in(dep->endpoint.desc) ||
+ dep->endpoint.ep_num == 0)
+ return 0;
+ /* Don't resize already resized IN endpoint */
+ if (dep->fifo_depth) {
+ dev_dbg(dwc->dev, "%s fifo_depth:%d is already set\n",
+ dep->endpoint.name, dep->fifo_depth);
+ return 0;
+ }
+
+ mdwidth = DWC3_MDWIDTH(dwc->hwparams.hwparams0);
/* MDWIDTH is represented in bits, we need it in bytes */
mdwidth >>= 3;
- last_fifo_depth = (dwc3_readl(dwc->regs, DWC3_GTXFIFOSIZ(0)) & 0xFFFF);
- dev_dbg(dwc->dev, "%s: num eps:%d max_packet:%d last_fifo_depth:%04x\n",
- __func__, num_eps, max_packet, last_fifo_depth);
-
- /* Don't resize ep0IN TxFIFO, start with ep1IN only. */
- for (num = 1; num < num_eps; num++) {
- /* bit0 indicates direction; 1 means IN ep */
- struct dwc3_ep *dep = dwc->eps[(num << 1) | 1];
- int mult = 1;
- int tmp;
-
- tmp = max_packet + mdwidth;
- /*
- * Interfaces like MBIM or ECM is having multiple data
- * interfaces. SET_CONFIG() happens before set_alt with
- * data interface 1 which results into calling this API
- * before GSI endpoint enabled. This results no txfifo
- * resize with GSI endpoint causing low throughput. Hence
- * use mult as 3 for GSI IN endpoint always irrespective
- * USB speed.
- */
- if (dep->endpoint.ep_type == EP_TYPE_GSI ||
- dep->endpoint.endless)
- mult = 3;
-
- if (!(dep->flags & DWC3_EP_ENABLED)) {
- dev_dbg(dwc->dev, "ep%dIn not enabled", num);
- goto resize_fifo;
- }
-
- if (((dep->endpoint.maxburst > 1) &&
- usb_endpoint_xfer_bulk(dep->endpoint.desc))
- || usb_endpoint_xfer_isoc(dep->endpoint.desc))
- mult = 3;
-
-resize_fifo:
- tmp *= mult;
- tmp += mdwidth;
-
- fifo_size = DIV_ROUND_UP(tmp, mdwidth);
-
- fifo_size |= (last_fifo_depth << 16);
-
- dwc3_trace(trace_dwc3_gadget, "%s: Fifo Addr %04x Size %d",
- dep->name, last_fifo_depth, fifo_size & 0xffff);
-
- last_fifo_depth += (fifo_size & 0xffff);
- if (dwc->tx_fifo_size &&
- (last_fifo_depth >= dwc->tx_fifo_size)) {
- /*
- * Fifo size allocated exceeded available RAM size.
- * Hence return error.
- */
- dev_err(dwc->dev, "Fifosize(%d) > available RAM(%d)\n",
- last_fifo_depth, dwc->tx_fifo_size);
- return -ENOMEM;
- }
-
- dwc3_writel(dwc->regs, DWC3_GTXFIFOSIZ(num), fifo_size);
+ if (dep->endpoint.ep_type == EP_TYPE_GSI || dep->endpoint.endless)
+ mult = 3;
+
+ if (((dep->endpoint.maxburst > 1) &&
+ usb_endpoint_xfer_bulk(dep->endpoint.desc))
+ || usb_endpoint_xfer_isoc(dep->endpoint.desc))
+ mult = 3;
+
+ tmp = ((max_packet + mdwidth) * mult) + mdwidth;
+ fifo_size = DIV_ROUND_UP(tmp, mdwidth);
+ dep->fifo_depth = fifo_size;
+ fifo_size |= (dwc3_readl(dwc->regs, DWC3_GTXFIFOSIZ(0)) & 0xffff0000)
+ + (dwc->last_fifo_depth << 16);
+ dwc->last_fifo_depth += (fifo_size & 0xffff);
+
+ dev_dbg(dwc->dev, "%s ep_num:%d last_fifo_depth:%04x fifo_depth:%d\n",
+ dep->endpoint.name, dep->endpoint.ep_num, dwc->last_fifo_depth,
+ dep->fifo_depth);
+
+ dbg_event(0xFF, "resize_fifo", dep->number);
+ dbg_event(0xFF, "fifo_depth", dep->fifo_depth);
+ /* Check fifo size allocation doesn't exceed available RAM size. */
+ if (dwc->tx_fifo_size &&
+ ((dwc->last_fifo_depth * mdwidth) >= dwc->tx_fifo_size)) {
+ dev_err(dwc->dev, "Fifosize(%d) > RAM size(%d) %s depth:%d\n",
+ (dwc->last_fifo_depth * mdwidth), dwc->tx_fifo_size,
+ dep->endpoint.name, fifo_size);
+ dwc->last_fifo_depth -= (fifo_size & 0xffff);
+ dep->fifo_depth = 0;
+ WARN_ON(1);
+ return -ENOMEM;
}
+ dwc3_writel(dwc->regs, DWC3_GTXFIFOSIZ(dep->endpoint.ep_num),
+ fifo_size);
return 0;
}
@@ -622,6 +599,17 @@ static int __dwc3_gadget_ep_enable(struct dwc3_ep *dep,
dwc3_trace(trace_dwc3_gadget, "Enabling %s", dep->name);
if (!(dep->flags & DWC3_EP_ENABLED)) {
+ dep->endpoint.desc = desc;
+ dep->comp_desc = comp_desc;
+ dep->type = usb_endpoint_type(desc);
+ ret = dwc3_gadget_resize_tx_fifos(dwc, dep);
+ if (ret) {
+ dep->endpoint.desc = NULL;
+ dep->comp_desc = NULL;
+ dep->type = 0;
+ return ret;
+ }
+
ret = dwc3_gadget_start_config(dwc, dep);
if (ret) {
dev_err(dwc->dev, "start_config() failed for %s\n",
@@ -641,9 +629,6 @@ static int __dwc3_gadget_ep_enable(struct dwc3_ep *dep,
struct dwc3_trb *trb_st_hw;
struct dwc3_trb *trb_link;
- dep->endpoint.desc = desc;
- dep->comp_desc = comp_desc;
- dep->type = usb_endpoint_type(desc);
dep->flags |= DWC3_EP_ENABLED;
reg = dwc3_readl(dwc->regs, DWC3_DALEPENA);
@@ -2894,9 +2879,6 @@ static void dwc3_gadget_reset_interrupt(struct dwc3 *dwc)
dwc3_stop_active_transfers(dwc);
dwc3_clear_stall_all_ep(dwc);
- /* bus reset issued due to missing status stage of a control transfer */
- dwc->resize_fifos = 0;
-
/* Reset device address to zero */
reg = dwc3_readl(dwc->regs, DWC3_DCFG);
reg &= ~(DWC3_DCFG_DEVADDR_MASK);
diff --git a/drivers/usb/gadget/udc/net2280.c b/drivers/usb/gadget/udc/net2280.c
index a47de8c31ce9..8efeadf30b4d 100644
--- a/drivers/usb/gadget/udc/net2280.c
+++ b/drivers/usb/gadget/udc/net2280.c
@@ -1542,11 +1542,14 @@ static int net2280_pullup(struct usb_gadget *_gadget, int is_on)
writel(tmp | BIT(USB_DETECT_ENABLE), &dev->usb->usbctl);
} else {
writel(tmp & ~BIT(USB_DETECT_ENABLE), &dev->usb->usbctl);
- stop_activity(dev, dev->driver);
+ stop_activity(dev, NULL);
}
spin_unlock_irqrestore(&dev->lock, flags);
+ if (!is_on && dev->driver)
+ dev->driver->disconnect(&dev->gadget);
+
return 0;
}
@@ -2425,8 +2428,11 @@ static void stop_activity(struct net2280 *dev, struct usb_gadget_driver *driver)
nuke(&dev->ep[i]);
/* report disconnect; the driver is already quiesced */
- if (driver)
+ if (driver) {
+ spin_unlock(&dev->lock);
driver->disconnect(&dev->gadget);
+ spin_lock(&dev->lock);
+ }
usb_reinit(dev);
}
@@ -3272,6 +3278,8 @@ next_endpoints:
BIT(PCI_RETRY_ABORT_INTERRUPT))
static void handle_stat1_irqs(struct net2280 *dev, u32 stat)
+__releases(dev->lock)
+__acquires(dev->lock)
{
struct net2280_ep *ep;
u32 tmp, num, mask, scratch;
@@ -3312,12 +3320,14 @@ static void handle_stat1_irqs(struct net2280 *dev, u32 stat)
if (disconnect || reset) {
stop_activity(dev, dev->driver);
ep0_start(dev);
+ spin_unlock(&dev->lock);
if (reset)
usb_gadget_udc_reset
(&dev->gadget, dev->driver);
else
(dev->driver->disconnect)
(&dev->gadget);
+ spin_lock(&dev->lock);
return;
}
}
@@ -3336,6 +3346,7 @@ static void handle_stat1_irqs(struct net2280 *dev, u32 stat)
tmp = BIT(SUSPEND_REQUEST_CHANGE_INTERRUPT);
if (stat & tmp) {
writel(tmp, &dev->regs->irqstat1);
+ spin_unlock(&dev->lock);
if (stat & BIT(SUSPEND_REQUEST_INTERRUPT)) {
if (dev->driver->suspend)
dev->driver->suspend(&dev->gadget);
@@ -3346,6 +3357,7 @@ static void handle_stat1_irqs(struct net2280 *dev, u32 stat)
dev->driver->resume(&dev->gadget);
/* at high speed, note erratum 0133 */
}
+ spin_lock(&dev->lock);
stat &= ~tmp;
}
diff --git a/drivers/usb/host/u132-hcd.c b/drivers/usb/host/u132-hcd.c
index 692ccc69345e..d5434e7a3b2e 100644
--- a/drivers/usb/host/u132-hcd.c
+++ b/drivers/usb/host/u132-hcd.c
@@ -2565,7 +2565,7 @@ static int u132_get_frame(struct usb_hcd *hcd)
} else {
int frame = 0;
dev_err(&u132->platform_dev->dev, "TODO: u132_get_frame\n");
- msleep(100);
+ mdelay(100);
return frame;
}
}
diff --git a/drivers/usb/host/xhci.c b/drivers/usb/host/xhci.c
index 91af817278e3..abe6d3c17047 100644
--- a/drivers/usb/host/xhci.c
+++ b/drivers/usb/host/xhci.c
@@ -3700,6 +3700,9 @@ void xhci_free_dev(struct usb_hcd *hcd, struct usb_device *udev)
virt_dev->udev = NULL;
spin_lock_irqsave(&xhci->lock, flags);
+
+ virt_dev->udev = NULL;
+
/* Don't disable the slot if the host controller is dead. */
state = readl(&xhci->op_regs->status);
if (state == 0xffffffff || (xhci->xhc_state & XHCI_STATE_DYING) ||
diff --git a/drivers/usb/misc/Kconfig b/drivers/usb/misc/Kconfig
index 4670e2f4c2de..278df845f066 100644
--- a/drivers/usb/misc/Kconfig
+++ b/drivers/usb/misc/Kconfig
@@ -279,13 +279,24 @@ config USB_QTI_KS_BRIDGE
To compile this driver as a module, choose M here: the module
will be called ks_bridge. If unsure, choose N.
+config USB_QCOM_IPC_BRIDGE
+ tristate "USB QTI IPC bridge driver"
+ depends on USB
+ depends on USB_QCOM_DIAG_BRIDGE
+ help
+ Say Y here if you have a QTI modem device connected via USB that
+ will be bridged in kernel space. This driver works as a transport
+ layer for IPC router module that enables communication between
+ APPS processor and MODEM processor.
+
config USB_QCOM_DIAG_BRIDGE
tristate "USB QTI diagnostic bridge driver"
depends on USB
+ select USB_QCOM_IPC_BRIDGE
help
Say Y here if you have a QTI modem device connected via USB that
will be bridged in kernel space. This driver communicates with the
- diagnostic and QMI interfaces and allows for bridging with the diag
- forwarding driver for diag interface and IPC router for QMI interface.
+ diagnostic interface and allows for bridging with the diag forwarding
+ driver.
To compile this driver as a module, choose M here: the
module will be called diag_bridge. If unsure, choose N.
diff --git a/drivers/usb/misc/uss720.c b/drivers/usb/misc/uss720.c
index 442b6631162e..3d750671b85a 100644
--- a/drivers/usb/misc/uss720.c
+++ b/drivers/usb/misc/uss720.c
@@ -388,7 +388,7 @@ static unsigned char parport_uss720_frob_control(struct parport *pp, unsigned ch
mask &= 0x0f;
val &= 0x0f;
d = (priv->reg[1] & (~mask)) ^ val;
- if (set_1284_register(pp, 2, d, GFP_KERNEL))
+ if (set_1284_register(pp, 2, d, GFP_ATOMIC))
return 0;
priv->reg[1] = d;
return d & 0xf;
@@ -398,7 +398,7 @@ static unsigned char parport_uss720_read_status(struct parport *pp)
{
unsigned char ret;
- if (get_1284_register(pp, 1, &ret, GFP_KERNEL))
+ if (get_1284_register(pp, 1, &ret, GFP_ATOMIC))
return 0;
return ret & 0xf8;
}
diff --git a/drivers/usb/misc/yurex.c b/drivers/usb/misc/yurex.c
index 512c84adcace..e8e8702d5adf 100644
--- a/drivers/usb/misc/yurex.c
+++ b/drivers/usb/misc/yurex.c
@@ -439,13 +439,13 @@ static ssize_t yurex_write(struct file *file, const char __user *user_buffer,
{
struct usb_yurex *dev;
int i, set = 0, retval = 0;
- char buffer[16];
+ char buffer[16 + 1];
char *data = buffer;
unsigned long long c, c2 = 0;
signed long timeout = 0;
DEFINE_WAIT(wait);
- count = min(sizeof(buffer), count);
+ count = min(sizeof(buffer) - 1, count);
dev = file->private_data;
/* verify that we actually have some data to write */
@@ -464,6 +464,7 @@ static ssize_t yurex_write(struct file *file, const char __user *user_buffer,
retval = -EFAULT;
goto error;
}
+ buffer[count] = 0;
memset(dev->cntl_buffer, CMD_PADDING, YUREX_BUF_SIZE);
switch (buffer[0]) {
diff --git a/drivers/usb/serial/io_ti.h b/drivers/usb/serial/io_ti.h
index 1bd67b24f916..bc9ff5ebd67c 100644
--- a/drivers/usb/serial/io_ti.h
+++ b/drivers/usb/serial/io_ti.h
@@ -178,7 +178,7 @@ struct ump_interrupt {
} __attribute__((packed));
-#define TIUMP_GET_PORT_FROM_CODE(c) (((c) >> 4) - 3)
+#define TIUMP_GET_PORT_FROM_CODE(c) (((c) >> 6) & 0x01)
#define TIUMP_GET_FUNC_FROM_CODE(c) ((c) & 0x0f)
#define TIUMP_INTERRUPT_CODE_LSR 0x03
#define TIUMP_INTERRUPT_CODE_MSR 0x04
diff --git a/drivers/usb/serial/ti_usb_3410_5052.h b/drivers/usb/serial/ti_usb_3410_5052.h
index 98f35c656c02..0cd247f75b8b 100644
--- a/drivers/usb/serial/ti_usb_3410_5052.h
+++ b/drivers/usb/serial/ti_usb_3410_5052.h
@@ -227,7 +227,7 @@ struct ti_interrupt {
} __attribute__((packed));
/* Interrupt codes */
-#define TI_GET_PORT_FROM_CODE(c) (((c) >> 4) - 3)
+#define TI_GET_PORT_FROM_CODE(c) (((c) >> 6) & 0x01)
#define TI_GET_FUNC_FROM_CODE(c) ((c) & 0x0f)
#define TI_CODE_HARDWARE_ERROR 0xFF
#define TI_CODE_DATA_ERROR 0x03
diff --git a/drivers/usb/storage/scsiglue.c b/drivers/usb/storage/scsiglue.c
index dba51362d2e2..6c186b4df94a 100644
--- a/drivers/usb/storage/scsiglue.c
+++ b/drivers/usb/storage/scsiglue.c
@@ -341,6 +341,15 @@ static int queuecommand_lck(struct scsi_cmnd *srb,
return 0;
}
+ if ((us->fflags & US_FL_NO_ATA_1X) &&
+ (srb->cmnd[0] == ATA_12 || srb->cmnd[0] == ATA_16)) {
+ memcpy(srb->sense_buffer, usb_stor_sense_invalidCDB,
+ sizeof(usb_stor_sense_invalidCDB));
+ srb->result = SAM_STAT_CHECK_CONDITION;
+ done(srb);
+ return 0;
+ }
+
/* enqueue the command and wake up the control thread */
srb->scsi_done = done;
us->srb = srb;
diff --git a/drivers/usb/storage/unusual_devs.h b/drivers/usb/storage/unusual_devs.h
index 1a34d2a89de6..898215cad351 100644
--- a/drivers/usb/storage/unusual_devs.h
+++ b/drivers/usb/storage/unusual_devs.h
@@ -2213,6 +2213,13 @@ UNUSUAL_DEV( 0x4146, 0xba01, 0x0100, 0x0100,
"Micro Mini 1GB",
USB_SC_DEVICE, USB_PR_DEVICE, NULL, US_FL_NOT_LOCKABLE ),
+/* Reported-by: Tim Anderson <tsa@biglakesoftware.com> */
+UNUSUAL_DEV( 0x2ca3, 0x0031, 0x0000, 0x9999,
+ "DJI",
+ "CineSSD",
+ USB_SC_DEVICE, USB_PR_DEVICE, NULL,
+ US_FL_NO_ATA_1X),
+
/*
* Nick Bowler <nbowler@elliptictech.com>
* SCSI stack spams (otherwise harmless) error messages.
diff --git a/drivers/video/fbdev/core/modedb.c b/drivers/video/fbdev/core/modedb.c
index 2510fa728d77..de119f11b78f 100644
--- a/drivers/video/fbdev/core/modedb.c
+++ b/drivers/video/fbdev/core/modedb.c
@@ -644,7 +644,7 @@ static int fb_try_mode(struct fb_var_screeninfo *var, struct fb_info *info,
*
* Valid mode specifiers for @mode_option:
*
- * <xres>x<yres>[M][R][-<bpp>][@<refresh>][i][m] or
+ * <xres>x<yres>[M][R][-<bpp>][@<refresh>][i][p][m] or
* <name>[-<bpp>][@<refresh>]
*
* with <xres>, <yres>, <bpp> and <refresh> decimal numbers and
@@ -653,10 +653,10 @@ static int fb_try_mode(struct fb_var_screeninfo *var, struct fb_info *info,
* If 'M' is present after yres (and before refresh/bpp if present),
* the function will compute the timings using VESA(tm) Coordinated
* Video Timings (CVT). If 'R' is present after 'M', will compute with
- * reduced blanking (for flatpanels). If 'i' is present, compute
- * interlaced mode. If 'm' is present, add margins equal to 1.8%
- * of xres rounded down to 8 pixels, and 1.8% of yres. The char
- * 'i' and 'm' must be after 'M' and 'R'. Example:
+ * reduced blanking (for flatpanels). If 'i' or 'p' are present, compute
+ * interlaced or progressive mode. If 'm' is present, add margins equal
+ * to 1.8% of xres rounded down to 8 pixels, and 1.8% of yres. The chars
+ * 'i', 'p' and 'm' must be after 'M' and 'R'. Example:
*
* 1024x768MR-8@60m - Reduced blank with margins at 60Hz.
*
@@ -697,7 +697,8 @@ int fb_find_mode(struct fb_var_screeninfo *var,
unsigned int namelen = strlen(name);
int res_specified = 0, bpp_specified = 0, refresh_specified = 0;
unsigned int xres = 0, yres = 0, bpp = default_bpp, refresh = 0;
- int yres_specified = 0, cvt = 0, rb = 0, interlace = 0;
+ int yres_specified = 0, cvt = 0, rb = 0;
+ int interlace_specified = 0, interlace = 0;
int margins = 0;
u32 best, diff, tdiff;
@@ -748,9 +749,17 @@ int fb_find_mode(struct fb_var_screeninfo *var,
if (!cvt)
margins = 1;
break;
+ case 'p':
+ if (!cvt) {
+ interlace = 0;
+ interlace_specified = 1;
+ }
+ break;
case 'i':
- if (!cvt)
+ if (!cvt) {
interlace = 1;
+ interlace_specified = 1;
+ }
break;
default:
goto done;
@@ -819,11 +828,21 @@ done:
if ((name_matches(db[i], name, namelen) ||
(res_specified && res_matches(db[i], xres, yres))) &&
!fb_try_mode(var, info, &db[i], bpp)) {
- if (refresh_specified && db[i].refresh == refresh)
- return 1;
+ const int db_interlace = (db[i].vmode &
+ FB_VMODE_INTERLACED ? 1 : 0);
+ int score = abs(db[i].refresh - refresh);
+
+ if (interlace_specified)
+ score += abs(db_interlace - interlace);
+
+ if (!interlace_specified ||
+ db_interlace == interlace)
+ if (refresh_specified &&
+ db[i].refresh == refresh)
+ return 1;
- if (abs(db[i].refresh - refresh) < diff) {
- diff = abs(db[i].refresh - refresh);
+ if (score < diff) {
+ diff = score;
best = i;
}
}
diff --git a/drivers/video/fbdev/goldfishfb.c b/drivers/video/fbdev/goldfishfb.c
index 88adb2970b44..39662b2e3537 100644
--- a/drivers/video/fbdev/goldfishfb.c
+++ b/drivers/video/fbdev/goldfishfb.c
@@ -368,6 +368,7 @@ static int goldfish_fb_remove(struct platform_device *pdev)
dma_free_coherent(&pdev->dev, framesize, (void *)fb->fb.screen_base,
fb->fb.fix.smem_start);
iounmap(fb->reg_base);
+ kfree(fb);
return 0;
}
diff --git a/drivers/video/fbdev/msm/mdss_debug.c b/drivers/video/fbdev/msm/mdss_debug.c
index 230b02061b39..e9989fbdd2ba 100644
--- a/drivers/video/fbdev/msm/mdss_debug.c
+++ b/drivers/video/fbdev/msm/mdss_debug.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2009-2017, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2009-2018, 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
@@ -433,6 +433,39 @@ static int mdss_debug_base_release(struct inode *inode, struct file *file)
return 0;
}
+/**
+ * mdss_debug_base_is_valid_range - verify if requested memory range is valid
+ * @off: address offset in bytes
+ * @cnt: memory size in bytes
+ * Return: true if valid; false otherwise
+ */
+static bool mdss_debug_base_is_valid_range(u32 off, u32 cnt)
+{
+ struct mdss_data_type *mdata = mdss_mdp_get_mdata();
+ struct mdss_debug_data *mdd = mdata->debug_inf.debug_data;
+ struct range_dump_node *node;
+ struct mdss_debug_base *base;
+
+ pr_debug("check offset=0x%x cnt=0x%x\n", off, cnt);
+
+ list_for_each_entry(base, &mdd->base_list, head) {
+ list_for_each_entry(node, &base->dump_list, head) {
+ pr_debug("%s: start=0x%x end=0x%x\n", node->range_name,
+ node->offset.start, node->offset.end);
+
+ if (node->offset.start <= off
+ && off <= node->offset.end
+ && off + cnt <= node->offset.end) {
+ pr_debug("valid range requested\n");
+ return true;
+ }
+ }
+ }
+
+ pr_err("invalid range requested\n");
+ return false;
+}
+
static ssize_t mdss_debug_base_offset_write(struct file *file,
const char __user *user_buf, size_t count, loff_t *ppos)
{
@@ -452,7 +485,8 @@ static ssize_t mdss_debug_base_offset_write(struct file *file,
buf[count] = 0; /* end of string */
- sscanf(buf, "%5x %x", &off, &cnt);
+ if (sscanf(buf, "%5x %x", &off, &cnt) != 2)
+ return -EFAULT;
if (off % sizeof(u32))
return -EINVAL;
@@ -463,6 +497,9 @@ static ssize_t mdss_debug_base_offset_write(struct file *file,
if (cnt > (dbg->max_offset - off))
cnt = dbg->max_offset - off;
+ if (!mdss_debug_base_is_valid_range(off, cnt))
+ return -EINVAL;
+
mutex_lock(&mdss_debug_lock);
dbg->off = off;
dbg->cnt = cnt;
diff --git a/drivers/video/fbdev/msm/mdss_dsi_panel.c b/drivers/video/fbdev/msm/mdss_dsi_panel.c
index 5ba0480436a2..bf695ae0beaf 100644
--- a/drivers/video/fbdev/msm/mdss_dsi_panel.c
+++ b/drivers/video/fbdev/msm/mdss_dsi_panel.c
@@ -1803,17 +1803,13 @@ static bool mdss_dsi_cmp_panel_reg_v2(struct mdss_dsi_ctrl_pdata *ctrl)
for (i = 0; i < ctrl->status_cmds.cmd_cnt; i++)
len += lenp[i];
- for (i = 0; i < len; i++) {
- pr_debug("[%i] return:0x%x status:0x%x\n",
- i, (unsigned int)ctrl->return_buf[i],
- (unsigned int)ctrl->status_value[j + i]);
- MDSS_XLOG(ctrl->ndx, ctrl->return_buf[i],
- ctrl->status_value[j + i]);
- j += len;
- }
-
for (j = 0; j < ctrl->groups; ++j) {
for (i = 0; i < len; ++i) {
+ pr_debug("[%i] return:0x%x status:0x%x\n",
+ i, ctrl->return_buf[i],
+ (unsigned int)ctrl->status_value[group + i]);
+ MDSS_XLOG(ctrl->ndx, ctrl->return_buf[i],
+ ctrl->status_value[group + i]);
if (ctrl->return_buf[i] !=
ctrl->status_value[group + i])
break;
diff --git a/drivers/video/fbdev/msm/mdss_mdp_ctl.c b/drivers/video/fbdev/msm/mdss_mdp_ctl.c
index ec56bcf6e64e..710aebbd9c59 100644
--- a/drivers/video/fbdev/msm/mdss_mdp_ctl.c
+++ b/drivers/video/fbdev/msm/mdss_mdp_ctl.c
@@ -77,13 +77,15 @@ static inline u64 fudge_factor(u64 val, u32 numer, u32 denom)
u64 result = val;
if (val) {
- u64 temp = -1UL;
+ u64 temp = U64_MAX;
do_div(temp, val);
if (temp > numer) {
/* no overflow, so we can do the operation*/
result = (val * (u64)numer);
do_div(result, denom);
+ } else {
+ pr_warn("Overflow, skip fudge factor\n");
}
}
return result;
@@ -4892,7 +4894,8 @@ static inline void __mdss_mdp_mixer_write_layer(struct mdss_mdp_ctl *ctl,
u32 off[NUM_MIXERCFG_REGS];
int i;
- BUG_ON(!values || count < NUM_MIXERCFG_REGS);
+ if (WARN_ON(!values || count < NUM_MIXERCFG_REGS))
+ return;
__mdss_mdp_mixer_get_offsets(mixer_num, off, ARRAY_SIZE(off));
diff --git a/drivers/video/fbdev/msm/mdss_mdp_intf_cmd.c b/drivers/video/fbdev/msm/mdss_mdp_intf_cmd.c
index a259ddda2ce2..83ab9c3973af 100644
--- a/drivers/video/fbdev/msm/mdss_mdp_intf_cmd.c
+++ b/drivers/video/fbdev/msm/mdss_mdp_intf_cmd.c
@@ -738,8 +738,16 @@ int mdss_mdp_resource_control(struct mdss_mdp_ctl *ctl, u32 sw_event)
int rc = 0;
bool schedule_off = false;
+ if (!ctl) {
+ pr_err("%s invalid ctl\n", __func__);
+ rc = -EINVAL;
+ goto exit;
+ }
+
/* Get both controllers in the correct order for dual displays */
- mdss_mdp_get_split_display_ctls(&ctl, &sctl);
+ rc = mdss_mdp_get_split_display_ctls(&ctl, &sctl);
+ if (rc)
+ goto exit;
ctx = (struct mdss_mdp_cmd_ctx *) ctl->intf_ctx[MASTER_CTX];
if (!ctx) {
diff --git a/drivers/video/fbdev/msm/msm_dba/adv7533.c b/drivers/video/fbdev/msm/msm_dba/adv7533.c
index a21b6db85ed8..7878276a06ef 100644
--- a/drivers/video/fbdev/msm/msm_dba/adv7533.c
+++ b/drivers/video/fbdev/msm/msm_dba/adv7533.c
@@ -1530,6 +1530,7 @@ static void adv7533_video_setup(struct adv7533 *pdata,
{
u32 h_total, hpw, hfp, hbp;
u32 v_total, vpw, vfp, vbp;
+ int dsi_pixel_clock_divider = 0x00;
if (!pdata || !cfg) {
pr_err("%s: invalid input\n", __func__);
@@ -1557,6 +1558,26 @@ static void adv7533_video_setup(struct adv7533 *pdata,
v_total, cfg->v_active, cfg->v_front_porch,
cfg->v_pulse_width, cfg->v_back_porch);
+ /* 0x16: dsi pclk divider control.
+ * bit2: 1 = manual dsi pclk divider control; 0 = automatic dsi
+ * pclk divider generation.
+ * bit3-7: the signal sets the dsi pclk divider setting when bit2
+ * is enable.
+ *
+ * If bit2=0 means automatically select dsi pclk divider, so
+ * other bits(divider factor) has no impact.
+ *
+ * If bit2=1, the divider factor should be related to lane num below
+ * 4lanes : divide by 3; 3lanes : divide by 4; 2lanes : divide by 6
+ * So the value of 0x16 can be set as follow:
+ * 4 lanes : 0x1C(00011 100)
+ * 3 lanes : 0x24(00100 100)
+ * 2 lanes : 0x34(00110 100)
+ *
+ * Here, use automatic dsi pclk divider generation, so set 0x00
+ * to cec 0x16 register for all lanes numbers.
+ */
+ adv7533_write(pdata, I2C_ADDR_CEC_DSI, 0x16, dsi_pixel_clock_divider);
/* h_width */
adv7533_write(pdata, I2C_ADDR_CEC_DSI, 0x28, ((h_total & 0xFF0) >> 4));
diff --git a/drivers/video/fbdev/omap/omapfb_main.c b/drivers/video/fbdev/omap/omapfb_main.c
index 393ae1bc07e8..a8a6f072fb78 100644
--- a/drivers/video/fbdev/omap/omapfb_main.c
+++ b/drivers/video/fbdev/omap/omapfb_main.c
@@ -977,7 +977,7 @@ int omapfb_register_client(struct omapfb_notifier_block *omapfb_nb,
{
int r;
- if ((unsigned)omapfb_nb->plane_idx > OMAPFB_PLANE_NUM)
+ if ((unsigned)omapfb_nb->plane_idx >= OMAPFB_PLANE_NUM)
return -EINVAL;
if (!notifier_inited) {
diff --git a/drivers/video/fbdev/via/viafbdev.c b/drivers/video/fbdev/via/viafbdev.c
index badee04ef496..71b5dca95bdb 100644
--- a/drivers/video/fbdev/via/viafbdev.c
+++ b/drivers/video/fbdev/via/viafbdev.c
@@ -19,6 +19,7 @@
* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
+#include <linux/compiler.h>
#include <linux/module.h>
#include <linux/seq_file.h>
#include <linux/slab.h>
@@ -1468,7 +1469,7 @@ static const struct file_operations viafb_vt1636_proc_fops = {
#endif /* CONFIG_FB_VIA_DIRECT_PROCFS */
-static int viafb_sup_odev_proc_show(struct seq_file *m, void *v)
+static int __maybe_unused viafb_sup_odev_proc_show(struct seq_file *m, void *v)
{
via_odev_to_seq(m, supported_odev_map[
viaparinfo->shared->chip_info.gfx_chip_name]);
diff --git a/fs/autofs4/autofs_i.h b/fs/autofs4/autofs_i.h
index 502d3892d8a4..d71e7ad4d382 100644
--- a/fs/autofs4/autofs_i.h
+++ b/fs/autofs4/autofs_i.h
@@ -18,6 +18,7 @@
#include <linux/mutex.h>
#include <linux/spinlock.h>
#include <linux/list.h>
+#include <linux/magic.h>
/* This is the range of ioctl() numbers we claim as ours */
#define AUTOFS_IOC_FIRST AUTOFS_IOC_READY
@@ -135,7 +136,8 @@ struct autofs_sb_info {
static inline struct autofs_sb_info *autofs4_sbi(struct super_block *sb)
{
- return (struct autofs_sb_info *)(sb->s_fs_info);
+ return sb->s_magic != AUTOFS_SUPER_MAGIC ?
+ NULL : (struct autofs_sb_info *)(sb->s_fs_info);
}
static inline struct autofs_info *autofs4_dentry_ino(struct dentry *dentry)
diff --git a/fs/autofs4/inode.c b/fs/autofs4/inode.c
index a3ae0b2aeb5a..1132fe71b312 100644
--- a/fs/autofs4/inode.c
+++ b/fs/autofs4/inode.c
@@ -18,7 +18,6 @@
#include <linux/pagemap.h>
#include <linux/parser.h>
#include <linux/bitops.h>
-#include <linux/magic.h>
#include "autofs_i.h"
#include <linux/module.h>
diff --git a/fs/binfmt_elf.c b/fs/binfmt_elf.c
index b9065d672887..ef90667e048b 100644
--- a/fs/binfmt_elf.c
+++ b/fs/binfmt_elf.c
@@ -1711,7 +1711,7 @@ static int fill_thread_core_info(struct elf_thread_core_info *t,
const struct user_regset *regset = &view->regsets[i];
do_thread_regset_writeback(t->task, regset);
if (regset->core_note_type && regset->get &&
- (!regset->active || regset->active(t->task, regset))) {
+ (!regset->active || regset->active(t->task, regset) > 0)) {
int ret;
size_t size = regset->n * regset->size;
void *data = kmalloc(size, GFP_KERNEL);
diff --git a/fs/btrfs/dev-replace.c b/fs/btrfs/dev-replace.c
index 1e668fb7dd4c..176a27bc63aa 100644
--- a/fs/btrfs/dev-replace.c
+++ b/fs/btrfs/dev-replace.c
@@ -574,6 +574,12 @@ static int btrfs_dev_replace_finishing(struct btrfs_fs_info *fs_info,
btrfs_rm_dev_replace_unblocked(fs_info);
/*
+ * Increment dev_stats_ccnt so that btrfs_run_dev_stats() will
+ * update on-disk dev stats value during commit transaction
+ */
+ atomic_inc(&tgt_device->dev_stats_ccnt);
+
+ /*
* this is again a consistent state where no dev_replace procedure
* is running, the target device is part of the filesystem, the
* source device is not part of the filesystem anymore and its 1st
diff --git a/fs/btrfs/disk-io.c b/fs/btrfs/disk-io.c
index d106b981d86f..ae6e3a30e61e 100644
--- a/fs/btrfs/disk-io.c
+++ b/fs/btrfs/disk-io.c
@@ -1011,8 +1011,9 @@ static int btree_writepages(struct address_space *mapping,
fs_info = BTRFS_I(mapping->host)->root->fs_info;
/* this is a bit racy, but that's ok */
- ret = percpu_counter_compare(&fs_info->dirty_metadata_bytes,
- BTRFS_DIRTY_METADATA_THRESH);
+ ret = __percpu_counter_compare(&fs_info->dirty_metadata_bytes,
+ BTRFS_DIRTY_METADATA_THRESH,
+ fs_info->dirty_metadata_batch);
if (ret < 0)
return 0;
}
@@ -3987,8 +3988,9 @@ static void __btrfs_btree_balance_dirty(struct btrfs_root *root,
if (flush_delayed)
btrfs_balance_delayed_items(root);
- ret = percpu_counter_compare(&root->fs_info->dirty_metadata_bytes,
- BTRFS_DIRTY_METADATA_THRESH);
+ ret = __percpu_counter_compare(&root->fs_info->dirty_metadata_bytes,
+ BTRFS_DIRTY_METADATA_THRESH,
+ root->fs_info->dirty_metadata_batch);
if (ret > 0) {
balance_dirty_pages_ratelimited(
root->fs_info->btree_inode->i_mapping);
diff --git a/fs/btrfs/extent-tree.c b/fs/btrfs/extent-tree.c
index 493c7354ec0b..a72f941ca750 100644
--- a/fs/btrfs/extent-tree.c
+++ b/fs/btrfs/extent-tree.c
@@ -10410,7 +10410,7 @@ void btrfs_delete_unused_bgs(struct btrfs_fs_info *fs_info)
/* Don't want to race with allocators so take the groups_sem */
down_write(&space_info->groups_sem);
spin_lock(&block_group->lock);
- if (block_group->reserved ||
+ if (block_group->reserved || block_group->pinned ||
btrfs_block_group_used(&block_group->item) ||
block_group->ro ||
list_is_singular(&block_group->list)) {
diff --git a/fs/btrfs/relocation.c b/fs/btrfs/relocation.c
index 9ebe027cc4b7..cfe913d2d3df 100644
--- a/fs/btrfs/relocation.c
+++ b/fs/btrfs/relocation.c
@@ -1318,18 +1318,19 @@ static void __del_reloc_root(struct btrfs_root *root)
struct mapping_node *node = NULL;
struct reloc_control *rc = root->fs_info->reloc_ctl;
- spin_lock(&rc->reloc_root_tree.lock);
- rb_node = tree_search(&rc->reloc_root_tree.rb_root,
- root->node->start);
- if (rb_node) {
- node = rb_entry(rb_node, struct mapping_node, rb_node);
- rb_erase(&node->rb_node, &rc->reloc_root_tree.rb_root);
+ if (rc) {
+ spin_lock(&rc->reloc_root_tree.lock);
+ rb_node = tree_search(&rc->reloc_root_tree.rb_root,
+ root->node->start);
+ if (rb_node) {
+ node = rb_entry(rb_node, struct mapping_node, rb_node);
+ rb_erase(&node->rb_node, &rc->reloc_root_tree.rb_root);
+ }
+ spin_unlock(&rc->reloc_root_tree.lock);
+ if (!node)
+ return;
+ BUG_ON((struct btrfs_root *)node->data != root);
}
- spin_unlock(&rc->reloc_root_tree.lock);
-
- if (!node)
- return;
- BUG_ON((struct btrfs_root *)node->data != root);
spin_lock(&root->fs_info->trans_lock);
list_del_init(&root->root_list);
diff --git a/fs/cifs/cifs_debug.c b/fs/cifs/cifs_debug.c
index bcbe42fb7e92..0e72a14228f8 100644
--- a/fs/cifs/cifs_debug.c
+++ b/fs/cifs/cifs_debug.c
@@ -285,6 +285,10 @@ static ssize_t cifs_stats_proc_write(struct file *file,
atomic_set(&totBufAllocCount, 0);
atomic_set(&totSmBufAllocCount, 0);
#endif /* CONFIG_CIFS_STATS2 */
+ spin_lock(&GlobalMid_Lock);
+ GlobalMaxActiveXid = 0;
+ GlobalCurrentXid = 0;
+ spin_unlock(&GlobalMid_Lock);
spin_lock(&cifs_tcp_ses_lock);
list_for_each(tmp1, &cifs_tcp_ses_list) {
server = list_entry(tmp1, struct TCP_Server_Info,
@@ -297,6 +301,10 @@ static ssize_t cifs_stats_proc_write(struct file *file,
struct cifs_tcon,
tcon_list);
atomic_set(&tcon->num_smbs_sent, 0);
+ spin_lock(&tcon->stat_lock);
+ tcon->bytes_read = 0;
+ tcon->bytes_written = 0;
+ spin_unlock(&tcon->stat_lock);
if (server->ops->clear_stats)
server->ops->clear_stats(tcon);
}
diff --git a/fs/cifs/file.c b/fs/cifs/file.c
index 0141aba9eca6..79a1bad88931 100644
--- a/fs/cifs/file.c
+++ b/fs/cifs/file.c
@@ -3406,13 +3406,13 @@ readpages_get_pages(struct address_space *mapping, struct list_head *page_list,
* should have access to this page, we're safe to simply set
* PG_locked without checking it first.
*/
- __set_page_locked(page);
+ __SetPageLocked(page);
rc = add_to_page_cache_locked(page, mapping,
page->index, gfp);
/* give up if we can't stick it in the cache */
if (rc) {
- __clear_page_locked(page);
+ __ClearPageLocked(page);
return rc;
}
@@ -3433,9 +3433,9 @@ readpages_get_pages(struct address_space *mapping, struct list_head *page_list,
if (*bytes + PAGE_CACHE_SIZE > rsize)
break;
- __set_page_locked(page);
+ __SetPageLocked(page);
if (add_to_page_cache_locked(page, mapping, page->index, gfp)) {
- __clear_page_locked(page);
+ __ClearPageLocked(page);
break;
}
list_move_tail(&page->lru, tmplist);
diff --git a/fs/cifs/readdir.c b/fs/cifs/readdir.c
index 97d1a15873c5..57b039ebfb1f 100644
--- a/fs/cifs/readdir.c
+++ b/fs/cifs/readdir.c
@@ -373,8 +373,15 @@ static char *nxt_dir_entry(char *old_entry, char *end_of_smb, int level)
new_entry = old_entry + sizeof(FIND_FILE_STANDARD_INFO) +
pfData->FileNameLength;
- } else
- new_entry = old_entry + le32_to_cpu(pDirInfo->NextEntryOffset);
+ } else {
+ u32 next_offset = le32_to_cpu(pDirInfo->NextEntryOffset);
+
+ if (old_entry + next_offset < old_entry) {
+ cifs_dbg(VFS, "invalid offset %u\n", next_offset);
+ return NULL;
+ }
+ new_entry = old_entry + next_offset;
+ }
cifs_dbg(FYI, "new entry %p old entry %p\n", new_entry, old_entry);
/* validate that new_entry is not past end of SMB */
if (new_entry >= end_of_smb) {
diff --git a/fs/cifs/smb2misc.c b/fs/cifs/smb2misc.c
index 76ccf20fbfb7..0e62bf1ebbd7 100644
--- a/fs/cifs/smb2misc.c
+++ b/fs/cifs/smb2misc.c
@@ -185,6 +185,13 @@ smb2_check_message(char *buf, unsigned int length)
return 0;
/*
+ * Some windows servers (win2016) will pad also the final
+ * PDU in a compound to 8 bytes.
+ */
+ if (((clc_len + 7) & ~7) == len)
+ return 0;
+
+ /*
* MacOS server pads after SMB2.1 write response with 3 bytes
* of junk. Other servers match RFC1001 len to actual
* SMB2/SMB3 frame length (header + smb2 response specific data)
diff --git a/fs/cifs/smb2pdu.c b/fs/cifs/smb2pdu.c
index 5f5ba807b414..f7111bb88ec1 100644
--- a/fs/cifs/smb2pdu.c
+++ b/fs/cifs/smb2pdu.c
@@ -315,7 +315,7 @@ small_smb2_init(__le16 smb2_command, struct cifs_tcon *tcon,
smb2_hdr_assemble((struct smb2_hdr *) *request_buf, smb2_command, tcon);
if (tcon != NULL) {
-#ifdef CONFIG_CIFS_STATS2
+#ifdef CONFIG_CIFS_STATS
uint16_t com_code = le16_to_cpu(smb2_command);
cifs_stats_inc(&tcon->stats.smb2_stats.smb2_com_sent[com_code]);
#endif
@@ -2402,33 +2402,38 @@ num_entries(char *bufstart, char *end_of_buf, char **lastentry, size_t size)
int len;
unsigned int entrycount = 0;
unsigned int next_offset = 0;
- FILE_DIRECTORY_INFO *entryptr;
+ char *entryptr;
+ FILE_DIRECTORY_INFO *dir_info;
if (bufstart == NULL)
return 0;
- entryptr = (FILE_DIRECTORY_INFO *)bufstart;
+ entryptr = bufstart;
while (1) {
- entryptr = (FILE_DIRECTORY_INFO *)
- ((char *)entryptr + next_offset);
-
- if ((char *)entryptr + size > end_of_buf) {
+ if (entryptr + next_offset < entryptr ||
+ entryptr + next_offset > end_of_buf ||
+ entryptr + next_offset + size > end_of_buf) {
cifs_dbg(VFS, "malformed search entry would overflow\n");
break;
}
- len = le32_to_cpu(entryptr->FileNameLength);
- if ((char *)entryptr + len + size > end_of_buf) {
+ entryptr = entryptr + next_offset;
+ dir_info = (FILE_DIRECTORY_INFO *)entryptr;
+
+ len = le32_to_cpu(dir_info->FileNameLength);
+ if (entryptr + len < entryptr ||
+ entryptr + len > end_of_buf ||
+ entryptr + len + size > end_of_buf) {
cifs_dbg(VFS, "directory entry name would overflow frame end of buf %p\n",
end_of_buf);
break;
}
- *lastentry = (char *)entryptr;
+ *lastentry = entryptr;
entrycount++;
- next_offset = le32_to_cpu(entryptr->NextEntryOffset);
+ next_offset = le32_to_cpu(dir_info->NextEntryOffset);
if (!next_offset)
break;
}
diff --git a/fs/dcache.c b/fs/dcache.c
index 94f7541c154d..86f52a555dec 100644
--- a/fs/dcache.c
+++ b/fs/dcache.c
@@ -278,7 +278,8 @@ void take_dentry_name_snapshot(struct name_snapshot *name, struct dentry *dentry
spin_unlock(&dentry->d_lock);
name->name = p->name;
} else {
- memcpy(name->inline_name, dentry->d_iname, DNAME_INLINE_LEN);
+ memcpy(name->inline_name, dentry->d_iname,
+ dentry->d_name.len + 1);
spin_unlock(&dentry->d_lock);
name->name = name->inline_name;
}
diff --git a/fs/f2fs/segment.h b/fs/f2fs/segment.h
index f18fc82fbe99..38c549d77a80 100644
--- a/fs/f2fs/segment.h
+++ b/fs/f2fs/segment.h
@@ -448,6 +448,8 @@ static inline void __set_test_and_free(struct f2fs_sb_info *sbi,
if (test_and_clear_bit(segno, free_i->free_segmap)) {
free_i->free_segments++;
+ if (IS_CURSEC(sbi, secno))
+ goto skip_free;
next = find_next_bit(free_i->free_segmap,
start_segno + sbi->segs_per_sec, start_segno);
if (next >= start_segno + sbi->segs_per_sec) {
@@ -455,6 +457,7 @@ static inline void __set_test_and_free(struct f2fs_sb_info *sbi,
free_i->free_sections++;
}
}
+skip_free:
spin_unlock(&free_i->segmap_lock);
}
diff --git a/fs/f2fs/super.c b/fs/f2fs/super.c
index 08635dc2594f..b43aa473a0b6 100644
--- a/fs/f2fs/super.c
+++ b/fs/f2fs/super.c
@@ -2286,12 +2286,17 @@ int f2fs_sanity_check_ckpt(struct f2fs_sb_info *sbi)
struct f2fs_checkpoint *ckpt = F2FS_CKPT(sbi);
unsigned int ovp_segments, reserved_segments;
unsigned int main_segs, blocks_per_seg;
+ unsigned int sit_segs, nat_segs;
+ unsigned int sit_bitmap_size, nat_bitmap_size;
+ unsigned int log_blocks_per_seg;
int i;
total = le32_to_cpu(raw_super->segment_count);
fsmeta = le32_to_cpu(raw_super->segment_count_ckpt);
- fsmeta += le32_to_cpu(raw_super->segment_count_sit);
- fsmeta += le32_to_cpu(raw_super->segment_count_nat);
+ sit_segs = le32_to_cpu(raw_super->segment_count_sit);
+ fsmeta += sit_segs;
+ nat_segs = le32_to_cpu(raw_super->segment_count_nat);
+ fsmeta += nat_segs;
fsmeta += le32_to_cpu(ckpt->rsvd_segment_count);
fsmeta += le32_to_cpu(raw_super->segment_count_ssa);
@@ -2322,6 +2327,18 @@ int f2fs_sanity_check_ckpt(struct f2fs_sb_info *sbi)
return 1;
}
+ sit_bitmap_size = le32_to_cpu(ckpt->sit_ver_bitmap_bytesize);
+ nat_bitmap_size = le32_to_cpu(ckpt->nat_ver_bitmap_bytesize);
+ log_blocks_per_seg = le32_to_cpu(raw_super->log_blocks_per_seg);
+
+ if (sit_bitmap_size != ((sit_segs / 2) << log_blocks_per_seg) / 8 ||
+ nat_bitmap_size != ((nat_segs / 2) << log_blocks_per_seg) / 8) {
+ f2fs_msg(sbi->sb, KERN_ERR,
+ "Wrong bitmap size: sit: %u, nat:%u",
+ sit_bitmap_size, nat_bitmap_size);
+ return 1;
+ }
+
if (unlikely(f2fs_cp_error(sbi))) {
f2fs_msg(sbi->sb, KERN_ERR, "A bug case: need to run fsck");
return 1;
diff --git a/fs/fat/cache.c b/fs/fat/cache.c
index 93fc62232ec2..9ae2c4d7e921 100644
--- a/fs/fat/cache.c
+++ b/fs/fat/cache.c
@@ -224,7 +224,8 @@ static inline void cache_init(struct fat_cache_id *cid, int fclus, int dclus)
int fat_get_cluster(struct inode *inode, int cluster, int *fclus, int *dclus)
{
struct super_block *sb = inode->i_sb;
- const int limit = sb->s_maxbytes >> MSDOS_SB(sb)->cluster_bits;
+ struct msdos_sb_info *sbi = MSDOS_SB(sb);
+ const int limit = sb->s_maxbytes >> sbi->cluster_bits;
struct fat_entry fatent;
struct fat_cache_id cid;
int nr;
@@ -233,6 +234,12 @@ int fat_get_cluster(struct inode *inode, int cluster, int *fclus, int *dclus)
*fclus = 0;
*dclus = MSDOS_I(inode)->i_start;
+ if (!fat_valid_entry(sbi, *dclus)) {
+ fat_fs_error_ratelimit(sb,
+ "%s: invalid start cluster (i_pos %lld, start %08x)",
+ __func__, MSDOS_I(inode)->i_pos, *dclus);
+ return -EIO;
+ }
if (cluster == 0)
return 0;
@@ -249,9 +256,8 @@ int fat_get_cluster(struct inode *inode, int cluster, int *fclus, int *dclus)
/* prevent the infinite loop of cluster chain */
if (*fclus > limit) {
fat_fs_error_ratelimit(sb,
- "%s: detected the cluster chain loop"
- " (i_pos %lld)", __func__,
- MSDOS_I(inode)->i_pos);
+ "%s: detected the cluster chain loop (i_pos %lld)",
+ __func__, MSDOS_I(inode)->i_pos);
nr = -EIO;
goto out;
}
@@ -261,9 +267,8 @@ int fat_get_cluster(struct inode *inode, int cluster, int *fclus, int *dclus)
goto out;
else if (nr == FAT_ENT_FREE) {
fat_fs_error_ratelimit(sb,
- "%s: invalid cluster chain (i_pos %lld)",
- __func__,
- MSDOS_I(inode)->i_pos);
+ "%s: invalid cluster chain (i_pos %lld)",
+ __func__, MSDOS_I(inode)->i_pos);
nr = -EIO;
goto out;
} else if (nr == FAT_ENT_EOF) {
diff --git a/fs/fat/fat.h b/fs/fat/fat.h
index be5e15323bab..1849b1adb6b9 100644
--- a/fs/fat/fat.h
+++ b/fs/fat/fat.h
@@ -344,6 +344,11 @@ static inline void fatent_brelse(struct fat_entry *fatent)
fatent->fat_inode = NULL;
}
+static inline bool fat_valid_entry(struct msdos_sb_info *sbi, int entry)
+{
+ return FAT_START_ENT <= entry && entry < sbi->max_cluster;
+}
+
extern void fat_ent_access_init(struct super_block *sb);
extern int fat_ent_read(struct inode *inode, struct fat_entry *fatent,
int entry);
diff --git a/fs/fat/fatent.c b/fs/fat/fatent.c
index 6abd78629140..e1f7655e75cb 100644
--- a/fs/fat/fatent.c
+++ b/fs/fat/fatent.c
@@ -23,7 +23,7 @@ static void fat12_ent_blocknr(struct super_block *sb, int entry,
{
struct msdos_sb_info *sbi = MSDOS_SB(sb);
int bytes = entry + (entry >> 1);
- WARN_ON(entry < FAT_START_ENT || sbi->max_cluster <= entry);
+ WARN_ON(!fat_valid_entry(sbi, entry));
*offset = bytes & (sb->s_blocksize - 1);
*blocknr = sbi->fat_start + (bytes >> sb->s_blocksize_bits);
}
@@ -33,7 +33,7 @@ static void fat_ent_blocknr(struct super_block *sb, int entry,
{
struct msdos_sb_info *sbi = MSDOS_SB(sb);
int bytes = (entry << sbi->fatent_shift);
- WARN_ON(entry < FAT_START_ENT || sbi->max_cluster <= entry);
+ WARN_ON(!fat_valid_entry(sbi, entry));
*offset = bytes & (sb->s_blocksize - 1);
*blocknr = sbi->fat_start + (bytes >> sb->s_blocksize_bits);
}
@@ -354,7 +354,7 @@ int fat_ent_read(struct inode *inode, struct fat_entry *fatent, int entry)
int err, offset;
sector_t blocknr;
- if (entry < FAT_START_ENT || sbi->max_cluster <= entry) {
+ if (!fat_valid_entry(sbi, entry)) {
fatent_brelse(fatent);
fat_fs_error(sb, "invalid access to FAT (entry 0x%08x)", entry);
return -EIO;
diff --git a/fs/gfs2/bmap.c b/fs/gfs2/bmap.c
index 61296ecbd0e2..09476bb8f6cd 100644
--- a/fs/gfs2/bmap.c
+++ b/fs/gfs2/bmap.c
@@ -1476,7 +1476,7 @@ int gfs2_write_alloc_required(struct gfs2_inode *ip, u64 offset,
end_of_file = (i_size_read(&ip->i_inode) + sdp->sd_sb.sb_bsize - 1) >> shift;
lblock = offset >> shift;
lblock_stop = (offset + len + sdp->sd_sb.sb_bsize - 1) >> shift;
- if (lblock_stop > end_of_file)
+ if (lblock_stop > end_of_file && ip != GFS2_I(sdp->sd_rindex))
return 1;
size = (lblock_stop - lblock) << shift;
diff --git a/fs/hfs/brec.c b/fs/hfs/brec.c
index 6fc766df0461..2a6f3c67cb3f 100644
--- a/fs/hfs/brec.c
+++ b/fs/hfs/brec.c
@@ -74,9 +74,10 @@ int hfs_brec_insert(struct hfs_find_data *fd, void *entry, int entry_len)
if (!fd->bnode) {
if (!tree->root)
hfs_btree_inc_height(tree);
- fd->bnode = hfs_bnode_find(tree, tree->leaf_head);
- if (IS_ERR(fd->bnode))
- return PTR_ERR(fd->bnode);
+ node = hfs_bnode_find(tree, tree->leaf_head);
+ if (IS_ERR(node))
+ return PTR_ERR(node);
+ fd->bnode = node;
fd->record = -1;
}
new_node = NULL;
diff --git a/fs/hfsplus/dir.c b/fs/hfsplus/dir.c
index d0f39dcbb58e..2b6e2ad57bf9 100644
--- a/fs/hfsplus/dir.c
+++ b/fs/hfsplus/dir.c
@@ -77,13 +77,13 @@ again:
cpu_to_be32(HFSP_HARDLINK_TYPE) &&
entry.file.user_info.fdCreator ==
cpu_to_be32(HFSP_HFSPLUS_CREATOR) &&
+ HFSPLUS_SB(sb)->hidden_dir &&
(entry.file.create_date ==
HFSPLUS_I(HFSPLUS_SB(sb)->hidden_dir)->
create_date ||
entry.file.create_date ==
HFSPLUS_I(d_inode(sb->s_root))->
- create_date) &&
- HFSPLUS_SB(sb)->hidden_dir) {
+ create_date)) {
struct qstr str;
char name[32];
diff --git a/fs/hfsplus/super.c b/fs/hfsplus/super.c
index fa40e756c501..422e00dc5f3b 100644
--- a/fs/hfsplus/super.c
+++ b/fs/hfsplus/super.c
@@ -521,8 +521,10 @@ static int hfsplus_fill_super(struct super_block *sb, void *data, int silent)
goto out_put_root;
if (!hfs_brec_read(&fd, &entry, sizeof(entry))) {
hfs_find_exit(&fd);
- if (entry.type != cpu_to_be16(HFSPLUS_FOLDER))
+ if (entry.type != cpu_to_be16(HFSPLUS_FOLDER)) {
+ err = -EINVAL;
goto out_put_root;
+ }
inode = hfsplus_iget(sb, be32_to_cpu(entry.folder.id));
if (IS_ERR(inode)) {
err = PTR_ERR(inode);
diff --git a/fs/nfs/callback_xdr.c b/fs/nfs/callback_xdr.c
index e2e857affbf2..0647cb1ede56 100644
--- a/fs/nfs/callback_xdr.c
+++ b/fs/nfs/callback_xdr.c
@@ -911,16 +911,21 @@ static __be32 nfs4_callback_compound(struct svc_rqst *rqstp, void *argp, void *r
if (hdr_arg.minorversion == 0) {
cps.clp = nfs4_find_client_ident(SVC_NET(rqstp), hdr_arg.cb_ident);
- if (!cps.clp || !check_gss_callback_principal(cps.clp, rqstp))
+ if (!cps.clp || !check_gss_callback_principal(cps.clp, rqstp)) {
+ if (cps.clp)
+ nfs_put_client(cps.clp);
goto out_invalidcred;
+ }
}
cps.minorversion = hdr_arg.minorversion;
hdr_res.taglen = hdr_arg.taglen;
hdr_res.tag = hdr_arg.tag;
- if (encode_compound_hdr_res(&xdr_out, &hdr_res) != 0)
+ if (encode_compound_hdr_res(&xdr_out, &hdr_res) != 0) {
+ if (cps.clp)
+ nfs_put_client(cps.clp);
return rpc_system_err;
-
+ }
while (status == 0 && nops != hdr_arg.nops) {
status = process_op(nops, rqstp, &xdr_in,
argp, &xdr_out, resp, &cps);
diff --git a/fs/overlayfs/copy_up.c b/fs/overlayfs/copy_up.c
index 63a0d0ba36de..64c5386d0c1b 100644
--- a/fs/overlayfs/copy_up.c
+++ b/fs/overlayfs/copy_up.c
@@ -317,7 +317,6 @@ int ovl_copy_up_one(struct dentry *parent, struct dentry *dentry,
struct dentry *upperdir;
struct dentry *upperdentry;
const struct cred *old_cred;
- struct cred *override_cred;
char *link = NULL;
if (WARN_ON(!workdir))
@@ -336,28 +335,7 @@ int ovl_copy_up_one(struct dentry *parent, struct dentry *dentry,
return PTR_ERR(link);
}
- err = -ENOMEM;
- override_cred = prepare_creds();
- if (!override_cred)
- goto out_free_link;
-
- override_cred->fsuid = stat->uid;
- override_cred->fsgid = stat->gid;
- /*
- * CAP_SYS_ADMIN for copying up extended attributes
- * CAP_DAC_OVERRIDE for create
- * CAP_FOWNER for chmod, timestamp update
- * CAP_FSETID for chmod
- * CAP_CHOWN for chown
- * CAP_MKNOD for mknod
- */
- cap_raise(override_cred->cap_effective, CAP_SYS_ADMIN);
- cap_raise(override_cred->cap_effective, CAP_DAC_OVERRIDE);
- cap_raise(override_cred->cap_effective, CAP_FOWNER);
- cap_raise(override_cred->cap_effective, CAP_FSETID);
- cap_raise(override_cred->cap_effective, CAP_CHOWN);
- cap_raise(override_cred->cap_effective, CAP_MKNOD);
- old_cred = override_creds(override_cred);
+ old_cred = ovl_override_creds(dentry->d_sb);
err = -EIO;
if (lock_rename(workdir, upperdir) != NULL) {
@@ -380,9 +358,7 @@ int ovl_copy_up_one(struct dentry *parent, struct dentry *dentry,
out_unlock:
unlock_rename(workdir, upperdir);
revert_creds(old_cred);
- put_cred(override_cred);
-out_free_link:
if (link)
free_page((unsigned long) link);
diff --git a/fs/overlayfs/dir.c b/fs/overlayfs/dir.c
index 327177df03a5..f8aa54272121 100644
--- a/fs/overlayfs/dir.c
+++ b/fs/overlayfs/dir.c
@@ -408,28 +408,13 @@ static int ovl_create_or_link(struct dentry *dentry, int mode, dev_t rdev,
err = ovl_create_upper(dentry, inode, &stat, link, hardlink);
} else {
const struct cred *old_cred;
- struct cred *override_cred;
- err = -ENOMEM;
- override_cred = prepare_creds();
- if (!override_cred)
- goto out_iput;
-
- /*
- * CAP_SYS_ADMIN for setting opaque xattr
- * CAP_DAC_OVERRIDE for create in workdir, rename
- * CAP_FOWNER for removing whiteout from sticky dir
- */
- cap_raise(override_cred->cap_effective, CAP_SYS_ADMIN);
- cap_raise(override_cred->cap_effective, CAP_DAC_OVERRIDE);
- cap_raise(override_cred->cap_effective, CAP_FOWNER);
- old_cred = override_creds(override_cred);
+ old_cred = ovl_override_creds(dentry->d_sb);
err = ovl_create_over_whiteout(dentry, inode, &stat, link,
hardlink);
revert_creds(old_cred);
- put_cred(override_cred);
}
if (!err)
@@ -659,32 +644,11 @@ static int ovl_do_remove(struct dentry *dentry, bool is_dir)
if (OVL_TYPE_PURE_UPPER(type)) {
err = ovl_remove_upper(dentry, is_dir);
} else {
- const struct cred *old_cred;
- struct cred *override_cred;
-
- err = -ENOMEM;
- override_cred = prepare_creds();
- if (!override_cred)
- goto out_drop_write;
-
- /*
- * CAP_SYS_ADMIN for setting xattr on whiteout, opaque dir
- * CAP_DAC_OVERRIDE for create in workdir, rename
- * CAP_FOWNER for removing whiteout from sticky dir
- * CAP_FSETID for chmod of opaque dir
- * CAP_CHOWN for chown of opaque dir
- */
- cap_raise(override_cred->cap_effective, CAP_SYS_ADMIN);
- cap_raise(override_cred->cap_effective, CAP_DAC_OVERRIDE);
- cap_raise(override_cred->cap_effective, CAP_FOWNER);
- cap_raise(override_cred->cap_effective, CAP_FSETID);
- cap_raise(override_cred->cap_effective, CAP_CHOWN);
- old_cred = override_creds(override_cred);
+ const struct cred *old_cred = ovl_override_creds(dentry->d_sb);
err = ovl_remove_and_whiteout(dentry, is_dir);
revert_creds(old_cred);
- put_cred(override_cred);
}
out_drop_write:
ovl_drop_write(dentry);
@@ -723,7 +687,6 @@ static int ovl_rename2(struct inode *olddir, struct dentry *old,
bool new_is_dir = false;
struct dentry *opaquedir = NULL;
const struct cred *old_cred = NULL;
- struct cred *override_cred = NULL;
err = -EINVAL;
if (flags & ~(RENAME_EXCHANGE | RENAME_NOREPLACE))
@@ -792,26 +755,8 @@ static int ovl_rename2(struct inode *olddir, struct dentry *old,
old_opaque = !OVL_TYPE_PURE_UPPER(old_type);
new_opaque = !OVL_TYPE_PURE_UPPER(new_type);
- if (old_opaque || new_opaque) {
- err = -ENOMEM;
- override_cred = prepare_creds();
- if (!override_cred)
- goto out_drop_write;
-
- /*
- * CAP_SYS_ADMIN for setting xattr on whiteout, opaque dir
- * CAP_DAC_OVERRIDE for create in workdir
- * CAP_FOWNER for removing whiteout from sticky dir
- * CAP_FSETID for chmod of opaque dir
- * CAP_CHOWN for chown of opaque dir
- */
- cap_raise(override_cred->cap_effective, CAP_SYS_ADMIN);
- cap_raise(override_cred->cap_effective, CAP_DAC_OVERRIDE);
- cap_raise(override_cred->cap_effective, CAP_FOWNER);
- cap_raise(override_cred->cap_effective, CAP_FSETID);
- cap_raise(override_cred->cap_effective, CAP_CHOWN);
- old_cred = override_creds(override_cred);
- }
+ if (old_opaque || new_opaque)
+ old_cred = ovl_override_creds(old->d_sb);
if (overwrite && OVL_TYPE_MERGE_OR_LOWER(new_type) && new_is_dir) {
opaquedir = ovl_check_empty_and_clear(new);
@@ -942,10 +887,8 @@ out_dput_old:
out_unlock:
unlock_rename(new_upperdir, old_upperdir);
out_revert_creds:
- if (old_opaque || new_opaque) {
+ if (old_opaque || new_opaque)
revert_creds(old_cred);
- put_cred(override_cred);
- }
out_drop_write:
ovl_drop_write(old);
out:
diff --git a/fs/overlayfs/overlayfs.h b/fs/overlayfs/overlayfs.h
index 28316b292b8a..27a42975d7cd 100644
--- a/fs/overlayfs/overlayfs.h
+++ b/fs/overlayfs/overlayfs.h
@@ -150,6 +150,7 @@ void ovl_drop_write(struct dentry *dentry);
bool ovl_dentry_is_opaque(struct dentry *dentry);
void ovl_dentry_set_opaque(struct dentry *dentry, bool opaque);
bool ovl_is_whiteout(struct dentry *dentry);
+const struct cred *ovl_override_creds(struct super_block *sb);
void ovl_dentry_update(struct dentry *dentry, struct dentry *upperdentry);
struct dentry *ovl_lookup(struct inode *dir, struct dentry *dentry,
unsigned int flags);
@@ -164,6 +165,8 @@ int ovl_check_empty_dir(struct dentry *dentry, struct list_head *list);
void ovl_cleanup_whiteouts(struct dentry *upper, struct list_head *list);
void ovl_cache_free(struct list_head *list);
int ovl_check_d_type_supported(struct path *realpath);
+void ovl_workdir_cleanup(struct inode *dir, struct vfsmount *mnt,
+ struct dentry *dentry, int level);
/* inode.c */
int ovl_setattr(struct dentry *dentry, struct iattr *attr);
diff --git a/fs/overlayfs/readdir.c b/fs/overlayfs/readdir.c
index 0c59955c4653..da999e73c97a 100644
--- a/fs/overlayfs/readdir.c
+++ b/fs/overlayfs/readdir.c
@@ -36,7 +36,8 @@ struct ovl_dir_cache {
struct ovl_readdir_data {
struct dir_context ctx;
- bool is_merge;
+ struct dentry *dentry;
+ bool is_lowest;
struct rb_root root;
struct list_head *list;
struct list_head middle;
@@ -140,9 +141,9 @@ static int ovl_cache_entry_add_rb(struct ovl_readdir_data *rdd,
return 0;
}
-static int ovl_fill_lower(struct ovl_readdir_data *rdd,
- const char *name, int namelen,
- loff_t offset, u64 ino, unsigned int d_type)
+static int ovl_fill_lowest(struct ovl_readdir_data *rdd,
+ const char *name, int namelen,
+ loff_t offset, u64 ino, unsigned int d_type)
{
struct ovl_cache_entry *p;
@@ -194,10 +195,10 @@ static int ovl_fill_merge(struct dir_context *ctx, const char *name,
container_of(ctx, struct ovl_readdir_data, ctx);
rdd->count++;
- if (!rdd->is_merge)
+ if (!rdd->is_lowest)
return ovl_cache_entry_add_rb(rdd, name, namelen, ino, d_type);
else
- return ovl_fill_lower(rdd, name, namelen, offset, ino, d_type);
+ return ovl_fill_lowest(rdd, name, namelen, offset, ino, d_type);
}
static int ovl_check_whiteouts(struct dentry *dir, struct ovl_readdir_data *rdd)
@@ -206,17 +207,8 @@ static int ovl_check_whiteouts(struct dentry *dir, struct ovl_readdir_data *rdd)
struct ovl_cache_entry *p;
struct dentry *dentry;
const struct cred *old_cred;
- struct cred *override_cred;
-
- override_cred = prepare_creds();
- if (!override_cred)
- return -ENOMEM;
- /*
- * CAP_DAC_OVERRIDE for lookup
- */
- cap_raise(override_cred->cap_effective, CAP_DAC_OVERRIDE);
- old_cred = override_creds(override_cred);
+ old_cred = ovl_override_creds(rdd->dentry->d_sb);
err = mutex_lock_killable(&dir->d_inode->i_mutex);
if (!err) {
@@ -232,7 +224,6 @@ static int ovl_check_whiteouts(struct dentry *dir, struct ovl_readdir_data *rdd)
mutex_unlock(&dir->d_inode->i_mutex);
}
revert_creds(old_cred);
- put_cred(override_cred);
return err;
}
@@ -257,7 +248,7 @@ static inline int ovl_dir_read(struct path *realpath,
err = rdd->err;
} while (!err && rdd->count);
- if (!err && rdd->first_maybe_whiteout)
+ if (!err && rdd->first_maybe_whiteout && rdd->dentry)
err = ovl_check_whiteouts(realpath->dentry, rdd);
fput(realfile);
@@ -288,9 +279,10 @@ static int ovl_dir_read_merged(struct dentry *dentry, struct list_head *list)
struct path realpath;
struct ovl_readdir_data rdd = {
.ctx.actor = ovl_fill_merge,
+ .dentry = dentry,
.list = list,
.root = RB_ROOT,
- .is_merge = false,
+ .is_lowest = false,
};
int idx, next;
@@ -307,7 +299,7 @@ static int ovl_dir_read_merged(struct dentry *dentry, struct list_head *list)
* allows offsets to be reasonably constant
*/
list_add(&rdd.middle, rdd.list);
- rdd.is_merge = true;
+ rdd.is_lowest = true;
err = ovl_dir_read(&realpath, &rdd);
list_del(&rdd.middle);
}
@@ -618,3 +610,64 @@ int ovl_check_d_type_supported(struct path *realpath)
return rdd.d_type_supported;
}
+
+static void ovl_workdir_cleanup_recurse(struct path *path, int level)
+{
+ int err;
+ struct inode *dir = path->dentry->d_inode;
+ LIST_HEAD(list);
+ struct ovl_cache_entry *p;
+ struct ovl_readdir_data rdd = {
+ .ctx.actor = ovl_fill_merge,
+ .dentry = NULL,
+ .list = &list,
+ .root = RB_ROOT,
+ .is_lowest = false,
+ };
+
+ err = ovl_dir_read(path, &rdd);
+ if (err)
+ goto out;
+
+ inode_lock_nested(dir, I_MUTEX_PARENT);
+ list_for_each_entry(p, &list, l_node) {
+ struct dentry *dentry;
+
+ if (p->name[0] == '.') {
+ if (p->len == 1)
+ continue;
+ if (p->len == 2 && p->name[1] == '.')
+ continue;
+ }
+ dentry = lookup_one_len(p->name, path->dentry, p->len);
+ if (IS_ERR(dentry))
+ continue;
+ if (dentry->d_inode)
+ ovl_workdir_cleanup(dir, path->mnt, dentry, level);
+ dput(dentry);
+ }
+ inode_unlock(dir);
+out:
+ ovl_cache_free(&list);
+}
+
+void ovl_workdir_cleanup(struct inode *dir, struct vfsmount *mnt,
+ struct dentry *dentry, int level)
+{
+ int err;
+
+ if (!d_is_dir(dentry) || level > 1) {
+ ovl_cleanup(dir, dentry);
+ return;
+ }
+
+ err = ovl_do_rmdir(dir, dentry);
+ if (err) {
+ struct path path = { .mnt = mnt, .dentry = dentry };
+
+ inode_unlock(dir);
+ ovl_workdir_cleanup_recurse(&path, level + 1);
+ inode_lock_nested(dir, I_MUTEX_PARENT);
+ ovl_cleanup(dir, dentry);
+ }
+}
diff --git a/fs/overlayfs/super.c b/fs/overlayfs/super.c
index 0035cb80ecd1..fa20c95bd456 100644
--- a/fs/overlayfs/super.c
+++ b/fs/overlayfs/super.c
@@ -42,6 +42,8 @@ struct ovl_fs {
long lower_namelen;
/* pathnames of lower and upper dirs, for show_options */
struct ovl_config config;
+ /* creds of process who forced instantiation of super block */
+ const struct cred *creator_cred;
};
struct ovl_dir_cache;
@@ -246,6 +248,13 @@ bool ovl_is_whiteout(struct dentry *dentry)
return inode && IS_WHITEOUT(inode);
}
+const struct cred *ovl_override_creds(struct super_block *sb)
+{
+ struct ovl_fs *ofs = sb->s_fs_info;
+
+ return override_creds(ofs->creator_cred);
+}
+
static bool ovl_is_opaquedir(struct dentry *dentry)
{
int res;
@@ -587,6 +596,7 @@ static void ovl_put_super(struct super_block *sb)
kfree(ufs->config.lowerdir);
kfree(ufs->config.upperdir);
kfree(ufs->config.workdir);
+ put_cred(ufs->creator_cred);
kfree(ufs);
}
@@ -774,7 +784,7 @@ retry:
goto out_dput;
retried = true;
- ovl_cleanup(dir, work);
+ ovl_workdir_cleanup(dir, mnt, work, 0);
dput(work);
goto retry;
}
@@ -1107,10 +1117,14 @@ static int ovl_fill_super(struct super_block *sb, void *data, int silent)
else
sb->s_d_op = &ovl_dentry_operations;
+ ufs->creator_cred = prepare_creds();
+ if (!ufs->creator_cred)
+ goto out_put_lower_mnt;
+
err = -ENOMEM;
oe = ovl_alloc_entry(numlower);
if (!oe)
- goto out_put_lower_mnt;
+ goto out_put_cred;
root_dentry = d_make_root(ovl_new_inode(sb, S_IFDIR, oe));
if (!root_dentry)
@@ -1143,6 +1157,8 @@ static int ovl_fill_super(struct super_block *sb, void *data, int silent)
out_free_oe:
kfree(oe);
+out_put_cred:
+ put_cred(ufs->creator_cred);
out_put_lower_mnt:
for (i = 0; i < ufs->numlower; i++)
mntput(ufs->lower_mnt[i]);
diff --git a/fs/pstore/ram_core.c b/fs/pstore/ram_core.c
index e11672aa4575..ecdb3baa1283 100644
--- a/fs/pstore/ram_core.c
+++ b/fs/pstore/ram_core.c
@@ -421,7 +421,12 @@ static void *persistent_ram_vmap(phys_addr_t start, size_t size,
vaddr = vmap(pages, page_count, VM_MAP, prot);
kfree(pages);
- return vaddr;
+ /*
+ * Since vmap() uses page granularity, we must add the offset
+ * into the page here, to get the byte granularity address
+ * into the mapping to represent the actual "start" location.
+ */
+ return vaddr + offset_in_page(start);
}
static void *persistent_ram_iomap(phys_addr_t start, size_t size,
@@ -440,6 +445,11 @@ static void *persistent_ram_iomap(phys_addr_t start, size_t size,
else
va = ioremap_wc(start, size);
+ /*
+ * Since request_mem_region() and ioremap() are byte-granularity
+ * there is no need handle anything special like we do when the
+ * vmap() case in persistent_ram_vmap() above.
+ */
return va;
}
@@ -460,7 +470,7 @@ static int persistent_ram_buffer_map(phys_addr_t start, phys_addr_t size,
return -ENOMEM;
}
- prz->buffer = prz->vaddr + offset_in_page(start);
+ prz->buffer = prz->vaddr;
prz->buffer_size = size - sizeof(struct persistent_ram_buffer);
return 0;
@@ -507,7 +517,8 @@ void persistent_ram_free(struct persistent_ram_zone *prz)
if (prz->vaddr) {
if (pfn_valid(prz->paddr >> PAGE_SHIFT)) {
- vunmap(prz->vaddr);
+ /* We must vunmap() at page-granularity. */
+ vunmap(prz->vaddr - offset_in_page(prz->paddr));
} else {
iounmap(prz->vaddr);
release_mem_region(prz->paddr, prz->size);
diff --git a/fs/reiserfs/reiserfs.h b/fs/reiserfs/reiserfs.h
index 6ca00471afbf..d920a646b578 100644
--- a/fs/reiserfs/reiserfs.h
+++ b/fs/reiserfs/reiserfs.h
@@ -270,7 +270,7 @@ struct reiserfs_journal_list {
struct mutex j_commit_mutex;
unsigned int j_trans_id;
- time_t j_timestamp;
+ time64_t j_timestamp; /* write-only but useful for crash dump analysis */
struct reiserfs_list_bitmap *j_list_bitmap;
struct buffer_head *j_commit_bh; /* commit buffer head */
struct reiserfs_journal_cnode *j_realblock;
diff --git a/fs/sdcardfs/main.c b/fs/sdcardfs/main.c
index 27ec726e7a46..1ad7718c05d9 100644
--- a/fs/sdcardfs/main.c
+++ b/fs/sdcardfs/main.c
@@ -264,7 +264,7 @@ static int sdcardfs_read_super(struct vfsmount *mnt, struct super_block *sb,
pr_info("sdcardfs: dev_name -> %s\n", dev_name);
pr_info("sdcardfs: options -> %s\n", (char *)raw_data);
- pr_info("sdcardfs: mnt -> %p\n", mnt);
+ pr_info("sdcardfs: mnt -> %pK\n", mnt);
/* parse lower path */
err = kern_path(dev_name, LOOKUP_FOLLOW | LOOKUP_DIRECTORY,
diff --git a/fs/sdcardfs/super.c b/fs/sdcardfs/super.c
index cffcdb11cb8a..fa7d9d2c5c2b 100644
--- a/fs/sdcardfs/super.c
+++ b/fs/sdcardfs/super.c
@@ -144,7 +144,7 @@ static int sdcardfs_remount_fs2(struct vfsmount *mnt, struct super_block *sb,
pr_err("sdcardfs: remount flags 0x%x unsupported\n", *flags);
err = -EINVAL;
}
- pr_info("Remount options were %s for vfsmnt %p.\n", options, mnt);
+ pr_info("Remount options were %s for vfsmnt %pK.\n", options, mnt);
err = parse_options_remount(sb, options, *flags & ~MS_SILENT, mnt->data);
diff --git a/include/linux/bug.h b/include/linux/bug.h
index 91eedf5fae38..218ac5875124 100644
--- a/include/linux/bug.h
+++ b/include/linux/bug.h
@@ -115,4 +115,23 @@ static inline enum bug_trap_type report_bug(unsigned long bug_addr,
#else
#define PANIC_CORRUPTION 0
#endif /* CONFIG_PANIC_ON_DATA_CORRUPTION */
+
+/*
+ * Since detected data corruption should stop operation on the affected
+ * structures. Return value must be checked and sanely acted on by caller.
+ */
+static inline __must_check bool check_data_corruption(bool v) { return v; }
+#define CHECK_DATA_CORRUPTION(condition, fmt, ...) \
+ check_data_corruption(({ \
+ bool corruption = unlikely(condition); \
+ if (corruption) { \
+ if (IS_ENABLED(CONFIG_BUG_ON_DATA_CORRUPTION)) { \
+ pr_err(fmt, ##__VA_ARGS__); \
+ BUG(); \
+ } else \
+ WARN(1, fmt, ##__VA_ARGS__); \
+ } \
+ corruption; \
+ }))
+
#endif /* _LINUX_BUG_H */
diff --git a/include/linux/list.h b/include/linux/list.h
index 993395a2e55c..d5750f2f1c36 100644
--- a/include/linux/list.h
+++ b/include/linux/list.h
@@ -28,27 +28,42 @@ static inline void INIT_LIST_HEAD(struct list_head *list)
list->prev = list;
}
+#ifdef CONFIG_DEBUG_LIST
+extern bool __list_add_valid(struct list_head *new,
+ struct list_head *prev,
+ struct list_head *next);
+extern bool __list_del_entry_valid(struct list_head *entry);
+#else
+static inline bool __list_add_valid(struct list_head *new,
+ struct list_head *prev,
+ struct list_head *next)
+{
+ return true;
+}
+static inline bool __list_del_entry_valid(struct list_head *entry)
+{
+ return true;
+}
+#endif
+
/*
* Insert a new entry between two known consecutive entries.
*
* This is only for internal list manipulation where we know
* the prev/next entries already!
*/
-#ifndef CONFIG_DEBUG_LIST
static inline void __list_add(struct list_head *new,
struct list_head *prev,
struct list_head *next)
{
+ if (!__list_add_valid(new, prev, next))
+ return;
+
next->prev = new;
new->next = next;
new->prev = prev;
prev->next = new;
}
-#else
-extern void __list_add(struct list_head *new,
- struct list_head *prev,
- struct list_head *next);
-#endif
/**
* list_add - add a new entry
@@ -96,22 +111,20 @@ static inline void __list_del(struct list_head * prev, struct list_head * next)
* Note: list_empty() on entry does not return true after this, the entry is
* in an undefined state.
*/
-#ifndef CONFIG_DEBUG_LIST
static inline void __list_del_entry(struct list_head *entry)
{
+ if (!__list_del_entry_valid(entry))
+ return;
+
__list_del(entry->prev, entry->next);
}
static inline void list_del(struct list_head *entry)
{
- __list_del(entry->prev, entry->next);
+ __list_del_entry(entry);
entry->next = LIST_POISON1;
entry->prev = LIST_POISON2;
}
-#else
-extern void __list_del_entry(struct list_head *entry);
-extern void list_del(struct list_head *entry);
-#endif
/**
* list_replace - replace old entry by new one
diff --git a/include/linux/mm_types.h b/include/linux/mm_types.h
index fe0a5de1eda5..29c17fae9bbf 100644
--- a/include/linux/mm_types.h
+++ b/include/linux/mm_types.h
@@ -404,7 +404,7 @@ struct kioctx_table;
struct mm_struct {
struct vm_area_struct *mmap; /* list of VMAs */
struct rb_root mm_rb;
- u32 vmacache_seqnum; /* per-thread vmacache */
+ u64 vmacache_seqnum; /* per-thread vmacache */
#ifdef CONFIG_MMU
unsigned long (*get_unmapped_area) (struct file *filp,
unsigned long addr, unsigned long len,
diff --git a/include/linux/mmdebug.h b/include/linux/mmdebug.h
index 772362adf471..053824b0a412 100644
--- a/include/linux/mmdebug.h
+++ b/include/linux/mmdebug.h
@@ -56,4 +56,10 @@ void dump_mm(const struct mm_struct *mm);
#define VIRTUAL_BUG_ON(cond) do { } while (0)
#endif
+#ifdef CONFIG_DEBUG_VM_PGFLAGS
+#define VM_BUG_ON_PGFLAGS(cond, page) VM_BUG_ON_PAGE(cond, page)
+#else
+#define VM_BUG_ON_PGFLAGS(cond, page) BUILD_BUG_ON_INVALID(cond)
+#endif
+
#endif
diff --git a/include/linux/page-flags.h b/include/linux/page-flags.h
index 86c233be1cfc..985fb2c63cb7 100644
--- a/include/linux/page-flags.h
+++ b/include/linux/page-flags.h
@@ -139,49 +139,101 @@ enum pageflags {
#ifndef __GENERATING_BOUNDS_H
+struct page; /* forward declaration */
+
+static inline struct page *compound_head(struct page *page)
+{
+ unsigned long head = READ_ONCE(page->compound_head);
+
+ if (unlikely(head & 1))
+ return (struct page *) (head - 1);
+ return page;
+}
+
+static inline int PageTail(struct page *page)
+{
+ return READ_ONCE(page->compound_head) & 1;
+}
+
+static inline int PageCompound(struct page *page)
+{
+ return test_bit(PG_head, &page->flags) || PageTail(page);
+}
+
+/*
+ * Page flags policies wrt compound pages
+ *
+ * PF_ANY:
+ * the page flag is relevant for small, head and tail pages.
+ *
+ * PF_HEAD:
+ * for compound page all operations related to the page flag applied to
+ * head page.
+ *
+ * PF_NO_TAIL:
+ * modifications of the page flag must be done on small or head pages,
+ * checks can be done on tail pages too.
+ *
+ * PF_NO_COMPOUND:
+ * the page flag is not relevant for compound pages.
+ */
+#define PF_ANY(page, enforce) page
+#define PF_HEAD(page, enforce) compound_head(page)
+#define PF_NO_TAIL(page, enforce) ({ \
+ VM_BUG_ON_PGFLAGS(enforce && PageTail(page), page); \
+ compound_head(page);})
+#define PF_NO_COMPOUND(page, enforce) ({ \
+ VM_BUG_ON_PGFLAGS(enforce && PageCompound(page), page); \
+ page;})
+
/*
* Macros to create function definitions for page flags
*/
-#define TESTPAGEFLAG(uname, lname) \
-static inline int Page##uname(const struct page *page) \
- { return test_bit(PG_##lname, &page->flags); }
+#define TESTPAGEFLAG(uname, lname, policy) \
+static inline int Page##uname(struct page *page) \
+ { return test_bit(PG_##lname, &policy(page, 0)->flags); }
-#define SETPAGEFLAG(uname, lname) \
+#define SETPAGEFLAG(uname, lname, policy) \
static inline void SetPage##uname(struct page *page) \
- { set_bit(PG_##lname, &page->flags); }
+ { set_bit(PG_##lname, &policy(page, 1)->flags); }
-#define CLEARPAGEFLAG(uname, lname) \
+#define CLEARPAGEFLAG(uname, lname, policy) \
static inline void ClearPage##uname(struct page *page) \
- { clear_bit(PG_##lname, &page->flags); }
+ { clear_bit(PG_##lname, &policy(page, 1)->flags); }
-#define __SETPAGEFLAG(uname, lname) \
+#define __SETPAGEFLAG(uname, lname, policy) \
static inline void __SetPage##uname(struct page *page) \
- { __set_bit(PG_##lname, &page->flags); }
+ { __set_bit(PG_##lname, &policy(page, 1)->flags); }
-#define __CLEARPAGEFLAG(uname, lname) \
+#define __CLEARPAGEFLAG(uname, lname, policy) \
static inline void __ClearPage##uname(struct page *page) \
- { __clear_bit(PG_##lname, &page->flags); }
+ { __clear_bit(PG_##lname, &policy(page, 1)->flags); }
-#define TESTSETFLAG(uname, lname) \
+#define TESTSETFLAG(uname, lname, policy) \
static inline int TestSetPage##uname(struct page *page) \
- { return test_and_set_bit(PG_##lname, &page->flags); }
+ { return test_and_set_bit(PG_##lname, &policy(page, 1)->flags); }
-#define TESTCLEARFLAG(uname, lname) \
+#define TESTCLEARFLAG(uname, lname, policy) \
static inline int TestClearPage##uname(struct page *page) \
- { return test_and_clear_bit(PG_##lname, &page->flags); }
+ { return test_and_clear_bit(PG_##lname, &policy(page, 1)->flags); }
-#define __TESTCLEARFLAG(uname, lname) \
+#define __TESTCLEARFLAG(uname, lname, policy) \
static inline int __TestClearPage##uname(struct page *page) \
- { return __test_and_clear_bit(PG_##lname, &page->flags); }
+ { return __test_and_clear_bit(PG_##lname, &policy(page, 1)->flags); }
-#define PAGEFLAG(uname, lname) TESTPAGEFLAG(uname, lname) \
- SETPAGEFLAG(uname, lname) CLEARPAGEFLAG(uname, lname)
+#define PAGEFLAG(uname, lname, policy) \
+ TESTPAGEFLAG(uname, lname, policy) \
+ SETPAGEFLAG(uname, lname, policy) \
+ CLEARPAGEFLAG(uname, lname, policy)
-#define __PAGEFLAG(uname, lname) TESTPAGEFLAG(uname, lname) \
- __SETPAGEFLAG(uname, lname) __CLEARPAGEFLAG(uname, lname)
+#define __PAGEFLAG(uname, lname, policy) \
+ TESTPAGEFLAG(uname, lname, policy) \
+ __SETPAGEFLAG(uname, lname, policy) \
+ __CLEARPAGEFLAG(uname, lname, policy)
-#define TESTSCFLAG(uname, lname) \
- TESTSETFLAG(uname, lname) TESTCLEARFLAG(uname, lname)
+#define TESTSCFLAG(uname, lname, policy) \
+ TESTSETFLAG(uname, lname, policy) \
+ TESTCLEARFLAG(uname, lname, policy)
#define TESTPAGEFLAG_FALSE(uname) \
static inline int Page##uname(const struct page *page) { return 0; }
@@ -210,28 +262,28 @@ static inline int __TestClearPage##uname(struct page *page) { return 0; }
#define TESTSCFLAG_FALSE(uname) \
TESTSETFLAG_FALSE(uname) TESTCLEARFLAG_FALSE(uname)
-struct page; /* forward declaration */
-
-TESTPAGEFLAG(Locked, locked)
-PAGEFLAG(Error, error) TESTCLEARFLAG(Error, error)
-PAGEFLAG(Referenced, referenced) TESTCLEARFLAG(Referenced, referenced)
- __SETPAGEFLAG(Referenced, referenced)
-PAGEFLAG(Dirty, dirty) TESTSCFLAG(Dirty, dirty) __CLEARPAGEFLAG(Dirty, dirty)
-PAGEFLAG(LRU, lru) __CLEARPAGEFLAG(LRU, lru)
-PAGEFLAG(Active, active) __CLEARPAGEFLAG(Active, active)
- TESTCLEARFLAG(Active, active)
-__PAGEFLAG(Slab, slab)
-PAGEFLAG(Checked, checked) /* Used by some filesystems */
-PAGEFLAG(Pinned, pinned) TESTSCFLAG(Pinned, pinned) /* Xen */
-PAGEFLAG(SavePinned, savepinned); /* Xen */
-PAGEFLAG(Foreign, foreign); /* Xen */
-PAGEFLAG(Reserved, reserved) __CLEARPAGEFLAG(Reserved, reserved)
-PAGEFLAG(SwapBacked, swapbacked) __CLEARPAGEFLAG(SwapBacked, swapbacked)
- __SETPAGEFLAG(SwapBacked, swapbacked)
-
-__PAGEFLAG(SlobFree, slob_free)
+__PAGEFLAG(Locked, locked, PF_NO_TAIL)
+PAGEFLAG(Error, error, PF_ANY) TESTCLEARFLAG(Error, error, PF_ANY)
+PAGEFLAG(Referenced, referenced, PF_ANY) TESTCLEARFLAG(Referenced, referenced, PF_ANY)
+ __SETPAGEFLAG(Referenced, referenced, PF_ANY)
+PAGEFLAG(Dirty, dirty, PF_ANY) TESTSCFLAG(Dirty, dirty, PF_ANY)
+ __CLEARPAGEFLAG(Dirty, dirty, PF_ANY)
+PAGEFLAG(LRU, lru, PF_ANY) __CLEARPAGEFLAG(LRU, lru, PF_ANY)
+PAGEFLAG(Active, active, PF_ANY) __CLEARPAGEFLAG(Active, active, PF_ANY)
+ TESTCLEARFLAG(Active, active, PF_ANY)
+__PAGEFLAG(Slab, slab, PF_ANY)
+PAGEFLAG(Checked, checked, PF_ANY) /* Used by some filesystems */
+PAGEFLAG(Pinned, pinned, PF_ANY) TESTSCFLAG(Pinned, pinned, PF_ANY) /* Xen */
+PAGEFLAG(SavePinned, savepinned, PF_ANY); /* Xen */
+PAGEFLAG(Foreign, foreign, PF_ANY); /* Xen */
+PAGEFLAG(Reserved, reserved, PF_ANY) __CLEARPAGEFLAG(Reserved, reserved, PF_ANY)
+PAGEFLAG(SwapBacked, swapbacked, PF_ANY)
+ __CLEARPAGEFLAG(SwapBacked, swapbacked, PF_ANY)
+ __SETPAGEFLAG(SwapBacked, swapbacked, PF_ANY)
+
+__PAGEFLAG(SlobFree, slob_free, PF_ANY)
#ifdef CONFIG_ZCACHE
-PAGEFLAG(WasActive, was_active)
+PAGEFLAG(WasActive, was_active, PF_ANY)
#else
PAGEFLAG_FALSE(WasActive)
#endif
@@ -241,21 +293,22 @@ PAGEFLAG_FALSE(WasActive)
* for its own purposes.
* - PG_private and PG_private_2 cause releasepage() and co to be invoked
*/
-PAGEFLAG(Private, private) __SETPAGEFLAG(Private, private)
- __CLEARPAGEFLAG(Private, private)
-PAGEFLAG(Private2, private_2) TESTSCFLAG(Private2, private_2)
-PAGEFLAG(OwnerPriv1, owner_priv_1) TESTCLEARFLAG(OwnerPriv1, owner_priv_1)
+PAGEFLAG(Private, private, PF_ANY) __SETPAGEFLAG(Private, private, PF_ANY)
+ __CLEARPAGEFLAG(Private, private, PF_ANY)
+PAGEFLAG(Private2, private_2, PF_ANY) TESTSCFLAG(Private2, private_2, PF_ANY)
+PAGEFLAG(OwnerPriv1, owner_priv_1, PF_ANY)
+ TESTCLEARFLAG(OwnerPriv1, owner_priv_1, PF_ANY)
/*
* Only test-and-set exist for PG_writeback. The unconditional operators are
* risky: they bypass page accounting.
*/
-TESTPAGEFLAG(Writeback, writeback) TESTSCFLAG(Writeback, writeback)
-PAGEFLAG(MappedToDisk, mappedtodisk)
+TESTPAGEFLAG(Writeback, writeback, PF_ANY) TESTSCFLAG(Writeback, writeback, PF_ANY)
+PAGEFLAG(MappedToDisk, mappedtodisk, PF_ANY)
/* PG_readahead is only used for reads; PG_reclaim is only for writes */
-PAGEFLAG(Reclaim, reclaim) TESTCLEARFLAG(Reclaim, reclaim)
-PAGEFLAG(Readahead, reclaim) TESTCLEARFLAG(Readahead, reclaim)
+PAGEFLAG(Reclaim, reclaim, PF_ANY) TESTCLEARFLAG(Reclaim, reclaim, PF_ANY)
+PAGEFLAG(Readahead, reclaim, PF_ANY) TESTCLEARFLAG(Readahead, reclaim, PF_ANY)
#ifdef CONFIG_HIGHMEM
/*
@@ -268,31 +321,32 @@ PAGEFLAG_FALSE(HighMem)
#endif
#ifdef CONFIG_SWAP
-PAGEFLAG(SwapCache, swapcache)
+PAGEFLAG(SwapCache, swapcache, PF_ANY)
#else
PAGEFLAG_FALSE(SwapCache)
#endif
-PAGEFLAG(Unevictable, unevictable) __CLEARPAGEFLAG(Unevictable, unevictable)
- TESTCLEARFLAG(Unevictable, unevictable)
+PAGEFLAG(Unevictable, unevictable, PF_ANY)
+ __CLEARPAGEFLAG(Unevictable, unevictable, PF_ANY)
+ TESTCLEARFLAG(Unevictable, unevictable, PF_ANY)
#ifdef CONFIG_MMU
-PAGEFLAG(Mlocked, mlocked) __CLEARPAGEFLAG(Mlocked, mlocked)
- TESTSCFLAG(Mlocked, mlocked) __TESTCLEARFLAG(Mlocked, mlocked)
+PAGEFLAG(Mlocked, mlocked, PF_ANY) __CLEARPAGEFLAG(Mlocked, mlocked, PF_ANY)
+ TESTSCFLAG(Mlocked, mlocked, PF_ANY) __TESTCLEARFLAG(Mlocked, mlocked, PF_ANY)
#else
PAGEFLAG_FALSE(Mlocked) __CLEARPAGEFLAG_NOOP(Mlocked)
TESTSCFLAG_FALSE(Mlocked) __TESTCLEARFLAG_FALSE(Mlocked)
#endif
#ifdef CONFIG_ARCH_USES_PG_UNCACHED
-PAGEFLAG(Uncached, uncached)
+PAGEFLAG(Uncached, uncached, PF_ANY)
#else
PAGEFLAG_FALSE(Uncached)
#endif
#ifdef CONFIG_MEMORY_FAILURE
-PAGEFLAG(HWPoison, hwpoison)
-TESTSCFLAG(HWPoison, hwpoison)
+PAGEFLAG(HWPoison, hwpoison, PF_ANY)
+TESTSCFLAG(HWPoison, hwpoison, PF_ANY)
#define __PG_HWPOISON (1UL << PG_hwpoison)
#else
PAGEFLAG_FALSE(HWPoison)
@@ -300,10 +354,10 @@ PAGEFLAG_FALSE(HWPoison)
#endif
#if defined(CONFIG_IDLE_PAGE_TRACKING) && defined(CONFIG_64BIT)
-TESTPAGEFLAG(Young, young)
-SETPAGEFLAG(Young, young)
-TESTCLEARFLAG(Young, young)
-PAGEFLAG(Idle, idle)
+TESTPAGEFLAG(Young, young, PF_ANY)
+SETPAGEFLAG(Young, young, PF_ANY)
+TESTCLEARFLAG(Young, young, PF_ANY)
+PAGEFLAG(Idle, idle, PF_ANY)
#endif
/*
@@ -397,7 +451,7 @@ static inline void SetPageUptodate(struct page *page)
set_bit(PG_uptodate, &(page)->flags);
}
-CLEARPAGEFLAG(Uptodate, uptodate)
+CLEARPAGEFLAG(Uptodate, uptodate, PF_ANY)
int test_clear_page_writeback(struct page *page);
int __test_set_page_writeback(struct page *page, bool keep_write);
@@ -417,12 +471,7 @@ static inline void set_page_writeback_keepwrite(struct page *page)
test_set_page_writeback_keepwrite(page);
}
-__PAGEFLAG(Head, head) CLEARPAGEFLAG(Head, head)
-
-static inline int PageTail(struct page *page)
-{
- return READ_ONCE(page->compound_head) & 1;
-}
+__PAGEFLAG(Head, head, PF_ANY) CLEARPAGEFLAG(Head, head, PF_ANY)
static inline void set_compound_head(struct page *page, struct page *head)
{
@@ -434,20 +483,6 @@ static inline void clear_compound_head(struct page *page)
WRITE_ONCE(page->compound_head, 0);
}
-static inline struct page *compound_head(struct page *page)
-{
- unsigned long head = READ_ONCE(page->compound_head);
-
- if (unlikely(head & 1))
- return (struct page *) (head - 1);
- return page;
-}
-
-static inline int PageCompound(struct page *page)
-{
- return PageHead(page) || PageTail(page);
-
-}
#ifdef CONFIG_TRANSPARENT_HUGEPAGE
static inline void ClearPageCompound(struct page *page)
{
@@ -573,7 +608,7 @@ static inline void __ClearPageBalloon(struct page *page)
atomic_set(&page->_mapcount, -1);
}
-__PAGEFLAG(Isolated, isolated);
+__PAGEFLAG(Isolated, isolated, PF_ANY);
/*
* If network-based swap is enabled, sl*b must keep track of whether pages
@@ -652,6 +687,10 @@ static inline int page_has_private(struct page *page)
return !!(page->flags & PAGE_FLAGS_PRIVATE);
}
+#undef PF_ANY
+#undef PF_HEAD
+#undef PF_NO_TAIL
+#undef PF_NO_COMPOUND
#endif /* !__GENERATING_BOUNDS_H */
#endif /* PAGE_FLAGS_H */
diff --git a/include/linux/pagemap.h b/include/linux/pagemap.h
index 443a063e6af8..d2f4a732b3e8 100644
--- a/include/linux/pagemap.h
+++ b/include/linux/pagemap.h
@@ -441,18 +441,9 @@ extern int __lock_page_or_retry(struct page *page, struct mm_struct *mm,
unsigned int flags);
extern void unlock_page(struct page *page);
-static inline void __set_page_locked(struct page *page)
-{
- __set_bit(PG_locked, &page->flags);
-}
-
-static inline void __clear_page_locked(struct page *page)
-{
- __clear_bit(PG_locked, &page->flags);
-}
-
static inline int trylock_page(struct page *page)
{
+ page = compound_head(page);
return (likely(!test_and_set_bit_lock(PG_locked, &page->flags)));
}
@@ -505,9 +496,9 @@ extern int wait_on_page_bit_killable_timeout(struct page *page,
static inline int wait_on_page_locked_killable(struct page *page)
{
- if (PageLocked(page))
- return wait_on_page_bit_killable(page, PG_locked);
- return 0;
+ if (!PageLocked(page))
+ return 0;
+ return wait_on_page_bit_killable(compound_head(page), PG_locked);
}
extern wait_queue_head_t *page_waitqueue(struct page *page);
@@ -526,7 +517,7 @@ static inline void wake_up_page(struct page *page, int bit)
static inline void wait_on_page_locked(struct page *page)
{
if (PageLocked(page))
- wait_on_page_bit(page, PG_locked);
+ wait_on_page_bit(compound_head(page), PG_locked);
}
/*
@@ -672,17 +663,17 @@ int replace_page_cache_page(struct page *old, struct page *new, gfp_t gfp_mask);
/*
* Like add_to_page_cache_locked, but used to add newly allocated pages:
- * the page is new, so we can just run __set_page_locked() against it.
+ * the page is new, so we can just run __SetPageLocked() against it.
*/
static inline int add_to_page_cache(struct page *page,
struct address_space *mapping, pgoff_t offset, gfp_t gfp_mask)
{
int error;
- __set_page_locked(page);
+ __SetPageLocked(page);
error = add_to_page_cache_locked(page, mapping, offset, gfp_mask);
if (unlikely(error))
- __clear_page_locked(page);
+ __ClearPageLocked(page);
return error;
}
diff --git a/include/linux/qdsp6v2/audio-anc-dev-mgr.h b/include/linux/qdsp6v2/audio-anc-dev-mgr.h
index dfa6752bc31b..b0ece2dbb239 100644
--- a/include/linux/qdsp6v2/audio-anc-dev-mgr.h
+++ b/include/linux/qdsp6v2/audio-anc-dev-mgr.h
@@ -39,6 +39,8 @@ int msm_anc_dev_stop(void);
int msm_anc_dev_set_info(void *info_p, int32_t anc_cmd);
+int msm_anc_dev_get_info(void *info_p, int32_t anc_cmd);
+
int msm_anc_dev_create(struct platform_device *pdev);
int msm_anc_dev_destroy(struct platform_device *pdev);
diff --git a/include/linux/qdsp6v2/sdsp_anc.h b/include/linux/qdsp6v2/sdsp_anc.h
index 3b236e827e3d..5c1b7055c1d5 100644
--- a/include/linux/qdsp6v2/sdsp_anc.h
+++ b/include/linux/qdsp6v2/sdsp_anc.h
@@ -15,7 +15,6 @@
#include <sound/q6afe-v2.h>
#include <sound/apr_audio-v2.h>
-
#define AUD_MSVC_MODULE_AUDIO_DEV_RESOURCE_SHARE 0x0001028A
#define AUD_MSVC_PARAM_ID_PORT_SHARE_RESOURCE_CONFIG 0x00010297
#define AUD_MSVC_API_VERSION_SHARE_RESOURCE_CONFIG 0x1
@@ -23,8 +22,6 @@
#define AUD_MSVC_PARAM_ID_DEV_ANC_REFS_CONFIG 0x00010286
#define AUD_MSVC_API_VERSION_DEV_ANC_REFS_CONFIG 0x1
#define AUD_MSVC_MODULE_AUDIO_DEV_ANC_ALGO 0x00010234
-#define AUD_MSVC_PARAM_ID_PORT_ANC_ALGO_RPM 0x00010235
-#define AUD_MSVC_API_VERSION_DEV_ANC_ALGO_RPM 0x1
struct aud_msvc_port_param_data_v2 {
/* ID of the module to be configured.
@@ -148,7 +145,7 @@ struct aud_msvc_port_cmd_get_param_v2 {
} __packed;
struct aud_audioif_config_command {
- struct apr_hdr hdr;
+ struct apr_hdr hdr;
struct aud_msvc_port_cmd_set_param_v2 param;
struct aud_msvc_port_param_data_v2 pdata;
union afe_port_config port;
@@ -162,13 +159,6 @@ struct aud_msvc_param_id_dev_share_resource_cfg {
u32 lpm_length;
} __packed;
-
-struct aud_msvc_param_id_dev_anc_algo_rpm {
- u32 minor_version;
- u32 rpm;
-} __packed;
-
-
struct aud_msvc_param_id_dev_anc_refs_cfg {
u32 minor_version;
u16 port_id;
@@ -177,65 +167,20 @@ struct aud_msvc_param_id_dev_anc_refs_cfg {
u32 bit_width;
} __packed;
-
struct anc_share_resource_command {
- struct apr_hdr hdr;
+ struct apr_hdr hdr;
struct aud_msvc_port_cmd_set_param_v2 param;
struct aud_msvc_port_param_data_v2 pdata;
struct aud_msvc_param_id_dev_share_resource_cfg resource;
} __packed;
-
struct anc_config_ref_command {
- struct apr_hdr hdr;
+ struct apr_hdr hdr;
struct aud_msvc_port_cmd_set_param_v2 param;
struct aud_msvc_port_param_data_v2 pdata;
struct aud_msvc_param_id_dev_anc_refs_cfg refs;
} __packed;
-
-
-struct anc_set_rpm_command {
- struct apr_hdr hdr;
- struct aud_msvc_port_cmd_set_param_v2 param;
- struct aud_msvc_port_param_data_v2 pdata;
- struct aud_msvc_param_id_dev_anc_algo_rpm set_rpm;
-} __packed;
-
-struct anc_get_rpm_command {
- struct apr_hdr hdr;
- struct aud_msvc_port_cmd_get_param_v2 param;
- struct aud_msvc_port_param_data_v2 pdata;
- struct aud_msvc_param_id_dev_anc_algo_rpm get_rpm;
-} __packed;
-
-struct anc_get_rpm_resp {
- uint32_t status;
- struct aud_msvc_port_param_data_v2 pdata;
- struct aud_msvc_param_id_dev_anc_algo_rpm res_rpm;
-} __packed;
-
-#define AUD_MSVC_PARAM_ID_PORT_ANC_ALGO_BYPASS_MODE 0x0001029B
-
-#define AUD_MSVC_API_VERSION_DEV_ANC_ALGO_BYPASS_MODE 0x1
-
-#define AUD_MSVC_ANC_ALGO_BYPASS_MODE_NO 0x0
-#define AUD_MSVC_ANC_ALGO_BYPASS_MODE_REFS_TO_ANC_SPKR 0x1
-#define AUD_MSVC_ANC_ALGO_BYPASS_MODE_ANC_MIC_TO_ANC_SPKR 0x2
-#define AUD_MSVC_ANC_ALGO_BYPASS_MODE_REFS_MIXED_ANC_MIC_TO_ANC_SPKR 0x3
-
-struct aud_msvc_param_id_dev_anc_algo_bypass_mode {
- uint32_t minor_version;
- uint32_t bypass_mode;
-} __packed;
-
-struct anc_set_bypass_mode_command {
- struct apr_hdr hdr;
- struct aud_msvc_port_cmd_set_param_v2 param;
- struct aud_msvc_port_param_data_v2 pdata;
- struct aud_msvc_param_id_dev_anc_algo_bypass_mode set_bypass_mode;
-} __packed;
-
#define AUD_MSVC_PARAM_ID_PORT_ANC_ALGO_MODULE_ID 0x0001023A
struct aud_msvc_param_id_dev_anc_algo_module_id {
@@ -244,7 +189,7 @@ struct aud_msvc_param_id_dev_anc_algo_module_id {
} __packed;
struct anc_set_algo_module_id_command {
- struct apr_hdr hdr;
+ struct apr_hdr hdr;
struct aud_msvc_port_cmd_set_param_v2 param;
struct aud_msvc_port_param_data_v2 pdata;
struct aud_msvc_param_id_dev_anc_algo_module_id set_algo_module_id;
@@ -269,13 +214,37 @@ struct aud_msvc_param_id_dev_anc_mic_spkr_layout_info {
} __packed;
struct anc_set_mic_spkr_layout_info_command {
- struct apr_hdr hdr;
+ struct apr_hdr hdr;
struct aud_msvc_port_cmd_set_param_v2 param;
struct aud_msvc_port_param_data_v2 pdata;
struct aud_msvc_param_id_dev_anc_mic_spkr_layout_info
set_mic_spkr_layout;
} __packed;
+struct anc_set_algo_module_cali_data_command {
+ struct apr_hdr hdr;
+ struct aud_msvc_port_cmd_set_param_v2 param;
+ struct aud_msvc_port_param_data_v2 pdata;
+ /*
+ * calibration data payload followed
+ */
+} __packed;
+
+struct anc_get_algo_module_cali_data_command {
+ struct apr_hdr hdr;
+ struct aud_msvc_port_cmd_get_param_v2 param;
+ struct aud_msvc_port_param_data_v2 pdata;
+ /*
+ * calibration data payload followed
+ */
+} __packed;
+
+struct anc_get_algo_module_cali_data_resp {
+ uint32_t status;
+ struct aud_msvc_port_param_data_v2 pdata;
+ uint32_t payload[128];
+} __packed;
+
int anc_if_tdm_port_start(u16 port_id, struct afe_tdm_port_config *tdm_port);
int anc_if_tdm_port_stop(u16 port_id);
@@ -286,15 +255,15 @@ int anc_if_share_resource(u16 port_id, u16 rddma_idx, u16 wrdma_idx,
int anc_if_config_ref(u16 port_id, u32 sample_rate, u32 bit_width,
u16 num_channel);
-int anc_if_set_rpm(u16 port_id, u32 rpm);
-
-int anc_if_set_bypass_mode(u16 port_id, u32 bypass_mode);
-
int anc_if_set_algo_module_id(u16 port_id, u32 module_id);
int anc_if_set_anc_mic_spkr_layout(u16 port_id,
struct aud_msvc_param_id_dev_anc_mic_spkr_layout_info *set_mic_spkr_layout_p);
+int anc_if_set_algo_module_cali_data(u16 port_id, void *data_p);
+
+int anc_if_get_algo_module_cali_data(u16 port_id, void *data_p);
+
int anc_if_shared_mem_map(void);
int anc_if_shared_mem_unmap(void);
diff --git a/include/linux/rculist.h b/include/linux/rculist.h
index 5ed540986019..0c94d17a4642 100644
--- a/include/linux/rculist.h
+++ b/include/linux/rculist.h
@@ -45,19 +45,17 @@ static inline void INIT_LIST_HEAD_RCU(struct list_head *list)
* This is only for internal list manipulation where we know
* the prev/next entries already!
*/
-#ifndef CONFIG_DEBUG_LIST
static inline void __list_add_rcu(struct list_head *new,
struct list_head *prev, struct list_head *next)
{
+ if (!__list_add_valid(new, prev, next))
+ return;
+
new->next = next;
new->prev = prev;
rcu_assign_pointer(list_next_rcu(prev), new);
next->prev = new;
}
-#else
-void __list_add_rcu(struct list_head *new,
- struct list_head *prev, struct list_head *next);
-#endif
/**
* list_add_rcu - add a new entry to rcu-protected list
diff --git a/include/linux/sched.h b/include/linux/sched.h
index 5fe8c3dfd60f..8f6894c6e83c 100644
--- a/include/linux/sched.h
+++ b/include/linux/sched.h
@@ -1726,7 +1726,7 @@ struct task_struct {
struct mm_struct *mm, *active_mm;
/* per-thread vma caching */
- u32 vmacache_seqnum;
+ u64 vmacache_seqnum;
struct vm_area_struct *vmacache[VMACACHE_SIZE];
#if defined(SPLIT_RSS_COUNTING)
struct task_rss_stat rss_stat;
diff --git a/include/linux/syscalls.h b/include/linux/syscalls.h
index c2b66a277e98..5d2779aa4bbe 100644
--- a/include/linux/syscalls.h
+++ b/include/linux/syscalls.h
@@ -205,6 +205,26 @@ extern struct trace_event_functions exit_syscall_print_funcs;
} \
static inline long SYSC##name(__MAP(x,__SC_DECL,__VA_ARGS__))
+/*
+ * Called before coming back to user-mode. Returning to user-mode with an
+ * address limit different than USER_DS can allow to overwrite kernel memory.
+ */
+static inline void addr_limit_user_check(void)
+{
+#ifdef TIF_FSCHECK
+ if (!test_thread_flag(TIF_FSCHECK))
+ return;
+#endif
+
+ if (CHECK_DATA_CORRUPTION(!segment_eq(get_fs(), USER_DS),
+ "Invalid address limit on user-mode return"))
+ force_sig(SIGKILL, current);
+
+#ifdef TIF_FSCHECK
+ clear_thread_flag(TIF_FSCHECK);
+#endif
+}
+
asmlinkage long sys32_quotactl(unsigned int cmd, const char __user *special,
qid_t id, void __user *addr);
asmlinkage long sys_time(time_t __user *tloc);
diff --git a/include/linux/vm_event_item.h b/include/linux/vm_event_item.h
index 056b4e5830a6..d31afe5d790d 100644
--- a/include/linux/vm_event_item.h
+++ b/include/linux/vm_event_item.h
@@ -89,7 +89,6 @@ enum vm_event_item { PGPGIN, PGPGOUT, PGPGOUTCLEAN, PSWPIN, PSWPOUT,
#ifdef CONFIG_DEBUG_VM_VMACACHE
VMACACHE_FIND_CALLS,
VMACACHE_FIND_HITS,
- VMACACHE_FULL_FLUSHES,
#endif
NR_VM_EVENT_ITEMS
};
diff --git a/include/linux/vmacache.h b/include/linux/vmacache.h
index c3fa0fd43949..4f58ff2dacd6 100644
--- a/include/linux/vmacache.h
+++ b/include/linux/vmacache.h
@@ -15,7 +15,6 @@ static inline void vmacache_flush(struct task_struct *tsk)
memset(tsk->vmacache, 0, sizeof(tsk->vmacache));
}
-extern void vmacache_flush_all(struct mm_struct *mm);
extern void vmacache_update(unsigned long addr, struct vm_area_struct *newvma);
extern struct vm_area_struct *vmacache_find(struct mm_struct *mm,
unsigned long addr);
@@ -29,10 +28,6 @@ extern struct vm_area_struct *vmacache_find_exact(struct mm_struct *mm,
static inline void vmacache_invalidate(struct mm_struct *mm)
{
mm->vmacache_seqnum++;
-
- /* deal with overflows */
- if (unlikely(mm->vmacache_seqnum == 0))
- vmacache_flush_all(mm);
}
#endif /* __LINUX_VMACACHE_H */
diff --git a/include/net/cnss2.h b/include/net/cnss2.h
index e06f0b670d90..7ca407f6b606 100644
--- a/include/net/cnss2.h
+++ b/include/net/cnss2.h
@@ -192,6 +192,9 @@ extern void cnss_lock_pm_sem(struct device *dev);
extern void cnss_release_pm_sem(struct device *dev);
extern int cnss_auto_suspend(struct device *dev);
extern int cnss_auto_resume(struct device *dev);
+extern int cnss_pci_force_wake_request(struct device *dev);
+extern int cnss_pci_is_device_awake(struct device *dev);
+extern int cnss_pci_force_wake_release(struct device *dev);
extern int cnss_get_user_msi_assignment(struct device *dev, char *user_name,
int *num_vectors,
uint32_t *user_base_data,
diff --git a/include/uapi/drm/msm_drm.h b/include/uapi/drm/msm_drm.h
index 30dbd1c34335..583ebc4616e9 100644
--- a/include/uapi/drm/msm_drm.h
+++ b/include/uapi/drm/msm_drm.h
@@ -62,6 +62,15 @@ struct drm_msm_timespec {
__s64 tv_nsec; /* nanoseconds */
};
+/* From CEA.861.3 */
+#define HDR_EOTF_SMTPE_ST2084 0x2
+#define HDR_EOTF_HLG 0x3
+
+/* hdr hdmi state takes possible values of 0, 1 and 2 respectively */
+#define DRM_MSM_HDR_DISABLE 0
+#define DRM_MSM_HDR_ENABLE 1
+#define DRM_MSM_HDR_RESET 2
+
/*
* HDR Metadata
* These are defined as per EDID spec and shall be used by the sink
diff --git a/include/uapi/linux/android/binder.h b/include/uapi/linux/android/binder.h
index 5539933b3491..bd0da0e992b8 100644
--- a/include/uapi/linux/android/binder.h
+++ b/include/uapi/linux/android/binder.h
@@ -246,6 +246,15 @@ struct binder_node_debug_info {
__u32 has_weak_ref;
};
+struct binder_node_info_for_ref {
+ __u32 handle;
+ __u32 strong_count;
+ __u32 weak_count;
+ __u32 reserved1;
+ __u32 reserved2;
+ __u32 reserved3;
+};
+
#define BINDER_WRITE_READ _IOWR('b', 1, struct binder_write_read)
#define BINDER_SET_IDLE_TIMEOUT _IOW('b', 3, __s64)
#define BINDER_SET_MAX_THREADS _IOW('b', 5, __u32)
@@ -254,6 +263,7 @@ struct binder_node_debug_info {
#define BINDER_THREAD_EXIT _IOW('b', 8, __s32)
#define BINDER_VERSION _IOWR('b', 9, struct binder_version)
#define BINDER_GET_NODE_DEBUG_INFO _IOWR('b', 11, struct binder_node_debug_info)
+#define BINDER_GET_NODE_INFO_FOR_REF _IOWR('b', 12, struct binder_node_info_for_ref)
/*
* NOTE: Two special error codes you should check for when calling
diff --git a/include/uapi/linux/ethtool.h b/include/uapi/linux/ethtool.h
index cd1629170103..08f47e0e9f8d 100644
--- a/include/uapi/linux/ethtool.h
+++ b/include/uapi/linux/ethtool.h
@@ -819,13 +819,13 @@ struct ethtool_rx_flow_spec {
static inline __u64 ethtool_get_flow_spec_ring(__u64 ring_cookie)
{
return ETHTOOL_RX_FLOW_SPEC_RING & ring_cookie;
-};
+}
static inline __u64 ethtool_get_flow_spec_ring_vf(__u64 ring_cookie)
{
return (ETHTOOL_RX_FLOW_SPEC_RING_VF & ring_cookie) >>
ETHTOOL_RX_FLOW_SPEC_RING_VF_OFF;
-};
+}
/**
* struct ethtool_rxnfc - command to get or set RX flow classification rules
diff --git a/include/uapi/linux/msm_audio_anc.h b/include/uapi/linux/msm_audio_anc.h
index d628f7ce9267..87701fd8ee3a 100644
--- a/include/uapi/linux/msm_audio_anc.h
+++ b/include/uapi/linux/msm_audio_anc.h
@@ -21,6 +21,8 @@
/* room for ANC_CMD define extend */
#define ANC_CMD_MAX 0xFF
+#define ANC_CALIBRATION_PAYLOAD_SIZE_MAX 100
+
struct audio_anc_header {
int32_t data_size;
int32_t version;
@@ -35,14 +37,23 @@ struct audio_anc_rpm_info {
struct audio_anc_bypass_mode {
int32_t mode;
};
-
struct audio_anc_algo_module_info {
int32_t module_id;
};
+struct audio_anc_algo_calibration_header {
+ uint32_t module_id;
+ uint32_t param_id;
+ uint32_t payload_size;
+};
+
+struct audio_anc_algo_calibration_body {
+ int32_t payload[ANC_CALIBRATION_PAYLOAD_SIZE_MAX];
+};
+
struct audio_anc_algo_calibration_info {
- int32_t payload_size;
- /* num bytes of payload specificed in payload_size followed */
+ struct audio_anc_algo_calibration_header cali_header;
+ struct audio_anc_algo_calibration_body cali_body;
};
union audio_anc_data {
diff --git a/include/uapi/linux/msm_kgsl.h b/include/uapi/linux/msm_kgsl.h
index 13bb8b79359a..005fb8284524 100644
--- a/include/uapi/linux/msm_kgsl.h
+++ b/include/uapi/linux/msm_kgsl.h
@@ -322,6 +322,8 @@ enum kgsl_timestamp_type {
#define KGSL_PROP_DEVICE_QDSS_STM 0x19
#define KGSL_PROP_DEVICE_QTIMER 0x20
#define KGSL_PROP_IB_TIMEOUT 0x21
+#define KGSL_PROP_SECURE_BUFFER_ALIGNMENT 0x23
+#define KGSL_PROP_SECURE_CTXT_SUPPORT 0x24
struct kgsl_shadowprop {
unsigned long gpuaddr;
diff --git a/kernel/audit_watch.c b/kernel/audit_watch.c
index a162661c9d60..f45a9a5d3e47 100644
--- a/kernel/audit_watch.c
+++ b/kernel/audit_watch.c
@@ -419,6 +419,13 @@ int audit_add_watch(struct audit_krule *krule, struct list_head **list)
struct path parent_path;
int h, ret = 0;
+ /*
+ * When we will be calling audit_add_to_parent, krule->watch might have
+ * been updated and watch might have been freed.
+ * So we need to keep a reference of watch.
+ */
+ audit_get_watch(watch);
+
mutex_unlock(&audit_filter_mutex);
/* Avoid calling path_lookup under audit_filter_mutex. */
@@ -427,8 +434,10 @@ int audit_add_watch(struct audit_krule *krule, struct list_head **list)
/* caller expects mutex locked */
mutex_lock(&audit_filter_mutex);
- if (ret)
+ if (ret) {
+ audit_put_watch(watch);
return ret;
+ }
/* either find an old parent or attach a new one */
parent = audit_find_parent(d_backing_inode(parent_path.dentry));
@@ -446,6 +455,7 @@ int audit_add_watch(struct audit_krule *krule, struct list_head **list)
*list = &audit_inode_hash[h];
error:
path_put(&parent_path);
+ audit_put_watch(watch);
return ret;
}
diff --git a/kernel/fork.c b/kernel/fork.c
index caa23ca489bb..77a21c3d02e3 100644
--- a/kernel/fork.c
+++ b/kernel/fork.c
@@ -1142,7 +1142,9 @@ static int copy_sighand(unsigned long clone_flags, struct task_struct *tsk)
return -ENOMEM;
atomic_set(&sig->count, 1);
+ spin_lock_irq(&current->sighand->siglock);
memcpy(sig->action, current->sighand->action, sizeof(sig->action));
+ spin_unlock_irq(&current->sighand->siglock);
return 0;
}
@@ -1370,6 +1372,18 @@ static struct task_struct *copy_process(unsigned long clone_flags,
cpufreq_task_times_init(p);
+ /*
+ * This _must_ happen before we call free_task(), i.e. before we jump
+ * to any of the bad_fork_* labels. This is to avoid freeing
+ * p->set_child_tid which is (ab)used as a kthread's data pointer for
+ * kernel threads (PF_KTHREAD).
+ */
+ p->set_child_tid = (clone_flags & CLONE_CHILD_SETTID) ? child_tidptr : NULL;
+ /*
+ * Clear TID on mm_release()?
+ */
+ p->clear_child_tid = (clone_flags & CLONE_CHILD_CLEARTID) ? child_tidptr : NULL;
+
ftrace_graph_init_task(p);
rt_mutex_init_task(p);
@@ -1531,11 +1545,6 @@ static struct task_struct *copy_process(unsigned long clone_flags,
}
}
- p->set_child_tid = (clone_flags & CLONE_CHILD_SETTID) ? child_tidptr : NULL;
- /*
- * Clear TID on mm_release()?
- */
- p->clear_child_tid = (clone_flags & CLONE_CHILD_CLEARTID) ? child_tidptr : NULL;
#ifdef CONFIG_BLOCK
p->plug = NULL;
#endif
diff --git a/kernel/irq/chip.c b/kernel/irq/chip.c
index e0449956298e..825ae448c7a9 100644
--- a/kernel/irq/chip.c
+++ b/kernel/irq/chip.c
@@ -338,7 +338,6 @@ void handle_nested_irq(unsigned int irq)
raw_spin_lock_irq(&desc->lock);
desc->istate &= ~(IRQS_REPLAY | IRQS_WAITING);
- kstat_incr_irqs_this_cpu(desc);
action = desc->action;
if (unlikely(!action || irqd_irq_disabled(&desc->irq_data))) {
@@ -346,6 +345,7 @@ void handle_nested_irq(unsigned int irq)
goto out_unlock;
}
+ kstat_incr_irqs_this_cpu(desc);
irqd_set(&desc->irq_data, IRQD_IRQ_INPROGRESS);
raw_spin_unlock_irq(&desc->lock);
@@ -412,13 +412,13 @@ void handle_simple_irq(struct irq_desc *desc)
goto out_unlock;
desc->istate &= ~(IRQS_REPLAY | IRQS_WAITING);
- kstat_incr_irqs_this_cpu(desc);
if (unlikely(!desc->action || irqd_irq_disabled(&desc->irq_data))) {
desc->istate |= IRQS_PENDING;
goto out_unlock;
}
+ kstat_incr_irqs_this_cpu(desc);
handle_irq_event(desc);
out_unlock:
@@ -462,7 +462,6 @@ void handle_level_irq(struct irq_desc *desc)
goto out_unlock;
desc->istate &= ~(IRQS_REPLAY | IRQS_WAITING);
- kstat_incr_irqs_this_cpu(desc);
/*
* If its disabled or no action available
@@ -473,6 +472,7 @@ void handle_level_irq(struct irq_desc *desc)
goto out_unlock;
}
+ kstat_incr_irqs_this_cpu(desc);
handle_irq_event(desc);
cond_unmask_irq(desc);
@@ -532,7 +532,6 @@ void handle_fasteoi_irq(struct irq_desc *desc)
goto out;
desc->istate &= ~(IRQS_REPLAY | IRQS_WAITING);
- kstat_incr_irqs_this_cpu(desc);
/*
* If its disabled or no action available
@@ -544,6 +543,7 @@ void handle_fasteoi_irq(struct irq_desc *desc)
goto out;
}
+ kstat_incr_irqs_this_cpu(desc);
if (desc->istate & IRQS_ONESHOT)
mask_irq(desc);
diff --git a/kernel/locking/rwsem-xadd.c b/kernel/locking/rwsem-xadd.c
index 75c950ede9c7..1be33caf157d 100644
--- a/kernel/locking/rwsem-xadd.c
+++ b/kernel/locking/rwsem-xadd.c
@@ -511,38 +511,30 @@ struct rw_semaphore *rwsem_wake(struct rw_semaphore *sem)
unsigned long flags;
/*
- * If a spinner is present, there is a chance that the load of
- * rwsem_has_spinner() in rwsem_wake() can be reordered with
- * respect to decrement of rwsem count in __up_write() leading
- * to wakeup being missed.
- *
- * spinning writer up_write caller
- * --------------- -----------------------
- * [S] osq_unlock() [L] osq
- * spin_lock(wait_lock)
- * sem->count=0xFFFFFFFF00000001
- * +0xFFFFFFFF00000000
- * count=sem->count
- * MB
- * sem->count=0xFFFFFFFE00000001
- * -0xFFFFFFFF00000001
- * RMB
- * spin_trylock(wait_lock)
- * return
- * rwsem_try_write_lock(count)
- * spin_unlock(wait_lock)
- * schedule()
- *
- * Reordering of atomic_long_sub_return_release() in __up_write()
- * and rwsem_has_spinner() in rwsem_wake() can cause missing of
- * wakeup in up_write() context. In spinning writer, sem->count
- * and local variable count is 0XFFFFFFFE00000001. It would result
- * in rwsem_try_write_lock() failing to acquire rwsem and spinning
- * writer going to sleep in rwsem_down_write_failed().
- *
- * The smp_rmb() here is to make sure that the spinner state is
- * consulted after sem->count is updated in up_write context.
- */
+ * __rwsem_down_write_failed_common(sem)
+ * rwsem_optimistic_spin(sem)
+ * osq_unlock(sem->osq)
+ * ...
+ * atomic_long_add_return(&sem->count)
+ *
+ * - VS -
+ *
+ * __up_write()
+ * if (atomic_long_sub_return_release(&sem->count) < 0)
+ * rwsem_wake(sem)
+ * osq_is_locked(&sem->osq)
+ *
+ * And __up_write() must observe !osq_is_locked() when it observes the
+ * atomic_long_add_return() in order to not miss a wakeup.
+ *
+ * This boils down to:
+ *
+ * [S.rel] X = 1 [RmW] r0 = (Y += 0)
+ * MB RMB
+ * [RmW] Y += 1 [L] r1 = X
+ *
+ * exists (r0=1 /\ r1=0)
+ */
smp_rmb();
/*
diff --git a/lib/Kconfig.debug b/lib/Kconfig.debug
index 2d8447a1674b..17fcf03bb384 100644
--- a/lib/Kconfig.debug
+++ b/lib/Kconfig.debug
@@ -588,6 +588,14 @@ config DEBUG_VM_RB
If unsure, say N.
+config DEBUG_VM_PGFLAGS
+ bool "Debug page-flags operations"
+ depends on DEBUG_VM
+ help
+ Enables extra validation on page flags operations.
+
+ If unsure, say N.
+
config DEBUG_VIRTUAL
bool "Debug VM translations"
depends on DEBUG_KERNEL && X86
@@ -2000,6 +2008,16 @@ config PANIC_ON_DATA_CORRUPTION
recoverable data corruption scenarios to system-halting panics,
for easier detection and debug.
+config BUG_ON_DATA_CORRUPTION
+ bool "Trigger a BUG when data corruption is detected"
+ select CONFIG_DEBUG_LIST
+ help
+ Select this option if the kernel should BUG when it encounters
+ data corruption in kernel memory structures when they get checked
+ for validity.
+
+ If unsure, say N.
+
source "samples/Kconfig"
source "lib/Kconfig.kgdb"
diff --git a/lib/debugobjects.c b/lib/debugobjects.c
index 9ddee8c271a7..04e3bb84560e 100644
--- a/lib/debugobjects.c
+++ b/lib/debugobjects.c
@@ -297,9 +297,12 @@ static void debug_object_is_on_stack(void *addr, int onstack)
limit++;
if (is_on_stack)
- pr_warn("object is on stack, but not annotated\n");
+ pr_warn("object %p is on stack %p, but NOT annotated.\n", addr,
+ task_stack_page(current));
else
- pr_warn("object is not on stack, but annotated\n");
+ pr_warn("object %p is NOT on stack %p, but annotated.\n", addr,
+ task_stack_page(current));
+
WARN_ON(1);
}
diff --git a/lib/list_debug.c b/lib/list_debug.c
index 8cf180bfaabe..18b872cc4242 100644
--- a/lib/list_debug.c
+++ b/lib/list_debug.c
@@ -2,8 +2,7 @@
* Copyright 2006, Red Hat, Inc., Dave Jones
* Released under the General Public License (GPL).
*
- * This file contains the linked list implementations for
- * DEBUG_LIST.
+ * This file contains the linked list validation for DEBUG_LIST.
*/
#include <linux/export.h>
@@ -14,94 +13,51 @@
#include <linux/bug.h>
/*
- * Insert a new entry between two known consecutive entries.
- *
- * This is only for internal list manipulation where we know
- * the prev/next entries already!
+ * Check that the data structures for the list manipulations are reasonably
+ * valid. Failures here indicate memory corruption (and possibly an exploit
+ * attempt).
*/
-void __list_add(struct list_head *new,
- struct list_head *prev,
- struct list_head *next)
+bool __list_add_valid(struct list_head *new, struct list_head *prev,
+ struct list_head *next)
{
- WARN(next->prev != prev,
- "list_add corruption. next->prev should be "
- "prev (%p), but was %p. (next=%p).\n",
- prev, next->prev, next);
- WARN(prev->next != next,
- "list_add corruption. prev->next should be "
- "next (%p), but was %p. (prev=%p).\n",
- next, prev->next, prev);
- WARN(new == prev || new == next,
- "list_add double add: new=%p, prev=%p, next=%p.\n",
- new, prev, next);
-
- BUG_ON((prev->next != next || next->prev != prev ||
- new == prev || new == next) && PANIC_CORRUPTION);
-
- next->prev = new;
- new->next = next;
- new->prev = prev;
- prev->next = new;
+ if (CHECK_DATA_CORRUPTION(next->prev != prev,
+ "list_add corruption. next->prev should be prev (%p), but was %p. (next=%p).\n",
+ prev, next->prev, next) ||
+ CHECK_DATA_CORRUPTION(prev->next != next,
+ "list_add corruption. prev->next should be next (%p), but was %p. (prev=%p).\n",
+ next, prev->next, prev) ||
+ CHECK_DATA_CORRUPTION(new == prev || new == next,
+ "list_add double add: new=%p, prev=%p, next=%p.\n",
+ new, prev, next))
+ return false;
+
+ return true;
}
-EXPORT_SYMBOL(__list_add);
+EXPORT_SYMBOL(__list_add_valid);
-void __list_del_entry(struct list_head *entry)
+bool __list_del_entry_valid(struct list_head *entry)
{
struct list_head *prev, *next;
prev = entry->prev;
next = entry->next;
- if (WARN(next == LIST_POISON1,
- "list_del corruption, %p->next is LIST_POISON1 (%p)\n",
- entry, LIST_POISON1) ||
- WARN(prev == LIST_POISON2,
- "list_del corruption, %p->prev is LIST_POISON2 (%p)\n",
- entry, LIST_POISON2) ||
- WARN(prev->next != entry,
- "list_del corruption. prev->next should be %p, "
- "but was %p\n", entry, prev->next) ||
- WARN(next->prev != entry,
- "list_del corruption. next->prev should be %p, "
- "but was %p\n", entry, next->prev)) {
- BUG_ON(PANIC_CORRUPTION);
- return;
- }
-
- __list_del(prev, next);
-}
-EXPORT_SYMBOL(__list_del_entry);
-
-/**
- * list_del - deletes entry from list.
- * @entry: the element to delete from the list.
- * Note: list_empty on entry does not return true after this, the entry is
- * in an undefined state.
- */
-void list_del(struct list_head *entry)
-{
- __list_del_entry(entry);
- entry->next = LIST_POISON1;
- entry->prev = LIST_POISON2;
-}
-EXPORT_SYMBOL(list_del);
+ if (CHECK_DATA_CORRUPTION(next == LIST_POISON1,
+ "list_del corruption, %p->next is LIST_POISON1 (%p)\n",
+ entry, LIST_POISON1) ||
+ CHECK_DATA_CORRUPTION(prev == LIST_POISON2,
+ "list_del corruption, %p->prev is LIST_POISON2 (%p)\n",
+ entry, LIST_POISON2) ||
+ CHECK_DATA_CORRUPTION(prev->next != entry,
+ "list_del corruption. prev->next should be %p, but was %p\n",
+ entry, prev->next) ||
+ CHECK_DATA_CORRUPTION(next->prev != entry,
+ "list_del corruption. next->prev should be %p, but was %p\n",
+ entry, next->prev))
+ return false;
+
+ return true;
-/*
- * RCU variants.
- */
-void __list_add_rcu(struct list_head *new,
- struct list_head *prev, struct list_head *next)
-{
- WARN(next->prev != prev,
- "list_add_rcu corruption. next->prev should be prev (%p), but was %p. (next=%p).\n",
- prev, next->prev, next);
- WARN(prev->next != next,
- "list_add_rcu corruption. prev->next should be next (%p), but was %p. (prev=%p).\n",
- next, prev->next, prev);
- new->next = next;
- new->prev = prev;
- rcu_assign_pointer(list_next_rcu(prev), new);
- next->prev = new;
}
-EXPORT_SYMBOL(__list_add_rcu);
+EXPORT_SYMBOL(__list_del_entry_valid);
diff --git a/mm/debug.c b/mm/debug.c
index 3621385c09ac..89ac083ea504 100644
--- a/mm/debug.c
+++ b/mm/debug.c
@@ -184,7 +184,7 @@ EXPORT_SYMBOL(dump_vma);
void dump_mm(const struct mm_struct *mm)
{
- pr_emerg("mm %p mmap %p seqnum %d task_size %lu\n"
+ pr_emerg("mm %p mmap %p seqnum %llu task_size %lu\n"
#ifdef CONFIG_MMU
"get_unmapped_area %p\n"
#endif
@@ -214,7 +214,7 @@ void dump_mm(const struct mm_struct *mm)
#endif
"%s", /* This is here to hold the comma */
- mm, mm->mmap, mm->vmacache_seqnum, mm->task_size,
+ mm, mm->mmap, (long long) mm->vmacache_seqnum, mm->task_size,
#ifdef CONFIG_MMU
mm->get_unmapped_area,
#endif
diff --git a/mm/fadvise.c b/mm/fadvise.c
index b8a5bc66b0c0..001877e32f0c 100644
--- a/mm/fadvise.c
+++ b/mm/fadvise.c
@@ -68,8 +68,12 @@ SYSCALL_DEFINE4(fadvise64_64, int, fd, loff_t, offset, loff_t, len, int, advice)
goto out;
}
- /* Careful about overflows. Len == 0 means "as much as possible" */
- endbyte = offset + len;
+ /*
+ * Careful about overflows. Len == 0 means "as much as possible". Use
+ * unsigned math because signed overflows are undefined and UBSan
+ * complains.
+ */
+ endbyte = (u64)offset + (u64)len;
if (!len || endbyte < len)
endbyte = -1;
else
diff --git a/mm/filemap.c b/mm/filemap.c
index 6aa6f0cc67e1..ea5c7a6e20d2 100644
--- a/mm/filemap.c
+++ b/mm/filemap.c
@@ -689,11 +689,11 @@ int add_to_page_cache_lru(struct page *page, struct address_space *mapping,
void *shadow = NULL;
int ret;
- __set_page_locked(page);
+ __SetPageLocked(page);
ret = __add_to_page_cache_locked(page, mapping, offset,
gfp_mask, &shadow);
if (unlikely(ret))
- __clear_page_locked(page);
+ __ClearPageLocked(page);
else {
/*
* The page might have been evicted from cache only
@@ -816,6 +816,7 @@ EXPORT_SYMBOL_GPL(add_page_wait_queue);
*/
void unlock_page(struct page *page)
{
+ page = compound_head(page);
VM_BUG_ON_PAGE(!PageLocked(page), page);
clear_bit_unlock(PG_locked, &page->flags);
smp_mb__after_atomic();
@@ -883,18 +884,20 @@ EXPORT_SYMBOL_GPL(page_endio);
*/
void __lock_page(struct page *page)
{
- DEFINE_WAIT_BIT(wait, &page->flags, PG_locked);
+ struct page *page_head = compound_head(page);
+ DEFINE_WAIT_BIT(wait, &page_head->flags, PG_locked);
- __wait_on_bit_lock(page_waitqueue(page), &wait, bit_wait_io,
+ __wait_on_bit_lock(page_waitqueue(page_head), &wait, bit_wait_io,
TASK_UNINTERRUPTIBLE);
}
EXPORT_SYMBOL(__lock_page);
int __lock_page_killable(struct page *page)
{
- DEFINE_WAIT_BIT(wait, &page->flags, PG_locked);
+ struct page *page_head = compound_head(page);
+ DEFINE_WAIT_BIT(wait, &page_head->flags, PG_locked);
- return __wait_on_bit_lock(page_waitqueue(page), &wait,
+ return __wait_on_bit_lock(page_waitqueue(page_head), &wait,
bit_wait_io, TASK_KILLABLE);
}
EXPORT_SYMBOL_GPL(__lock_page_killable);
diff --git a/mm/huge_memory.c b/mm/huge_memory.c
index d64d48ca789c..67f5a8ca0af1 100644
--- a/mm/huge_memory.c
+++ b/mm/huge_memory.c
@@ -1392,12 +1392,12 @@ int do_huge_pmd_numa_page(struct mm_struct *mm, struct vm_area_struct *vma,
/* Migration could have started since the pmd_trans_migrating check */
if (!page_locked) {
+ page_nid = -1;
if (!get_page_unless_zero(page))
goto out_unlock;
spin_unlock(ptl);
wait_on_page_locked(page);
put_page(page);
- page_nid = -1;
goto out;
}
diff --git a/mm/ksm.c b/mm/ksm.c
index 33a790d85142..5766229a3507 100644
--- a/mm/ksm.c
+++ b/mm/ksm.c
@@ -1989,7 +1989,7 @@ struct page *ksm_might_need_to_copy(struct page *page,
SetPageDirty(new_page);
__SetPageUptodate(new_page);
- __set_page_locked(new_page);
+ __SetPageLocked(new_page);
}
return new_page;
diff --git a/mm/memory-failure.c b/mm/memory-failure.c
index d4271ebc37d0..d5d9839ede9b 100644
--- a/mm/memory-failure.c
+++ b/mm/memory-failure.c
@@ -1173,7 +1173,7 @@ int memory_failure(unsigned long pfn, int trapno, int flags)
/*
* We ignore non-LRU pages for good reasons.
* - PG_locked is only well defined for LRU pages and a few others
- * - to avoid races with __set_page_locked()
+ * - to avoid races with __SetPageLocked()
* - to avoid races with __SetPageSlab*() (and more non-atomic ops)
* The check (unnecessarily) ignores LRU pages being isolated and
* walked by the page reclaim code, however that's not a big loss.
diff --git a/mm/migrate.c b/mm/migrate.c
index 921cf12b03ce..879aabed46bb 100644
--- a/mm/migrate.c
+++ b/mm/migrate.c
@@ -1936,7 +1936,7 @@ int migrate_misplaced_transhuge_page(struct mm_struct *mm,
flush_tlb_range(vma, mmun_start, mmun_end);
/* Prepare a page as a migration target */
- __set_page_locked(new_page);
+ __SetPageLocked(new_page);
SetPageSwapBacked(new_page);
/* anon mapping, we can simply copy page->mapping to the new page: */
diff --git a/mm/shmem.c b/mm/shmem.c
index 79997e8cf807..9bdb044d4dee 100644
--- a/mm/shmem.c
+++ b/mm/shmem.c
@@ -1003,7 +1003,7 @@ static int shmem_replace_page(struct page **pagep, gfp_t gfp,
copy_highpage(newpage, oldpage);
flush_dcache_page(newpage);
- __set_page_locked(newpage);
+ __SetPageLocked(newpage);
SetPageUptodate(newpage);
SetPageSwapBacked(newpage);
set_page_private(newpage, swap_index);
@@ -1195,7 +1195,7 @@ repeat:
}
__SetPageSwapBacked(page);
- __set_page_locked(page);
+ __SetPageLocked(page);
if (sgp == SGP_WRITE)
__SetPageReferenced(page);
diff --git a/mm/slub.c b/mm/slub.c
index 675e6efd5c8f..f806a8af741f 100644
--- a/mm/slub.c
+++ b/mm/slub.c
@@ -333,11 +333,13 @@ static inline int oo_objects(struct kmem_cache_order_objects x)
*/
static __always_inline void slab_lock(struct page *page)
{
+ VM_BUG_ON_PAGE(PageTail(page), page);
bit_spin_lock(PG_locked, &page->flags);
}
static __always_inline void slab_unlock(struct page *page)
{
+ VM_BUG_ON_PAGE(PageTail(page), page);
__bit_spin_unlock(PG_locked, &page->flags);
}
diff --git a/mm/swap_state.c b/mm/swap_state.c
index 61039e39e25f..9f49247ef0e6 100644
--- a/mm/swap_state.c
+++ b/mm/swap_state.c
@@ -355,7 +355,7 @@ struct page *__read_swap_cache_async(swp_entry_t entry, gfp_t gfp_mask,
}
/* May fail (-ENOMEM) if radix-tree node allocation failed. */
- __set_page_locked(new_page);
+ __SetPageLocked(new_page);
SetPageSwapBacked(new_page);
err = __add_to_swap_cache(new_page, entry);
if (likely(!err)) {
@@ -369,7 +369,7 @@ struct page *__read_swap_cache_async(swp_entry_t entry, gfp_t gfp_mask,
}
radix_tree_preload_end();
ClearPageSwapBacked(new_page);
- __clear_page_locked(new_page);
+ __ClearPageLocked(new_page);
/*
* add_to_swap_cache() doesn't return -EEXIST, so we can safely
* clear SWAP_HAS_CACHE flag.
diff --git a/mm/vmacache.c b/mm/vmacache.c
index fd09dc9c6812..9c8ff3d4eda9 100644
--- a/mm/vmacache.c
+++ b/mm/vmacache.c
@@ -6,44 +6,6 @@
#include <linux/vmacache.h>
/*
- * Flush vma caches for threads that share a given mm.
- *
- * The operation is safe because the caller holds the mmap_sem
- * exclusively and other threads accessing the vma cache will
- * have mmap_sem held at least for read, so no extra locking
- * is required to maintain the vma cache.
- */
-void vmacache_flush_all(struct mm_struct *mm)
-{
- struct task_struct *g, *p;
-
- count_vm_vmacache_event(VMACACHE_FULL_FLUSHES);
-
- /*
- * Single threaded tasks need not iterate the entire
- * list of process. We can avoid the flushing as well
- * since the mm's seqnum was increased and don't have
- * to worry about other threads' seqnum. Current's
- * flush will occur upon the next lookup.
- */
- if (atomic_read(&mm->mm_users) == 1)
- return;
-
- rcu_read_lock();
- for_each_process_thread(g, p) {
- /*
- * Only flush the vmacache pointers as the
- * mm seqnum is already set and curr's will
- * be set upon invalidation when the next
- * lookup is done.
- */
- if (mm == p->mm)
- vmacache_flush(p);
- }
- rcu_read_unlock();
-}
-
-/*
* This task may be accessing a foreign mm via (for example)
* get_user_pages()->find_vma(). The vmacache is task-local and this
* task's vmacache pertains to a different mm (ie, its own). There is
diff --git a/mm/vmscan.c b/mm/vmscan.c
index abeea66bc429..aa1074d3031b 100644
--- a/mm/vmscan.c
+++ b/mm/vmscan.c
@@ -1247,7 +1247,7 @@ static unsigned long shrink_page_list(struct list_head *page_list,
* we obviously don't have to worry about waking up a process
* waiting on the page lock, because there are no references.
*/
- __clear_page_locked(page);
+ __ClearPageLocked(page);
free_it:
nr_reclaimed++;
diff --git a/net/9p/trans_virtio.c b/net/9p/trans_virtio.c
index 6018a1c0dc28..2a15b6aa9cdd 100644
--- a/net/9p/trans_virtio.c
+++ b/net/9p/trans_virtio.c
@@ -574,7 +574,7 @@ static int p9_virtio_probe(struct virtio_device *vdev)
chan->vq = virtio_find_single_vq(vdev, req_done, "requests");
if (IS_ERR(chan->vq)) {
err = PTR_ERR(chan->vq);
- goto out_free_vq;
+ goto out_free_chan;
}
chan->vq->vdev->priv = chan;
spin_lock_init(&chan->lock);
@@ -627,6 +627,7 @@ out_free_tag:
kfree(tag);
out_free_vq:
vdev->config->del_vqs(vdev);
+out_free_chan:
kfree(chan);
fail:
return err;
diff --git a/net/bluetooth/hidp/core.c b/net/bluetooth/hidp/core.c
index a295b5ec9d4a..e614940c4e98 100644
--- a/net/bluetooth/hidp/core.c
+++ b/net/bluetooth/hidp/core.c
@@ -775,7 +775,7 @@ static int hidp_setup_hid(struct hidp_session *session,
hid->version = req->version;
hid->country = req->country;
- strncpy(hid->name, req->name, sizeof(req->name) - 1);
+ strncpy(hid->name, req->name, sizeof(hid->name));
snprintf(hid->phys, sizeof(hid->phys), "%pMR",
&l2cap_pi(session->ctrl_sock->sk)->chan->src);
diff --git a/net/dcb/dcbnl.c b/net/dcb/dcbnl.c
index 4f6c1862dfd2..6fe2b615518c 100644
--- a/net/dcb/dcbnl.c
+++ b/net/dcb/dcbnl.c
@@ -1763,7 +1763,7 @@ static struct dcb_app_type *dcb_app_lookup(const struct dcb_app *app,
if (itr->app.selector == app->selector &&
itr->app.protocol == app->protocol &&
itr->ifindex == ifindex &&
- (!prio || itr->app.priority == prio))
+ ((prio == -1) || itr->app.priority == prio))
return itr;
}
@@ -1798,7 +1798,8 @@ u8 dcb_getapp(struct net_device *dev, struct dcb_app *app)
u8 prio = 0;
spin_lock_bh(&dcb_lock);
- if ((itr = dcb_app_lookup(app, dev->ifindex, 0)))
+ itr = dcb_app_lookup(app, dev->ifindex, -1);
+ if (itr)
prio = itr->app.priority;
spin_unlock_bh(&dcb_lock);
@@ -1826,7 +1827,8 @@ int dcb_setapp(struct net_device *dev, struct dcb_app *new)
spin_lock_bh(&dcb_lock);
/* Search for existing match and replace */
- if ((itr = dcb_app_lookup(new, dev->ifindex, 0))) {
+ itr = dcb_app_lookup(new, dev->ifindex, -1);
+ if (itr) {
if (new->priority)
itr->app.priority = new->priority;
else {
@@ -1859,7 +1861,8 @@ u8 dcb_ieee_getapp_mask(struct net_device *dev, struct dcb_app *app)
u8 prio = 0;
spin_lock_bh(&dcb_lock);
- if ((itr = dcb_app_lookup(app, dev->ifindex, 0)))
+ itr = dcb_app_lookup(app, dev->ifindex, -1);
+ if (itr)
prio |= 1 << itr->app.priority;
spin_unlock_bh(&dcb_lock);
diff --git a/net/ipv4/tcp_minisocks.c b/net/ipv4/tcp_minisocks.c
index 4c1c94fa8f08..d270870bf492 100644
--- a/net/ipv4/tcp_minisocks.c
+++ b/net/ipv4/tcp_minisocks.c
@@ -200,8 +200,9 @@ kill:
inet_twsk_deschedule_put(tw);
return TCP_TW_SUCCESS;
}
+ } else {
+ inet_twsk_reschedule(tw, TCP_TIMEWAIT_LEN);
}
- inet_twsk_reschedule(tw, TCP_TIMEWAIT_LEN);
if (tmp_opt.saw_tstamp) {
tcptw->tw_ts_recent = tmp_opt.rcv_tsval;
diff --git a/net/ipv6/ip6_vti.c b/net/ipv6/ip6_vti.c
index 060862a6f2f2..ca697f16d2ea 100644
--- a/net/ipv6/ip6_vti.c
+++ b/net/ipv6/ip6_vti.c
@@ -470,7 +470,7 @@ vti6_xmit(struct sk_buff *skb, struct net_device *dev, struct flowi *fl)
}
mtu = dst_mtu(dst);
- if (!skb->ignore_df && skb->len > mtu) {
+ if (skb->len > mtu) {
skb_dst(skb)->ops->update_pmtu(dst, NULL, skb, mtu);
if (skb->protocol == htons(ETH_P_IPV6)) {
diff --git a/net/irda/af_irda.c b/net/irda/af_irda.c
index 4a116d766c15..7cc9db38e1b6 100644
--- a/net/irda/af_irda.c
+++ b/net/irda/af_irda.c
@@ -774,6 +774,13 @@ static int irda_bind(struct socket *sock, struct sockaddr *uaddr, int addr_len)
return -EINVAL;
lock_sock(sk);
+
+ /* Ensure that the socket is not already bound */
+ if (self->ias_obj) {
+ err = -EINVAL;
+ goto out;
+ }
+
#ifdef CONFIG_IRDA_ULTRA
/* Special care for Ultra sockets */
if ((sk->sk_type == SOCK_DGRAM) &&
@@ -2020,7 +2027,11 @@ static int irda_setsockopt(struct socket *sock, int level, int optname,
err = -EINVAL;
goto out;
}
- irias_insert_object(ias_obj);
+
+ /* Only insert newly allocated objects */
+ if (free_ias)
+ irias_insert_object(ias_obj);
+
kfree(ias_opt);
break;
case IRLMP_IAS_DEL:
diff --git a/net/mac80211/cfg.c b/net/mac80211/cfg.c
index 00a8cc572a22..1f930032253a 100644
--- a/net/mac80211/cfg.c
+++ b/net/mac80211/cfg.c
@@ -286,7 +286,7 @@ static int ieee80211_del_key(struct wiphy *wiphy, struct net_device *dev,
goto out_unlock;
}
- ieee80211_key_free(key, true);
+ ieee80211_key_free(key, sdata->vif.type == NL80211_IFTYPE_STATION);
ret = 0;
out_unlock:
diff --git a/net/mac80211/key.c b/net/mac80211/key.c
index 4a72c0d1e56f..91a4e606edcd 100644
--- a/net/mac80211/key.c
+++ b/net/mac80211/key.c
@@ -647,11 +647,15 @@ int ieee80211_key_link(struct ieee80211_key *key,
{
struct ieee80211_local *local = sdata->local;
struct ieee80211_key *old_key;
- int idx, ret;
- bool pairwise;
-
- pairwise = key->conf.flags & IEEE80211_KEY_FLAG_PAIRWISE;
- idx = key->conf.keyidx;
+ int idx = key->conf.keyidx;
+ bool pairwise = key->conf.flags & IEEE80211_KEY_FLAG_PAIRWISE;
+ /*
+ * We want to delay tailroom updates only for station - in that
+ * case it helps roaming speed, but in other cases it hurts and
+ * can cause warnings to appear.
+ */
+ bool delay_tailroom = sdata->vif.type == NL80211_IFTYPE_STATION;
+ int ret;
mutex_lock(&sdata->local->key_mtx);
@@ -679,14 +683,14 @@ int ieee80211_key_link(struct ieee80211_key *key,
increment_tailroom_need_count(sdata);
ieee80211_key_replace(sdata, sta, pairwise, old_key, key);
- ieee80211_key_destroy(old_key, true);
+ ieee80211_key_destroy(old_key, delay_tailroom);
ieee80211_debugfs_key_add(key);
if (!local->wowlan) {
ret = ieee80211_key_enable_hw_accel(key);
if (ret)
- ieee80211_key_free(key, true);
+ ieee80211_key_free(key, delay_tailroom);
} else {
ret = 0;
}
@@ -874,7 +878,8 @@ void ieee80211_free_sta_keys(struct ieee80211_local *local,
ieee80211_key_replace(key->sdata, key->sta,
key->conf.flags & IEEE80211_KEY_FLAG_PAIRWISE,
key, NULL);
- __ieee80211_key_destroy(key, true);
+ __ieee80211_key_destroy(key, key->sdata->vif.type ==
+ NL80211_IFTYPE_STATION);
}
for (i = 0; i < NUM_DEFAULT_KEYS; i++) {
@@ -884,7 +889,8 @@ void ieee80211_free_sta_keys(struct ieee80211_local *local,
ieee80211_key_replace(key->sdata, key->sta,
key->conf.flags & IEEE80211_KEY_FLAG_PAIRWISE,
key, NULL);
- __ieee80211_key_destroy(key, true);
+ __ieee80211_key_destroy(key, key->sdata->vif.type ==
+ NL80211_IFTYPE_STATION);
}
mutex_unlock(&local->key_mtx);
diff --git a/net/netfilter/ipvs/ip_vs_core.c b/net/netfilter/ipvs/ip_vs_core.c
index dd1649caa2b2..ac212542a217 100644
--- a/net/netfilter/ipvs/ip_vs_core.c
+++ b/net/netfilter/ipvs/ip_vs_core.c
@@ -1809,13 +1809,20 @@ ip_vs_in(struct netns_ipvs *ipvs, unsigned int hooknum, struct sk_buff *skb, int
if (cp->dest && !(cp->dest->flags & IP_VS_DEST_F_AVAILABLE)) {
/* the destination server is not available */
- if (sysctl_expire_nodest_conn(ipvs)) {
+ __u32 flags = cp->flags;
+
+ /* when timer already started, silently drop the packet.*/
+ if (timer_pending(&cp->timer))
+ __ip_vs_conn_put(cp);
+ else
+ ip_vs_conn_put(cp);
+
+ if (sysctl_expire_nodest_conn(ipvs) &&
+ !(flags & IP_VS_CONN_F_ONE_PACKET)) {
/* try to expire the connection immediately */
ip_vs_conn_expire_now(cp);
}
- /* don't restart its timer, and silently
- drop the packet. */
- __ip_vs_conn_put(cp);
+
return NF_DROP;
}
diff --git a/net/netfilter/x_tables.c b/net/netfilter/x_tables.c
index 1f3c305df45d..b6e72af15237 100644
--- a/net/netfilter/x_tables.c
+++ b/net/netfilter/x_tables.c
@@ -876,7 +876,7 @@ void *xt_copy_counters_from_user(const void __user *user, unsigned int len,
if (copy_from_user(&compat_tmp, user, sizeof(compat_tmp)) != 0)
return ERR_PTR(-EFAULT);
- strlcpy(info->name, compat_tmp.name, sizeof(info->name));
+ memcpy(info->name, compat_tmp.name, sizeof(info->name) - 1);
info->num_counters = compat_tmp.num_counters;
user += sizeof(compat_tmp);
} else
@@ -889,9 +889,9 @@ void *xt_copy_counters_from_user(const void __user *user, unsigned int len,
if (copy_from_user(info, user, sizeof(*info)) != 0)
return ERR_PTR(-EFAULT);
- info->name[sizeof(info->name) - 1] = '\0';
user += sizeof(*info);
}
+ info->name[sizeof(info->name) - 1] = '\0';
size = sizeof(struct xt_counters);
size *= info->num_counters;
diff --git a/net/sched/sch_hhf.c b/net/sched/sch_hhf.c
index 45d4b2f22f62..aff2a1b46f7f 100644
--- a/net/sched/sch_hhf.c
+++ b/net/sched/sch_hhf.c
@@ -501,6 +501,9 @@ static void hhf_destroy(struct Qdisc *sch)
hhf_free(q->hhf_valid_bits[i]);
}
+ if (!q->hh_flows)
+ return;
+
for (i = 0; i < HH_FLOWS_CNT; i++) {
struct hh_flow_state *flow, *next;
struct list_head *head = &q->hh_flows[i];
diff --git a/net/sched/sch_htb.c b/net/sched/sch_htb.c
index 87b02ed3d5f2..daa01d5604c2 100644
--- a/net/sched/sch_htb.c
+++ b/net/sched/sch_htb.c
@@ -1025,6 +1025,9 @@ static int htb_init(struct Qdisc *sch, struct nlattr *opt)
int err;
int i;
+ qdisc_watchdog_init(&q->watchdog, sch);
+ INIT_WORK(&q->work, htb_work_func);
+
if (!opt)
return -EINVAL;
@@ -1045,8 +1048,6 @@ static int htb_init(struct Qdisc *sch, struct nlattr *opt)
for (i = 0; i < TC_HTB_NUMPRIO; i++)
INIT_LIST_HEAD(q->drops + i);
- qdisc_watchdog_init(&q->watchdog, sch);
- INIT_WORK(&q->work, htb_work_func);
__skb_queue_head_init(&q->direct_queue);
if (tb[TCA_HTB_DIRECT_QLEN])
diff --git a/net/sched/sch_multiq.c b/net/sched/sch_multiq.c
index bcdd54bb101c..cef36ad691dd 100644
--- a/net/sched/sch_multiq.c
+++ b/net/sched/sch_multiq.c
@@ -254,7 +254,7 @@ static int multiq_tune(struct Qdisc *sch, struct nlattr *opt)
static int multiq_init(struct Qdisc *sch, struct nlattr *opt)
{
struct multiq_sched_data *q = qdisc_priv(sch);
- int i, err;
+ int i;
q->queues = NULL;
@@ -269,12 +269,7 @@ static int multiq_init(struct Qdisc *sch, struct nlattr *opt)
for (i = 0; i < q->max_bands; i++)
q->queues[i] = &noop_qdisc;
- err = multiq_tune(sch, opt);
-
- if (err)
- kfree(q->queues);
-
- return err;
+ return multiq_tune(sch, opt);
}
static int multiq_dump(struct Qdisc *sch, struct sk_buff *skb)
diff --git a/net/sched/sch_netem.c b/net/sched/sch_netem.c
index b7c29d5b6f04..743ff23885da 100644
--- a/net/sched/sch_netem.c
+++ b/net/sched/sch_netem.c
@@ -943,11 +943,11 @@ static int netem_init(struct Qdisc *sch, struct nlattr *opt)
struct netem_sched_data *q = qdisc_priv(sch);
int ret;
+ qdisc_watchdog_init(&q->watchdog, sch);
+
if (!opt)
return -EINVAL;
- qdisc_watchdog_init(&q->watchdog, sch);
-
q->loss_model = CLG_RANDOM;
ret = netem_change(sch, opt);
if (ret)
diff --git a/net/sched/sch_tbf.c b/net/sched/sch_tbf.c
index c2fbde742f37..a06c9d6bfc9c 100644
--- a/net/sched/sch_tbf.c
+++ b/net/sched/sch_tbf.c
@@ -432,12 +432,13 @@ static int tbf_init(struct Qdisc *sch, struct nlattr *opt)
{
struct tbf_sched_data *q = qdisc_priv(sch);
+ qdisc_watchdog_init(&q->watchdog, sch);
+ q->qdisc = &noop_qdisc;
+
if (opt == NULL)
return -EINVAL;
q->t_c = ktime_get_ns();
- qdisc_watchdog_init(&q->watchdog, sch);
- q->qdisc = &noop_qdisc;
return tbf_change(sch, opt);
}
diff --git a/net/xfrm/xfrm_policy.c b/net/xfrm/xfrm_policy.c
index 4615138b104f..e098ca928538 100644
--- a/net/xfrm/xfrm_policy.c
+++ b/net/xfrm/xfrm_policy.c
@@ -1846,7 +1846,10 @@ xfrm_resolve_and_create_bundle(struct xfrm_policy **pols, int num_pols,
/* Try to instantiate a bundle */
err = xfrm_tmpl_resolve(pols, num_pols, fl, xfrm, family);
if (err <= 0) {
- if (err != 0 && err != -EAGAIN)
+ if (err == 0)
+ return NULL;
+
+ if (err != -EAGAIN)
XFRM_INC_STATS(net, LINUX_MIB_XFRMOUTPOLERROR);
return ERR_PTR(err);
}
diff --git a/scripts/Kbuild.include b/scripts/Kbuild.include
index 0924291ef059..52aa80135426 100644
--- a/scripts/Kbuild.include
+++ b/scripts/Kbuild.include
@@ -373,3 +373,6 @@ endif
endef
#
###############################################################################
+
+# delete partially updated (i.e. corrupted) files on error
+.DELETE_ON_ERROR:
diff --git a/scripts/depmod.sh b/scripts/depmod.sh
index ea1e96921e3b..baedaef53ca0 100755
--- a/scripts/depmod.sh
+++ b/scripts/depmod.sh
@@ -15,9 +15,9 @@ if ! test -r System.map ; then
fi
if [ -z $(command -v $DEPMOD) ]; then
- echo "'make modules_install' requires $DEPMOD. Please install it." >&2
+ echo "Warning: 'make modules_install' requires $DEPMOD. Please install it." >&2
echo "This is probably in the kmod package." >&2
- exit 1
+ exit 0
fi
# older versions of depmod don't support -P <symbol-prefix>
diff --git a/scripts/mod/modpost.c b/scripts/mod/modpost.c
index bd5151915e5a..064fbfbbb22c 100644
--- a/scripts/mod/modpost.c
+++ b/scripts/mod/modpost.c
@@ -649,7 +649,7 @@ static void handle_modversions(struct module *mod, struct elf_info *info,
if (ELF_ST_TYPE(sym->st_info) == STT_SPARC_REGISTER)
break;
if (symname[0] == '.') {
- char *munged = strdup(symname);
+ char *munged = NOFAIL(strdup(symname));
munged[0] = '_';
munged[1] = toupper(munged[1]);
symname = munged;
@@ -1311,7 +1311,7 @@ static Elf_Sym *find_elf_symbol2(struct elf_info *elf, Elf_Addr addr,
static char *sec2annotation(const char *s)
{
if (match(s, init_exit_sections)) {
- char *p = malloc(20);
+ char *p = NOFAIL(malloc(20));
char *r = p;
*p++ = '_';
@@ -1331,7 +1331,7 @@ static char *sec2annotation(const char *s)
strcat(p, " ");
return r;
} else {
- return strdup("");
+ return NOFAIL(strdup(""));
}
}
@@ -2032,7 +2032,7 @@ void buf_write(struct buffer *buf, const char *s, int len)
{
if (buf->size - buf->pos < len) {
buf->size += len + SZ;
- buf->p = realloc(buf->p, buf->size);
+ buf->p = NOFAIL(realloc(buf->p, buf->size));
}
strncpy(buf->p + buf->pos, s, len);
buf->pos += len;
diff --git a/security/selinux/avc.c b/security/selinux/avc.c
index e60c79de13e1..52f3c550abcc 100644
--- a/security/selinux/avc.c
+++ b/security/selinux/avc.c
@@ -348,27 +348,26 @@ static struct avc_xperms_decision_node
struct avc_xperms_decision_node *xpd_node;
struct extended_perms_decision *xpd;
- xpd_node = kmem_cache_zalloc(avc_xperms_decision_cachep,
- GFP_ATOMIC | __GFP_NOMEMALLOC);
+ xpd_node = kmem_cache_zalloc(avc_xperms_decision_cachep, GFP_NOWAIT);
if (!xpd_node)
return NULL;
xpd = &xpd_node->xpd;
if (which & XPERMS_ALLOWED) {
xpd->allowed = kmem_cache_zalloc(avc_xperms_data_cachep,
- GFP_ATOMIC | __GFP_NOMEMALLOC);
+ GFP_NOWAIT);
if (!xpd->allowed)
goto error;
}
if (which & XPERMS_AUDITALLOW) {
xpd->auditallow = kmem_cache_zalloc(avc_xperms_data_cachep,
- GFP_ATOMIC | __GFP_NOMEMALLOC);
+ GFP_NOWAIT);
if (!xpd->auditallow)
goto error;
}
if (which & XPERMS_DONTAUDIT) {
xpd->dontaudit = kmem_cache_zalloc(avc_xperms_data_cachep,
- GFP_ATOMIC | __GFP_NOMEMALLOC);
+ GFP_NOWAIT);
if (!xpd->dontaudit)
goto error;
}
@@ -396,8 +395,7 @@ static struct avc_xperms_node *avc_xperms_alloc(void)
{
struct avc_xperms_node *xp_node;
- xp_node = kmem_cache_zalloc(avc_xperms_cachep,
- GFP_ATOMIC|__GFP_NOMEMALLOC);
+ xp_node = kmem_cache_zalloc(avc_xperms_cachep, GFP_NOWAIT);
if (!xp_node)
return xp_node;
INIT_LIST_HEAD(&xp_node->xpd_head);
@@ -550,7 +548,7 @@ static struct avc_node *avc_alloc_node(void)
{
struct avc_node *node;
- node = kmem_cache_zalloc(avc_node_cachep, GFP_ATOMIC|__GFP_NOMEMALLOC);
+ node = kmem_cache_zalloc(avc_node_cachep, GFP_NOWAIT);
if (!node)
goto out;
diff --git a/sound/core/pcm_lib.c b/sound/core/pcm_lib.c
index 711084a5a029..ddf1cf3c6a45 100644
--- a/sound/core/pcm_lib.c
+++ b/sound/core/pcm_lib.c
@@ -652,27 +652,33 @@ EXPORT_SYMBOL(snd_interval_refine);
static int snd_interval_refine_first(struct snd_interval *i)
{
+ const unsigned int last_max = i->max;
+
if (snd_BUG_ON(snd_interval_empty(i)))
return -EINVAL;
if (snd_interval_single(i))
return 0;
i->max = i->min;
- i->openmax = i->openmin;
- if (i->openmax)
+ if (i->openmin)
i->max++;
+ /* only exclude max value if also excluded before refine */
+ i->openmax = (i->openmax && i->max >= last_max);
return 1;
}
static int snd_interval_refine_last(struct snd_interval *i)
{
+ const unsigned int last_min = i->min;
+
if (snd_BUG_ON(snd_interval_empty(i)))
return -EINVAL;
if (snd_interval_single(i))
return 0;
i->min = i->max;
- i->openmin = i->openmax;
- if (i->openmin)
+ if (i->openmax)
i->min--;
+ /* only exclude min value if also excluded before refine */
+ i->openmin = (i->openmin && i->min <= last_min);
return 1;
}
diff --git a/sound/isa/msnd/msnd_pinnacle.c b/sound/isa/msnd/msnd_pinnacle.c
index a31ea6c22d19..2d7379dec1f0 100644
--- a/sound/isa/msnd/msnd_pinnacle.c
+++ b/sound/isa/msnd/msnd_pinnacle.c
@@ -82,10 +82,10 @@
static void set_default_audio_parameters(struct snd_msnd *chip)
{
- chip->play_sample_size = DEFSAMPLESIZE;
+ chip->play_sample_size = snd_pcm_format_width(DEFSAMPLESIZE);
chip->play_sample_rate = DEFSAMPLERATE;
chip->play_channels = DEFCHANNELS;
- chip->capture_sample_size = DEFSAMPLESIZE;
+ chip->capture_sample_size = snd_pcm_format_width(DEFSAMPLESIZE);
chip->capture_sample_rate = DEFSAMPLERATE;
chip->capture_channels = DEFCHANNELS;
}
diff --git a/sound/pci/hda/hda_codec.c b/sound/pci/hda/hda_codec.c
index 3324f98c35f6..f6d4a1046e54 100644
--- a/sound/pci/hda/hda_codec.c
+++ b/sound/pci/hda/hda_codec.c
@@ -4019,7 +4019,8 @@ void snd_hda_bus_reset_codecs(struct hda_bus *bus)
list_for_each_codec(codec, bus) {
/* FIXME: maybe a better way needed for forced reset */
- cancel_delayed_work_sync(&codec->jackpoll_work);
+ if (current_work() != &codec->jackpoll_work.work)
+ cancel_delayed_work_sync(&codec->jackpoll_work);
#ifdef CONFIG_PM
if (hda_codec_is_power_on(codec)) {
hda_call_codec_suspend(codec);
diff --git a/sound/soc/codecs/wm8994.c b/sound/soc/codecs/wm8994.c
index a18aecb49935..2b770d3f05d4 100644
--- a/sound/soc/codecs/wm8994.c
+++ b/sound/soc/codecs/wm8994.c
@@ -2431,6 +2431,7 @@ static int wm8994_set_dai_sysclk(struct snd_soc_dai *dai,
snd_soc_update_bits(codec, WM8994_POWER_MANAGEMENT_2,
WM8994_OPCLK_ENA, 0);
}
+ break;
default:
return -EINVAL;
diff --git a/sound/soc/codecs/wsa881x.c b/sound/soc/codecs/wsa881x.c
index e4f6df077d98..0c672fd89652 100644
--- a/sound/soc/codecs/wsa881x.c
+++ b/sound/soc/codecs/wsa881x.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2015-2017, The Linux Foundation. All rights reserved.
+ * Copyright (c) 2015-2018, 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
@@ -76,6 +76,7 @@ struct swr_port {
enum {
WSA881X_DEV_DOWN,
WSA881X_DEV_UP,
+ WSA881X_DEV_READY,
};
/*
@@ -99,6 +100,7 @@ struct wsa881x_priv {
int version;
struct mutex bg_lock;
struct mutex res_lock;
+ struct mutex temp_lock;
struct snd_info_entry *entry;
struct snd_info_entry *version_entry;
int state;
@@ -464,6 +466,17 @@ static const struct file_operations codec_debug_ops = {
.read = codec_debug_read,
};
+static void wsa881x_regcache_sync(struct wsa881x_priv *wsa881x)
+{
+ mutex_lock(&wsa881x->res_lock);
+ if (wsa881x->state != WSA881X_DEV_READY) {
+ regcache_mark_dirty(wsa881x->regmap);
+ regcache_sync(wsa881x->regmap);
+ wsa881x->state = WSA881X_DEV_READY;
+ }
+ mutex_unlock(&wsa881x->res_lock);
+}
+
static const struct reg_sequence wsa881x_pre_pmu_pa[] = {
{WSA881X_SPKR_DRV_GAIN, 0x41, 0},
{WSA881X_SPKR_MISC_CTL1, 0x01, 0},
@@ -790,7 +803,9 @@ static int wsa881x_rdac_event(struct snd_soc_dapm_widget *w,
switch (event) {
case SND_SOC_DAPM_PRE_PMU:
+ mutex_lock(&wsa881x->temp_lock);
wsa881x_resource_acquire(codec, ENABLE);
+ mutex_unlock(&wsa881x->temp_lock);
wsa881x_boost_ctrl(codec, ENABLE);
break;
case SND_SOC_DAPM_POST_PMD:
@@ -798,7 +813,9 @@ static int wsa881x_rdac_event(struct snd_soc_dapm_widget *w,
wsa881x->swr_slave->dev_num,
false);
wsa881x_boost_ctrl(codec, DISABLE);
+ mutex_lock(&wsa881x->temp_lock);
wsa881x_resource_acquire(codec, DISABLE);
+ mutex_unlock(&wsa881x->temp_lock);
break;
}
return 0;
@@ -1042,13 +1059,8 @@ static int32_t wsa881x_temp_reg_read(struct snd_soc_codec *codec,
return -EINVAL;
}
}
- mutex_lock(&wsa881x->res_lock);
- if (!wsa881x->clk_cnt) {
- regcache_mark_dirty(wsa881x->regmap);
- regcache_sync(wsa881x->regmap);
- }
- mutex_unlock(&wsa881x->res_lock);
-
+ wsa881x_regcache_sync(wsa881x);
+ mutex_lock(&wsa881x->temp_lock);
wsa881x_resource_acquire(codec, ENABLE);
snd_soc_update_bits(codec, WSA881X_TADC_VALUE_CTL, 0x01, 0x00);
@@ -1061,6 +1073,7 @@ static int32_t wsa881x_temp_reg_read(struct snd_soc_codec *codec,
wsa_temp_reg->d2_lsb = snd_soc_read(codec, WSA881X_OTP_REG_4);
wsa881x_resource_acquire(codec, DISABLE);
+ mutex_unlock(&wsa881x->temp_lock);
return 0;
}
@@ -1076,7 +1089,6 @@ static int wsa881x_probe(struct snd_soc_codec *codec)
dev = wsa881x->swr_slave;
wsa881x->codec = codec;
mutex_init(&wsa881x->bg_lock);
- mutex_init(&wsa881x->res_lock);
wsa881x_init(codec);
snprintf(wsa881x->tz_pdata.name, sizeof(wsa881x->tz_pdata.name),
"%s.%x", "wsatz", (u8)dev->addr);
@@ -1098,7 +1110,6 @@ static int wsa881x_remove(struct snd_soc_codec *codec)
if (wsa881x->tz_pdata.tz_dev)
wsa881x_deinit_thermal(wsa881x->tz_pdata.tz_dev);
mutex_destroy(&wsa881x->bg_lock);
- mutex_destroy(&wsa881x->res_lock);
return 0;
}
@@ -1224,6 +1235,8 @@ static int wsa881x_swr_probe(struct swr_device *pdev)
if (wsa881x->wsa_rst_np)
pin_state_current = msm_cdc_pinctrl_get_state(
wsa881x->wsa_rst_np);
+ mutex_init(&wsa881x->res_lock);
+ mutex_init(&wsa881x->temp_lock);
wsa881x_gpio_ctrl(wsa881x, true);
wsa881x->state = WSA881X_DEV_UP;
@@ -1303,6 +1316,8 @@ static int wsa881x_swr_remove(struct swr_device *pdev)
return -EINVAL;
}
debugfs_remove_recursive(debugfs_wsa881x_dent);
+ mutex_destroy(&wsa881x->res_lock);
+ mutex_destroy(&wsa881x->temp_lock);
snd_soc_unregister_codec(&pdev->dev);
if (wsa881x->pd_gpio)
gpio_free(wsa881x->pd_gpio);
@@ -1361,6 +1376,11 @@ static int wsa881x_swr_reset(struct swr_device *pdev)
dev_err(&pdev->dev, "%s: wsa881x is NULL\n", __func__);
return -EINVAL;
}
+ if (wsa881x->state == WSA881X_DEV_READY) {
+ dev_dbg(&pdev->dev, "%s: device already active\n", __func__);
+ return 0;
+ }
+
wsa881x->bg_cnt = 0;
wsa881x->clk_cnt = 0;
while (swr_get_logical_dev_num(pdev, pdev->addr, &devnum) && retry--) {
@@ -1368,8 +1388,7 @@ static int wsa881x_swr_reset(struct swr_device *pdev)
usleep_range(1000, 1100);
}
pdev->dev_num = devnum;
- regcache_mark_dirty(wsa881x->regmap);
- regcache_sync(wsa881x->regmap);
+ wsa881x_regcache_sync(wsa881x);
return 0;
}
diff --git a/sound/usb/quirks-table.h b/sound/usb/quirks-table.h
index 69bf5cf1e91e..15cbe2565703 100644
--- a/sound/usb/quirks-table.h
+++ b/sound/usb/quirks-table.h
@@ -2875,7 +2875,8 @@ YAMAHA_DEVICE(0x7010, "UB99"),
*/
#define AU0828_DEVICE(vid, pid, vname, pname) { \
- USB_DEVICE_VENDOR_SPEC(vid, pid), \
+ .idVendor = vid, \
+ .idProduct = pid, \
.match_flags = USB_DEVICE_ID_MATCH_DEVICE | \
USB_DEVICE_ID_MATCH_INT_CLASS | \
USB_DEVICE_ID_MATCH_INT_SUBCLASS, \
diff --git a/tools/hv/hv_kvp_daemon.c b/tools/hv/hv_kvp_daemon.c
index 60a94b3e532e..177480066816 100644
--- a/tools/hv/hv_kvp_daemon.c
+++ b/tools/hv/hv_kvp_daemon.c
@@ -286,7 +286,7 @@ static int kvp_key_delete(int pool, const __u8 *key, int key_size)
* Found a match; just move the remaining
* entries up.
*/
- if (i == num_records) {
+ if (i == (num_records - 1)) {
kvp_file_info[pool].num_records--;
kvp_update_file(pool);
return 0;
diff --git a/tools/perf/arch/powerpc/util/skip-callchain-idx.c b/tools/perf/arch/powerpc/util/skip-callchain-idx.c
index bd630c222e65..9a53f6e9ef43 100644
--- a/tools/perf/arch/powerpc/util/skip-callchain-idx.c
+++ b/tools/perf/arch/powerpc/util/skip-callchain-idx.c
@@ -58,9 +58,13 @@ static int check_return_reg(int ra_regno, Dwarf_Frame *frame)
}
/*
- * Check if return address is on the stack.
+ * Check if return address is on the stack. If return address
+ * is in a register (typically R0), it is yet to be saved on
+ * the stack.
*/
- if (nops != 0 || ops != NULL)
+ if ((nops != 0 || ops != NULL) &&
+ !(nops == 1 && ops[0].atom == DW_OP_regx &&
+ ops[0].number2 == 0 && ops[0].offset == 0))
return 0;
/*
@@ -246,7 +250,7 @@ int arch_skip_callchain_idx(struct thread *thread, struct ip_callchain *chain)
if (!chain || chain->nr < 3)
return skip_slot;
- ip = chain->ips[2];
+ ip = chain->ips[1];
thread__find_addr_location(thread, PERF_RECORD_MISC_USER,
MAP__FUNCTION, ip, &al);
diff --git a/tools/perf/perf.h b/tools/perf/perf.h
index 90129accffbe..4341ed267d4e 100644
--- a/tools/perf/perf.h
+++ b/tools/perf/perf.h
@@ -29,7 +29,9 @@ static inline unsigned long long rdclock(void)
return ts.tv_sec * 1000000000ULL + ts.tv_nsec;
}
+#ifndef MAX_NR_CPUS
#define MAX_NR_CPUS 1024
+#endif
extern const char *input_name;
extern bool perf_host, perf_guest;
diff --git a/tools/testing/selftests/powerpc/harness.c b/tools/testing/selftests/powerpc/harness.c
index f45cee80c58b..af2b1e66e35e 100644
--- a/tools/testing/selftests/powerpc/harness.c
+++ b/tools/testing/selftests/powerpc/harness.c
@@ -85,13 +85,13 @@ wait:
return status;
}
-static void alarm_handler(int signum)
+static void sig_handler(int signum)
{
- /* Jut wake us up from waitpid */
+ /* Just wake us up from waitpid */
}
-static struct sigaction alarm_action = {
- .sa_handler = alarm_handler,
+static struct sigaction sig_action = {
+ .sa_handler = sig_handler,
};
int test_harness(int (test_function)(void), char *name)
@@ -101,8 +101,14 @@ int test_harness(int (test_function)(void), char *name)
test_start(name);
test_set_git_version(GIT_VERSION);
- if (sigaction(SIGALRM, &alarm_action, NULL)) {
- perror("sigaction");
+ if (sigaction(SIGINT, &sig_action, NULL)) {
+ perror("sigaction (sigint)");
+ test_error(name);
+ return 1;
+ }
+
+ if (sigaction(SIGALRM, &sig_action, NULL)) {
+ perror("sigaction (sigalrm)");
test_error(name);
return 1;
}
diff --git a/tools/testing/selftests/timers/raw_skew.c b/tools/testing/selftests/timers/raw_skew.c
index 30906bfd9c1b..0ab937a17ebb 100644
--- a/tools/testing/selftests/timers/raw_skew.c
+++ b/tools/testing/selftests/timers/raw_skew.c
@@ -146,6 +146,11 @@ int main(int argv, char **argc)
printf(" %lld.%i(act)", ppm/1000, abs((int)(ppm%1000)));
if (llabs(eppm - ppm) > 1000) {
+ if (tx1.offset || tx2.offset ||
+ tx1.freq != tx2.freq || tx1.tick != tx2.tick) {
+ printf(" [SKIP]\n");
+ return ksft_exit_skip("The clock was adjusted externally. Shutdown NTPd or other time sync daemons\n");
+ }
printf(" [FAILED]\n");
return ksft_exit_fail();
}