Merge tag 'irqchip-4.21' of git://git.kernel.org/pub/scm/linux/kernel/git/maz/arm...
authorThomas Gleixner <tglx@linutronix.de>
Tue, 18 Dec 2018 17:37:27 +0000 (18:37 +0100)
committerThomas Gleixner <tglx@linutronix.de>
Tue, 18 Dec 2018 17:37:27 +0000 (18:37 +0100)
Pull irqchip updates from Marc Zyngier:

 - A bunch of new irqchip drivers (RDA8810PL, Madera, imx-irqsteer)
 - Updates for new (and old) platforms (i.MX8MQ, F1C100s)
 - A number of SPDX cleanups
 - A workaround for a very broken GICv3 implementation
 - A platform-msi fix
 - Various cleanups

401 files changed:
Documentation/admin-guide/kernel-parameters.txt
Documentation/arm64/silicon-errata.txt
Documentation/devicetree/bindings/phy/qcom-qmp-phy.txt
Documentation/devicetree/bindings/spi/spi-uniphier.txt
Documentation/userspace-api/spec_ctrl.rst
Documentation/x86/boot.txt
MAINTAINERS
Makefile
arch/arm/boot/dts/am3517-evm.dts
arch/arm/boot/dts/am3517-som.dtsi
arch/arm/boot/dts/imx51-zii-rdu1.dts
arch/arm/boot/dts/logicpd-som-lv.dtsi
arch/arm/boot/dts/logicpd-torpedo-37xx-devkit.dts
arch/arm/boot/dts/rk3288-veyron.dtsi
arch/arm/boot/dts/sama5d2.dtsi
arch/arm/kernel/ftrace.c
arch/arm/mach-davinci/da830.c
arch/arm/mach-davinci/da850.c
arch/arm/mach-davinci/devices-da8xx.c
arch/arm/mach-davinci/dm355.c
arch/arm/mach-davinci/dm365.c
arch/arm/mach-davinci/dm644x.c
arch/arm/mach-davinci/dm646x.c
arch/arm/mach-omap1/board-ams-delta.c
arch/arm/mach-omap2/prm44xx.c
arch/arm64/Kconfig
arch/arm64/boot/dts/qcom/msm8998-mtp.dtsi
arch/arm64/boot/dts/qcom/sdm845-mtp.dts
arch/arm64/boot/dts/rockchip/rk3399-puma-haikou.dts
arch/arm64/boot/dts/rockchip/rk3399-rock960.dtsi
arch/arm64/boot/dts/ti/k3-am65-wakeup.dtsi
arch/arm64/include/asm/ftrace.h
arch/arm64/include/asm/tlbflush.h
arch/arm64/kernel/cpu_errata.c
arch/arm64/kernel/ftrace.c
arch/arm64/net/bpf_jit_comp.c
arch/ia64/include/asm/numa.h
arch/ia64/kernel/acpi.c
arch/ia64/mm/numa.c
arch/microblaze/kernel/ftrace.c
arch/mips/include/asm/syscall.h
arch/mips/kernel/ftrace.c
arch/mips/ralink/mt7620.c
arch/nds32/kernel/ftrace.c
arch/parisc/kernel/ftrace.c
arch/powerpc/kernel/trace/ftrace.c
arch/powerpc/kvm/book3s_hv.c
arch/powerpc/net/bpf_jit_comp64.c
arch/riscv/kernel/ftrace.c
arch/s390/kernel/ftrace.c
arch/s390/kernel/perf_cpum_cf.c
arch/s390/mm/pgalloc.c
arch/sh/kernel/ftrace.c
arch/sparc/kernel/ftrace.c
arch/sparc/net/bpf_jit_comp_64.c
arch/x86/Kconfig
arch/x86/Makefile
arch/x86/boot/header.S
arch/x86/events/core.c
arch/x86/events/intel/core.c
arch/x86/events/perf_event.h
arch/x86/include/asm/fpu/internal.h
arch/x86/include/asm/kvm_host.h
arch/x86/include/asm/msr-index.h
arch/x86/include/asm/nospec-branch.h
arch/x86/include/asm/spec-ctrl.h
arch/x86/include/asm/switch_to.h
arch/x86/include/asm/thread_info.h
arch/x86/include/asm/tlbflush.h
arch/x86/include/asm/x86_init.h
arch/x86/include/uapi/asm/bootparam.h
arch/x86/kernel/acpi/boot.c
arch/x86/kernel/cpu/bugs.c
arch/x86/kernel/cpu/mcheck/mce_amd.c
arch/x86/kernel/fpu/signal.c
arch/x86/kernel/ftrace.c
arch/x86/kernel/head32.c
arch/x86/kernel/head64.c
arch/x86/kernel/process.c
arch/x86/kernel/process.h [new file with mode: 0644]
arch/x86/kernel/process_32.c
arch/x86/kernel/process_64.c
arch/x86/kernel/setup.c
arch/x86/kvm/lapic.c
arch/x86/kvm/mmu.c
arch/x86/kvm/svm.c
arch/x86/kvm/vmx.c
arch/x86/kvm/x86.c
arch/x86/mm/tlb.c
arch/x86/xen/enlighten.c
arch/x86/xen/multicalls.c
arch/x86/xen/setup.c
arch/x86/xen/spinlock.c
arch/xtensa/kernel/asm-offsets.c
arch/xtensa/kernel/process.c
arch/xtensa/kernel/ptrace.c
block/blk-merge.c
drivers/acpi/acpica/exserial.c
drivers/acpi/arm64/iort.c
drivers/android/binder.c
drivers/android/binder_alloc.c
drivers/android/binder_alloc.h
drivers/atm/firestream.c
drivers/base/devres.c
drivers/dma/at_hdmac.c
drivers/firmware/efi/efi.c
drivers/fsi/Kconfig
drivers/fsi/fsi-scom.c
drivers/gpio/gpio-davinci.c
drivers/gpu/drm/amd/amdgpu/amdgpu_vm.c
drivers/gpu/drm/amd/amdgpu/gfx_v9_0.c
drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_mst_types.c
drivers/gpu/drm/ast/ast_main.c
drivers/gpu/drm/ast/ast_mode.c
drivers/gpu/drm/drm_auth.c
drivers/gpu/drm/i915/gvt/aperture_gm.c
drivers/gpu/drm/i915/gvt/gtt.c
drivers/gpu/drm/i915/gvt/mmio_context.c
drivers/gpu/drm/meson/meson_crtc.c
drivers/gpu/drm/meson/meson_dw_hdmi.c
drivers/gpu/drm/meson/meson_venc.c
drivers/gpu/drm/meson/meson_viu.c
drivers/gpu/drm/rcar-du/rcar_du_group.c
drivers/hid/hid-sensor-custom.c
drivers/hid/hid-sensor-hub.c
drivers/hv/channel.c
drivers/hwmon/ina2xx.c
drivers/hwmon/mlxreg-fan.c
drivers/hwmon/raspberrypi-hwmon.c
drivers/hwmon/w83795.c
drivers/iio/accel/hid-sensor-accel-3d.c
drivers/iio/gyro/hid-sensor-gyro-3d.c
drivers/iio/humidity/hid-sensor-humidity.c
drivers/iio/light/hid-sensor-als.c
drivers/iio/light/hid-sensor-prox.c
drivers/iio/magnetometer/hid-sensor-magn-3d.c
drivers/iio/magnetometer/st_magn_buffer.c
drivers/iio/orientation/hid-sensor-incl-3d.c
drivers/iio/pressure/hid-sensor-press.c
drivers/iio/temperature/hid-sensor-temperature.c
drivers/infiniband/core/roce_gid_mgmt.c
drivers/infiniband/core/umem_odp.c
drivers/infiniband/hw/bnxt_re/main.c
drivers/infiniband/hw/hns/hns_roce_hw_v2.c
drivers/infiniband/hw/mlx5/main.c
drivers/infiniband/hw/mlx5/odp.c
drivers/infiniband/hw/mlx5/qp.c
drivers/infiniband/sw/rdmavt/ah.c
drivers/infiniband/sw/rdmavt/ah.h
drivers/infiniband/ulp/iser/iser_verbs.c
drivers/irqchip/irq-dw-apb-ictl.c
drivers/irqchip/irq-gic.c
drivers/irqchip/irq-renesas-h8s.c
drivers/irqchip/irq-s3c24xx.c
drivers/misc/mic/scif/scif_rma.c
drivers/mtd/nand/bbt.c
drivers/mtd/spi-nor/spi-nor.c
drivers/net/ethernet/cavium/thunder/nic_main.c
drivers/net/ethernet/hisilicon/hip04_eth.c
drivers/net/ethernet/intel/i40e/i40e_main.c
drivers/net/ethernet/intel/i40e/i40e_xsk.c
drivers/net/ethernet/intel/igb/e1000_i210.c
drivers/net/ethernet/intel/ixgbe/ixgbe_x550.c
drivers/net/ethernet/microchip/lan743x_main.c
drivers/net/ethernet/microchip/lan743x_main.h
drivers/net/ethernet/qlogic/qed/qed_debug.c
drivers/net/ethernet/via/via-velocity.c
drivers/net/phy/phy_device.c
drivers/net/rionet.c
drivers/net/usb/ipheth.c
drivers/nvme/host/core.c
drivers/nvme/host/fc.c
drivers/nvme/host/nvme.h
drivers/nvme/host/rdma.c
drivers/opp/of.c
drivers/opp/ti-opp-supply.c
drivers/pci/controller/dwc/pci-imx6.c
drivers/pci/controller/dwc/pci-layerscape.c
drivers/pci/controller/dwc/pcie-designware-ep.c
drivers/pci/msi.c
drivers/pci/pci.c
drivers/phy/qualcomm/phy-qcom-qusb2.c
drivers/phy/socionext/Kconfig
drivers/rtc/rtc-hid-sensor-time.c
drivers/s390/cio/vfio_ccw_cp.c
drivers/s390/cio/vfio_ccw_drv.c
drivers/s390/crypto/ap_bus.c
drivers/s390/crypto/ap_bus.h
drivers/s390/crypto/ap_queue.c
drivers/s390/crypto/zcrypt_cex2a.c
drivers/s390/crypto/zcrypt_cex2c.c
drivers/s390/crypto/zcrypt_cex4.c
drivers/s390/net/qeth_core_main.c
drivers/spi/spi-mt65xx.c
drivers/spi/spi-omap2-mcspi.c
drivers/staging/comedi/comedi.h
drivers/staging/comedi/drivers/ni_mio_common.c
drivers/staging/media/sunxi/cedrus/cedrus.c
drivers/staging/most/core.c
drivers/staging/mt7621-dma/mtk-hsdma.c
drivers/staging/mt7621-pinctrl/pinctrl-rt2880.c
drivers/staging/rtl8723bs/hal/rtl8723bs_recv.c
drivers/staging/rtl8723bs/os_dep/ioctl_cfg80211.c
drivers/staging/rtl8723bs/os_dep/ioctl_linux.c
drivers/staging/vc04_services/interface/vchiq_arm/vchiq_arm.c
drivers/thunderbolt/switch.c
drivers/usb/core/quirks.c
drivers/usb/dwc3/gadget.c
drivers/usb/gadget/function/u_ether.c
drivers/usb/gadget/udc/omap_udc.c
drivers/usb/storage/unusual_realtek.h
drivers/xen/balloon.c
drivers/xen/pvcalls-front.c
drivers/xen/xlate_mmu.c
fs/afs/dir.c
fs/afs/fs_probe.c
fs/afs/inode.c
fs/afs/internal.h
fs/afs/misc.c
fs/afs/rotate.c
fs/afs/vl_probe.c
fs/afs/vl_rotate.c
fs/aio.c
fs/btrfs/disk-io.c
fs/btrfs/file.c
fs/btrfs/qgroup.c
fs/btrfs/relocation.c
fs/btrfs/send.c
fs/btrfs/super.c
fs/cachefiles/namei.c
fs/cachefiles/rdwr.c
fs/cachefiles/xattr.c
fs/direct-io.c
fs/exportfs/expfs.c
fs/ext2/super.c
fs/ext2/xattr.c
fs/fscache/object.c
fs/hfs/btree.c
fs/hfsplus/btree.c
fs/ocfs2/export.c
fs/ocfs2/move_extents.c
fs/pstore/ram.c
fs/sysv/inode.c
fs/udf/super.c
fs/udf/unicode.c
fs/userfaultfd.c
include/linux/filter.h
include/linux/fscache-cache.h
include/linux/ftrace.h
include/linux/hid-sensor-hub.h
include/linux/interrupt.h
include/linux/irqchip.h
include/linux/mlx5/mlx5_ifc.h
include/linux/netfilter/nf_conntrack_proto_gre.h
include/linux/platform_data/gpio-davinci.h
include/linux/psi.h
include/linux/pstore.h
include/linux/ptrace.h
include/linux/sched.h
include/linux/sched/smt.h [new file with mode: 0644]
include/linux/tracehook.h
include/linux/tracepoint.h
include/net/netfilter/ipv4/nf_nat_masquerade.h
include/net/netfilter/ipv6/nf_nat_masquerade.h
include/sound/soc.h
include/trace/events/sched.h
include/uapi/linux/prctl.h
include/xen/balloon.h
init/Kconfig
init/initramfs.c
kernel/bpf/core.c
kernel/bpf/local_storage.c
kernel/bpf/queue_stack_maps.c
kernel/bpf/verifier.c
kernel/cpu.c
kernel/events/uprobes.c
kernel/irq/affinity.c
kernel/irq/chip.c
kernel/irq/ipi.c
kernel/irq/manage.c
kernel/irq/matrix.c
kernel/irq/spurious.c
kernel/kcov.c
kernel/ptrace.c
kernel/sched/core.c
kernel/sched/psi.c
kernel/sched/sched.h
kernel/sched/stats.h
kernel/stackleak.c
kernel/trace/bpf_trace.c
kernel/trace/ftrace.c
kernel/trace/trace.h
kernel/trace/trace_functions_graph.c
kernel/trace/trace_irqsoff.c
kernel/trace/trace_sched_wakeup.c
lib/debugobjects.c
lib/iov_iter.c
lib/test_hexdump.c
lib/test_kmod.c
mm/gup.c
mm/huge_memory.c
mm/hugetlb.c
mm/khugepaged.c
mm/page_alloc.c
mm/rmap.c
mm/shmem.c
mm/truncate.c
mm/userfaultfd.c
net/core/filter.c
net/ipv4/ip_output.c
net/ipv4/netfilter/ipt_MASQUERADE.c
net/ipv4/netfilter/nf_nat_masquerade_ipv4.c
net/ipv4/netfilter/nft_masq_ipv4.c
net/ipv4/tcp_input.c
net/ipv4/tcp_timer.c
net/ipv6/ip6_output.c
net/ipv6/netfilter.c
net/ipv6/netfilter/ip6t_MASQUERADE.c
net/ipv6/netfilter/nf_nat_masquerade_ipv6.c
net/ipv6/netfilter/nft_masq_ipv6.c
net/netfilter/ipvs/ip_vs_ctl.c
net/netfilter/nf_conncount.c
net/netfilter/nf_conntrack_proto_gre.c
net/netfilter/nf_tables_api.c
net/netfilter/nfnetlink_cttimeout.c
net/netfilter/nft_compat.c
net/netfilter/nft_flow_offload.c
net/netfilter/xt_RATEEST.c
net/netfilter/xt_hashlimit.c
net/sctp/output.c
net/tipc/node.c
scripts/Makefile.build
scripts/unifdef.c
security/selinux/nlmsgtab.c
sound/core/control.c
sound/isa/wss/wss_lib.c
sound/pci/ac97/ac97_codec.c
sound/pci/hda/hda_intel.c
sound/pci/hda/patch_realtek.c
sound/soc/codecs/hdac_hdmi.c
sound/soc/codecs/pcm186x.h
sound/soc/codecs/pcm3060.c
sound/soc/codecs/wm_adsp.c
sound/soc/intel/Kconfig
sound/soc/intel/boards/Kconfig
sound/soc/intel/boards/cht_bsw_max98090_ti.c
sound/soc/intel/skylake/skl.c
sound/soc/omap/omap-abe-twl6040.c
sound/soc/omap/omap-dmic.c
sound/soc/omap/omap-mcbsp.c
sound/soc/omap/omap-mcpdm.c
sound/soc/qcom/common.c
sound/soc/qcom/qdsp6/q6afe-dai.c
sound/soc/qcom/qdsp6/q6afe.c
sound/soc/qcom/qdsp6/q6asm-dai.c
sound/soc/qcom/qdsp6/q6routing.c
sound/soc/rockchip/rockchip_pcm.c
sound/soc/sh/rcar/ssi.c
sound/soc/soc-acpi.c
sound/soc/soc-core.c
sound/soc/stm/stm32_sai_sub.c
sound/soc/sunxi/Kconfig
sound/soc/sunxi/sun8i-codec.c
sound/sparc/cs4231.c
sound/usb/quirks-table.h
tools/arch/x86/include/asm/cpufeatures.h
tools/bpf/bpftool/Documentation/bpftool-cgroup.rst
tools/bpf/bpftool/Documentation/bpftool-map.rst
tools/bpf/bpftool/Documentation/bpftool-net.rst
tools/bpf/bpftool/Documentation/bpftool-perf.rst
tools/bpf/bpftool/Documentation/bpftool-prog.rst
tools/bpf/bpftool/Documentation/bpftool.rst
tools/bpf/bpftool/common.c
tools/bpf/bpftool/main.h
tools/bpf/bpftool/prog.c
tools/build/Makefile.feature
tools/build/feature/Makefile
tools/build/feature/test-all.c
tools/build/feature/test-get_current_dir_name.c [new file with mode: 0644]
tools/include/uapi/asm-generic/ioctls.h
tools/include/uapi/drm/i915_drm.h
tools/include/uapi/linux/pkt_cls.h [new file with mode: 0644]
tools/include/uapi/linux/prctl.h
tools/include/uapi/linux/tc_act/tc_bpf.h [new file with mode: 0644]
tools/objtool/elf.c
tools/perf/Makefile.config
tools/perf/tests/attr/base-record
tools/perf/trace/beauty/ioctl.c
tools/perf/util/Build
tools/perf/util/evsel.c
tools/perf/util/get_current_dir_name.c [new file with mode: 0644]
tools/perf/util/namespaces.c
tools/perf/util/namespaces.h
tools/perf/util/util.h
tools/testing/selftests/Makefile
tools/testing/selftests/bpf/test_netcnt.c
tools/testing/selftests/bpf/test_verifier.c
tools/testing/selftests/netfilter/Makefile [new file with mode: 0644]
tools/testing/selftests/netfilter/config [new file with mode: 0644]
tools/testing/selftests/netfilter/nft_trans_stress.sh [new file with mode: 0755]
tools/testing/selftests/proc/proc-self-map-files-002.c

index 19f4423..aefd358 100644 (file)
                        causing system reset or hang due to sending
                        INIT from AP to BSP.
 
-       disable_counter_freezing [HW]
+       perf_v4_pmi=    [X86,INTEL]
+                       Format: <bool>
                        Disable Intel PMU counter freezing feature.
                        The feature only exists starting from
                        Arch Perfmon v4 (Skylake and newer).
                        before loading.
                        See Documentation/blockdev/ramdisk.txt.
 
+       psi=            [KNL] Enable or disable pressure stall information
+                       tracking.
+                       Format: <bool>
+
        psmouse.proto=  [HW,MOUSE] Highest PS2 mouse protocol extension to
                        probe for; one of (bare|imps|exps|lifebook|any).
        psmouse.rate=   [HW,MOUSE] Set desired mouse report rate, in reports
 
        spectre_v2=     [X86] Control mitigation of Spectre variant 2
                        (indirect branch speculation) vulnerability.
+                       The default operation protects the kernel from
+                       user space attacks.
 
-                       on   - unconditionally enable
-                       off  - unconditionally disable
+                       on   - unconditionally enable, implies
+                              spectre_v2_user=on
+                       off  - unconditionally disable, implies
+                              spectre_v2_user=off
                        auto - kernel detects whether your CPU model is
                               vulnerable
 
                        CONFIG_RETPOLINE configuration option, and the
                        compiler with which the kernel was built.
 
+                       Selecting 'on' will also enable the mitigation
+                       against user space to user space task attacks.
+
+                       Selecting 'off' will disable both the kernel and
+                       the user space protections.
+
                        Specific mitigations can also be selected manually:
 
                        retpoline         - replace indirect branches
                        Not specifying this option is equivalent to
                        spectre_v2=auto.
 
+       spectre_v2_user=
+                       [X86] Control mitigation of Spectre variant 2
+                       (indirect branch speculation) vulnerability between
+                       user space tasks
+
+                       on      - Unconditionally enable mitigations. Is
+                                 enforced by spectre_v2=on
+
+                       off     - Unconditionally disable mitigations. Is
+                                 enforced by spectre_v2=off
+
+                       prctl   - Indirect branch speculation is enabled,
+                                 but mitigation can be enabled via prctl
+                                 per thread.  The mitigation control state
+                                 is inherited on fork.
+
+                       prctl,ibpb
+                               - Like "prctl" above, but only STIBP is
+                                 controlled per thread. IBPB is issued
+                                 always when switching between different user
+                                 space processes.
+
+                       seccomp
+                               - Same as "prctl" above, but all seccomp
+                                 threads will enable the mitigation unless
+                                 they explicitly opt out.
+
+                       seccomp,ibpb
+                               - Like "seccomp" above, but only STIBP is
+                                 controlled per thread. IBPB is issued
+                                 always when switching between different
+                                 user space processes.
+
+                       auto    - Kernel selects the mitigation depending on
+                                 the available CPU features and vulnerability.
+
+                       Default mitigation:
+                       If CONFIG_SECCOMP=y then "seccomp", otherwise "prctl"
+
+                       Not specifying this option is equivalent to
+                       spectre_v2_user=auto.
+
        spec_store_bypass_disable=
                        [HW] Control Speculative Store Bypass (SSB) Disable mitigation
                        (Speculative Store Bypass vulnerability)
index 76ccded..8f95776 100644 (file)
@@ -57,6 +57,7 @@ stable kernels.
 | ARM            | Cortex-A73      | #858921         | ARM64_ERRATUM_858921        |
 | ARM            | Cortex-A55      | #1024718        | ARM64_ERRATUM_1024718       |
 | ARM            | Cortex-A76      | #1188873        | ARM64_ERRATUM_1188873       |
+| ARM            | Cortex-A76      | #1286807        | ARM64_ERRATUM_1286807       |
 | ARM            | MMU-500         | #841119,#826419 | N/A                         |
 |                |                 |                 |                             |
 | Cavium         | ThunderX ITS    | #22375, #24313  | CAVIUM_ERRATUM_22375        |
index adf20b2..fbc198d 100644 (file)
@@ -40,24 +40,36 @@ Required properties:
                "ref" for 19.2 MHz ref clk,
                "com_aux" for phy common block aux clock,
                "ref_aux" for phy reference aux clock,
+
+               For "qcom,ipq8074-qmp-pcie-phy": no clocks are listed.
                For "qcom,msm8996-qmp-pcie-phy" must contain:
                        "aux", "cfg_ahb", "ref".
                For "qcom,msm8996-qmp-usb3-phy" must contain:
                        "aux", "cfg_ahb", "ref".
-               For "qcom,qmp-v3-usb3-phy" must contain:
+               For "qcom,sdm845-qmp-usb3-phy" must contain:
+                       "aux", "cfg_ahb", "ref", "com_aux".
+               For "qcom,sdm845-qmp-usb3-uni-phy" must contain:
                        "aux", "cfg_ahb", "ref", "com_aux".
+               For "qcom,sdm845-qmp-ufs-phy" must contain:
+                       "ref", "ref_aux".
 
  - resets: a list of phandles and reset controller specifier pairs,
           one for each entry in reset-names.
  - reset-names: "phy" for reset of phy block,
                "common" for phy common block reset,
-               "cfg" for phy's ahb cfg block reset (Optional).
+               "cfg" for phy's ahb cfg block reset.
+
+               For "qcom,ipq8074-qmp-pcie-phy" must contain:
+                       "phy", "common".
                For "qcom,msm8996-qmp-pcie-phy" must contain:
-                "phy", "common", "cfg".
+                       "phy", "common", "cfg".
                For "qcom,msm8996-qmp-usb3-phy" must contain
-                "phy", "common".
-               For "qcom,ipq8074-qmp-pcie-phy" must contain:
-                "phy", "common".
+                       "phy", "common".
+               For "qcom,sdm845-qmp-usb3-phy" must contain:
+                       "phy", "common".
+               For "qcom,sdm845-qmp-usb3-uni-phy" must contain:
+                       "phy", "common".
+               For "qcom,sdm845-qmp-ufs-phy": no resets are listed.
 
  - vdda-phy-supply: Phandle to a regulator supply to PHY core block.
  - vdda-pll-supply: Phandle to 1.8V regulator supply to PHY refclk pll block.
@@ -79,9 +91,10 @@ Required properties for child node:
 
  - #phy-cells: must be 0
 
+Required properties child node of pcie and usb3 qmp phys:
  - clocks: a list of phandles and clock-specifier pairs,
           one for each entry in clock-names.
- - clock-names: Must contain following for pcie and usb qmp phys:
+ - clock-names: Must contain following:
                 "pipe<lane-number>" for pipe clock specific to each lane.
  - clock-output-names: Name of the PHY clock that will be the parent for
                       the above pipe clock.
@@ -91,9 +104,11 @@ Required properties for child node:
                        (or)
                  "pcie20_phy1_pipe_clk"
 
+Required properties for child node of PHYs with lane reset, AKA:
+       "qcom,msm8996-qmp-pcie-phy"
  - resets: a list of phandles and reset controller specifier pairs,
           one for each entry in reset-names.
- - reset-names: Must contain following for pcie qmp phys:
+ - reset-names: Must contain following:
                 "lane<lane-number>" for reset specific to each lane.
 
 Example:
index 504a4ec..b04e66a 100644 (file)
@@ -5,18 +5,20 @@ UniPhier SoCs have SCSSI which supports SPI single channel.
 Required properties:
  - compatible: should be "socionext,uniphier-scssi"
  - reg: address and length of the spi master registers
- - #address-cells: must be <1>, see spi-bus.txt
- - #size-cells: must be <0>, see spi-bus.txt
- - clocks: A phandle to the clock for the device.
- - resets: A phandle to the reset control for the device.
+ - interrupts: a single interrupt specifier
+ - pinctrl-names: should be "default"
+ - pinctrl-0: pin control state for the default mode
+ - clocks: a phandle to the clock for the device
+ - resets: a phandle to the reset control for the device
 
 Example:
 
 spi0: spi@54006000 {
        compatible = "socionext,uniphier-scssi";
        reg = <0x54006000 0x100>;
-       #address-cells = <1>;
-       #size-cells = <0>;
+       interrupts = <0 39 4>;
+       pinctrl-names = "default";
+       pinctrl-0 = <&pinctrl_spi0>;
        clocks = <&peri_clk 11>;
        resets = <&peri_rst 11>;
 };
index 32f3d55..c4dbe6f 100644 (file)
@@ -92,3 +92,12 @@ Speculation misfeature controls
    * prctl(PR_SET_SPECULATION_CTRL, PR_SPEC_STORE_BYPASS, PR_SPEC_ENABLE, 0, 0);
    * prctl(PR_SET_SPECULATION_CTRL, PR_SPEC_STORE_BYPASS, PR_SPEC_DISABLE, 0, 0);
    * prctl(PR_SET_SPECULATION_CTRL, PR_SPEC_STORE_BYPASS, PR_SPEC_FORCE_DISABLE, 0, 0);
+
+- PR_SPEC_INDIR_BRANCH: Indirect Branch Speculation in User Processes
+                        (Mitigate Spectre V2 style attacks against user processes)
+
+  Invocations:
+   * prctl(PR_GET_SPECULATION_CTRL, PR_SPEC_INDIRECT_BRANCH, 0, 0, 0);
+   * prctl(PR_SET_SPECULATION_CTRL, PR_SPEC_INDIRECT_BRANCH, PR_SPEC_ENABLE, 0, 0);
+   * prctl(PR_SET_SPECULATION_CTRL, PR_SPEC_INDIRECT_BRANCH, PR_SPEC_DISABLE, 0, 0);
+   * prctl(PR_SET_SPECULATION_CTRL, PR_SPEC_INDIRECT_BRANCH, PR_SPEC_FORCE_DISABLE, 0, 0);
index 7727db8..5e9b826 100644 (file)
@@ -61,18 +61,6 @@ Protocol 2.12:       (Kernel 3.8) Added the xloadflags field and extension fields
                to struct boot_params for loading bzImage and ramdisk
                above 4G in 64bit.
 
-Protocol 2.13: (Kernel 3.14) Support 32- and 64-bit flags being set in
-               xloadflags to support booting a 64-bit kernel from 32-bit
-               EFI
-
-Protocol 2.14: (Kernel 4.20) Added acpi_rsdp_addr holding the physical
-               address of the ACPI RSDP table.
-               The bootloader updates version with:
-               0x8000 | min(kernel-version, bootloader-version)
-               kernel-version being the protocol version supported by
-               the kernel and bootloader-version the protocol version
-               supported by the bootloader.
-
 **** MEMORY LAYOUT
 
 The traditional memory map for the kernel loader, used for Image or
@@ -209,7 +197,6 @@ Offset      Proto   Name            Meaning
 0258/8 2.10+   pref_address    Preferred loading address
 0260/4 2.10+   init_size       Linear memory required during initialization
 0264/4 2.11+   handover_offset Offset of handover entry point
-0268/8 2.14+   acpi_rsdp_addr  Physical address of RSDP table
 
 (1) For backwards compatibility, if the setup_sects field contains 0, the
     real value is 4.
@@ -322,7 +309,7 @@ Protocol:   2.00+
   Contains the magic number "HdrS" (0x53726448).
 
 Field name:    version
-Type:          modify
+Type:          read
 Offset/size:   0x206/2
 Protocol:      2.00+
 
@@ -330,12 +317,6 @@ Protocol:  2.00+
   e.g. 0x0204 for version 2.04, and 0x0a11 for a hypothetical version
   10.17.
 
-  Up to protocol version 2.13 this information is only read by the
-  bootloader. From protocol version 2.14 onwards the bootloader will
-  write the used protocol version or-ed with 0x8000 to the field. The
-  used protocol version will be the minimum of the supported protocol
-  versions of the bootloader and the kernel.
-
 Field name:    realmode_swtch
 Type:          modify (optional)
 Offset/size:   0x208/4
@@ -763,17 +744,6 @@ Offset/size:       0x264/4
 
   See EFI HANDOVER PROTOCOL below for more details.
 
-Field name:    acpi_rsdp_addr
-Type:          write
-Offset/size:   0x268/8
-Protocol:      2.14+
-
-  This field can be set by the boot loader to tell the kernel the
-  physical address of the ACPI RSDP table.
-
-  A value of 0 indicates the kernel should fall back to the standard
-  methods to locate the RSDP.
-
 
 **** THE IMAGE CHECKSUM
 
index 9bc599d..ca8940e 100644 (file)
@@ -1923,7 +1923,6 @@ ARM/QUALCOMM SUPPORT
 M:     Andy Gross <andy.gross@linaro.org>
 M:     David Brown <david.brown@linaro.org>
 L:     linux-arm-msm@vger.kernel.org
-L:     linux-soc@vger.kernel.org
 S:     Maintained
 F:     Documentation/devicetree/bindings/soc/qcom/
 F:     arch/arm/boot/dts/qcom-*.dts
@@ -2491,7 +2490,7 @@ F:        drivers/net/wireless/ath/*
 ATHEROS ATH5K WIRELESS DRIVER
 M:     Jiri Slaby <jirislaby@gmail.com>
 M:     Nick Kossifidis <mickflemm@gmail.com>
-M:     "Luis R. Rodriguez" <mcgrof@do-not-panic.com>
+M:     Luis Chamberlain <mcgrof@kernel.org>
 L:     linux-wireless@vger.kernel.org
 W:     http://wireless.kernel.org/en/users/Drivers/ath5k
 S:     Maintained
@@ -2801,7 +2800,7 @@ T:        git git://git.kernel.org/pub/scm/linux/kernel/git/bpf/bpf.git
 T:     git git://git.kernel.org/pub/scm/linux/kernel/git/bpf/bpf-next.git
 Q:     https://patchwork.ozlabs.org/project/netdev/list/?delegate=77147
 S:     Supported
-F:     arch/x86/net/bpf_jit*
+F:     arch/*/net/*
 F:     Documentation/networking/filter.txt
 F:     Documentation/bpf/
 F:     include/linux/bpf*
@@ -2821,6 +2820,67 @@ F:       tools/bpf/
 F:     tools/lib/bpf/
 F:     tools/testing/selftests/bpf/
 
+BPF JIT for ARM
+M:     Shubham Bansal <illusionist.neo@gmail.com>
+L:     netdev@vger.kernel.org
+S:     Maintained
+F:     arch/arm/net/
+
+BPF JIT for ARM64
+M:     Daniel Borkmann <daniel@iogearbox.net>
+M:     Alexei Starovoitov <ast@kernel.org>
+M:     Zi Shen Lim <zlim.lnx@gmail.com>
+L:     netdev@vger.kernel.org
+S:     Supported
+F:     arch/arm64/net/
+
+BPF JIT for MIPS (32-BIT AND 64-BIT)
+M:     Paul Burton <paul.burton@mips.com>
+L:     netdev@vger.kernel.org
+S:     Maintained
+F:     arch/mips/net/
+
+BPF JIT for NFP NICs
+M:     Jakub Kicinski <jakub.kicinski@netronome.com>
+L:     netdev@vger.kernel.org
+S:     Supported
+F:     drivers/net/ethernet/netronome/nfp/bpf/
+
+BPF JIT for POWERPC (32-BIT AND 64-BIT)
+M:     Naveen N. Rao <naveen.n.rao@linux.ibm.com>
+M:     Sandipan Das <sandipan@linux.ibm.com>
+L:     netdev@vger.kernel.org
+S:     Maintained
+F:     arch/powerpc/net/
+
+BPF JIT for S390
+M:     Martin Schwidefsky <schwidefsky@de.ibm.com>
+M:     Heiko Carstens <heiko.carstens@de.ibm.com>
+L:     netdev@vger.kernel.org
+S:     Maintained
+F:     arch/s390/net/
+X:     arch/s390/net/pnet.c
+
+BPF JIT for SPARC (32-BIT AND 64-BIT)
+M:     David S. Miller <davem@davemloft.net>
+L:     netdev@vger.kernel.org
+S:     Maintained
+F:     arch/sparc/net/
+
+BPF JIT for X86 32-BIT
+M:     Wang YanQing <udknight@gmail.com>
+L:     netdev@vger.kernel.org
+S:     Maintained
+F:     arch/x86/net/bpf_jit_comp32.c
+
+BPF JIT for X86 64-BIT
+M:     Alexei Starovoitov <ast@kernel.org>
+M:     Daniel Borkmann <daniel@iogearbox.net>
+L:     netdev@vger.kernel.org
+S:     Supported
+F:     arch/x86/net/
+X:     arch/x86/net/bpf_jit_comp32.c
+
 BROADCOM B44 10/100 ETHERNET DRIVER
 M:     Michael Chan <michael.chan@broadcom.com>
 L:     netdev@vger.kernel.org
@@ -2861,7 +2921,7 @@ F:        drivers/staging/vc04_services
 BROADCOM BCM47XX MIPS ARCHITECTURE
 M:     Hauke Mehrtens <hauke@hauke-m.de>
 M:     RafaÅ‚ MiÅ‚ecki <zajec5@gmail.com>
-L:     linux-mips@linux-mips.org
+L:     linux-mips@vger.kernel.org
 S:     Maintained
 F:     Documentation/devicetree/bindings/mips/brcm/
 F:     arch/mips/bcm47xx/*
@@ -2870,7 +2930,6 @@ F:        arch/mips/include/asm/mach-bcm47xx/*
 BROADCOM BCM5301X ARM ARCHITECTURE
 M:     Hauke Mehrtens <hauke@hauke-m.de>
 M:     RafaÅ‚ MiÅ‚ecki <zajec5@gmail.com>
-M:     Jon Mason <jonmason@broadcom.com>
 M:     bcm-kernel-feedback-list@broadcom.com
 L:     linux-arm-kernel@lists.infradead.org
 S:     Maintained
@@ -2925,7 +2984,7 @@ F:        drivers/cpufreq/bmips-cpufreq.c
 BROADCOM BMIPS MIPS ARCHITECTURE
 M:     Kevin Cernekee <cernekee@gmail.com>
 M:     Florian Fainelli <f.fainelli@gmail.com>
-L:     linux-mips@linux-mips.org
+L:     linux-mips@vger.kernel.org
 T:     git git://github.com/broadcom/stblinux.git
 S:     Maintained
 F:     arch/mips/bmips/*
@@ -3016,7 +3075,6 @@ F:        drivers/net/ethernet/broadcom/genet/
 BROADCOM IPROC ARM ARCHITECTURE
 M:     Ray Jui <rjui@broadcom.com>
 M:     Scott Branden <sbranden@broadcom.com>
-M:     Jon Mason <jonmason@broadcom.com>
 M:     bcm-kernel-feedback-list@broadcom.com
 L:     linux-arm-kernel@lists.infradead.org (moderated for non-subscribers)
 T:     git git://github.com/broadcom/cygnus-linux.git
@@ -3063,7 +3121,7 @@ F:        include/uapi/rdma/bnxt_re-abi.h
 
 BROADCOM NVRAM DRIVER
 M:     RafaÅ‚ MiÅ‚ecki <zajec5@gmail.com>
-L:     linux-mips@linux-mips.org
+L:     linux-mips@vger.kernel.org
 S:     Maintained
 F:     drivers/firmware/broadcom/*
 
@@ -4167,7 +4225,7 @@ F:        net/decnet/
 
 DECSTATION PLATFORM SUPPORT
 M:     "Maciej W. Rozycki" <macro@linux-mips.org>
-L:     linux-mips@linux-mips.org
+L:     linux-mips@vger.kernel.org
 W:     http://www.linux-mips.org/wiki/DECstation
 S:     Maintained
 F:     arch/mips/dec/
@@ -5258,7 +5316,7 @@ EDAC-CAVIUM OCTEON
 M:     Ralf Baechle <ralf@linux-mips.org>
 M:     David Daney <david.daney@cavium.com>
 L:     linux-edac@vger.kernel.org
-L:     linux-mips@linux-mips.org
+L:     linux-mips@vger.kernel.org
 S:     Supported
 F:     drivers/edac/octeon_edac*
 
@@ -5776,7 +5834,7 @@ F:        include/uapi/linux/firewire*.h
 F:     tools/firewire/
 
 FIRMWARE LOADER (request_firmware)
-M:     Luis R. Rodriguez <mcgrof@kernel.org>
+M:     Luis Chamberlain <mcgrof@kernel.org>
 L:     linux-kernel@vger.kernel.org
 S:     Maintained
 F:     Documentation/firmware_class/
@@ -7705,7 +7763,7 @@ F:        Documentation/devicetree/bindings/iio/gyroscope/invensense,mpu3050.txt
 
 IOC3 ETHERNET DRIVER
 M:     Ralf Baechle <ralf@linux-mips.org>
-L:     linux-mips@linux-mips.org
+L:     linux-mips@vger.kernel.org
 S:     Maintained
 F:     drivers/net/ethernet/sgi/ioc3-eth.c
 
@@ -8076,7 +8134,7 @@ F:        tools/testing/selftests/
 F:     Documentation/dev-tools/kselftest*
 
 KERNEL USERMODE HELPER
-M:     "Luis R. Rodriguez" <mcgrof@kernel.org>
+M:     Luis Chamberlain <mcgrof@kernel.org>
 L:     linux-kernel@vger.kernel.org
 S:     Maintained
 F:     kernel/umh.c
@@ -8133,7 +8191,7 @@ F:        arch/arm64/kvm/
 
 KERNEL VIRTUAL MACHINE FOR MIPS (KVM/mips)
 M:     James Hogan <jhogan@kernel.org>
-L:     linux-mips@linux-mips.org
+L:     linux-mips@vger.kernel.org
 S:     Supported
 F:     arch/mips/include/uapi/asm/kvm*
 F:     arch/mips/include/asm/kvm*
@@ -8252,7 +8310,7 @@ F:        mm/kmemleak.c
 F:     mm/kmemleak-test.c
 
 KMOD KERNEL MODULE LOADER - USERMODE HELPER
-M:     "Luis R. Rodriguez" <mcgrof@kernel.org>
+M:     Luis Chamberlain <mcgrof@kernel.org>
 L:     linux-kernel@vger.kernel.org
 S:     Maintained
 F:     kernel/kmod.c
@@ -8306,7 +8364,7 @@ F:        drivers/net/dsa/lantiq_gswip.c
 
 LANTIQ MIPS ARCHITECTURE
 M:     John Crispin <john@phrozen.org>
-L:     linux-mips@linux-mips.org
+L:     linux-mips@vger.kernel.org
 S:     Maintained
 F:     arch/mips/lantiq
 F:     drivers/soc/lantiq
@@ -8869,7 +8927,7 @@ S:        Maintained
 
 MARDUK (CREATOR CI40) DEVICE TREE SUPPORT
 M:     Rahul Bedarkar <rahulbedarkar89@gmail.com>
-L:     linux-mips@linux-mips.org
+L:     linux-mips@vger.kernel.org
 S:     Maintained
 F:     arch/mips/boot/dts/img/pistachio_marduk.dts
 
@@ -9828,7 +9886,7 @@ F:        drivers/dma/at_xdmac.c
 
 MICROSEMI MIPS SOCS
 M:     Alexandre Belloni <alexandre.belloni@bootlin.com>
-L:     linux-mips@linux-mips.org
+L:     linux-mips@vger.kernel.org
 S:     Maintained
 F:     arch/mips/generic/board-ocelot.c
 F:     arch/mips/configs/generic/board-ocelot.config
@@ -9868,7 +9926,7 @@ MIPS
 M:     Ralf Baechle <ralf@linux-mips.org>
 M:     Paul Burton <paul.burton@mips.com>
 M:     James Hogan <jhogan@kernel.org>
-L:     linux-mips@linux-mips.org
+L:     linux-mips@vger.kernel.org
 W:     http://www.linux-mips.org/
 T:     git git://git.linux-mips.org/pub/scm/ralf/linux.git
 T:     git git://git.kernel.org/pub/scm/linux/kernel/git/mips/linux.git
@@ -9881,7 +9939,7 @@ F:        drivers/platform/mips/
 
 MIPS BOSTON DEVELOPMENT BOARD
 M:     Paul Burton <paul.burton@mips.com>
-L:     linux-mips@linux-mips.org
+L:     linux-mips@vger.kernel.org
 S:     Maintained
 F:     Documentation/devicetree/bindings/clock/img,boston-clock.txt
 F:     arch/mips/boot/dts/img/boston.dts
@@ -9891,7 +9949,7 @@ F:        include/dt-bindings/clock/boston-clock.h
 
 MIPS GENERIC PLATFORM
 M:     Paul Burton <paul.burton@mips.com>
-L:     linux-mips@linux-mips.org
+L:     linux-mips@vger.kernel.org
 S:     Supported
 F:     Documentation/devicetree/bindings/power/mti,mips-cpc.txt
 F:     arch/mips/generic/
@@ -9899,7 +9957,7 @@ F:        arch/mips/tools/generic-board-config.sh
 
 MIPS/LOONGSON1 ARCHITECTURE
 M:     Keguang Zhang <keguang.zhang@gmail.com>
-L:     linux-mips@linux-mips.org
+L:     linux-mips@vger.kernel.org
 S:     Maintained
 F:     arch/mips/loongson32/
 F:     arch/mips/include/asm/mach-loongson32/
@@ -9908,7 +9966,7 @@ F:        drivers/*/*/*loongson1*
 
 MIPS/LOONGSON2 ARCHITECTURE
 M:     Jiaxun Yang <jiaxun.yang@flygoat.com>
-L:     linux-mips@linux-mips.org
+L:     linux-mips@vger.kernel.org
 S:     Maintained
 F:     arch/mips/loongson64/fuloong-2e/
 F:     arch/mips/loongson64/lemote-2f/
@@ -9918,7 +9976,7 @@ F:        drivers/*/*/*loongson2*
 
 MIPS/LOONGSON3 ARCHITECTURE
 M:     Huacai Chen <chenhc@lemote.com>
-L:     linux-mips@linux-mips.org
+L:     linux-mips@vger.kernel.org
 S:     Maintained
 F:     arch/mips/loongson64/
 F:     arch/mips/include/asm/mach-loongson64/
@@ -9928,7 +9986,7 @@ F:        drivers/*/*/*loongson3*
 
 MIPS RINT INSTRUCTION EMULATION
 M:     Aleksandar Markovic <aleksandar.markovic@mips.com>
-L:     linux-mips@linux-mips.org
+L:     linux-mips@vger.kernel.org
 S:     Supported
 F:     arch/mips/math-emu/sp_rint.c
 F:     arch/mips/math-emu/dp_rint.c
@@ -10913,7 +10971,7 @@ F:      include/linux/platform_data/i2c-omap.h
 
 ONION OMEGA2+ BOARD
 M:     Harvey Hunt <harveyhuntnexus@gmail.com>
-L:     linux-mips@linux-mips.org
+L:     linux-mips@vger.kernel.org
 S:     Maintained
 F:     arch/mips/boot/dts/ralink/omega2p.dts
 
@@ -11822,7 +11880,7 @@ F:      drivers/pinctrl/spear/
 
 PISTACHIO SOC SUPPORT
 M:     James Hartley <james.hartley@sondrel.com>
-L:     linux-mips@linux-mips.org
+L:     linux-mips@vger.kernel.org
 S:     Odd Fixes
 F:     arch/mips/pistachio/
 F:     arch/mips/include/asm/mach-pistachio/
@@ -12002,7 +12060,7 @@ F:      kernel/printk/
 F:     include/linux/printk.h
 
 PRISM54 WIRELESS DRIVER
-M:     "Luis R. Rodriguez" <mcgrof@gmail.com>
+M:     Luis Chamberlain <mcgrof@kernel.org>
 L:     linux-wireless@vger.kernel.org
 W:     http://wireless.kernel.org/en/users/Drivers/p54
 S:     Obsolete
@@ -12016,9 +12074,10 @@ S:     Maintained
 F:     fs/proc/
 F:     include/linux/proc_fs.h
 F:     tools/testing/selftests/proc/
+F:     Documentation/filesystems/proc.txt
 
 PROC SYSCTL
-M:     "Luis R. Rodriguez" <mcgrof@kernel.org>
+M:     Luis Chamberlain <mcgrof@kernel.org>
 M:     Kees Cook <keescook@chromium.org>
 L:     linux-kernel@vger.kernel.org
 L:     linux-fsdevel@vger.kernel.org
@@ -12481,7 +12540,7 @@ F:      drivers/media/usb/rainshadow-cec/*
 
 RALINK MIPS ARCHITECTURE
 M:     John Crispin <john@phrozen.org>
-L:     linux-mips@linux-mips.org
+L:     linux-mips@vger.kernel.org
 S:     Maintained
 F:     arch/mips/ralink
 
@@ -12501,7 +12560,7 @@ F:      drivers/block/brd.c
 
 RANCHU VIRTUAL BOARD FOR MIPS
 M:     Miodrag Dinic <miodrag.dinic@mips.com>
-L:     linux-mips@linux-mips.org
+L:     linux-mips@vger.kernel.org
 S:     Supported
 F:     arch/mips/generic/board-ranchu.c
 F:     arch/mips/configs/generic/board-ranchu.config
@@ -13951,6 +14010,7 @@ S:      Supported
 F:     Documentation/devicetree/bindings/sound/
 F:     Documentation/sound/soc/
 F:     sound/soc/
+F:     include/dt-bindings/sound/
 F:     include/sound/soc*
 
 SOUNDWIRE SUBSYSTEM
@@ -15236,7 +15296,7 @@ F:      arch/um/os-Linux/drivers/
 TURBOCHANNEL SUBSYSTEM
 M:     "Maciej W. Rozycki" <macro@linux-mips.org>
 M:     Ralf Baechle <ralf@linux-mips.org>
-L:     linux-mips@linux-mips.org
+L:     linux-mips@vger.kernel.org
 Q:     http://patchwork.linux-mips.org/project/linux-mips/list/
 S:     Maintained
 F:     drivers/tc/
@@ -16057,7 +16117,7 @@ F:      drivers/net/vmxnet3/
 
 VOCORE VOCORE2 BOARD
 M:     Harvey Hunt <harveyhuntnexus@gmail.com>
-L:     linux-mips@linux-mips.org
+L:     linux-mips@vger.kernel.org
 S:     Maintained
 F:     arch/mips/boot/dts/ralink/vocore2.dts
 
index 0ce4e29..e9fd22c 100644 (file)
--- a/Makefile
+++ b/Makefile
@@ -2,7 +2,7 @@
 VERSION = 4
 PATCHLEVEL = 20
 SUBLEVEL = 0
-EXTRAVERSION = -rc4
+EXTRAVERSION = -rc5
 NAME = Shy Crocodile
 
 # *DOCUMENTATION*
index d4d33cd..1e2bb68 100644 (file)
        vmmc-supply = <&vmmc_fixed>;
        bus-width = <4>;
        wp-gpios = <&gpio4 30 GPIO_ACTIVE_HIGH>; /* gpio_126 */
-       cd-gpios = <&gpio4 31 GPIO_ACTIVE_HIGH>; /* gpio_127 */
+       cd-gpios = <&gpio4 31 GPIO_ACTIVE_LOW>; /* gpio_127 */
 };
 
 &mmc3 {
index dae6e45..b1c988e 100644 (file)
                compatible = "ti,wl1271";
                reg = <2>;
                interrupt-parent = <&gpio6>;
-               interrupts = <10 IRQ_TYPE_LEVEL_HIGH>; /* gpio_170 */
+               interrupts = <10 IRQ_TYPE_EDGE_RISING>; /* gpio_170 */
                ref-clock-frequency = <26000000>;
                tcxo-clock-frequency = <26000000>;
        };
index e45a15c..69d753c 100644 (file)
        pinctrl-0 = <&pinctrl_i2c2>;
        status = "okay";
 
-       eeprom@50 {
-               compatible = "atmel,24c04";
-               pagesize = <16>;
-               reg = <0x50>;
-       };
-
        hpa1: amp@60 {
                compatible = "ti,tpa6130a2";
                reg = <0x60>;
index ac34333..98b682a 100644 (file)
 };
 
 &mmc3 {
-       interrupts-extended = <&intc 94 &omap3_pmx_core2 0x46>;
+       interrupts-extended = <&intc 94 &omap3_pmx_core 0x136>;
        pinctrl-0 = <&mmc3_pins &wl127x_gpio>;
        pinctrl-names = "default";
        vmmc-supply = <&wl12xx_vmmc>;
index 9d5d53f..c39cf2c 100644 (file)
@@ -35,7 +35,7 @@
  * jumpering combinations for the long run.
  */
 &mmc3 {
-       interrupts-extended = <&intc 94 &omap3_pmx_core2 0x46>;
+       interrupts-extended = <&intc 94 &omap3_pmx_core 0x136>;
        pinctrl-0 = <&mmc3_pins &mmc3_core2_pins>;
        pinctrl-names = "default";
        vmmc-supply = <&wl12xx_vmmc>;
index 2075120..d8bf939 100644 (file)
 #include "rk3288.dtsi"
 
 / {
-       memory@0 {
+       /*
+        * The default coreboot on veyron devices ignores memory@0 nodes
+        * and would instead create another memory node.
+        */
+       memory {
                device_type = "memory";
                reg = <0x0 0x0 0x0 0x80000000>;
        };
index 843052f..dd0dda6 100644 (file)
                                  0x1 0x0 0x60000000 0x10000000
                                  0x2 0x0 0x70000000 0x10000000
                                  0x3 0x0 0x80000000 0x10000000>;
-                       clocks = <&mck>;
+                       clocks = <&h32ck>;
                        status = "disabled";
 
                        nand_controller: nand-controller {
index 0142fcf..bda949f 100644 (file)
@@ -183,9 +183,7 @@ void prepare_ftrace_return(unsigned long *parent, unsigned long self_addr,
                           unsigned long frame_pointer)
 {
        unsigned long return_hooker = (unsigned long) &return_to_handler;
-       struct ftrace_graph_ent trace;
        unsigned long old;
-       int err;
 
        if (unlikely(atomic_read(&current->tracing_graph_pause)))
                return;
@@ -193,21 +191,8 @@ void prepare_ftrace_return(unsigned long *parent, unsigned long self_addr,
        old = *parent;
        *parent = return_hooker;
 
-       trace.func = self_addr;
-       trace.depth = current->curr_ret_stack + 1;
-
-       /* Only trace if the calling function expects to */
-       if (!ftrace_graph_entry(&trace)) {
+       if (function_graph_enter(old, self_addr, frame_pointer, NULL))
                *parent = old;
-               return;
-       }
-
-       err = ftrace_push_return_trace(old, self_addr, &trace.depth,
-                                      frame_pointer, NULL);
-       if (err == -EBUSY) {
-               *parent = old;
-               return;
-       }
 }
 
 #ifdef CONFIG_DYNAMIC_FTRACE
index 0bc5bd2..2cc9fe4 100644 (file)
@@ -759,7 +759,9 @@ static struct davinci_id da830_ids[] = {
 };
 
 static struct davinci_gpio_platform_data da830_gpio_platform_data = {
-       .ngpio = 128,
+       .no_auto_base   = true,
+       .base           = 0,
+       .ngpio          = 128,
 };
 
 int __init da830_register_gpio(void)
index 4528bbf..e7b78df 100644 (file)
@@ -719,7 +719,9 @@ int __init da850_register_vpif_capture(struct vpif_capture_config
 }
 
 static struct davinci_gpio_platform_data da850_gpio_platform_data = {
-       .ngpio = 144,
+       .no_auto_base   = true,
+       .base           = 0,
+       .ngpio          = 144,
 };
 
 int __init da850_register_gpio(void)
index 1fd3619..cf78da5 100644 (file)
@@ -701,6 +701,46 @@ static struct resource da8xx_gpio_resources[] = {
        },
        { /* interrupt */
                .start  = IRQ_DA8XX_GPIO0,
+               .end    = IRQ_DA8XX_GPIO0,
+               .flags  = IORESOURCE_IRQ,
+       },
+       {
+               .start  = IRQ_DA8XX_GPIO1,
+               .end    = IRQ_DA8XX_GPIO1,
+               .flags  = IORESOURCE_IRQ,
+       },
+       {
+               .start  = IRQ_DA8XX_GPIO2,
+               .end    = IRQ_DA8XX_GPIO2,
+               .flags  = IORESOURCE_IRQ,
+       },
+       {
+               .start  = IRQ_DA8XX_GPIO3,
+               .end    = IRQ_DA8XX_GPIO3,
+               .flags  = IORESOURCE_IRQ,
+       },
+       {
+               .start  = IRQ_DA8XX_GPIO4,
+               .end    = IRQ_DA8XX_GPIO4,
+               .flags  = IORESOURCE_IRQ,
+       },
+       {
+               .start  = IRQ_DA8XX_GPIO5,
+               .end    = IRQ_DA8XX_GPIO5,
+               .flags  = IORESOURCE_IRQ,
+       },
+       {
+               .start  = IRQ_DA8XX_GPIO6,
+               .end    = IRQ_DA8XX_GPIO6,
+               .flags  = IORESOURCE_IRQ,
+       },
+       {
+               .start  = IRQ_DA8XX_GPIO7,
+               .end    = IRQ_DA8XX_GPIO7,
+               .flags  = IORESOURCE_IRQ,
+       },
+       {
+               .start  = IRQ_DA8XX_GPIO8,
                .end    = IRQ_DA8XX_GPIO8,
                .flags  = IORESOURCE_IRQ,
        },
index 9f7d38d..4c6e0be 100644 (file)
@@ -548,12 +548,44 @@ static struct resource dm355_gpio_resources[] = {
        },
        {       /* interrupt */
                .start  = IRQ_DM355_GPIOBNK0,
+               .end    = IRQ_DM355_GPIOBNK0,
+               .flags  = IORESOURCE_IRQ,
+       },
+       {
+               .start  = IRQ_DM355_GPIOBNK1,
+               .end    = IRQ_DM355_GPIOBNK1,
+               .flags  = IORESOURCE_IRQ,
+       },
+       {
+               .start  = IRQ_DM355_GPIOBNK2,
+               .end    = IRQ_DM355_GPIOBNK2,
+               .flags  = IORESOURCE_IRQ,
+       },
+       {
+               .start  = IRQ_DM355_GPIOBNK3,
+               .end    = IRQ_DM355_GPIOBNK3,
+               .flags  = IORESOURCE_IRQ,
+       },
+       {
+               .start  = IRQ_DM355_GPIOBNK4,
+               .end    = IRQ_DM355_GPIOBNK4,
+               .flags  = IORESOURCE_IRQ,
+       },
+       {
+               .start  = IRQ_DM355_GPIOBNK5,
+               .end    = IRQ_DM355_GPIOBNK5,
+               .flags  = IORESOURCE_IRQ,
+       },
+       {
+               .start  = IRQ_DM355_GPIOBNK6,
                .end    = IRQ_DM355_GPIOBNK6,
                .flags  = IORESOURCE_IRQ,
        },
 };
 
 static struct davinci_gpio_platform_data dm355_gpio_platform_data = {
+       .no_auto_base   = true,
+       .base           = 0,
        .ngpio          = 104,
 };
 
index abcf2a5..01fb2b0 100644 (file)
@@ -267,12 +267,49 @@ static struct resource dm365_gpio_resources[] = {
        },
        {       /* interrupt */
                .start  = IRQ_DM365_GPIO0,
+               .end    = IRQ_DM365_GPIO0,
+               .flags  = IORESOURCE_IRQ,
+       },
+       {
+               .start  = IRQ_DM365_GPIO1,
+               .end    = IRQ_DM365_GPIO1,
+               .flags  = IORESOURCE_IRQ,
+       },
+       {
+               .start  = IRQ_DM365_GPIO2,
+               .end    = IRQ_DM365_GPIO2,
+               .flags  = IORESOURCE_IRQ,
+       },
+       {
+               .start  = IRQ_DM365_GPIO3,
+               .end    = IRQ_DM365_GPIO3,
+               .flags  = IORESOURCE_IRQ,
+       },
+       {
+               .start  = IRQ_DM365_GPIO4,
+               .end    = IRQ_DM365_GPIO4,
+               .flags  = IORESOURCE_IRQ,
+       },
+       {
+               .start  = IRQ_DM365_GPIO5,
+               .end    = IRQ_DM365_GPIO5,
+               .flags  = IORESOURCE_IRQ,
+       },
+       {
+               .start  = IRQ_DM365_GPIO6,
+               .end    = IRQ_DM365_GPIO6,
+               .flags  = IORESOURCE_IRQ,
+       },
+       {
+               .start  = IRQ_DM365_GPIO7,
                .end    = IRQ_DM365_GPIO7,
                .flags  = IORESOURCE_IRQ,
        },
 };
 
 static struct davinci_gpio_platform_data dm365_gpio_platform_data = {
+       .no_auto_base   = true,
+       .base           = 0,
        .ngpio          = 104,
        .gpio_unbanked  = 8,
 };
index 0720da7..38f92b7 100644 (file)
@@ -492,12 +492,34 @@ static struct resource dm644_gpio_resources[] = {
        },
        {       /* interrupt */
                .start  = IRQ_GPIOBNK0,
+               .end    = IRQ_GPIOBNK0,
+               .flags  = IORESOURCE_IRQ,
+       },
+       {
+               .start  = IRQ_GPIOBNK1,
+               .end    = IRQ_GPIOBNK1,
+               .flags  = IORESOURCE_IRQ,
+       },
+       {
+               .start  = IRQ_GPIOBNK2,
+               .end    = IRQ_GPIOBNK2,
+               .flags  = IORESOURCE_IRQ,
+       },
+       {
+               .start  = IRQ_GPIOBNK3,
+               .end    = IRQ_GPIOBNK3,
+               .flags  = IORESOURCE_IRQ,
+       },
+       {
+               .start  = IRQ_GPIOBNK4,
                .end    = IRQ_GPIOBNK4,
                .flags  = IORESOURCE_IRQ,
        },
 };
 
 static struct davinci_gpio_platform_data dm644_gpio_platform_data = {
+       .no_auto_base   = true,
+       .base           = 0,
        .ngpio          = 71,
 };
 
index 6bd2ed0..7dc54b2 100644 (file)
@@ -442,12 +442,24 @@ static struct resource dm646x_gpio_resources[] = {
        },
        {       /* interrupt */
                .start  = IRQ_DM646X_GPIOBNK0,
+               .end    = IRQ_DM646X_GPIOBNK0,
+               .flags  = IORESOURCE_IRQ,
+       },
+       {
+               .start  = IRQ_DM646X_GPIOBNK1,
+               .end    = IRQ_DM646X_GPIOBNK1,
+               .flags  = IORESOURCE_IRQ,
+       },
+       {
+               .start  = IRQ_DM646X_GPIOBNK2,
                .end    = IRQ_DM646X_GPIOBNK2,
                .flags  = IORESOURCE_IRQ,
        },
 };
 
 static struct davinci_gpio_platform_data dm646x_gpio_platform_data = {
+       .no_auto_base   = true,
+       .base           = 0,
        .ngpio          = 43,
 };
 
index 3d191fd..1788674 100644 (file)
@@ -750,6 +750,9 @@ static void modem_pm(struct uart_port *port, unsigned int state, unsigned old)
        struct modem_private_data *priv = port->private_data;
        int ret;
 
+       if (!priv)
+               return;
+
        if (IS_ERR(priv->regulator))
                return;
 
index 7b95729..38a1be6 100644 (file)
@@ -351,7 +351,7 @@ static void omap44xx_prm_reconfigure_io_chain(void)
  * to occur, WAKEUPENABLE bits must be set in the pad mux registers, and
  * omap44xx_prm_reconfigure_io_chain() must be called.  No return value.
  */
-static void __init omap44xx_prm_enable_io_wakeup(void)
+static void omap44xx_prm_enable_io_wakeup(void)
 {
        s32 inst = omap4_prmst_get_prm_dev_inst();
 
index 787d785..ea2ab03 100644 (file)
@@ -497,6 +497,24 @@ config ARM64_ERRATUM_1188873
 
          If unsure, say Y.
 
+config ARM64_ERRATUM_1286807
+       bool "Cortex-A76: Modification of the translation table for a virtual address might lead to read-after-read ordering violation"
+       default y
+       select ARM64_WORKAROUND_REPEAT_TLBI
+       help
+         This option adds workaround for ARM Cortex-A76 erratum 1286807
+
+         On the affected Cortex-A76 cores (r0p0 to r3p0), if a virtual
+         address for a cacheable mapping of a location is being
+         accessed by a core while another core is remapping the virtual
+         address to a new physical page using the recommended
+         break-before-make sequence, then under very rare circumstances
+         TLBI+DSB completes before a read using the translation being
+         invalidated has been observed by other observers. The
+         workaround repeats the TLBI+DSB operation.
+
+         If unsure, say Y.
+
 config CAVIUM_ERRATUM_22375
        bool "Cavium erratum 22375, 24313"
        default y
@@ -566,9 +584,16 @@ config QCOM_FALKOR_ERRATUM_1003
          is unchanged. Work around the erratum by invalidating the walk cache
          entries for the trampoline before entering the kernel proper.
 
+config ARM64_WORKAROUND_REPEAT_TLBI
+       bool
+       help
+         Enable the repeat TLBI workaround for Falkor erratum 1009 and
+         Cortex-A76 erratum 1286807.
+
 config QCOM_FALKOR_ERRATUM_1009
        bool "Falkor E1009: Prematurely complete a DSB after a TLBI"
        default y
+       select ARM64_WORKAROUND_REPEAT_TLBI
        help
          On Falkor v1, the CPU may prematurely complete a DSB following a
          TLBI xxIS invalidate maintenance operation. Repeat the TLBI operation
index b4276da..11fd1fe 100644 (file)
                };
        };
 };
+
+&tlmm {
+       gpio-reserved-ranges = <0 4>, <81 4>;
+};
index eedfaf8..d667eee 100644 (file)
        status = "okay";
 };
 
+&tlmm {
+       gpio-reserved-ranges = <0 4>, <81 4>;
+};
+
 &uart9 {
        status = "okay";
 };
index 2dceeea..1e6a710 100644 (file)
 };
 
 &pcie0 {
-       ep-gpios = <&gpio4 RK_PC6 GPIO_ACTIVE_LOW>;
+       ep-gpios = <&gpio4 RK_PC6 GPIO_ACTIVE_HIGH>;
        num-lanes = <4>;
        pinctrl-names = "default";
        pinctrl-0 = <&pcie_clkreqn_cpm>;
index 6c8c4ab..56abbb0 100644 (file)
                regulator-always-on;
                vin-supply = <&vcc_sys>;
        };
-
-       vdd_log: vdd-log {
-               compatible = "pwm-regulator";
-               pwms = <&pwm2 0 25000 0>;
-               regulator-name = "vdd_log";
-               regulator-min-microvolt = <800000>;
-               regulator-max-microvolt = <1400000>;
-               regulator-always-on;
-               regulator-boot-on;
-               vin-supply = <&vcc_sys>;
-       };
-
 };
 
 &cpu_l0 {
index affc3c3..8d7b47f 100644 (file)
@@ -36,7 +36,7 @@
 
        wkup_uart0: serial@42300000 {
                compatible = "ti,am654-uart";
-               reg = <0x00 0x42300000 0x00 0x100>;
+               reg = <0x42300000 0x100>;
                reg-shift = <2>;
                reg-io-width = <4>;
                interrupts = <GIC_SPI 697 IRQ_TYPE_LEVEL_HIGH>;
index caa955f..fac54fb 100644 (file)
@@ -56,6 +56,19 @@ static inline bool arch_trace_is_compat_syscall(struct pt_regs *regs)
 {
        return is_compat_task();
 }
+
+#define ARCH_HAS_SYSCALL_MATCH_SYM_NAME
+
+static inline bool arch_syscall_match_sym_name(const char *sym,
+                                              const char *name)
+{
+       /*
+        * Since all syscall functions have __arm64_ prefix, we must skip it.
+        * However, as we described above, we decided to ignore compat
+        * syscalls, so we don't care about __arm64_compat_ prefix here.
+        */
+       return !strcmp(sym + 8, name);
+}
 #endif /* ifndef __ASSEMBLY__ */
 
 #endif /* __ASM_FTRACE_H */
index c3c0387..5dfd238 100644 (file)
                   ALTERNATIVE("nop\n                   nop",                  \
                               "dsb ish\n               tlbi " #op,            \
                               ARM64_WORKAROUND_REPEAT_TLBI,                   \
-                              CONFIG_QCOM_FALKOR_ERRATUM_1009)                \
+                              CONFIG_ARM64_WORKAROUND_REPEAT_TLBI)            \
                            : : )
 
 #define __TLBI_1(op, arg) asm ("tlbi " #op ", %0\n"                           \
                   ALTERNATIVE("nop\n                   nop",                  \
                               "dsb ish\n               tlbi " #op ", %0",     \
                               ARM64_WORKAROUND_REPEAT_TLBI,                   \
-                              CONFIG_QCOM_FALKOR_ERRATUM_1009)                \
+                              CONFIG_ARM64_WORKAROUND_REPEAT_TLBI)            \
                            : : "r" (arg))
 
 #define __TLBI_N(op, arg, n, ...) __TLBI_##n(op, arg)
index a509e35..6ad715d 100644 (file)
@@ -570,6 +570,20 @@ static const struct midr_range arm64_harden_el2_vectors[] = {
 
 #endif
 
+#ifdef CONFIG_ARM64_WORKAROUND_REPEAT_TLBI
+
+static const struct midr_range arm64_repeat_tlbi_cpus[] = {
+#ifdef CONFIG_QCOM_FALKOR_ERRATUM_1009
+       MIDR_RANGE(MIDR_QCOM_FALKOR_V1, 0, 0, 0, 0),
+#endif
+#ifdef CONFIG_ARM64_ERRATUM_1286807
+       MIDR_RANGE(MIDR_CORTEX_A76, 0, 0, 3, 0),
+#endif
+       {},
+};
+
+#endif
+
 const struct arm64_cpu_capabilities arm64_errata[] = {
 #if    defined(CONFIG_ARM64_ERRATUM_826319) || \
        defined(CONFIG_ARM64_ERRATUM_827319) || \
@@ -695,11 +709,11 @@ const struct arm64_cpu_capabilities arm64_errata[] = {
                .matches = is_kryo_midr,
        },
 #endif
-#ifdef CONFIG_QCOM_FALKOR_ERRATUM_1009
+#ifdef CONFIG_ARM64_WORKAROUND_REPEAT_TLBI
        {
-               .desc = "Qualcomm Technologies Falkor erratum 1009",
+               .desc = "Qualcomm erratum 1009, ARM erratum 1286807",
                .capability = ARM64_WORKAROUND_REPEAT_TLBI,
-               ERRATA_MIDR_REV(MIDR_QCOM_FALKOR_V1, 0, 0),
+               ERRATA_MIDR_RANGE_LIST(arm64_repeat_tlbi_cpus),
        },
 #endif
 #ifdef CONFIG_ARM64_ERRATUM_858921
index 50986e3..57e9622 100644 (file)
@@ -216,8 +216,6 @@ void prepare_ftrace_return(unsigned long *parent, unsigned long self_addr,
 {
        unsigned long return_hooker = (unsigned long)&return_to_handler;
        unsigned long old;
-       struct ftrace_graph_ent trace;
-       int err;
 
        if (unlikely(atomic_read(&current->tracing_graph_pause)))
                return;
@@ -229,18 +227,7 @@ void prepare_ftrace_return(unsigned long *parent, unsigned long self_addr,
         */
        old = *parent;
 
-       trace.func = self_addr;
-       trace.depth = current->curr_ret_stack + 1;
-
-       /* Only trace if the calling function expects to */
-       if (!ftrace_graph_entry(&trace))
-               return;
-
-       err = ftrace_push_return_trace(old, self_addr, &trace.depth,
-                                      frame_pointer, NULL);
-       if (err == -EBUSY)
-               return;
-       else
+       if (!function_graph_enter(old, self_addr, frame_pointer, NULL))
                *parent = return_hooker;
 }
 
index a6fdaea..8919801 100644 (file)
@@ -351,7 +351,8 @@ static void build_epilogue(struct jit_ctx *ctx)
  * >0 - successfully JITed a 16-byte eBPF instruction.
  * <0 - failed to JIT.
  */
-static int build_insn(const struct bpf_insn *insn, struct jit_ctx *ctx)
+static int build_insn(const struct bpf_insn *insn, struct jit_ctx *ctx,
+                     bool extra_pass)
 {
        const u8 code = insn->code;
        const u8 dst = bpf2a64[insn->dst_reg];
@@ -625,12 +626,19 @@ emit_cond_jmp:
        case BPF_JMP | BPF_CALL:
        {
                const u8 r0 = bpf2a64[BPF_REG_0];
-               const u64 func = (u64)__bpf_call_base + imm;
+               bool func_addr_fixed;
+               u64 func_addr;
+               int ret;
 
-               if (ctx->prog->is_func)
-                       emit_addr_mov_i64(tmp, func, ctx);
+               ret = bpf_jit_get_func_addr(ctx->prog, insn, extra_pass,
+                                           &func_addr, &func_addr_fixed);
+               if (ret < 0)
+                       return ret;
+               if (func_addr_fixed)
+                       /* We can use optimized emission here. */
+                       emit_a64_mov_i64(tmp, func_addr, ctx);
                else
-                       emit_a64_mov_i64(tmp, func, ctx);
+                       emit_addr_mov_i64(tmp, func_addr, ctx);
                emit(A64_BLR(tmp), ctx);
                emit(A64_MOV(1, r0, A64_R(0)), ctx);
                break;
@@ -753,7 +761,7 @@ emit_cond_jmp:
        return 0;
 }
 
-static int build_body(struct jit_ctx *ctx)
+static int build_body(struct jit_ctx *ctx, bool extra_pass)
 {
        const struct bpf_prog *prog = ctx->prog;
        int i;
@@ -762,7 +770,7 @@ static int build_body(struct jit_ctx *ctx)
                const struct bpf_insn *insn = &prog->insnsi[i];
                int ret;
 
-               ret = build_insn(insn, ctx);
+               ret = build_insn(insn, ctx, extra_pass);
                if (ret > 0) {
                        i++;
                        if (ctx->image == NULL)
@@ -858,7 +866,7 @@ struct bpf_prog *bpf_int_jit_compile(struct bpf_prog *prog)
        /* 1. Initial fake pass to compute ctx->idx. */
 
        /* Fake pass to fill in ctx->offset. */
-       if (build_body(&ctx)) {
+       if (build_body(&ctx, extra_pass)) {
                prog = orig_prog;
                goto out_off;
        }
@@ -888,7 +896,7 @@ skip_init_ctx:
 
        build_prologue(&ctx, was_classic);
 
-       if (build_body(&ctx)) {
+       if (build_body(&ctx, extra_pass)) {
                bpf_jit_binary_free(header);
                prog = orig_prog;
                goto out_off;
index ebef7f4..c5c253c 100644 (file)
@@ -59,7 +59,9 @@ extern struct node_cpuid_s node_cpuid[NR_CPUS];
  */
 
 extern u8 numa_slit[MAX_NUMNODES * MAX_NUMNODES];
-#define node_distance(from,to) (numa_slit[(from) * MAX_NUMNODES + (to)])
+#define slit_distance(from,to) (numa_slit[(from) * MAX_NUMNODES + (to)])
+extern int __node_distance(int from, int to);
+#define node_distance(from,to) __node_distance(from, to)
 
 extern int paddr_to_nid(unsigned long paddr);
 
index 1dacbf5..41eb281 100644 (file)
@@ -578,8 +578,8 @@ void __init acpi_numa_fixup(void)
        if (!slit_table) {
                for (i = 0; i < MAX_NUMNODES; i++)
                        for (j = 0; j < MAX_NUMNODES; j++)
-                               node_distance(i, j) = i == j ? LOCAL_DISTANCE :
-                                                       REMOTE_DISTANCE;
+                               slit_distance(i, j) = i == j ?
+                                       LOCAL_DISTANCE : REMOTE_DISTANCE;
                return;
        }
 
@@ -592,7 +592,7 @@ void __init acpi_numa_fixup(void)
                        if (!pxm_bit_test(j))
                                continue;
                        node_to = pxm_to_node(j);
-                       node_distance(node_from, node_to) =
+                       slit_distance(node_from, node_to) =
                            slit_table->entry[i * slit_table->locality_count + j];
                }
        }
index 3861d6e..a038035 100644 (file)
@@ -36,6 +36,12 @@ struct node_cpuid_s node_cpuid[NR_CPUS] =
  */
 u8 numa_slit[MAX_NUMNODES * MAX_NUMNODES];
 
+int __node_distance(int from, int to)
+{
+       return slit_distance(from, to);
+}
+EXPORT_SYMBOL(__node_distance);
+
 /* Identify which cnode a physical address resides on */
 int
 paddr_to_nid(unsigned long paddr)
index d57563c..224eea4 100644 (file)
@@ -22,8 +22,7 @@
 void prepare_ftrace_return(unsigned long *parent, unsigned long self_addr)
 {
        unsigned long old;
-       int faulted, err;
-       struct ftrace_graph_ent trace;
+       int faulted;
        unsigned long return_hooker = (unsigned long)
                                &return_to_handler;
 
@@ -63,18 +62,8 @@ void prepare_ftrace_return(unsigned long *parent, unsigned long self_addr)
                return;
        }
 
-       err = ftrace_push_return_trace(old, self_addr, &trace.depth, 0, NULL);
-       if (err == -EBUSY) {
+       if (function_graph_enter(old, self_addr, 0, NULL))
                *parent = old;
-               return;
-       }
-
-       trace.func = self_addr;
-       /* Only trace if the calling function expects to */
-       if (!ftrace_graph_entry(&trace)) {
-               current->curr_ret_stack--;
-               *parent = old;
-       }
 }
 #endif /* CONFIG_FUNCTION_GRAPH_TRACER */
 
index 0170602..6cf8ffb 100644 (file)
@@ -73,7 +73,7 @@ static inline unsigned long mips_get_syscall_arg(unsigned long *arg,
 #ifdef CONFIG_64BIT
        case 4: case 5: case 6: case 7:
 #ifdef CONFIG_MIPS32_O32
-               if (test_thread_flag(TIF_32BIT_REGS))
+               if (test_tsk_thread_flag(task, TIF_32BIT_REGS))
                        return get_user(*arg, (int *)usp + n);
                else
 #endif
index 7f3dfdb..b122cbb 100644 (file)
@@ -322,7 +322,6 @@ void prepare_ftrace_return(unsigned long *parent_ra_addr, unsigned long self_ra,
                           unsigned long fp)
 {
        unsigned long old_parent_ra;
-       struct ftrace_graph_ent trace;
        unsigned long return_hooker = (unsigned long)
            &return_to_handler;
        int faulted, insns;
@@ -369,12 +368,6 @@ void prepare_ftrace_return(unsigned long *parent_ra_addr, unsigned long self_ra,
        if (unlikely(faulted))
                goto out;
 
-       if (ftrace_push_return_trace(old_parent_ra, self_ra, &trace.depth, fp,
-                                    NULL) == -EBUSY) {
-               *parent_ra_addr = old_parent_ra;
-               return;
-       }
-
        /*
         * Get the recorded ip of the current mcount calling site in the
         * __mcount_loc section, which will be used to filter the function
@@ -382,13 +375,10 @@ void prepare_ftrace_return(unsigned long *parent_ra_addr, unsigned long self_ra,
         */
 
        insns = core_kernel_text(self_ra) ? 2 : MCOUNT_OFFSET_INSNS + 1;
-       trace.func = self_ra - (MCOUNT_INSN_SIZE * insns);
+       self_ra -= (MCOUNT_INSN_SIZE * insns);
 
-       /* Only trace if the calling function expects to */
-       if (!ftrace_graph_entry(&trace)) {
-               current->curr_ret_stack--;
+       if (function_graph_enter(old_parent_ra, self_ra, fp, NULL))
                *parent_ra_addr = old_parent_ra;
-       }
        return;
 out:
        ftrace_graph_stop();
index 41b71c4..c1ce6f4 100644 (file)
@@ -84,7 +84,7 @@ static struct rt2880_pmx_func pcie_rst_grp[] = {
 };
 static struct rt2880_pmx_func nd_sd_grp[] = {
        FUNC("nand", MT7620_GPIO_MODE_NAND, 45, 15),
-       FUNC("sd", MT7620_GPIO_MODE_SD, 45, 15)
+       FUNC("sd", MT7620_GPIO_MODE_SD, 47, 13)
 };
 
 static struct rt2880_pmx_group mt7620a_pinmux_data[] = {
index a0a9679..8a41372 100644 (file)
@@ -211,29 +211,15 @@ void prepare_ftrace_return(unsigned long *parent, unsigned long self_addr,
                           unsigned long frame_pointer)
 {
        unsigned long return_hooker = (unsigned long)&return_to_handler;
-       struct ftrace_graph_ent trace;
        unsigned long old;
-       int err;
 
        if (unlikely(atomic_read(&current->tracing_graph_pause)))
                return;
 
        old = *parent;
 
-       trace.func = self_addr;
-       trace.depth = current->curr_ret_stack + 1;
-
-       /* Only trace if the calling function expects to */
-       if (!ftrace_graph_entry(&trace))
-               return;
-
-       err = ftrace_push_return_trace(old, self_addr, &trace.depth,
-                                      frame_pointer, NULL);
-
-       if (err == -EBUSY)
-               return;
-
-       *parent = return_hooker;
+       if (!function_graph_enter(old, self_addr, frame_pointer, NULL))
+               *parent = return_hooker;
 }
 
 noinline void ftrace_graph_caller(void)
index 6fa8535..e46a415 100644 (file)
@@ -30,7 +30,6 @@ static void __hot prepare_ftrace_return(unsigned long *parent,
                                        unsigned long self_addr)
 {
        unsigned long old;
-       struct ftrace_graph_ent trace;
        extern int parisc_return_to_handler;
 
        if (unlikely(ftrace_graph_is_dead()))
@@ -41,19 +40,9 @@ static void __hot prepare_ftrace_return(unsigned long *parent,
 
        old = *parent;
 
-       trace.func = self_addr;
-       trace.depth = current->curr_ret_stack + 1;
-
-       /* Only trace if the calling function expects to */
-       if (!ftrace_graph_entry(&trace))
-               return;
-
-        if (ftrace_push_return_trace(old, self_addr, &trace.depth,
-                                    0, NULL) == -EBUSY)
-                return;
-
-       /* activate parisc_return_to_handler() as return point */
-       *parent = (unsigned long) &parisc_return_to_handler;
+       if (!function_graph_enter(old, self_addr, 0, NULL))
+               /* activate parisc_return_to_handler() as return point */
+               *parent = (unsigned long) &parisc_return_to_handler;
 }
 #endif /* CONFIG_FUNCTION_GRAPH_TRACER */
 
index 4bf051d..b65c8a3 100644 (file)
@@ -950,7 +950,6 @@ int ftrace_disable_ftrace_graph_caller(void)
  */
 unsigned long prepare_ftrace_return(unsigned long parent, unsigned long ip)
 {
-       struct ftrace_graph_ent trace;
        unsigned long return_hooker;
 
        if (unlikely(ftrace_graph_is_dead()))
@@ -961,18 +960,8 @@ unsigned long prepare_ftrace_return(unsigned long parent, unsigned long ip)
 
        return_hooker = ppc_function_entry(return_to_handler);
 
-       trace.func = ip;
-       trace.depth = current->curr_ret_stack + 1;
-
-       /* Only trace if the calling function expects to */
-       if (!ftrace_graph_entry(&trace))
-               goto out;
-
-       if (ftrace_push_return_trace(parent, ip, &trace.depth, 0,
-                                    NULL) == -EBUSY)
-               goto out;
-
-       parent = return_hooker;
+       if (!function_graph_enter(parent, ip, 0, NULL))
+               parent = return_hooker;
 out:
        return parent;
 }
index d65b961..a56f841 100644 (file)
@@ -983,6 +983,7 @@ int kvmppc_pseries_do_hcall(struct kvm_vcpu *vcpu)
                ret = kvmhv_enter_nested_guest(vcpu);
                if (ret == H_INTERRUPT) {
                        kvmppc_set_gpr(vcpu, 3, 0);
+                       vcpu->arch.hcall_needed = 0;
                        return -EINTR;
                }
                break;
index 50b1297..17482f5 100644 (file)
@@ -166,7 +166,33 @@ static void bpf_jit_build_epilogue(u32 *image, struct codegen_context *ctx)
        PPC_BLR();
 }
 
-static void bpf_jit_emit_func_call(u32 *image, struct codegen_context *ctx, u64 func)
+static void bpf_jit_emit_func_call_hlp(u32 *image, struct codegen_context *ctx,
+                                      u64 func)
+{
+#ifdef PPC64_ELF_ABI_v1
+       /* func points to the function descriptor */
+       PPC_LI64(b2p[TMP_REG_2], func);
+       /* Load actual entry point from function descriptor */
+       PPC_BPF_LL(b2p[TMP_REG_1], b2p[TMP_REG_2], 0);
+       /* ... and move it to LR */
+       PPC_MTLR(b2p[TMP_REG_1]);
+       /*
+        * Load TOC from function descriptor at offset 8.
+        * We can clobber r2 since we get called through a
+        * function pointer (so caller will save/restore r2)
+        * and since we don't use a TOC ourself.
+        */
+       PPC_BPF_LL(2, b2p[TMP_REG_2], 8);
+#else
+       /* We can clobber r12 */
+       PPC_FUNC_ADDR(12, func);
+       PPC_MTLR(12);
+#endif
+       PPC_BLRL();
+}
+
+static void bpf_jit_emit_func_call_rel(u32 *image, struct codegen_context *ctx,
+                                      u64 func)
 {
        unsigned int i, ctx_idx = ctx->idx;
 
@@ -273,7 +299,7 @@ static int bpf_jit_build_body(struct bpf_prog *fp, u32 *image,
 {
        const struct bpf_insn *insn = fp->insnsi;
        int flen = fp->len;
-       int i;
+       int i, ret;
 
        /* Start of epilogue code - will only be valid 2nd pass onwards */
        u32 exit_addr = addrs[flen];
@@ -284,8 +310,9 @@ static int bpf_jit_build_body(struct bpf_prog *fp, u32 *image,
                u32 src_reg = b2p[insn[i].src_reg];
                s16 off = insn[i].off;
                s32 imm = insn[i].imm;
+               bool func_addr_fixed;
+               u64 func_addr;
                u64 imm64;
-               u8 *func;
                u32 true_cond;
                u32 tmp_idx;
 
@@ -711,23 +738,15 @@ emit_clear:
                case BPF_JMP | BPF_CALL:
                        ctx->seen |= SEEN_FUNC;
 
-                       /* bpf function call */
-                       if (insn[i].src_reg == BPF_PSEUDO_CALL)
-                               if (!extra_pass)
-                                       func = NULL;
-                               else if (fp->aux->func && off < fp->aux->func_cnt)
-                                       /* use the subprog id from the off
-                                        * field to lookup the callee address
-                                        */
-                                       func = (u8 *) fp->aux->func[off]->bpf_func;
-                               else
-                                       return -EINVAL;
-                       /* kernel helper call */
-                       else
-                               func = (u8 *) __bpf_call_base + imm;
-
-                       bpf_jit_emit_func_call(image, ctx, (u64)func);
+                       ret = bpf_jit_get_func_addr(fp, &insn[i], extra_pass,
+                                                   &func_addr, &func_addr_fixed);
+                       if (ret < 0)
+                               return ret;
 
+                       if (func_addr_fixed)
+                               bpf_jit_emit_func_call_hlp(image, ctx, func_addr);
+                       else
+                               bpf_jit_emit_func_call_rel(image, ctx, func_addr);
                        /* move return value from r3 to BPF_REG_0 */
                        PPC_MR(b2p[BPF_REG_0], 3);
                        break;
index 1157b6b..c433f6d 100644 (file)
@@ -132,7 +132,6 @@ void prepare_ftrace_return(unsigned long *parent, unsigned long self_addr,
 {
        unsigned long return_hooker = (unsigned long)&return_to_handler;
        unsigned long old;
-       struct ftrace_graph_ent trace;
        int err;
 
        if (unlikely(atomic_read(&current->tracing_graph_pause)))
@@ -144,17 +143,8 @@ void prepare_ftrace_return(unsigned long *parent, unsigned long self_addr,
         */
        old = *parent;
 
-       trace.func = self_addr;
-       trace.depth = current->curr_ret_stack + 1;
-
-       if (!ftrace_graph_entry(&trace))
-               return;
-
-       err = ftrace_push_return_trace(old, self_addr, &trace.depth,
-                                      frame_pointer, parent);
-       if (err == -EBUSY)
-               return;
-       *parent = return_hooker;
+       if (function_graph_enter(old, self_addr, frame_pointer, parent))
+               *parent = return_hooker;
 }
 
 #ifdef CONFIG_DYNAMIC_FTRACE
index 84be7f0..39b13d7 100644 (file)
@@ -203,22 +203,13 @@ device_initcall(ftrace_plt_init);
  */
 unsigned long prepare_ftrace_return(unsigned long parent, unsigned long ip)
 {
-       struct ftrace_graph_ent trace;
-
        if (unlikely(ftrace_graph_is_dead()))
                goto out;
        if (unlikely(atomic_read(&current->tracing_graph_pause)))
                goto out;
        ip -= MCOUNT_INSN_SIZE;
-       trace.func = ip;
-       trace.depth = current->curr_ret_stack + 1;
-       /* Only trace if the calling function expects to. */
-       if (!ftrace_graph_entry(&trace))
-               goto out;
-       if (ftrace_push_return_trace(parent, ip, &trace.depth, 0,
-                                    NULL) == -EBUSY)
-               goto out;
-       parent = (unsigned long) return_to_handler;
+       if (!function_graph_enter(parent, ip, 0, NULL))
+               parent = (unsigned long) return_to_handler;
 out:
        return parent;
 }
index 74091fd..d5523ad 100644 (file)
@@ -346,6 +346,8 @@ static int __hw_perf_event_init(struct perf_event *event)
                break;
 
        case PERF_TYPE_HARDWARE:
+               if (is_sampling_event(event))   /* No sampling support */
+                       return -ENOENT;
                ev = attr->config;
                /* Count user space (problem-state) only */
                if (!attr->exclude_user && attr->exclude_kernel) {
index 814f265..6791562 100644 (file)
@@ -131,6 +131,7 @@ void crst_table_downgrade(struct mm_struct *mm)
        }
 
        pgd = mm->pgd;
+       mm_dec_nr_pmds(mm);
        mm->pgd = (pgd_t *) (pgd_val(*pgd) & _REGION_ENTRY_ORIGIN);
        mm->context.asce_limit = _REGION3_SIZE;
        mm->context.asce = __pa(mm->pgd) | _ASCE_TABLE_LENGTH |
index 96dd9f7..1b04270 100644 (file)
@@ -321,8 +321,7 @@ int ftrace_disable_ftrace_graph_caller(void)
 void prepare_ftrace_return(unsigned long *parent, unsigned long self_addr)
 {
        unsigned long old;
-       int faulted, err;
-       struct ftrace_graph_ent trace;
+       int faulted;
        unsigned long return_hooker = (unsigned long)&return_to_handler;
 
        if (unlikely(ftrace_graph_is_dead()))
@@ -365,18 +364,7 @@ void prepare_ftrace_return(unsigned long *parent, unsigned long self_addr)
                return;
        }
 
-       err = ftrace_push_return_trace(old, self_addr, &trace.depth, 0, NULL);
-       if (err == -EBUSY) {
+       if (function_graph_enter(old, self_addr, 0, NULL))
                __raw_writel(old, parent);
-               return;
-       }
-
-       trace.func = self_addr;
-
-       /* Only trace if the calling function expects to */
-       if (!ftrace_graph_entry(&trace)) {
-               current->curr_ret_stack--;
-               __raw_writel(old, parent);
-       }
 }
 #endif /* CONFIG_FUNCTION_GRAPH_TRACER */
index 915dda4..684b84c 100644 (file)
@@ -126,20 +126,11 @@ unsigned long prepare_ftrace_return(unsigned long parent,
                                    unsigned long frame_pointer)
 {
        unsigned long return_hooker = (unsigned long) &return_to_handler;
-       struct ftrace_graph_ent trace;
 
        if (unlikely(atomic_read(&current->tracing_graph_pause)))
                return parent + 8UL;
 
-       trace.func = self_addr;
-       trace.depth = current->curr_ret_stack + 1;
-
-       /* Only trace if the calling function expects to */
-       if (!ftrace_graph_entry(&trace))
-               return parent + 8UL;
-
-       if (ftrace_push_return_trace(parent, self_addr, &trace.depth,
-                                    frame_pointer, NULL) == -EBUSY)
+       if (function_graph_enter(parent, self_addr, frame_pointer, NULL))
                return parent + 8UL;
 
        return return_hooker;
index 222785a..5fda4f7 100644 (file)
@@ -791,7 +791,7 @@ static int emit_compare_and_branch(const u8 code, const u8 dst, u8 src,
 }
 
 /* Just skip the save instruction and the ctx register move.  */
-#define BPF_TAILCALL_PROLOGUE_SKIP     16
+#define BPF_TAILCALL_PROLOGUE_SKIP     32
 #define BPF_TAILCALL_CNT_SP_OFF                (STACK_BIAS + 128)
 
 static void build_prologue(struct jit_ctx *ctx)
@@ -824,9 +824,15 @@ static void build_prologue(struct jit_ctx *ctx)
                const u8 vfp = bpf2sparc[BPF_REG_FP];
 
                emit(ADD | IMMED | RS1(FP) | S13(STACK_BIAS) | RD(vfp), ctx);
+       } else {
+               emit_nop(ctx);
        }
 
        emit_reg_move(I0, O0, ctx);
+       emit_reg_move(I1, O1, ctx);
+       emit_reg_move(I2, O2, ctx);
+       emit_reg_move(I3, O3, ctx);
+       emit_reg_move(I4, O4, ctx);
        /* If you add anything here, adjust BPF_TAILCALL_PROLOGUE_SKIP above. */
 }
 
@@ -1270,6 +1276,9 @@ static int build_insn(const struct bpf_insn *insn, struct jit_ctx *ctx)
                const u8 tmp2 = bpf2sparc[TMP_REG_2];
                u32 opcode = 0, rs2;
 
+               if (insn->dst_reg == BPF_REG_FP)
+                       ctx->saw_frame_pointer = true;
+
                ctx->tmp_2_used = true;
                emit_loadimm(imm, tmp2, ctx);
 
@@ -1308,6 +1317,9 @@ static int build_insn(const struct bpf_insn *insn, struct jit_ctx *ctx)
                const u8 tmp = bpf2sparc[TMP_REG_1];
                u32 opcode = 0, rs2;
 
+               if (insn->dst_reg == BPF_REG_FP)
+                       ctx->saw_frame_pointer = true;
+
                switch (BPF_SIZE(code)) {
                case BPF_W:
                        opcode = ST32;
@@ -1340,6 +1352,9 @@ static int build_insn(const struct bpf_insn *insn, struct jit_ctx *ctx)
                const u8 tmp2 = bpf2sparc[TMP_REG_2];
                const u8 tmp3 = bpf2sparc[TMP_REG_3];
 
+               if (insn->dst_reg == BPF_REG_FP)
+                       ctx->saw_frame_pointer = true;
+
                ctx->tmp_1_used = true;
                ctx->tmp_2_used = true;
                ctx->tmp_3_used = true;
@@ -1360,6 +1375,9 @@ static int build_insn(const struct bpf_insn *insn, struct jit_ctx *ctx)
                const u8 tmp2 = bpf2sparc[TMP_REG_2];
                const u8 tmp3 = bpf2sparc[TMP_REG_3];
 
+               if (insn->dst_reg == BPF_REG_FP)
+                       ctx->saw_frame_pointer = true;
+
                ctx->tmp_1_used = true;
                ctx->tmp_2_used = true;
                ctx->tmp_3_used = true;
@@ -1425,12 +1443,12 @@ struct bpf_prog *bpf_int_jit_compile(struct bpf_prog *prog)
        struct bpf_prog *tmp, *orig_prog = prog;
        struct sparc64_jit_data *jit_data;
        struct bpf_binary_header *header;
+       u32 prev_image_size, image_size;
        bool tmp_blinded = false;
        bool extra_pass = false;
        struct jit_ctx ctx;
-       u32 image_size;
        u8 *image_ptr;
-       int pass;
+       int pass, i;
 
        if (!prog->jit_requested)
                return orig_prog;
@@ -1461,61 +1479,82 @@ struct bpf_prog *bpf_int_jit_compile(struct bpf_prog *prog)
                header = jit_data->header;
                extra_pass = true;
                image_size = sizeof(u32) * ctx.idx;
+               prev_image_size = image_size;
+               pass = 1;
                goto skip_init_ctx;
        }
 
        memset(&ctx, 0, sizeof(ctx));
        ctx.prog = prog;
 
-       ctx.offset = kcalloc(prog->len, sizeof(unsigned int), GFP_KERNEL);
+       ctx.offset = kmalloc_array(prog->len, sizeof(unsigned int), GFP_KERNEL);
        if (ctx.offset == NULL) {
                prog = orig_prog;
                goto out_off;
        }
 
-       /* Fake pass to detect features used, and get an accurate assessment
-        * of what the final image size will be.
+       /* Longest sequence emitted is for bswap32, 12 instructions.  Pre-cook
+        * the offset array so that we converge faster.
         */
-       if (build_body(&ctx)) {
-               prog = orig_prog;
-               goto out_off;
-       }
-       build_prologue(&ctx);
-       build_epilogue(&ctx);
-
-       /* Now we know the actual image size. */
-       image_size = sizeof(u32) * ctx.idx;
-       header = bpf_jit_binary_alloc(image_size, &image_ptr,
-                                     sizeof(u32), jit_fill_hole);
-       if (header == NULL) {
-               prog = orig_prog;
-               goto out_off;
-       }
+       for (i = 0; i < prog->len; i++)
+               ctx.offset[i] = i * (12 * 4);
 
-       ctx.image = (u32 *)image_ptr;
-skip_init_ctx:
-       for (pass = 1; pass < 3; pass++) {
+       prev_image_size = ~0U;
+       for (pass = 1; pass < 40; pass++) {
                ctx.idx = 0;
 
                build_prologue(&ctx);
-
                if (build_body(&ctx)) {
-                       bpf_jit_binary_free(header);
                        prog = orig_prog;
                        goto out_off;
                }
-
                build_epilogue(&ctx);
 
                if (bpf_jit_enable > 1)
-                       pr_info("Pass %d: shrink = %d, seen = [%c%c%c%c%c%c]\n", pass,
-                               image_size - (ctx.idx * 4),
+                       pr_info("Pass %d: size = %u, seen = [%c%c%c%c%c%c]\n", pass,
+                               ctx.idx * 4,
                                ctx.tmp_1_used ? '1' : ' ',
                                ctx.tmp_2_used ? '2' : ' ',
                                ctx.tmp_3_used ? '3' : ' ',
                                ctx.saw_frame_pointer ? 'F' : ' ',
                                ctx.saw_call ? 'C' : ' ',
                                ctx.saw_tail_call ? 'T' : ' ');
+
+               if (ctx.idx * 4 == prev_image_size)
+                       break;
+               prev_image_size = ctx.idx * 4;
+               cond_resched();
+       }
+
+       /* Now we know the actual image size. */
+       image_size = sizeof(u32) * ctx.idx;
+       header = bpf_jit_binary_alloc(image_size, &image_ptr,
+                                     sizeof(u32), jit_fill_hole);
+       if (header == NULL) {
+               prog = orig_prog;
+               goto out_off;
+       }
+
+       ctx.image = (u32 *)image_ptr;
+skip_init_ctx:
+       ctx.idx = 0;
+
+       build_prologue(&ctx);
+
+       if (build_body(&ctx)) {
+               bpf_jit_binary_free(header);
+               prog = orig_prog;
+               goto out_off;
+       }
+
+       build_epilogue(&ctx);
+
+       if (ctx.idx * 4 != prev_image_size) {
+               pr_err("bpf_jit: Failed to converge, prev_size=%u size=%d\n",
+                      prev_image_size, ctx.idx * 4);
+               bpf_jit_binary_free(header);
+               prog = orig_prog;
+               goto out_off;
        }
 
        if (bpf_jit_enable > 1)
index 9d734f3..8689e79 100644 (file)
@@ -444,10 +444,6 @@ config RETPOLINE
          branches. Requires a compiler with -mindirect-branch=thunk-extern
          support for full protection. The kernel may run slower.
 
-         Without compiler support, at least indirect branches in assembler
-         code are eliminated. Since this includes the syscall entry path,
-         it is not entirely pointless.
-
 config INTEL_RDT
        bool "Intel Resource Director Technology support"
        depends on X86 && CPU_SUP_INTEL
@@ -1004,13 +1000,7 @@ config NR_CPUS
          to the kernel image.
 
 config SCHED_SMT
-       bool "SMT (Hyperthreading) scheduler support"
-       depends on SMP
-       ---help---
-         SMT scheduler support improves the CPU scheduler's decision making
-         when dealing with Intel Pentium 4 chips with HyperThreading at a
-         cost of slightly increased overhead in some places. If unsure say
-         N here.
+       def_bool y if SMP
 
 config SCHED_MC
        def_bool y
index 88398fd..f5d7f41 100644 (file)
@@ -220,9 +220,10 @@ KBUILD_CFLAGS += -fno-asynchronous-unwind-tables
 
 # Avoid indirect branches in kernel to deal with Spectre
 ifdef CONFIG_RETPOLINE
-ifneq ($(RETPOLINE_CFLAGS),)
-  KBUILD_CFLAGS += $(RETPOLINE_CFLAGS) -DRETPOLINE
+ifeq ($(RETPOLINE_CFLAGS),)
+  $(error You are building kernel with non-retpoline compiler, please update your compiler.)
 endif
+  KBUILD_CFLAGS += $(RETPOLINE_CFLAGS)
 endif
 
 archscripts: scripts_basic
index 4c881c8..850b876 100644 (file)
@@ -300,7 +300,7 @@ _start:
        # Part 2 of the header, from the old setup.S
 
                .ascii  "HdrS"          # header signature
-               .word   0x020e          # header version number (>= 0x0105)
+               .word   0x020d          # header version number (>= 0x0105)
                                        # or else old loadlin-1.5 will fail)
                .globl realmode_swtch
 realmode_swtch:        .word   0, 0            # default_switch, SETUPSEG
@@ -558,10 +558,6 @@ pref_address:              .quad LOAD_PHYSICAL_ADDR        # preferred load addr
 init_size:             .long INIT_SIZE         # kernel initialization size
 handover_offset:       .long 0                 # Filled in by build.c
 
-acpi_rsdp_addr:                .quad 0                 # 64-bit physical pointer to the
-                                               # ACPI RSDP table, added with
-                                               # version 2.14
-
 # End of setup header #####################################################
 
        .section ".entrytext", "ax"
index 106911b..374a197 100644 (file)
@@ -438,26 +438,6 @@ int x86_setup_perfctr(struct perf_event *event)
        if (config == -1LL)
                return -EINVAL;
 
-       /*
-        * Branch tracing:
-        */
-       if (attr->config == PERF_COUNT_HW_BRANCH_INSTRUCTIONS &&
-           !attr->freq && hwc->sample_period == 1) {
-               /* BTS is not supported by this architecture. */
-               if (!x86_pmu.bts_active)
-                       return -EOPNOTSUPP;
-
-               /* BTS is currently only allowed for user-mode. */
-               if (!attr->exclude_kernel)
-                       return -EOPNOTSUPP;
-
-               /* disallow bts if conflicting events are present */
-               if (x86_add_exclusive(x86_lbr_exclusive_lbr))
-                       return -EBUSY;
-
-               event->destroy = hw_perf_lbr_event_destroy;
-       }
-
        hwc->config |= config;
 
        return 0;
index 273c62e..ecc3e34 100644 (file)
@@ -2306,14 +2306,18 @@ static int handle_pmi_common(struct pt_regs *regs, u64 status)
        return handled;
 }
 
-static bool disable_counter_freezing;
+static bool disable_counter_freezing = true;
 static int __init intel_perf_counter_freezing_setup(char *s)
 {
-       disable_counter_freezing = true;
-       pr_info("Intel PMU Counter freezing feature disabled\n");
+       bool res;
+
+       if (kstrtobool(s, &res))
+               return -EINVAL;
+
+       disable_counter_freezing = !res;
        return 1;
 }
-__setup("disable_counter_freezing", intel_perf_counter_freezing_setup);
+__setup("perf_v4_pmi=", intel_perf_counter_freezing_setup);
 
 /*
  * Simplified handler for Arch Perfmon v4:
@@ -2470,16 +2474,7 @@ done:
 static struct event_constraint *
 intel_bts_constraints(struct perf_event *event)
 {
-       struct hw_perf_event *hwc = &event->hw;
-       unsigned int hw_event, bts_event;
-
-       if (event->attr.freq)
-               return NULL;
-
-       hw_event = hwc->config & INTEL_ARCH_EVENT_MASK;
-       bts_event = x86_pmu.event_map(PERF_COUNT_HW_BRANCH_INSTRUCTIONS);
-
-       if (unlikely(hw_event == bts_event && hwc->sample_period == 1))
+       if (unlikely(intel_pmu_has_bts(event)))
                return &bts_constraint;
 
        return NULL;
@@ -3098,10 +3093,51 @@ static unsigned long intel_pmu_large_pebs_flags(struct perf_event *event)
        return flags;
 }
 
+static int intel_pmu_bts_config(struct perf_event *event)
+{
+       struct perf_event_attr *attr = &event->attr;
+
+       if (unlikely(intel_pmu_has_bts(event))) {
+               /* BTS is not supported by this architecture. */
+               if (!x86_pmu.bts_active)
+                       return -EOPNOTSUPP;
+
+               /* BTS is currently only allowed for user-mode. */
+               if (!attr->exclude_kernel)
+                       return -EOPNOTSUPP;
+
+               /* BTS is not allowed for precise events. */
+               if (attr->precise_ip)
+                       return -EOPNOTSUPP;
+
+               /* disallow bts if conflicting events are present */
+               if (x86_add_exclusive(x86_lbr_exclusive_lbr))
+                       return -EBUSY;
+
+               event->destroy = hw_perf_lbr_event_destroy;
+       }
+
+       return 0;
+}
+
+static int core_pmu_hw_config(struct perf_event *event)
+{
+       int ret = x86_pmu_hw_config(event);
+
+       if (ret)
+               return ret;
+
+       return intel_pmu_bts_config(event);
+}
+
 static int intel_pmu_hw_config(struct perf_event *event)
 {
        int ret = x86_pmu_hw_config(event);
 
+       if (ret)
+               return ret;
+
+       ret = intel_pmu_bts_config(event);
        if (ret)
                return ret;
 
@@ -3127,7 +3163,7 @@ static int intel_pmu_hw_config(struct perf_event *event)
                /*
                 * BTS is set up earlier in this path, so don't account twice
                 */
-               if (!intel_pmu_has_bts(event)) {
+               if (!unlikely(intel_pmu_has_bts(event))) {
                        /* disallow lbr if conflicting events are present */
                        if (x86_add_exclusive(x86_lbr_exclusive_lbr))
                                return -EBUSY;
@@ -3596,7 +3632,7 @@ static __initconst const struct x86_pmu core_pmu = {
        .enable_all             = core_pmu_enable_all,
        .enable                 = core_pmu_enable_event,
        .disable                = x86_pmu_disable_event,
-       .hw_config              = x86_pmu_hw_config,
+       .hw_config              = core_pmu_hw_config,
        .schedule_events        = x86_schedule_events,
        .eventsel               = MSR_ARCH_PERFMON_EVENTSEL0,
        .perfctr                = MSR_ARCH_PERFMON_PERFCTR0,
index adae087..78d7b70 100644 (file)
@@ -859,11 +859,16 @@ static inline int amd_pmu_init(void)
 
 static inline bool intel_pmu_has_bts(struct perf_event *event)
 {
-       if (event->attr.config == PERF_COUNT_HW_BRANCH_INSTRUCTIONS &&
-           !event->attr.freq && event->hw.sample_period == 1)
-               return true;
+       struct hw_perf_event *hwc = &event->hw;
+       unsigned int hw_event, bts_event;
+
+       if (event->attr.freq)
+               return false;
+
+       hw_event = hwc->config & INTEL_ARCH_EVENT_MASK;
+       bts_event = x86_pmu.event_map(PERF_COUNT_HW_BRANCH_INSTRUCTIONS);
 
-       return false;
+       return hw_event == bts_event && hwc->sample_period == 1;
 }
 
 int intel_pmu_save_and_restart(struct perf_event *event);
index 5f7290e..69dcdf1 100644 (file)
@@ -226,7 +226,7 @@ static inline void copy_fxregs_to_kernel(struct fpu *fpu)
                     "3: movl $-2,%[err]\n\t"                           \
                     "jmp 2b\n\t"                                       \
                     ".popsection\n\t"                                  \
-                    _ASM_EXTABLE_UA(1b, 3b)                            \
+                    _ASM_EXTABLE(1b, 3b)                               \
                     : [err] "=r" (err)                                 \
                     : "D" (st), "m" (*st), "a" (lmask), "d" (hmask)    \
                     : "memory")
index 55e51ff..fbda5a9 100644 (file)
@@ -1094,7 +1094,8 @@ struct kvm_x86_ops {
        bool (*has_wbinvd_exit)(void);
 
        u64 (*read_l1_tsc_offset)(struct kvm_vcpu *vcpu);
-       void (*write_tsc_offset)(struct kvm_vcpu *vcpu, u64 offset);
+       /* Returns actual tsc_offset set in active VMCS */
+       u64 (*write_l1_tsc_offset)(struct kvm_vcpu *vcpu, u64 offset);
 
        void (*get_exit_info)(struct kvm_vcpu *vcpu, u64 *info1, u64 *info2);
 
index 80f4a4f..c8f73ef 100644 (file)
 
 #define MSR_IA32_SPEC_CTRL             0x00000048 /* Speculation Control */
 #define SPEC_CTRL_IBRS                 (1 << 0)   /* Indirect Branch Restricted Speculation */
-#define SPEC_CTRL_STIBP                        (1 << 1)   /* Single Thread Indirect Branch Predictors */
+#define SPEC_CTRL_STIBP_SHIFT          1          /* Single Thread Indirect Branch Predictor (STIBP) bit */
+#define SPEC_CTRL_STIBP                        (1 << SPEC_CTRL_STIBP_SHIFT)    /* STIBP mask */
 #define SPEC_CTRL_SSBD_SHIFT           2          /* Speculative Store Bypass Disable bit */
-#define SPEC_CTRL_SSBD                 (1 << SPEC_CTRL_SSBD_SHIFT)   /* Speculative Store Bypass Disable */
+#define SPEC_CTRL_SSBD                 (1 << SPEC_CTRL_SSBD_SHIFT)     /* Speculative Store Bypass Disable */
 
 #define MSR_IA32_PRED_CMD              0x00000049 /* Prediction Command */
 #define PRED_CMD_IBPB                  (1 << 0)   /* Indirect Branch Prediction Barrier */
index 80dc144..032b600 100644 (file)
@@ -3,6 +3,8 @@
 #ifndef _ASM_X86_NOSPEC_BRANCH_H_
 #define _ASM_X86_NOSPEC_BRANCH_H_
 
+#include <linux/static_key.h>
+
 #include <asm/alternative.h>
 #include <asm/alternative-asm.h>
 #include <asm/cpufeatures.h>
        _ASM_PTR " 999b\n\t"                                    \
        ".popsection\n\t"
 
-#if defined(CONFIG_X86_64) && defined(RETPOLINE)
+#ifdef CONFIG_RETPOLINE
+#ifdef CONFIG_X86_64
 
 /*
- * Since the inline asm uses the %V modifier which is only in newer GCC,
- * the 64-bit one is dependent on RETPOLINE not CONFIG_RETPOLINE.
+ * Inline asm uses the %V modifier which is only in newer GCC
+ * which is ensured when CONFIG_RETPOLINE is defined.
  */
 # define CALL_NOSPEC                                           \
        ANNOTATE_NOSPEC_ALTERNATIVE                             \
        X86_FEATURE_RETPOLINE_AMD)
 # define THUNK_TARGET(addr) [thunk_target] "r" (addr)
 
-#elif defined(CONFIG_X86_32) && defined(CONFIG_RETPOLINE)
+#else /* CONFIG_X86_32 */
 /*
  * For i386 we use the original ret-equivalent retpoline, because
  * otherwise we'll run out of registers. We don't care about CET
        X86_FEATURE_RETPOLINE_AMD)
 
 # define THUNK_TARGET(addr) [thunk_target] "rm" (addr)
+#endif
 #else /* No retpoline for C / inline asm */
 # define CALL_NOSPEC "call *%[thunk_target]\n"
 # define THUNK_TARGET(addr) [thunk_target] "rm" (addr)
 /* The Spectre V2 mitigation variants */
 enum spectre_v2_mitigation {
        SPECTRE_V2_NONE,
-       SPECTRE_V2_RETPOLINE_MINIMAL,
-       SPECTRE_V2_RETPOLINE_MINIMAL_AMD,
        SPECTRE_V2_RETPOLINE_GENERIC,
        SPECTRE_V2_RETPOLINE_AMD,
        SPECTRE_V2_IBRS_ENHANCED,
 };
 
+/* The indirect branch speculation control variants */
+enum spectre_v2_user_mitigation {
+       SPECTRE_V2_USER_NONE,
+       SPECTRE_V2_USER_STRICT,
+       SPECTRE_V2_USER_PRCTL,
+       SPECTRE_V2_USER_SECCOMP,
+};
+
 /* The Speculative Store Bypass disable variants */
 enum ssb_mitigation {
        SPEC_STORE_BYPASS_NONE,
@@ -303,6 +313,10 @@ do {                                                                       \
        preempt_enable();                                               \
 } while (0)
 
+DECLARE_STATIC_KEY_FALSE(switch_to_cond_stibp);
+DECLARE_STATIC_KEY_FALSE(switch_mm_cond_ibpb);
+DECLARE_STATIC_KEY_FALSE(switch_mm_always_ibpb);
+
 #endif /* __ASSEMBLY__ */
 
 /*
index ae7c2c5..5393bab 100644 (file)
@@ -53,12 +53,24 @@ static inline u64 ssbd_tif_to_spec_ctrl(u64 tifn)
        return (tifn & _TIF_SSBD) >> (TIF_SSBD - SPEC_CTRL_SSBD_SHIFT);
 }
 
+static inline u64 stibp_tif_to_spec_ctrl(u64 tifn)
+{
+       BUILD_BUG_ON(TIF_SPEC_IB < SPEC_CTRL_STIBP_SHIFT);
+       return (tifn & _TIF_SPEC_IB) >> (TIF_SPEC_IB - SPEC_CTRL_STIBP_SHIFT);
+}
+
 static inline unsigned long ssbd_spec_ctrl_to_tif(u64 spec_ctrl)
 {
        BUILD_BUG_ON(TIF_SSBD < SPEC_CTRL_SSBD_SHIFT);
        return (spec_ctrl & SPEC_CTRL_SSBD) << (TIF_SSBD - SPEC_CTRL_SSBD_SHIFT);
 }
 
+static inline unsigned long stibp_spec_ctrl_to_tif(u64 spec_ctrl)
+{
+       BUILD_BUG_ON(TIF_SPEC_IB < SPEC_CTRL_STIBP_SHIFT);
+       return (spec_ctrl & SPEC_CTRL_STIBP) << (TIF_SPEC_IB - SPEC_CTRL_STIBP_SHIFT);
+}
+
 static inline u64 ssbd_tif_to_amd_ls_cfg(u64 tifn)
 {
        return (tifn & _TIF_SSBD) ? x86_amd_ls_cfg_ssbd_mask : 0ULL;
@@ -70,11 +82,7 @@ extern void speculative_store_bypass_ht_init(void);
 static inline void speculative_store_bypass_ht_init(void) { }
 #endif
 
-extern void speculative_store_bypass_update(unsigned long tif);
-
-static inline void speculative_store_bypass_update_current(void)
-{
-       speculative_store_bypass_update(current_thread_info()->flags);
-}
+extern void speculation_ctrl_update(unsigned long tif);
+extern void speculation_ctrl_update_current(void);
 
 #endif
index 36bd243..7cf1a27 100644 (file)
@@ -11,9 +11,6 @@ struct task_struct *__switch_to_asm(struct task_struct *prev,
 
 __visible struct task_struct *__switch_to(struct task_struct *prev,
                                          struct task_struct *next);
-struct tss_struct;
-void __switch_to_xtra(struct task_struct *prev_p, struct task_struct *next_p,
-                     struct tss_struct *tss);
 
 /* This runs runs on the previous thread's stack. */
 static inline void prepare_switch_to(struct task_struct *next)
index 2ff2a30..82b73b7 100644 (file)
@@ -79,10 +79,12 @@ struct thread_info {
 #define TIF_SIGPENDING         2       /* signal pending */
 #define TIF_NEED_RESCHED       3       /* rescheduling necessary */
 #define TIF_SINGLESTEP         4       /* reenable singlestep on user return*/
-#define TIF_SSBD                       5       /* Reduced data speculation */
+#define TIF_SSBD               5       /* Speculative store bypass disable */
 #define TIF_SYSCALL_EMU                6       /* syscall emulation active */
 #define TIF_SYSCALL_AUDIT      7       /* syscall auditing active */
 #define TIF_SECCOMP            8       /* secure computing */
+#define TIF_SPEC_IB            9       /* Indirect branch speculation mitigation */
+#define TIF_SPEC_FORCE_UPDATE  10      /* Force speculation MSR update in context switch */
 #define TIF_USER_RETURN_NOTIFY 11      /* notify kernel of userspace return */
 #define TIF_UPROBE             12      /* breakpointed or singlestepping */
 #define TIF_PATCH_PENDING      13      /* pending live patching update */
@@ -110,6 +112,8 @@ struct thread_info {
 #define _TIF_SYSCALL_EMU       (1 << TIF_SYSCALL_EMU)
 #define _TIF_SYSCALL_AUDIT     (1 << TIF_SYSCALL_AUDIT)
 #define _TIF_SECCOMP           (1 << TIF_SECCOMP)
+#define _TIF_SPEC_IB           (1 << TIF_SPEC_IB)
+#define _TIF_SPEC_FORCE_UPDATE (1 << TIF_SPEC_FORCE_UPDATE)
 #define _TIF_USER_RETURN_NOTIFY        (1 << TIF_USER_RETURN_NOTIFY)
 #define _TIF_UPROBE            (1 << TIF_UPROBE)
 #define _TIF_PATCH_PENDING     (1 << TIF_PATCH_PENDING)
@@ -145,8 +149,18 @@ struct thread_info {
         _TIF_FSCHECK)
 
 /* flags to check in __switch_to() */
-#define _TIF_WORK_CTXSW                                                        \
-       (_TIF_IO_BITMAP|_TIF_NOCPUID|_TIF_NOTSC|_TIF_BLOCKSTEP|_TIF_SSBD)
+#define _TIF_WORK_CTXSW_BASE                                           \
+       (_TIF_IO_BITMAP|_TIF_NOCPUID|_TIF_NOTSC|_TIF_BLOCKSTEP|         \
+        _TIF_SSBD | _TIF_SPEC_FORCE_UPDATE)
+
+/*
+ * Avoid calls to __switch_to_xtra() on UP as STIBP is not evaluated.
+ */
+#ifdef CONFIG_SMP
+# define _TIF_WORK_CTXSW       (_TIF_WORK_CTXSW_BASE | _TIF_SPEC_IB)
+#else
+# define _TIF_WORK_CTXSW       (_TIF_WORK_CTXSW_BASE)
+#endif
 
 #define _TIF_WORK_CTXSW_PREV (_TIF_WORK_CTXSW|_TIF_USER_RETURN_NOTIFY)
 #define _TIF_WORK_CTXSW_NEXT (_TIF_WORK_CTXSW)
index d760611..f4204bf 100644 (file)
@@ -169,10 +169,14 @@ struct tlb_state {
 
 #define LOADED_MM_SWITCHING ((struct mm_struct *)1)
 
+       /* Last user mm for optimizing IBPB */
+       union {
+               struct mm_struct        *last_user_mm;
+               unsigned long           last_user_mm_ibpb;
+       };
+
        u16 loaded_mm_asid;
        u16 next_asid;
-       /* last user mm's ctx id */
-       u64 last_ctx_id;
 
        /*
         * We can be in one of several states:
index 0f84210..b85a7c5 100644 (file)
@@ -303,6 +303,4 @@ extern void x86_init_noop(void);
 extern void x86_init_uint_noop(unsigned int unused);
 extern bool x86_pnpbios_disabled(void);
 
-void x86_verify_bootdata_version(void);
-
 #endif
index 22f89d0..60733f1 100644 (file)
@@ -16,9 +16,6 @@
 #define RAMDISK_PROMPT_FLAG            0x8000
 #define RAMDISK_LOAD_FLAG              0x4000
 
-/* version flags */
-#define VERSION_WRITTEN        0x8000
-
 /* loadflags */
 #define LOADED_HIGH    (1<<0)
 #define KASLR_FLAG     (1<<1)
@@ -89,7 +86,6 @@ struct setup_header {
        __u64   pref_address;
        __u32   init_size;
        __u32   handover_offset;
-       __u64   acpi_rsdp_addr;
 } __attribute__((packed));
 
 struct sys_desc_table {
@@ -159,7 +155,8 @@ struct boot_params {
        __u8  _pad2[4];                                 /* 0x054 */
        __u64  tboot_addr;                              /* 0x058 */
        struct ist_info ist_info;                       /* 0x060 */
-       __u8  _pad3[16];                                /* 0x070 */
+       __u64 acpi_rsdp_addr;                           /* 0x070 */
+       __u8  _pad3[8];                                 /* 0x078 */
        __u8  hd0_info[16];     /* obsolete! */         /* 0x080 */
        __u8  hd1_info[16];     /* obsolete! */         /* 0x090 */
        struct sys_desc_table sys_desc_table; /* obsolete! */   /* 0x0a0 */
index 92c76bf..06635fb 100644 (file)
@@ -1776,5 +1776,5 @@ void __init arch_reserve_mem_area(acpi_physical_address addr, size_t size)
 
 u64 x86_default_get_root_pointer(void)
 {
-       return boot_params.hdr.acpi_rsdp_addr;
+       return boot_params.acpi_rsdp_addr;
 }
index c37e66e..500278f 100644 (file)
@@ -14,6 +14,7 @@
 #include <linux/module.h>
 #include <linux/nospec.h>
 #include <linux/prctl.h>
+#include <linux/sched/smt.h>
 
 #include <asm/spec-ctrl.h>
 #include <asm/cmdline.h>
@@ -53,6 +54,13 @@ static u64 __ro_after_init x86_spec_ctrl_mask = SPEC_CTRL_IBRS;
 u64 __ro_after_init x86_amd_ls_cfg_base;
 u64 __ro_after_init x86_amd_ls_cfg_ssbd_mask;
 
+/* Control conditional STIPB in switch_to() */
+DEFINE_STATIC_KEY_FALSE(switch_to_cond_stibp);
+/* Control conditional IBPB in switch_mm() */
+DEFINE_STATIC_KEY_FALSE(switch_mm_cond_ibpb);
+/* Control unconditional IBPB in switch_mm() */
+DEFINE_STATIC_KEY_FALSE(switch_mm_always_ibpb);
+
 void __init check_bugs(void)
 {
        identify_boot_cpu();
@@ -123,31 +131,6 @@ void __init check_bugs(void)
 #endif
 }
 
-/* The kernel command line selection */
-enum spectre_v2_mitigation_cmd {
-       SPECTRE_V2_CMD_NONE,
-       SPECTRE_V2_CMD_AUTO,
-       SPECTRE_V2_CMD_FORCE,
-       SPECTRE_V2_CMD_RETPOLINE,
-       SPECTRE_V2_CMD_RETPOLINE_GENERIC,
-       SPECTRE_V2_CMD_RETPOLINE_AMD,
-};
-
-static const char *spectre_v2_strings[] = {
-       [SPECTRE_V2_NONE]                       = "Vulnerable",
-       [SPECTRE_V2_RETPOLINE_MINIMAL]          = "Vulnerable: Minimal generic ASM retpoline",
-       [SPECTRE_V2_RETPOLINE_MINIMAL_AMD]      = "Vulnerable: Minimal AMD ASM retpoline",
-       [SPECTRE_V2_RETPOLINE_GENERIC]          = "Mitigation: Full generic retpoline",
-       [SPECTRE_V2_RETPOLINE_AMD]              = "Mitigation: Full AMD retpoline",
-       [SPECTRE_V2_IBRS_ENHANCED]              = "Mitigation: Enhanced IBRS",
-};
-
-#undef pr_fmt
-#define pr_fmt(fmt)     "Spectre V2 : " fmt
-
-static enum spectre_v2_mitigation spectre_v2_enabled __ro_after_init =
-       SPECTRE_V2_NONE;
-
 void
 x86_virt_spec_ctrl(u64 guest_spec_ctrl, u64 guest_virt_spec_ctrl, bool setguest)
 {
@@ -169,6 +152,10 @@ x86_virt_spec_ctrl(u64 guest_spec_ctrl, u64 guest_virt_spec_ctrl, bool setguest)
                    static_cpu_has(X86_FEATURE_AMD_SSBD))
                        hostval |= ssbd_tif_to_spec_ctrl(ti->flags);
 
+               /* Conditional STIBP enabled? */
+               if (static_branch_unlikely(&switch_to_cond_stibp))
+                       hostval |= stibp_tif_to_spec_ctrl(ti->flags);
+
                if (hostval != guestval) {
                        msrval = setguest ? guestval : hostval;
                        wrmsrl(MSR_IA32_SPEC_CTRL, msrval);
@@ -202,7 +189,7 @@ x86_virt_spec_ctrl(u64 guest_spec_ctrl, u64 guest_virt_spec_ctrl, bool setguest)
                tif = setguest ? ssbd_spec_ctrl_to_tif(guestval) :
                                 ssbd_spec_ctrl_to_tif(hostval);
 
-               speculative_store_bypass_update(tif);
+               speculation_ctrl_update(tif);
        }
 }
 EXPORT_SYMBOL_GPL(x86_virt_spec_ctrl);
@@ -217,6 +204,15 @@ static void x86_amd_ssb_disable(void)
                wrmsrl(MSR_AMD64_LS_CFG, msrval);
 }
 
+#undef pr_fmt
+#define pr_fmt(fmt)     "Spectre V2 : " fmt
+
+static enum spectre_v2_mitigation spectre_v2_enabled __ro_after_init =
+       SPECTRE_V2_NONE;
+
+static enum spectre_v2_user_mitigation spectre_v2_user __ro_after_init =
+       SPECTRE_V2_USER_NONE;
+
 #ifdef RETPOLINE
 static bool spectre_v2_bad_module;
 
@@ -238,67 +234,217 @@ static inline const char *spectre_v2_module_string(void)
 static inline const char *spectre_v2_module_string(void) { return ""; }
 #endif
 
-static void __init spec2_print_if_insecure(const char *reason)
+static inline bool match_option(const char *arg, int arglen, const char *opt)
 {
-       if (boot_cpu_has_bug(X86_BUG_SPECTRE_V2))
-               pr_info("%s selected on command line.\n", reason);
+       int len = strlen(opt);
+
+       return len == arglen && !strncmp(arg, opt, len);
 }
 
-static void __init spec2_print_if_secure(const char *reason)
+/* The kernel command line selection for spectre v2 */
+enum spectre_v2_mitigation_cmd {
+       SPECTRE_V2_CMD_NONE,
+       SPECTRE_V2_CMD_AUTO,
+       SPECTRE_V2_CMD_FORCE,
+       SPECTRE_V2_CMD_RETPOLINE,
+       SPECTRE_V2_CMD_RETPOLINE_GENERIC,
+       SPECTRE_V2_CMD_RETPOLINE_AMD,
+};
+
+enum spectre_v2_user_cmd {
+       SPECTRE_V2_USER_CMD_NONE,
+       SPECTRE_V2_USER_CMD_AUTO,
+       SPECTRE_V2_USER_CMD_FORCE,
+       SPECTRE_V2_USER_CMD_PRCTL,
+       SPECTRE_V2_USER_CMD_PRCTL_IBPB,
+       SPECTRE_V2_USER_CMD_SECCOMP,
+       SPECTRE_V2_USER_CMD_SECCOMP_IBPB,
+};
+
+static const char * const spectre_v2_user_strings[] = {
+       [SPECTRE_V2_USER_NONE]          = "User space: Vulnerable",
+       [SPECTRE_V2_USER_STRICT]        = "User space: Mitigation: STIBP protection",
+       [SPECTRE_V2_USER_PRCTL]         = "User space: Mitigation: STIBP via prctl",
+       [SPECTRE_V2_USER_SECCOMP]       = "User space: Mitigation: STIBP via seccomp and prctl",
+};
+
+static const struct {
+       const char                      *option;
+       enum spectre_v2_user_cmd        cmd;
+       bool                            secure;
+} v2_user_options[] __initdata = {
+       { "auto",               SPECTRE_V2_USER_CMD_AUTO,               false },
+       { "off",                SPECTRE_V2_USER_CMD_NONE,               false },
+       { "on",                 SPECTRE_V2_USER_CMD_FORCE,              true  },
+       { "prctl",              SPECTRE_V2_USER_CMD_PRCTL,              false },
+       { "prctl,ibpb",         SPECTRE_V2_USER_CMD_PRCTL_IBPB,         false },
+       { "seccomp",            SPECTRE_V2_USER_CMD_SECCOMP,            false },
+       { "seccomp,ibpb",       SPECTRE_V2_USER_CMD_SECCOMP_IBPB,       false },
+};
+
+static void __init spec_v2_user_print_cond(const char *reason, bool secure)
 {
-       if (!boot_cpu_has_bug(X86_BUG_SPECTRE_V2))
-               pr_info("%s selected on command line.\n", reason);
+       if (boot_cpu_has_bug(X86_BUG_SPECTRE_V2) != secure)
+               pr_info("spectre_v2_user=%s forced on command line.\n", reason);
 }
 
-static inline bool retp_compiler(void)
+static enum spectre_v2_user_cmd __init
+spectre_v2_parse_user_cmdline(enum spectre_v2_mitigation_cmd v2_cmd)
 {
-       return __is_defined(RETPOLINE);
+       char arg[20];
+       int ret, i;
+
+       switch (v2_cmd) {
+       case SPECTRE_V2_CMD_NONE:
+               return SPECTRE_V2_USER_CMD_NONE;
+       case SPECTRE_V2_CMD_FORCE:
+               return SPECTRE_V2_USER_CMD_FORCE;
+       default:
+               break;
+       }
+
+       ret = cmdline_find_option(boot_command_line, "spectre_v2_user",
+                                 arg, sizeof(arg));
+       if (ret < 0)
+               return SPECTRE_V2_USER_CMD_AUTO;
+
+       for (i = 0; i < ARRAY_SIZE(v2_user_options); i++) {
+               if (match_option(arg, ret, v2_user_options[i].option)) {
+                       spec_v2_user_print_cond(v2_user_options[i].option,
+                                               v2_user_options[i].secure);
+                       return v2_user_options[i].cmd;
+               }
+       }
+
+       pr_err("Unknown user space protection option (%s). Switching to AUTO select\n", arg);
+       return SPECTRE_V2_USER_CMD_AUTO;
 }
 
-static inline bool match_option(const char *arg, int arglen, const char *opt)
+static void __init
+spectre_v2_user_select_mitigation(enum spectre_v2_mitigation_cmd v2_cmd)
 {
-       int len = strlen(opt);
+       enum spectre_v2_user_mitigation mode = SPECTRE_V2_USER_NONE;
+       bool smt_possible = IS_ENABLED(CONFIG_SMP);
+       enum spectre_v2_user_cmd cmd;
 
-       return len == arglen && !strncmp(arg, opt, len);
+       if (!boot_cpu_has(X86_FEATURE_IBPB) && !boot_cpu_has(X86_FEATURE_STIBP))
+               return;
+
+       if (cpu_smt_control == CPU_SMT_FORCE_DISABLED ||
+           cpu_smt_control == CPU_SMT_NOT_SUPPORTED)
+               smt_possible = false;
+
+       cmd = spectre_v2_parse_user_cmdline(v2_cmd);
+       switch (cmd) {
+       case SPECTRE_V2_USER_CMD_NONE:
+               goto set_mode;
+       case SPECTRE_V2_USER_CMD_FORCE:
+               mode = SPECTRE_V2_USER_STRICT;
+               break;
+       case SPECTRE_V2_USER_CMD_PRCTL:
+       case SPECTRE_V2_USER_CMD_PRCTL_IBPB:
+               mode = SPECTRE_V2_USER_PRCTL;
+               break;
+       case SPECTRE_V2_USER_CMD_AUTO:
+       case SPECTRE_V2_USER_CMD_SECCOMP:
+       case SPECTRE_V2_USER_CMD_SECCOMP_IBPB:
+               if (IS_ENABLED(CONFIG_SECCOMP))
+                       mode = SPECTRE_V2_USER_SECCOMP;
+               else
+                       mode = SPECTRE_V2_USER_PRCTL;
+               break;
+       }
+
+       /* Initialize Indirect Branch Prediction Barrier */
+       if (boot_cpu_has(X86_FEATURE_IBPB)) {
+               setup_force_cpu_cap(X86_FEATURE_USE_IBPB);
+
+               switch (cmd) {
+               case SPECTRE_V2_USER_CMD_FORCE:
+               case SPECTRE_V2_USER_CMD_PRCTL_IBPB:
+               case SPECTRE_V2_USER_CMD_SECCOMP_IBPB:
+                       static_branch_enable(&switch_mm_always_ibpb);
+                       break;
+               case SPECTRE_V2_USER_CMD_PRCTL:
+               case SPECTRE_V2_USER_CMD_AUTO:
+               case SPECTRE_V2_USER_CMD_SECCOMP:
+                       static_branch_enable(&switch_mm_cond_ibpb);
+                       break;
+               default:
+                       break;
+               }
+
+               pr_info("mitigation: Enabling %s Indirect Branch Prediction Barrier\n",
+                       static_key_enabled(&switch_mm_always_ibpb) ?
+                       "always-on" : "conditional");
+       }
+
+       /* If enhanced IBRS is enabled no STIPB required */
+       if (spectre_v2_enabled == SPECTRE_V2_IBRS_ENHANCED)
+               return;
+
+       /*
+        * If SMT is not possible or STIBP is not available clear the STIPB
+        * mode.
+        */
+       if (!smt_possible || !boot_cpu_has(X86_FEATURE_STIBP))
+               mode = SPECTRE_V2_USER_NONE;
+set_mode:
+       spectre_v2_user = mode;
+       /* Only print the STIBP mode when SMT possible */
+       if (smt_possible)
+               pr_info("%s\n", spectre_v2_user_strings[mode]);
 }
 
+static const char * const spectre_v2_strings[] = {
+       [SPECTRE_V2_NONE]                       = "Vulnerable",
+       [SPECTRE_V2_RETPOLINE_GENERIC]          = "Mitigation: Full generic retpoline",
+       [SPECTRE_V2_RETPOLINE_AMD]              = "Mitigation: Full AMD retpoline",
+       [SPECTRE_V2_IBRS_ENHANCED]              = "Mitigation: Enhanced IBRS",
+};
+
 static const struct {
        const char *option;
        enum spectre_v2_mitigation_cmd cmd;
        bool secure;
-} mitigation_options[] = {
-       { "off",               SPECTRE_V2_CMD_NONE,              false },
-       { "on",                SPECTRE_V2_CMD_FORCE,             true },
-       { "retpoline",         SPECTRE_V2_CMD_RETPOLINE,         false },
-       { "retpoline,amd",     SPECTRE_V2_CMD_RETPOLINE_AMD,     false },
-       { "retpoline,generic", SPECTRE_V2_CMD_RETPOLINE_GENERIC, false },
-       { "auto",              SPECTRE_V2_CMD_AUTO,              false },
+} mitigation_options[] __initdata = {
+       { "off",                SPECTRE_V2_CMD_NONE,              false },
+       { "on",                 SPECTRE_V2_CMD_FORCE,             true  },
+       { "retpoline",          SPECTRE_V2_CMD_RETPOLINE,         false },
+       { "retpoline,amd",      SPECTRE_V2_CMD_RETPOLINE_AMD,     false },
+       { "retpoline,generic",  SPECTRE_V2_CMD_RETPOLINE_GENERIC, false },
+       { "auto",               SPECTRE_V2_CMD_AUTO,              false },
 };
 
+static void __init spec_v2_print_cond(const char *reason, bool secure)
+{
+       if (boot_cpu_has_bug(X86_BUG_SPECTRE_V2) != secure)
+               pr_info("%s selected on command line.\n", reason);
+}
+
 static enum spectre_v2_mitigation_cmd __init spectre_v2_parse_cmdline(void)
 {
+       enum spectre_v2_mitigation_cmd cmd = SPECTRE_V2_CMD_AUTO;
        char arg[20];
        int ret, i;
-       enum spectre_v2_mitigation_cmd cmd = SPECTRE_V2_CMD_AUTO;
 
        if (cmdline_find_option_bool(boot_command_line, "nospectre_v2"))
                return SPECTRE_V2_CMD_NONE;
-       else {
-               ret = cmdline_find_option(boot_command_line, "spectre_v2", arg, sizeof(arg));
-               if (ret < 0)
-                       return SPECTRE_V2_CMD_AUTO;
 
-               for (i = 0; i < ARRAY_SIZE(mitigation_options); i++) {
-                       if (!match_option(arg, ret, mitigation_options[i].option))
-                               continue;
-                       cmd = mitigation_options[i].cmd;
-                       break;
-               }
+       ret = cmdline_find_option(boot_command_line, "spectre_v2", arg, sizeof(arg));
+       if (ret < 0)
+               return SPECTRE_V2_CMD_AUTO;
 
-               if (i >= ARRAY_SIZE(mitigation_options)) {
-                       pr_err("unknown option (%s). Switching to AUTO select\n", arg);
-                       return SPECTRE_V2_CMD_AUTO;
-               }
+       for (i = 0; i < ARRAY_SIZE(mitigation_options); i++) {
+               if (!match_option(arg, ret, mitigation_options[i].option))
+                       continue;
+               cmd = mitigation_options[i].cmd;
+               break;
+       }
+
+       if (i >= ARRAY_SIZE(mitigation_options)) {
+               pr_err("unknown option (%s). Switching to AUTO select\n", arg);
+               return SPECTRE_V2_CMD_AUTO;
        }
 
        if ((cmd == SPECTRE_V2_CMD_RETPOLINE ||
@@ -316,54 +462,11 @@ static enum spectre_v2_mitigation_cmd __init spectre_v2_parse_cmdline(void)
                return SPECTRE_V2_CMD_AUTO;
        }
 
-       if (mitigation_options[i].secure)
-               spec2_print_if_secure(mitigation_options[i].option);
-       else
-               spec2_print_if_insecure(mitigation_options[i].option);
-
+       spec_v2_print_cond(mitigation_options[i].option,
+                          mitigation_options[i].secure);
        return cmd;
 }
 
-static bool stibp_needed(void)
-{
-       if (spectre_v2_enabled == SPECTRE_V2_NONE)
-               return false;
-
-       if (!boot_cpu_has(X86_FEATURE_STIBP))
-               return false;
-
-       return true;
-}
-
-static void update_stibp_msr(void *info)
-{
-       wrmsrl(MSR_IA32_SPEC_CTRL, x86_spec_ctrl_base);
-}
-
-void arch_smt_update(void)
-{
-       u64 mask;
-
-       if (!stibp_needed())
-               return;
-
-       mutex_lock(&spec_ctrl_mutex);
-       mask = x86_spec_ctrl_base;
-       if (cpu_smt_control == CPU_SMT_ENABLED)
-               mask |= SPEC_CTRL_STIBP;
-       else
-               mask &= ~SPEC_CTRL_STIBP;
-
-       if (mask != x86_spec_ctrl_base) {
-               pr_info("Spectre v2 cross-process SMT mitigation: %s STIBP\n",
-                               cpu_smt_control == CPU_SMT_ENABLED ?
-                               "Enabling" : "Disabling");
-               x86_spec_ctrl_base = mask;
-               on_each_cpu(update_stibp_msr, NULL, 1);
-       }
-       mutex_unlock(&spec_ctrl_mutex);
-}
-
 static void __init spectre_v2_select_mitigation(void)
 {
        enum spectre_v2_mitigation_cmd cmd = spectre_v2_parse_cmdline();
@@ -417,14 +520,12 @@ retpoline_auto:
                        pr_err("Spectre mitigation: LFENCE not serializing, switching to generic retpoline\n");
                        goto retpoline_generic;
                }
-               mode = retp_compiler() ? SPECTRE_V2_RETPOLINE_AMD :
-                                        SPECTRE_V2_RETPOLINE_MINIMAL_AMD;
+               mode = SPECTRE_V2_RETPOLINE_AMD;
                setup_force_cpu_cap(X86_FEATURE_RETPOLINE_AMD);
                setup_force_cpu_cap(X86_FEATURE_RETPOLINE);
        } else {
        retpoline_generic:
-               mode = retp_compiler() ? SPECTRE_V2_RETPOLINE_GENERIC :
-                                        SPECTRE_V2_RETPOLINE_MINIMAL;
+               mode = SPECTRE_V2_RETPOLINE_GENERIC;
                setup_force_cpu_cap(X86_FEATURE_RETPOLINE);
        }
 
@@ -443,12 +544,6 @@ specv2_set_mode:
        setup_force_cpu_cap(X86_FEATURE_RSB_CTXSW);
        pr_info("Spectre v2 / SpectreRSB mitigation: Filling RSB on context switch\n");
 
-       /* Initialize Indirect Branch Prediction Barrier if supported */
-       if (boot_cpu_has(X86_FEATURE_IBPB)) {
-               setup_force_cpu_cap(X86_FEATURE_USE_IBPB);
-               pr_info("Spectre v2 mitigation: Enabling Indirect Branch Prediction Barrier\n");
-       }
-
        /*
         * Retpoline means the kernel is safe because it has no indirect
         * branches. Enhanced IBRS protects firmware too, so, enable restricted
@@ -465,10 +560,67 @@ specv2_set_mode:
                pr_info("Enabling Restricted Speculation for firmware calls\n");
        }
 
+       /* Set up IBPB and STIBP depending on the general spectre V2 command */
+       spectre_v2_user_select_mitigation(cmd);
+
        /* Enable STIBP if appropriate */
        arch_smt_update();
 }
 
+static void update_stibp_msr(void * __unused)
+{
+       wrmsrl(MSR_IA32_SPEC_CTRL, x86_spec_ctrl_base);
+}
+
+/* Update x86_spec_ctrl_base in case SMT state changed. */
+static void update_stibp_strict(void)
+{
+       u64 mask = x86_spec_ctrl_base & ~SPEC_CTRL_STIBP;
+
+       if (sched_smt_active())
+               mask |= SPEC_CTRL_STIBP;
+
+       if (mask == x86_spec_ctrl_base)
+               return;
+
+       pr_info("Update user space SMT mitigation: STIBP %s\n",
+               mask & SPEC_CTRL_STIBP ? "always-on" : "off");
+       x86_spec_ctrl_base = mask;
+       on_each_cpu(update_stibp_msr, NULL, 1);
+}
+
+/* Update the static key controlling the evaluation of TIF_SPEC_IB */
+static void update_indir_branch_cond(void)
+{
+       if (sched_smt_active())
+               static_branch_enable(&switch_to_cond_stibp);
+       else
+               static_branch_disable(&switch_to_cond_stibp);
+}
+
+void arch_smt_update(void)
+{
+       /* Enhanced IBRS implies STIBP. No update required. */
+       if (spectre_v2_enabled == SPECTRE_V2_IBRS_ENHANCED)
+               return;
+
+       mutex_lock(&spec_ctrl_mutex);
+
+       switch (spectre_v2_user) {
+       case SPECTRE_V2_USER_NONE:
+               break;
+       case SPECTRE_V2_USER_STRICT:
+               update_stibp_strict();
+               break;
+       case SPECTRE_V2_USER_PRCTL:
+       case SPECTRE_V2_USER_SECCOMP:
+               update_indir_branch_cond();
+               break;
+       }
+
+       mutex_unlock(&spec_ctrl_mutex);
+}
+
 #undef pr_fmt
 #define pr_fmt(fmt)    "Speculative Store Bypass: " fmt
 
@@ -483,7 +635,7 @@ enum ssb_mitigation_cmd {
        SPEC_STORE_BYPASS_CMD_SECCOMP,
 };
 
-static const char *ssb_strings[] = {
+static const char * const ssb_strings[] = {
        [SPEC_STORE_BYPASS_NONE]        = "Vulnerable",
        [SPEC_STORE_BYPASS_DISABLE]     = "Mitigation: Speculative Store Bypass disabled",
        [SPEC_STORE_BYPASS_PRCTL]       = "Mitigation: Speculative Store Bypass disabled via prctl",
@@ -493,7 +645,7 @@ static const char *ssb_strings[] = {
 static const struct {
        const char *option;
        enum ssb_mitigation_cmd cmd;
-} ssb_mitigation_options[] = {
+} ssb_mitigation_options[]  __initdata = {
        { "auto",       SPEC_STORE_BYPASS_CMD_AUTO },    /* Platform decides */
        { "on",         SPEC_STORE_BYPASS_CMD_ON },      /* Disable Speculative Store Bypass */
        { "off",        SPEC_STORE_BYPASS_CMD_NONE },    /* Don't touch Speculative Store Bypass */
@@ -604,10 +756,25 @@ static void ssb_select_mitigation(void)
 #undef pr_fmt
 #define pr_fmt(fmt)     "Speculation prctl: " fmt
 
-static int ssb_prctl_set(struct task_struct *task, unsigned long ctrl)
+static void task_update_spec_tif(struct task_struct *tsk)
 {
-       bool update;
+       /* Force the update of the real TIF bits */
+       set_tsk_thread_flag(tsk, TIF_SPEC_FORCE_UPDATE);
 
+       /*
+        * Immediately update the speculation control MSRs for the current
+        * task, but for a non-current task delay setting the CPU
+        * mitigation until it is scheduled next.
+        *
+        * This can only happen for SECCOMP mitigation. For PRCTL it's
+        * always the current task.
+        */
+       if (tsk == current)
+               speculation_ctrl_update_current();
+}
+
+static int ssb_prctl_set(struct task_struct *task, unsigned long ctrl)
+{
        if (ssb_mode != SPEC_STORE_BYPASS_PRCTL &&
            ssb_mode != SPEC_STORE_BYPASS_SECCOMP)
                return -ENXIO;
@@ -618,28 +785,56 @@ static int ssb_prctl_set(struct task_struct *task, unsigned long ctrl)
                if (task_spec_ssb_force_disable(task))
                        return -EPERM;
                task_clear_spec_ssb_disable(task);
-               update = test_and_clear_tsk_thread_flag(task, TIF_SSBD);
+               task_update_spec_tif(task);
                break;
        case PR_SPEC_DISABLE:
                task_set_spec_ssb_disable(task);
-               update = !test_and_set_tsk_thread_flag(task, TIF_SSBD);
+               task_update_spec_tif(task);
                break;
        case PR_SPEC_FORCE_DISABLE:
                task_set_spec_ssb_disable(task);
                task_set_spec_ssb_force_disable(task);
-               update = !test_and_set_tsk_thread_flag(task, TIF_SSBD);
+               task_update_spec_tif(task);
                break;
        default:
                return -ERANGE;
        }
+       return 0;
+}
 
-       /*
-        * If being set on non-current task, delay setting the CPU
-        * mitigation until it is next scheduled.
-        */
-       if (task == current && update)
-               speculative_store_bypass_update_current();
-
+static int ib_prctl_set(struct task_struct *task, unsigned long ctrl)
+{
+       switch (ctrl) {
+       case PR_SPEC_ENABLE:
+               if (spectre_v2_user == SPECTRE_V2_USER_NONE)
+                       return 0;
+               /*
+                * Indirect branch speculation is always disabled in strict
+                * mode.
+                */
+               if (spectre_v2_user == SPECTRE_V2_USER_STRICT)
+                       return -EPERM;
+               task_clear_spec_ib_disable(task);
+               task_update_spec_tif(task);
+               break;
+       case PR_SPEC_DISABLE:
+       case PR_SPEC_FORCE_DISABLE:
+               /*
+                * Indirect branch speculation is always allowed when
+                * mitigation is force disabled.
+                */
+               if (spectre_v2_user == SPECTRE_V2_USER_NONE)
+                       return -EPERM;
+               if (spectre_v2_user == SPECTRE_V2_USER_STRICT)
+                       return 0;
+               task_set_spec_ib_disable(task);
+               if (ctrl == PR_SPEC_FORCE_DISABLE)
+                       task_set_spec_ib_force_disable(task);
+               task_update_spec_tif(task);
+               break;
+       default:
+               return -ERANGE;
+       }
        return 0;
 }
 
@@ -649,6 +844,8 @@ int arch_prctl_spec_ctrl_set(struct task_struct *task, unsigned long which,
        switch (which) {
        case PR_SPEC_STORE_BYPASS:
                return ssb_prctl_set(task, ctrl);
+       case PR_SPEC_INDIRECT_BRANCH:
+               return ib_prctl_set(task, ctrl);
        default:
                return -ENODEV;
        }
@@ -659,6 +856,8 @@ void arch_seccomp_spec_mitigate(struct task_struct *task)
 {
        if (ssb_mode == SPEC_STORE_BYPASS_SECCOMP)
                ssb_prctl_set(task, PR_SPEC_FORCE_DISABLE);
+       if (spectre_v2_user == SPECTRE_V2_USER_SECCOMP)
+               ib_prctl_set(task, PR_SPEC_FORCE_DISABLE);
 }
 #endif
 
@@ -681,11 +880,35 @@ static int ssb_prctl_get(struct task_struct *task)
        }
 }
 
+static int ib_prctl_get(struct task_struct *task)
+{
+       if (!boot_cpu_has_bug(X86_BUG_SPECTRE_V2))
+               return PR_SPEC_NOT_AFFECTED;
+
+       switch (spectre_v2_user) {
+       case SPECTRE_V2_USER_NONE:
+               return PR_SPEC_ENABLE;
+       case SPECTRE_V2_USER_PRCTL:
+       case SPECTRE_V2_USER_SECCOMP:
+               if (task_spec_ib_force_disable(task))
+                       return PR_SPEC_PRCTL | PR_SPEC_FORCE_DISABLE;
+               if (task_spec_ib_disable(task))
+                       return PR_SPEC_PRCTL | PR_SPEC_DISABLE;
+               return PR_SPEC_PRCTL | PR_SPEC_ENABLE;
+       case SPECTRE_V2_USER_STRICT:
+               return PR_SPEC_DISABLE;
+       default:
+               return PR_SPEC_NOT_AFFECTED;
+       }
+}
+
 int arch_prctl_spec_ctrl_get(struct task_struct *task, unsigned long which)
 {
        switch (which) {
        case PR_SPEC_STORE_BYPASS:
                return ssb_prctl_get(task);
+       case PR_SPEC_INDIRECT_BRANCH:
+               return ib_prctl_get(task);
        default:
                return -ENODEV;
        }
@@ -823,7 +1046,7 @@ early_param("l1tf", l1tf_cmdline);
 #define L1TF_DEFAULT_MSG "Mitigation: PTE Inversion"
 
 #if IS_ENABLED(CONFIG_KVM_INTEL)
-static const char *l1tf_vmx_states[] = {
+static const char * const l1tf_vmx_states[] = {
        [VMENTER_L1D_FLUSH_AUTO]                = "auto",
        [VMENTER_L1D_FLUSH_NEVER]               = "vulnerable",
        [VMENTER_L1D_FLUSH_COND]                = "conditional cache flushes",
@@ -839,13 +1062,14 @@ static ssize_t l1tf_show_state(char *buf)
 
        if (l1tf_vmx_mitigation == VMENTER_L1D_FLUSH_EPT_DISABLED ||
            (l1tf_vmx_mitigation == VMENTER_L1D_FLUSH_NEVER &&
-            cpu_smt_control == CPU_SMT_ENABLED))
+            sched_smt_active())) {
                return sprintf(buf, "%s; VMX: %s\n", L1TF_DEFAULT_MSG,
                               l1tf_vmx_states[l1tf_vmx_mitigation]);
+       }
 
        return sprintf(buf, "%s; VMX: %s, SMT %s\n", L1TF_DEFAULT_MSG,
                       l1tf_vmx_states[l1tf_vmx_mitigation],
-                      cpu_smt_control == CPU_SMT_ENABLED ? "vulnerable" : "disabled");
+                      sched_smt_active() ? "vulnerable" : "disabled");
 }
 #else
 static ssize_t l1tf_show_state(char *buf)
@@ -854,11 +1078,39 @@ static ssize_t l1tf_show_state(char *buf)
 }
 #endif
 
+static char *stibp_state(void)
+{
+       if (spectre_v2_enabled == SPECTRE_V2_IBRS_ENHANCED)
+               return "";
+
+       switch (spectre_v2_user) {
+       case SPECTRE_V2_USER_NONE:
+               return ", STIBP: disabled";
+       case SPECTRE_V2_USER_STRICT:
+               return ", STIBP: forced";
+       case SPECTRE_V2_USER_PRCTL:
+       case SPECTRE_V2_USER_SECCOMP:
+               if (static_key_enabled(&switch_to_cond_stibp))
+                       return ", STIBP: conditional";
+       }
+       return "";
+}
+
+static char *ibpb_state(void)
+{
+       if (boot_cpu_has(X86_FEATURE_IBPB)) {
+               if (static_key_enabled(&switch_mm_always_ibpb))
+                       return ", IBPB: always-on";
+               if (static_key_enabled(&switch_mm_cond_ibpb))
+                       return ", IBPB: conditional";
+               return ", IBPB: disabled";
+       }
+       return "";
+}
+
 static ssize_t cpu_show_common(struct device *dev, struct device_attribute *attr,
                               char *buf, unsigned int bug)
 {
-       int ret;
-
        if (!boot_cpu_has_bug(bug))
                return sprintf(buf, "Not affected\n");
 
@@ -876,13 +1128,12 @@ static ssize_t cpu_show_common(struct device *dev, struct device_attribute *attr
                return sprintf(buf, "Mitigation: __user pointer sanitization\n");
 
        case X86_BUG_SPECTRE_V2:
-               ret = sprintf(buf, "%s%s%s%s%s%s\n", spectre_v2_strings[spectre_v2_enabled],
-                              boot_cpu_has(X86_FEATURE_USE_IBPB) ? ", IBPB" : "",
+               return sprintf(buf, "%s%s%s%s%s%s\n", spectre_v2_strings[spectre_v2_enabled],
+                              ibpb_state(),
                               boot_cpu_has(X86_FEATURE_USE_IBRS_FW) ? ", IBRS_FW" : "",
-                              (x86_spec_ctrl_base & SPEC_CTRL_STIBP) ? ", STIBP" : "",
+                              stibp_state(),
                               boot_cpu_has(X86_FEATURE_RSB_CTXSW) ? ", RSB filling" : "",
                               spectre_v2_module_string());
-               return ret;
 
        case X86_BUG_SPEC_STORE_BYPASS:
                return sprintf(buf, "%s\n", ssb_strings[ssb_mode]);
index dd33c35..e12454e 100644 (file)
@@ -56,7 +56,7 @@
 /* Threshold LVT offset is at MSR0xC0000410[15:12] */
 #define SMCA_THR_LVT_OFF       0xF000
 
-static bool thresholding_en;
+static bool thresholding_irq_en;
 
 static const char * const th_names[] = {
        "load_store",
@@ -534,9 +534,8 @@ prepare_threshold_block(unsigned int bank, unsigned int block, u32 addr,
 
 set_offset:
        offset = setup_APIC_mce_threshold(offset, new);
-
-       if ((offset == new) && (mce_threshold_vector != amd_threshold_interrupt))
-               mce_threshold_vector = amd_threshold_interrupt;
+       if (offset == new)
+               thresholding_irq_en = true;
 
 done:
        mce_threshold_block_init(&b, offset);
@@ -1357,9 +1356,6 @@ int mce_threshold_remove_device(unsigned int cpu)
 {
        unsigned int bank;
 
-       if (!thresholding_en)
-               return 0;
-
        for (bank = 0; bank < mca_cfg.banks; ++bank) {
                if (!(per_cpu(bank_map, cpu) & (1 << bank)))
                        continue;
@@ -1377,9 +1373,6 @@ int mce_threshold_create_device(unsigned int cpu)
        struct threshold_bank **bp;
        int err = 0;
 
-       if (!thresholding_en)
-               return 0;
-
        bp = per_cpu(threshold_banks, cpu);
        if (bp)
                return 0;
@@ -1408,9 +1401,6 @@ static __init int threshold_init_device(void)
 {
        unsigned lcpu = 0;
 
-       if (mce_threshold_vector == amd_threshold_interrupt)
-               thresholding_en = true;
-
        /* to hit CPUs online before the notifier is up */
        for_each_online_cpu(lcpu) {
                int err = mce_threshold_create_device(lcpu);
@@ -1419,6 +1409,9 @@ static __init int threshold_init_device(void)
                        return err;
        }
 
+       if (thresholding_irq_en)
+               mce_threshold_vector = amd_threshold_interrupt;
+
        return 0;
 }
 /*
index 61a949d..d99a8ee 100644 (file)
@@ -344,10 +344,10 @@ static int __fpu__restore_sig(void __user *buf, void __user *buf_fx, int size)
                        sanitize_restored_xstate(tsk, &env, xfeatures, fx_only);
                }
 
+               local_bh_disable();
                fpu->initialized = 1;
-               preempt_disable();
                fpu__restore(fpu);
-               preempt_enable();
+               local_bh_enable();
 
                return err;
        } else {
index 01ebcb6..7ee8067 100644 (file)
@@ -994,7 +994,6 @@ void prepare_ftrace_return(unsigned long self_addr, unsigned long *parent,
 {
        unsigned long old;
        int faulted;
-       struct ftrace_graph_ent trace;
        unsigned long return_hooker = (unsigned long)
                                &return_to_handler;
 
@@ -1046,19 +1045,7 @@ void prepare_ftrace_return(unsigned long self_addr, unsigned long *parent,
                return;
        }
 
-       trace.func = self_addr;
-       trace.depth = current->curr_ret_stack + 1;
-
-       /* Only trace if the calling function expects to */
-       if (!ftrace_graph_entry(&trace)) {
+       if (function_graph_enter(old, self_addr, frame_pointer, parent))
                *parent = old;
-               return;
-       }
-
-       if (ftrace_push_return_trace(old, self_addr, &trace.depth,
-                                    frame_pointer, parent) == -EBUSY) {
-               *parent = old;
-               return;
-       }
 }
 #endif /* CONFIG_FUNCTION_GRAPH_TRACER */
index 76fa3b8..ec6fefb 100644 (file)
@@ -37,7 +37,6 @@ asmlinkage __visible void __init i386_start_kernel(void)
        cr4_init_shadow();
 
        sanitize_boot_params(&boot_params);
-       x86_verify_bootdata_version();
 
        x86_early_init_platform_quirks();
 
index 7663a8e..16b1cbd 100644 (file)
@@ -457,8 +457,6 @@ void __init x86_64_start_reservations(char *real_mode_data)
        if (!boot_params.hdr.version)
                copy_bootdata(__va(real_mode_data));
 
-       x86_verify_bootdata_version();
-
        x86_early_init_platform_quirks();
 
        switch (boot_params.hdr.hardware_subarch) {
index c93fcfd..7d31192 100644 (file)
@@ -40,6 +40,8 @@
 #include <asm/prctl.h>
 #include <asm/spec-ctrl.h>
 
+#include "process.h"
+
 /*
  * per-CPU TSS segments. Threads are completely 'soft' on Linux,
  * no more per-task TSS's. The TSS size is kept cacheline-aligned
@@ -252,11 +254,12 @@ void arch_setup_new_exec(void)
                enable_cpuid();
 }
 
-static inline void switch_to_bitmap(struct tss_struct *tss,
-                                   struct thread_struct *prev,
+static inline void switch_to_bitmap(struct thread_struct *prev,
                                    struct thread_struct *next,
                                    unsigned long tifp, unsigned long tifn)
 {
+       struct tss_struct *tss = this_cpu_ptr(&cpu_tss_rw);
+
        if (tifn & _TIF_IO_BITMAP) {
                /*
                 * Copy the relevant range of the IO bitmap.
@@ -395,32 +398,85 @@ static __always_inline void amd_set_ssb_virt_state(unsigned long tifn)
        wrmsrl(MSR_AMD64_VIRT_SPEC_CTRL, ssbd_tif_to_spec_ctrl(tifn));
 }
 
-static __always_inline void intel_set_ssb_state(unsigned long tifn)
+/*
+ * Update the MSRs managing speculation control, during context switch.
+ *
+ * tifp: Previous task's thread flags
+ * tifn: Next task's thread flags
+ */
+static __always_inline void __speculation_ctrl_update(unsigned long tifp,
+                                                     unsigned long tifn)
 {
-       u64 msr = x86_spec_ctrl_base | ssbd_tif_to_spec_ctrl(tifn);
+       unsigned long tif_diff = tifp ^ tifn;
+       u64 msr = x86_spec_ctrl_base;
+       bool updmsr = false;
+
+       /*
+        * If TIF_SSBD is different, select the proper mitigation
+        * method. Note that if SSBD mitigation is disabled or permanentely
+        * enabled this branch can't be taken because nothing can set
+        * TIF_SSBD.
+        */
+       if (tif_diff & _TIF_SSBD) {
+               if (static_cpu_has(X86_FEATURE_VIRT_SSBD)) {
+                       amd_set_ssb_virt_state(tifn);
+               } else if (static_cpu_has(X86_FEATURE_LS_CFG_SSBD)) {
+                       amd_set_core_ssb_state(tifn);
+               } else if (static_cpu_has(X86_FEATURE_SPEC_CTRL_SSBD) ||
+                          static_cpu_has(X86_FEATURE_AMD_SSBD)) {
+                       msr |= ssbd_tif_to_spec_ctrl(tifn);
+                       updmsr  = true;
+               }
+       }
+
+       /*
+        * Only evaluate TIF_SPEC_IB if conditional STIBP is enabled,
+        * otherwise avoid the MSR write.
+        */
+       if (IS_ENABLED(CONFIG_SMP) &&
+           static_branch_unlikely(&switch_to_cond_stibp)) {
+               updmsr |= !!(tif_diff & _TIF_SPEC_IB);
+               msr |= stibp_tif_to_spec_ctrl(tifn);
+       }
 
-       wrmsrl(MSR_IA32_SPEC_CTRL, msr);
+       if (updmsr)
+               wrmsrl(MSR_IA32_SPEC_CTRL, msr);
 }
 
-static __always_inline void __speculative_store_bypass_update(unsigned long tifn)
+static unsigned long speculation_ctrl_update_tif(struct task_struct *tsk)
 {
-       if (static_cpu_has(X86_FEATURE_VIRT_SSBD))
-               amd_set_ssb_virt_state(tifn);
-       else if (static_cpu_has(X86_FEATURE_LS_CFG_SSBD))
-               amd_set_core_ssb_state(tifn);
-       else
-               intel_set_ssb_state(tifn);
+       if (test_and_clear_tsk_thread_flag(tsk, TIF_SPEC_FORCE_UPDATE)) {
+               if (task_spec_ssb_disable(tsk))
+                       set_tsk_thread_flag(tsk, TIF_SSBD);
+               else
+                       clear_tsk_thread_flag(tsk, TIF_SSBD);
+
+               if (task_spec_ib_disable(tsk))
+                       set_tsk_thread_flag(tsk, TIF_SPEC_IB);
+               else
+                       clear_tsk_thread_flag(tsk, TIF_SPEC_IB);
+       }
+       /* Return the updated threadinfo flags*/
+       return task_thread_info(tsk)->flags;
 }
 
-void speculative_store_bypass_update(unsigned long tif)
+void speculation_ctrl_update(unsigned long tif)
 {
+       /* Forced update. Make sure all relevant TIF flags are different */
        preempt_disable();
-       __speculative_store_bypass_update(tif);
+       __speculation_ctrl_update(~tif, tif);
        preempt_enable();
 }
 
-void __switch_to_xtra(struct task_struct *prev_p, struct task_struct *next_p,
-                     struct tss_struct *tss)
+/* Called from seccomp/prctl update */
+void speculation_ctrl_update_current(void)
+{
+       preempt_disable();
+       speculation_ctrl_update(speculation_ctrl_update_tif(current));
+       preempt_enable();
+}
+
+void __switch_to_xtra(struct task_struct *prev_p, struct task_struct *next_p)
 {
        struct thread_struct *prev, *next;
        unsigned long tifp, tifn;
@@ -430,7 +486,7 @@ void __switch_to_xtra(struct task_struct *prev_p, struct task_struct *next_p,
 
        tifn = READ_ONCE(task_thread_info(next_p)->flags);
        tifp = READ_ONCE(task_thread_info(prev_p)->flags);
-       switch_to_bitmap(tss, prev, next, tifp, tifn);
+       switch_to_bitmap(prev, next, tifp, tifn);
 
        propagate_user_return_notify(prev_p, next_p);
 
@@ -451,8 +507,15 @@ void __switch_to_xtra(struct task_struct *prev_p, struct task_struct *next_p,
        if ((tifp ^ tifn) & _TIF_NOCPUID)
                set_cpuid_faulting(!!(tifn & _TIF_NOCPUID));
 
-       if ((tifp ^ tifn) & _TIF_SSBD)
-               __speculative_store_bypass_update(tifn);
+       if (likely(!((tifp | tifn) & _TIF_SPEC_FORCE_UPDATE))) {
+               __speculation_ctrl_update(tifp, tifn);
+       } else {
+               speculation_ctrl_update_tif(prev_p);
+               tifn = speculation_ctrl_update_tif(next_p);
+
+               /* Enforce MSR update to ensure consistent state */
+               __speculation_ctrl_update(~tifn, tifn);
+       }
 }
 
 /*
diff --git a/arch/x86/kernel/process.h b/arch/x86/kernel/process.h
new file mode 100644 (file)
index 0000000..898e97c
--- /dev/null
@@ -0,0 +1,39 @@
+// SPDX-License-Identifier: GPL-2.0
+//
+// Code shared between 32 and 64 bit
+
+#include <asm/spec-ctrl.h>
+
+void __switch_to_xtra(struct task_struct *prev_p, struct task_struct *next_p);
+
+/*
+ * This needs to be inline to optimize for the common case where no extra
+ * work needs to be done.
+ */
+static inline void switch_to_extra(struct task_struct *prev,
+                                  struct task_struct *next)
+{
+       unsigned long next_tif = task_thread_info(next)->flags;
+       unsigned long prev_tif = task_thread_info(prev)->flags;
+
+       if (IS_ENABLED(CONFIG_SMP)) {
+               /*
+                * Avoid __switch_to_xtra() invocation when conditional
+                * STIPB is disabled and the only different bit is
+                * TIF_SPEC_IB. For CONFIG_SMP=n TIF_SPEC_IB is not
+                * in the TIF_WORK_CTXSW masks.
+                */
+               if (!static_branch_likely(&switch_to_cond_stibp)) {
+                       prev_tif &= ~_TIF_SPEC_IB;
+                       next_tif &= ~_TIF_SPEC_IB;
+               }
+       }
+
+       /*
+        * __switch_to_xtra() handles debug registers, i/o bitmaps,
+        * speculation mitigations etc.
+        */
+       if (unlikely(next_tif & _TIF_WORK_CTXSW_NEXT ||
+                    prev_tif & _TIF_WORK_CTXSW_PREV))
+               __switch_to_xtra(prev, next);
+}
index 5046a3c..d3e593e 100644 (file)
@@ -59,6 +59,8 @@
 #include <asm/intel_rdt_sched.h>
 #include <asm/proto.h>
 
+#include "process.h"
+
 void __show_regs(struct pt_regs *regs, enum show_regs_mode mode)
 {
        unsigned long cr0 = 0L, cr2 = 0L, cr3 = 0L, cr4 = 0L;
@@ -232,7 +234,6 @@ __switch_to(struct task_struct *prev_p, struct task_struct *next_p)
        struct fpu *prev_fpu = &prev->fpu;
        struct fpu *next_fpu = &next->fpu;
        int cpu = smp_processor_id();
-       struct tss_struct *tss = &per_cpu(cpu_tss_rw, cpu);
 
        /* never put a printk in __switch_to... printk() calls wake_up*() indirectly */
 
@@ -264,12 +265,7 @@ __switch_to(struct task_struct *prev_p, struct task_struct *next_p)
        if (get_kernel_rpl() && unlikely(prev->iopl != next->iopl))
                set_iopl_mask(next->iopl);
 
-       /*
-        * Now maybe handle debug registers and/or IO bitmaps
-        */
-       if (unlikely(task_thread_info(prev_p)->flags & _TIF_WORK_CTXSW_PREV ||
-                    task_thread_info(next_p)->flags & _TIF_WORK_CTXSW_NEXT))
-               __switch_to_xtra(prev_p, next_p, tss);
+       switch_to_extra(prev_p, next_p);
 
        /*
         * Leave lazy mode, flushing any hypercalls made here.
index 0e0b428..bbfbf01 100644 (file)
@@ -60,6 +60,8 @@
 #include <asm/unistd_32_ia32.h>
 #endif
 
+#include "process.h"
+
 /* Prints also some state that isn't saved in the pt_regs */
 void __show_regs(struct pt_regs *regs, enum show_regs_mode mode)
 {
@@ -553,7 +555,6 @@ __switch_to(struct task_struct *prev_p, struct task_struct *next_p)
        struct fpu *prev_fpu = &prev->fpu;
        struct fpu *next_fpu = &next->fpu;
        int cpu = smp_processor_id();
-       struct tss_struct *tss = &per_cpu(cpu_tss_rw, cpu);
 
        WARN_ON_ONCE(IS_ENABLED(CONFIG_DEBUG_ENTRY) &&
                     this_cpu_read(irq_count) != -1);
@@ -617,12 +618,7 @@ __switch_to(struct task_struct *prev_p, struct task_struct *next_p)
        /* Reload sp0. */
        update_task_stack(next_p);
 
-       /*
-        * Now maybe reload the debug registers and handle I/O bitmaps
-        */
-       if (unlikely(task_thread_info(next_p)->flags & _TIF_WORK_CTXSW_NEXT ||
-                    task_thread_info(prev_p)->flags & _TIF_WORK_CTXSW_PREV))
-               __switch_to_xtra(prev_p, next_p, tss);
+       switch_to_extra(prev_p, next_p);
 
 #ifdef CONFIG_XEN_PV
        /*
index b74e7bf..d494b9b 100644 (file)
@@ -1280,23 +1280,6 @@ void __init setup_arch(char **cmdline_p)
        unwind_init();
 }
 
-/*
- * From boot protocol 2.14 onwards we expect the bootloader to set the
- * version to "0x8000 | <used version>". In case we find a version >= 2.14
- * without the 0x8000 we assume the boot loader supports 2.13 only and
- * reset the version accordingly. The 0x8000 flag is removed in any case.
- */
-void __init x86_verify_bootdata_version(void)
-{
-       if (boot_params.hdr.version & VERSION_WRITTEN)
-               boot_params.hdr.version &= ~VERSION_WRITTEN;
-       else if (boot_params.hdr.version >= 0x020e)
-               boot_params.hdr.version = 0x020d;
-
-       if (boot_params.hdr.version < 0x020e)
-               boot_params.hdr.acpi_rsdp_addr = 0;
-}
-
 #ifdef CONFIG_X86_32
 
 static struct resource video_ram_resource = {
index 89db20f..c4533d0 100644 (file)
@@ -55,7 +55,7 @@
 #define PRIo64 "o"
 
 /* #define apic_debug(fmt,arg...) printk(KERN_WARNING fmt,##arg) */
-#define apic_debug(fmt, arg...)
+#define apic_debug(fmt, arg...) do {} while (0)
 
 /* 14 is the version for Xeon and Pentium 8.4.8*/
 #define APIC_VERSION                   (0x14UL | ((KVM_APIC_LVT_NUM - 1) << 16))
@@ -576,6 +576,11 @@ int kvm_pv_send_ipi(struct kvm *kvm, unsigned long ipi_bitmap_low,
        rcu_read_lock();
        map = rcu_dereference(kvm->arch.apic_map);
 
+       if (unlikely(!map)) {
+               count = -EOPNOTSUPP;
+               goto out;
+       }
+
        if (min > map->max_apic_id)
                goto out;
        /* Bits above cluster_size are masked in the caller.  */
index cf5f572..7c03c0f 100644 (file)
@@ -5074,9 +5074,9 @@ static bool need_remote_flush(u64 old, u64 new)
 }
 
 static u64 mmu_pte_write_fetch_gpte(struct kvm_vcpu *vcpu, gpa_t *gpa,
-                                   const u8 *new, int *bytes)
+                                   int *bytes)
 {
-       u64 gentry;
+       u64 gentry = 0;
        int r;
 
        /*
@@ -5088,22 +5088,12 @@ static u64 mmu_pte_write_fetch_gpte(struct kvm_vcpu *vcpu, gpa_t *gpa,
                /* Handle a 32-bit guest writing two halves of a 64-bit gpte */
                *gpa &= ~(gpa_t)7;
                *bytes = 8;
-               r = kvm_vcpu_read_guest(vcpu, *gpa, &gentry, 8);
-               if (r)
-                       gentry = 0;
-               new = (const u8 *)&gentry;
        }
 
-       switch (*bytes) {
-       case 4:
-               gentry = *(const u32 *)new;
-               break;
-       case 8:
-               gentry = *(const u64 *)new;
-               break;
-       default:
-               gentry = 0;
-               break;
+       if (*bytes == 4 || *bytes == 8) {
+               r = kvm_vcpu_read_guest_atomic(vcpu, *gpa, &gentry, *bytes);
+               if (r)
+                       gentry = 0;
        }
 
        return gentry;
@@ -5207,8 +5197,6 @@ static void kvm_mmu_pte_write(struct kvm_vcpu *vcpu, gpa_t gpa,
 
        pgprintk("%s: gpa %llx bytes %d\n", __func__, gpa, bytes);
 
-       gentry = mmu_pte_write_fetch_gpte(vcpu, &gpa, new, &bytes);
-
        /*
         * No need to care whether allocation memory is successful
         * or not since pte prefetch is skiped if it does not have
@@ -5217,6 +5205,9 @@ static void kvm_mmu_pte_write(struct kvm_vcpu *vcpu, gpa_t gpa,
        mmu_topup_memory_caches(vcpu);
 
        spin_lock(&vcpu->kvm->mmu_lock);
+
+       gentry = mmu_pte_write_fetch_gpte(vcpu, &gpa, &bytes);
+
        ++vcpu->kvm->stat.mmu_pte_write;
        kvm_mmu_audit(vcpu, AUDIT_PRE_PTE_WRITE);
 
index 0e21ccc..cc6467b 100644 (file)
@@ -1446,7 +1446,7 @@ static u64 svm_read_l1_tsc_offset(struct kvm_vcpu *vcpu)
        return vcpu->arch.tsc_offset;
 }
 
-static void svm_write_tsc_offset(struct kvm_vcpu *vcpu, u64 offset)
+static u64 svm_write_l1_tsc_offset(struct kvm_vcpu *vcpu, u64 offset)
 {
        struct vcpu_svm *svm = to_svm(vcpu);
        u64 g_tsc_offset = 0;
@@ -1464,6 +1464,7 @@ static void svm_write_tsc_offset(struct kvm_vcpu *vcpu, u64 offset)
        svm->vmcb->control.tsc_offset = offset + g_tsc_offset;
 
        mark_dirty(svm->vmcb, VMCB_INTERCEPTS);
+       return svm->vmcb->control.tsc_offset;
 }
 
 static void avic_init_vmcb(struct vcpu_svm *svm)
@@ -1664,20 +1665,23 @@ static u64 *avic_get_physical_id_entry(struct kvm_vcpu *vcpu,
 static int avic_init_access_page(struct kvm_vcpu *vcpu)
 {
        struct kvm *kvm = vcpu->kvm;
-       int ret;
+       int ret = 0;
 
+       mutex_lock(&kvm->slots_lock);
        if (kvm->arch.apic_access_page_done)
-               return 0;
+               goto out;
 
-       ret = x86_set_memory_region(kvm,
-                                   APIC_ACCESS_PAGE_PRIVATE_MEMSLOT,
-                                   APIC_DEFAULT_PHYS_BASE,
-                                   PAGE_SIZE);
+       ret = __x86_set_memory_region(kvm,
+                                     APIC_ACCESS_PAGE_PRIVATE_MEMSLOT,
+                                     APIC_DEFAULT_PHYS_BASE,
+                                     PAGE_SIZE);
        if (ret)
-               return ret;
+               goto out;
 
        kvm->arch.apic_access_page_done = true;
-       return 0;
+out:
+       mutex_unlock(&kvm->slots_lock);
+       return ret;
 }
 
 static int avic_init_backing_page(struct kvm_vcpu *vcpu)
@@ -2189,21 +2193,31 @@ out:
        return ERR_PTR(err);
 }
 
+static void svm_clear_current_vmcb(struct vmcb *vmcb)
+{
+       int i;
+
+       for_each_online_cpu(i)
+               cmpxchg(&per_cpu(svm_data, i)->current_vmcb, vmcb, NULL);
+}
+
 static void svm_free_vcpu(struct kvm_vcpu *vcpu)
 {
        struct vcpu_svm *svm = to_svm(vcpu);
 
+       /*
+        * The vmcb page can be recycled, causing a false negative in
+        * svm_vcpu_load(). So, ensure that no logical CPU has this
+        * vmcb page recorded as its current vmcb.
+        */
+       svm_clear_current_vmcb(svm->vmcb);
+
        __free_page(pfn_to_page(__sme_clr(svm->vmcb_pa) >> PAGE_SHIFT));
        __free_pages(virt_to_page(svm->msrpm), MSRPM_ALLOC_ORDER);
        __free_page(virt_to_page(svm->nested.hsave));
        __free_pages(virt_to_page(svm->nested.msrpm), MSRPM_ALLOC_ORDER);
        kvm_vcpu_uninit(vcpu);
        kmem_cache_free(kvm_vcpu_cache, svm);
-       /*
-        * The vmcb page can be recycled, causing a false negative in
-        * svm_vcpu_load(). So do a full IBPB now.
-        */
-       indirect_branch_prediction_barrier();
 }
 
 static void svm_vcpu_load(struct kvm_vcpu *vcpu, int cpu)
@@ -7149,7 +7163,7 @@ static struct kvm_x86_ops svm_x86_ops __ro_after_init = {
        .has_wbinvd_exit = svm_has_wbinvd_exit,
 
        .read_l1_tsc_offset = svm_read_l1_tsc_offset,
-       .write_tsc_offset = svm_write_tsc_offset,
+       .write_l1_tsc_offset = svm_write_l1_tsc_offset,
 
        .set_tdp_cr3 = set_tdp_cr3,
 
index 4555077..02edd99 100644 (file)
@@ -174,6 +174,7 @@ module_param_named(preemption_timer, enable_preemption_timer, bool, S_IRUGO);
  * refer SDM volume 3b section 21.6.13 & 22.1.3.
  */
 static unsigned int ple_gap = KVM_DEFAULT_PLE_GAP;
+module_param(ple_gap, uint, 0444);
 
 static unsigned int ple_window = KVM_VMX_DEFAULT_PLE_WINDOW;
 module_param(ple_window, uint, 0444);
@@ -984,6 +985,7 @@ struct vcpu_vmx {
        struct shared_msr_entry *guest_msrs;
        int                   nmsrs;
        int                   save_nmsrs;
+       bool                  guest_msrs_dirty;
        unsigned long         host_idt_base;
 #ifdef CONFIG_X86_64
        u64                   msr_host_kernel_gs_base;
@@ -1306,7 +1308,7 @@ static void vmx_set_nmi_mask(struct kvm_vcpu *vcpu, bool masked);
 static bool nested_vmx_is_page_fault_vmexit(struct vmcs12 *vmcs12,
                                            u16 error_code);
 static void vmx_update_msr_bitmap(struct kvm_vcpu *vcpu);
-static void __always_inline vmx_disable_intercept_for_msr(unsigned long *msr_bitmap,
+static __always_inline void vmx_disable_intercept_for_msr(unsigned long *msr_bitmap,
                                                          u32 msr, int type);
 
 static DEFINE_PER_CPU(struct vmcs *, vmxarea);
@@ -1610,12 +1612,6 @@ static int nested_enable_evmcs(struct kvm_vcpu *vcpu,
 {
        struct vcpu_vmx *vmx = to_vmx(vcpu);
 
-       /* We don't support disabling the feature for simplicity. */
-       if (vmx->nested.enlightened_vmcs_enabled)
-               return 0;
-
-       vmx->nested.enlightened_vmcs_enabled = true;
-
        /*
         * vmcs_version represents the range of supported Enlightened VMCS
         * versions: lower 8 bits is the minimal version, higher 8 bits is the
@@ -1625,6 +1621,12 @@ static int nested_enable_evmcs(struct kvm_vcpu *vcpu,
        if (vmcs_version)
                *vmcs_version = (KVM_EVMCS_VERSION << 8) | 1;
 
+       /* We don't support disabling the feature for simplicity. */
+       if (vmx->nested.enlightened_vmcs_enabled)
+               return 0;
+
+       vmx->nested.enlightened_vmcs_enabled = true;
+
        vmx->nested.msrs.pinbased_ctls_high &= ~EVMCS1_UNSUPPORTED_PINCTRL;
        vmx->nested.msrs.entry_ctls_high &= ~EVMCS1_UNSUPPORTED_VMENTRY_CTRL;
        vmx->nested.msrs.exit_ctls_high &= ~EVMCS1_UNSUPPORTED_VMEXIT_CTRL;
@@ -2897,6 +2899,20 @@ static void vmx_prepare_switch_to_guest(struct kvm_vcpu *vcpu)
 
        vmx->req_immediate_exit = false;
 
+       /*
+        * Note that guest MSRs to be saved/restored can also be changed
+        * when guest state is loaded. This happens when guest transitions
+        * to/from long-mode by setting MSR_EFER.LMA.
+        */
+       if (!vmx->loaded_cpu_state || vmx->guest_msrs_dirty) {
+               vmx->guest_msrs_dirty = false;
+               for (i = 0; i < vmx->save_nmsrs; ++i)
+                       kvm_set_shared_msr(vmx->guest_msrs[i].index,
+                                          vmx->guest_msrs[i].data,
+                                          vmx->guest_msrs[i].mask);
+
+       }
+
        if (vmx->loaded_cpu_state)
                return;
 
@@ -2957,11 +2973,6 @@ static void vmx_prepare_switch_to_guest(struct kvm_vcpu *vcpu)
                vmcs_writel(HOST_GS_BASE, gs_base);
                host_state->gs_base = gs_base;
        }
-
-       for (i = 0; i < vmx->save_nmsrs; ++i)
-               kvm_set_shared_msr(vmx->guest_msrs[i].index,
-                                  vmx->guest_msrs[i].data,
-                                  vmx->guest_msrs[i].mask);
 }
 
 static void vmx_prepare_switch_to_host(struct vcpu_vmx *vmx)
@@ -3436,6 +3447,7 @@ static void setup_msrs(struct vcpu_vmx *vmx)
                move_msr_up(vmx, index, save_nmsrs++);
 
        vmx->save_nmsrs = save_nmsrs;
+       vmx->guest_msrs_dirty = true;
 
        if (cpu_has_vmx_msr_bitmap())
                vmx_update_msr_bitmap(&vmx->vcpu);
@@ -3452,11 +3464,9 @@ static u64 vmx_read_l1_tsc_offset(struct kvm_vcpu *vcpu)
        return vcpu->arch.tsc_offset;
 }
 
-/*
- * writes 'offset' into guest's timestamp counter offset register
- */
-static void vmx_write_tsc_offset(struct kvm_vcpu *vcpu, u64 offset)
+static u64 vmx_write_l1_tsc_offset(struct kvm_vcpu *vcpu, u64 offset)
 {
+       u64 active_offset = offset;
        if (is_guest_mode(vcpu)) {
                /*
                 * We're here if L1 chose not to trap WRMSR to TSC. According
@@ -3464,17 +3474,16 @@ static void vmx_write_tsc_offset(struct kvm_vcpu *vcpu, u64 offset)
                 * set for L2 remains unchanged, and still needs to be added
                 * to the newly set TSC to get L2's TSC.
                 */
-               struct vmcs12 *vmcs12;
-               /* recalculate vmcs02.TSC_OFFSET: */
-               vmcs12 = get_vmcs12(vcpu);
-               vmcs_write64(TSC_OFFSET, offset +
-                       (nested_cpu_has(vmcs12, CPU_BASED_USE_TSC_OFFSETING) ?
-                        vmcs12->tsc_offset : 0));
+               struct vmcs12 *vmcs12 = get_vmcs12(vcpu);
+               if (nested_cpu_has(vmcs12, CPU_BASED_USE_TSC_OFFSETING))
+                       active_offset += vmcs12->tsc_offset;
        } else {
                trace_kvm_write_tsc_offset(vcpu->vcpu_id,
                                           vmcs_read64(TSC_OFFSET), offset);
-               vmcs_write64(TSC_OFFSET, offset);
        }
+
+       vmcs_write64(TSC_OFFSET, active_offset);
+       return active_offset;
 }
 
 /*
@@ -5944,7 +5953,7 @@ static void free_vpid(int vpid)
        spin_unlock(&vmx_vpid_lock);
 }
 
-static void __always_inline vmx_disable_intercept_for_msr(unsigned long *msr_bitmap,
+static __always_inline void vmx_disable_intercept_for_msr(unsigned long *msr_bitmap,
                                                          u32 msr, int type)
 {
        int f = sizeof(unsigned long);
@@ -5982,7 +5991,7 @@ static void __always_inline vmx_disable_intercept_for_msr(unsigned long *msr_bit
        }
 }
 
-static void __always_inline vmx_enable_intercept_for_msr(unsigned long *msr_bitmap,
+static __always_inline void vmx_enable_intercept_for_msr(unsigned long *msr_bitmap,
                                                         u32 msr, int type)
 {
        int f = sizeof(unsigned long);
@@ -6020,7 +6029,7 @@ static void __always_inline vmx_enable_intercept_for_msr(unsigned long *msr_bitm
        }
 }
 
-static void __always_inline vmx_set_intercept_for_msr(unsigned long *msr_bitmap,
+static __always_inline void vmx_set_intercept_for_msr(unsigned long *msr_bitmap,
                                                      u32 msr, int type, bool value)
 {
        if (value)
@@ -8664,8 +8673,6 @@ static int copy_enlightened_to_vmcs12(struct vcpu_vmx *vmx)
        struct vmcs12 *vmcs12 = vmx->nested.cached_vmcs12;
        struct hv_enlightened_vmcs *evmcs = vmx->nested.hv_evmcs;
 
-       vmcs12->hdr.revision_id = evmcs->revision_id;
-
        /* HV_VMX_ENLIGHTENED_CLEAN_FIELD_NONE */
        vmcs12->tpr_threshold = evmcs->tpr_threshold;
        vmcs12->guest_rip = evmcs->guest_rip;
@@ -9369,7 +9376,30 @@ static int nested_vmx_handle_enlightened_vmptrld(struct kvm_vcpu *vcpu,
 
                vmx->nested.hv_evmcs = kmap(vmx->nested.hv_evmcs_page);
 
-               if (vmx->nested.hv_evmcs->revision_id != VMCS12_REVISION) {
+               /*
+                * Currently, KVM only supports eVMCS version 1
+                * (== KVM_EVMCS_VERSION) and thus we expect guest to set this
+                * value to first u32 field of eVMCS which should specify eVMCS
+                * VersionNumber.
+                *
+                * Guest should be aware of supported eVMCS versions by host by
+                * examining CPUID.0x4000000A.EAX[0:15]. Host userspace VMM is
+                * expected to set this CPUID leaf according to the value
+                * returned in vmcs_version from nested_enable_evmcs().
+                *
+                * However, it turns out that Microsoft Hyper-V fails to comply
+                * to their own invented interface: When Hyper-V use eVMCS, it
+                * just sets first u32 field of eVMCS to revision_id specified
+                * in MSR_IA32_VMX_BASIC. Instead of used eVMCS version number
+                * which is one of the supported versions specified in
+                * CPUID.0x4000000A.EAX[0:15].
+                *
+                * To overcome Hyper-V bug, we accept here either a supported
+                * eVMCS version or VMCS12 revision_id as valid values for first
+                * u32 field of eVMCS.
+                */
+               if ((vmx->nested.hv_evmcs->revision_id != KVM_EVMCS_VERSION) &&
+                   (vmx->nested.hv_evmcs->revision_id != VMCS12_REVISION)) {
                        nested_release_evmcs(vcpu);
                        return 0;
                }
@@ -9390,9 +9420,11 @@ static int nested_vmx_handle_enlightened_vmptrld(struct kvm_vcpu *vcpu,
                 * present in struct hv_enlightened_vmcs, ...). Make sure there
                 * are no leftovers.
                 */
-               if (from_launch)
-                       memset(vmx->nested.cached_vmcs12, 0,
-                              sizeof(*vmx->nested.cached_vmcs12));
+               if (from_launch) {
+                       struct vmcs12 *vmcs12 = get_vmcs12(vcpu);
+                       memset(vmcs12, 0, sizeof(*vmcs12));
+                       vmcs12->hdr.revision_id = VMCS12_REVISION;
+               }
 
        }
        return 1;
@@ -15062,7 +15094,7 @@ static struct kvm_x86_ops vmx_x86_ops __ro_after_init = {
        .has_wbinvd_exit = cpu_has_vmx_wbinvd_exit,
 
        .read_l1_tsc_offset = vmx_read_l1_tsc_offset,
-       .write_tsc_offset = vmx_write_tsc_offset,
+       .write_l1_tsc_offset = vmx_write_l1_tsc_offset,
 
        .set_tdp_cr3 = vmx_set_cr3,
 
index 5cd5647..d029377 100644 (file)
@@ -1665,8 +1665,7 @@ EXPORT_SYMBOL_GPL(kvm_read_l1_tsc);
 
 static void kvm_vcpu_write_tsc_offset(struct kvm_vcpu *vcpu, u64 offset)
 {
-       kvm_x86_ops->write_tsc_offset(vcpu, offset);
-       vcpu->arch.tsc_offset = offset;
+       vcpu->arch.tsc_offset = kvm_x86_ops->write_l1_tsc_offset(vcpu, offset);
 }
 
 static inline bool kvm_check_tsc_unstable(void)
@@ -1794,7 +1793,8 @@ EXPORT_SYMBOL_GPL(kvm_write_tsc);
 static inline void adjust_tsc_offset_guest(struct kvm_vcpu *vcpu,
                                           s64 adjustment)
 {
-       kvm_vcpu_write_tsc_offset(vcpu, vcpu->arch.tsc_offset + adjustment);
+       u64 tsc_offset = kvm_x86_ops->read_l1_tsc_offset(vcpu);
+       kvm_vcpu_write_tsc_offset(vcpu, tsc_offset + adjustment);
 }
 
 static inline void adjust_tsc_offset_host(struct kvm_vcpu *vcpu, s64 adjustment)
@@ -6918,6 +6918,7 @@ static int kvm_pv_clock_pairing(struct kvm_vcpu *vcpu, gpa_t paddr,
        clock_pairing.nsec = ts.tv_nsec;
        clock_pairing.tsc = kvm_read_l1_tsc(vcpu, cycle);
        clock_pairing.flags = 0;
+       memset(&clock_pairing.pad, 0, sizeof(clock_pairing.pad));
 
        ret = 0;
        if (kvm_write_guest(vcpu->kvm, paddr, &clock_pairing,
@@ -7455,7 +7456,8 @@ static void vcpu_scan_ioapic(struct kvm_vcpu *vcpu)
        else {
                if (vcpu->arch.apicv_active)
                        kvm_x86_ops->sync_pir_to_irr(vcpu);
-               kvm_ioapic_scan_entry(vcpu, vcpu->arch.ioapic_handled_vectors);
+               if (ioapic_in_kernel(vcpu->kvm))
+                       kvm_ioapic_scan_entry(vcpu, vcpu->arch.ioapic_handled_vectors);
        }
 
        if (is_guest_mode(vcpu))
index bddd6b3..03b6b4c 100644 (file)
@@ -7,7 +7,6 @@
 #include <linux/export.h>
 #include <linux/cpu.h>
 #include <linux/debugfs.h>
-#include <linux/ptrace.h>
 
 #include <asm/tlbflush.h>
 #include <asm/mmu_context.h>
  *     Implement flush IPI by CALL_FUNCTION_VECTOR, Alex Shi
  */
 
+/*
+ * Use bit 0 to mangle the TIF_SPEC_IB state into the mm pointer which is
+ * stored in cpu_tlb_state.last_user_mm_ibpb.
+ */
+#define LAST_USER_MM_IBPB      0x1UL
+
 /*
  * We get here when we do something requiring a TLB invalidation
  * but could not go invalidate all of the contexts.  We do the
@@ -181,17 +186,87 @@ static void sync_current_stack_to_mm(struct mm_struct *mm)
        }
 }
 
-static bool ibpb_needed(struct task_struct *tsk, u64 last_ctx_id)
+static inline unsigned long mm_mangle_tif_spec_ib(struct task_struct *next)
+{
+       unsigned long next_tif = task_thread_info(next)->flags;
+       unsigned long ibpb = (next_tif >> TIF_SPEC_IB) & LAST_USER_MM_IBPB;
+
+       return (unsigned long)next->mm | ibpb;
+}
+
+static void cond_ibpb(struct task_struct *next)
 {
+       if (!next || !next->mm)
+               return;
+
        /*
-        * Check if the current (previous) task has access to the memory
-        * of the @tsk (next) task. If access is denied, make sure to
-        * issue a IBPB to stop user->user Spectre-v2 attacks.
-        *
-        * Note: __ptrace_may_access() returns 0 or -ERRNO.
+        * Both, the conditional and the always IBPB mode use the mm
+        * pointer to avoid the IBPB when switching between tasks of the
+        * same process. Using the mm pointer instead of mm->context.ctx_id
+        * opens a hypothetical hole vs. mm_struct reuse, which is more or
+        * less impossible to control by an attacker. Aside of that it
+        * would only affect the first schedule so the theoretically
+        * exposed data is not really interesting.
         */
-       return (tsk && tsk->mm && tsk->mm->context.ctx_id != last_ctx_id &&
-               ptrace_may_access_sched(tsk, PTRACE_MODE_SPEC_IBPB));
+       if (static_branch_likely(&switch_mm_cond_ibpb)) {
+               unsigned long prev_mm, next_mm;
+
+               /*
+                * This is a bit more complex than the always mode because
+                * it has to handle two cases:
+                *
+                * 1) Switch from a user space task (potential attacker)
+                *    which has TIF_SPEC_IB set to a user space task
+                *    (potential victim) which has TIF_SPEC_IB not set.
+                *
+                * 2) Switch from a user space task (potential attacker)
+                *    which has TIF_SPEC_IB not set to a user space task
+                *    (potential victim) which has TIF_SPEC_IB set.
+                *
+                * This could be done by unconditionally issuing IBPB when
+                * a task which has TIF_SPEC_IB set is either scheduled in
+                * or out. Though that results in two flushes when:
+                *
+                * - the same user space task is scheduled out and later
+                *   scheduled in again and only a kernel thread ran in
+                *   between.
+                *
+                * - a user space task belonging to the same process is
+                *   scheduled in after a kernel thread ran in between
+                *
+                * - a user space task belonging to the same process is
+                *   scheduled in immediately.
+                *
+                * Optimize this with reasonably small overhead for the
+                * above cases. Mangle the TIF_SPEC_IB bit into the mm
+                * pointer of the incoming task which is stored in
+                * cpu_tlbstate.last_user_mm_ibpb for comparison.
+                */
+               next_mm = mm_mangle_tif_spec_ib(next);
+               prev_mm = this_cpu_read(cpu_tlbstate.last_user_mm_ibpb);
+
+               /*
+                * Issue IBPB only if the mm's are different and one or
+                * both have the IBPB bit set.
+                */
+               if (next_mm != prev_mm &&
+                   (next_mm | prev_mm) & LAST_USER_MM_IBPB)
+                       indirect_branch_prediction_barrier();
+
+               this_cpu_write(cpu_tlbstate.last_user_mm_ibpb, next_mm);
+       }
+
+       if (static_branch_unlikely(&switch_mm_always_ibpb)) {
+               /*
+                * Only flush when switching to a user space task with a
+                * different context than the user space task which ran
+                * last on this CPU.
+                */
+               if (this_cpu_read(cpu_tlbstate.last_user_mm) != next->mm) {
+                       indirect_branch_prediction_barrier();
+                       this_cpu_write(cpu_tlbstate.last_user_mm, next->mm);
+               }
+       }
 }
 
 void switch_mm_irqs_off(struct mm_struct *prev, struct mm_struct *next,
@@ -292,22 +367,12 @@ void switch_mm_irqs_off(struct mm_struct *prev, struct mm_struct *next,
                new_asid = prev_asid;
                need_flush = true;
        } else {
-               u64 last_ctx_id = this_cpu_read(cpu_tlbstate.last_ctx_id);
-
                /*
                 * Avoid user/user BTB poisoning by flushing the branch
                 * predictor when switching between processes. This stops
                 * one process from doing Spectre-v2 attacks on another.
-                *
-                * As an optimization, flush indirect branches only when
-                * switching into a processes that can't be ptrace by the
-                * current one (as in such case, attacker has much more
-                * convenient way how to tamper with the next process than
-                * branch buffer poisoning).
                 */
-               if (static_cpu_has(X86_FEATURE_USE_IBPB) &&
-                               ibpb_needed(tsk, last_ctx_id))
-                       indirect_branch_prediction_barrier();
+               cond_ibpb(tsk);
 
                if (IS_ENABLED(CONFIG_VMAP_STACK)) {
                        /*
@@ -365,14 +430,6 @@ void switch_mm_irqs_off(struct mm_struct *prev, struct mm_struct *next,
                trace_tlb_flush_rcuidle(TLB_FLUSH_ON_TASK_SWITCH, 0);
        }
 
-       /*
-        * Record last user mm's context id, so we can avoid
-        * flushing branch buffer with IBPB if we switch back
-        * to the same user.
-        */
-       if (next != &init_mm)
-               this_cpu_write(cpu_tlbstate.last_ctx_id, next->context.ctx_id);
-
        /* Make sure we write CR3 before loaded_mm. */
        barrier();
 
@@ -441,7 +498,7 @@ void initialize_tlbstate_and_flush(void)
        write_cr3(build_cr3(mm->pgd, 0));
 
        /* Reinitialize tlbstate. */
-       this_cpu_write(cpu_tlbstate.last_ctx_id, mm->context.ctx_id);
+       this_cpu_write(cpu_tlbstate.last_user_mm_ibpb, LAST_USER_MM_IBPB);
        this_cpu_write(cpu_tlbstate.loaded_mm_asid, 0);
        this_cpu_write(cpu_tlbstate.next_asid, 1);
        this_cpu_write(cpu_tlbstate.ctxs[0].ctx_id, mm->context.ctx_id);
index e996e8e..750f46a 100644 (file)
@@ -10,7 +10,6 @@
 #include <xen/xen.h>
 #include <xen/features.h>
 #include <xen/page.h>
-#include <xen/interface/memory.h>
 
 #include <asm/xen/hypercall.h>
 #include <asm/xen/hypervisor.h>
@@ -346,80 +345,3 @@ void xen_arch_unregister_cpu(int num)
 }
 EXPORT_SYMBOL(xen_arch_unregister_cpu);
 #endif
-
-#ifdef CONFIG_XEN_BALLOON_MEMORY_HOTPLUG
-void __init arch_xen_balloon_init(struct resource *hostmem_resource)
-{
-       struct xen_memory_map memmap;
-       int rc;
-       unsigned int i, last_guest_ram;
-       phys_addr_t max_addr = PFN_PHYS(max_pfn);
-       struct e820_table *xen_e820_table;
-       const struct e820_entry *entry;
-       struct resource *res;
-
-       if (!xen_initial_domain())
-               return;
-
-       xen_e820_table = kmalloc(sizeof(*xen_e820_table), GFP_KERNEL);
-       if (!xen_e820_table)
-               return;
-
-       memmap.nr_entries = ARRAY_SIZE(xen_e820_table->entries);
-       set_xen_guest_handle(memmap.buffer, xen_e820_table->entries);
-       rc = HYPERVISOR_memory_op(XENMEM_machine_memory_map, &memmap);
-       if (rc) {
-               pr_warn("%s: Can't read host e820 (%d)\n", __func__, rc);
-               goto out;
-       }
-
-       last_guest_ram = 0;
-       for (i = 0; i < memmap.nr_entries; i++) {
-               if (xen_e820_table->entries[i].addr >= max_addr)
-                       break;
-               if (xen_e820_table->entries[i].type == E820_TYPE_RAM)
-                       last_guest_ram = i;
-       }
-
-       entry = &xen_e820_table->entries[last_guest_ram];
-       if (max_addr >= entry->addr + entry->size)
-               goto out; /* No unallocated host RAM. */
-
-       hostmem_resource->start = max_addr;
-       hostmem_resource->end = entry->addr + entry->size;
-
-       /*
-        * Mark non-RAM regions between the end of dom0 RAM and end of host RAM
-        * as unavailable. The rest of that region can be used for hotplug-based
-        * ballooning.
-        */
-       for (; i < memmap.nr_entries; i++) {
-               entry = &xen_e820_table->entries[i];
-
-               if (entry->type == E820_TYPE_RAM)
-                       continue;
-
-               if (entry->addr >= hostmem_resource->end)
-                       break;
-
-               res = kzalloc(sizeof(*res), GFP_KERNEL);
-               if (!res)
-                       goto out;
-
-               res->name = "Unavailable host RAM";
-               res->start = entry->addr;
-               res->end = (entry->addr + entry->size < hostmem_resource->end) ?
-                           entry->addr + entry->size : hostmem_resource->end;
-               rc = insert_resource(hostmem_resource, res);
-               if (rc) {
-                       pr_warn("%s: Can't insert [%llx - %llx) (%d)\n",
-                               __func__, res->start, res->end, rc);
-                       kfree(res);
-                       goto  out;
-               }
-       }
-
- out:
-       kfree(xen_e820_table);
-}
-#endif /* CONFIG_XEN_BALLOON_MEMORY_HOTPLUG */
index 2bce795..0766a08 100644 (file)
@@ -69,6 +69,11 @@ void xen_mc_flush(void)
 
        trace_xen_mc_flush(b->mcidx, b->argidx, b->cbidx);
 
+#if MC_DEBUG
+       memcpy(b->debug, b->entries,
+              b->mcidx * sizeof(struct multicall_entry));
+#endif
+
        switch (b->mcidx) {
        case 0:
                /* no-op */
@@ -87,32 +92,34 @@ void xen_mc_flush(void)
                break;
 
        default:
-#if MC_DEBUG
-               memcpy(b->debug, b->entries,
-                      b->mcidx * sizeof(struct multicall_entry));
-#endif
-
                if (HYPERVISOR_multicall(b->entries, b->mcidx) != 0)
                        BUG();
                for (i = 0; i < b->mcidx; i++)
                        if (b->entries[i].result < 0)
                                ret++;
+       }
 
+       if (WARN_ON(ret)) {
+               pr_err("%d of %d multicall(s) failed: cpu %d\n",
+                      ret, b->mcidx, smp_processor_id());
+               for (i = 0; i < b->mcidx; i++) {
+                       if (b->entries[i].result < 0) {
 #if MC_DEBUG
-               if (ret) {
-                       printk(KERN_ERR "%d multicall(s) failed: cpu %d\n",
-                              ret, smp_processor_id());
-                       dump_stack();
-                       for (i = 0; i < b->mcidx; i++) {
-                               printk(KERN_DEBUG "  call %2d/%d: op=%lu arg=[%lx] result=%ld\t%pF\n",
-                                      i+1, b->mcidx,
+                               pr_err("  call %2d: op=%lu arg=[%lx] result=%ld\t%pF\n",
+                                      i + 1,
                                       b->debug[i].op,
                                       b->debug[i].args[0],
                                       b->entries[i].result,
                                       b->caller[i]);
+#else
+                               pr_err("  call %2d: op=%lu arg=[%lx] result=%ld\n",
+                                      i + 1,
+                                      b->entries[i].op,
+                                      b->entries[i].args[0],
+                                      b->entries[i].result);
+#endif
                        }
                }
-#endif
        }
 
        b->mcidx = 0;
@@ -126,8 +133,6 @@ void xen_mc_flush(void)
        b->cbidx = 0;
 
        local_irq_restore(flags);
-
-       WARN_ON(ret);
 }
 
 struct multicall_space __xen_mc_entry(size_t args)
index 1163e33..075ed47 100644 (file)
@@ -808,6 +808,7 @@ char * __init xen_memory_setup(void)
        addr = xen_e820_table.entries[0].addr;
        size = xen_e820_table.entries[0].size;
        while (i < xen_e820_table.nr_entries) {
+               bool discard = false;
 
                chunk_size = size;
                type = xen_e820_table.entries[i].type;
@@ -823,10 +824,11 @@ char * __init xen_memory_setup(void)
                                xen_add_extra_mem(pfn_s, n_pfns);
                                xen_max_p2m_pfn = pfn_s + n_pfns;
                        } else
-                               type = E820_TYPE_UNUSABLE;
+                               discard = true;
                }
 
-               xen_align_and_add_e820_region(addr, chunk_size, type);
+               if (!discard)
+                       xen_align_and_add_e820_region(addr, chunk_size, type);
 
                addr += chunk_size;
                size -= chunk_size;
index 1c8a881..3776122 100644 (file)
@@ -3,22 +3,17 @@
  * Split spinlock implementation out into its own file, so it can be
  * compiled in a FTRACE-compatible way.
  */
-#include <linux/kernel_stat.h>
+#include <linux/kernel.h>
 #include <linux/spinlock.h>
-#include <linux/debugfs.h>
-#include <linux/log2.h>
-#include <linux/gfp.h>
 #include <linux/slab.h>
 #include <linux/atomic.h>
 
 #include <asm/paravirt.h>
 #include <asm/qspinlock.h>
 
-#include <xen/interface/xen.h>
 #include <xen/events.h>
 
 #include "xen-ops.h"
-#include "debugfs.h"
 
 static DEFINE_PER_CPU(int, lock_kicker_irq) = -1;
 static DEFINE_PER_CPU(char *, irq_name);
index 67904f5..120dd74 100644 (file)
@@ -94,14 +94,14 @@ int main(void)
        DEFINE(THREAD_SP, offsetof (struct task_struct, thread.sp));
        DEFINE(THREAD_CPENABLE, offsetof (struct thread_info, cpenable));
 #if XTENSA_HAVE_COPROCESSORS
-       DEFINE(THREAD_XTREGS_CP0, offsetof (struct thread_info, xtregs_cp));
-       DEFINE(THREAD_XTREGS_CP1, offsetof (struct thread_info, xtregs_cp));
-       DEFINE(THREAD_XTREGS_CP2, offsetof (struct thread_info, xtregs_cp));
-       DEFINE(THREAD_XTREGS_CP3, offsetof (struct thread_info, xtregs_cp));
-       DEFINE(THREAD_XTREGS_CP4, offsetof (struct thread_info, xtregs_cp));
-       DEFINE(THREAD_XTREGS_CP5, offsetof (struct thread_info, xtregs_cp));
-       DEFINE(THREAD_XTREGS_CP6, offsetof (struct thread_info, xtregs_cp));
-       DEFINE(THREAD_XTREGS_CP7, offsetof (struct thread_info, xtregs_cp));
+       DEFINE(THREAD_XTREGS_CP0, offsetof(struct thread_info, xtregs_cp.cp0));
+       DEFINE(THREAD_XTREGS_CP1, offsetof(struct thread_info, xtregs_cp.cp1));
+       DEFINE(THREAD_XTREGS_CP2, offsetof(struct thread_info, xtregs_cp.cp2));
+       DEFINE(THREAD_XTREGS_CP3, offsetof(struct thread_info, xtregs_cp.cp3));
+       DEFINE(THREAD_XTREGS_CP4, offsetof(struct thread_info, xtregs_cp.cp4));
+       DEFINE(THREAD_XTREGS_CP5, offsetof(struct thread_info, xtregs_cp.cp5));
+       DEFINE(THREAD_XTREGS_CP6, offsetof(struct thread_info, xtregs_cp.cp6));
+       DEFINE(THREAD_XTREGS_CP7, offsetof(struct thread_info, xtregs_cp.cp7));
 #endif
        DEFINE(THREAD_XTREGS_USER, offsetof (struct thread_info, xtregs_user));
        DEFINE(XTREGS_USER_SIZE, sizeof(xtregs_user_t));
index 483dcfb..4bb6813 100644 (file)
@@ -94,18 +94,21 @@ void coprocessor_release_all(struct thread_info *ti)
 
 void coprocessor_flush_all(struct thread_info *ti)
 {
-       unsigned long cpenable;
+       unsigned long cpenable, old_cpenable;
        int i;
 
        preempt_disable();
 
+       RSR_CPENABLE(old_cpenable);
        cpenable = ti->cpenable;
+       WSR_CPENABLE(cpenable);
 
        for (i = 0; i < XCHAL_CP_MAX; i++) {
                if ((cpenable & 1) != 0 && coprocessor_owner[i] == ti)
                        coprocessor_flush(ti, i);
                cpenable >>= 1;
        }
+       WSR_CPENABLE(old_cpenable);
 
        preempt_enable();
 }
index c0845cb..d9541be 100644 (file)
@@ -127,12 +127,37 @@ static int ptrace_setregs(struct task_struct *child, void __user *uregs)
 }
 
 
+#if XTENSA_HAVE_COPROCESSORS
+#define CP_OFFSETS(cp) \
+       { \
+               .elf_xtregs_offset = offsetof(elf_xtregs_t, cp), \
+               .ti_offset = offsetof(struct thread_info, xtregs_cp.cp), \
+               .sz = sizeof(xtregs_ ## cp ## _t), \
+       }
+
+static const struct {
+       size_t elf_xtregs_offset;
+       size_t ti_offset;
+       size_t sz;
+} cp_offsets[] = {
+       CP_OFFSETS(cp0),
+       CP_OFFSETS(cp1),
+       CP_OFFSETS(cp2),
+       CP_OFFSETS(cp3),
+       CP_OFFSETS(cp4),
+       CP_OFFSETS(cp5),
+       CP_OFFSETS(cp6),
+       CP_OFFSETS(cp7),
+};
+#endif
+
 static int ptrace_getxregs(struct task_struct *child, void __user *uregs)
 {
        struct pt_regs *regs = task_pt_regs(child);
        struct thread_info *ti = task_thread_info(child);
        elf_xtregs_t __user *xtregs = uregs;
        int ret = 0;
+       int i __maybe_unused;
 
        if (!access_ok(VERIFY_WRITE, uregs, sizeof(elf_xtregs_t)))
                return -EIO;
@@ -140,8 +165,13 @@ static int ptrace_getxregs(struct task_struct *child, void __user *uregs)
 #if XTENSA_HAVE_COPROCESSORS
        /* Flush all coprocessor registers to memory. */
        coprocessor_flush_all(ti);
-       ret |= __copy_to_user(&xtregs->cp0, &ti->xtregs_cp,
-                             sizeof(xtregs_coprocessor_t));
+
+       for (i = 0; i < ARRAY_SIZE(cp_offsets); ++i)
+               ret |= __copy_to_user((char __user *)xtregs +
+                                     cp_offsets[i].elf_xtregs_offset,
+                                     (const char *)ti +
+                                     cp_offsets[i].ti_offset,
+                                     cp_offsets[i].sz);
 #endif
        ret |= __copy_to_user(&xtregs->opt, &regs->xtregs_opt,
                              sizeof(xtregs->opt));
@@ -157,6 +187,7 @@ static int ptrace_setxregs(struct task_struct *child, void __user *uregs)
        struct pt_regs *regs = task_pt_regs(child);
        elf_xtregs_t *xtregs = uregs;
        int ret = 0;
+       int i __maybe_unused;
 
        if (!access_ok(VERIFY_READ, uregs, sizeof(elf_xtregs_t)))
                return -EFAULT;
@@ -166,8 +197,11 @@ static int ptrace_setxregs(struct task_struct *child, void __user *uregs)
        coprocessor_flush_all(ti);
        coprocessor_release_all(ti);
 
-       ret |= __copy_from_user(&ti->xtregs_cp, &xtregs->cp0,
-                               sizeof(xtregs_coprocessor_t));
+       for (i = 0; i < ARRAY_SIZE(cp_offsets); ++i)
+               ret |= __copy_from_user((char *)ti + cp_offsets[i].ti_offset,
+                                       (const char __user *)xtregs +
+                                       cp_offsets[i].elf_xtregs_offset,
+                                       cp_offsets[i].sz);
 #endif
        ret |= __copy_from_user(&regs->xtregs_opt, &xtregs->opt,
                                sizeof(xtregs->opt));
index e7696c4..7695034 100644 (file)
@@ -820,7 +820,7 @@ static struct request *attempt_merge(struct request_queue *q,
 
        req->__data_len += blk_rq_bytes(next);
 
-       if (req_op(req) != REQ_OP_DISCARD)
+       if (!blk_discard_mergable(req))
                elv_merge_requests(q, req, next);
 
        /*
index 0d42f30..9920fac 100644 (file)
@@ -244,7 +244,6 @@ acpi_ex_write_serial_bus(union acpi_operand_object *source_desc,
 {
        acpi_status status;
        u32 buffer_length;
-       u32 data_length;
        void *buffer;
        union acpi_operand_object *buffer_desc;
        u32 function;
@@ -282,14 +281,12 @@ acpi_ex_write_serial_bus(union acpi_operand_object *source_desc,
        case ACPI_ADR_SPACE_SMBUS:
 
                buffer_length = ACPI_SMBUS_BUFFER_SIZE;
-               data_length = ACPI_SMBUS_DATA_SIZE;
                function = ACPI_WRITE | (obj_desc->field.attribute << 16);
                break;
 
        case ACPI_ADR_SPACE_IPMI:
 
                buffer_length = ACPI_IPMI_BUFFER_SIZE;
-               data_length = ACPI_IPMI_DATA_SIZE;
                function = ACPI_WRITE;
                break;
 
@@ -310,7 +307,6 @@ acpi_ex_write_serial_bus(union acpi_operand_object *source_desc,
                /* Add header length to get the full size of the buffer */
 
                buffer_length += ACPI_SERIAL_HEADER_SIZE;
-               data_length = source_desc->buffer.pointer[1];
                function = ACPI_WRITE | (accessor_type << 16);
                break;
 
@@ -318,20 +314,6 @@ acpi_ex_write_serial_bus(union acpi_operand_object *source_desc,
                return_ACPI_STATUS(AE_AML_INVALID_SPACE_ID);
        }
 
-#if 0
-       OBSOLETE ?
-           /* Check for possible buffer overflow */
-           if (data_length > source_desc->buffer.length) {
-               ACPI_ERROR((AE_INFO,
-                           "Length in buffer header (%u)(%u) is greater than "
-                           "the physical buffer length (%u) and will overflow",
-                           data_length, buffer_length,
-                           source_desc->buffer.length));
-
-               return_ACPI_STATUS(AE_AML_BUFFER_LIMIT);
-       }
-#endif
-
        /* Create the transfer/bidirectional/return buffer */
 
        buffer_desc = acpi_ut_create_buffer_object(buffer_length);
@@ -342,7 +324,8 @@ acpi_ex_write_serial_bus(union acpi_operand_object *source_desc,
        /* Copy the input buffer data to the transfer buffer */
 
        buffer = buffer_desc->buffer.pointer;
-       memcpy(buffer, source_desc->buffer.pointer, data_length);
+       memcpy(buffer, source_desc->buffer.pointer,
+              min(buffer_length, source_desc->buffer.length));
 
        /* Lock entire transaction if requested */
 
index 2a361e2..70f4e80 100644 (file)
@@ -700,7 +700,7 @@ static void iort_set_device_domain(struct device *dev,
  */
 static struct irq_domain *iort_get_platform_device_domain(struct device *dev)
 {
-       struct acpi_iort_node *node, *msi_parent;
+       struct acpi_iort_node *node, *msi_parent = NULL;
        struct fwnode_handle *iort_fwnode;
        struct acpi_iort_its_group *its;
        int i;
index cb30a52..9f1000d 100644 (file)
@@ -2974,7 +2974,6 @@ static void binder_transaction(struct binder_proc *proc,
                t->buffer = NULL;
                goto err_binder_alloc_buf_failed;
        }
-       t->buffer->allow_user_free = 0;
        t->buffer->debug_id = t->debug_id;
        t->buffer->transaction = t;
        t->buffer->target_node = target_node;
@@ -3510,14 +3509,18 @@ static int binder_thread_write(struct binder_proc *proc,
 
                        buffer = binder_alloc_prepare_to_free(&proc->alloc,
                                                              data_ptr);
-                       if (buffer == NULL) {
-                               binder_user_error("%d:%d BC_FREE_BUFFER u%016llx no match\n",
-                                       proc->pid, thread->pid, (u64)data_ptr);
-                               break;
-                       }
-                       if (!buffer->allow_user_free) {
-                               binder_user_error("%d:%d BC_FREE_BUFFER u%016llx matched unreturned buffer\n",
-                                       proc->pid, thread->pid, (u64)data_ptr);
+                       if (IS_ERR_OR_NULL(buffer)) {
+                               if (PTR_ERR(buffer) == -EPERM) {
+                                       binder_user_error(
+                                               "%d:%d BC_FREE_BUFFER u%016llx matched unreturned or currently freeing buffer\n",
+                                               proc->pid, thread->pid,
+                                               (u64)data_ptr);
+                               } else {
+                                       binder_user_error(
+                                               "%d:%d BC_FREE_BUFFER u%016llx no match\n",
+                                               proc->pid, thread->pid,
+                                               (u64)data_ptr);
+                               }
                                break;
                        }
                        binder_debug(BINDER_DEBUG_FREE_BUFFER,
index 64fd96e..030c98f 100644 (file)
@@ -151,16 +151,12 @@ static struct binder_buffer *binder_alloc_prepare_to_free_locked(
                else {
                        /*
                         * Guard against user threads attempting to
-                        * free the buffer twice
+                        * free the buffer when in use by kernel or
+                        * after it's already been freed.
                         */
-                       if (buffer->free_in_progress) {
-                               binder_alloc_debug(BINDER_DEBUG_USER_ERROR,
-                                                  "%d:%d FREE_BUFFER u%016llx user freed buffer twice\n",
-                                                  alloc->pid, current->pid,
-                                                  (u64)user_ptr);
-                               return NULL;
-                       }
-                       buffer->free_in_progress = 1;
+                       if (!buffer->allow_user_free)
+                               return ERR_PTR(-EPERM);
+                       buffer->allow_user_free = 0;
                        return buffer;
                }
        }
@@ -500,7 +496,7 @@ static struct binder_buffer *binder_alloc_new_buf_locked(
 
        rb_erase(best_fit, &alloc->free_buffers);
        buffer->free = 0;
-       buffer->free_in_progress = 0;
+       buffer->allow_user_free = 0;
        binder_insert_allocated_buffer_locked(alloc, buffer);
        binder_alloc_debug(BINDER_DEBUG_BUFFER_ALLOC,
                     "%d: binder_alloc_buf size %zd got %pK\n",
index 9ef64e5..fb3238c 100644 (file)
@@ -50,8 +50,7 @@ struct binder_buffer {
        unsigned free:1;
        unsigned allow_user_free:1;
        unsigned async_transaction:1;
-       unsigned free_in_progress:1;
-       unsigned debug_id:28;
+       unsigned debug_id:29;
 
        struct binder_transaction *transaction;
 
index 4e46dc9..11e1663 100644 (file)
@@ -1410,7 +1410,7 @@ static int init_q(struct fs_dev *dev, struct queue *txq, int queue,
 
        func_enter ();
 
-       fs_dprintk (FS_DEBUG_INIT, "Inititing queue at %x: %d entries:\n", 
+       fs_dprintk (FS_DEBUG_INIT, "Initializing queue at %x: %d entries:\n",
                    queue, nentries);
 
        p = aligned_kmalloc (sz, GFP_KERNEL, 0x10);
@@ -1443,7 +1443,7 @@ static int init_fp(struct fs_dev *dev, struct freepool *fp, int queue,
 {
        func_enter ();
 
-       fs_dprintk (FS_DEBUG_INIT, "Inititing free pool at %x:\n", queue);
+       fs_dprintk (FS_DEBUG_INIT, "Initializing free pool at %x:\n", queue);
 
        write_fs (dev, FP_CNF(queue), (bufsize * RBFP_RBS) | RBFP_RBSVAL | RBFP_CME);
        write_fs (dev, FP_SA(queue),  0);
index 4aaf00d..e038e2b 100644 (file)
@@ -26,8 +26,14 @@ struct devres_node {
 
 struct devres {
        struct devres_node              node;
-       /* -- 3 pointers */
-       unsigned long long              data[]; /* guarantee ull alignment */
+       /*
+        * Some archs want to perform DMA into kmalloc caches
+        * and need a guaranteed alignment larger than
+        * the alignment of a 64-bit integer.
+        * Thus we use ARCH_KMALLOC_MINALIGN here and get exactly the same
+        * buffer alignment as if it was allocated by plain kmalloc().
+        */
+       u8 __aligned(ARCH_KMALLOC_MINALIGN) data[];
 };
 
 struct devres_group {
index 7cbac6e..01d936c 100644 (file)
@@ -1641,6 +1641,12 @@ static void atc_free_chan_resources(struct dma_chan *chan)
        atchan->descs_allocated = 0;
        atchan->status = 0;
 
+       /*
+        * Free atslave allocated in at_dma_xlate()
+        */
+       kfree(chan->private);
+       chan->private = NULL;
+
        dev_vdbg(chan2dev(chan), "free_chan_resources: done\n");
 }
 
@@ -1675,7 +1681,7 @@ static struct dma_chan *at_dma_xlate(struct of_phandle_args *dma_spec,
        dma_cap_zero(mask);
        dma_cap_set(DMA_SLAVE, mask);
 
-       atslave = devm_kzalloc(&dmac_pdev->dev, sizeof(*atslave), GFP_KERNEL);
+       atslave = kzalloc(sizeof(*atslave), GFP_KERNEL);
        if (!atslave)
                return NULL;
 
@@ -2000,6 +2006,8 @@ static int at_dma_remove(struct platform_device *pdev)
        struct resource         *io;
 
        at_dma_off(atdma);
+       if (pdev->dev.of_node)
+               of_dma_controller_free(pdev->dev.of_node);
        dma_async_device_unregister(&atdma->dma_common);
 
        dma_pool_destroy(atdma->memset_pool);
index fad7c62..415849b 100644 (file)
@@ -969,13 +969,33 @@ bool efi_is_table_address(unsigned long phys_addr)
 static DEFINE_SPINLOCK(efi_mem_reserve_persistent_lock);
 static struct linux_efi_memreserve *efi_memreserve_root __ro_after_init;
 
-int efi_mem_reserve_persistent(phys_addr_t addr, u64 size)
+static int __init efi_memreserve_map_root(void)
+{
+       if (efi.mem_reserve == EFI_INVALID_TABLE_ADDR)
+               return -ENODEV;
+
+       efi_memreserve_root = memremap(efi.mem_reserve,
+                                      sizeof(*efi_memreserve_root),
+                                      MEMREMAP_WB);
+       if (WARN_ON_ONCE(!efi_memreserve_root))
+               return -ENOMEM;
+       return 0;
+}
+
+int __ref efi_mem_reserve_persistent(phys_addr_t addr, u64 size)
 {
        struct linux_efi_memreserve *rsv;
+       int rc;
 
-       if (!efi_memreserve_root)
+       if (efi_memreserve_root == (void *)ULONG_MAX)
                return -ENODEV;
 
+       if (!efi_memreserve_root) {
+               rc = efi_memreserve_map_root();
+               if (rc)
+                       return rc;
+       }
+
        rsv = kmalloc(sizeof(*rsv), GFP_ATOMIC);
        if (!rsv)
                return -ENOMEM;
@@ -993,14 +1013,10 @@ int efi_mem_reserve_persistent(phys_addr_t addr, u64 size)
 
 static int __init efi_memreserve_root_init(void)
 {
-       if (efi.mem_reserve == EFI_INVALID_TABLE_ADDR)
-               return -ENODEV;
-
-       efi_memreserve_root = memremap(efi.mem_reserve,
-                                      sizeof(*efi_memreserve_root),
-                                      MEMREMAP_WB);
-       if (!efi_memreserve_root)
-               return -ENOMEM;
+       if (efi_memreserve_root)
+               return 0;
+       if (efi_memreserve_map_root())
+               efi_memreserve_root = (void *)ULONG_MAX;
        return 0;
 }
 early_initcall(efi_memreserve_root_init);
index af3a20d..99c99a5 100644 (file)
@@ -46,6 +46,7 @@ config FSI_MASTER_AST_CF
        tristate "FSI master based on Aspeed ColdFire coprocessor"
        depends on GPIOLIB
        depends on GPIO_ASPEED
+       select GENERIC_ALLOCATOR
        ---help---
        This option enables a FSI master using the AST2400 and AST2500 GPIO
        lines driven by the internal ColdFire coprocessor. This requires
index df94021..81dc01a 100644 (file)
@@ -20,7 +20,6 @@
 #include <linux/fs.h>
 #include <linux/uaccess.h>
 #include <linux/slab.h>
-#include <linux/cdev.h>
 #include <linux/list.h>
 
 #include <uapi/linux/fsi.h>
index 5c1564f..bdb29e5 100644 (file)
@@ -258,7 +258,7 @@ static int davinci_gpio_probe(struct platform_device *pdev)
        chips->chip.set = davinci_gpio_set;
 
        chips->chip.ngpio = ngpio;
-       chips->chip.base = -1;
+       chips->chip.base = pdata->no_auto_base ? pdata->base : -1;
 
 #ifdef CONFIG_OF_GPIO
        chips->chip.of_gpio_n_cells = 2;
index dad0e23..0877ff9 100644 (file)
@@ -181,7 +181,7 @@ static unsigned amdgpu_vm_num_entries(struct amdgpu_device *adev,
 
        if (level == adev->vm_manager.root_level)
                /* For the root directory */
-               return round_up(adev->vm_manager.max_pfn, 1 << shift) >> shift;
+               return round_up(adev->vm_manager.max_pfn, 1ULL << shift) >> shift;
        else if (level != AMDGPU_VM_PTB)
                /* Everything in between */
                return 512;
@@ -1656,9 +1656,11 @@ static int amdgpu_vm_update_ptes(struct amdgpu_pte_update_params *params,
                        if (!amdgpu_vm_pt_descendant(adev, &cursor))
                                return -ENOENT;
                        continue;
-               } else if (frag >= parent_shift) {
+               } else if (frag >= parent_shift &&
+                          cursor.level - 1 != adev->vm_manager.root_level) {
                        /* If the fragment size is even larger than the parent
-                        * shift we should go up one level and check it again.
+                        * shift we should go up one level and check it again
+                        * unless one level up is the root level.
                         */
                        if (!amdgpu_vm_pt_ancestor(&cursor))
                                return -ENOENT;
@@ -1666,10 +1668,10 @@ static int amdgpu_vm_update_ptes(struct amdgpu_pte_update_params *params,
                }
 
                /* Looks good so far, calculate parameters for the update */
-               incr = AMDGPU_GPU_PAGE_SIZE << shift;
+               incr = (uint64_t)AMDGPU_GPU_PAGE_SIZE << shift;
                mask = amdgpu_vm_entries_mask(adev, cursor.level);
                pe_start = ((cursor.pfn >> shift) & mask) * 8;
-               entry_end = (mask + 1) << shift;
+               entry_end = (uint64_t)(mask + 1) << shift;
                entry_end += cursor.pfn & ~(entry_end - 1);
                entry_end = min(entry_end, end);
 
@@ -1682,7 +1684,7 @@ static int amdgpu_vm_update_ptes(struct amdgpu_pte_update_params *params,
                                              flags | AMDGPU_PTE_FRAG(frag));
 
                        pe_start += nptes * 8;
-                       dst += nptes * AMDGPU_GPU_PAGE_SIZE << shift;
+                       dst += (uint64_t)nptes * AMDGPU_GPU_PAGE_SIZE << shift;
 
                        frag_start = upd_end;
                        if (frag_start >= frag_end) {
index 6d7baf5..21363b2 100644 (file)
@@ -2440,12 +2440,13 @@ static void gfx_v9_0_rlc_start(struct amdgpu_device *adev)
 #endif
 
        WREG32_FIELD15(GC, 0, RLC_CNTL, RLC_ENABLE_F32, 1);
+       udelay(50);
 
        /* carrizo do enable cp interrupt after cp inited */
-       if (!(adev->flags & AMD_IS_APU))
+       if (!(adev->flags & AMD_IS_APU)) {
                gfx_v9_0_enable_gui_idle_interrupt(adev, true);
-
-       udelay(50);
+               udelay(50);
+       }
 
 #ifdef AMDGPU_RLC_DEBUG_RETRY
        /* RLC_GPM_GENERAL_6 : RLC Ucode version */
index d02c32a..1b0d209 100644 (file)
@@ -342,10 +342,9 @@ dm_dp_add_mst_connector(struct drm_dp_mst_topology_mgr *mgr,
                master->connector_id);
 
        aconnector->mst_encoder = dm_dp_create_fake_mst_encoder(master);
+       drm_connector_attach_encoder(&aconnector->base,
+                                    &aconnector->mst_encoder->base);
 
-       /*
-        * TODO: understand why this one is needed
-        */
        drm_object_attach_property(
                &connector->base,
                dev->mode_config.path_property,
index dac3558..373700c 100644 (file)
@@ -583,7 +583,8 @@ void ast_driver_unload(struct drm_device *dev)
        drm_mode_config_cleanup(dev);
 
        ast_mm_fini(ast);
-       pci_iounmap(dev->pdev, ast->ioregs);
+       if (ast->ioregs != ast->regs + AST_IO_MM_OFFSET)
+               pci_iounmap(dev->pdev, ast->ioregs);
        pci_iounmap(dev->pdev, ast->regs);
        kfree(ast);
 }
index 7c6ac3c..8bb355d 100644 (file)
@@ -973,9 +973,21 @@ static int get_clock(void *i2c_priv)
 {
        struct ast_i2c_chan *i2c = i2c_priv;
        struct ast_private *ast = i2c->dev->dev_private;
-       uint32_t val;
+       uint32_t val, val2, count, pass;
+
+       count = 0;
+       pass = 0;
+       val = (ast_get_index_reg_mask(ast, AST_IO_CRTC_PORT, 0xb7, 0x10) >> 4) & 0x01;
+       do {
+               val2 = (ast_get_index_reg_mask(ast, AST_IO_CRTC_PORT, 0xb7, 0x10) >> 4) & 0x01;
+               if (val == val2) {
+                       pass++;
+               } else {
+                       pass = 0;
+                       val = (ast_get_index_reg_mask(ast, AST_IO_CRTC_PORT, 0xb7, 0x10) >> 4) & 0x01;
+               }
+       } while ((pass < 5) && (count++ < 0x10000));
 
-       val = ast_get_index_reg_mask(ast, AST_IO_CRTC_PORT, 0xb7, 0x10) >> 4;
        return val & 1 ? 1 : 0;
 }
 
@@ -983,9 +995,21 @@ static int get_data(void *i2c_priv)
 {
        struct ast_i2c_chan *i2c = i2c_priv;
        struct ast_private *ast = i2c->dev->dev_private;
-       uint32_t val;
+       uint32_t val, val2, count, pass;
+
+       count = 0;
+       pass = 0;
+       val = (ast_get_index_reg_mask(ast, AST_IO_CRTC_PORT, 0xb7, 0x20) >> 5) & 0x01;
+       do {
+               val2 = (ast_get_index_reg_mask(ast, AST_IO_CRTC_PORT, 0xb7, 0x20) >> 5) & 0x01;
+               if (val == val2) {
+                       pass++;
+               } else {
+                       pass = 0;
+                       val = (ast_get_index_reg_mask(ast, AST_IO_CRTC_PORT, 0xb7, 0x20) >> 5) & 0x01;
+               }
+       } while ((pass < 5) && (count++ < 0x10000));
 
-       val = ast_get_index_reg_mask(ast, AST_IO_CRTC_PORT, 0xb7, 0x20) >> 5;
        return val & 1 ? 1 : 0;
 }
 
@@ -998,7 +1022,7 @@ static void set_clock(void *i2c_priv, int clock)
 
        for (i = 0; i < 0x10000; i++) {
                ujcrb7 = ((clock & 0x01) ? 0 : 1);
-               ast_set_index_reg_mask(ast, AST_IO_CRTC_PORT, 0xb7, 0xfe, ujcrb7);
+               ast_set_index_reg_mask(ast, AST_IO_CRTC_PORT, 0xb7, 0xf4, ujcrb7);
                jtemp = ast_get_index_reg_mask(ast, AST_IO_CRTC_PORT, 0xb7, 0x01);
                if (ujcrb7 == jtemp)
                        break;
@@ -1014,7 +1038,7 @@ static void set_data(void *i2c_priv, int data)
 
        for (i = 0; i < 0x10000; i++) {
                ujcrb7 = ((data & 0x01) ? 0 : 1) << 2;
-               ast_set_index_reg_mask(ast, AST_IO_CRTC_PORT, 0xb7, 0xfb, ujcrb7);
+               ast_set_index_reg_mask(ast, AST_IO_CRTC_PORT, 0xb7, 0xf1, ujcrb7);
                jtemp = ast_get_index_reg_mask(ast, AST_IO_CRTC_PORT, 0xb7, 0x04);
                if (ujcrb7 == jtemp)
                        break;
index d9c0f75..1669c42 100644 (file)
@@ -142,6 +142,7 @@ static int drm_new_set_master(struct drm_device *dev, struct drm_file *fpriv)
 
        lockdep_assert_held_once(&dev->master_mutex);
 
+       WARN_ON(fpriv->is_master);
        old_master = fpriv->master;
        fpriv->master = drm_master_create(dev);
        if (!fpriv->master) {
@@ -170,6 +171,7 @@ out_err:
        /* drop references and restore old master on failure */
        drm_master_put(&fpriv->master);
        fpriv->master = old_master;
+       fpriv->is_master = 0;
 
        return ret;
 }
index fe75402..359d37d 100644 (file)
@@ -61,10 +61,12 @@ static int alloc_gm(struct intel_vgpu *vgpu, bool high_gm)
        }
 
        mutex_lock(&dev_priv->drm.struct_mutex);
+       mmio_hw_access_pre(dev_priv);
        ret = i915_gem_gtt_insert(&dev_priv->ggtt.vm, node,
                                  size, I915_GTT_PAGE_SIZE,
                                  I915_COLOR_UNEVICTABLE,
                                  start, end, flags);
+       mmio_hw_access_post(dev_priv);
        mutex_unlock(&dev_priv->drm.struct_mutex);
        if (ret)
                gvt_err("fail to alloc %s gm space from host\n",
index 58e166e..c7103dd 100644 (file)
@@ -2447,10 +2447,11 @@ static void intel_vgpu_destroy_all_ppgtt_mm(struct intel_vgpu *vgpu)
 
 static void intel_vgpu_destroy_ggtt_mm(struct intel_vgpu *vgpu)
 {
-       struct intel_gvt_partial_pte *pos;
+       struct intel_gvt_partial_pte *pos, *next;
 
-       list_for_each_entry(pos,
-                       &vgpu->gtt.ggtt_mm->ggtt_mm.partial_pte_list, list) {
+       list_for_each_entry_safe(pos, next,
+                                &vgpu->gtt.ggtt_mm->ggtt_mm.partial_pte_list,
+                                list) {
                gvt_dbg_mm("partial PTE update on hold 0x%lx : 0x%llx\n",
                        pos->offset, pos->data);
                kfree(pos);
index 36a5147..d6e02c1 100644 (file)
@@ -158,6 +158,8 @@ static void load_render_mocs(struct drm_i915_private *dev_priv)
        int ring_id, i;
 
        for (ring_id = 0; ring_id < ARRAY_SIZE(regs); ring_id++) {
+               if (!HAS_ENGINE(dev_priv, ring_id))
+                       continue;
                offset.reg = regs[ring_id];
                for (i = 0; i < GEN9_MOCS_SIZE; i++) {
                        gen9_render_mocs.control_table[ring_id][i] =
index 0552020..191b314 100644 (file)
@@ -45,6 +45,7 @@ struct meson_crtc {
        struct drm_crtc base;
        struct drm_pending_vblank_event *event;
        struct meson_drm *priv;
+       bool enabled;
 };
 #define to_meson_crtc(x) container_of(x, struct meson_crtc, base)
 
@@ -80,8 +81,7 @@ static const struct drm_crtc_funcs meson_crtc_funcs = {
 
 };
 
-static void meson_crtc_atomic_enable(struct drm_crtc *crtc,
-                                    struct drm_crtc_state *old_state)
+static void meson_crtc_enable(struct drm_crtc *crtc)
 {
        struct meson_crtc *meson_crtc = to_meson_crtc(crtc);
        struct drm_crtc_state *crtc_state = crtc->state;
@@ -101,6 +101,22 @@ static void meson_crtc_atomic_enable(struct drm_crtc *crtc,
        writel_bits_relaxed(VPP_POSTBLEND_ENABLE, VPP_POSTBLEND_ENABLE,
                            priv->io_base + _REG(VPP_MISC));
 
+       drm_crtc_vblank_on(crtc);
+
+       meson_crtc->enabled = true;
+}
+
+static void meson_crtc_atomic_enable(struct drm_crtc *crtc,
+                                    struct drm_crtc_state *old_state)
+{
+       struct meson_crtc *meson_crtc = to_meson_crtc(crtc);
+       struct meson_drm *priv = meson_crtc->priv;
+
+       DRM_DEBUG_DRIVER("\n");
+
+       if (!meson_crtc->enabled)
+               meson_crtc_enable(crtc);
+
        priv->viu.osd1_enabled = true;
 }
 
@@ -110,6 +126,8 @@ static void meson_crtc_atomic_disable(struct drm_crtc *crtc,
        struct meson_crtc *meson_crtc = to_meson_crtc(crtc);
        struct meson_drm *priv = meson_crtc->priv;
 
+       drm_crtc_vblank_off(crtc);
+
        priv->viu.osd1_enabled = false;
        priv->viu.osd1_commit = false;
 
@@ -124,6 +142,8 @@ static void meson_crtc_atomic_disable(struct drm_crtc *crtc,
 
                crtc->state->event = NULL;
        }
+
+       meson_crtc->enabled = false;
 }
 
 static void meson_crtc_atomic_begin(struct drm_crtc *crtc,
@@ -132,6 +152,9 @@ static void meson_crtc_atomic_begin(struct drm_crtc *crtc,
        struct meson_crtc *meson_crtc = to_meson_crtc(crtc);
        unsigned long flags;
 
+       if (crtc->state->enable && !meson_crtc->enabled)
+               meson_crtc_enable(crtc);
+
        if (crtc->state->event) {
                WARN_ON(drm_crtc_vblank_get(crtc) != 0);
 
index df7247c..2cb2ad2 100644 (file)
@@ -706,6 +706,7 @@ static const struct regmap_config meson_dw_hdmi_regmap_config = {
        .reg_read = meson_dw_hdmi_reg_read,
        .reg_write = meson_dw_hdmi_reg_write,
        .max_register = 0x10000,
+       .fast_io = true,
 };
 
 static bool meson_hdmi_connector_is_available(struct device *dev)
index acbbad3..be76f3d 100644 (file)
@@ -71,6 +71,7 @@
  */
 
 /* HHI Registers */
+#define HHI_GCLK_MPEG2         0x148 /* 0x52 offset in data sheet */
 #define HHI_VDAC_CNTL0         0x2F4 /* 0xbd offset in data sheet */
 #define HHI_VDAC_CNTL1         0x2F8 /* 0xbe offset in data sheet */
 #define HHI_HDMI_PHY_CNTL0     0x3a0 /* 0xe8 offset in data sheet */
@@ -714,6 +715,7 @@ struct meson_hdmi_venc_vic_mode {
        { 5, &meson_hdmi_encp_mode_1080i60 },
        { 20, &meson_hdmi_encp_mode_1080i50 },
        { 32, &meson_hdmi_encp_mode_1080p24 },
+       { 33, &meson_hdmi_encp_mode_1080p50 },
        { 34, &meson_hdmi_encp_mode_1080p30 },
        { 31, &meson_hdmi_encp_mode_1080p50 },
        { 16, &meson_hdmi_encp_mode_1080p60 },
@@ -1530,10 +1532,12 @@ unsigned int meson_venci_get_field(struct meson_drm *priv)
 void meson_venc_enable_vsync(struct meson_drm *priv)
 {
        writel_relaxed(2, priv->io_base + _REG(VENC_INTCTRL));
+       regmap_update_bits(priv->hhi, HHI_GCLK_MPEG2, BIT(25), BIT(25));
 }
 
 void meson_venc_disable_vsync(struct meson_drm *priv)
 {
+       regmap_update_bits(priv->hhi, HHI_GCLK_MPEG2, BIT(25), 0);
        writel_relaxed(0, priv->io_base + _REG(VENC_INTCTRL));
 }
 
index 6bcfa52..26a0857 100644 (file)
@@ -184,18 +184,18 @@ void meson_viu_set_osd_lut(struct meson_drm *priv, enum viu_lut_sel_e lut_sel,
        if (lut_sel == VIU_LUT_OSD_OETF) {
                writel(0, priv->io_base + _REG(addr_port));
 
-               for (i = 0; i < 20; i++)
+               for (i = 0; i < (OSD_OETF_LUT_SIZE / 2); i++)
                        writel(r_map[i * 2] | (r_map[i * 2 + 1] << 16),
                                priv->io_base + _REG(data_port));
 
                writel(r_map[OSD_OETF_LUT_SIZE - 1] | (g_map[0] << 16),
                        priv->io_base + _REG(data_port));
 
-               for (i = 0; i < 20; i++)
+               for (i = 0; i < (OSD_OETF_LUT_SIZE / 2); i++)
                        writel(g_map[i * 2 + 1] | (g_map[i * 2 + 2] << 16),
                                priv->io_base + _REG(data_port));
 
-               for (i = 0; i < 20; i++)
+               for (i = 0; i < (OSD_OETF_LUT_SIZE / 2); i++)
                        writel(b_map[i * 2] | (b_map[i * 2 + 1] << 16),
                                priv->io_base + _REG(data_port));
 
@@ -211,18 +211,18 @@ void meson_viu_set_osd_lut(struct meson_drm *priv, enum viu_lut_sel_e lut_sel,
        } else if (lut_sel == VIU_LUT_OSD_EOTF) {
                writel(0, priv->io_base + _REG(addr_port));
 
-               for (i = 0; i < 20; i++)
+               for (i = 0; i < (OSD_EOTF_LUT_SIZE / 2); i++)
                        writel(r_map[i * 2] | (r_map[i * 2 + 1] << 16),
                                priv->io_base + _REG(data_port));
 
                writel(r_map[OSD_EOTF_LUT_SIZE - 1] | (g_map[0] << 16),
                        priv->io_base + _REG(data_port));
 
-               for (i = 0; i < 20; i++)
+               for (i = 0; i < (OSD_EOTF_LUT_SIZE / 2); i++)
                        writel(g_map[i * 2 + 1] | (g_map[i * 2 + 2] << 16),
                                priv->io_base + _REG(data_port));
 
-               for (i = 0; i < 20; i++)
+               for (i = 0; i < (OSD_EOTF_LUT_SIZE / 2); i++)
                        writel(b_map[i * 2] | (b_map[i * 2 + 1] << 16),
                                priv->io_base + _REG(data_port));
 
index d85f0a1..cebf313 100644 (file)
@@ -202,10 +202,25 @@ void rcar_du_group_put(struct rcar_du_group *rgrp)
 
 static void __rcar_du_group_start_stop(struct rcar_du_group *rgrp, bool start)
 {
-       struct rcar_du_crtc *rcrtc = &rgrp->dev->crtcs[rgrp->index * 2];
+       struct rcar_du_device *rcdu = rgrp->dev;
+
+       /*
+        * Group start/stop is controlled by the DRES and DEN bits of DSYSR0
+        * for the first group and DSYSR2 for the second group. On most DU
+        * instances, this maps to the first CRTC of the group, and we can just
+        * use rcar_du_crtc_dsysr_clr_set() to access the correct DSYSR. On
+        * M3-N, however, DU2 doesn't exist, but DSYSR2 does. We thus need to
+        * access the register directly using group read/write.
+        */
+       if (rcdu->info->channels_mask & BIT(rgrp->index * 2)) {
+               struct rcar_du_crtc *rcrtc = &rgrp->dev->crtcs[rgrp->index * 2];
 
-       rcar_du_crtc_dsysr_clr_set(rcrtc, DSYSR_DRES | DSYSR_DEN,
-                                  start ? DSYSR_DEN : DSYSR_DRES);
+               rcar_du_crtc_dsysr_clr_set(rcrtc, DSYSR_DRES | DSYSR_DEN,
+                                          start ? DSYSR_DEN : DSYSR_DRES);
+       } else {
+               rcar_du_group_write(rgrp, DSYSR,
+                                   start ? DSYSR_DEN : DSYSR_DRES);
+       }
 }
 
 void rcar_du_group_start_stop(struct rcar_du_group *rgrp, bool start)
index e8a1141..bb012bc 100644 (file)
@@ -358,7 +358,7 @@ static ssize_t show_value(struct device *dev, struct device_attribute *attr,
                                                sensor_inst->hsdev,
                                                sensor_inst->hsdev->usage,
                                                usage, report_id,
-                                               SENSOR_HUB_SYNC);
+                                               SENSOR_HUB_SYNC, false);
        } else if (!strncmp(name, "units", strlen("units")))
                value = sensor_inst->fields[field_index].attribute.units;
        else if (!strncmp(name, "unit-expo", strlen("unit-expo")))
index 2b63487..4256fdc 100644 (file)
@@ -299,7 +299,8 @@ EXPORT_SYMBOL_GPL(sensor_hub_get_feature);
 int sensor_hub_input_attr_get_raw_value(struct hid_sensor_hub_device *hsdev,
                                        u32 usage_id,
                                        u32 attr_usage_id, u32 report_id,
-                                       enum sensor_hub_read_flags flag)
+                                       enum sensor_hub_read_flags flag,
+                                       bool is_signed)
 {
        struct sensor_hub_data *data = hid_get_drvdata(hsdev->hdev);
        unsigned long flags;
@@ -331,10 +332,16 @@ int sensor_hub_input_attr_get_raw_value(struct hid_sensor_hub_device *hsdev,
                                                &hsdev->pending.ready, HZ*5);
                switch (hsdev->pending.raw_size) {
                case 1:
-                       ret_val = *(u8 *)hsdev->pending.raw_data;
+                       if (is_signed)
+                               ret_val = *(s8 *)hsdev->pending.raw_data;
+                       else
+                               ret_val = *(u8 *)hsdev->pending.raw_data;
                        break;
                case 2:
-                       ret_val = *(u16 *)hsdev->pending.raw_data;
+                       if (is_signed)
+                               ret_val = *(s16 *)hsdev->pending.raw_data;
+                       else
+                               ret_val = *(u16 *)hsdev->pending.raw_data;
                        break;
                case 4:
                        ret_val = *(u32 *)hsdev->pending.raw_data;
index de8193f..fe00b12 100644 (file)
@@ -516,6 +516,14 @@ int vmbus_establish_gpadl(struct vmbus_channel *channel, void *kbuffer,
        }
        wait_for_completion(&msginfo->waitevent);
 
+       if (msginfo->response.gpadl_created.creation_status != 0) {
+               pr_err("Failed to establish GPADL: err = 0x%x\n",
+                      msginfo->response.gpadl_created.creation_status);
+
+               ret = -EDQUOT;
+               goto cleanup;
+       }
+
        if (channel->rescind) {
                ret = -ENODEV;
                goto cleanup;
index 71d3445..07ee195 100644 (file)
@@ -274,7 +274,7 @@ static int ina2xx_get_value(struct ina2xx_data *data, u8 reg,
                break;
        case INA2XX_CURRENT:
                /* signed register, result in mA */
-               val = regval * data->current_lsb_uA;
+               val = (s16)regval * data->current_lsb_uA;
                val = DIV_ROUND_CLOSEST(val, 1000);
                break;
        case INA2XX_CALIBRATION:
@@ -491,7 +491,7 @@ static int ina2xx_probe(struct i2c_client *client,
        }
 
        data->groups[group++] = &ina2xx_group;
-       if (id->driver_data == ina226)
+       if (chip == ina226)
                data->groups[group++] = &ina226_group;
 
        hwmon_dev = devm_hwmon_device_register_with_groups(dev, client->name,
@@ -500,7 +500,7 @@ static int ina2xx_probe(struct i2c_client *client,
                return PTR_ERR(hwmon_dev);
 
        dev_info(dev, "power monitor %s (Rshunt = %li uOhm)\n",
-                id->name, data->rshunt);
+                client->name, data->rshunt);
 
        return 0;
 }
index de46577..d8fa4be 100644 (file)
@@ -51,7 +51,7 @@
  */
 #define MLXREG_FAN_GET_RPM(rval, d, s) (DIV_ROUND_CLOSEST(15000000 * 100, \
                                         ((rval) + (s)) * (d)))
-#define MLXREG_FAN_GET_FAULT(val, mask) (!!((val) ^ (mask)))
+#define MLXREG_FAN_GET_FAULT(val, mask) (!((val) ^ (mask)))
 #define MLXREG_FAN_PWM_DUTY2STATE(duty)        (DIV_ROUND_CLOSEST((duty) *     \
                                         MLXREG_FAN_MAX_STATE,          \
                                         MLXREG_FAN_MAX_DUTY))
index be5ba46..0d04572 100644 (file)
@@ -115,7 +115,6 @@ static int rpi_hwmon_probe(struct platform_device *pdev)
 {
        struct device *dev = &pdev->dev;
        struct rpi_hwmon_data *data;
-       int ret;
 
        data = devm_kzalloc(dev, sizeof(*data), GFP_KERNEL);
        if (!data)
@@ -124,11 +123,6 @@ static int rpi_hwmon_probe(struct platform_device *pdev)
        /* Parent driver assure that firmware is correct */
        data->fw = dev_get_drvdata(dev->parent);
 
-       /* Init throttled */
-       ret = rpi_firmware_property(data->fw, RPI_FIRMWARE_GET_THROTTLED,
-                                   &data->last_throttled,
-                                   sizeof(data->last_throttled));
-
        data->hwmon_dev = devm_hwmon_device_register_with_info(dev, "rpi_volt",
                                                               data,
                                                               &rpi_chip_info,
index 49276bb..1bb80f9 100644 (file)
@@ -1691,7 +1691,7 @@ store_sf_setup(struct device *dev, struct device_attribute *attr,
  * somewhere else in the code
  */
 #define SENSOR_ATTR_TEMP(index) {                                      \
-       SENSOR_ATTR_2(temp##index##_type, S_IRUGO | (index < 4 ? S_IWUSR : 0), \
+       SENSOR_ATTR_2(temp##index##_type, S_IRUGO | (index < 5 ? S_IWUSR : 0), \
                show_temp_mode, store_temp_mode, NOT_USED, index - 1),  \
        SENSOR_ATTR_2(temp##index##_input, S_IRUGO, show_temp,          \
                NULL, TEMP_READ, index - 1),                            \
index 41d97fa..38ff374 100644 (file)
@@ -149,6 +149,7 @@ static int accel_3d_read_raw(struct iio_dev *indio_dev,
        int report_id = -1;
        u32 address;
        int ret_type;
+       s32 min;
        struct hid_sensor_hub_device *hsdev =
                                        accel_state->common_attributes.hsdev;
 
@@ -158,12 +159,14 @@ static int accel_3d_read_raw(struct iio_dev *indio_dev,
        case IIO_CHAN_INFO_RAW:
                hid_sensor_power_state(&accel_state->common_attributes, true);
                report_id = accel_state->accel[chan->scan_index].report_id;
+               min = accel_state->accel[chan->scan_index].logical_minimum;
                address = accel_3d_addresses[chan->scan_index];
                if (report_id >= 0)
                        *val = sensor_hub_input_attr_get_raw_value(
                                        accel_state->common_attributes.hsdev,
                                        hsdev->usage, address, report_id,
-                                       SENSOR_HUB_SYNC);
+                                       SENSOR_HUB_SYNC,
+                                       min < 0);
                else {
                        *val = 0;
                        hid_sensor_power_state(&accel_state->common_attributes,
index 36941e6..88e857c 100644 (file)
@@ -111,6 +111,7 @@ static int gyro_3d_read_raw(struct iio_dev *indio_dev,
        int report_id = -1;
        u32 address;
        int ret_type;
+       s32 min;
 
        *val = 0;
        *val2 = 0;
@@ -118,13 +119,15 @@ static int gyro_3d_read_raw(struct iio_dev *indio_dev,
        case IIO_CHAN_INFO_RAW:
                hid_sensor_power_state(&gyro_state->common_attributes, true);
                report_id = gyro_state->gyro[chan->scan_index].report_id;
+               min = gyro_state->gyro[chan->scan_index].logical_minimum;
                address = gyro_3d_addresses[chan->scan_index];
                if (report_id >= 0)
                        *val = sensor_hub_input_attr_get_raw_value(
                                        gyro_state->common_attributes.hsdev,
                                        HID_USAGE_SENSOR_GYRO_3D, address,
                                        report_id,
-                                       SENSOR_HUB_SYNC);
+                                       SENSOR_HUB_SYNC,
+                                       min < 0);
                else {
                        *val = 0;
                        hid_sensor_power_state(&gyro_state->common_attributes,
index beab6d6..4bc95f3 100644 (file)
@@ -75,7 +75,8 @@ static int humidity_read_raw(struct iio_dev *indio_dev,
                                HID_USAGE_SENSOR_HUMIDITY,
                                HID_USAGE_SENSOR_ATMOSPHERIC_HUMIDITY,
                                humid_st->humidity_attr.report_id,
-                               SENSOR_HUB_SYNC);
+                               SENSOR_HUB_SYNC,
+                               humid_st->humidity_attr.logical_minimum < 0);
                hid_sensor_power_state(&humid_st->common_attributes, false);
 
                return IIO_VAL_INT;
index 406caae..94f3325 100644 (file)
@@ -93,6 +93,7 @@ static int als_read_raw(struct iio_dev *indio_dev,
        int report_id = -1;
        u32 address;
        int ret_type;
+       s32 min;
 
        *val = 0;
        *val2 = 0;
@@ -102,8 +103,8 @@ static int als_read_raw(struct iio_dev *indio_dev,
                case  CHANNEL_SCAN_INDEX_INTENSITY:
                case  CHANNEL_SCAN_INDEX_ILLUM:
                        report_id = als_state->als_illum.report_id;
-                       address =
-                       HID_USAGE_SENSOR_LIGHT_ILLUM;
+                       min = als_state->als_illum.logical_minimum;
+                       address = HID_USAGE_SENSOR_LIGHT_ILLUM;
                        break;
                default:
                        report_id = -1;
@@ -116,7 +117,8 @@ static int als_read_raw(struct iio_dev *indio_dev,
                                        als_state->common_attributes.hsdev,
                                        HID_USAGE_SENSOR_ALS, address,
                                        report_id,
-                                       SENSOR_HUB_SYNC);
+                                       SENSOR_HUB_SYNC,
+                                       min < 0);
                        hid_sensor_power_state(&als_state->common_attributes,
                                                false);
                } else {
index 45107f7..cf5a0c2 100644 (file)
@@ -73,6 +73,7 @@ static int prox_read_raw(struct iio_dev *indio_dev,
        int report_id = -1;
        u32 address;
        int ret_type;
+       s32 min;
 
        *val = 0;
        *val2 = 0;
@@ -81,8 +82,8 @@ static int prox_read_raw(struct iio_dev *indio_dev,
                switch (chan->scan_index) {
                case  CHANNEL_SCAN_INDEX_PRESENCE:
                        report_id = prox_state->prox_attr.report_id;
-                       address =
-                       HID_USAGE_SENSOR_HUMAN_PRESENCE;
+                       min = prox_state->prox_attr.logical_minimum;
+                       address = HID_USAGE_SENSOR_HUMAN_PRESENCE;
                        break;
                default:
                        report_id = -1;
@@ -95,7 +96,8 @@ static int prox_read_raw(struct iio_dev *indio_dev,
                                prox_state->common_attributes.hsdev,
                                HID_USAGE_SENSOR_PROX, address,
                                report_id,
-                               SENSOR_HUB_SYNC);
+                               SENSOR_HUB_SYNC,
+                               min < 0);
                        hid_sensor_power_state(&prox_state->common_attributes,
                                                false);
                } else {
index d55c488..f3c0d41 100644 (file)
@@ -163,21 +163,23 @@ static int magn_3d_read_raw(struct iio_dev *indio_dev,
        int report_id = -1;
        u32 address;
        int ret_type;
+       s32 min;
 
        *val = 0;
        *val2 = 0;
        switch (mask) {
        case IIO_CHAN_INFO_RAW:
                hid_sensor_power_state(&magn_state->magn_flux_attributes, true);
-               report_id =
-                       magn_state->magn[chan->address].report_id;
+               report_id = magn_state->magn[chan->address].report_id;
+               min = magn_state->magn[chan->address].logical_minimum;
                address = magn_3d_addresses[chan->address];
                if (report_id >= 0)
                        *val = sensor_hub_input_attr_get_raw_value(
                                magn_state->magn_flux_attributes.hsdev,
                                HID_USAGE_SENSOR_COMPASS_3D, address,
                                report_id,
-                               SENSOR_HUB_SYNC);
+                               SENSOR_HUB_SYNC,
+                               min < 0);
                else {
                        *val = 0;
                        hid_sensor_power_state(
index 0a9e8fa..37ab305 100644 (file)
@@ -30,11 +30,6 @@ int st_magn_trig_set_state(struct iio_trigger *trig, bool state)
        return st_sensors_set_dataready_irq(indio_dev, state);
 }
 
-static int st_magn_buffer_preenable(struct iio_dev *indio_dev)
-{
-       return st_sensors_set_enable(indio_dev, true);
-}
-
 static int st_magn_buffer_postenable(struct iio_dev *indio_dev)
 {
        int err;
@@ -50,7 +45,7 @@ static int st_magn_buffer_postenable(struct iio_dev *indio_dev)
        if (err < 0)
                goto st_magn_buffer_postenable_error;
 
-       return err;
+       return st_sensors_set_enable(indio_dev, true);
 
 st_magn_buffer_postenable_error:
        kfree(mdata->buffer_data);
@@ -63,11 +58,11 @@ static int st_magn_buffer_predisable(struct iio_dev *indio_dev)
        int err;
        struct st_sensor_data *mdata = iio_priv(indio_dev);
 
-       err = iio_triggered_buffer_predisable(indio_dev);
+       err = st_sensors_set_enable(indio_dev, false);
        if (err < 0)
                goto st_magn_buffer_predisable_error;
 
-       err = st_sensors_set_enable(indio_dev, false);
+       err = iio_triggered_buffer_predisable(indio_dev);
 
 st_magn_buffer_predisable_error:
        kfree(mdata->buffer_data);
@@ -75,7 +70,6 @@ st_magn_buffer_predisable_error:
 }
 
 static const struct iio_buffer_setup_ops st_magn_buffer_setup_ops = {
-       .preenable = &st_magn_buffer_preenable,
        .postenable = &st_magn_buffer_postenable,
        .predisable = &st_magn_buffer_predisable,
 };
index 1e5451d..bdc5e45 100644 (file)
@@ -111,21 +111,23 @@ static int incl_3d_read_raw(struct iio_dev *indio_dev,
        int report_id = -1;
        u32 address;
        int ret_type;
+       s32 min;
 
        *val = 0;
        *val2 = 0;
        switch (mask) {
        case IIO_CHAN_INFO_RAW:
                hid_sensor_power_state(&incl_state->common_attributes, true);
-               report_id =
-                       incl_state->incl[chan->scan_index].report_id;
+               report_id = incl_state->incl[chan->scan_index].report_id;
+               min = incl_state->incl[chan->scan_index].logical_minimum;
                address = incl_3d_addresses[chan->scan_index];
                if (report_id >= 0)
                        *val = sensor_hub_input_attr_get_raw_value(
                                incl_state->common_attributes.hsdev,
                                HID_USAGE_SENSOR_INCLINOMETER_3D, address,
                                report_id,
-                               SENSOR_HUB_SYNC);
+                               SENSOR_HUB_SYNC,
+                               min < 0);
                else {
                        hid_sensor_power_state(&incl_state->common_attributes,
                                                false);
index 4c43791..d7b1c00 100644 (file)
@@ -77,6 +77,7 @@ static int press_read_raw(struct iio_dev *indio_dev,
        int report_id = -1;
        u32 address;
        int ret_type;
+       s32 min;
 
        *val = 0;
        *val2 = 0;
@@ -85,8 +86,8 @@ static int press_read_raw(struct iio_dev *indio_dev,
                switch (chan->scan_index) {
                case  CHANNEL_SCAN_INDEX_PRESSURE:
                        report_id = press_state->press_attr.report_id;
-                       address =
-                       HID_USAGE_SENSOR_ATMOSPHERIC_PRESSURE;
+                       min = press_state->press_attr.logical_minimum;
+                       address = HID_USAGE_SENSOR_ATMOSPHERIC_PRESSURE;
                        break;
                default:
                        report_id = -1;
@@ -99,7 +100,8 @@ static int press_read_raw(struct iio_dev *indio_dev,
                                press_state->common_attributes.hsdev,
                                HID_USAGE_SENSOR_PRESSURE, address,
                                report_id,
-                               SENSOR_HUB_SYNC);
+                               SENSOR_HUB_SYNC,
+                               min < 0);
                        hid_sensor_power_state(&press_state->common_attributes,
                                                false);
                } else {
index beaf6fd..b592fc4 100644 (file)
@@ -76,7 +76,8 @@ static int temperature_read_raw(struct iio_dev *indio_dev,
                        HID_USAGE_SENSOR_TEMPERATURE,
                        HID_USAGE_SENSOR_DATA_ENVIRONMENTAL_TEMPERATURE,
                        temp_st->temperature_attr.report_id,
-                       SENSOR_HUB_SYNC);
+                       SENSOR_HUB_SYNC,
+                       temp_st->temperature_attr.logical_minimum < 0);
                hid_sensor_power_state(
                                &temp_st->common_attributes,
                                false);
index ee36619..25d43c8 100644 (file)
@@ -767,8 +767,10 @@ static int netdevice_event(struct notifier_block *this, unsigned long event,
 
        case NETDEV_CHANGEADDR:
                cmds[0] = netdev_del_cmd;
-               cmds[1] = add_default_gid_cmd;
-               cmds[2] = add_cmd;
+               if (ndev->reg_state == NETREG_REGISTERED) {
+                       cmds[1] = add_default_gid_cmd;
+                       cmds[2] = add_cmd;
+               }
                break;
 
        case NETDEV_CHANGEUPPER:
index 2b4c5e7..676c1fd 100644 (file)
@@ -137,15 +137,6 @@ static void ib_umem_notifier_release(struct mmu_notifier *mn,
        up_read(&per_mm->umem_rwsem);
 }
 
-static int invalidate_page_trampoline(struct ib_umem_odp *item, u64 start,
-                                     u64 end, void *cookie)
-{
-       ib_umem_notifier_start_account(item);
-       item->umem.context->invalidate_range(item, start, start + PAGE_SIZE);
-       ib_umem_notifier_end_account(item);
-       return 0;
-}
-
 static int invalidate_range_start_trampoline(struct ib_umem_odp *item,
                                             u64 start, u64 end, void *cookie)
 {
@@ -553,12 +544,13 @@ out:
                put_page(page);
 
        if (remove_existing_mapping && umem->context->invalidate_range) {
-               invalidate_page_trampoline(
+               ib_umem_notifier_start_account(umem_odp);
+               umem->context->invalidate_range(
                        umem_odp,
-                       ib_umem_start(umem) + (page_index >> umem->page_shift),
-                       ib_umem_start(umem) + ((page_index + 1) >>
-                                              umem->page_shift),
-                       NULL);
+                       ib_umem_start(umem) + (page_index << umem->page_shift),
+                       ib_umem_start(umem) +
+                               ((page_index + 1) << umem->page_shift));
+               ib_umem_notifier_end_account(umem_odp);
                ret = -EAGAIN;
        }
 
index cf22826..77f095e 100644 (file)
@@ -1268,6 +1268,7 @@ static int bnxt_re_ib_reg(struct bnxt_re_dev *rdev)
        /* Registered a new RoCE device instance to netdev */
        rc = bnxt_re_register_netdev(rdev);
        if (rc) {
+               rtnl_unlock();
                pr_err("Failed to register with netedev: %#x\n", rc);
                return -EINVAL;
        }
@@ -1466,6 +1467,7 @@ static void bnxt_re_task(struct work_struct *work)
                                "Failed to register with IB: %#x", rc);
                        bnxt_re_remove_one(rdev);
                        bnxt_re_dev_unreg(rdev);
+                       goto exit;
                }
                break;
        case NETDEV_UP:
@@ -1489,6 +1491,7 @@ static void bnxt_re_task(struct work_struct *work)
        }
        smp_mb__before_atomic();
        atomic_dec(&rdev->sched_count);
+exit:
        kfree(re_work);
 }
 
index a4c62ae..3beb152 100644 (file)
@@ -1756,10 +1756,9 @@ static int hns_roce_v2_set_mac(struct hns_roce_dev *hr_dev, u8 phy_port,
        return hns_roce_cmq_send(hr_dev, &desc, 1);
 }
 
-static int hns_roce_v2_write_mtpt(void *mb_buf, struct hns_roce_mr *mr,
-                                 unsigned long mtpt_idx)
+static int set_mtpt_pbl(struct hns_roce_v2_mpt_entry *mpt_entry,
+                       struct hns_roce_mr *mr)
 {
-       struct hns_roce_v2_mpt_entry *mpt_entry;
        struct scatterlist *sg;
        u64 page_addr;
        u64 *pages;
@@ -1767,6 +1766,53 @@ static int hns_roce_v2_write_mtpt(void *mb_buf, struct hns_roce_mr *mr,
        int len;
        int entry;
 
+       mpt_entry->pbl_size = cpu_to_le32(mr->pbl_size);
+       mpt_entry->pbl_ba_l = cpu_to_le32(lower_32_bits(mr->pbl_ba >> 3));
+       roce_set_field(mpt_entry->byte_48_mode_ba,
+                      V2_MPT_BYTE_48_PBL_BA_H_M, V2_MPT_BYTE_48_PBL_BA_H_S,
+                      upper_32_bits(mr->pbl_ba >> 3));
+
+       pages = (u64 *)__get_free_page(GFP_KERNEL);
+       if (!pages)
+               return -ENOMEM;
+
+       i = 0;
+       for_each_sg(mr->umem->sg_head.sgl, sg, mr->umem->nmap, entry) {
+               len = sg_dma_len(sg) >> PAGE_SHIFT;
+               for (j = 0; j < len; ++j) {
+                       page_addr = sg_dma_address(sg) +
+                               (j << mr->umem->page_shift);
+                       pages[i] = page_addr >> 6;
+                       /* Record the first 2 entry directly to MTPT table */
+                       if (i >= HNS_ROCE_V2_MAX_INNER_MTPT_NUM - 1)
+                               goto found;
+                       i++;
+               }
+       }
+found:
+       mpt_entry->pa0_l = cpu_to_le32(lower_32_bits(pages[0]));
+       roce_set_field(mpt_entry->byte_56_pa0_h, V2_MPT_BYTE_56_PA0_H_M,
+                      V2_MPT_BYTE_56_PA0_H_S, upper_32_bits(pages[0]));
+
+       mpt_entry->pa1_l = cpu_to_le32(lower_32_bits(pages[1]));
+       roce_set_field(mpt_entry->byte_64_buf_pa1, V2_MPT_BYTE_64_PA1_H_M,
+                      V2_MPT_BYTE_64_PA1_H_S, upper_32_bits(pages[1]));
+       roce_set_field(mpt_entry->byte_64_buf_pa1,
+                      V2_MPT_BYTE_64_PBL_BUF_PG_SZ_M,
+                      V2_MPT_BYTE_64_PBL_BUF_PG_SZ_S,
+                      mr->pbl_buf_pg_sz + PG_SHIFT_OFFSET);
+
+       free_page((unsigned long)pages);
+
+       return 0;
+}
+
+static int hns_roce_v2_write_mtpt(void *mb_buf, struct hns_roce_mr *mr,
+                                 unsigned long mtpt_idx)
+{
+       struct hns_roce_v2_mpt_entry *mpt_entry;
+       int ret;
+
        mpt_entry = mb_buf;
        memset(mpt_entry, 0, sizeof(*mpt_entry));
 
@@ -1781,7 +1827,6 @@ static int hns_roce_v2_write_mtpt(void *mb_buf, struct hns_roce_mr *mr,
                       mr->pbl_ba_pg_sz + PG_SHIFT_OFFSET);
        roce_set_field(mpt_entry->byte_4_pd_hop_st, V2_MPT_BYTE_4_PD_M,
                       V2_MPT_BYTE_4_PD_S, mr->pd);
-       mpt_entry->byte_4_pd_hop_st = cpu_to_le32(mpt_entry->byte_4_pd_hop_st);
 
        roce_set_bit(mpt_entry->byte_8_mw_cnt_en, V2_MPT_BYTE_8_RA_EN_S, 0);
        roce_set_bit(mpt_entry->byte_8_mw_cnt_en, V2_MPT_BYTE_8_R_INV_EN_S, 1);
@@ -1796,13 +1841,11 @@ static int hns_roce_v2_write_mtpt(void *mb_buf, struct hns_roce_mr *mr,
                     (mr->access & IB_ACCESS_REMOTE_WRITE ? 1 : 0));
        roce_set_bit(mpt_entry->byte_8_mw_cnt_en, V2_MPT_BYTE_8_LW_EN_S,
                     (mr->access & IB_ACCESS_LOCAL_WRITE ? 1 : 0));
-       mpt_entry->byte_8_mw_cnt_en = cpu_to_le32(mpt_entry->byte_8_mw_cnt_en);
 
        roce_set_bit(mpt_entry->byte_12_mw_pa, V2_MPT_BYTE_12_PA_S,
                     mr->type == MR_TYPE_MR ? 0 : 1);
        roce_set_bit(mpt_entry->byte_12_mw_pa, V2_MPT_BYTE_12_INNER_PA_VLD_S,
                     1);
-       mpt_entry->byte_12_mw_pa = cpu_to_le32(mpt_entry->byte_12_mw_pa);
 
        mpt_entry->len_l = cpu_to_le32(lower_32_bits(mr->size));
        mpt_entry->len_h = cpu_to_le32(upper_32_bits(mr->size));
@@ -1813,53 +1856,9 @@ static int hns_roce_v2_write_mtpt(void *mb_buf, struct hns_roce_mr *mr,
        if (mr->type == MR_TYPE_DMA)
                return 0;
 
-       mpt_entry->pbl_size = cpu_to_le32(mr->pbl_size);
-
-       mpt_entry->pbl_ba_l = cpu_to_le32(lower_32_bits(mr->pbl_ba >> 3));
-       roce_set_field(mpt_entry->byte_48_mode_ba, V2_MPT_BYTE_48_PBL_BA_H_M,
-                      V2_MPT_BYTE_48_PBL_BA_H_S,
-                      upper_32_bits(mr->pbl_ba >> 3));
-       mpt_entry->byte_48_mode_ba = cpu_to_le32(mpt_entry->byte_48_mode_ba);
-
-       pages = (u64 *)__get_free_page(GFP_KERNEL);
-       if (!pages)
-               return -ENOMEM;
-
-       i = 0;
-       for_each_sg(mr->umem->sg_head.sgl, sg, mr->umem->nmap, entry) {
-               len = sg_dma_len(sg) >> PAGE_SHIFT;
-               for (j = 0; j < len; ++j) {
-                       page_addr = sg_dma_address(sg) +
-                                   (j << mr->umem->page_shift);
-                       pages[i] = page_addr >> 6;
-
-                       /* Record the first 2 entry directly to MTPT table */
-                       if (i >= HNS_ROCE_V2_MAX_INNER_MTPT_NUM - 1)
-                               goto found;
-                       i++;
-               }
-       }
-
-found:
-       mpt_entry->pa0_l = cpu_to_le32(lower_32_bits(pages[0]));
-       roce_set_field(mpt_entry->byte_56_pa0_h, V2_MPT_BYTE_56_PA0_H_M,
-                      V2_MPT_BYTE_56_PA0_H_S,
-                      upper_32_bits(pages[0]));
-       mpt_entry->byte_56_pa0_h = cpu_to_le32(mpt_entry->byte_56_pa0_h);
-
-       mpt_entry->pa1_l = cpu_to_le32(lower_32_bits(pages[1]));
-       roce_set_field(mpt_entry->byte_64_buf_pa1, V2_MPT_BYTE_64_PA1_H_M,
-                      V2_MPT_BYTE_64_PA1_H_S, upper_32_bits(pages[1]));
+       ret = set_mtpt_pbl(mpt_entry, mr);
 
-       free_page((unsigned long)pages);
-
-       roce_set_field(mpt_entry->byte_64_buf_pa1,
-                      V2_MPT_BYTE_64_PBL_BUF_PG_SZ_M,
-                      V2_MPT_BYTE_64_PBL_BUF_PG_SZ_S,
-                      mr->pbl_buf_pg_sz + PG_SHIFT_OFFSET);
-       mpt_entry->byte_64_buf_pa1 = cpu_to_le32(mpt_entry->byte_64_buf_pa1);
-
-       return 0;
+       return ret;
 }
 
 static int hns_roce_v2_rereg_write_mtpt(struct hns_roce_dev *hr_dev,
@@ -1868,6 +1867,7 @@ static int hns_roce_v2_rereg_write_mtpt(struct hns_roce_dev *hr_dev,
                                        u64 size, void *mb_buf)
 {
        struct hns_roce_v2_mpt_entry *mpt_entry = mb_buf;
+       int ret = 0;
 
        if (flags & IB_MR_REREG_PD) {
                roce_set_field(mpt_entry->byte_4_pd_hop_st, V2_MPT_BYTE_4_PD_M,
@@ -1880,14 +1880,14 @@ static int hns_roce_v2_rereg_write_mtpt(struct hns_roce_dev *hr_dev,
                             V2_MPT_BYTE_8_BIND_EN_S,
                             (mr_access_flags & IB_ACCESS_MW_BIND ? 1 : 0));
                roce_set_bit(mpt_entry->byte_8_mw_cnt_en,
-                          V2_MPT_BYTE_8_ATOMIC_EN_S,
-                          (mr_access_flags & IB_ACCESS_REMOTE_ATOMIC ? 1 : 0));
+                            V2_MPT_BYTE_8_ATOMIC_EN_S,
+                            mr_access_flags & IB_ACCESS_REMOTE_ATOMIC ? 1 : 0);
                roce_set_bit(mpt_entry->byte_8_mw_cnt_en, V2_MPT_BYTE_8_RR_EN_S,
-                            (mr_access_flags & IB_ACCESS_REMOTE_READ ? 1 : 0));
+                            mr_access_flags & IB_ACCESS_REMOTE_READ ? 1 : 0);
                roce_set_bit(mpt_entry->byte_8_mw_cnt_en, V2_MPT_BYTE_8_RW_EN_S,
-                           (mr_access_flags & IB_ACCESS_REMOTE_WRITE ? 1 : 0));
+                            mr_access_flags & IB_ACCESS_REMOTE_WRITE ? 1 : 0);
                roce_set_bit(mpt_entry->byte_8_mw_cnt_en, V2_MPT_BYTE_8_LW_EN_S,
-                            (mr_access_flags & IB_ACCESS_LOCAL_WRITE ? 1 : 0));
+                            mr_access_flags & IB_ACCESS_LOCAL_WRITE ? 1 : 0);
        }
 
        if (flags & IB_MR_REREG_TRANS) {
@@ -1896,21 +1896,13 @@ static int hns_roce_v2_rereg_write_mtpt(struct hns_roce_dev *hr_dev,
                mpt_entry->len_l = cpu_to_le32(lower_32_bits(size));
                mpt_entry->len_h = cpu_to_le32(upper_32_bits(size));
 
-               mpt_entry->pbl_size = cpu_to_le32(mr->pbl_size);
-               mpt_entry->pbl_ba_l =
-                               cpu_to_le32(lower_32_bits(mr->pbl_ba >> 3));
-               roce_set_field(mpt_entry->byte_48_mode_ba,
-                              V2_MPT_BYTE_48_PBL_BA_H_M,
-                              V2_MPT_BYTE_48_PBL_BA_H_S,
-                              upper_32_bits(mr->pbl_ba >> 3));
-               mpt_entry->byte_48_mode_ba =
-                               cpu_to_le32(mpt_entry->byte_48_mode_ba);
-
                mr->iova = iova;
                mr->size = size;
+
+               ret = set_mtpt_pbl(mpt_entry, mr);
        }
 
-       return 0;
+       return ret;
 }
 
 static int hns_roce_v2_frmr_write_mtpt(void *mb_buf, struct hns_roce_mr *mr)
index e9c4280..3569fda 100644 (file)
@@ -1094,31 +1094,26 @@ enum mlx5_ib_width {
        MLX5_IB_WIDTH_12X       = 1 << 4
 };
 
-static int translate_active_width(struct ib_device *ibdev, u8 active_width,
+static void translate_active_width(struct ib_device *ibdev, u8 active_width,
                                  u8 *ib_width)
 {
        struct mlx5_ib_dev *dev = to_mdev(ibdev);
-       int err = 0;
 
-       if (active_width & MLX5_IB_WIDTH_1X) {
+       if (active_width & MLX5_IB_WIDTH_1X)
                *ib_width = IB_WIDTH_1X;
-       } else if (active_width & MLX5_IB_WIDTH_2X) {
-               mlx5_ib_dbg(dev, "active_width %d is not supported by IB spec\n",
-                           (int)active_width);
-               err = -EINVAL;
-       } else if (active_width & MLX5_IB_WIDTH_4X) {
+       else if (active_width & MLX5_IB_WIDTH_4X)
                *ib_width = IB_WIDTH_4X;
-       } else if (active_width & MLX5_IB_WIDTH_8X) {
+       else if (active_width & MLX5_IB_WIDTH_8X)
                *ib_width = IB_WIDTH_8X;
-       } else if (active_width & MLX5_IB_WIDTH_12X) {
+       else if (active_width & MLX5_IB_WIDTH_12X)
                *ib_width = IB_WIDTH_12X;
-       else {
-               mlx5_ib_dbg(dev, "Invalid active_width %d\n",
+       else {
+               mlx5_ib_dbg(dev, "Invalid active_width %d, setting width to default value: 4x\n",
                            (int)active_width);
-               err = -EINVAL;
+               *ib_width = IB_WIDTH_4X;
        }
 
-       return err;
+       return;
 }
 
 static int mlx5_mtu_to_ib_mtu(int mtu)
@@ -1225,10 +1220,8 @@ static int mlx5_query_hca_port(struct ib_device *ibdev, u8 port,
        if (err)
                goto out;
 
-       err = translate_active_width(ibdev, ib_link_width_oper,
-                                    &props->active_width);
-       if (err)
-               goto out;
+       translate_active_width(ibdev, ib_link_width_oper, &props->active_width);
+
        err = mlx5_query_port_ib_proto_oper(mdev, &props->active_speed, port);
        if (err)
                goto out;
index b04eb67..2cc3d69 100644 (file)
@@ -674,6 +674,15 @@ next_mr:
                        goto srcu_unlock;
                }
 
+               if (!mr->umem->is_odp) {
+                       mlx5_ib_dbg(dev, "skipping non ODP MR (lkey=0x%06x) in page fault handler.\n",
+                                   key);
+                       if (bytes_mapped)
+                               *bytes_mapped += bcnt;
+                       ret = 0;
+                       goto srcu_unlock;
+               }
+
                ret = pagefault_mr(dev, mr, io_virt, bcnt, bytes_mapped);
                if (ret < 0)
                        goto srcu_unlock;
@@ -735,6 +744,7 @@ next_mr:
                        head = frame;
 
                        bcnt -= frame->bcnt;
+                       offset = 0;
                }
                break;
 
index 6841c0f..3747cc6 100644 (file)
@@ -2633,8 +2633,7 @@ static int to_mlx5_access_flags(struct mlx5_ib_qp *qp,
 
        if (access_flags & IB_ACCESS_REMOTE_READ)
                *hw_access_flags |= MLX5_QP_BIT_RRE;
-       if ((access_flags & IB_ACCESS_REMOTE_ATOMIC) &&
-           qp->ibqp.qp_type == IB_QPT_RC) {
+       if (access_flags & IB_ACCESS_REMOTE_ATOMIC) {
                int atomic_mode;
 
                atomic_mode = get_atomic_mode(dev, qp->ibqp.qp_type);
@@ -4678,17 +4677,18 @@ static int _mlx5_ib_post_send(struct ib_qp *ibqp, const struct ib_send_wr *wr,
                        goto out;
                }
 
-               if (wr->opcode == IB_WR_LOCAL_INV ||
-                   wr->opcode == IB_WR_REG_MR) {
+               if (wr->opcode == IB_WR_REG_MR) {
                        fence = dev->umr_fence;
                        next_fence = MLX5_FENCE_MODE_INITIATOR_SMALL;
-               } else if (wr->send_flags & IB_SEND_FENCE) {
-                       if (qp->next_fence)
-                               fence = MLX5_FENCE_MODE_SMALL_AND_FENCE;
-                       else
-                               fence = MLX5_FENCE_MODE_FENCE;
-               } else {
-                       fence = qp->next_fence;
+               } else  {
+                       if (wr->send_flags & IB_SEND_FENCE) {
+                               if (qp->next_fence)
+                                       fence = MLX5_FENCE_MODE_SMALL_AND_FENCE;
+                               else
+                                       fence = MLX5_FENCE_MODE_FENCE;
+                       } else {
+                               fence = qp->next_fence;
+                       }
                }
 
                switch (ibqp->qp_type) {
index 89ec0f6..084bb4b 100644 (file)
@@ -91,13 +91,15 @@ EXPORT_SYMBOL(rvt_check_ah);
  * rvt_create_ah - create an address handle
  * @pd: the protection domain
  * @ah_attr: the attributes of the AH
+ * @udata: pointer to user's input output buffer information.
  *
  * This may be called from interrupt context.
  *
  * Return: newly allocated ah
  */
 struct ib_ah *rvt_create_ah(struct ib_pd *pd,
-                           struct rdma_ah_attr *ah_attr)
+                           struct rdma_ah_attr *ah_attr,
+                           struct ib_udata *udata)
 {
        struct rvt_ah *ah;
        struct rvt_dev_info *dev = ib_to_rvt(pd->device);
index 16105af..25271b4 100644 (file)
@@ -51,7 +51,8 @@
 #include <rdma/rdma_vt.h>
 
 struct ib_ah *rvt_create_ah(struct ib_pd *pd,
-                           struct rdma_ah_attr *ah_attr);
+                           struct rdma_ah_attr *ah_attr,
+                           struct ib_udata *udata);
 int rvt_destroy_ah(struct ib_ah *ibah);
 int rvt_modify_ah(struct ib_ah *ibah, struct rdma_ah_attr *ah_attr);
 int rvt_query_ah(struct ib_ah *ibah, struct rdma_ah_attr *ah_attr);
index 946b623..4ff3d98 100644 (file)
@@ -1124,7 +1124,9 @@ u8 iser_check_task_pi_status(struct iscsi_iser_task *iser_task,
                                         IB_MR_CHECK_SIG_STATUS, &mr_status);
                if (ret) {
                        pr_err("ib_check_mr_status failed, ret %d\n", ret);
-                       goto err;
+                       /* Not a lot we can do, return ambiguous guard error */
+                       *sector = 0;
+                       return 0x1;
                }
 
                if (mr_status.fail_status & IB_MR_CHECK_SIG_STATUS) {
@@ -1152,9 +1154,6 @@ u8 iser_check_task_pi_status(struct iscsi_iser_task *iser_task,
        }
 
        return 0;
-err:
-       /* Not alot we can do here, return ambiguous guard error */
-       return 0x1;
 }
 
 void iser_err_comp(struct ib_wc *wc, const char *type)
index 0a19618..e4550e9 100644 (file)
@@ -105,7 +105,7 @@ static int __init dw_apb_ictl_init(struct device_node *np,
         * DW IP can be configured to allow 2-64 irqs. We can determine
         * the number of irqs supported by writing into enable register
         * and look for bits not set, as corresponding flip-flops will
-        * have been removed by sythesis tool.
+        * have been removed by synthesis tool.
         */
 
        /* mask and enable all interrupts */
index ced10c4..ba2a37a 100644 (file)
@@ -604,8 +604,8 @@ void gic_dist_save(struct gic_chip_data *gic)
 /*
  * Restores the GIC distributor registers during resume or when coming out of
  * idle.  Must be called before enabling interrupts.  If a level interrupt
- * that occured while the GIC was suspended is still present, it will be
- * handled normally, but any edge interrupts that occured will not be seen by
+ * that occurred while the GIC was suspended is still present, it will be
+ * handled normally, but any edge interrupts that occurred will not be seen by
  * the GIC and need to be handled by the platform-specific wakeup source.
  */
 void gic_dist_restore(struct gic_chip_data *gic)
@@ -899,7 +899,7 @@ void gic_migrate_target(unsigned int new_cpu_id)
        gic_cpu_map[cpu] = 1 << new_cpu_id;
 
        /*
-        * Find all the peripheral interrupts targetting the current
+        * Find all the peripheral interrupts targeting the current
         * CPU interface and migrate them to the new CPU interface.
         * We skip DIST_TARGET 0 to 7 as they are read-only.
         */
index 85234d4..4e2461b 100644 (file)
@@ -1,6 +1,6 @@
 // SPDX-License-Identifier: GPL-2.0
 /*
- * H8S interrupt contoller driver
+ * H8S interrupt controller driver
  *
  * Copyright 2015 Yoshinori Sato <ysato@users.sourceforge.jp>
  */
index c19766f..b623f30 100644 (file)
@@ -58,7 +58,7 @@ struct s3c_irq_data {
 };
 
 /*
- * Sructure holding the controller data
+ * Structure holding the controller data
  * @reg_pending                register holding pending irqs
  * @reg_intpnd         special register intpnd in main intc
  * @reg_mask           mask register
index c824329..0e4193c 100644 (file)
@@ -416,7 +416,7 @@ static int scif_create_remote_lookup(struct scif_dev *remote_dev,
                if (err)
                        goto error_window;
                err = scif_map_page(&window->num_pages_lookup.lookup[j],
-                                   vmalloc_dma_phys ?
+                                   vmalloc_num_pages ?
                                    vmalloc_to_page(&window->num_pages[i]) :
                                    virt_to_page(&window->num_pages[i]),
                                    remote_dev);
index 56cde38..044adf9 100644 (file)
@@ -27,7 +27,8 @@ int nanddev_bbt_init(struct nand_device *nand)
        unsigned int nwords = DIV_ROUND_UP(nblocks * bits_per_block,
                                           BITS_PER_LONG);
 
-       nand->bbt.cache = kzalloc(nwords, GFP_KERNEL);
+       nand->bbt.cache = kcalloc(nwords, sizeof(*nand->bbt.cache),
+                                 GFP_KERNEL);
        if (!nand->bbt.cache)
                return -ENOMEM;
 
index 93c9bc8..1fdd283 100644 (file)
@@ -2995,12 +2995,13 @@ static int spi_nor_init_non_uniform_erase_map(struct spi_nor *nor,
                                              const u32 *smpt)
 {
        struct spi_nor_erase_map *map = &nor->erase_map;
-       const struct spi_nor_erase_type *erase = map->erase_type;
+       struct spi_nor_erase_type *erase = map->erase_type;
        struct spi_nor_erase_region *region;
        u64 offset;
        u32 region_count;
        int i, j;
-       u8 erase_type, uniform_erase_type;
+       u8 uniform_erase_type, save_uniform_erase_type;
+       u8 erase_type, regions_erase_type;
 
        region_count = SMPT_MAP_REGION_COUNT(*smpt);
        /*
@@ -3014,6 +3015,7 @@ static int spi_nor_init_non_uniform_erase_map(struct spi_nor *nor,
        map->regions = region;
 
        uniform_erase_type = 0xff;
+       regions_erase_type = 0;
        offset = 0;
        /* Populate regions. */
        for (i = 0; i < region_count; i++) {
@@ -3030,13 +3032,38 @@ static int spi_nor_init_non_uniform_erase_map(struct spi_nor *nor,
                 */
                uniform_erase_type &= erase_type;
 
+               /*
+                * regions_erase_type mask will indicate all the erase types
+                * supported in this configuration map.
+                */
+               regions_erase_type |= erase_type;
+
                offset = (region[i].offset & ~SNOR_ERASE_FLAGS_MASK) +
                         region[i].size;
        }
 
+       save_uniform_erase_type = map->uniform_erase_type;
        map->uniform_erase_type = spi_nor_sort_erase_mask(map,
                                                          uniform_erase_type);
 
+       if (!regions_erase_type) {
+               /*
+                * Roll back to the previous uniform_erase_type mask, SMPT is
+                * broken.
+                */
+               map->uniform_erase_type = save_uniform_erase_type;
+               return -EINVAL;
+       }
+
+       /*
+        * BFPT advertises all the erase types supported by all the possible
+        * map configurations. Mask out the erase types that are not supported
+        * by the current map configuration.
+        */
+       for (i = 0; i < SNOR_ERASE_TYPE_MAX; i++)
+               if (!(regions_erase_type & BIT(erase[i].idx)))
+                       spi_nor_set_erase_type(&erase[i], 0, 0xFF);
+
        spi_nor_region_mark_end(&region[i - 1]);
 
        return 0;
index 55af04f..6c8dcb6 100644 (file)
@@ -1441,6 +1441,9 @@ static void nic_remove(struct pci_dev *pdev)
 {
        struct nicpf *nic = pci_get_drvdata(pdev);
 
+       if (!nic)
+               return;
+
        if (nic->flags & NIC_SRIOV_ENABLED)
                pci_disable_sriov(pdev);
 
index be268dc..f9a4e76 100644 (file)
@@ -915,10 +915,8 @@ static int hip04_mac_probe(struct platform_device *pdev)
        }
 
        ret = register_netdev(ndev);
-       if (ret) {
-               free_netdev(ndev);
+       if (ret)
                goto alloc_fail;
-       }
 
        return 0;
 
index 21c2688..a3f4533 100644 (file)
@@ -1413,7 +1413,7 @@ void __i40e_del_filter(struct i40e_vsi *vsi, struct i40e_mac_filter *f)
        }
 
        vsi->flags |= I40E_VSI_FLAG_FILTER_CHANGED;
-       set_bit(__I40E_MACVLAN_SYNC_PENDING, vsi->state);
+       set_bit(__I40E_MACVLAN_SYNC_PENDING, vsi->back->state);
 }
 
 /**
index add1e45..433c8e6 100644 (file)
@@ -33,7 +33,7 @@ static int i40e_alloc_xsk_umems(struct i40e_vsi *vsi)
 }
 
 /**
- * i40e_add_xsk_umem - Store an UMEM for a certain ring/qid
+ * i40e_add_xsk_umem - Store a UMEM for a certain ring/qid
  * @vsi: Current VSI
  * @umem: UMEM to store
  * @qid: Ring/qid to associate with the UMEM
@@ -56,7 +56,7 @@ static int i40e_add_xsk_umem(struct i40e_vsi *vsi, struct xdp_umem *umem,
 }
 
 /**
- * i40e_remove_xsk_umem - Remove an UMEM for a certain ring/qid
+ * i40e_remove_xsk_umem - Remove a UMEM for a certain ring/qid
  * @vsi: Current VSI
  * @qid: Ring/qid associated with the UMEM
  **/
@@ -130,7 +130,7 @@ static void i40e_xsk_umem_dma_unmap(struct i40e_vsi *vsi, struct xdp_umem *umem)
 }
 
 /**
- * i40e_xsk_umem_enable - Enable/associate an UMEM to a certain ring/qid
+ * i40e_xsk_umem_enable - Enable/associate a UMEM to a certain ring/qid
  * @vsi: Current VSI
  * @umem: UMEM
  * @qid: Rx ring to associate UMEM to
@@ -189,7 +189,7 @@ static int i40e_xsk_umem_enable(struct i40e_vsi *vsi, struct xdp_umem *umem,
 }
 
 /**
- * i40e_xsk_umem_disable - Diassociate an UMEM from a certain ring/qid
+ * i40e_xsk_umem_disable - Disassociate a UMEM from a certain ring/qid
  * @vsi: Current VSI
  * @qid: Rx ring to associate UMEM to
  *
@@ -255,12 +255,12 @@ int i40e_xsk_umem_query(struct i40e_vsi *vsi, struct xdp_umem **umem,
 }
 
 /**
- * i40e_xsk_umem_query - Queries a certain ring/qid for its UMEM
+ * i40e_xsk_umem_setup - Enable/disassociate a UMEM to/from a ring/qid
  * @vsi: Current VSI
  * @umem: UMEM to enable/associate to a ring, or NULL to disable
  * @qid: Rx ring to (dis)associate UMEM (from)to
  *
- * This function enables or disables an UMEM to a certain ring.
+ * This function enables or disables a UMEM to a certain ring.
  *
  * Returns 0 on success, <0 on failure
  **/
@@ -276,7 +276,7 @@ int i40e_xsk_umem_setup(struct i40e_vsi *vsi, struct xdp_umem *umem,
  * @rx_ring: Rx ring
  * @xdp: xdp_buff used as input to the XDP program
  *
- * This function enables or disables an UMEM to a certain ring.
+ * This function enables or disables a UMEM to a certain ring.
  *
  * Returns any of I40E_XDP_{PASS, CONSUMED, TX, REDIR}
  **/
index c54ebed..c393cb2 100644 (file)
@@ -842,6 +842,7 @@ s32 igb_pll_workaround_i210(struct e1000_hw *hw)
                nvm_word = E1000_INVM_DEFAULT_AL;
        tmp_nvm = nvm_word | E1000_INVM_PLL_WO_VAL;
        igb_write_phy_reg_82580(hw, I347AT4_PAGE_SELECT, E1000_PHY_PLL_FREQ_PAGE);
+       phy_word = E1000_PHY_PLL_UNCONF;
        for (i = 0; i < E1000_MAX_PLL_TRIES; i++) {
                /* check current state directly from internal PHY */
                igb_read_phy_reg_82580(hw, E1000_PHY_PLL_FREQ_REG, &phy_word);
index 10dbaf4..9c42f74 100644 (file)
@@ -2262,7 +2262,9 @@ static s32 ixgbe_get_link_capabilities_X550em(struct ixgbe_hw *hw,
                *autoneg = false;
 
                if (hw->phy.sfp_type == ixgbe_sfp_type_1g_sx_core0 ||
-                   hw->phy.sfp_type == ixgbe_sfp_type_1g_sx_core1) {
+                   hw->phy.sfp_type == ixgbe_sfp_type_1g_sx_core1 ||
+                   hw->phy.sfp_type == ixgbe_sfp_type_1g_lx_core0 ||
+                   hw->phy.sfp_type == ixgbe_sfp_type_1g_lx_core1) {
                        *speed = IXGBE_LINK_SPEED_1GB_FULL;
                        return 0;
                }
index 867cddb..e8ca98c 100644 (file)
@@ -1672,7 +1672,7 @@ static int lan743x_tx_napi_poll(struct napi_struct *napi, int weight)
                netif_wake_queue(adapter->netdev);
        }
 
-       if (!napi_complete_done(napi, weight))
+       if (!napi_complete(napi))
                goto done;
 
        /* enable isr */
@@ -1681,7 +1681,7 @@ static int lan743x_tx_napi_poll(struct napi_struct *napi, int weight)
        lan743x_csr_read(adapter, INT_STS);
 
 done:
-       return weight;
+       return 0;
 }
 
 static void lan743x_tx_ring_cleanup(struct lan743x_tx *tx)
@@ -1870,9 +1870,9 @@ static int lan743x_tx_open(struct lan743x_tx *tx)
        tx->vector_flags = lan743x_intr_get_vector_flags(adapter,
                                                         INT_BIT_DMA_TX_
                                                         (tx->channel_number));
-       netif_napi_add(adapter->netdev,
-                      &tx->napi, lan743x_tx_napi_poll,
-                      tx->ring_size - 1);
+       netif_tx_napi_add(adapter->netdev,
+                         &tx->napi, lan743x_tx_napi_poll,
+                         tx->ring_size - 1);
        napi_enable(&tx->napi);
 
        data = 0;
@@ -3017,6 +3017,7 @@ static const struct dev_pm_ops lan743x_pm_ops = {
 
 static const struct pci_device_id lan743x_pcidev_tbl[] = {
        { PCI_DEVICE(PCI_VENDOR_ID_SMSC, PCI_DEVICE_ID_SMSC_LAN7430) },
+       { PCI_DEVICE(PCI_VENDOR_ID_SMSC, PCI_DEVICE_ID_SMSC_LAN7431) },
        { 0, }
 };
 
index 0e82b63..2d6eea1 100644 (file)
@@ -548,6 +548,7 @@ struct lan743x_adapter;
 /* SMSC acquired EFAR late 1990's, MCHP acquired SMSC 2012 */
 #define PCI_VENDOR_ID_SMSC             PCI_VENDOR_ID_EFAR
 #define PCI_DEVICE_ID_SMSC_LAN7430     (0x7430)
+#define PCI_DEVICE_ID_SMSC_LAN7431     (0x7431)
 
 #define PCI_CONFIG_LENGTH              (0x1000)
 
index 78a638e..979f1e4 100644 (file)
@@ -6071,7 +6071,7 @@ static const char * const s_igu_fifo_error_strs[] = {
        "no error",
        "length error",
        "function disabled",
-       "VF sent command to attnetion address",
+       "VF sent command to attention address",
        "host sent prod update command",
        "read of during interrupt register while in MIMD mode",
        "access to PXP BAR reserved address",
index ef9538e..8241269 100644 (file)
@@ -3605,7 +3605,7 @@ static const char velocity_gstrings[][ETH_GSTRING_LEN] = {
        "tx_jumbo",
        "rx_mac_control_frames",
        "tx_mac_control_frames",
-       "rx_frame_alignement_errors",
+       "rx_frame_alignment_errors",
        "rx_long_ok",
        "rx_long_err",
        "tx_sqe_errors",
index ab33d17..23ee396 100644 (file)
@@ -2197,6 +2197,14 @@ int phy_driver_register(struct phy_driver *new_driver, struct module *owner)
        new_driver->mdiodrv.driver.remove = phy_remove;
        new_driver->mdiodrv.driver.owner = owner;
 
+       /* The following works around an issue where the PHY driver doesn't bind
+        * to the device, resulting in the genphy driver being used instead of
+        * the dedicated driver. The root cause of the issue isn't known yet
+        * and seems to be in the base driver core. Once this is fixed we may
+        * remove this workaround.
+        */
+       new_driver->mdiodrv.driver.probe_type = PROBE_FORCE_SYNCHRONOUS;
+
        retval = driver_register(&new_driver->mdiodrv.driver);
        if (retval) {
                pr_err("%s: Error %d in registering driver\n",
index e9f101c..bfbb39f 100644 (file)
@@ -216,9 +216,9 @@ static int rionet_start_xmit(struct sk_buff *skb, struct net_device *ndev)
                         * it just report sending a packet to the target
                         * (without actual packet transfer).
                         */
-                       dev_kfree_skb_any(skb);
                        ndev->stats.tx_packets++;
                        ndev->stats.tx_bytes += skb->len;
+                       dev_kfree_skb_any(skb);
                }
        }
 
index 7275761..3d8a70d 100644 (file)
@@ -140,7 +140,6 @@ struct ipheth_device {
        struct usb_device *udev;
        struct usb_interface *intf;
        struct net_device *net;
-       struct sk_buff *tx_skb;
        struct urb *tx_urb;
        struct urb *rx_urb;
        unsigned char *tx_buf;
@@ -230,6 +229,7 @@ static void ipheth_rcvbulk_callback(struct urb *urb)
        case -ENOENT:
        case -ECONNRESET:
        case -ESHUTDOWN:
+       case -EPROTO:
                return;
        case 0:
                break;
@@ -281,7 +281,6 @@ static void ipheth_sndbulk_callback(struct urb *urb)
                dev_err(&dev->intf->dev, "%s: urb status: %d\n",
                __func__, status);
 
-       dev_kfree_skb_irq(dev->tx_skb);
        if (status == 0)
                netif_wake_queue(dev->net);
        else
@@ -423,7 +422,7 @@ static int ipheth_tx(struct sk_buff *skb, struct net_device *net)
        if (skb->len > IPHETH_BUF_SIZE) {
                WARN(1, "%s: skb too large: %d bytes\n", __func__, skb->len);
                dev->net->stats.tx_dropped++;
-               dev_kfree_skb_irq(skb);
+               dev_kfree_skb_any(skb);
                return NETDEV_TX_OK;
        }
 
@@ -443,12 +442,11 @@ static int ipheth_tx(struct sk_buff *skb, struct net_device *net)
                dev_err(&dev->intf->dev, "%s: usb_submit_urb: %d\n",
                        __func__, retval);
                dev->net->stats.tx_errors++;
-               dev_kfree_skb_irq(skb);
+               dev_kfree_skb_any(skb);
        } else {
-               dev->tx_skb = skb;
-
                dev->net->stats.tx_packets++;
                dev->net->stats.tx_bytes += skb->len;
+               dev_consume_skb_any(skb);
                netif_stop_queue(net);
        }
 
index 559d567..3cf1b77 100644 (file)
@@ -3314,6 +3314,9 @@ void nvme_remove_namespaces(struct nvme_ctrl *ctrl)
        struct nvme_ns *ns, *next;
        LIST_HEAD(ns_list);
 
+       /* prevent racing with ns scanning */
+       flush_work(&ctrl->scan_work);
+
        /*
         * The dead states indicates the controller was not gracefully
         * disconnected. In that case, we won't be able to flush any data while
@@ -3476,7 +3479,6 @@ void nvme_stop_ctrl(struct nvme_ctrl *ctrl)
        nvme_mpath_stop(ctrl);
        nvme_stop_keep_alive(ctrl);
        flush_work(&ctrl->async_event_work);
-       flush_work(&ctrl->scan_work);
        cancel_work_sync(&ctrl->fw_act_work);
        if (ctrl->ops->stop_ctrl)
                ctrl->ops->stop_ctrl(ctrl);
@@ -3585,7 +3587,7 @@ int nvme_init_ctrl(struct nvme_ctrl *ctrl, struct device *dev,
 
        return 0;
 out_free_name:
-       kfree_const(dev->kobj.name);
+       kfree_const(ctrl->device->kobj.name);
 out_release_instance:
        ida_simple_remove(&nvme_instance_ida, ctrl->instance);
 out:
@@ -3607,7 +3609,7 @@ void nvme_kill_queues(struct nvme_ctrl *ctrl)
        down_read(&ctrl->namespaces_rwsem);
 
        /* Forcibly unquiesce queues to avoid blocking dispatch */
-       if (ctrl->admin_q)
+       if (ctrl->admin_q && !blk_queue_dying(ctrl->admin_q))
                blk_mq_unquiesce_queue(ctrl->admin_q);
 
        list_for_each_entry(ns, &ctrl->namespaces, list)
index 54032c4..feb86b5 100644 (file)
@@ -1752,12 +1752,12 @@ nvme_fc_init_request(struct blk_mq_tag_set *set, struct request *rq,
        struct nvme_fc_queue *queue = &ctrl->queues[queue_idx];
        int res;
 
-       nvme_req(rq)->ctrl = &ctrl->ctrl;
        res = __nvme_fc_init_request(ctrl, queue, &op->op, rq, queue->rqcnt++);
        if (res)
                return res;
        op->op.fcp_req.first_sgl = &op->sgl[0];
        op->op.fcp_req.private = &op->priv[0];
+       nvme_req(rq)->ctrl = &ctrl->ctrl;
        return res;
 }
 
index cee79cb..081cbdc 100644 (file)
@@ -531,6 +531,9 @@ static inline void nvme_mpath_check_last_path(struct nvme_ns *ns)
 static inline int nvme_mpath_init(struct nvme_ctrl *ctrl,
                struct nvme_id_ctrl *id)
 {
+       if (ctrl->subsys->cmic & (1 << 3))
+               dev_warn(ctrl->device,
+"Please enable CONFIG_NVME_MULTIPATH for full support of multi-port devices.\n");
        return 0;
 }
 static inline void nvme_mpath_uninit(struct nvme_ctrl *ctrl)
index d181caf..ab6ec72 100644 (file)
@@ -184,6 +184,7 @@ static int nvme_rdma_alloc_qe(struct ib_device *ibdev, struct nvme_rdma_qe *qe,
        qe->dma = ib_dma_map_single(ibdev, qe->data, capsule_size, dir);
        if (ib_dma_mapping_error(ibdev, qe->dma)) {
                kfree(qe->data);
+               qe->data = NULL;
                return -ENOMEM;
        }
 
@@ -823,6 +824,7 @@ out_free_tagset:
 out_free_async_qe:
        nvme_rdma_free_qe(ctrl->device->dev, &ctrl->async_event_sqe,
                sizeof(struct nvme_command), DMA_TO_DEVICE);
+       ctrl->async_event_sqe.data = NULL;
 out_free_queue:
        nvme_rdma_free_queue(&ctrl->queues[0]);
        return error;
index 5a4b479..38a0880 100644 (file)
@@ -579,10 +579,8 @@ int dev_pm_opp_of_add_table_indexed(struct device *dev, int index)
                 */
                count = of_count_phandle_with_args(dev->of_node,
                                                   "operating-points-v2", NULL);
-               if (count != 1)
-                       return -ENODEV;
-
-               index = 0;
+               if (count == 1)
+                       index = 0;
        }
 
        opp_table = dev_pm_opp_get_opp_table_indexed(dev, index);
index 3f4fb4d..1c69c40 100644 (file)
@@ -417,7 +417,6 @@ static struct platform_driver ti_opp_supply_driver = {
        .probe = ti_opp_supply_probe,
        .driver = {
                   .name = "ti_opp_supply",
-                  .owner = THIS_MODULE,
                   .of_match_table = of_match_ptr(ti_opp_supply_of_match),
                   },
 };
index 2cbef2d..88af6bf 100644 (file)
@@ -81,8 +81,6 @@ struct imx6_pcie {
 #define PCIE_PL_PFLR_FORCE_LINK                        (1 << 15)
 #define PCIE_PHY_DEBUG_R0 (PL_OFFSET + 0x28)
 #define PCIE_PHY_DEBUG_R1 (PL_OFFSET + 0x2c)
-#define PCIE_PHY_DEBUG_R1_XMLH_LINK_IN_TRAINING        (1 << 29)
-#define PCIE_PHY_DEBUG_R1_XMLH_LINK_UP         (1 << 4)
 
 #define PCIE_PHY_CTRL (PL_OFFSET + 0x114)
 #define PCIE_PHY_CTRL_DATA_LOC 0
@@ -711,12 +709,6 @@ static int imx6_pcie_host_init(struct pcie_port *pp)
        return 0;
 }
 
-static int imx6_pcie_link_up(struct dw_pcie *pci)
-{
-       return dw_pcie_readl_dbi(pci, PCIE_PHY_DEBUG_R1) &
-                       PCIE_PHY_DEBUG_R1_XMLH_LINK_UP;
-}
-
 static const struct dw_pcie_host_ops imx6_pcie_host_ops = {
        .host_init = imx6_pcie_host_init,
 };
@@ -749,7 +741,7 @@ static int imx6_add_pcie_port(struct imx6_pcie *imx6_pcie,
 }
 
 static const struct dw_pcie_ops dw_pcie_ops = {
-       .link_up = imx6_pcie_link_up,
+       /* No special ops needed, but pcie-designware still expects this struct */
 };
 
 #ifdef CONFIG_PM_SLEEP
index 3724d3e..7aa9a82 100644 (file)
@@ -88,7 +88,7 @@ static void ls_pcie_disable_outbound_atus(struct ls_pcie *pcie)
        int i;
 
        for (i = 0; i < PCIE_IATU_NUM; i++)
-               dw_pcie_disable_atu(pcie->pci, DW_PCIE_REGION_OUTBOUND, i);
+               dw_pcie_disable_atu(pcie->pci, i, DW_PCIE_REGION_OUTBOUND);
 }
 
 static int ls1021_pcie_link_up(struct dw_pcie *pci)
index 1e7b022..de8635a 100644 (file)
@@ -440,7 +440,6 @@ int dw_pcie_ep_raise_msix_irq(struct dw_pcie_ep *ep, u8 func_no,
        tbl_offset = dw_pcie_readl_dbi(pci, reg);
        bir = (tbl_offset & PCI_MSIX_TABLE_BIR);
        tbl_offset &= PCI_MSIX_TABLE_OFFSET;
-       tbl_offset >>= 3;
 
        reg = PCI_BASE_ADDRESS_0 + (4 * bir);
        bar_addr_upper = 0;
index af24ed5..265ed3e 100644 (file)
@@ -1036,6 +1036,13 @@ static int __pci_enable_msi_range(struct pci_dev *dev, int minvec, int maxvec,
        if (maxvec < minvec)
                return -ERANGE;
 
+       /*
+        * If the caller is passing in sets, we can't support a range of
+        * vectors. The caller needs to handle that.
+        */
+       if (affd && affd->nr_sets && minvec != maxvec)
+               return -EINVAL;
+
        if (WARN_ON_ONCE(dev->msi_enabled))
                return -EINVAL;
 
@@ -1087,6 +1094,13 @@ static int __pci_enable_msix_range(struct pci_dev *dev,
        if (maxvec < minvec)
                return -ERANGE;
 
+       /*
+        * If the caller is passing in sets, we can't support a range of
+        * supported vectors. The caller needs to handle that.
+        */
+       if (affd && affd->nr_sets && minvec != maxvec)
+               return -EINVAL;
+
        if (WARN_ON_ONCE(dev->msix_enabled))
                return -EINVAL;
 
index d068f11..c9d8e3c 100644 (file)
@@ -5556,9 +5556,13 @@ enum pci_bus_speed pcie_get_speed_cap(struct pci_dev *dev)
        u32 lnkcap2, lnkcap;
 
        /*
-        * PCIe r4.0 sec 7.5.3.18 recommends using the Supported Link
-        * Speeds Vector in Link Capabilities 2 when supported, falling
-        * back to Max Link Speed in Link Capabilities otherwise.
+        * Link Capabilities 2 was added in PCIe r3.0, sec 7.8.18.  The
+        * implementation note there recommends using the Supported Link
+        * Speeds Vector in Link Capabilities 2 when supported.
+        *
+        * Without Link Capabilities 2, i.e., prior to PCIe r3.0, software
+        * should use the Supported Link Speeds field in Link Capabilities,
+        * where only 2.5 GT/s and 5.0 GT/s speeds were defined.
         */
        pcie_capability_read_dword(dev, PCI_EXP_LNKCAP2, &lnkcap2);
        if (lnkcap2) { /* PCIe r3.0-compliant */
@@ -5574,16 +5578,10 @@ enum pci_bus_speed pcie_get_speed_cap(struct pci_dev *dev)
        }
 
        pcie_capability_read_dword(dev, PCI_EXP_LNKCAP, &lnkcap);
-       if (lnkcap) {
-               if (lnkcap & PCI_EXP_LNKCAP_SLS_16_0GB)
-                       return PCIE_SPEED_16_0GT;
-               else if (lnkcap & PCI_EXP_LNKCAP_SLS_8_0GB)
-                       return PCIE_SPEED_8_0GT;
-               else if (lnkcap & PCI_EXP_LNKCAP_SLS_5_0GB)
-                       return PCIE_SPEED_5_0GT;
-               else if (lnkcap & PCI_EXP_LNKCAP_SLS_2_5GB)
-                       return PCIE_SPEED_2_5GT;
-       }
+       if ((lnkcap & PCI_EXP_LNKCAP_SLS) == PCI_EXP_LNKCAP_SLS_5_0GB)
+               return PCIE_SPEED_5_0GT;
+       else if ((lnkcap & PCI_EXP_LNKCAP_SLS) == PCI_EXP_LNKCAP_SLS_2_5GB)
+               return PCIE_SPEED_2_5GT;
 
        return PCI_SPEED_UNKNOWN;
 }
index 9ce5311..6d4b44b 100644 (file)
@@ -231,6 +231,7 @@ static const struct qusb2_phy_cfg sdm845_phy_cfg = {
        .mask_core_ready = CORE_READY_STATUS,
        .has_pll_override = true,
        .autoresume_en    = BIT(0),
+       .update_tune1_with_efuse = true,
 };
 
 static const char * const qusb2_phy_vreg_names[] = {
@@ -402,10 +403,10 @@ static void qusb2_phy_set_tune2_param(struct qusb2_phy *qphy)
 
        /*
         * Read efuse register having TUNE2/1 parameter's high nibble.
-        * If efuse register shows value as 0x0, or if we fail to find
-        * a valid efuse register settings, then use default value
-        * as 0xB for high nibble that we have already set while
-        * configuring phy.
+        * If efuse register shows value as 0x0 (indicating value is not
+        * fused), or if we fail to find a valid efuse register setting,
+        * then use default value for high nibble that we have already
+        * set while configuring the phy.
         */
        val = nvmem_cell_read(qphy->cell, NULL);
        if (IS_ERR(val) || !val[0]) {
@@ -415,12 +416,13 @@ static void qusb2_phy_set_tune2_param(struct qusb2_phy *qphy)
 
        /* Fused TUNE1/2 value is the higher nibble only */
        if (cfg->update_tune1_with_efuse)
-               qusb2_setbits(qphy->base, cfg->regs[QUSB2PHY_PORT_TUNE1],
-                             val[0] << 0x4);
+               qusb2_write_mask(qphy->base, cfg->regs[QUSB2PHY_PORT_TUNE1],
+                                val[0] << HSTX_TRIM_SHIFT,
+                                HSTX_TRIM_MASK);
        else
-               qusb2_setbits(qphy->base, cfg->regs[QUSB2PHY_PORT_TUNE2],
-                             val[0] << 0x4);
-
+               qusb2_write_mask(qphy->base, cfg->regs[QUSB2PHY_PORT_TUNE2],
+                                val[0] << HSTX_TRIM_SHIFT,
+                                HSTX_TRIM_MASK);
 }
 
 static int qusb2_phy_set_mode(struct phy *phy, enum phy_mode mode)
index 467e814..9c85231 100644 (file)
@@ -26,7 +26,8 @@ config PHY_UNIPHIER_USB3
 
 config PHY_UNIPHIER_PCIE
        tristate "Uniphier PHY driver for PCIe controller"
-       depends on (ARCH_UNIPHIER || COMPILE_TEST) && OF
+       depends on ARCH_UNIPHIER || COMPILE_TEST
+       depends on OF && HAS_IOMEM
        default PCIE_UNIPHIER
        select GENERIC_PHY
        help
index 2751dba..3e1abb4 100644 (file)
@@ -213,7 +213,7 @@ static int hid_rtc_read_time(struct device *dev, struct rtc_time *tm)
        /* get a report with all values through requesting one value */
        sensor_hub_input_attr_get_raw_value(time_state->common_attributes.hsdev,
                        HID_USAGE_SENSOR_TIME, hid_time_addresses[0],
-                       time_state->info[0].report_id, SENSOR_HUB_SYNC);
+                       time_state->info[0].report_id, SENSOR_HUB_SYNC, false);
        /* wait for all values (event) */
        ret = wait_for_completion_killable_timeout(
                        &time_state->comp_last_time, HZ*6);
index fd77e46..70a006b 100644 (file)
@@ -387,8 +387,10 @@ static int ccwchain_calc_length(u64 iova, struct channel_program *cp)
                 * orb specified one of the unsupported formats, we defer
                 * checking for IDAWs in unsupported formats to here.
                 */
-               if ((!cp->orb.cmd.c64 || cp->orb.cmd.i2k) && ccw_is_idal(ccw))
+               if ((!cp->orb.cmd.c64 || cp->orb.cmd.i2k) && ccw_is_idal(ccw)) {
+                       kfree(p);
                        return -EOPNOTSUPP;
+               }
 
                if ((!ccw_is_chain(ccw)) && (!ccw_is_tic(ccw)))
                        break;
@@ -528,7 +530,7 @@ static int ccwchain_fetch_direct(struct ccwchain *chain,
 
        ret = pfn_array_alloc_pin(pat->pat_pa, cp->mdev, ccw->cda, ccw->count);
        if (ret < 0)
-               goto out_init;
+               goto out_unpin;
 
        /* Translate this direct ccw to a idal ccw. */
        idaws = kcalloc(ret, sizeof(*idaws), GFP_DMA | GFP_KERNEL);
index f47d16b..a10cec0 100644 (file)
@@ -22,7 +22,7 @@
 #include "vfio_ccw_private.h"
 
 struct workqueue_struct *vfio_ccw_work_q;
-struct kmem_cache *vfio_ccw_io_region;
+static struct kmem_cache *vfio_ccw_io_region;
 
 /*
  * Helpers
@@ -134,14 +134,14 @@ static int vfio_ccw_sch_probe(struct subchannel *sch)
        if (ret)
                goto out_free;
 
-       ret = vfio_ccw_mdev_reg(sch);
-       if (ret)
-               goto out_disable;
-
        INIT_WORK(&private->io_work, vfio_ccw_sch_io_todo);
        atomic_set(&private->avail, 1);
        private->state = VFIO_CCW_STATE_STANDBY;
 
+       ret = vfio_ccw_mdev_reg(sch);
+       if (ret)
+               goto out_disable;
+
        return 0;
 
 out_disable:
index 048665e..9f5a201 100644 (file)
@@ -775,6 +775,8 @@ static int ap_device_probe(struct device *dev)
                drvres = ap_drv->flags & AP_DRIVER_FLAG_DEFAULT;
                if (!!devres != !!drvres)
                        return -ENODEV;
+               /* (re-)init queue's state machine */
+               ap_queue_reinit_state(to_ap_queue(dev));
        }
 
        /* Add queue/card to list of active queues/cards */
@@ -807,6 +809,8 @@ static int ap_device_remove(struct device *dev)
        struct ap_device *ap_dev = to_ap_dev(dev);
        struct ap_driver *ap_drv = ap_dev->drv;
 
+       if (is_queue_dev(dev))
+               ap_queue_remove(to_ap_queue(dev));
        if (ap_drv->remove)
                ap_drv->remove(ap_dev);
 
@@ -1444,10 +1448,6 @@ static void ap_scan_bus(struct work_struct *unused)
                        aq->ap_dev.device.parent = &ac->ap_dev.device;
                        dev_set_name(&aq->ap_dev.device,
                                     "%02x.%04x", id, dom);
-                       /* Start with a device reset */
-                       spin_lock_bh(&aq->lock);
-                       ap_wait(ap_sm_event(aq, AP_EVENT_POLL));
-                       spin_unlock_bh(&aq->lock);
                        /* Register device */
                        rc = device_register(&aq->ap_dev.device);
                        if (rc) {
index 3eed1b3..bfc66e4 100644 (file)
@@ -254,6 +254,7 @@ struct ap_queue *ap_queue_create(ap_qid_t qid, int device_type);
 void ap_queue_remove(struct ap_queue *aq);
 void ap_queue_suspend(struct ap_device *ap_dev);
 void ap_queue_resume(struct ap_device *ap_dev);
+void ap_queue_reinit_state(struct ap_queue *aq);
 
 struct ap_card *ap_card_create(int id, int queue_depth, int raw_device_type,
                               int comp_device_type, unsigned int functions);
index 66f7334..0aa4b3c 100644 (file)
@@ -718,5 +718,20 @@ void ap_queue_remove(struct ap_queue *aq)
 {
        ap_flush_queue(aq);
        del_timer_sync(&aq->timeout);
+
+       /* reset with zero, also clears irq registration */
+       spin_lock_bh(&aq->lock);
+       ap_zapq(aq->qid);
+       aq->state = AP_STATE_BORKED;
+       spin_unlock_bh(&aq->lock);
 }
 EXPORT_SYMBOL(ap_queue_remove);
+
+void ap_queue_reinit_state(struct ap_queue *aq)
+{
+       spin_lock_bh(&aq->lock);
+       aq->state = AP_STATE_RESET_START;
+       ap_wait(ap_sm_event(aq, AP_EVENT_POLL));
+       spin_unlock_bh(&aq->lock);
+}
+EXPORT_SYMBOL(ap_queue_reinit_state);
index 146f54f..c50f3e8 100644 (file)
@@ -196,7 +196,6 @@ static void zcrypt_cex2a_queue_remove(struct ap_device *ap_dev)
        struct ap_queue *aq = to_ap_queue(&ap_dev->device);
        struct zcrypt_queue *zq = aq->private;
 
-       ap_queue_remove(aq);
        if (zq)
                zcrypt_queue_unregister(zq);
 }
index 546f676..35c7c66 100644 (file)
@@ -251,7 +251,6 @@ static void zcrypt_cex2c_queue_remove(struct ap_device *ap_dev)
        struct ap_queue *aq = to_ap_queue(&ap_dev->device);
        struct zcrypt_queue *zq = aq->private;
 
-       ap_queue_remove(aq);
        if (zq)
                zcrypt_queue_unregister(zq);
 }
index f9d4c6c..582ffa7 100644 (file)
@@ -275,7 +275,6 @@ static void zcrypt_cex4_queue_remove(struct ap_device *ap_dev)
        struct ap_queue *aq = to_ap_queue(&ap_dev->device);
        struct zcrypt_queue *zq = aq->private;
 
-       ap_queue_remove(aq);
        if (zq)
                zcrypt_queue_unregister(zq);
 }
index 4bce5ae..2540652 100644 (file)
@@ -4518,8 +4518,8 @@ static int qeth_snmp_command_cb(struct qeth_card *card,
 {
        struct qeth_ipa_cmd *cmd;
        struct qeth_arp_query_info *qinfo;
-       struct qeth_snmp_cmd *snmp;
        unsigned char *data;
+       void *snmp_data;
        __u16 data_len;
 
        QETH_CARD_TEXT(card, 3, "snpcmdcb");
@@ -4527,7 +4527,6 @@ static int qeth_snmp_command_cb(struct qeth_card *card,
        cmd = (struct qeth_ipa_cmd *) sdata;
        data = (unsigned char *)((char *)cmd - reply->offset);
        qinfo = (struct qeth_arp_query_info *) reply->param;
-       snmp = &cmd->data.setadapterparms.data.snmp;
 
        if (cmd->hdr.return_code) {
                QETH_CARD_TEXT_(card, 4, "scer1%x", cmd->hdr.return_code);
@@ -4540,10 +4539,15 @@ static int qeth_snmp_command_cb(struct qeth_card *card,
                return 0;
        }
        data_len = *((__u16 *)QETH_IPA_PDU_LEN_PDU1(data));
-       if (cmd->data.setadapterparms.hdr.seq_no == 1)
-               data_len -= (__u16)((char *)&snmp->data - (char *)cmd);
-       else
-               data_len -= (__u16)((char *)&snmp->request - (char *)cmd);
+       if (cmd->data.setadapterparms.hdr.seq_no == 1) {
+               snmp_data = &cmd->data.setadapterparms.data.snmp;
+               data_len -= offsetof(struct qeth_ipa_cmd,
+                                    data.setadapterparms.data.snmp);
+       } else {
+               snmp_data = &cmd->data.setadapterparms.data.snmp.request;
+               data_len -= offsetof(struct qeth_ipa_cmd,
+                                    data.setadapterparms.data.snmp.request);
+       }
 
        /* check if there is enough room in userspace */
        if ((qinfo->udata_len - qinfo->udata_offset) < data_len) {
@@ -4556,16 +4560,9 @@ static int qeth_snmp_command_cb(struct qeth_card *card,
        QETH_CARD_TEXT_(card, 4, "sseqn%i",
                cmd->data.setadapterparms.hdr.seq_no);
        /*copy entries to user buffer*/
-       if (cmd->data.setadapterparms.hdr.seq_no == 1) {
-               memcpy(qinfo->udata + qinfo->udata_offset,
-                      (char *)snmp,
-                      data_len + offsetof(struct qeth_snmp_cmd, data));
-               qinfo->udata_offset += offsetof(struct qeth_snmp_cmd, data);
-       } else {
-               memcpy(qinfo->udata + qinfo->udata_offset,
-                      (char *)&snmp->request, data_len);
-       }
+       memcpy(qinfo->udata + qinfo->udata_offset, snmp_data, data_len);
        qinfo->udata_offset += data_len;
+
        /* check if all replies received ... */
                QETH_CARD_TEXT_(card, 4, "srtot%i",
                               cmd->data.setadapterparms.hdr.used_total);
index 3dc3162..0c2867d 100644 (file)
@@ -522,11 +522,11 @@ static irqreturn_t mtk_spi_interrupt(int irq, void *dev_id)
                mdata->xfer_len = min(MTK_SPI_MAX_FIFO_SIZE, len);
                mtk_spi_setup_packet(master);
 
-               cnt = len / 4;
+               cnt = mdata->xfer_len / 4;
                iowrite32_rep(mdata->base + SPI_TX_DATA_REG,
                                trans->tx_buf + mdata->num_xfered, cnt);
 
-               remainder = len % 4;
+               remainder = mdata->xfer_len % 4;
                if (remainder > 0) {
                        reg_val = 0;
                        memcpy(&reg_val,
index f024c3f..2fd8881 100644 (file)
@@ -1540,13 +1540,26 @@ static int omap2_mcspi_remove(struct platform_device *pdev)
 /* work with hotplug and coldplug */
 MODULE_ALIAS("platform:omap2_mcspi");
 
-#ifdef CONFIG_SUSPEND
-static int omap2_mcspi_suspend_noirq(struct device *dev)
+static int __maybe_unused omap2_mcspi_suspend(struct device *dev)
 {
-       return pinctrl_pm_select_sleep_state(dev);
+       struct spi_master *master = dev_get_drvdata(dev);
+       struct omap2_mcspi *mcspi = spi_master_get_devdata(master);
+       int error;
+
+       error = pinctrl_pm_select_sleep_state(dev);
+       if (error)
+               dev_warn(mcspi->dev, "%s: failed to set pins: %i\n",
+                        __func__, error);
+
+       error = spi_master_suspend(master);
+       if (error)
+               dev_warn(mcspi->dev, "%s: master suspend failed: %i\n",
+                        __func__, error);
+
+       return pm_runtime_force_suspend(dev);
 }
 
-static int omap2_mcspi_resume_noirq(struct device *dev)
+static int __maybe_unused omap2_mcspi_resume(struct device *dev)
 {
        struct spi_master *master = dev_get_drvdata(dev);
        struct omap2_mcspi *mcspi = spi_master_get_devdata(master);
@@ -1557,17 +1570,17 @@ static int omap2_mcspi_resume_noirq(struct device *dev)
                dev_warn(mcspi->dev, "%s: failed to set pins: %i\n",
                         __func__, error);
 
-       return 0;
-}
+       error = spi_master_resume(master);
+       if (error)
+               dev_warn(mcspi->dev, "%s: master resume failed: %i\n",
+                        __func__, error);
 
-#else
-#define omap2_mcspi_suspend_noirq      NULL
-#define omap2_mcspi_resume_noirq       NULL
-#endif
+       return pm_runtime_force_resume(dev);
+}
 
 static const struct dev_pm_ops omap2_mcspi_pm_ops = {
-       .suspend_noirq = omap2_mcspi_suspend_noirq,
-       .resume_noirq = omap2_mcspi_resume_noirq,
+       SET_SYSTEM_SLEEP_PM_OPS(omap2_mcspi_suspend,
+                               omap2_mcspi_resume)
        .runtime_resume = omap_mcspi_runtime_resume,
 };
 
index e90b177..09a9400 100644 (file)
@@ -1005,35 +1005,38 @@ enum i8254_mode {
  * and INSN_DEVICE_CONFIG_GET_ROUTES.
  */
 #define NI_NAMES_BASE  0x8000u
+
+#define _TERM_N(base, n, x)    ((base) + ((x) & ((n) - 1)))
+
 /*
  * not necessarily all allowed 64 PFIs are valid--certainly not for all devices
  */
-#define NI_PFI(x)      (NI_NAMES_BASE        + ((x) & 0x3f))
+#define NI_PFI(x)              _TERM_N(NI_NAMES_BASE, 64, x)
 /* 8 trigger lines by standard, Some devices cannot talk to all eight. */
-#define TRIGGER_LINE(x)        (NI_PFI(-1)       + 1 + ((x) & 0x7))
+#define TRIGGER_LINE(x)                _TERM_N(NI_PFI(-1) + 1, 8, x)
 /* 4 RTSI shared MUXes to route signals to/from TRIGGER_LINES on NI hardware */
-#define NI_RTSI_BRD(x) (TRIGGER_LINE(-1) + 1 + ((x) & 0x3))
+#define NI_RTSI_BRD(x)         _TERM_N(TRIGGER_LINE(-1) + 1, 4, x)
 
 /* *** Counter/timer names : 8 counters max *** */
-#define NI_COUNTER_NAMES_BASE  (NI_RTSI_BRD(-1)  + 1)
-#define NI_MAX_COUNTERS               7
-#define NI_CtrSource(x)               (NI_COUNTER_NAMES_BASE + ((x) & NI_MAX_COUNTERS))
+#define NI_MAX_COUNTERS                8
+#define NI_COUNTER_NAMES_BASE  (NI_RTSI_BRD(-1)  + 1)
+#define NI_CtrSource(x)              _TERM_N(NI_COUNTER_NAMES_BASE, NI_MAX_COUNTERS, x)
 /* Gate, Aux, A,B,Z are all treated, at times as gates */
-#define NI_GATES_NAMES_BASE    (NI_CtrSource(-1) + 1)
-#define NI_CtrGate(x)         (NI_GATES_NAMES_BASE   + ((x) & NI_MAX_COUNTERS))
-#define NI_CtrAux(x)          (NI_CtrGate(-1)   + 1  + ((x) & NI_MAX_COUNTERS))
-#define NI_CtrA(x)            (NI_CtrAux(-1)    + 1  + ((x) & NI_MAX_COUNTERS))
-#define NI_CtrB(x)            (NI_CtrA(-1)      + 1  + ((x) & NI_MAX_COUNTERS))
-#define NI_CtrZ(x)            (NI_CtrB(-1)      + 1  + ((x) & NI_MAX_COUNTERS))
-#define NI_GATES_NAMES_MAX     NI_CtrZ(-1)
-#define NI_CtrArmStartTrigger(x) (NI_CtrZ(-1)    + 1  + ((x) & NI_MAX_COUNTERS))
+#define NI_GATES_NAMES_BASE    (NI_CtrSource(-1) + 1)
+#define NI_CtrGate(x)          _TERM_N(NI_GATES_NAMES_BASE, NI_MAX_COUNTERS, x)
+#define NI_CtrAux(x)           _TERM_N(NI_CtrGate(-1)  + 1, NI_MAX_COUNTERS, x)
+#define NI_CtrA(x)             _TERM_N(NI_CtrAux(-1)   + 1, NI_MAX_COUNTERS, x)
+#define NI_CtrB(x)             _TERM_N(NI_CtrA(-1)     + 1, NI_MAX_COUNTERS, x)
+#define NI_CtrZ(x)             _TERM_N(NI_CtrB(-1)     + 1, NI_MAX_COUNTERS, x)
+#define NI_GATES_NAMES_MAX     NI_CtrZ(-1)
+#define NI_CtrArmStartTrigger(x) _TERM_N(NI_CtrZ(-1)    + 1, NI_MAX_COUNTERS, x)
 #define NI_CtrInternalOutput(x) \
-                    (NI_CtrArmStartTrigger(-1)  + 1  + ((x) & NI_MAX_COUNTERS))
+                     _TERM_N(NI_CtrArmStartTrigger(-1) + 1, NI_MAX_COUNTERS, x)
 /** external pin(s) labeled conveniently as Ctr<i>Out. */
-#define NI_CtrOut(x)  (NI_CtrInternalOutput(-1)  + 1  + ((x) & NI_MAX_COUNTERS))
+#define NI_CtrOut(x)   _TERM_N(NI_CtrInternalOutput(-1) + 1, NI_MAX_COUNTERS, x)
 /** For Buffered sampling of ctr -- x series capability. */
-#define NI_CtrSampleClock(x)   (NI_CtrOut(-1)   + 1  + ((x) & NI_MAX_COUNTERS))
-#define NI_COUNTER_NAMES_MAX   NI_CtrSampleClock(-1)
+#define NI_CtrSampleClock(x)   _TERM_N(NI_CtrOut(-1)   + 1, NI_MAX_COUNTERS, x)
+#define NI_COUNTER_NAMES_MAX   NI_CtrSampleClock(-1)
 
 enum ni_common_signal_names {
        /* PXI_Star: this is a non-NI-specific signal */
index 2d1e032..5edf59a 100644 (file)
@@ -2843,7 +2843,8 @@ static int ni_ao_insn_config(struct comedi_device *dev,
                return ni_ao_arm(dev, s);
        case INSN_CONFIG_GET_CMD_TIMING_CONSTRAINTS:
                /* we don't care about actual channels */
-               data[1] = board->ao_speed;
+               /* data[3] : chanlist_len */
+               data[1] = board->ao_speed * data[3];
                data[2] = 0;
                return 0;
        default:
index dd121f6..c912c70 100644 (file)
@@ -108,17 +108,6 @@ static int cedrus_request_validate(struct media_request *req)
        unsigned int count;
        unsigned int i;
 
-       count = vb2_request_buffer_cnt(req);
-       if (!count) {
-               v4l2_info(&ctx->dev->v4l2_dev,
-                         "No buffer was provided with the request\n");
-               return -ENOENT;
-       } else if (count > 1) {
-               v4l2_info(&ctx->dev->v4l2_dev,
-                         "More than one buffer was provided with the request\n");
-               return -EINVAL;
-       }
-
        list_for_each_entry(obj, &req->objects, list) {
                struct vb2_buffer *vb;
 
@@ -133,6 +122,17 @@ static int cedrus_request_validate(struct media_request *req)
        if (!ctx)
                return -ENOENT;
 
+       count = vb2_request_buffer_cnt(req);
+       if (!count) {
+               v4l2_info(&ctx->dev->v4l2_dev,
+                         "No buffer was provided with the request\n");
+               return -ENOENT;
+       } else if (count > 1) {
+               v4l2_info(&ctx->dev->v4l2_dev,
+                         "More than one buffer was provided with the request\n");
+               return -EINVAL;
+       }
+
        parent_hdl = &ctx->hdl;
 
        hdl = v4l2_ctrl_request_hdl_find(req, parent_hdl);
index 6a18cf7..18936cd 100644 (file)
@@ -351,7 +351,7 @@ static ssize_t set_datatype_show(struct device *dev,
 
        for (i = 0; i < ARRAY_SIZE(ch_data_type); i++) {
                if (c->cfg.data_type & ch_data_type[i].most_ch_data_type)
-                       return snprintf(buf, PAGE_SIZE, ch_data_type[i].name);
+                       return snprintf(buf, PAGE_SIZE, "%s", ch_data_type[i].name);
        }
        return snprintf(buf, PAGE_SIZE, "unconfigured\n");
 }
index df6ebf4..5831f81 100644 (file)
@@ -335,6 +335,8 @@ static int mtk_hsdma_start_transfer(struct mtk_hsdam_engine *hsdma,
        /* tx desc */
        src = sg->src_addr;
        for (i = 0; i < chan->desc->num_sgs; i++) {
+               tx_desc = &chan->tx_ring[chan->tx_idx];
+
                if (len > HSDMA_MAX_PLEN)
                        tlen = HSDMA_MAX_PLEN;
                else
@@ -344,7 +346,6 @@ static int mtk_hsdma_start_transfer(struct mtk_hsdam_engine *hsdma,
                        tx_desc->addr1 = src;
                        tx_desc->flags |= HSDMA_DESC_PLEN1(tlen);
                } else {
-                       tx_desc = &chan->tx_ring[chan->tx_idx];
                        tx_desc->addr0 = src;
                        tx_desc->flags = HSDMA_DESC_PLEN0(tlen);
 
index b8566ed..aa98fbb 100644 (file)
@@ -82,7 +82,7 @@ static int rt2880_pinctrl_dt_node_to_map(struct pinctrl_dev *pctrldev,
        struct property *prop;
        const char *function_name, *group_name;
        int ret;
-       int ngroups;
+       int ngroups = 0;
        unsigned int reserved_maps = 0;
 
        for_each_node_with_property(np_config, "group")
index 8507794..85aba8a 100644 (file)
@@ -109,12 +109,12 @@ static void update_recvframe_phyinfo(union recv_frame *precvframe,
        rx_bssid = get_hdr_bssid(wlanhdr);
        pkt_info.bssid_match = ((!IsFrameTypeCtrl(wlanhdr)) &&
                                !pattrib->icv_err && !pattrib->crc_err &&
-                               !ether_addr_equal(rx_bssid, my_bssid));
+                               ether_addr_equal(rx_bssid, my_bssid));
 
        rx_ra = get_ra(wlanhdr);
        my_hwaddr = myid(&padapter->eeprompriv);
        pkt_info.to_self = pkt_info.bssid_match &&
-               !ether_addr_equal(rx_ra, my_hwaddr);
+               ether_addr_equal(rx_ra, my_hwaddr);
 
 
        pkt_info.is_beacon = pkt_info.bssid_match &&
index af22347..db553f2 100644 (file)
@@ -1277,7 +1277,7 @@ static int cfg80211_rtw_get_station(struct wiphy *wiphy,
 
                sinfo->filled |= BIT_ULL(NL80211_STA_INFO_TX_PACKETS);
                sinfo->tx_packets = psta->sta_stats.tx_pkts;
-
+               sinfo->filled |= BIT_ULL(NL80211_STA_INFO_TX_FAILED);
        }
 
        /* for Ad-Hoc/AP mode */
index 28bfdbd..b8631ba 100644 (file)
@@ -2289,7 +2289,7 @@ static int rtw_wx_read32(struct net_device *dev,
 exit:
        kfree(ptmp);
 
-       return 0;
+       return ret;
 }
 
 static int rtw_wx_write32(struct net_device *dev,
index ea78937..45de21c 100644 (file)
@@ -1795,6 +1795,7 @@ vchiq_compat_ioctl_await_completion(struct file *file,
        struct vchiq_await_completion32 args32;
        struct vchiq_completion_data32 completion32;
        unsigned int *msgbufcount32;
+       unsigned int msgbufcount_native;
        compat_uptr_t msgbuf32;
        void *msgbuf;
        void **msgbufptr;
@@ -1906,7 +1907,11 @@ vchiq_compat_ioctl_await_completion(struct file *file,
                         sizeof(completion32)))
                return -EFAULT;
 
-       args32.msgbufcount--;
+       if (get_user(msgbufcount_native, &args->msgbufcount))
+               return -EFAULT;
+
+       if (!msgbufcount_native)
+               args32.msgbufcount--;
 
        msgbufcount32 =
                &((struct vchiq_await_completion32 __user *)arg)->msgbufcount;
index 52ff854..cd96994 100644 (file)
@@ -863,6 +863,30 @@ static ssize_t key_store(struct device *dev, struct device_attribute *attr,
 }
 static DEVICE_ATTR(key, 0600, key_show, key_store);
 
+static void nvm_authenticate_start(struct tb_switch *sw)
+{
+       struct pci_dev *root_port;
+
+       /*
+        * During host router NVM upgrade we should not allow root port to
+        * go into D3cold because some root ports cannot trigger PME
+        * itself. To be on the safe side keep the root port in D0 during
+        * the whole upgrade process.
+        */
+       root_port = pci_find_pcie_root_port(sw->tb->nhi->pdev);
+       if (root_port)
+               pm_runtime_get_noresume(&root_port->dev);
+}
+
+static void nvm_authenticate_complete(struct tb_switch *sw)
+{
+       struct pci_dev *root_port;
+
+       root_port = pci_find_pcie_root_port(sw->tb->nhi->pdev);
+       if (root_port)
+               pm_runtime_put(&root_port->dev);
+}
+
 static ssize_t nvm_authenticate_show(struct device *dev,
        struct device_attribute *attr, char *buf)
 {
@@ -912,10 +936,18 @@ static ssize_t nvm_authenticate_store(struct device *dev,
 
                sw->nvm->authenticating = true;
 
-               if (!tb_route(sw))
+               if (!tb_route(sw)) {
+                       /*
+                        * Keep root port from suspending as long as the
+                        * NVM upgrade process is running.
+                        */
+                       nvm_authenticate_start(sw);
                        ret = nvm_authenticate_host(sw);
-               else
+                       if (ret)
+                               nvm_authenticate_complete(sw);
+               } else {
                        ret = nvm_authenticate_device(sw);
+               }
                pm_runtime_mark_last_busy(&sw->dev);
                pm_runtime_put_autosuspend(&sw->dev);
        }
@@ -1334,6 +1366,10 @@ static int tb_switch_add_dma_port(struct tb_switch *sw)
        if (ret <= 0)
                return ret;
 
+       /* Now we can allow root port to suspend again */
+       if (!tb_route(sw))
+               nvm_authenticate_complete(sw);
+
        if (status) {
                tb_sw_info(sw, "switch flash authentication failed\n");
                tb_switch_set_uuid(sw);
index f9ff03e..0690fcf 100644 (file)
@@ -209,6 +209,9 @@ static const struct usb_device_id usb_quirk_list[] = {
        /* Microsoft LifeCam-VX700 v2.0 */
        { USB_DEVICE(0x045e, 0x0770), .driver_info = USB_QUIRK_RESET_RESUME },
 
+       /* Cherry Stream G230 2.0 (G85-231) and 3.0 (G85-232) */
+       { USB_DEVICE(0x046a, 0x0023), .driver_info = USB_QUIRK_RESET_RESUME },
+
        /* Logitech HD Pro Webcams C920, C920-C, C925e and C930e */
        { USB_DEVICE(0x046d, 0x082d), .driver_info = USB_QUIRK_DELAY_INIT },
        { USB_DEVICE(0x046d, 0x0841), .driver_info = USB_QUIRK_DELAY_INIT },
index 9faad89..9f92ee0 100644 (file)
@@ -1470,9 +1470,6 @@ int __dwc3_gadget_ep_set_halt(struct dwc3_ep *dep, int value, int protocol)
                unsigned transfer_in_flight;
                unsigned started;
 
-               if (dep->flags & DWC3_EP_STALL)
-                       return 0;
-
                if (dep->number > 1)
                        trb = dwc3_ep_prev_trb(dep, dep->trb_enqueue);
                else
@@ -1494,8 +1491,6 @@ int __dwc3_gadget_ep_set_halt(struct dwc3_ep *dep, int value, int protocol)
                else
                        dep->flags |= DWC3_EP_STALL;
        } else {
-               if (!(dep->flags & DWC3_EP_STALL))
-                       return 0;
 
                ret = dwc3_send_clear_stall_ep_cmd(dep);
                if (ret)
index 1000d86..0f026d4 100644 (file)
@@ -401,12 +401,12 @@ done:
 static void rx_fill(struct eth_dev *dev, gfp_t gfp_flags)
 {
        struct usb_request      *req;
-       struct usb_request      *tmp;
        unsigned long           flags;
 
        /* fill unused rxq slots with some skb */
        spin_lock_irqsave(&dev->req_lock, flags);
-       list_for_each_entry_safe(req, tmp, &dev->rx_reqs, list) {
+       while (!list_empty(&dev->rx_reqs)) {
+               req = list_first_entry(&dev->rx_reqs, struct usb_request, list);
                list_del_init(&req->list);
                spin_unlock_irqrestore(&dev->req_lock, flags);
 
@@ -1125,7 +1125,6 @@ void gether_disconnect(struct gether *link)
 {
        struct eth_dev          *dev = link->ioport;
        struct usb_request      *req;
-       struct usb_request      *tmp;
 
        WARN_ON(!dev);
        if (!dev)
@@ -1142,7 +1141,8 @@ void gether_disconnect(struct gether *link)
         */
        usb_ep_disable(link->in_ep);
        spin_lock(&dev->req_lock);
-       list_for_each_entry_safe(req, tmp, &dev->tx_reqs, list) {
+       while (!list_empty(&dev->tx_reqs)) {
+               req = list_first_entry(&dev->tx_reqs, struct usb_request, list);
                list_del(&req->list);
 
                spin_unlock(&dev->req_lock);
@@ -1154,7 +1154,8 @@ void gether_disconnect(struct gether *link)
 
        usb_ep_disable(link->out_ep);
        spin_lock(&dev->req_lock);
-       list_for_each_entry_safe(req, tmp, &dev->rx_reqs, list) {
+       while (!list_empty(&dev->rx_reqs)) {
+               req = list_first_entry(&dev->rx_reqs, struct usb_request, list);
                list_del(&req->list);
 
                spin_unlock(&dev->req_lock);
index 3a16431..fcf13ef 100644 (file)
@@ -2033,6 +2033,7 @@ static inline int machine_without_vbus_sense(void)
 {
        return machine_is_omap_innovator()
                || machine_is_omap_osk()
+               || machine_is_omap_palmte()
                || machine_is_sx1()
                /* No known omap7xx boards with vbus sense */
                || cpu_is_omap7xx();
@@ -2041,7 +2042,7 @@ static inline int machine_without_vbus_sense(void)
 static int omap_udc_start(struct usb_gadget *g,
                struct usb_gadget_driver *driver)
 {
-       int             status = -ENODEV;
+       int             status;
        struct omap_ep  *ep;
        unsigned long   flags;
 
@@ -2079,6 +2080,7 @@ static int omap_udc_start(struct usb_gadget *g,
                        goto done;
                }
        } else {
+               status = 0;
                if (can_pullup(udc))
                        pullup_enable(udc);
                else
@@ -2593,9 +2595,22 @@ omap_ep_setup(char *name, u8 addr, u8 type,
 
 static void omap_udc_release(struct device *dev)
 {
-       complete(udc->done);
+       pullup_disable(udc);
+       if (!IS_ERR_OR_NULL(udc->transceiver)) {
+               usb_put_phy(udc->transceiver);
+               udc->transceiver = NULL;
+       }
+       omap_writew(0, UDC_SYSCON1);
+       remove_proc_file();
+       if (udc->dc_clk) {
+               if (udc->clk_requested)
+                       omap_udc_enable_clock(0);
+               clk_put(udc->hhc_clk);
+               clk_put(udc->dc_clk);
+       }
+       if (udc->done)
+               complete(udc->done);
        kfree(udc);
-       udc = NULL;
 }
 
 static int
@@ -2627,6 +2642,7 @@ omap_udc_setup(struct platform_device *odev, struct usb_phy *xceiv)
        udc->gadget.speed = USB_SPEED_UNKNOWN;
        udc->gadget.max_speed = USB_SPEED_FULL;
        udc->gadget.name = driver_name;
+       udc->gadget.quirk_ep_out_aligned_size = 1;
        udc->transceiver = xceiv;
 
        /* ep0 is special; put it right after the SETUP buffer */
@@ -2867,8 +2883,8 @@ bad_on_1710:
                udc->clr_halt = UDC_RESET_EP;
 
        /* USB general purpose IRQ:  ep0, state changes, dma, etc */
-       status = request_irq(pdev->resource[1].start, omap_udc_irq,
-                       0, driver_name, udc);
+       status = devm_request_irq(&pdev->dev, pdev->resource[1].start,
+                                 omap_udc_irq, 0, driver_name, udc);
        if (status != 0) {
                ERR("can't get irq %d, err %d\n",
                        (int) pdev->resource[1].start, status);
@@ -2876,20 +2892,20 @@ bad_on_1710:
        }
 
        /* USB "non-iso" IRQ (PIO for all but ep0) */
-       status = request_irq(pdev->resource[2].start, omap_udc_pio_irq,
-                       0, "omap_udc pio", udc);
+       status = devm_request_irq(&pdev->dev, pdev->resource[2].start,
+                                 omap_udc_pio_irq, 0, "omap_udc pio", udc);
        if (status != 0) {
                ERR("can't get irq %d, err %d\n",
                        (int) pdev->resource[2].start, status);
-               goto cleanup2;
+               goto cleanup1;
        }
 #ifdef USE_ISO
-       status = request_irq(pdev->resource[3].start, omap_udc_iso_irq,
-                       0, "omap_udc iso", udc);
+       status = devm_request_irq(&pdev->dev, pdev->resource[3].start,
+                                 omap_udc_iso_irq, 0, "omap_udc iso", udc);
        if (status != 0) {
                ERR("can't get irq %d, err %d\n",
                        (int) pdev->resource[3].start, status);
-               goto cleanup3;
+               goto cleanup1;
        }
 #endif
        if (cpu_is_omap16xx() || cpu_is_omap7xx()) {
@@ -2900,23 +2916,8 @@ bad_on_1710:
        }
 
        create_proc_file();
-       status = usb_add_gadget_udc_release(&pdev->dev, &udc->gadget,
-                       omap_udc_release);
-       if (status)
-               goto cleanup4;
-
-       return 0;
-
-cleanup4:
-       remove_proc_file();
-
-#ifdef USE_ISO
-cleanup3:
-       free_irq(pdev->resource[2].start, udc);
-#endif
-
-cleanup2:
-       free_irq(pdev->resource[1].start, udc);
+       return usb_add_gadget_udc_release(&pdev->dev, &udc->gadget,
+                                         omap_udc_release);
 
 cleanup1:
        kfree(udc);
@@ -2943,42 +2944,15 @@ static int omap_udc_remove(struct platform_device *pdev)
 {
        DECLARE_COMPLETION_ONSTACK(done);
 
-       if (!udc)
-               return -ENODEV;
-
-       usb_del_gadget_udc(&udc->gadget);
-       if (udc->driver)
-               return -EBUSY;
-
        udc->done = &done;
 
-       pullup_disable(udc);
-       if (!IS_ERR_OR_NULL(udc->transceiver)) {
-               usb_put_phy(udc->transceiver);
-               udc->transceiver = NULL;
-       }
-       omap_writew(0, UDC_SYSCON1);
-
-       remove_proc_file();
-
-#ifdef USE_ISO
-       free_irq(pdev->resource[3].start, udc);
-#endif
-       free_irq(pdev->resource[2].start, udc);
-       free_irq(pdev->resource[1].start, udc);
+       usb_del_gadget_udc(&udc->gadget);
 
-       if (udc->dc_clk) {
-               if (udc->clk_requested)
-                       omap_udc_enable_clock(0);
-               clk_put(udc->hhc_clk);
-               clk_put(udc->dc_clk);
-       }
+       wait_for_completion(&done);
 
        release_mem_region(pdev->resource[0].start,
                        pdev->resource[0].end - pdev->resource[0].start + 1);
 
-       wait_for_completion(&done);
-
        return 0;
 }
 
index d17cd95..6b2140f 100644 (file)
@@ -27,4 +27,14 @@ UNUSUAL_DEV(0x0bda, 0x0159, 0x0000, 0x9999,
                "USB Card Reader",
                USB_SC_DEVICE, USB_PR_DEVICE, init_realtek_cr, 0),
 
+UNUSUAL_DEV(0x0bda, 0x0177, 0x0000, 0x9999,
+               "Realtek",
+               "USB Card Reader",
+               USB_SC_DEVICE, USB_PR_DEVICE, init_realtek_cr, 0),
+
+UNUSUAL_DEV(0x0bda, 0x0184, 0x0000, 0x9999,
+               "Realtek",
+               "USB Card Reader",
+               USB_SC_DEVICE, USB_PR_DEVICE, init_realtek_cr, 0),
+
 #endif  /* defined(CONFIG_USB_STORAGE_REALTEK) || ... */
index fdfc64f..221b733 100644 (file)
@@ -251,25 +251,10 @@ static void release_memory_resource(struct resource *resource)
        kfree(resource);
 }
 
-/*
- * Host memory not allocated to dom0. We can use this range for hotplug-based
- * ballooning.
- *
- * It's a type-less resource. Setting IORESOURCE_MEM will make resource
- * management algorithms (arch_remove_reservations()) look into guest e820,
- * which we don't want.
- */
-static struct resource hostmem_resource = {
-       .name   = "Host RAM",
-};
-
-void __attribute__((weak)) __init arch_xen_balloon_init(struct resource *res)
-{}
-
 static struct resource *additional_memory_resource(phys_addr_t size)
 {
-       struct resource *res, *res_hostmem;
-       int ret = -ENOMEM;
+       struct resource *res;
+       int ret;
 
        res = kzalloc(sizeof(*res), GFP_KERNEL);
        if (!res)
@@ -278,42 +263,13 @@ static struct resource *additional_memory_resource(phys_addr_t size)
        res->name = "System RAM";
        res->flags = IORESOURCE_SYSTEM_RAM | IORESOURCE_BUSY;
 
-       res_hostmem = kzalloc(sizeof(*res), GFP_KERNEL);
-       if (res_hostmem) {
-               /* Try to grab a range from hostmem */
-               res_hostmem->name = "Host memory";
-               ret = allocate_resource(&hostmem_resource, res_hostmem,
-                                       size, 0, -1,
-                                       PAGES_PER_SECTION * PAGE_SIZE, NULL, NULL);
-       }
-
-       if (!ret) {
-               /*
-                * Insert this resource into iomem. Because hostmem_resource
-                * tracks portion of guest e820 marked as UNUSABLE noone else
-                * should try to use it.
-                */
-               res->start = res_hostmem->start;
-               res->end = res_hostmem->end;
-               ret = insert_resource(&iomem_resource, res);
-               if (ret < 0) {
-                       pr_err("Can't insert iomem_resource [%llx - %llx]\n",
-                               res->start, res->end);
-                       release_memory_resource(res_hostmem);
-                       res_hostmem = NULL;
-                       res->start = res->end = 0;
-               }
-       }
-
-       if (ret) {
-               ret = allocate_resource(&iomem_resource, res,
-                                       size, 0, -1,
-                                       PAGES_PER_SECTION * PAGE_SIZE, NULL, NULL);
-               if (ret < 0) {
-                       pr_err("Cannot allocate new System RAM resource\n");
-                       kfree(res);
-                       return NULL;
-               }
+       ret = allocate_resource(&iomem_resource, res,
+                               size, 0, -1,
+                               PAGES_PER_SECTION * PAGE_SIZE, NULL, NULL);
+       if (ret < 0) {
+               pr_err("Cannot allocate new System RAM resource\n");
+               kfree(res);
+               return NULL;
        }
 
 #ifdef CONFIG_SPARSEMEM
@@ -325,7 +281,6 @@ static struct resource *additional_memory_resource(phys_addr_t size)
                        pr_err("New System RAM resource outside addressable RAM (%lu > %lu)\n",
                               pfn, limit);
                        release_memory_resource(res);
-                       release_memory_resource(res_hostmem);
                        return NULL;
                }
        }
@@ -750,8 +705,6 @@ static int __init balloon_init(void)
        set_online_page_callback(&xen_online_page);
        register_memory_notifier(&xen_memory_nb);
        register_sysctl_table(xen_root);
-
-       arch_xen_balloon_init(&hostmem_resource);
 #endif
 
 #ifdef CONFIG_XEN_PV
index 2f11ca7..77224d8 100644 (file)
@@ -385,8 +385,8 @@ static int create_active(struct sock_mapping *map, int *evtchn)
 out_error:
        if (*evtchn >= 0)
                xenbus_free_evtchn(pvcalls_front_dev, *evtchn);
-       kfree(map->active.data.in);
-       kfree(map->active.ring);
+       free_pages((unsigned long)map->active.data.in, PVCALLS_RING_ORDER);
+       free_page((unsigned long)map->active.ring);
        return ret;
 }
 
index 23f1387..e7df65d 100644 (file)
@@ -36,6 +36,7 @@
 #include <asm/xen/hypervisor.h>
 
 #include <xen/xen.h>
+#include <xen/xen-ops.h>
 #include <xen/page.h>
 #include <xen/interface/xen.h>
 #include <xen/interface/memory.h>
index 43dea3b..8a2562e 100644 (file)
@@ -1075,8 +1075,6 @@ static void afs_vnode_new_inode(struct afs_fs_cursor *fc,
        if (fc->ac.error < 0)
                return;
 
-       d_drop(new_dentry);
-
        inode = afs_iget(fc->vnode->vfs_inode.i_sb, fc->key,
                         newfid, newstatus, newcb, fc->cbi);
        if (IS_ERR(inode)) {
@@ -1090,7 +1088,7 @@ static void afs_vnode_new_inode(struct afs_fs_cursor *fc,
        vnode = AFS_FS_I(inode);
        set_bit(AFS_VNODE_NEW_CONTENT, &vnode->flags);
        afs_vnode_commit_status(fc, vnode, 0);
-       d_add(new_dentry, inode);
+       d_instantiate(new_dentry, inode);
 }
 
 /*
index d049cb4..fde6b4d 100644 (file)
@@ -61,8 +61,11 @@ void afs_fileserver_probe_result(struct afs_call *call)
                afs_io_error(call, afs_io_error_fs_probe_fail);
                goto out;
        case -ECONNRESET: /* Responded, but call expired. */
+       case -ERFKILL:
+       case -EADDRNOTAVAIL:
        case -ENETUNREACH:
        case -EHOSTUNREACH:
+       case -EHOSTDOWN:
        case -ECONNREFUSED:
        case -ETIMEDOUT:
        case -ETIME:
@@ -132,12 +135,14 @@ out:
 static int afs_do_probe_fileserver(struct afs_net *net,
                                   struct afs_server *server,
                                   struct key *key,
-                                  unsigned int server_index)
+                                  unsigned int server_index,
+                                  struct afs_error *_e)
 {
        struct afs_addr_cursor ac = {
                .index = 0,
        };
-       int ret;
+       bool in_progress = false;
+       int err;
 
        _enter("%pU", &server->uuid);
 
@@ -151,15 +156,17 @@ static int afs_do_probe_fileserver(struct afs_net *net,
        server->probe.rtt = UINT_MAX;
 
        for (ac.index = 0; ac.index < ac.alist->nr_addrs; ac.index++) {
-               ret = afs_fs_get_capabilities(net, server, &ac, key, server_index,
+               err = afs_fs_get_capabilities(net, server, &ac, key, server_index,
                                              true);
-               if (ret != -EINPROGRESS) {
-                       afs_fs_probe_done(server);
-                       return ret;
-               }
+               if (err == -EINPROGRESS)
+                       in_progress = true;
+               else
+                       afs_prioritise_error(_e, err, ac.abort_code);
        }
 
-       return 0;
+       if (!in_progress)
+               afs_fs_probe_done(server);
+       return in_progress;
 }
 
 /*
@@ -169,21 +176,23 @@ int afs_probe_fileservers(struct afs_net *net, struct key *key,
                          struct afs_server_list *list)
 {
        struct afs_server *server;
-       int i, ret;
+       struct afs_error e;
+       bool in_progress = false;
+       int i;
 
+       e.error = 0;
+       e.responded = false;
        for (i = 0; i < list->nr_servers; i++) {
                server = list->servers[i].server;
                if (test_bit(AFS_SERVER_FL_PROBED, &server->flags))
                        continue;
 
-               if (!test_and_set_bit_lock(AFS_SERVER_FL_PROBING, &server->flags)) {
-                       ret = afs_do_probe_fileserver(net, server, key, i);
-                       if (ret)
-                               return ret;
-               }
+               if (!test_and_set_bit_lock(AFS_SERVER_FL_PROBING, &server->flags) &&
+                   afs_do_probe_fileserver(net, server, key, i, &e))
+                       in_progress = true;
        }
 
-       return 0;
+       return in_progress ? 0 : e.error;
 }
 
 /*
index 4c6d8e1..6b17d36 100644 (file)
@@ -382,7 +382,7 @@ void afs_zap_data(struct afs_vnode *vnode)
 int afs_validate(struct afs_vnode *vnode, struct key *key)
 {
        time64_t now = ktime_get_real_seconds();
-       bool valid = false;
+       bool valid;
        int ret;
 
        _enter("{v={%llx:%llu} fl=%lx},%x",
@@ -402,15 +402,21 @@ int afs_validate(struct afs_vnode *vnode, struct key *key)
                        vnode->cb_v_break = vnode->volume->cb_v_break;
                        valid = false;
                } else if (vnode->status.type == AFS_FTYPE_DIR &&
-                          test_bit(AFS_VNODE_DIR_VALID, &vnode->flags) &&
-                          vnode->cb_expires_at - 10 > now) {
-                       valid = true;
-               } else if (!test_bit(AFS_VNODE_ZAP_DATA, &vnode->flags) &&
-                          vnode->cb_expires_at - 10 > now) {
+                          (!test_bit(AFS_VNODE_DIR_VALID, &vnode->flags) ||
+                           vnode->cb_expires_at - 10 <= now)) {
+                       valid = false;
+               } else if (test_bit(AFS_VNODE_ZAP_DATA, &vnode->flags) ||
+                          vnode->cb_expires_at - 10 <= now) {
+                       valid = false;
+               } else {
                        valid = true;
                }
        } else if (test_bit(AFS_VNODE_DELETED, &vnode->flags)) {
                valid = true;
+       } else {
+               vnode->cb_s_break = vnode->cb_interest->server->cb_s_break;
+               vnode->cb_v_break = vnode->volume->cb_v_break;
+               valid = false;
        }
 
        read_sequnlock_excl(&vnode->cb_lock);
index 5da3b09..8871b9e 100644 (file)
@@ -695,6 +695,14 @@ struct afs_interface {
        unsigned        mtu;            /* MTU of interface */
 };
 
+/*
+ * Error prioritisation and accumulation.
+ */
+struct afs_error {
+       short   error;                  /* Accumulated error */
+       bool    responded;              /* T if server responded */
+};
+
 /*
  * Cursor for iterating over a server's address list.
  */
@@ -1015,6 +1023,7 @@ static inline void __afs_stat(atomic_t *s)
  * misc.c
  */
 extern int afs_abort_to_error(u32);
+extern void afs_prioritise_error(struct afs_error *, int, u32);
 
 /*
  * mntpt.c
index 700a5fa..bbb1fd5 100644 (file)
@@ -118,3 +118,55 @@ int afs_abort_to_error(u32 abort_code)
        default:                return -EREMOTEIO;
        }
 }
+
+/*
+ * Select the error to report from a set of errors.
+ */
+void afs_prioritise_error(struct afs_error *e, int error, u32 abort_code)
+{
+       switch (error) {
+       case 0:
+               return;
+       default:
+               if (e->error == -ETIMEDOUT ||
+                   e->error == -ETIME)
+                       return;
+       case -ETIMEDOUT:
+       case -ETIME:
+               if (e->error == -ENOMEM ||
+                   e->error == -ENONET)
+                       return;
+       case -ENOMEM:
+       case -ENONET:
+               if (e->error == -ERFKILL)
+                       return;
+       case -ERFKILL:
+               if (e->error == -EADDRNOTAVAIL)
+                       return;
+       case -EADDRNOTAVAIL:
+               if (e->error == -ENETUNREACH)
+                       return;
+       case -ENETUNREACH:
+               if (e->error == -EHOSTUNREACH)
+                       return;
+       case -EHOSTUNREACH:
+               if (e->error == -EHOSTDOWN)
+                       return;
+       case -EHOSTDOWN:
+               if (e->error == -ECONNREFUSED)
+                       return;
+       case -ECONNREFUSED:
+               if (e->error == -ECONNRESET)
+                       return;
+       case -ECONNRESET: /* Responded, but call expired. */
+               if (e->responded)
+                       return;
+               e->error = error;
+               return;
+
+       case -ECONNABORTED:
+               e->responded = true;
+               e->error = afs_abort_to_error(abort_code);
+               return;
+       }
+}
index 0050425..c3ae324 100644 (file)
@@ -136,7 +136,8 @@ bool afs_select_fileserver(struct afs_fs_cursor *fc)
        struct afs_addr_list *alist;
        struct afs_server *server;
        struct afs_vnode *vnode = fc->vnode;
-       u32 rtt, abort_code;
+       struct afs_error e;
+       u32 rtt;
        int error = fc->ac.error, i;
 
        _enter("%lx[%d],%lx[%d],%d,%d",
@@ -306,8 +307,11 @@ bool afs_select_fileserver(struct afs_fs_cursor *fc)
                if (fc->error != -EDESTADDRREQ)
                        goto iterate_address;
                /* Fall through */
+       case -ERFKILL:
+       case -EADDRNOTAVAIL:
        case -ENETUNREACH:
        case -EHOSTUNREACH:
+       case -EHOSTDOWN:
        case -ECONNREFUSED:
                _debug("no conn");
                fc->error = error;
@@ -446,50 +450,15 @@ no_more_servers:
        if (fc->flags & AFS_FS_CURSOR_VBUSY)
                goto restart_from_beginning;
 
-       abort_code = 0;
-       error = -EDESTADDRREQ;
+       e.error = -EDESTADDRREQ;
+       e.responded = false;
        for (i = 0; i < fc->server_list->nr_servers; i++) {
                struct afs_server *s = fc->server_list->servers[i].server;
-               int probe_error = READ_ONCE(s->probe.error);
 
-               switch (probe_error) {
-               case 0:
-                       continue;
-               default:
-                       if (error == -ETIMEDOUT ||
-                           error == -ETIME)
-                               continue;
-               case -ETIMEDOUT:
-               case -ETIME:
-                       if (error == -ENOMEM ||
-                           error == -ENONET)
-                               continue;
-               case -ENOMEM:
-               case -ENONET:
-                       if (error == -ENETUNREACH)
-                               continue;
-               case -ENETUNREACH:
-                       if (error == -EHOSTUNREACH)
-                               continue;
-               case -EHOSTUNREACH:
-                       if (error == -ECONNREFUSED)
-                               continue;
-               case -ECONNREFUSED:
-                       if (error == -ECONNRESET)
-                               continue;
-               case -ECONNRESET: /* Responded, but call expired. */
-                       if (error == -ECONNABORTED)
-                               continue;
-               case -ECONNABORTED:
-                       abort_code = s->probe.abort_code;
-                       error = probe_error;
-                       continue;
-               }
+               afs_prioritise_error(&e, READ_ONCE(s->probe.error),
+                                    s->probe.abort_code);
        }
 
-       if (error == -ECONNABORTED)
-               error = afs_abort_to_error(abort_code);
-
 failed_set_error:
        fc->error = error;
 failed:
@@ -553,8 +522,11 @@ bool afs_select_current_fileserver(struct afs_fs_cursor *fc)
                _leave(" = f [abort]");
                return false;
 
+       case -ERFKILL:
+       case -EADDRNOTAVAIL:
        case -ENETUNREACH:
        case -EHOSTUNREACH:
+       case -EHOSTDOWN:
        case -ECONNREFUSED:
        case -ETIMEDOUT:
        case -ETIME:
@@ -633,6 +605,7 @@ int afs_end_vnode_operation(struct afs_fs_cursor *fc)
        struct afs_net *net = afs_v2net(fc->vnode);
 
        if (fc->error == -EDESTADDRREQ ||
+           fc->error == -EADDRNOTAVAIL ||
            fc->error == -ENETUNREACH ||
            fc->error == -EHOSTUNREACH)
                afs_dump_edestaddrreq(fc);
index c0f616b..f0b0329 100644 (file)
@@ -61,8 +61,11 @@ void afs_vlserver_probe_result(struct afs_call *call)
                afs_io_error(call, afs_io_error_vl_probe_fail);
                goto out;
        case -ECONNRESET: /* Responded, but call expired. */
+       case -ERFKILL:
+       case -EADDRNOTAVAIL:
        case -ENETUNREACH:
        case -EHOSTUNREACH:
+       case -EHOSTDOWN:
        case -ECONNREFUSED:
        case -ETIMEDOUT:
        case -ETIME:
@@ -129,15 +132,17 @@ out:
  * Probe all of a vlserver's addresses to find out the best route and to
  * query its capabilities.
  */
-static int afs_do_probe_vlserver(struct afs_net *net,
-                                struct afs_vlserver *server,
-                                struct key *key,
-                                unsigned int server_index)
+static bool afs_do_probe_vlserver(struct afs_net *net,
+                                 struct afs_vlserver *server,
+                                 struct key *key,
+                                 unsigned int server_index,
+                                 struct afs_error *_e)
 {
        struct afs_addr_cursor ac = {
                .index = 0,
        };
-       int ret;
+       bool in_progress = false;
+       int err;
 
        _enter("%s", server->name);
 
@@ -151,15 +156,17 @@ static int afs_do_probe_vlserver(struct afs_net *net,
        server->probe.rtt = UINT_MAX;
 
        for (ac.index = 0; ac.index < ac.alist->nr_addrs; ac.index++) {
-               ret = afs_vl_get_capabilities(net, &ac, key, server,
+               err = afs_vl_get_capabilities(net, &ac, key, server,
                                              server_index, true);
-               if (ret != -EINPROGRESS) {
-                       afs_vl_probe_done(server);
-                       return ret;
-               }
+               if (err == -EINPROGRESS)
+                       in_progress = true;
+               else
+                       afs_prioritise_error(_e, err, ac.abort_code);
        }
 
-       return 0;
+       if (!in_progress)
+               afs_vl_probe_done(server);
+       return in_progress;
 }
 
 /*
@@ -169,21 +176,23 @@ int afs_send_vl_probes(struct afs_net *net, struct key *key,
                       struct afs_vlserver_list *vllist)
 {
        struct afs_vlserver *server;
-       int i, ret;
+       struct afs_error e;
+       bool in_progress = false;
+       int i;
 
+       e.error = 0;
+       e.responded = false;
        for (i = 0; i < vllist->nr_servers; i++) {
                server = vllist->servers[i].server;
                if (test_bit(AFS_VLSERVER_FL_PROBED, &server->flags))
                        continue;
 
-               if (!test_and_set_bit_lock(AFS_VLSERVER_FL_PROBING, &server->flags)) {
-                       ret = afs_do_probe_vlserver(net, server, key, i);
-                       if (ret)
-                               return ret;
-               }
+               if (!test_and_set_bit_lock(AFS_VLSERVER_FL_PROBING, &server->flags) &&
+                   afs_do_probe_vlserver(net, server, key, i, &e))
+                       in_progress = true;
        }
 
-       return 0;
+       return in_progress ? 0 : e.error;
 }
 
 /*
index b64a284..7adde83 100644 (file)
@@ -71,8 +71,9 @@ bool afs_select_vlserver(struct afs_vl_cursor *vc)
 {
        struct afs_addr_list *alist;
        struct afs_vlserver *vlserver;
+       struct afs_error e;
        u32 rtt;
-       int error = vc->ac.error, abort_code, i;
+       int error = vc->ac.error, i;
 
        _enter("%lx[%d],%lx[%d],%d,%d",
               vc->untried, vc->index,
@@ -119,8 +120,11 @@ bool afs_select_vlserver(struct afs_vl_cursor *vc)
                        goto failed;
                }
 
+       case -ERFKILL:
+       case -EADDRNOTAVAIL:
        case -ENETUNREACH:
        case -EHOSTUNREACH:
+       case -EHOSTDOWN:
        case -ECONNREFUSED:
        case -ETIMEDOUT:
        case -ETIME:
@@ -235,50 +239,15 @@ no_more_servers:
        if (vc->flags & AFS_VL_CURSOR_RETRY)
                goto restart_from_beginning;
 
-       abort_code = 0;
-       error = -EDESTADDRREQ;
+       e.error = -EDESTADDRREQ;
+       e.responded = false;
        for (i = 0; i < vc->server_list->nr_servers; i++) {
                struct afs_vlserver *s = vc->server_list->servers[i].server;
-               int probe_error = READ_ONCE(s->probe.error);
 
-               switch (probe_error) {
-               case 0:
-                       continue;
-               default:
-                       if (error == -ETIMEDOUT ||
-                           error == -ETIME)
-                               continue;
-               case -ETIMEDOUT:
-               case -ETIME:
-                       if (error == -ENOMEM ||
-                           error == -ENONET)
-                               continue;
-               case -ENOMEM:
-               case -ENONET:
-                       if (error == -ENETUNREACH)
-                               continue;
-               case -ENETUNREACH:
-                       if (error == -EHOSTUNREACH)
-                               continue;
-               case -EHOSTUNREACH:
-                       if (error == -ECONNREFUSED)
-                               continue;
-               case -ECONNREFUSED:
-                       if (error == -ECONNRESET)
-                               continue;
-               case -ECONNRESET: /* Responded, but call expired. */
-                       if (error == -ECONNABORTED)
-                               continue;
-               case -ECONNABORTED:
-                       abort_code = s->probe.abort_code;
-                       error = probe_error;
-                       continue;
-               }
+               afs_prioritise_error(&e, READ_ONCE(s->probe.error),
+                                    s->probe.abort_code);
        }
 
-       if (error == -ECONNABORTED)
-               error = afs_abort_to_error(abort_code);
-
 failed_set_error:
        vc->error = error;
 failed:
@@ -341,6 +310,7 @@ int afs_end_vlserver_operation(struct afs_vl_cursor *vc)
        struct afs_net *net = vc->cell->net;
 
        if (vc->error == -EDESTADDRREQ ||
+           vc->error == -EADDRNOTAVAIL ||
            vc->error == -ENETUNREACH ||
            vc->error == -EHOSTUNREACH)
                afs_vl_dump_edestaddrreq(vc);
index 301e631..97f9835 100644 (file)
--- a/fs/aio.c
+++ b/fs/aio.c
@@ -1436,6 +1436,7 @@ static int aio_prep_rw(struct kiocb *req, struct iocb *iocb)
                ret = ioprio_check_cap(iocb->aio_reqprio);
                if (ret) {
                        pr_debug("aio ioprio check cap error: %d\n", ret);
+                       fput(req->ki_filp);
                        return ret;
                }
 
index 3f0b6d1..6d77671 100644 (file)
@@ -477,9 +477,9 @@ static int btree_read_extent_buffer_pages(struct btrfs_fs_info *fs_info,
        int mirror_num = 0;
        int failed_mirror = 0;
 
-       clear_bit(EXTENT_BUFFER_CORRUPT, &eb->bflags);
        io_tree = &BTRFS_I(fs_info->btree_inode)->io_tree;
        while (1) {
+               clear_bit(EXTENT_BUFFER_CORRUPT, &eb->bflags);
                ret = read_extent_buffer_pages(io_tree, eb, WAIT_COMPLETE,
                                               mirror_num);
                if (!ret) {
@@ -493,15 +493,6 @@ static int btree_read_extent_buffer_pages(struct btrfs_fs_info *fs_info,
                                break;
                }
 
-               /*
-                * This buffer's crc is fine, but its contents are corrupted, so
-                * there is no reason to read the other copies, they won't be
-                * any less wrong.
-                */
-               if (test_bit(EXTENT_BUFFER_CORRUPT, &eb->bflags) ||
-                   ret == -EUCLEAN)
-                       break;
-
                num_copies = btrfs_num_copies(fs_info,
                                              eb->start, eb->len);
                if (num_copies == 1)
index a3c22e1..58e93bc 100644 (file)
@@ -2088,6 +2088,30 @@ int btrfs_sync_file(struct file *file, loff_t start, loff_t end, int datasync)
 
        atomic_inc(&root->log_batch);
 
+       /*
+        * Before we acquired the inode's lock, someone may have dirtied more
+        * pages in the target range. We need to make sure that writeback for
+        * any such pages does not start while we are logging the inode, because
+        * if it does, any of the following might happen when we are not doing a
+        * full inode sync:
+        *
+        * 1) We log an extent after its writeback finishes but before its
+        *    checksums are added to the csum tree, leading to -EIO errors
+        *    when attempting to read the extent after a log replay.
+        *
+        * 2) We can end up logging an extent before its writeback finishes.
+        *    Therefore after the log replay we will have a file extent item
+        *    pointing to an unwritten extent (and no data checksums as well).
+        *
+        * So trigger writeback for any eventual new dirty pages and then we
+        * wait for all ordered extents to complete below.
+        */
+       ret = start_ordered_ops(inode, start, end);
+       if (ret) {
+               inode_unlock(inode);
+               goto out;
+       }
+
        /*
         * We have to do this here to avoid the priority inversion of waiting on
         * IO of a lower priority task while holding a transaciton open.
index 45868fd..f70825a 100644 (file)
@@ -2659,7 +2659,7 @@ int btrfs_qgroup_inherit(struct btrfs_trans_handle *trans, u64 srcid,
        int i;
        u64 *i_qgroups;
        struct btrfs_fs_info *fs_info = trans->fs_info;
-       struct btrfs_root *quota_root = fs_info->quota_root;
+       struct btrfs_root *quota_root;
        struct btrfs_qgroup *srcgroup;
        struct btrfs_qgroup *dstgroup;
        u32 level_size = 0;
@@ -2669,6 +2669,7 @@ int btrfs_qgroup_inherit(struct btrfs_trans_handle *trans, u64 srcid,
        if (!test_bit(BTRFS_FS_QUOTA_ENABLED, &fs_info->flags))
                goto out;
 
+       quota_root = fs_info->quota_root;
        if (!quota_root) {
                ret = -EINVAL;
                goto out;
index 924116f..a3f75b8 100644 (file)
@@ -3959,6 +3959,7 @@ static noinline_for_stack int relocate_block_group(struct reloc_control *rc)
 restart:
                if (update_backref_cache(trans, &rc->backref_cache)) {
                        btrfs_end_transaction(trans);
+                       trans = NULL;
                        continue;
                }
 
index 094cc14..5be83b5 100644 (file)
@@ -3340,7 +3340,8 @@ static void free_pending_move(struct send_ctx *sctx, struct pending_dir_move *m)
        kfree(m);
 }
 
-static void tail_append_pending_moves(struct pending_dir_move *moves,
+static void tail_append_pending_moves(struct send_ctx *sctx,
+                                     struct pending_dir_move *moves,
                                      struct list_head *stack)
 {
        if (list_empty(&moves->list)) {
@@ -3351,6 +3352,10 @@ static void tail_append_pending_moves(struct pending_dir_move *moves,
                list_add_tail(&moves->list, stack);
                list_splice_tail(&list, stack);
        }
+       if (!RB_EMPTY_NODE(&moves->node)) {
+               rb_erase(&moves->node, &sctx->pending_dir_moves);
+               RB_CLEAR_NODE(&moves->node);
+       }
 }
 
 static int apply_children_dir_moves(struct send_ctx *sctx)
@@ -3365,7 +3370,7 @@ static int apply_children_dir_moves(struct send_ctx *sctx)
                return 0;
 
        INIT_LIST_HEAD(&stack);
-       tail_append_pending_moves(pm, &stack);
+       tail_append_pending_moves(sctx, pm, &stack);
 
        while (!list_empty(&stack)) {
                pm = list_first_entry(&stack, struct pending_dir_move, list);
@@ -3376,7 +3381,7 @@ static int apply_children_dir_moves(struct send_ctx *sctx)
                        goto out;
                pm = get_pending_dir_moves(sctx, parent_ino);
                if (pm)
-                       tail_append_pending_moves(pm, &stack);
+                       tail_append_pending_moves(sctx, pm, &stack);
        }
        return 0;
 
index cbc9d0d..645fc81 100644 (file)
@@ -2237,6 +2237,7 @@ static long btrfs_control_ioctl(struct file *file, unsigned int cmd,
        vol = memdup_user((void __user *)arg, sizeof(*vol));
        if (IS_ERR(vol))
                return PTR_ERR(vol);
+       vol->name[BTRFS_PATH_NAME_MAX] = '\0';
 
        switch (cmd) {
        case BTRFS_IOC_SCAN_DEV:
index 95983c7..1645fcf 100644 (file)
@@ -244,11 +244,13 @@ wait_for_old_object:
 
        ASSERT(!test_bit(CACHEFILES_OBJECT_ACTIVE, &xobject->flags));
 
-       cache->cache.ops->put_object(&xobject->fscache, cachefiles_obj_put_wait_retry);
+       cache->cache.ops->put_object(&xobject->fscache,
+               (enum fscache_obj_ref_trace)cachefiles_obj_put_wait_retry);
        goto try_again;
 
 requeue:
-       cache->cache.ops->put_object(&xobject->fscache, cachefiles_obj_put_wait_timeo);
+       cache->cache.ops->put_object(&xobject->fscache,
+               (enum fscache_obj_ref_trace)cachefiles_obj_put_wait_timeo);
        _leave(" = -ETIMEDOUT");
        return -ETIMEDOUT;
 }
@@ -336,7 +338,7 @@ static int cachefiles_bury_object(struct cachefiles_cache *cache,
 try_again:
        /* first step is to make up a grave dentry in the graveyard */
        sprintf(nbuffer, "%08x%08x",
-               (uint32_t) get_seconds(),
+               (uint32_t) ktime_get_real_seconds(),
                (uint32_t) atomic_inc_return(&cache->gravecounter));
 
        /* do the multiway lock magic */
index 40f7595..8a57740 100644 (file)
@@ -535,7 +535,10 @@ static int cachefiles_read_backing_file(struct cachefiles_object *object,
                                            netpage->index, cachefiles_gfp);
                if (ret < 0) {
                        if (ret == -EEXIST) {
+                               put_page(backpage);
+                               backpage = NULL;
                                put_page(netpage);
+                               netpage = NULL;
                                fscache_retrieval_complete(op, 1);
                                continue;
                        }
@@ -608,7 +611,10 @@ static int cachefiles_read_backing_file(struct cachefiles_object *object,
                                            netpage->index, cachefiles_gfp);
                if (ret < 0) {
                        if (ret == -EEXIST) {
+                               put_page(backpage);
+                               backpage = NULL;
                                put_page(netpage);
+                               netpage = NULL;
                                fscache_retrieval_complete(op, 1);
                                continue;
                        }
@@ -962,11 +968,8 @@ void cachefiles_uncache_page(struct fscache_object *_object, struct page *page)
        __releases(&object->fscache.cookie->lock)
 {
        struct cachefiles_object *object;
-       struct cachefiles_cache *cache;
 
        object = container_of(_object, struct cachefiles_object, fscache);
-       cache = container_of(object->fscache.cache,
-                            struct cachefiles_cache, cache);
 
        _enter("%p,{%lu}", object, page->index);
 
index 0a29a00..511e6c6 100644 (file)
@@ -135,7 +135,8 @@ int cachefiles_update_object_xattr(struct cachefiles_object *object,
        struct dentry *dentry = object->dentry;
        int ret;
 
-       ASSERT(dentry);
+       if (!dentry)
+               return -ESTALE;
 
        _enter("%p,#%d", object, auxdata->len);
 
index 722d17c..41a0e97 100644 (file)
@@ -325,8 +325,8 @@ static ssize_t dio_complete(struct dio *dio, ssize_t ret, unsigned int flags)
                 */
                dio->iocb->ki_pos += transferred;
 
-               if (dio->op == REQ_OP_WRITE)
-                       ret = generic_write_sync(dio->iocb,  transferred);
+               if (ret > 0 && dio->op == REQ_OP_WRITE)
+                       ret = generic_write_sync(dio->iocb, ret);
                dio->iocb->ki_complete(dio->iocb, ret, 0);
        }
 
index 645158d..c69927b 100644 (file)
@@ -77,7 +77,7 @@ static bool dentry_connected(struct dentry *dentry)
                struct dentry *parent = dget_parent(dentry);
 
                dput(dentry);
-               if (IS_ROOT(dentry)) {
+               if (dentry == parent) {
                        dput(parent);
                        return false;
                }
@@ -147,6 +147,7 @@ static struct dentry *reconnect_one(struct vfsmount *mnt,
        tmp = lookup_one_len_unlocked(nbuf, parent, strlen(nbuf));
        if (IS_ERR(tmp)) {
                dprintk("%s: lookup failed: %d\n", __func__, PTR_ERR(tmp));
+               err = PTR_ERR(tmp);
                goto out_err;
        }
        if (tmp != dentry) {
index cb91baa..eb11502 100644 (file)
@@ -892,6 +892,7 @@ static int ext2_fill_super(struct super_block *sb, void *data, int silent)
        if (sb->s_magic != EXT2_SUPER_MAGIC)
                goto cantfind_ext2;
 
+       opts.s_mount_opt = 0;
        /* Set defaults before we parse the mount options */
        def_mount_opts = le32_to_cpu(es->s_default_mount_opts);
        if (def_mount_opts & EXT2_DEFM_DEBUG)
index 62d9a65..dd8f10d 100644 (file)
@@ -612,9 +612,9 @@ skip_replace:
        }
 
 cleanup:
-       brelse(bh);
        if (!(bh && header == HDR(bh)))
                kfree(header);
+       brelse(bh);
        up_write(&EXT2_I(inode)->xattr_sem);
 
        return error;
index 9edc920..6d9cb17 100644 (file)
@@ -730,6 +730,9 @@ static const struct fscache_state *fscache_drop_object(struct fscache_object *ob
 
        if (awaken)
                wake_up_bit(&cookie->flags, FSCACHE_COOKIE_INVALIDATING);
+       if (test_and_clear_bit(FSCACHE_COOKIE_LOOKING_UP, &cookie->flags))
+               wake_up_bit(&cookie->flags, FSCACHE_COOKIE_LOOKING_UP);
+
 
        /* Prevent a race with our last child, which has to signal EV_CLEARED
         * before dropping our spinlock.
index 98b96ff..19017d2 100644 (file)
@@ -338,13 +338,14 @@ void hfs_bmap_free(struct hfs_bnode *node)
 
                nidx -= len * 8;
                i = node->next;
-               hfs_bnode_put(node);
                if (!i) {
                        /* panic */;
                        pr_crit("unable to free bnode %u. bmap not found!\n",
                                node->this);
+                       hfs_bnode_put(node);
                        return;
                }
+               hfs_bnode_put(node);
                node = hfs_bnode_find(tree, i);
                if (IS_ERR(node))
                        return;
index 236efe5..66774f4 100644 (file)
@@ -466,14 +466,15 @@ void hfs_bmap_free(struct hfs_bnode *node)
 
                nidx -= len * 8;
                i = node->next;
-               hfs_bnode_put(node);
                if (!i) {
                        /* panic */;
                        pr_crit("unable to free bnode %u. "
                                        "bmap not found!\n",
                                node->this);
+                       hfs_bnode_put(node);
                        return;
                }
+               hfs_bnode_put(node);
                node = hfs_bnode_find(tree, i);
                if (IS_ERR(node))
                        return;
index 9f88188..4bf8d58 100644 (file)
@@ -125,10 +125,10 @@ check_err:
 
 check_gen:
        if (handle->ih_generation != inode->i_generation) {
-               iput(inode);
                trace_ocfs2_get_dentry_generation((unsigned long long)blkno,
                                                  handle->ih_generation,
                                                  inode->i_generation);
+               iput(inode);
                result = ERR_PTR(-ESTALE);
                goto bail;
        }
index 3f1685d..1565dd8 100644 (file)
@@ -157,18 +157,14 @@ out:
 }
 
 /*
- * lock allocators, and reserving appropriate number of bits for
- * meta blocks and data clusters.
- *
- * in some cases, we don't need to reserve clusters, just let data_ac
- * be NULL.
+ * lock allocator, and reserve appropriate number of bits for
+ * meta blocks.
  */
-static int ocfs2_lock_allocators_move_extents(struct inode *inode,
+static int ocfs2_lock_meta_allocator_move_extents(struct inode *inode,
                                        struct ocfs2_extent_tree *et,
                                        u32 clusters_to_move,
                                        u32 extents_to_split,
                                        struct ocfs2_alloc_context **meta_ac,
-                                       struct ocfs2_alloc_context **data_ac,
                                        int extra_blocks,
                                        int *credits)
 {
@@ -193,13 +189,6 @@ static int ocfs2_lock_allocators_move_extents(struct inode *inode,
                goto out;
        }
 
-       if (data_ac) {
-               ret = ocfs2_reserve_clusters(osb, clusters_to_move, data_ac);
-               if (ret) {
-                       mlog_errno(ret);
-                       goto out;
-               }
-       }
 
        *credits += ocfs2_calc_extend_credits(osb->sb, et->et_root_el);
 
@@ -259,10 +248,10 @@ static int ocfs2_defrag_extent(struct ocfs2_move_extents_context *context,
                }
        }
 
-       ret = ocfs2_lock_allocators_move_extents(inode, &context->et, *len, 1,
-                                                &context->meta_ac,
-                                                &context->data_ac,
-                                                extra_blocks, &credits);
+       ret = ocfs2_lock_meta_allocator_move_extents(inode, &context->et,
+                                               *len, 1,
+                                               &context->meta_ac,
+                                               extra_blocks, &credits);
        if (ret) {
                mlog_errno(ret);
                goto out;
@@ -285,6 +274,21 @@ static int ocfs2_defrag_extent(struct ocfs2_move_extents_context *context,
                }
        }
 
+       /*
+        * Make sure ocfs2_reserve_cluster is called after
+        * __ocfs2_flush_truncate_log, otherwise, dead lock may happen.
+        *
+        * If ocfs2_reserve_cluster is called
+        * before __ocfs2_flush_truncate_log, dead lock on global bitmap
+        * may happen.
+        *
+        */
+       ret = ocfs2_reserve_clusters(osb, *len, &context->data_ac);
+       if (ret) {
+               mlog_errno(ret);
+               goto out_unlock_mutex;
+       }
+
        handle = ocfs2_start_trans(osb, credits);
        if (IS_ERR(handle)) {
                ret = PTR_ERR(handle);
@@ -617,9 +621,10 @@ static int ocfs2_move_extent(struct ocfs2_move_extents_context *context,
                }
        }
 
-       ret = ocfs2_lock_allocators_move_extents(inode, &context->et, len, 1,
-                                                &context->meta_ac,
-                                                NULL, extra_blocks, &credits);
+       ret = ocfs2_lock_meta_allocator_move_extents(inode, &context->et,
+                                               len, 1,
+                                               &context->meta_ac,
+                                               extra_blocks, &credits);
        if (ret) {
                mlog_errno(ret);
                goto out;
index ffcff65..e02a903 100644 (file)
@@ -816,17 +816,14 @@ static int ramoops_probe(struct platform_device *pdev)
 
        cxt->pstore.data = cxt;
        /*
-        * Console can handle any buffer size, so prefer LOG_LINE_MAX. If we
-        * have to handle dumps, we must have at least record_size buffer. And
-        * for ftrace, bufsize is irrelevant (if bufsize is 0, buf will be
-        * ZERO_SIZE_PTR).
+        * Since bufsize is only used for dmesg crash dumps, it
+        * must match the size of the dprz record (after PRZ header
+        * and ECC bytes have been accounted for).
         */
-       if (cxt->console_size)
-               cxt->pstore.bufsize = 1024; /* LOG_LINE_MAX */
-       cxt->pstore.bufsize = max(cxt->record_size, cxt->pstore.bufsize);
-       cxt->pstore.buf = kmalloc(cxt->pstore.bufsize, GFP_KERNEL);
+       cxt->pstore.bufsize = cxt->dprzs[0]->buffer_size;
+       cxt->pstore.buf = kzalloc(cxt->pstore.bufsize, GFP_KERNEL);
        if (!cxt->pstore.buf) {
-               pr_err("cannot allocate pstore buffer\n");
+               pr_err("cannot allocate pstore crash dump buffer\n");
                err = -ENOMEM;
                goto fail_clear;
        }
index 499a20a..273736f 100644 (file)
@@ -275,7 +275,7 @@ static int __sysv_write_inode(struct inode *inode, int wait)
                 }
         }
        brelse(bh);
-       return 0;
+       return err;
 }
 
 int sysv_write_inode(struct inode *inode, struct writeback_control *wbc)
index 8f2f56d..e3d684e 100644 (file)
@@ -827,16 +827,20 @@ static int udf_load_pvoldesc(struct super_block *sb, sector_t block)
 
 
        ret = udf_dstrCS0toChar(sb, outstr, 31, pvoldesc->volIdent, 32);
-       if (ret < 0)
-               goto out_bh;
-
-       strncpy(UDF_SB(sb)->s_volume_ident, outstr, ret);
+       if (ret < 0) {
+               strcpy(UDF_SB(sb)->s_volume_ident, "InvalidName");
+               pr_warn("incorrect volume identification, setting to "
+                       "'InvalidName'\n");
+       } else {
+               strncpy(UDF_SB(sb)->s_volume_ident, outstr, ret);
+       }
        udf_debug("volIdent[] = '%s'\n", UDF_SB(sb)->s_volume_ident);
 
        ret = udf_dstrCS0toChar(sb, outstr, 127, pvoldesc->volSetIdent, 128);
-       if (ret < 0)
+       if (ret < 0) {
+               ret = 0;
                goto out_bh;
-
+       }
        outstr[ret] = 0;
        udf_debug("volSetIdent[] = '%s'\n", outstr);
 
index 4523479..5fcfa96 100644 (file)
@@ -351,6 +351,11 @@ try_again:
        return u_len;
 }
 
+/*
+ * Convert CS0 dstring to output charset. Warning: This function may truncate
+ * input string if it is too long as it is used for informational strings only
+ * and it is better to truncate the string than to refuse mounting a media.
+ */
 int udf_dstrCS0toChar(struct super_block *sb, uint8_t *utf_o, int o_len,
                      const uint8_t *ocu_i, int i_len)
 {
@@ -359,9 +364,12 @@ int udf_dstrCS0toChar(struct super_block *sb, uint8_t *utf_o, int o_len,
        if (i_len > 0) {
                s_len = ocu_i[i_len - 1];
                if (s_len >= i_len) {
-                       pr_err("incorrect dstring lengths (%d/%d)\n",
-                              s_len, i_len);
-                       return -EINVAL;
+                       pr_warn("incorrect dstring lengths (%d/%d),"
+                               " truncating\n", s_len, i_len);
+                       s_len = i_len - 1;
+                       /* 2-byte encoding? Need to round properly... */
+                       if (ocu_i[0] == 16)
+                               s_len -= (s_len - 1) & 2;
                }
        }
 
index 356d2b8..cd58939 100644 (file)
@@ -1361,6 +1361,19 @@ static int userfaultfd_register(struct userfaultfd_ctx *ctx,
                ret = -EINVAL;
                if (!vma_can_userfault(cur))
                        goto out_unlock;
+
+               /*
+                * UFFDIO_COPY will fill file holes even without
+                * PROT_WRITE. This check enforces that if this is a
+                * MAP_SHARED, the process has write permission to the backing
+                * file. If VM_MAYWRITE is set it also enforces that on a
+                * MAP_SHARED vma: there is no F_WRITE_SEAL and no further
+                * F_WRITE_SEAL can be taken until the vma is destroyed.
+                */
+               ret = -EPERM;
+               if (unlikely(!(cur->vm_flags & VM_MAYWRITE)))
+                       goto out_unlock;
+
                /*
                 * If this vma contains ending address, and huge pages
                 * check alignment.
@@ -1406,6 +1419,7 @@ static int userfaultfd_register(struct userfaultfd_ctx *ctx,
                BUG_ON(!vma_can_userfault(vma));
                BUG_ON(vma->vm_userfaultfd_ctx.ctx &&
                       vma->vm_userfaultfd_ctx.ctx != ctx);
+               WARN_ON(!(vma->vm_flags & VM_MAYWRITE));
 
                /*
                 * Nothing to do: this vma is already registered into this
@@ -1552,6 +1566,7 @@ static int userfaultfd_unregister(struct userfaultfd_ctx *ctx,
                cond_resched();
 
                BUG_ON(!vma_can_userfault(vma));
+               WARN_ON(!(vma->vm_flags & VM_MAYWRITE));
 
                /*
                 * Nothing to do: this vma is already registered into this
index de629b7..448dcc4 100644 (file)
@@ -866,6 +866,10 @@ void bpf_jit_binary_free(struct bpf_binary_header *hdr);
 
 void bpf_jit_free(struct bpf_prog *fp);
 
+int bpf_jit_get_func_addr(const struct bpf_prog *prog,
+                         const struct bpf_insn *insn, bool extra_pass,
+                         u64 *func_addr, bool *func_addr_fixed);
+
 struct bpf_prog *bpf_jit_blind_constants(struct bpf_prog *fp);
 void bpf_jit_prog_release_other(struct bpf_prog *fp, struct bpf_prog *fp_other);
 
index 34cf0fd..610815e 100644 (file)
@@ -196,8 +196,7 @@ static inline void fscache_enqueue_retrieval(struct fscache_retrieval *op)
 static inline void fscache_retrieval_complete(struct fscache_retrieval *op,
                                              int n_pages)
 {
-       atomic_sub(n_pages, &op->n_pages);
-       if (atomic_read(&op->n_pages) <= 0)
+       if (atomic_sub_return_relaxed(n_pages, &op->n_pages) <= 0)
                fscache_op_complete(&op->op, false);
 }
 
index a397907..dd16e82 100644 (file)
@@ -777,8 +777,8 @@ struct ftrace_ret_stack {
 extern void return_to_handler(void);
 
 extern int
-ftrace_push_return_trace(unsigned long ret, unsigned long func, int *depth,
-                        unsigned long frame_pointer, unsigned long *retp);
+function_graph_enter(unsigned long ret, unsigned long func,
+                    unsigned long frame_pointer, unsigned long *retp);
 
 unsigned long ftrace_graph_ret_addr(struct task_struct *task, int *idx,
                                    unsigned long ret, unsigned long *retp);
index 331dc37..dc12f5c 100644 (file)
@@ -177,6 +177,7 @@ int sensor_hub_input_get_attribute_info(struct hid_sensor_hub_device *hsdev,
 * @attr_usage_id:      Attribute usage id as per spec
 * @report_id:  Report id to look for
 * @flag:      Synchronous or asynchronous read
+* @is_signed:   If true then fields < 32 bits will be sign-extended
 *
 * Issues a synchronous or asynchronous read request for an input attribute.
 * Returns data upto 32 bits.
@@ -190,7 +191,8 @@ enum sensor_hub_read_flags {
 int sensor_hub_input_attr_get_raw_value(struct hid_sensor_hub_device *hsdev,
                                        u32 usage_id,
                                        u32 attr_usage_id, u32 report_id,
-                                       enum sensor_hub_read_flags flag
+                                       enum sensor_hub_read_flags flag,
+                                       bool is_signed
 );
 
 /**
index 1d6711c..ca397ff 100644 (file)
@@ -247,10 +247,14 @@ struct irq_affinity_notify {
  *                     the MSI(-X) vector space
  * @post_vectors:      Don't apply affinity to @post_vectors at end of
  *                     the MSI(-X) vector space
+ * @nr_sets:           Length of passed in *sets array
+ * @sets:              Number of affinitized sets
  */
 struct irq_affinity {
        int     pre_vectors;
        int     post_vectors;
+       int     nr_sets;
+       int     *sets;
 };
 
 #if defined(CONFIG_SMP)
index 89c34b2..950e4b2 100644 (file)
@@ -19,7 +19,7 @@
  * the association between their DT compatible string and their
  * initialization function.
  *
- * @name: name that must be unique accross all IRQCHIP_DECLARE of the
+ * @name: name that must be unique across all IRQCHIP_DECLARE of the
  * same file.
  * @compstr: compatible string of the irqchip driver
  * @fn: initialization function
@@ -30,7 +30,7 @@
  * This macro must be used by the different irqchip drivers to declare
  * the association between their version and their initialization function.
  *
- * @name: name that must be unique accross all IRQCHIP_ACPI_DECLARE of the
+ * @name: name that must be unique across all IRQCHIP_ACPI_DECLARE of the
  * same file.
  * @subtable: Subtable to be identified in MADT
  * @validate: Function to be called on that subtable to check its validity.
index dbff9ff..34e17e6 100644 (file)
@@ -2473,14 +2473,15 @@ struct mlx5_ifc_xrc_srqc_bits {
 
        u8         wq_signature[0x1];
        u8         cont_srq[0x1];
-       u8         dbr_umem_valid[0x1];
+       u8         reserved_at_22[0x1];
        u8         rlky[0x1];
        u8         basic_cyclic_rcv_wqe[0x1];
        u8         log_rq_stride[0x3];
        u8         xrcd[0x18];
 
        u8         page_offset[0x6];
-       u8         reserved_at_46[0x2];
+       u8         reserved_at_46[0x1];
+       u8         dbr_umem_valid[0x1];
        u8         cqn[0x18];
 
        u8         reserved_at_60[0x20];
@@ -6689,9 +6690,12 @@ struct mlx5_ifc_create_xrc_srq_in_bits {
 
        struct mlx5_ifc_xrc_srqc_bits xrc_srq_context_entry;
 
-       u8         reserved_at_280[0x40];
+       u8         reserved_at_280[0x60];
+
        u8         xrc_srq_umem_valid[0x1];
-       u8         reserved_at_2c1[0x5bf];
+       u8         reserved_at_2e1[0x1f];
+
+       u8         reserved_at_300[0x580];
 
        u8         pas[0][0x40];
 };
index b8d9556..14edb79 100644 (file)
@@ -21,6 +21,19 @@ struct nf_ct_gre_keymap {
        struct nf_conntrack_tuple tuple;
 };
 
+enum grep_conntrack {
+       GRE_CT_UNREPLIED,
+       GRE_CT_REPLIED,
+       GRE_CT_MAX
+};
+
+struct netns_proto_gre {
+       struct nf_proto_net     nf;
+       rwlock_t                keymap_lock;
+       struct list_head        keymap_list;
+       unsigned int            gre_timeouts[GRE_CT_MAX];
+};
+
 /* add new tuple->key_reply pair to keymap */
 int nf_ct_gre_keymap_add(struct nf_conn *ct, enum ip_conntrack_dir dir,
                         struct nf_conntrack_tuple *t);
index f92a47e..a93841b 100644 (file)
@@ -17,6 +17,8 @@
 #define __DAVINCI_GPIO_PLATFORM_H
 
 struct davinci_gpio_platform_data {
+       bool    no_auto_base;
+       u32     base;
        u32     ngpio;
        u32     gpio_unbanked;
 };
index 8e0725a..7006008 100644 (file)
@@ -1,6 +1,7 @@
 #ifndef _LINUX_PSI_H
 #define _LINUX_PSI_H
 
+#include <linux/jump_label.h>
 #include <linux/psi_types.h>
 #include <linux/sched.h>
 
@@ -9,7 +10,7 @@ struct css_set;
 
 #ifdef CONFIG_PSI
 
-extern bool psi_disabled;
+extern struct static_key_false psi_disabled;
 
 void psi_init(void);
 
index a15bc4d..30fcec3 100644 (file)
@@ -90,7 +90,10 @@ struct pstore_record {
  *
  * @buf_lock:  spinlock to serialize access to @buf
  * @buf:       preallocated crash dump buffer
- * @bufsize:   size of @buf available for crash dump writes
+ * @bufsize:   size of @buf available for crash dump bytes (must match
+ *             smallest number of bytes available for writing to a
+ *             backend entry, since compressed bytes don't take kindly
+ *             to being truncated)
  *
  * @read_mutex:        serializes @open, @read, @close, and @erase callbacks
  * @flags:     bitfield of frontends the backend can accept writes for
index 6c2ffed..de20ede 100644 (file)
@@ -64,15 +64,12 @@ extern void exit_ptrace(struct task_struct *tracer, struct list_head *dead);
 #define PTRACE_MODE_NOAUDIT    0x04
 #define PTRACE_MODE_FSCREDS    0x08
 #define PTRACE_MODE_REALCREDS  0x10
-#define PTRACE_MODE_SCHED      0x20
-#define PTRACE_MODE_IBPB       0x40
 
 /* shorthands for READ/ATTACH and FSCREDS/REALCREDS combinations */
 #define PTRACE_MODE_READ_FSCREDS (PTRACE_MODE_READ | PTRACE_MODE_FSCREDS)
 #define PTRACE_MODE_READ_REALCREDS (PTRACE_MODE_READ | PTRACE_MODE_REALCREDS)
 #define PTRACE_MODE_ATTACH_FSCREDS (PTRACE_MODE_ATTACH | PTRACE_MODE_FSCREDS)
 #define PTRACE_MODE_ATTACH_REALCREDS (PTRACE_MODE_ATTACH | PTRACE_MODE_REALCREDS)
-#define PTRACE_MODE_SPEC_IBPB (PTRACE_MODE_ATTACH_REALCREDS | PTRACE_MODE_IBPB)
 
 /**
  * ptrace_may_access - check whether the caller is permitted to access
@@ -90,20 +87,6 @@ extern void exit_ptrace(struct task_struct *tracer, struct list_head *dead);
  */
 extern bool ptrace_may_access(struct task_struct *task, unsigned int mode);
 
-/**
- * ptrace_may_access - check whether the caller is permitted to access
- * a target task.
- * @task: target task
- * @mode: selects type of access and caller credentials
- *
- * Returns true on success, false on denial.
- *
- * Similar to ptrace_may_access(). Only to be called from context switch
- * code. Does not call into audit and the regular LSM hooks due to locking
- * constraints.
- */
-extern bool ptrace_may_access_sched(struct task_struct *task, unsigned int mode);
-
 static inline int ptrace_reparented(struct task_struct *child)
 {
        return !same_thread_group(child->real_parent, child->parent);
index a51c13c..291a9bd 100644 (file)
@@ -1116,6 +1116,7 @@ struct task_struct {
 #ifdef CONFIG_FUNCTION_GRAPH_TRACER
        /* Index of current stored address in ret_stack: */
        int                             curr_ret_stack;
+       int                             curr_ret_depth;
 
        /* Stack of return addresses for return function tracing: */
        struct ftrace_ret_stack         *ret_stack;
@@ -1453,6 +1454,8 @@ static inline bool is_percpu_thread(void)
 #define PFA_SPREAD_SLAB                        2       /* Spread some slab caches over cpuset */
 #define PFA_SPEC_SSB_DISABLE           3       /* Speculative Store Bypass disabled */
 #define PFA_SPEC_SSB_FORCE_DISABLE     4       /* Speculative Store Bypass force disabled*/
+#define PFA_SPEC_IB_DISABLE            5       /* Indirect branch speculation restricted */
+#define PFA_SPEC_IB_FORCE_DISABLE      6       /* Indirect branch speculation permanently restricted */
 
 #define TASK_PFA_TEST(name, func)                                      \
        static inline bool task_##func(struct task_struct *p)           \
@@ -1484,6 +1487,13 @@ TASK_PFA_CLEAR(SPEC_SSB_DISABLE, spec_ssb_disable)
 TASK_PFA_TEST(SPEC_SSB_FORCE_DISABLE, spec_ssb_force_disable)
 TASK_PFA_SET(SPEC_SSB_FORCE_DISABLE, spec_ssb_force_disable)
 
+TASK_PFA_TEST(SPEC_IB_DISABLE, spec_ib_disable)
+TASK_PFA_SET(SPEC_IB_DISABLE, spec_ib_disable)
+TASK_PFA_CLEAR(SPEC_IB_DISABLE, spec_ib_disable)
+
+TASK_PFA_TEST(SPEC_IB_FORCE_DISABLE, spec_ib_force_disable)
+TASK_PFA_SET(SPEC_IB_FORCE_DISABLE, spec_ib_force_disable)
+
 static inline void
 current_restore_flags(unsigned long orig_flags, unsigned long flags)
 {
diff --git a/include/linux/sched/smt.h b/include/linux/sched/smt.h
new file mode 100644 (file)
index 0000000..59d3736
--- /dev/null
@@ -0,0 +1,20 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+#ifndef _LINUX_SCHED_SMT_H
+#define _LINUX_SCHED_SMT_H
+
+#include <linux/static_key.h>
+
+#ifdef CONFIG_SCHED_SMT
+extern struct static_key_false sched_smt_present;
+
+static __always_inline bool sched_smt_active(void)
+{
+       return static_branch_likely(&sched_smt_present);
+}
+#else
+static inline bool sched_smt_active(void) { return false; }
+#endif
+
+void arch_smt_update(void);
+
+#endif
index 40b0b4c..df20f8b 100644 (file)
@@ -83,8 +83,8 @@ static inline int ptrace_report_syscall(struct pt_regs *regs)
  * tracehook_report_syscall_entry - task is about to attempt a system call
  * @regs:              user register state of current task
  *
- * This will be called if %TIF_SYSCALL_TRACE has been set, when the
- * current task has just entered the kernel for a system call.
+ * This will be called if %TIF_SYSCALL_TRACE or %TIF_SYSCALL_EMU have been set,
+ * when the current task has just entered the kernel for a system call.
  * Full user register state is available here.  Changing the values
  * in @regs can affect the system call number and arguments to be tried.
  * It is safe to block here, preventing the system call from beginning.
index 538ba1a..e9de8ad 100644 (file)
@@ -166,7 +166,7 @@ static inline struct tracepoint *tracepoint_ptr_deref(tracepoint_ptr_t *p)
                struct tracepoint_func *it_func_ptr;                    \
                void *it_func;                                          \
                void *__data;                                           \
-               int __maybe_unused idx = 0;                             \
+               int __maybe_unused __idx = 0;                           \
                                                                        \
                if (!(cond))                                            \
                        return;                                         \
@@ -182,7 +182,7 @@ static inline struct tracepoint *tracepoint_ptr_deref(tracepoint_ptr_t *p)
                 * doesn't work from the idle path.                     \
                 */                                                     \
                if (rcuidle) {                                          \
-                       idx = srcu_read_lock_notrace(&tracepoint_srcu); \
+                       __idx = srcu_read_lock_notrace(&tracepoint_srcu);\
                        rcu_irq_enter_irqson();                         \
                }                                                       \
                                                                        \
@@ -198,7 +198,7 @@ static inline struct tracepoint *tracepoint_ptr_deref(tracepoint_ptr_t *p)
                                                                        \
                if (rcuidle) {                                          \
                        rcu_irq_exit_irqson();                          \
-                       srcu_read_unlock_notrace(&tracepoint_srcu, idx);\
+                       srcu_read_unlock_notrace(&tracepoint_srcu, __idx);\
                }                                                       \
                                                                        \
                preempt_enable_notrace();                               \
index cd24be4..13d5520 100644 (file)
@@ -9,7 +9,7 @@ nf_nat_masquerade_ipv4(struct sk_buff *skb, unsigned int hooknum,
                       const struct nf_nat_range2 *range,
                       const struct net_device *out);
 
-void nf_nat_masquerade_ipv4_register_notifier(void);
+int nf_nat_masquerade_ipv4_register_notifier(void);
 void nf_nat_masquerade_ipv4_unregister_notifier(void);
 
 #endif /*_NF_NAT_MASQUERADE_IPV4_H_ */
index 0c3b5eb..2917bf9 100644 (file)
@@ -5,7 +5,7 @@
 unsigned int
 nf_nat_masquerade_ipv6(struct sk_buff *skb, const struct nf_nat_range2 *range,
                       const struct net_device *out);
-void nf_nat_masquerade_ipv6_register_notifier(void);
+int nf_nat_masquerade_ipv6_register_notifier(void);
 void nf_nat_masquerade_ipv6_unregister_notifier(void);
 
 #endif /* _NF_NAT_MASQUERADE_IPV6_H_ */
index f1dab1f..70c10a8 100644 (file)
@@ -1192,7 +1192,7 @@ struct snd_soc_pcm_runtime {
             ((i) < rtd->num_codecs) && ((dai) = rtd->codec_dais[i]); \
             (i)++)
 #define for_each_rtd_codec_dai_rollback(rtd, i, dai)           \
-       for (; ((i--) >= 0) && ((dai) = rtd->codec_dais[i]);)
+       for (; ((--i) >= 0) && ((dai) = rtd->codec_dais[i]);)
 
 
 /* mixer control */
index f07b270..9a4bdfa 100644 (file)
@@ -107,6 +107,8 @@ DEFINE_EVENT(sched_wakeup_template, sched_wakeup_new,
 #ifdef CREATE_TRACE_POINTS
 static inline long __trace_sched_switch_state(bool preempt, struct task_struct *p)
 {
+       unsigned int state;
+
 #ifdef CONFIG_SCHED_DEBUG
        BUG_ON(p != current);
 #endif /* CONFIG_SCHED_DEBUG */
@@ -118,7 +120,15 @@ static inline long __trace_sched_switch_state(bool preempt, struct task_struct *
        if (preempt)
                return TASK_REPORT_MAX;
 
-       return 1 << task_state_index(p);
+       /*
+        * task_state_index() uses fls() and returns a value from 0-8 range.
+        * Decrement it by 1 (except TASK_RUNNING state i.e 0) before using
+        * it for left shift operation to get the correct task->state
+        * mapping.
+        */
+       state = task_state_index(p);
+
+       return state ? (1 << (state - 1)) : state;
 }
 #endif /* CREATE_TRACE_POINTS */
 
index c0d7ea0..b17201e 100644 (file)
@@ -212,6 +212,7 @@ struct prctl_mm_map {
 #define PR_SET_SPECULATION_CTRL                53
 /* Speculation control variants */
 # define PR_SPEC_STORE_BYPASS          0
+# define PR_SPEC_INDIRECT_BRANCH       1
 /* Return and control values for PR_SET/GET_SPECULATION_CTRL */
 # define PR_SPEC_NOT_AFFECTED          0
 # define PR_SPEC_PRCTL                 (1UL << 0)
index 61f410f..4914b93 100644 (file)
@@ -44,8 +44,3 @@ static inline void xen_balloon_init(void)
 {
 }
 #endif
-
-#ifdef CONFIG_XEN_BALLOON_MEMORY_HOTPLUG
-struct resource;
-void arch_xen_balloon_init(struct resource *hostmem_resource);
-#endif
index a4112e9..cf5b5a0 100644 (file)
@@ -509,6 +509,15 @@ config PSI
 
          Say N if unsure.
 
+config PSI_DEFAULT_DISABLED
+       bool "Require boot parameter to enable pressure stall information tracking"
+       default n
+       depends on PSI
+       help
+         If set, pressure stall information tracking will be disabled
+         per default but can be enabled through passing psi_enable=1
+         on the kernel commandline during boot.
+
 endmenu # "CPU/Task time and stats accounting"
 
 config CPU_ISOLATION
index 6405577..f6f4a1e 100644 (file)
@@ -291,16 +291,6 @@ static int __init do_reset(void)
        return 1;
 }
 
-static int __init maybe_link(void)
-{
-       if (nlink >= 2) {
-               char *old = find_link(major, minor, ino, mode, collected);
-               if (old)
-                       return (ksys_link(old, collected) < 0) ? -1 : 1;
-       }
-       return 0;
-}
-
 static void __init clean_path(char *path, umode_t fmode)
 {
        struct kstat st;
@@ -313,6 +303,18 @@ static void __init clean_path(char *path, umode_t fmode)
        }
 }
 
+static int __init maybe_link(void)
+{
+       if (nlink >= 2) {
+               char *old = find_link(major, minor, ino, mode, collected);
+               if (old) {
+                       clean_path(collected, 0);
+                       return (ksys_link(old, collected) < 0) ? -1 : 1;
+               }
+       }
+       return 0;
+}
+
 static __initdata int wfd;
 
 static int __init do_name(void)
index 1a796e0..b1a3545 100644 (file)
@@ -672,6 +672,40 @@ void __weak bpf_jit_free(struct bpf_prog *fp)
        bpf_prog_unlock_free(fp);
 }
 
+int bpf_jit_get_func_addr(const struct bpf_prog *prog,
+                         const struct bpf_insn *insn, bool extra_pass,
+                         u64 *func_addr, bool *func_addr_fixed)
+{
+       s16 off = insn->off;
+       s32 imm = insn->imm;
+       u8 *addr;
+
+       *func_addr_fixed = insn->src_reg != BPF_PSEUDO_CALL;
+       if (!*func_addr_fixed) {
+               /* Place-holder address till the last pass has collected
+                * all addresses for JITed subprograms in which case we
+                * can pick them up from prog->aux.
+                */
+               if (!extra_pass)
+                       addr = NULL;
+               else if (prog->aux->func &&
+                        off >= 0 && off < prog->aux->func_cnt)
+                       addr = (u8 *)prog->aux->func[off]->bpf_func;
+               else
+                       return -EINVAL;
+       } else {
+               /* Address of a BPF helper call. Since part of the core
+                * kernel, it's always at a fixed location. __bpf_call_base
+                * and the helper with imm relative to it are both in core
+                * kernel.
+                */
+               addr = (u8 *)__bpf_call_base + imm;
+       }
+
+       *func_addr = (unsigned long)addr;
+       return 0;
+}
+
 static int bpf_jit_blind_insn(const struct bpf_insn *from,
                              const struct bpf_insn *aux,
                              struct bpf_insn *to_buff)
index c97a8f9..bed9d48 100644 (file)
@@ -139,7 +139,8 @@ static int cgroup_storage_update_elem(struct bpf_map *map, void *_key,
                return -ENOENT;
 
        new = kmalloc_node(sizeof(struct bpf_storage_buffer) +
-                          map->value_size, __GFP_ZERO | GFP_USER,
+                          map->value_size,
+                          __GFP_ZERO | GFP_ATOMIC | __GFP_NOWARN,
                           map->numa_node);
        if (!new)
                return -ENOMEM;
index 8bbd72d..b384ea9 100644 (file)
@@ -7,6 +7,7 @@
 #include <linux/bpf.h>
 #include <linux/list.h>
 #include <linux/slab.h>
+#include <linux/capability.h>
 #include "percpu_freelist.h"
 
 #define QUEUE_STACK_CREATE_FLAG_MASK \
@@ -45,8 +46,12 @@ static bool queue_stack_map_is_full(struct bpf_queue_stack *qs)
 /* Called from syscall */
 static int queue_stack_map_alloc_check(union bpf_attr *attr)
 {
+       if (!capable(CAP_SYS_ADMIN))
+               return -EPERM;
+
        /* check sanity of attributes */
        if (attr->max_entries == 0 || attr->key_size != 0 ||
+           attr->value_size == 0 ||
            attr->map_flags & ~QUEUE_STACK_CREATE_FLAG_MASK)
                return -EINVAL;
 
@@ -63,15 +68,10 @@ static struct bpf_map *queue_stack_map_alloc(union bpf_attr *attr)
 {
        int ret, numa_node = bpf_map_attr_numa_node(attr);
        struct bpf_queue_stack *qs;
-       u32 size, value_size;
-       u64 queue_size, cost;
-
-       size = attr->max_entries + 1;
-       value_size = attr->value_size;
-
-       queue_size = sizeof(*qs) + (u64) value_size * size;
+       u64 size, queue_size, cost;
 
-       cost = queue_size;
+       size = (u64) attr->max_entries + 1;
+       cost = queue_size = sizeof(*qs) + size * attr->value_size;
        if (cost >= U32_MAX - PAGE_SIZE)
                return ERR_PTR(-E2BIG);
 
index 1971ca3..6dd4195 100644 (file)
@@ -5650,7 +5650,7 @@ static void adjust_subprog_starts(struct bpf_verifier_env *env, u32 off, u32 len
                return;
        /* NOTE: fake 'exit' subprog should be updated as well. */
        for (i = 0; i <= env->subprog_cnt; i++) {
-               if (env->subprog_info[i].start < off)
+               if (env->subprog_info[i].start <= off)
                        continue;
                env->subprog_info[i].start += len - 1;
        }
index 3c7f3b4..91d5c38 100644 (file)
@@ -10,6 +10,7 @@
 #include <linux/sched/signal.h>
 #include <linux/sched/hotplug.h>
 #include <linux/sched/task.h>
+#include <linux/sched/smt.h>
 #include <linux/unistd.h>
 #include <linux/cpu.h>
 #include <linux/oom.h>
@@ -367,6 +368,12 @@ static void lockdep_release_cpus_lock(void)
 
 #endif /* CONFIG_HOTPLUG_CPU */
 
+/*
+ * Architectures that need SMT-specific errata handling during SMT hotplug
+ * should override this.
+ */
+void __weak arch_smt_update(void) { }
+
 #ifdef CONFIG_HOTPLUG_SMT
 enum cpuhp_smt_control cpu_smt_control __read_mostly = CPU_SMT_ENABLED;
 EXPORT_SYMBOL_GPL(cpu_smt_control);
@@ -1011,6 +1018,7 @@ out:
         * concurrent CPU hotplug via cpu_add_remove_lock.
         */
        lockup_detector_cleanup();
+       arch_smt_update();
        return ret;
 }
 
@@ -1139,6 +1147,7 @@ static int _cpu_up(unsigned int cpu, int tasks_frozen, enum cpuhp_state target)
        ret = cpuhp_up_callbacks(cpu, st, target);
 out:
        cpus_write_unlock();
+       arch_smt_update();
        return ret;
 }
 
@@ -2055,12 +2064,6 @@ static void cpuhp_online_cpu_device(unsigned int cpu)
        kobject_uevent(&dev->kobj, KOBJ_ONLINE);
 }
 
-/*
- * Architectures that need SMT-specific errata handling during SMT hotplug
- * should override this.
- */
-void __weak arch_smt_update(void) { };
-
 static int cpuhp_smt_disable(enum cpuhp_smt_control ctrlval)
 {
        int cpu, ret = 0;
index 96d4bee..322e97b 100644 (file)
@@ -829,7 +829,7 @@ static int prepare_uprobe(struct uprobe *uprobe, struct file *file,
        BUG_ON((uprobe->offset & ~PAGE_MASK) +
                        UPROBE_SWBP_INSN_SIZE > PAGE_SIZE);
 
-       smp_wmb(); /* pairs with rmb() in find_active_uprobe() */
+       smp_wmb(); /* pairs with the smp_rmb() in handle_swbp() */
        set_bit(UPROBE_COPY_INSN, &uprobe->flags);
 
  out:
@@ -2178,10 +2178,18 @@ static void handle_swbp(struct pt_regs *regs)
         * After we hit the bp, _unregister + _register can install the
         * new and not-yet-analyzed uprobe at the same address, restart.
         */
-       smp_rmb(); /* pairs with wmb() in install_breakpoint() */
        if (unlikely(!test_bit(UPROBE_COPY_INSN, &uprobe->flags)))
                goto out;
 
+       /*
+        * Pairs with the smp_wmb() in prepare_uprobe().
+        *
+        * Guarantees that if we see the UPROBE_COPY_INSN bit set, then
+        * we must also see the stores to &uprobe->arch performed by the
+        * prepare_uprobe() call.
+        */
+       smp_rmb();
+
        /* Tracing handlers use ->utask to communicate with fetch methods */
        if (!get_utask())
                goto out;
index f4f29b9..08c904e 100644 (file)
@@ -94,15 +94,15 @@ static int get_nodes_in_cpumask(cpumask_var_t *node_to_cpumask,
        return nodes;
 }
 
-static int irq_build_affinity_masks(const struct irq_affinity *affd,
-                                   int startvec, int numvecs,
+static int __irq_build_affinity_masks(const struct irq_affinity *affd,
+                                   int startvec, int numvecs, int firstvec,
                                    cpumask_var_t *node_to_cpumask,
                                    const struct cpumask *cpu_mask,
                                    struct cpumask *nmsk,
                                    struct cpumask *masks)
 {
        int n, nodes, cpus_per_vec, extra_vecs, done = 0;
-       int last_affv = affd->pre_vectors + numvecs;
+       int last_affv = firstvec + numvecs;
        int curvec = startvec;
        nodemask_t nodemsk = NODE_MASK_NONE;
 
@@ -117,12 +117,11 @@ static int irq_build_affinity_masks(const struct irq_affinity *affd,
         */
        if (numvecs <= nodes) {
                for_each_node_mask(n, nodemsk) {
-                       cpumask_copy(masks + curvec, node_to_cpumask[n]);
-                       if (++done == numvecs)
-                               break;
+                       cpumask_or(masks + curvec, masks + curvec, node_to_cpumask[n]);
                        if (++curvec == last_affv)
-                               curvec = affd->pre_vectors;
+                               curvec = firstvec;
                }
+               done = numvecs;
                goto out;
        }
 
@@ -130,7 +129,7 @@ static int irq_build_affinity_masks(const struct irq_affinity *affd,
                int ncpus, v, vecs_to_assign, vecs_per_node;
 
                /* Spread the vectors per node */
-               vecs_per_node = (numvecs - (curvec - affd->pre_vectors)) / nodes;
+               vecs_per_node = (numvecs - (curvec - firstvec)) / nodes;
 
                /* Get the cpus on this node which are in the mask */
                cpumask_and(nmsk, cpu_mask, node_to_cpumask[n]);
@@ -158,7 +157,7 @@ static int irq_build_affinity_masks(const struct irq_affinity *affd,
                if (done >= numvecs)
                        break;
                if (curvec >= last_affv)
-                       curvec = affd->pre_vectors;
+                       curvec = firstvec;
                --nodes;
        }
 
@@ -166,6 +165,62 @@ out:
        return done;
 }
 
+/*
+ * build affinity in two stages:
+ *     1) spread present CPU on these vectors
+ *     2) spread other possible CPUs on these vectors
+ */
+static int irq_build_affinity_masks(const struct irq_affinity *affd,
+                                   int startvec, int numvecs, int firstvec,
+                                   cpumask_var_t *node_to_cpumask,
+                                   struct cpumask *masks)
+{
+       int curvec = startvec, nr_present, nr_others;
+       int ret = -ENOMEM;
+       cpumask_var_t nmsk, npresmsk;
+
+       if (!zalloc_cpumask_var(&nmsk, GFP_KERNEL))
+                       return ret;
+
+       if (!zalloc_cpumask_var(&npresmsk, GFP_KERNEL))
+                       goto fail;
+
+       ret = 0;
+       /* Stabilize the cpumasks */
+       get_online_cpus();
+       build_node_to_cpumask(node_to_cpumask);
+
+       /* Spread on present CPUs starting from affd->pre_vectors */
+       nr_present = __irq_build_affinity_masks(affd, curvec, numvecs,
+                                               firstvec, node_to_cpumask,
+                                               cpu_present_mask, nmsk, masks);
+
+       /*
+        * Spread on non present CPUs starting from the next vector to be
+        * handled. If the spreading of present CPUs already exhausted the
+        * vector space, assign the non present CPUs to the already spread
+        * out vectors.
+        */
+       if (nr_present >= numvecs)
+               curvec = firstvec;
+       else
+               curvec = firstvec + nr_present;
+       cpumask_andnot(npresmsk, cpu_possible_mask, cpu_present_mask);
+       nr_others = __irq_build_affinity_masks(affd, curvec, numvecs,
+                                              firstvec, node_to_cpumask,
+                                              npresmsk, nmsk, masks);
+       put_online_cpus();
+
+       if (nr_present < numvecs)
+                       WARN_ON(nr_present + nr_others < numvecs);
+
+       free_cpumask_var(npresmsk);
+
+ fail:
+       free_cpumask_var(nmsk);
+       return ret;
+}
+
 /**
  * irq_create_affinity_masks - Create affinity masks for multiqueue spreading
  * @nvecs:     The total number of vectors
@@ -178,8 +233,9 @@ irq_create_affinity_masks(int nvecs, const struct irq_affinity *affd)
 {
        int affvecs = nvecs - affd->pre_vectors - affd->post_vectors;
        int curvec, usedvecs;
-       cpumask_var_t nmsk, npresmsk, *node_to_cpumask;
+       cpumask_var_t *node_to_cpumask;
        struct cpumask *masks = NULL;
+       int i, nr_sets;
 
        /*
         * If there aren't any vectors left after applying the pre/post
@@ -188,15 +244,9 @@ irq_create_affinity_masks(int nvecs, const struct irq_affinity *affd)
        if (nvecs == affd->pre_vectors + affd->post_vectors)
                return NULL;
 
-       if (!zalloc_cpumask_var(&nmsk, GFP_KERNEL))
-               return NULL;
-
-       if (!zalloc_cpumask_var(&npresmsk, GFP_KERNEL))
-               goto outcpumsk;
-
        node_to_cpumask = alloc_node_to_cpumask();
        if (!node_to_cpumask)
-               goto outnpresmsk;
+               return NULL;
 
        masks = kcalloc(nvecs, sizeof(*masks), GFP_KERNEL);
        if (!masks)
@@ -206,30 +256,28 @@ irq_create_affinity_masks(int nvecs, const struct irq_affinity *affd)
        for (curvec = 0; curvec < affd->pre_vectors; curvec++)
                cpumask_copy(masks + curvec, irq_default_affinity);
 
-       /* Stabilize the cpumasks */
-       get_online_cpus();
-       build_node_to_cpumask(node_to_cpumask);
-
-       /* Spread on present CPUs starting from affd->pre_vectors */
-       usedvecs = irq_build_affinity_masks(affd, curvec, affvecs,
-                                           node_to_cpumask, cpu_present_mask,
-                                           nmsk, masks);
-
        /*
-        * Spread on non present CPUs starting from the next vector to be
-        * handled. If the spreading of present CPUs already exhausted the
-        * vector space, assign the non present CPUs to the already spread
-        * out vectors.
+        * Spread on present CPUs starting from affd->pre_vectors. If we
+        * have multiple sets, build each sets affinity mask separately.
         */
-       if (usedvecs >= affvecs)
-               curvec = affd->pre_vectors;
-       else
-               curvec = affd->pre_vectors + usedvecs;
-       cpumask_andnot(npresmsk, cpu_possible_mask, cpu_present_mask);
-       usedvecs += irq_build_affinity_masks(affd, curvec, affvecs,
-                                            node_to_cpumask, npresmsk,
-                                            nmsk, masks);
-       put_online_cpus();
+       nr_sets = affd->nr_sets;
+       if (!nr_sets)
+               nr_sets = 1;
+
+       for (i = 0, usedvecs = 0; i < nr_sets; i++) {
+               int this_vecs = affd->sets ? affd->sets[i] : affvecs;
+               int ret;
+
+               ret = irq_build_affinity_masks(affd, curvec, this_vecs,
+                                               curvec, node_to_cpumask, masks);
+               if (ret) {
+                               kfree(masks);
+                               masks = NULL;
+                               goto outnodemsk;
+               }
+               curvec += this_vecs;
+               usedvecs += this_vecs;
+       }
 
        /* Fill out vectors at the end that don't need affinity */
        if (usedvecs >= affvecs)
@@ -241,10 +289,6 @@ irq_create_affinity_masks(int nvecs, const struct irq_affinity *affd)
 
 outnodemsk:
        free_node_to_cpumask(node_to_cpumask);
-outnpresmsk:
-       free_cpumask_var(npresmsk);
-outcpumsk:
-       free_cpumask_var(nmsk);
        return masks;
 }
 
@@ -258,13 +302,21 @@ int irq_calc_affinity_vectors(int minvec, int maxvec, const struct irq_affinity
 {
        int resv = affd->pre_vectors + affd->post_vectors;
        int vecs = maxvec - resv;
-       int ret;
+       int set_vecs;
 
        if (resv > minvec)
                return 0;
 
-       get_online_cpus();
-       ret = min_t(int, cpumask_weight(cpu_possible_mask), vecs) + resv;
-       put_online_cpus();
-       return ret;
+       if (affd->nr_sets) {
+               int i;
+
+               for (i = 0, set_vecs = 0;  i < affd->nr_sets; i++)
+                       set_vecs += affd->sets[i];
+       } else {
+               get_online_cpus();
+               set_vecs = cpumask_weight(cpu_possible_mask);
+               put_online_cpus();
+       }
+
+       return resv + min(set_vecs, vecs);
 }
index a2b3d9d..34e9690 100644 (file)
@@ -929,7 +929,7 @@ __irq_do_set_handler(struct irq_desc *desc, irq_flow_handler_t handle,
                                break;
                        /*
                         * Bail out if the outer chip is not set up
-                        * and the interrrupt supposed to be started
+                        * and the interrupt supposed to be started
                         * right away.
                         */
                        if (WARN_ON(is_chained))
index 8b778e3..43e3d1b 100644 (file)
@@ -56,7 +56,7 @@ int irq_reserve_ipi(struct irq_domain *domain,
                unsigned int next;
 
                /*
-                * The IPI requires a seperate HW irq on each CPU. We require
+                * The IPI requires a separate HW irq on each CPU. We require
                 * that the destination mask is consecutive. If an
                 * implementation needs to support holes, it can reserve
                 * several IPI ranges.
@@ -172,7 +172,7 @@ irq_hw_number_t ipi_get_hwirq(unsigned int irq, unsigned int cpu)
 
        /*
         * Get the real hardware irq number if the underlying implementation
-        * uses a seperate irq per cpu. If the underlying implementation uses
+        * uses a separate irq per cpu. If the underlying implementation uses
         * a single hardware irq for all cpus then the IPI send mechanism
         * needs to take care of the cpu destinations.
         */
index 9dbdcca..a4888ce 100644 (file)
@@ -915,7 +915,7 @@ irq_thread_check_affinity(struct irq_desc *desc, struct irqaction *action) { }
 #endif
 
 /*
- * Interrupts which are not explicitely requested as threaded
+ * Interrupts which are not explicitly requested as threaded
  * interrupts rely on the implicit bh/preempt disable of the hard irq
  * context. So we need to disable bh here to avoid deadlocks and other
  * side effects.
index 1f0985a..30cc217 100644 (file)
@@ -14,6 +14,7 @@ struct cpumap {
        unsigned int            available;
        unsigned int            allocated;
        unsigned int            managed;
+       unsigned int            managed_allocated;
        bool                    initialized;
        bool                    online;
        unsigned long           alloc_map[IRQ_MATRIX_SIZE];
@@ -145,6 +146,27 @@ static unsigned int matrix_find_best_cpu(struct irq_matrix *m,
        return best_cpu;
 }
 
+/* Find the best CPU which has the lowest number of managed IRQs allocated */
+static unsigned int matrix_find_best_cpu_managed(struct irq_matrix *m,
+                                               const struct cpumask *msk)
+{
+       unsigned int cpu, best_cpu, allocated = UINT_MAX;
+       struct cpumap *cm;
+
+       best_cpu = UINT_MAX;
+
+       for_each_cpu(cpu, msk) {
+               cm = per_cpu_ptr(m->maps, cpu);
+
+               if (!cm->online || cm->managed_allocated > allocated)
+                       continue;
+
+               best_cpu = cpu;
+               allocated = cm->managed_allocated;
+       }
+       return best_cpu;
+}
+
 /**
  * irq_matrix_assign_system - Assign system wide entry in the matrix
  * @m:         Matrix pointer
@@ -269,7 +291,7 @@ int irq_matrix_alloc_managed(struct irq_matrix *m, const struct cpumask *msk,
        if (cpumask_empty(msk))
                return -EINVAL;
 
-       cpu = matrix_find_best_cpu(m, msk);
+       cpu = matrix_find_best_cpu_managed(m, msk);
        if (cpu == UINT_MAX)
                return -ENOSPC;
 
@@ -282,6 +304,7 @@ int irq_matrix_alloc_managed(struct irq_matrix *m, const struct cpumask *msk,
                return -ENOSPC;
        set_bit(bit, cm->alloc_map);
        cm->allocated++;
+       cm->managed_allocated++;
        m->total_allocated++;
        *mapped_cpu = cpu;
        trace_irq_matrix_alloc_managed(bit, cpu, m, cm);
@@ -395,6 +418,8 @@ void irq_matrix_free(struct irq_matrix *m, unsigned int cpu,
 
        clear_bit(bit, cm->alloc_map);
        cm->allocated--;
+       if(managed)
+               cm->managed_allocated--;
 
        if (cm->online)
                m->total_allocated--;
@@ -464,13 +489,14 @@ void irq_matrix_debug_show(struct seq_file *sf, struct irq_matrix *m, int ind)
        seq_printf(sf, "Total allocated:  %6u\n", m->total_allocated);
        seq_printf(sf, "System: %u: %*pbl\n", nsys, m->matrix_bits,
                   m->system_map);
-       seq_printf(sf, "%*s| CPU | avl | man | act | vectors\n", ind, " ");
+       seq_printf(sf, "%*s| CPU | avl | man | mac | act | vectors\n", ind, " ");
        cpus_read_lock();
        for_each_online_cpu(cpu) {
                struct cpumap *cm = per_cpu_ptr(m->maps, cpu);
 
-               seq_printf(sf, "%*s %4d  %4u  %4u  %4u  %*pbl\n", ind, " ",
-                          cpu, cm->available, cm->managed, cm->allocated,
+               seq_printf(sf, "%*s %4d  %4u  %4u  %4u %4u  %*pbl\n", ind, " ",
+                          cpu, cm->available, cm->managed,
+                          cm->managed_allocated, cm->allocated,
                           m->matrix_bits, cm->alloc_map);
        }
        cpus_read_unlock();
index d867d6d..6d2fa69 100644 (file)
@@ -66,7 +66,7 @@ static int try_one_irq(struct irq_desc *desc, bool force)
        raw_spin_lock(&desc->lock);
 
        /*
-        * PER_CPU, nested thread interrupts and interrupts explicitely
+        * PER_CPU, nested thread interrupts and interrupts explicitly
         * marked polled are excluded from polling.
         */
        if (irq_settings_is_per_cpu(desc) ||
@@ -76,7 +76,7 @@ static int try_one_irq(struct irq_desc *desc, bool force)
 
        /*
         * Do not poll disabled interrupts unless the spurious
-        * disabled poller asks explicitely.
+        * disabled poller asks explicitly.
         */
        if (irqd_irq_disabled(&desc->irq_data) && !force)
                goto out;
@@ -292,7 +292,7 @@ void note_interrupt(struct irq_desc *desc, irqreturn_t action_ret)
         * So in case a thread is woken, we just note the fact and
         * defer the analysis to the next hardware interrupt.
         *
-        * The threaded handlers store whether they sucessfully
+        * The threaded handlers store whether they successfully
         * handled an interrupt and we check whether that number
         * changed versus the last invocation.
         *
index 3ebd09e..97959d7 100644 (file)
@@ -56,7 +56,7 @@ struct kcov {
        struct task_struct      *t;
 };
 
-static bool check_kcov_mode(enum kcov_mode needed_mode, struct task_struct *t)
+static notrace bool check_kcov_mode(enum kcov_mode needed_mode, struct task_struct *t)
 {
        unsigned int mode;
 
@@ -78,7 +78,7 @@ static bool check_kcov_mode(enum kcov_mode needed_mode, struct task_struct *t)
        return mode == needed_mode;
 }
 
-static unsigned long canonicalize_ip(unsigned long ip)
+static notrace unsigned long canonicalize_ip(unsigned long ip)
 {
 #ifdef CONFIG_RANDOMIZE_BASE
        ip -= kaslr_offset();
index 80b34df..c2cee9d 100644 (file)
@@ -261,9 +261,6 @@ static int ptrace_check_attach(struct task_struct *child, bool ignore_state)
 
 static int ptrace_has_cap(struct user_namespace *ns, unsigned int mode)
 {
-       if (mode & PTRACE_MODE_SCHED)
-               return false;
-
        if (mode & PTRACE_MODE_NOAUDIT)
                return has_ns_capability_noaudit(current, ns, CAP_SYS_PTRACE);
        else
@@ -331,16 +328,9 @@ ok:
             !ptrace_has_cap(mm->user_ns, mode)))
            return -EPERM;
 
-       if (mode & PTRACE_MODE_SCHED)
-               return 0;
        return security_ptrace_access_check(task, mode);
 }
 
-bool ptrace_may_access_sched(struct task_struct *task, unsigned int mode)
-{
-       return __ptrace_may_access(task, mode | PTRACE_MODE_SCHED);
-}
-
 bool ptrace_may_access(struct task_struct *task, unsigned int mode)
 {
        int err;
index 091e089..6fedf3a 100644 (file)
@@ -5738,15 +5738,10 @@ int sched_cpu_activate(unsigned int cpu)
 
 #ifdef CONFIG_SCHED_SMT
        /*
-        * The sched_smt_present static key needs to be evaluated on every
-        * hotplug event because at boot time SMT might be disabled when
-        * the number of booted CPUs is limited.
-        *
-        * If then later a sibling gets hotplugged, then the key would stay
-        * off and SMT scheduling would never be functional.
+        * When going up, increment the number of cores with SMT present.
         */
-       if (cpumask_weight(cpu_smt_mask(cpu)) > 1)
-               static_branch_enable_cpuslocked(&sched_smt_present);
+       if (cpumask_weight(cpu_smt_mask(cpu)) == 2)
+               static_branch_inc_cpuslocked(&sched_smt_present);
 #endif
        set_cpu_active(cpu, true);
 
@@ -5790,6 +5785,14 @@ int sched_cpu_deactivate(unsigned int cpu)
         */
        synchronize_rcu_mult(call_rcu, call_rcu_sched);
 
+#ifdef CONFIG_SCHED_SMT
+       /*
+        * When going down, decrement the number of cores with SMT present.
+        */
+       if (cpumask_weight(cpu_smt_mask(cpu)) == 2)
+               static_branch_dec_cpuslocked(&sched_smt_present);
+#endif
+
        if (!sched_smp_initialized)
                return 0;
 
index 3d7355d..fe24de3 100644 (file)
 
 static int psi_bug __read_mostly;
 
-bool psi_disabled __read_mostly;
-core_param(psi_disabled, psi_disabled, bool, 0644);
+DEFINE_STATIC_KEY_FALSE(psi_disabled);
+
+#ifdef CONFIG_PSI_DEFAULT_DISABLED
+bool psi_enable;
+#else
+bool psi_enable = true;
+#endif
+static int __init setup_psi(char *str)
+{
+       return kstrtobool(str, &psi_enable) == 0;
+}
+__setup("psi=", setup_psi);
 
 /* Running averages - we need to be higher-res than loadavg */
 #define PSI_FREQ       (2*HZ+1)        /* 2 sec intervals */
@@ -169,8 +179,10 @@ static void group_init(struct psi_group *group)
 
 void __init psi_init(void)
 {
-       if (psi_disabled)
+       if (!psi_enable) {
+               static_branch_enable(&psi_disabled);
                return;
+       }
 
        psi_period = jiffies_to_nsecs(PSI_FREQ);
        group_init(&psi_system);
@@ -549,7 +561,7 @@ void psi_memstall_enter(unsigned long *flags)
        struct rq_flags rf;
        struct rq *rq;
 
-       if (psi_disabled)
+       if (static_branch_likely(&psi_disabled))
                return;
 
        *flags = current->flags & PF_MEMSTALL;
@@ -579,7 +591,7 @@ void psi_memstall_leave(unsigned long *flags)
        struct rq_flags rf;
        struct rq *rq;
 
-       if (psi_disabled)
+       if (static_branch_likely(&psi_disabled))
                return;
 
        if (*flags)
@@ -600,7 +612,7 @@ void psi_memstall_leave(unsigned long *flags)
 #ifdef CONFIG_CGROUPS
 int psi_cgroup_alloc(struct cgroup *cgroup)
 {
-       if (psi_disabled)
+       if (static_branch_likely(&psi_disabled))
                return 0;
 
        cgroup->psi.pcpu = alloc_percpu(struct psi_group_cpu);
@@ -612,7 +624,7 @@ int psi_cgroup_alloc(struct cgroup *cgroup)
 
 void psi_cgroup_free(struct cgroup *cgroup)
 {
-       if (psi_disabled)
+       if (static_branch_likely(&psi_disabled))
                return;
 
        cancel_delayed_work_sync(&cgroup->psi.clock_work);
@@ -637,7 +649,7 @@ void cgroup_move_task(struct task_struct *task, struct css_set *to)
        struct rq_flags rf;
        struct rq *rq;
 
-       if (psi_disabled) {
+       if (static_branch_likely(&psi_disabled)) {
                /*
                 * Lame to do this here, but the scheduler cannot be locked
                 * from the outside, so we move cgroups from inside sched/.
@@ -673,7 +685,7 @@ int psi_show(struct seq_file *m, struct psi_group *group, enum psi_res res)
 {
        int full;
 
-       if (psi_disabled)
+       if (static_branch_likely(&psi_disabled))
                return -EOPNOTSUPP;
 
        update_stats(group);
index 618577f..4e524ab 100644 (file)
@@ -23,6 +23,7 @@
 #include <linux/sched/prio.h>
 #include <linux/sched/rt.h>
 #include <linux/sched/signal.h>
+#include <linux/sched/smt.h>
 #include <linux/sched/stat.h>
 #include <linux/sched/sysctl.h>
 #include <linux/sched/task.h>
@@ -936,9 +937,6 @@ static inline int cpu_of(struct rq *rq)
 
 
 #ifdef CONFIG_SCHED_SMT
-
-extern struct static_key_false sched_smt_present;
-
 extern void __update_idle_core(struct rq *rq);
 
 static inline void update_idle_core(struct rq *rq)
index 4904c46..aa0de24 100644 (file)
@@ -66,7 +66,7 @@ static inline void psi_enqueue(struct task_struct *p, bool wakeup)
 {
        int clear = 0, set = TSK_RUNNING;
 
-       if (psi_disabled)
+       if (static_branch_likely(&psi_disabled))
                return;
 
        if (!wakeup || p->sched_psi_wake_requeue) {
@@ -86,7 +86,7 @@ static inline void psi_dequeue(struct task_struct *p, bool sleep)
 {
        int clear = TSK_RUNNING, set = 0;
 
-       if (psi_disabled)
+       if (static_branch_likely(&psi_disabled))
                return;
 
        if (!sleep) {
@@ -102,7 +102,7 @@ static inline void psi_dequeue(struct task_struct *p, bool sleep)
 
 static inline void psi_ttwu_dequeue(struct task_struct *p)
 {
-       if (psi_disabled)
+       if (static_branch_likely(&psi_disabled))
                return;
        /*
         * Is the task being migrated during a wakeup? Make sure to
@@ -128,7 +128,7 @@ static inline void psi_ttwu_dequeue(struct task_struct *p)
 
 static inline void psi_task_tick(struct rq *rq)
 {
-       if (psi_disabled)
+       if (static_branch_likely(&psi_disabled))
                return;
 
        if (unlikely(rq->curr->flags & PF_MEMSTALL))
index e428929..08cb57e 100644 (file)
@@ -11,6 +11,7 @@
  */
 
 #include <linux/stackleak.h>
+#include <linux/kprobes.h>
 
 #ifdef CONFIG_STACKLEAK_RUNTIME_DISABLE
 #include <linux/jump_label.h>
@@ -47,7 +48,7 @@ int stack_erasing_sysctl(struct ctl_table *table, int write,
 #define skip_erasing() false
 #endif /* CONFIG_STACKLEAK_RUNTIME_DISABLE */
 
-asmlinkage void stackleak_erase(void)
+asmlinkage void notrace stackleak_erase(void)
 {
        /* It would be nice not to have 'kstack_ptr' and 'boundary' on stack */
        unsigned long kstack_ptr = current->lowest_stack;
@@ -101,6 +102,7 @@ asmlinkage void stackleak_erase(void)
        /* Reset the 'lowest_stack' value for the next syscall */
        current->lowest_stack = current_top_of_stack() - THREAD_SIZE/64;
 }
+NOKPROBE_SYMBOL(stackleak_erase);
 
 void __used stackleak_track_stack(void)
 {
index 08fcfe4..9864a35 100644 (file)
@@ -196,11 +196,13 @@ BPF_CALL_5(bpf_trace_printk, char *, fmt, u32, fmt_size, u64, arg1,
                        i++;
                } else if (fmt[i] == 'p' || fmt[i] == 's') {
                        mod[fmt_cnt]++;
-                       i++;
-                       if (!isspace(fmt[i]) && !ispunct(fmt[i]) && fmt[i] != 0)
+                       /* disallow any further format extensions */
+                       if (fmt[i + 1] != 0 &&
+                           !isspace(fmt[i + 1]) &&
+                           !ispunct(fmt[i + 1]))
                                return -EINVAL;
                        fmt_cnt++;
-                       if (fmt[i - 1] == 's') {
+                       if (fmt[i] == 's') {
                                if (str_seen)
                                        /* allow only one '%s' per fmt string */
                                        return -EINVAL;
index f536f60..7773445 100644 (file)
@@ -817,7 +817,7 @@ function_profile_call(unsigned long ip, unsigned long parent_ip,
 #ifdef CONFIG_FUNCTION_GRAPH_TRACER
 static int profile_graph_entry(struct ftrace_graph_ent *trace)
 {
-       int index = trace->depth;
+       int index = current->curr_ret_stack;
 
        function_profile_call(trace->func, 0, NULL, NULL);
 
@@ -852,7 +852,7 @@ static void profile_graph_return(struct ftrace_graph_ret *trace)
        if (!fgraph_graph_time) {
                int index;
 
-               index = trace->depth;
+               index = current->curr_ret_stack;
 
                /* Append this call time to the parent time to subtract */
                if (index)
@@ -6814,6 +6814,7 @@ static int alloc_retstack_tasklist(struct ftrace_ret_stack **ret_stack_list)
                        atomic_set(&t->tracing_graph_pause, 0);
                        atomic_set(&t->trace_overrun, 0);
                        t->curr_ret_stack = -1;
+                       t->curr_ret_depth = -1;
                        /* Make sure the tasks see the -1 first: */
                        smp_wmb();
                        t->ret_stack = ret_stack_list[start++];
@@ -7038,6 +7039,7 @@ graph_init_task(struct task_struct *t, struct ftrace_ret_stack *ret_stack)
 void ftrace_graph_init_idle_task(struct task_struct *t, int cpu)
 {
        t->curr_ret_stack = -1;
+       t->curr_ret_depth = -1;
        /*
         * The idle task has no parent, it either has its own
         * stack or no stack at all.
@@ -7068,6 +7070,7 @@ void ftrace_graph_init_task(struct task_struct *t)
        /* Make sure we do not use the parent ret_stack */
        t->ret_stack = NULL;
        t->curr_ret_stack = -1;
+       t->curr_ret_depth = -1;
 
        if (ftrace_graph_active) {
                struct ftrace_ret_stack *ret_stack;
index 3b8c0e2..447bd96 100644 (file)
@@ -512,12 +512,44 @@ enum {
  * can only be modified by current, we can reuse trace_recursion.
  */
        TRACE_IRQ_BIT,
+
+       /* Set if the function is in the set_graph_function file */
+       TRACE_GRAPH_BIT,
+
+       /*
+        * In the very unlikely case that an interrupt came in
+        * at a start of graph tracing, and we want to trace
+        * the function in that interrupt, the depth can be greater
+        * than zero, because of the preempted start of a previous
+        * trace. In an even more unlikely case, depth could be 2
+        * if a softirq interrupted the start of graph tracing,
+        * followed by an interrupt preempting a start of graph
+        * tracing in the softirq, and depth can even be 3
+        * if an NMI came in at the start of an interrupt function
+        * that preempted a softirq start of a function that
+        * preempted normal context!!!! Luckily, it can't be
+        * greater than 3, so the next two bits are a mask
+        * of what the depth is when we set TRACE_GRAPH_BIT
+        */
+
+       TRACE_GRAPH_DEPTH_START_BIT,
+       TRACE_GRAPH_DEPTH_END_BIT,
 };
 
 #define trace_recursion_set(bit)       do { (current)->trace_recursion |= (1<<(bit)); } while (0)
 #define trace_recursion_clear(bit)     do { (current)->trace_recursion &= ~(1<<(bit)); } while (0)
 #define trace_recursion_test(bit)      ((current)->trace_recursion & (1<<(bit)))
 
+#define trace_recursion_depth() \
+       (((current)->trace_recursion >> TRACE_GRAPH_DEPTH_START_BIT) & 3)
+#define trace_recursion_set_depth(depth) \
+       do {                                                            \
+               current->trace_recursion &=                             \
+                       ~(3 << TRACE_GRAPH_DEPTH_START_BIT);            \
+               current->trace_recursion |=                             \
+                       ((depth) & 3) << TRACE_GRAPH_DEPTH_START_BIT;   \
+       } while (0)
+
 #define TRACE_CONTEXT_BITS     4
 
 #define TRACE_FTRACE_START     TRACE_FTRACE_BIT
@@ -843,8 +875,9 @@ extern void __trace_graph_return(struct trace_array *tr,
 extern struct ftrace_hash *ftrace_graph_hash;
 extern struct ftrace_hash *ftrace_graph_notrace_hash;
 
-static inline int ftrace_graph_addr(unsigned long addr)
+static inline int ftrace_graph_addr(struct ftrace_graph_ent *trace)
 {
+       unsigned long addr = trace->func;
        int ret = 0;
 
        preempt_disable_notrace();
@@ -855,6 +888,14 @@ static inline int ftrace_graph_addr(unsigned long addr)
        }
 
        if (ftrace_lookup_ip(ftrace_graph_hash, addr)) {
+
+               /*
+                * This needs to be cleared on the return functions
+                * when the depth is zero.
+                */
+               trace_recursion_set(TRACE_GRAPH_BIT);
+               trace_recursion_set_depth(trace->depth);
+
                /*
                 * If no irqs are to be traced, but a set_graph_function
                 * is set, and called by an interrupt handler, we still
@@ -872,6 +913,13 @@ out:
        return ret;
 }
 
+static inline void ftrace_graph_addr_finish(struct ftrace_graph_ret *trace)
+{
+       if (trace_recursion_test(TRACE_GRAPH_BIT) &&
+           trace->depth == trace_recursion_depth())
+               trace_recursion_clear(TRACE_GRAPH_BIT);
+}
+
 static inline int ftrace_graph_notrace_addr(unsigned long addr)
 {
        int ret = 0;
@@ -885,7 +933,7 @@ static inline int ftrace_graph_notrace_addr(unsigned long addr)
        return ret;
 }
 #else
-static inline int ftrace_graph_addr(unsigned long addr)
+static inline int ftrace_graph_addr(struct ftrace_graph_ent *trace)
 {
        return 1;
 }
@@ -894,6 +942,8 @@ static inline int ftrace_graph_notrace_addr(unsigned long addr)
 {
        return 0;
 }
+static inline void ftrace_graph_addr_finish(struct ftrace_graph_ret *trace)
+{ }
 #endif /* CONFIG_DYNAMIC_FTRACE */
 
 extern unsigned int fgraph_max_depth;
@@ -901,7 +951,8 @@ extern unsigned int fgraph_max_depth;
 static inline bool ftrace_graph_ignore_func(struct ftrace_graph_ent *trace)
 {
        /* trace it when it is-nested-in or is a function enabled. */
-       return !(trace->depth || ftrace_graph_addr(trace->func)) ||
+       return !(trace_recursion_test(TRACE_GRAPH_BIT) ||
+                ftrace_graph_addr(trace)) ||
                (trace->depth < 0) ||
                (fgraph_max_depth && trace->depth >= fgraph_max_depth);
 }
index 169b3c4..086af4f 100644 (file)
@@ -118,8 +118,8 @@ print_graph_duration(struct trace_array *tr, unsigned long long duration,
                     struct trace_seq *s, u32 flags);
 
 /* Add a function return address to the trace stack on thread info.*/
-int
-ftrace_push_return_trace(unsigned long ret, unsigned long func, int *depth,
+static int
+ftrace_push_return_trace(unsigned long ret, unsigned long func,
                         unsigned long frame_pointer, unsigned long *retp)
 {
        unsigned long long calltime;
@@ -177,9 +177,31 @@ ftrace_push_return_trace(unsigned long ret, unsigned long func, int *depth,
 #ifdef HAVE_FUNCTION_GRAPH_RET_ADDR_PTR
        current->ret_stack[index].retp = retp;
 #endif
-       *depth = current->curr_ret_stack;
+       return 0;
+}
+
+int function_graph_enter(unsigned long ret, unsigned long func,
+                        unsigned long frame_pointer, unsigned long *retp)
+{
+       struct ftrace_graph_ent trace;
+
+       trace.func = func;
+       trace.depth = ++current->curr_ret_depth;
+
+       if (ftrace_push_return_trace(ret, func,
+                                    frame_pointer, retp))
+               goto out;
+
+       /* Only trace if the calling function expects to */
+       if (!ftrace_graph_entry(&trace))
+               goto out_ret;
 
        return 0;
+ out_ret:
+       current->curr_ret_stack--;
+ out:
+       current->curr_ret_depth--;
+       return -EBUSY;
 }
 
 /* Retrieve a function return address to the trace stack on thread info.*/
@@ -241,7 +263,13 @@ ftrace_pop_return_trace(struct ftrace_graph_ret *trace, unsigned long *ret,
        trace->func = current->ret_stack[index].func;
        trace->calltime = current->ret_stack[index].calltime;
        trace->overrun = atomic_read(&current->trace_overrun);
-       trace->depth = index;
+       trace->depth = current->curr_ret_depth--;
+       /*
+        * We still want to trace interrupts coming in if
+        * max_depth is set to 1. Make sure the decrement is
+        * seen before ftrace_graph_return.
+        */
+       barrier();
 }
 
 /*
@@ -255,6 +283,12 @@ unsigned long ftrace_return_to_handler(unsigned long frame_pointer)
 
        ftrace_pop_return_trace(&trace, &ret, frame_pointer);
        trace.rettime = trace_clock_local();
+       ftrace_graph_return(&trace);
+       /*
+        * The ftrace_graph_return() may still access the current
+        * ret_stack structure, we need to make sure the update of
+        * curr_ret_stack is after that.
+        */
        barrier();
        current->curr_ret_stack--;
        /*
@@ -267,13 +301,6 @@ unsigned long ftrace_return_to_handler(unsigned long frame_pointer)
                return ret;
        }
 
-       /*
-        * The trace should run after decrementing the ret counter
-        * in case an interrupt were to come in. We don't want to
-        * lose the interrupt if max_depth is set.
-        */
-       ftrace_graph_return(&trace);
-
        if (unlikely(!ret)) {
                ftrace_graph_stop();
                WARN_ON(1);
@@ -482,6 +509,8 @@ void trace_graph_return(struct ftrace_graph_ret *trace)
        int cpu;
        int pc;
 
+       ftrace_graph_addr_finish(trace);
+
        local_irq_save(flags);
        cpu = raw_smp_processor_id();
        data = per_cpu_ptr(tr->trace_buffer.data, cpu);
@@ -505,6 +534,8 @@ void set_graph_array(struct trace_array *tr)
 
 static void trace_graph_thresh_return(struct ftrace_graph_ret *trace)
 {
+       ftrace_graph_addr_finish(trace);
+
        if (tracing_thresh &&
            (trace->rettime - trace->calltime < tracing_thresh))
                return;
index b7357f9..98ea6d2 100644 (file)
@@ -208,6 +208,8 @@ static void irqsoff_graph_return(struct ftrace_graph_ret *trace)
        unsigned long flags;
        int pc;
 
+       ftrace_graph_addr_finish(trace);
+
        if (!func_prolog_dec(tr, &data, &flags))
                return;
 
index a86b303..7d04b98 100644 (file)
@@ -270,6 +270,8 @@ static void wakeup_graph_return(struct ftrace_graph_ret *trace)
        unsigned long flags;
        int pc;
 
+       ftrace_graph_addr_finish(trace);
+
        if (!func_prolog_preempt_disable(tr, &data, &pc))
                return;
 
index 70935ed..14afeeb 100644 (file)
@@ -135,7 +135,6 @@ static void fill_pool(void)
                if (!new)
                        return;
 
-               kmemleak_ignore(new);
                raw_spin_lock_irqsave(&pool_lock, flags);
                hlist_add_head(&new->node, &obj_pool);
                debug_objects_allocated++;
@@ -1128,7 +1127,6 @@ static int __init debug_objects_replace_static_objects(void)
                obj = kmem_cache_zalloc(obj_cache, GFP_KERNEL);
                if (!obj)
                        goto free;
-               kmemleak_ignore(obj);
                hlist_add_head(&obj->node, &objects);
        }
 
@@ -1184,7 +1182,8 @@ void __init debug_objects_mem_init(void)
 
        obj_cache = kmem_cache_create("debug_objects_cache",
                                      sizeof (struct debug_obj), 0,
-                                     SLAB_DEBUG_OBJECTS, NULL);
+                                     SLAB_DEBUG_OBJECTS | SLAB_NOLEAKTRACE,
+                                     NULL);
 
        if (!obj_cache || debug_objects_replace_static_objects()) {
                debug_objects_enabled = 0;
index 7ebccb5..54c2485 100644 (file)
@@ -560,6 +560,38 @@ static size_t copy_pipe_to_iter(const void *addr, size_t bytes,
        return bytes;
 }
 
+static size_t csum_and_copy_to_pipe_iter(const void *addr, size_t bytes,
+                               __wsum *csum, struct iov_iter *i)
+{
+       struct pipe_inode_info *pipe = i->pipe;
+       size_t n, r;
+       size_t off = 0;
+       __wsum sum = *csum, next;
+       int idx;
+
+       if (!sanity(i))
+               return 0;
+
+       bytes = n = push_pipe(i, bytes, &idx, &r);
+       if (unlikely(!n))
+               return 0;
+       for ( ; n; idx = next_idx(idx, pipe), r = 0) {
+               size_t chunk = min_t(size_t, n, PAGE_SIZE - r);
+               char *p = kmap_atomic(pipe->bufs[idx].page);
+               next = csum_partial_copy_nocheck(addr, p + r, chunk, 0);
+               sum = csum_block_add(sum, next, off);
+               kunmap_atomic(p);
+               i->idx = idx;
+               i->iov_offset = r + chunk;
+               n -= chunk;
+               off += chunk;
+               addr += chunk;
+       }
+       i->count -= bytes;
+       *csum = sum;
+       return bytes;
+}
+
 size_t _copy_to_iter(const void *addr, size_t bytes, struct iov_iter *i)
 {
        const char *from = addr;
@@ -1438,8 +1470,12 @@ size_t csum_and_copy_to_iter(const void *addr, size_t bytes, __wsum *csum,
        const char *from = addr;
        __wsum sum, next;
        size_t off = 0;
+
+       if (unlikely(iov_iter_is_pipe(i)))
+               return csum_and_copy_to_pipe_iter(addr, bytes, csum, i);
+
        sum = *csum;
-       if (unlikely(iov_iter_is_pipe(i) || iov_iter_is_discard(i))) {
+       if (unlikely(iov_iter_is_discard(i))) {
                WARN_ON(1);     /* for now */
                return 0;
        }
index 626f580..5144899 100644 (file)
@@ -99,7 +99,7 @@ static void __init test_hexdump_prepare_test(size_t len, int rowsize,
                const char *q = *result++;
                size_t amount = strlen(q);
 
-               strncpy(p, q, amount);
+               memcpy(p, q, amount);
                p += amount;
 
                *p++ = ' ';
index e3ddd83..d82d022 100644 (file)
@@ -1214,7 +1214,6 @@ void unregister_test_dev_kmod(struct kmod_test_device *test_dev)
 
        dev_info(test_dev->dev, "removing interface\n");
        misc_deregister(&test_dev->misc_dev);
-       kfree(&test_dev->misc_dev.name);
 
        mutex_unlock(&test_dev->config_mutex);
        mutex_unlock(&test_dev->trigger_mutex);
index aa43620..8cb68a5 100644 (file)
--- a/mm/gup.c
+++ b/mm/gup.c
@@ -702,12 +702,11 @@ static long __get_user_pages(struct task_struct *tsk, struct mm_struct *mm,
                if (!vma || start >= vma->vm_end) {
                        vma = find_extend_vma(mm, start);
                        if (!vma && in_gate_area(mm, start)) {
-                               int ret;
                                ret = get_gate_page(mm, start & PAGE_MASK,
                                                gup_flags, &vma,
                                                pages ? &pages[i] : NULL);
                                if (ret)
-                                       return i ? : ret;
+                                       goto out;
                                ctx.page_mask = 0;
                                goto next_page;
                        }
index 55478ab..622cced 100644 (file)
@@ -2350,7 +2350,7 @@ void vma_adjust_trans_huge(struct vm_area_struct *vma,
        }
 }
 
-static void freeze_page(struct page *page)
+static void unmap_page(struct page *page)
 {
        enum ttu_flags ttu_flags = TTU_IGNORE_MLOCK | TTU_IGNORE_ACCESS |
                TTU_RMAP_LOCKED | TTU_SPLIT_HUGE_PMD;
@@ -2365,7 +2365,7 @@ static void freeze_page(struct page *page)
        VM_BUG_ON_PAGE(!unmap_success, page);
 }
 
-static void unfreeze_page(struct page *page)
+static void remap_page(struct page *page)
 {
        int i;
        if (PageTransHuge(page)) {
@@ -2402,6 +2402,12 @@ static void __split_huge_page_tail(struct page *head, int tail,
                         (1L << PG_unevictable) |
                         (1L << PG_dirty)));
 
+       /* ->mapping in first tail page is compound_mapcount */
+       VM_BUG_ON_PAGE(tail > 2 && page_tail->mapping != TAIL_MAPPING,
+                       page_tail);
+       page_tail->mapping = head->mapping;
+       page_tail->index = head->index + tail;
+
        /* Page flags must be visible before we make the page non-compound. */
        smp_wmb();
 
@@ -2422,12 +2428,6 @@ static void __split_huge_page_tail(struct page *head, int tail,
        if (page_is_idle(head))
                set_page_idle(page_tail);
 
-       /* ->mapping in first tail page is compound_mapcount */
-       VM_BUG_ON_PAGE(tail > 2 && page_tail->mapping != TAIL_MAPPING,
-                       page_tail);
-       page_tail->mapping = head->mapping;
-
-       page_tail->index = head->index + tail;
        page_cpupid_xchg_last(page_tail, page_cpupid_last(head));
 
        /*
@@ -2439,12 +2439,11 @@ static void __split_huge_page_tail(struct page *head, int tail,
 }
 
 static void __split_huge_page(struct page *page, struct list_head *list,
-               unsigned long flags)
+               pgoff_t end, unsigned long flags)
 {
        struct page *head = compound_head(page);
        struct zone *zone = page_zone(head);
        struct lruvec *lruvec;
-       pgoff_t end = -1;
        int i;
 
        lruvec = mem_cgroup_page_lruvec(head, zone->zone_pgdat);
@@ -2452,9 +2451,6 @@ static void __split_huge_page(struct page *page, struct list_head *list,
        /* complete memcg works before add pages to LRU */
        mem_cgroup_split_huge_fixup(head);
 
-       if (!PageAnon(page))
-               end = DIV_ROUND_UP(i_size_read(head->mapping->host), PAGE_SIZE);
-
        for (i = HPAGE_PMD_NR - 1; i >= 1; i--) {
                __split_huge_page_tail(head, i, lruvec, list);
                /* Some pages can be beyond i_size: drop them from page cache */
@@ -2483,7 +2479,7 @@ static void __split_huge_page(struct page *page, struct list_head *list,
 
        spin_unlock_irqrestore(zone_lru_lock(page_zone(head)), flags);
 
-       unfreeze_page(head);
+       remap_page(head);
 
        for (i = 0; i < HPAGE_PMD_NR; i++) {
                struct page *subpage = head + i;
@@ -2626,6 +2622,7 @@ int split_huge_page_to_list(struct page *page, struct list_head *list)
        int count, mapcount, extra_pins, ret;
        bool mlocked;
        unsigned long flags;
+       pgoff_t end;
 
        VM_BUG_ON_PAGE(is_huge_zero_page(page), page);
        VM_BUG_ON_PAGE(!PageLocked(page), page);
@@ -2648,6 +2645,7 @@ int split_huge_page_to_list(struct page *page, struct list_head *list)
                        ret = -EBUSY;
                        goto out;
                }
+               end = -1;
                mapping = NULL;
                anon_vma_lock_write(anon_vma);
        } else {
@@ -2661,10 +2659,19 @@ int split_huge_page_to_list(struct page *page, struct list_head *list)
 
                anon_vma = NULL;
                i_mmap_lock_read(mapping);
+
+               /*
+                *__split_huge_page() may need to trim off pages beyond EOF:
+                * but on 32-bit, i_size_read() takes an irq-unsafe seqlock,
+                * which cannot be nested inside the page tree lock. So note
+                * end now: i_size itself may be changed at any moment, but
+                * head page lock is good enough to serialize the trimming.
+                */
+               end = DIV_ROUND_UP(i_size_read(mapping->host), PAGE_SIZE);
        }
 
        /*
-        * Racy check if we can split the page, before freeze_page() will
+        * Racy check if we can split the page, before unmap_page() will
         * split PMDs
         */
        if (!can_split_huge_page(head, &extra_pins)) {
@@ -2673,7 +2680,7 @@ int split_huge_page_to_list(struct page *page, struct list_head *list)
        }
 
        mlocked = PageMlocked(page);
-       freeze_page(head);
+       unmap_page(head);
        VM_BUG_ON_PAGE(compound_mapcount(head), head);
 
        /* Make sure the page is not on per-CPU pagevec as it takes pin */
@@ -2707,7 +2714,7 @@ int split_huge_page_to_list(struct page *page, struct list_head *list)
                if (mapping)
                        __dec_node_page_state(page, NR_SHMEM_THPS);
                spin_unlock(&pgdata->split_queue_lock);
-               __split_huge_page(page, list, flags);
+               __split_huge_page(page, list, end, flags);
                if (PageSwapCache(head)) {
                        swp_entry_t entry = { .val = page_private(head) };
 
@@ -2727,7 +2734,7 @@ int split_huge_page_to_list(struct page *page, struct list_head *list)
 fail:          if (mapping)
                        xa_unlock(&mapping->i_pages);
                spin_unlock_irqrestore(zone_lru_lock(page_zone(head)), flags);
-               unfreeze_page(head);
+               remap_page(head);
                ret = -EBUSY;
        }
 
index 7f2a28a..705a3e9 100644 (file)
@@ -4080,7 +4080,7 @@ int hugetlb_mcopy_atomic_pte(struct mm_struct *dst_mm,
 
                /* fallback to copy_from_user outside mmap_sem */
                if (unlikely(ret)) {
-                       ret = -EFAULT;
+                       ret = -ENOENT;
                        *pagep = page;
                        /* don't free the page */
                        goto out;
index c13625c..8e2ff19 100644 (file)
@@ -1287,7 +1287,7 @@ static void retract_page_tables(struct address_space *mapping, pgoff_t pgoff)
  * collapse_shmem - collapse small tmpfs/shmem pages into huge one.
  *
  * Basic scheme is simple, details are more complex:
- *  - allocate and freeze a new huge page;
+ *  - allocate and lock a new huge page;
  *  - scan page cache replacing old pages with the new one
  *    + swap in pages if necessary;
  *    + fill in gaps;
@@ -1295,11 +1295,11 @@ static void retract_page_tables(struct address_space *mapping, pgoff_t pgoff)
  *  - if replacing succeeds:
  *    + copy data over;
  *    + free old pages;
- *    + unfreeze huge page;
+ *    + unlock huge page;
  *  - if replacing failed;
  *    + put all pages back and unfreeze them;
  *    + restore gaps in the page cache;
- *    + free huge page;
+ *    + unlock and free huge page;
  */
 static void collapse_shmem(struct mm_struct *mm,
                struct address_space *mapping, pgoff_t start,
@@ -1329,19 +1329,6 @@ static void collapse_shmem(struct mm_struct *mm,
                goto out;
        }
 
-       new_page->index = start;
-       new_page->mapping = mapping;
-       __SetPageSwapBacked(new_page);
-       __SetPageLocked(new_page);
-       BUG_ON(!page_ref_freeze(new_page, 1));
-
-       /*
-        * At this point the new_page is 'frozen' (page_count() is zero),
-        * locked and not up-to-date. It's safe to insert it into the page
-        * cache, because nobody would be able to map it or use it in other
-        * way until we unfreeze it.
-        */
-
        /* This will be less messy when we use multi-index entries */
        do {
                xas_lock_irq(&xas);
@@ -1349,19 +1336,44 @@ static void collapse_shmem(struct mm_struct *mm,
                if (!xas_error(&xas))
                        break;
                xas_unlock_irq(&xas);
-               if (!xas_nomem(&xas, GFP_KERNEL))
+               if (!xas_nomem(&xas, GFP_KERNEL)) {
+                       mem_cgroup_cancel_charge(new_page, memcg, true);
+                       result = SCAN_FAIL;
                        goto out;
+               }
        } while (1);
 
+       __SetPageLocked(new_page);
+       __SetPageSwapBacked(new_page);
+       new_page->index = start;
+       new_page->mapping = mapping;
+
+       /*
+        * At this point the new_page is locked and not up-to-date.
+        * It's safe to insert it into the page cache, because nobody would
+        * be able to map it or use it in another way until we unlock it.
+        */
+
        xas_set(&xas, start);
        for (index = start; index < end; index++) {
                struct page *page = xas_next(&xas);
 
                VM_BUG_ON(index != xas.xa_index);
                if (!page) {
+                       /*
+                        * Stop if extent has been truncated or hole-punched,
+                        * and is now completely empty.
+                        */
+                       if (index == start) {
+                               if (!xas_next_entry(&xas, end - 1)) {
+                                       result = SCAN_TRUNCATED;
+                                       goto xa_locked;
+                               }
+                               xas_set(&xas, index);
+                       }
                        if (!shmem_charge(mapping->host, 1)) {
                                result = SCAN_FAIL;
-                               break;
+                               goto xa_locked;
                        }
                        xas_store(&xas, new_page + (index % HPAGE_PMD_NR));
                        nr_none++;
@@ -1376,13 +1388,12 @@ static void collapse_shmem(struct mm_struct *mm,
                                result = SCAN_FAIL;
                                goto xa_unlocked;
                        }
-                       xas_lock_irq(&xas);
-                       xas_set(&xas, index);
                } else if (trylock_page(page)) {
                        get_page(page);
+                       xas_unlock_irq(&xas);
                } else {
                        result = SCAN_PAGE_LOCK;
-                       break;
+                       goto xa_locked;
                }
 
                /*
@@ -1391,17 +1402,24 @@ static void collapse_shmem(struct mm_struct *mm,
                 */
                VM_BUG_ON_PAGE(!PageLocked(page), page);
                VM_BUG_ON_PAGE(!PageUptodate(page), page);
-               VM_BUG_ON_PAGE(PageTransCompound(page), page);
+
+               /*
+                * If file was truncated then extended, or hole-punched, before
+                * we locked the first page, then a THP might be there already.
+                */
+               if (PageTransCompound(page)) {
+                       result = SCAN_PAGE_COMPOUND;
+                       goto out_unlock;
+               }
 
                if (page_mapping(page) != mapping) {
                        result = SCAN_TRUNCATED;
                        goto out_unlock;
                }
-               xas_unlock_irq(&xas);
 
                if (isolate_lru_page(page)) {
                        result = SCAN_DEL_PAGE_LRU;
-                       goto out_isolate_failed;
+                       goto out_unlock;
                }
 
                if (page_mapped(page))
@@ -1421,7 +1439,9 @@ static void collapse_shmem(struct mm_struct *mm,
                 */
                if (!page_ref_freeze(page, 3)) {
                        result = SCAN_PAGE_COUNT;
-                       goto out_lru;
+                       xas_unlock_irq(&xas);
+                       putback_lru_page(page);
+                       goto out_unlock;
                }
 
                /*
@@ -1433,71 +1453,74 @@ static void collapse_shmem(struct mm_struct *mm,
                /* Finally, replace with the new page. */
                xas_store(&xas, new_page + (index % HPAGE_PMD_NR));
                continue;
-out_lru:
-               xas_unlock_irq(&xas);
-               putback_lru_page(page);
-out_isolate_failed:
-               unlock_page(page);
-               put_page(page);
-               goto xa_unlocked;
 out_unlock:
                unlock_page(page);
                put_page(page);
-               break;
+               goto xa_unlocked;
        }
-       xas_unlock_irq(&xas);
 
+       __inc_node_page_state(new_page, NR_SHMEM_THPS);
+       if (nr_none) {
+               struct zone *zone = page_zone(new_page);
+
+               __mod_node_page_state(zone->zone_pgdat, NR_FILE_PAGES, nr_none);
+               __mod_node_page_state(zone->zone_pgdat, NR_SHMEM, nr_none);
+       }
+
+xa_locked:
+       xas_unlock_irq(&xas);
 xa_unlocked:
+
        if (result == SCAN_SUCCEED) {
                struct page *page, *tmp;
-               struct zone *zone = page_zone(new_page);
 
                /*
                 * Replacing old pages with new one has succeeded, now we
                 * need to copy the content and free the old pages.
                 */
+               index = start;
                list_for_each_entry_safe(page, tmp, &pagelist, lru) {
+                       while (index < page->index) {
+                               clear_highpage(new_page + (index % HPAGE_PMD_NR));
+                               index++;
+                       }
                        copy_highpage(new_page + (page->index % HPAGE_PMD_NR),
                                        page);
                        list_del(&page->lru);
-                       unlock_page(page);
-                       page_ref_unfreeze(page, 1);
                        page->mapping = NULL;
+                       page_ref_unfreeze(page, 1);
                        ClearPageActive(page);
                        ClearPageUnevictable(page);
+                       unlock_page(page);
                        put_page(page);
+                       index++;
                }
-
-               local_irq_disable();
-               __inc_node_page_state(new_page, NR_SHMEM_THPS);
-               if (nr_none) {
-                       __mod_node_page_state(zone->zone_pgdat, NR_FILE_PAGES, nr_none);
-                       __mod_node_page_state(zone->zone_pgdat, NR_SHMEM, nr_none);
+               while (index < end) {
+                       clear_highpage(new_page + (index % HPAGE_PMD_NR));
+                       index++;
                }
-               local_irq_enable();
 
-               /*
-                * Remove pte page tables, so we can re-fault
-                * the page as huge.
-                */
-               retract_page_tables(mapping, start);
-
-               /* Everything is ready, let's unfreeze the new_page */
-               set_page_dirty(new_page);
                SetPageUptodate(new_page);
-               page_ref_unfreeze(new_page, HPAGE_PMD_NR);
+               page_ref_add(new_page, HPAGE_PMD_NR - 1);
+               set_page_dirty(new_page);
                mem_cgroup_commit_charge(new_page, memcg, false, true);
                lru_cache_add_anon(new_page);
-               unlock_page(new_page);
 
+               /*
+                * Remove pte page tables, so we can re-fault the page as huge.
+                */
+               retract_page_tables(mapping, start);
                *hpage = NULL;
 
                khugepaged_pages_collapsed++;
        } else {
                struct page *page;
+
                /* Something went wrong: roll back page cache changes */
-               shmem_uncharge(mapping->host, nr_none);
                xas_lock_irq(&xas);
+               mapping->nrpages -= nr_none;
+               shmem_uncharge(mapping->host, nr_none);
+
                xas_set(&xas, start);
                xas_for_each(&xas, page, end - 1) {
                        page = list_first_entry_or_null(&pagelist,
@@ -1519,19 +1542,18 @@ xa_unlocked:
                        xas_store(&xas, page);
                        xas_pause(&xas);
                        xas_unlock_irq(&xas);
-                       putback_lru_page(page);
                        unlock_page(page);
+                       putback_lru_page(page);
                        xas_lock_irq(&xas);
                }
                VM_BUG_ON(nr_none);
                xas_unlock_irq(&xas);
 
-               /* Unfreeze new_page, caller would take care about freeing it */
-               page_ref_unfreeze(new_page, 1);
                mem_cgroup_cancel_charge(new_page, memcg, true);
-               unlock_page(new_page);
                new_page->mapping = NULL;
        }
+
+       unlock_page(new_page);
 out:
        VM_BUG_ON(!list_empty(&pagelist));
        /* TODO: tracepoints */
index 6847177..2ec9cc4 100644 (file)
@@ -5813,8 +5813,10 @@ void __meminit init_currently_empty_zone(struct zone *zone,
                                        unsigned long size)
 {
        struct pglist_data *pgdat = zone->zone_pgdat;
+       int zone_idx = zone_idx(zone) + 1;
 
-       pgdat->nr_zones = zone_idx(zone) + 1;
+       if (zone_idx > pgdat->nr_zones)
+               pgdat->nr_zones = zone_idx;
 
        zone->zone_start_pfn = zone_start_pfn;
 
index 1e79fac..85b7f94 100644 (file)
--- a/mm/rmap.c
+++ b/mm/rmap.c
@@ -1627,16 +1627,9 @@ static bool try_to_unmap_one(struct page *page, struct vm_area_struct *vma,
                                                      address + PAGE_SIZE);
                } else {
                        /*
-                        * We should not need to notify here as we reach this
-                        * case only from freeze_page() itself only call from
-                        * split_huge_page_to_list() so everything below must
-                        * be true:
-                        *   - page is not anonymous
-                        *   - page is locked
-                        *
-                        * So as it is a locked file back page thus it can not
-                        * be remove from the page cache and replace by a new
-                        * page before mmu_notifier_invalidate_range_end so no
+                        * This is a locked file-backed page, thus it cannot
+                        * be removed from the page cache and replaced by a new
+                        * page before mmu_notifier_invalidate_range_end, so no
                         * concurrent thread might update its page table to
                         * point at new page while a device still is using this
                         * page.
index d44991e..cddc72a 100644 (file)
@@ -297,12 +297,14 @@ bool shmem_charge(struct inode *inode, long pages)
        if (!shmem_inode_acct_block(inode, pages))
                return false;
 
+       /* nrpages adjustment first, then shmem_recalc_inode() when balanced */
+       inode->i_mapping->nrpages += pages;
+
        spin_lock_irqsave(&info->lock, flags);
        info->alloced += pages;
        inode->i_blocks += pages * BLOCKS_PER_PAGE;
        shmem_recalc_inode(inode);
        spin_unlock_irqrestore(&info->lock, flags);
-       inode->i_mapping->nrpages += pages;
 
        return true;
 }
@@ -312,6 +314,8 @@ void shmem_uncharge(struct inode *inode, long pages)
        struct shmem_inode_info *info = SHMEM_I(inode);
        unsigned long flags;
 
+       /* nrpages adjustment done by __delete_from_page_cache() or caller */
+
        spin_lock_irqsave(&info->lock, flags);
        info->alloced -= pages;
        inode->i_blocks -= pages * BLOCKS_PER_PAGE;
@@ -1509,11 +1513,13 @@ static int shmem_replace_page(struct page **pagep, gfp_t gfp,
 {
        struct page *oldpage, *newpage;
        struct address_space *swap_mapping;
+       swp_entry_t entry;
        pgoff_t swap_index;
        int error;
 
        oldpage = *pagep;
-       swap_index = page_private(oldpage);
+       entry.val = page_private(oldpage);
+       swap_index = swp_offset(entry);
        swap_mapping = page_mapping(oldpage);
 
        /*
@@ -1532,7 +1538,7 @@ static int shmem_replace_page(struct page **pagep, gfp_t gfp,
        __SetPageLocked(newpage);
        __SetPageSwapBacked(newpage);
        SetPageUptodate(newpage);
-       set_page_private(newpage, swap_index);
+       set_page_private(newpage, entry.val);
        SetPageSwapCache(newpage);
 
        /*
@@ -2214,6 +2220,7 @@ static int shmem_mfill_atomic_pte(struct mm_struct *dst_mm,
        struct page *page;
        pte_t _dst_pte, *dst_pte;
        int ret;
+       pgoff_t offset, max_off;
 
        ret = -ENOMEM;
        if (!shmem_inode_acct_block(inode, 1))
@@ -2236,7 +2243,7 @@ static int shmem_mfill_atomic_pte(struct mm_struct *dst_mm,
                                *pagep = page;
                                shmem_inode_unacct_blocks(inode, 1);
                                /* don't free the page */
-                               return -EFAULT;
+                               return -ENOENT;
                        }
                } else {                /* mfill_zeropage_atomic */
                        clear_highpage(page);
@@ -2251,6 +2258,12 @@ static int shmem_mfill_atomic_pte(struct mm_struct *dst_mm,
        __SetPageSwapBacked(page);
        __SetPageUptodate(page);
 
+       ret = -EFAULT;
+       offset = linear_page_index(dst_vma, dst_addr);
+       max_off = DIV_ROUND_UP(i_size_read(inode), PAGE_SIZE);
+       if (unlikely(offset >= max_off))
+               goto out_release;
+
        ret = mem_cgroup_try_charge_delay(page, dst_mm, gfp, &memcg, false);
        if (ret)
                goto out_release;
@@ -2265,9 +2278,25 @@ static int shmem_mfill_atomic_pte(struct mm_struct *dst_mm,
        _dst_pte = mk_pte(page, dst_vma->vm_page_prot);
        if (dst_vma->vm_flags & VM_WRITE)
                _dst_pte = pte_mkwrite(pte_mkdirty(_dst_pte));
+       else {
+               /*
+                * We don't set the pte dirty if the vma has no
+                * VM_WRITE permission, so mark the page dirty or it
+                * could be freed from under us. We could do it
+                * unconditionally before unlock_page(), but doing it
+                * only if VM_WRITE is not set is faster.
+                */
+               set_page_dirty(page);
+       }
 
-       ret = -EEXIST;
        dst_pte = pte_offset_map_lock(dst_mm, dst_pmd, dst_addr, &ptl);
+
+       ret = -EFAULT;
+       max_off = DIV_ROUND_UP(i_size_read(inode), PAGE_SIZE);
+       if (unlikely(offset >= max_off))
+               goto out_release_uncharge_unlock;
+
+       ret = -EEXIST;
        if (!pte_none(*dst_pte))
                goto out_release_uncharge_unlock;
 
@@ -2285,13 +2314,15 @@ static int shmem_mfill_atomic_pte(struct mm_struct *dst_mm,
 
        /* No need to invalidate - it was non-present before */
        update_mmu_cache(dst_vma, dst_addr, dst_pte);
-       unlock_page(page);
        pte_unmap_unlock(dst_pte, ptl);
+       unlock_page(page);
        ret = 0;
 out:
        return ret;
 out_release_uncharge_unlock:
        pte_unmap_unlock(dst_pte, ptl);
+       ClearPageDirty(page);
+       delete_from_page_cache(page);
 out_release_uncharge:
        mem_cgroup_cancel_charge(page, memcg, false);
 out_release:
index 45d68e9..798e7cc 100644 (file)
@@ -517,9 +517,13 @@ void truncate_inode_pages_final(struct address_space *mapping)
                 */
                xa_lock_irq(&mapping->i_pages);
                xa_unlock_irq(&mapping->i_pages);
-
-               truncate_inode_pages(mapping, 0);
        }
+
+       /*
+        * Cleancache needs notification even if there are no pages or shadow
+        * entries.
+        */
+       truncate_inode_pages(mapping, 0);
 }
 EXPORT_SYMBOL(truncate_inode_pages_final);
 
index 5029f24..458acda 100644 (file)
@@ -33,6 +33,8 @@ static int mcopy_atomic_pte(struct mm_struct *dst_mm,
        void *page_kaddr;
        int ret;
        struct page *page;
+       pgoff_t offset, max_off;
+       struct inode *inode;
 
        if (!*pagep) {
                ret = -ENOMEM;
@@ -48,7 +50,7 @@ static int mcopy_atomic_pte(struct mm_struct *dst_mm,
 
                /* fallback to copy_from_user outside mmap_sem */
                if (unlikely(ret)) {
-                       ret = -EFAULT;
+                       ret = -ENOENT;
                        *pagep = page;
                        /* don't free the page */
                        goto out;
@@ -73,8 +75,17 @@ static int mcopy_atomic_pte(struct mm_struct *dst_mm,
        if (dst_vma->vm_flags & VM_WRITE)
                _dst_pte = pte_mkwrite(pte_mkdirty(_dst_pte));
 
-       ret = -EEXIST;
        dst_pte = pte_offset_map_lock(dst_mm, dst_pmd, dst_addr, &ptl);
+       if (dst_vma->vm_file) {
+               /* the shmem MAP_PRIVATE case requires checking the i_size */
+               inode = dst_vma->vm_file->f_inode;
+               offset = linear_page_index(dst_vma, dst_addr);
+               max_off = DIV_ROUND_UP(i_size_read(inode), PAGE_SIZE);
+               ret = -EFAULT;
+               if (unlikely(offset >= max_off))
+                       goto out_release_uncharge_unlock;
+       }
+       ret = -EEXIST;
        if (!pte_none(*dst_pte))
                goto out_release_uncharge_unlock;
 
@@ -108,11 +119,22 @@ static int mfill_zeropage_pte(struct mm_struct *dst_mm,
        pte_t _dst_pte, *dst_pte;
        spinlock_t *ptl;
        int ret;
+       pgoff_t offset, max_off;
+       struct inode *inode;
 
        _dst_pte = pte_mkspecial(pfn_pte(my_zero_pfn(dst_addr),
                                         dst_vma->vm_page_prot));
-       ret = -EEXIST;
        dst_pte = pte_offset_map_lock(dst_mm, dst_pmd, dst_addr, &ptl);
+       if (dst_vma->vm_file) {
+               /* the shmem MAP_PRIVATE case requires checking the i_size */
+               inode = dst_vma->vm_file->f_inode;
+               offset = linear_page_index(dst_vma, dst_addr);
+               max_off = DIV_ROUND_UP(i_size_read(inode), PAGE_SIZE);
+               ret = -EFAULT;
+               if (unlikely(offset >= max_off))
+                       goto out_unlock;
+       }
+       ret = -EEXIST;
        if (!pte_none(*dst_pte))
                goto out_unlock;
        set_pte_at(dst_mm, dst_addr, dst_pte, _dst_pte);
@@ -205,8 +227,9 @@ retry:
                if (!dst_vma || !is_vm_hugetlb_page(dst_vma))
                        goto out_unlock;
                /*
-                * Only allow __mcopy_atomic_hugetlb on userfaultfd
-                * registered ranges.
+                * Check the vma is registered in uffd, this is
+                * required to enforce the VM_MAYWRITE check done at
+                * uffd registration time.
                 */
                if (!dst_vma->vm_userfaultfd_ctx.ctx)
                        goto out_unlock;
@@ -274,7 +297,7 @@ retry:
 
                cond_resched();
 
-               if (unlikely(err == -EFAULT)) {
+               if (unlikely(err == -ENOENT)) {
                        up_read(&dst_mm->mmap_sem);
                        BUG_ON(!page);
 
@@ -380,7 +403,17 @@ static __always_inline ssize_t mfill_atomic_pte(struct mm_struct *dst_mm,
 {
        ssize_t err;
 
-       if (vma_is_anonymous(dst_vma)) {
+       /*
+        * The normal page fault path for a shmem will invoke the
+        * fault, fill the hole in the file and COW it right away. The
+        * result generates plain anonymous memory. So when we are
+        * asked to fill an hole in a MAP_PRIVATE shmem mapping, we'll
+        * generate anonymous memory directly without actually filling
+        * the hole. For the MAP_PRIVATE case the robustness check
+        * only happens in the pagetable (to verify it's still none)
+        * and not in the radix tree.
+        */
+       if (!(dst_vma->vm_flags & VM_SHARED)) {
                if (!zeropage)
                        err = mcopy_atomic_pte(dst_mm, dst_pmd, dst_vma,
                                               dst_addr, src_addr, page);
@@ -449,13 +482,9 @@ retry:
        if (!dst_vma)
                goto out_unlock;
        /*
-        * Be strict and only allow __mcopy_atomic on userfaultfd
-        * registered ranges to prevent userland errors going
-        * unnoticed. As far as the VM consistency is concerned, it
-        * would be perfectly safe to remove this check, but there's
-        * no useful usage for __mcopy_atomic ouside of userfaultfd
-        * registered ranges. This is after all why these are ioctls
-        * belonging to the userfaultfd and not syscalls.
+        * Check the vma is registered in uffd, this is required to
+        * enforce the VM_MAYWRITE check done at uffd registration
+        * time.
         */
        if (!dst_vma->vm_userfaultfd_ctx.ctx)
                goto out_unlock;
@@ -489,7 +518,8 @@ retry:
         * dst_vma.
         */
        err = -ENOMEM;
-       if (vma_is_anonymous(dst_vma) && unlikely(anon_vma_prepare(dst_vma)))
+       if (!(dst_vma->vm_flags & VM_SHARED) &&
+           unlikely(anon_vma_prepare(dst_vma)))
                goto out_unlock;
 
        while (src_addr < src_start + len) {
@@ -530,7 +560,7 @@ retry:
                                       src_addr, &page, zeropage);
                cond_resched();
 
-               if (unlikely(err == -EFAULT)) {
+               if (unlikely(err == -ENOENT)) {
                        void *page_kaddr;
 
                        up_read(&dst_mm->mmap_sem);
index e521c5e..9a1327e 100644 (file)
@@ -4852,18 +4852,17 @@ static struct sock *sk_lookup(struct net *net, struct bpf_sock_tuple *tuple,
        } else {
                struct in6_addr *src6 = (struct in6_addr *)&tuple->ipv6.saddr;
                struct in6_addr *dst6 = (struct in6_addr *)&tuple->ipv6.daddr;
-               u16 hnum = ntohs(tuple->ipv6.dport);
                int sdif = inet6_sdif(skb);
 
                if (proto == IPPROTO_TCP)
                        sk = __inet6_lookup(net, &tcp_hashinfo, skb, 0,
                                            src6, tuple->ipv6.sport,
-                                           dst6, hnum,
+                                           dst6, ntohs(tuple->ipv6.dport),
                                            dif, sdif, &refcounted);
                else if (likely(ipv6_bpf_stub))
                        sk = ipv6_bpf_stub->udp6_lib_lookup(net,
                                                            src6, tuple->ipv6.sport,
-                                                           dst6, hnum,
+                                                           dst6, tuple->ipv6.dport,
                                                            dif, sdif,
                                                            &udp_table, skb);
 #endif
index c09219e..5dbec21 100644 (file)
@@ -939,7 +939,7 @@ static int __ip_append_data(struct sock *sk,
                        unsigned int fraglen;
                        unsigned int fraggap;
                        unsigned int alloclen;
-                       unsigned int pagedlen = 0;
+                       unsigned int pagedlen;
                        struct sk_buff *skb_prev;
 alloc_new_skb:
                        skb_prev = skb;
@@ -956,6 +956,7 @@ alloc_new_skb:
                        if (datalen > mtu - fragheaderlen)
                                datalen = maxfraglen - fragheaderlen;
                        fraglen = datalen + fragheaderlen;
+                       pagedlen = 0;
 
                        if ((flags & MSG_MORE) &&
                            !(rt->dst.dev->features&NETIF_F_SG))
index ce1512b..fd3f9e8 100644 (file)
@@ -81,9 +81,12 @@ static int __init masquerade_tg_init(void)
        int ret;
 
        ret = xt_register_target(&masquerade_tg_reg);
+       if (ret)
+               return ret;
 
-       if (ret == 0)
-               nf_nat_masquerade_ipv4_register_notifier();
+       ret = nf_nat_masquerade_ipv4_register_notifier();
+       if (ret)
+               xt_unregister_target(&masquerade_tg_reg);
 
        return ret;
 }
index a9d5e01..41327bb 100644 (file)
@@ -147,28 +147,50 @@ static struct notifier_block masq_inet_notifier = {
        .notifier_call  = masq_inet_event,
 };
 
-static atomic_t masquerade_notifier_refcount = ATOMIC_INIT(0);
+static int masq_refcnt;
+static DEFINE_MUTEX(masq_mutex);
 
-void nf_nat_masquerade_ipv4_register_notifier(void)
+int nf_nat_masquerade_ipv4_register_notifier(void)
 {
+       int ret = 0;
+
+       mutex_lock(&masq_mutex);
        /* check if the notifier was already set */
-       if (atomic_inc_return(&masquerade_notifier_refcount) > 1)
-               return;
+       if (++masq_refcnt > 1)
+               goto out_unlock;
 
        /* Register for device down reports */
-       register_netdevice_notifier(&masq_dev_notifier);
+       ret = register_netdevice_notifier(&masq_dev_notifier);
+       if (ret)
+               goto err_dec;
        /* Register IP address change reports */
-       register_inetaddr_notifier(&masq_inet_notifier);
+       ret = register_inetaddr_notifier(&masq_inet_notifier);
+       if (ret)
+               goto err_unregister;
+
+       mutex_unlock(&masq_mutex);
+       return ret;
+
+err_unregister:
+       unregister_netdevice_notifier(&masq_dev_notifier);
+err_dec:
+       masq_refcnt--;
+out_unlock:
+       mutex_unlock(&masq_mutex);
+       return ret;
 }
 EXPORT_SYMBOL_GPL(nf_nat_masquerade_ipv4_register_notifier);
 
 void nf_nat_masquerade_ipv4_unregister_notifier(void)
 {
+       mutex_lock(&masq_mutex);
        /* check if the notifier still has clients */
-       if (atomic_dec_return(&masquerade_notifier_refcount) > 0)
-               return;
+       if (--masq_refcnt > 0)
+               goto out_unlock;
 
        unregister_netdevice_notifier(&masq_dev_notifier);
        unregister_inetaddr_notifier(&masq_inet_notifier);
+out_unlock:
+       mutex_unlock(&masq_mutex);
 }
 EXPORT_SYMBOL_GPL(nf_nat_masquerade_ipv4_unregister_notifier);
index f1193e1..6847de1 100644 (file)
@@ -69,7 +69,9 @@ static int __init nft_masq_ipv4_module_init(void)
        if (ret < 0)
                return ret;
 
-       nf_nat_masquerade_ipv4_register_notifier();
+       ret = nf_nat_masquerade_ipv4_register_notifier();
+       if (ret)
+               nft_unregister_expr(&nft_masq_ipv4_type);
 
        return ret;
 }
index 1e37c13..a9d9555 100644 (file)
@@ -579,10 +579,12 @@ static inline void tcp_rcv_rtt_measure_ts(struct sock *sk,
                u32 delta = tcp_time_stamp(tp) - tp->rx_opt.rcv_tsecr;
                u32 delta_us;
 
-               if (!delta)
-                       delta = 1;
-               delta_us = delta * (USEC_PER_SEC / TCP_TS_HZ);
-               tcp_rcv_rtt_update(tp, delta_us, 0);
+               if (likely(delta < INT_MAX / (USEC_PER_SEC / TCP_TS_HZ))) {
+                       if (!delta)
+                               delta = 1;
+                       delta_us = delta * (USEC_PER_SEC / TCP_TS_HZ);
+                       tcp_rcv_rtt_update(tp, delta_us, 0);
+               }
        }
 }
 
@@ -2910,9 +2912,11 @@ static bool tcp_ack_update_rtt(struct sock *sk, const int flag,
        if (seq_rtt_us < 0 && tp->rx_opt.saw_tstamp && tp->rx_opt.rcv_tsecr &&
            flag & FLAG_ACKED) {
                u32 delta = tcp_time_stamp(tp) - tp->rx_opt.rcv_tsecr;
-               u32 delta_us = delta * (USEC_PER_SEC / TCP_TS_HZ);
 
-               seq_rtt_us = ca_rtt_us = delta_us;
+               if (likely(delta < INT_MAX / (USEC_PER_SEC / TCP_TS_HZ))) {
+                       seq_rtt_us = delta * (USEC_PER_SEC / TCP_TS_HZ);
+                       ca_rtt_us = seq_rtt_us;
+               }
        }
        rs->rtt_us = ca_rtt_us; /* RTT of last (S)ACKed packet (or -1) */
        if (seq_rtt_us < 0)
index 5f8b6d3..091c539 100644 (file)
@@ -40,15 +40,17 @@ static u32 tcp_clamp_rto_to_user_timeout(const struct sock *sk)
 {
        struct inet_connection_sock *icsk = inet_csk(sk);
        u32 elapsed, start_ts;
+       s32 remaining;
 
        start_ts = tcp_retransmit_stamp(sk);
        if (!icsk->icsk_user_timeout || !start_ts)
                return icsk->icsk_rto;
        elapsed = tcp_time_stamp(tcp_sk(sk)) - start_ts;
-       if (elapsed >= icsk->icsk_user_timeout)
+       remaining = icsk->icsk_user_timeout - elapsed;
+       if (remaining <= 0)
                return 1; /* user timeout has passed; fire ASAP */
-       else
-               return min_t(u32, icsk->icsk_rto, msecs_to_jiffies(icsk->icsk_user_timeout - elapsed));
+
+       return min_t(u32, icsk->icsk_rto, msecs_to_jiffies(remaining));
 }
 
 /**
@@ -209,7 +211,7 @@ static bool retransmits_timed_out(struct sock *sk,
                                (boundary - linear_backoff_thresh) * TCP_RTO_MAX;
                timeout = jiffies_to_msecs(timeout);
        }
-       return (tcp_time_stamp(tcp_sk(sk)) - start_ts) >= timeout;
+       return (s32)(tcp_time_stamp(tcp_sk(sk)) - start_ts - timeout) >= 0;
 }
 
 /* A write timeout has occurred. Process the after effects. */
index 89e0d51..827a3f5 100644 (file)
@@ -1354,7 +1354,7 @@ emsgsize:
                        unsigned int fraglen;
                        unsigned int fraggap;
                        unsigned int alloclen;
-                       unsigned int pagedlen = 0;
+                       unsigned int pagedlen;
 alloc_new_skb:
                        /* There's no room in the current skb */
                        if (skb)
@@ -1378,6 +1378,7 @@ alloc_new_skb:
                        if (datalen > (cork->length <= mtu && !(cork->flags & IPCORK_ALLFRAG) ? mtu : maxfraglen) - fragheaderlen)
                                datalen = maxfraglen - fragheaderlen - rt->dst.trailer_len;
                        fraglen = datalen + fragheaderlen;
+                       pagedlen = 0;
 
                        if ((flags & MSG_MORE) &&
                            !(rt->dst.dev->features&NETIF_F_SG))
index 5ae8e1c..8b075f0 100644 (file)
@@ -24,7 +24,8 @@ int ip6_route_me_harder(struct net *net, struct sk_buff *skb)
        unsigned int hh_len;
        struct dst_entry *dst;
        struct flowi6 fl6 = {
-               .flowi6_oif = sk ? sk->sk_bound_dev_if : 0,
+               .flowi6_oif = sk && sk->sk_bound_dev_if ? sk->sk_bound_dev_if :
+                       rt6_need_strict(&iph->daddr) ? skb_dst(skb)->dev->ifindex : 0,
                .flowi6_mark = skb->mark,
                .flowi6_uid = sock_net_uid(net, sk),
                .daddr = iph->daddr,
index 491f808..29c7f19 100644 (file)
@@ -58,8 +58,12 @@ static int __init masquerade_tg6_init(void)
        int err;
 
        err = xt_register_target(&masquerade_tg6_reg);
-       if (err == 0)
-               nf_nat_masquerade_ipv6_register_notifier();
+       if (err)
+               return err;
+
+       err = nf_nat_masquerade_ipv6_register_notifier();
+       if (err)
+               xt_unregister_target(&masquerade_tg6_reg);
 
        return err;
 }
index 3e4bf22..0ad0da5 100644 (file)
@@ -132,8 +132,8 @@ static void iterate_cleanup_work(struct work_struct *work)
  * of ipv6 addresses being deleted), we also need to add an upper
  * limit to the number of queued work items.
  */
-static int masq_inet_event(struct notifier_block *this,
-                          unsigned long event, void *ptr)
+static int masq_inet6_event(struct notifier_block *this,
+                           unsigned long event, void *ptr)
 {
        struct inet6_ifaddr *ifa = ptr;
        const struct net_device *dev;
@@ -171,30 +171,53 @@ static int masq_inet_event(struct notifier_block *this,
        return NOTIFY_DONE;
 }
 
-static struct notifier_block masq_inet_notifier = {
-       .notifier_call  = masq_inet_event,
+static struct notifier_block masq_inet6_notifier = {
+       .notifier_call  = masq_inet6_event,
 };
 
-static atomic_t masquerade_notifier_refcount = ATOMIC_INIT(0);
+static int masq_refcnt;
+static DEFINE_MUTEX(masq_mutex);
 
-void nf_nat_masquerade_ipv6_register_notifier(void)
+int nf_nat_masquerade_ipv6_register_notifier(void)
 {
+       int ret = 0;
+
+       mutex_lock(&masq_mutex);
        /* check if the notifier is already set */
-       if (atomic_inc_return(&masquerade_notifier_refcount) > 1)
-               return;
+       if (++masq_refcnt > 1)
+               goto out_unlock;
+
+       ret = register_netdevice_notifier(&masq_dev_notifier);
+       if (ret)
+               goto err_dec;
+
+       ret = register_inet6addr_notifier(&masq_inet6_notifier);
+       if (ret)
+               goto err_unregister;
 
-       register_netdevice_notifier(&masq_dev_notifier);
-       register_inet6addr_notifier(&masq_inet_notifier);
+       mutex_unlock(&masq_mutex);
+       return ret;
+
+err_unregister:
+       unregister_netdevice_notifier(&masq_dev_notifier);
+err_dec:
+       masq_refcnt--;
+out_unlock:
+       mutex_unlock(&masq_mutex);
+       return ret;
 }
 EXPORT_SYMBOL_GPL(nf_nat_masquerade_ipv6_register_notifier);
 
 void nf_nat_masquerade_ipv6_unregister_notifier(void)
 {
+       mutex_lock(&masq_mutex);
        /* check if the notifier still has clients */
-       if (atomic_dec_return(&masquerade_notifier_refcount) > 0)
-               return;
+       if (--masq_refcnt > 0)
+               goto out_unlock;
 
-       unregister_inet6addr_notifier(&masq_inet_notifier);
+       unregister_inet6addr_notifier(&masq_inet6_notifier);
        unregister_netdevice_notifier(&masq_dev_notifier);
+out_unlock:
+       mutex_unlock(&masq_mutex);
 }
 EXPORT_SYMBOL_GPL(nf_nat_masquerade_ipv6_unregister_notifier);
index dd0122f..e06c82e 100644 (file)
@@ -70,7 +70,9 @@ static int __init nft_masq_ipv6_module_init(void)
        if (ret < 0)
                return ret;
 
-       nf_nat_masquerade_ipv6_register_notifier();
+       ret = nf_nat_masquerade_ipv6_register_notifier();
+       if (ret)
+               nft_unregister_expr(&nft_masq_ipv6_type);
 
        return ret;
 }
index 83395bf..432141f 100644 (file)
@@ -3980,6 +3980,9 @@ static void __net_exit ip_vs_control_net_cleanup_sysctl(struct netns_ipvs *ipvs)
 
 static struct notifier_block ip_vs_dst_notifier = {
        .notifier_call = ip_vs_dst_event,
+#ifdef CONFIG_IP_VS_IPV6
+       .priority = ADDRCONF_NOTIFY_PRIORITY + 5,
+#endif
 };
 
 int __net_init ip_vs_control_net_init(struct netns_ipvs *ipvs)
index 02ca7df..b6d0f6d 100644 (file)
@@ -49,6 +49,7 @@ struct nf_conncount_tuple {
        struct nf_conntrack_zone        zone;
        int                             cpu;
        u32                             jiffies32;
+       bool                            dead;
        struct rcu_head                 rcu_head;
 };
 
@@ -106,15 +107,16 @@ nf_conncount_add(struct nf_conncount_list *list,
        conn->zone = *zone;
        conn->cpu = raw_smp_processor_id();
        conn->jiffies32 = (u32)jiffies;
-       spin_lock(&list->list_lock);
+       conn->dead = false;
+       spin_lock_bh(&list->list_lock);
        if (list->dead == true) {
                kmem_cache_free(conncount_conn_cachep, conn);
-               spin_unlock(&list->list_lock);
+               spin_unlock_bh(&list->list_lock);
                return NF_CONNCOUNT_SKIP;
        }
        list_add_tail(&conn->node, &list->head);
        list->count++;
-       spin_unlock(&list->list_lock);
+       spin_unlock_bh(&list->list_lock);
        return NF_CONNCOUNT_ADDED;
 }
 EXPORT_SYMBOL_GPL(nf_conncount_add);
@@ -132,19 +134,22 @@ static bool conn_free(struct nf_conncount_list *list,
 {
        bool free_entry = false;
 
-       spin_lock(&list->list_lock);
+       spin_lock_bh(&list->list_lock);
 
-       if (list->count == 0) {
-               spin_unlock(&list->list_lock);
-                return free_entry;
+       if (conn->dead) {
+               spin_unlock_bh(&list->list_lock);
+               return free_entry;
        }
 
        list->count--;
+       conn->dead = true;
        list_del_rcu(&conn->node);
-       if (list->count == 0)
+       if (list->count == 0) {
+               list->dead = true;
                free_entry = true;
+       }
 
-       spin_unlock(&list->list_lock);
+       spin_unlock_bh(&list->list_lock);
        call_rcu(&conn->rcu_head, __conn_free);
        return free_entry;
 }
@@ -245,7 +250,7 @@ void nf_conncount_list_init(struct nf_conncount_list *list)
 {
        spin_lock_init(&list->list_lock);
        INIT_LIST_HEAD(&list->head);
-       list->count = 1;
+       list->count = 0;
        list->dead = false;
 }
 EXPORT_SYMBOL_GPL(nf_conncount_list_init);
@@ -259,6 +264,7 @@ bool nf_conncount_gc_list(struct net *net,
        struct nf_conn *found_ct;
        unsigned int collected = 0;
        bool free_entry = false;
+       bool ret = false;
 
        list_for_each_entry_safe(conn, conn_n, &list->head, node) {
                found = find_or_evict(net, list, conn, &free_entry);
@@ -288,7 +294,15 @@ bool nf_conncount_gc_list(struct net *net,
                if (collected > CONNCOUNT_GC_MAX_NODES)
                        return false;
        }
-       return false;
+
+       spin_lock_bh(&list->list_lock);
+       if (!list->count) {
+               list->dead = true;
+               ret = true;
+       }
+       spin_unlock_bh(&list->list_lock);
+
+       return ret;
 }
 EXPORT_SYMBOL_GPL(nf_conncount_gc_list);
 
@@ -309,11 +323,8 @@ static void tree_nodes_free(struct rb_root *root,
        while (gc_count) {
                rbconn = gc_nodes[--gc_count];
                spin_lock(&rbconn->list.list_lock);
-               if (rbconn->list.count == 0 && rbconn->list.dead == false) {
-                       rbconn->list.dead = true;
-                       rb_erase(&rbconn->node, root);
-                       call_rcu(&rbconn->rcu_head, __tree_nodes_free);
-               }
+               rb_erase(&rbconn->node, root);
+               call_rcu(&rbconn->rcu_head, __tree_nodes_free);
                spin_unlock(&rbconn->list.list_lock);
        }
 }
@@ -414,6 +425,7 @@ insert_tree(struct net *net,
        nf_conncount_list_init(&rbconn->list);
        list_add(&conn->node, &rbconn->list.head);
        count = 1;
+       rbconn->list.count = count;
 
        rb_link_node(&rbconn->node, parent, rbnode);
        rb_insert_color(&rbconn->node, root);
index 9b48dc8..2a5e56c 100644 (file)
 #include <linux/netfilter/nf_conntrack_proto_gre.h>
 #include <linux/netfilter/nf_conntrack_pptp.h>
 
-enum grep_conntrack {
-       GRE_CT_UNREPLIED,
-       GRE_CT_REPLIED,
-       GRE_CT_MAX
-};
-
 static const unsigned int gre_timeouts[GRE_CT_MAX] = {
        [GRE_CT_UNREPLIED]      = 30*HZ,
        [GRE_CT_REPLIED]        = 180*HZ,
 };
 
 static unsigned int proto_gre_net_id __read_mostly;
-struct netns_proto_gre {
-       struct nf_proto_net     nf;
-       rwlock_t                keymap_lock;
-       struct list_head        keymap_list;
-       unsigned int            gre_timeouts[GRE_CT_MAX];
-};
 
 static inline struct netns_proto_gre *gre_pernet(struct net *net)
 {
@@ -402,6 +390,8 @@ static int __init nf_ct_proto_gre_init(void)
 {
        int ret;
 
+       BUILD_BUG_ON(offsetof(struct netns_proto_gre, nf) != 0);
+
        ret = register_pernet_subsys(&proto_gre_net_ops);
        if (ret < 0)
                goto out_pernet;
index 42487d0..2e61aab 100644 (file)
@@ -2457,7 +2457,7 @@ err:
 static void nf_tables_rule_destroy(const struct nft_ctx *ctx,
                                   struct nft_rule *rule)
 {
-       struct nft_expr *expr;
+       struct nft_expr *expr, *next;
 
        /*
         * Careful: some expressions might not be initialized in case this
@@ -2465,8 +2465,9 @@ static void nf_tables_rule_destroy(const struct nft_ctx *ctx,
         */
        expr = nft_expr_first(rule);
        while (expr != nft_expr_last(rule) && expr->ops) {
+               next = nft_expr_next(expr);
                nf_tables_expr_destroy(ctx, expr);
-               expr = nft_expr_next(expr);
+               expr = next;
        }
        kfree(rule);
 }
@@ -2589,17 +2590,14 @@ static int nf_tables_newrule(struct net *net, struct sock *nlsk,
 
                if (chain->use == UINT_MAX)
                        return -EOVERFLOW;
-       }
-
-       if (nla[NFTA_RULE_POSITION]) {
-               if (!(nlh->nlmsg_flags & NLM_F_CREATE))
-                       return -EOPNOTSUPP;
 
-               pos_handle = be64_to_cpu(nla_get_be64(nla[NFTA_RULE_POSITION]));
-               old_rule = __nft_rule_lookup(chain, pos_handle);
-               if (IS_ERR(old_rule)) {
-                       NL_SET_BAD_ATTR(extack, nla[NFTA_RULE_POSITION]);
-                       return PTR_ERR(old_rule);
+               if (nla[NFTA_RULE_POSITION]) {
+                       pos_handle = be64_to_cpu(nla_get_be64(nla[NFTA_RULE_POSITION]));
+                       old_rule = __nft_rule_lookup(chain, pos_handle);
+                       if (IS_ERR(old_rule)) {
+                               NL_SET_BAD_ATTR(extack, nla[NFTA_RULE_POSITION]);
+                               return PTR_ERR(old_rule);
+                       }
                }
        }
 
@@ -2669,21 +2667,14 @@ static int nf_tables_newrule(struct net *net, struct sock *nlsk,
        }
 
        if (nlh->nlmsg_flags & NLM_F_REPLACE) {
-               if (!nft_is_active_next(net, old_rule)) {
-                       err = -ENOENT;
-                       goto err2;
-               }
-               trans = nft_trans_rule_add(&ctx, NFT_MSG_DELRULE,
-                                          old_rule);
+               trans = nft_trans_rule_add(&ctx, NFT_MSG_NEWRULE, rule);
                if (trans == NULL) {
                        err = -ENOMEM;
                        goto err2;
                }
-               nft_deactivate_next(net, old_rule);
-               chain->use--;
-
-               if (nft_trans_rule_add(&ctx, NFT_MSG_NEWRULE, rule) == NULL) {
-                       err = -ENOMEM;
+               err = nft_delrule(&ctx, old_rule);
+               if (err < 0) {
+                       nft_trans_destroy(trans);
                        goto err2;
                }
 
@@ -6324,7 +6315,7 @@ static void nf_tables_commit_chain_free_rules_old(struct nft_rule **rules)
        call_rcu(&old->h, __nf_tables_commit_chain_free_rules_old);
 }
 
-static void nf_tables_commit_chain_active(struct net *net, struct nft_chain *chain)
+static void nf_tables_commit_chain(struct net *net, struct nft_chain *chain)
 {
        struct nft_rule **g0, **g1;
        bool next_genbit;
@@ -6441,11 +6432,8 @@ static int nf_tables_commit(struct net *net, struct sk_buff *skb)
 
        /* step 2.  Make rules_gen_X visible to packet path */
        list_for_each_entry(table, &net->nft.tables, list) {
-               list_for_each_entry(chain, &table->chains, list) {
-                       if (!nft_is_active_next(net, chain))
-                               continue;
-                       nf_tables_commit_chain_active(net, chain);
-               }
+               list_for_each_entry(chain, &table->chains, list)
+                       nf_tables_commit_chain(net, chain);
        }
 
        /*
index a518eb1..109b0d2 100644 (file)
@@ -455,7 +455,8 @@ static int cttimeout_default_get(struct net *net, struct sock *ctnl,
        case IPPROTO_TCP:
                timeouts = nf_tcp_pernet(net)->timeouts;
                break;
-       case IPPROTO_UDP:
+       case IPPROTO_UDP: /* fallthrough */
+       case IPPROTO_UDPLITE:
                timeouts = nf_udp_pernet(net)->timeouts;
                break;
        case IPPROTO_DCCP:
@@ -469,13 +470,23 @@ static int cttimeout_default_get(struct net *net, struct sock *ctnl,
        case IPPROTO_SCTP:
 #ifdef CONFIG_NF_CT_PROTO_SCTP
                timeouts = nf_sctp_pernet(net)->timeouts;
+#endif
+               break;
+       case IPPROTO_GRE:
+#ifdef CONFIG_NF_CT_PROTO_GRE
+               if (l4proto->net_id) {
+                       struct netns_proto_gre *net_gre;
+
+                       net_gre = net_generic(net, *l4proto->net_id);
+                       timeouts = net_gre->gre_timeouts;
+               }
 #endif
                break;
        case 255:
                timeouts = &nf_generic_pernet(net)->timeout;
                break;
        default:
-               WARN_ON_ONCE(1);
+               WARN_ONCE(1, "Missing timeouts for proto %d", l4proto->l4proto);
                break;
        }
 
index 9d0ede4..7334e0b 100644 (file)
@@ -520,6 +520,7 @@ __nft_match_destroy(const struct nft_ctx *ctx, const struct nft_expr *expr,
                    void *info)
 {
        struct xt_match *match = expr->ops->data;
+       struct module *me = match->me;
        struct xt_mtdtor_param par;
 
        par.net = ctx->net;
@@ -530,7 +531,7 @@ __nft_match_destroy(const struct nft_ctx *ctx, const struct nft_expr *expr,
                par.match->destroy(&par);
 
        if (nft_xt_put(container_of(expr->ops, struct nft_xt, ops)))
-               module_put(match->me);
+               module_put(me);
 }
 
 static void
index e82d9a9..974525e 100644 (file)
@@ -214,7 +214,9 @@ static int __init nft_flow_offload_module_init(void)
 {
        int err;
 
-       register_netdevice_notifier(&flow_offload_netdev_notifier);
+       err = register_netdevice_notifier(&flow_offload_netdev_notifier);
+       if (err)
+               goto err;
 
        err = nft_register_expr(&nft_flow_offload_type);
        if (err < 0)
@@ -224,6 +226,7 @@ static int __init nft_flow_offload_module_init(void)
 
 register_expr:
        unregister_netdevice_notifier(&flow_offload_netdev_notifier);
+err:
        return err;
 }
 
index dec843c..9e05c86 100644 (file)
@@ -201,18 +201,8 @@ static __net_init int xt_rateest_net_init(struct net *net)
        return 0;
 }
 
-static void __net_exit xt_rateest_net_exit(struct net *net)
-{
-       struct xt_rateest_net *xn = net_generic(net, xt_rateest_id);
-       int i;
-
-       for (i = 0; i < ARRAY_SIZE(xn->hash); i++)
-               WARN_ON_ONCE(!hlist_empty(&xn->hash[i]));
-}
-
 static struct pernet_operations xt_rateest_net_ops = {
        .init = xt_rateest_net_init,
-       .exit = xt_rateest_net_exit,
        .id   = &xt_rateest_id,
        .size = sizeof(struct xt_rateest_net),
 };
index 3e7d259..1ad4017 100644 (file)
@@ -295,9 +295,10 @@ static int htable_create(struct net *net, struct hashlimit_cfg3 *cfg,
 
        /* copy match config into hashtable config */
        ret = cfg_copy(&hinfo->cfg, (void *)cfg, 3);
-
-       if (ret)
+       if (ret) {
+               vfree(hinfo);
                return ret;
+       }
 
        hinfo->cfg.size = size;
        if (hinfo->cfg.max == 0)
@@ -814,7 +815,6 @@ hashlimit_mt_v1(const struct sk_buff *skb, struct xt_action_param *par)
        int ret;
 
        ret = cfg_copy(&cfg, (void *)&info->cfg, 1);
-
        if (ret)
                return ret;
 
@@ -830,7 +830,6 @@ hashlimit_mt_v2(const struct sk_buff *skb, struct xt_action_param *par)
        int ret;
 
        ret = cfg_copy(&cfg, (void *)&info->cfg, 2);
-
        if (ret)
                return ret;
 
@@ -921,7 +920,6 @@ static int hashlimit_mt_check_v1(const struct xt_mtchk_param *par)
                return ret;
 
        ret = cfg_copy(&cfg, (void *)&info->cfg, 1);
-
        if (ret)
                return ret;
 
@@ -940,7 +938,6 @@ static int hashlimit_mt_check_v2(const struct xt_mtchk_param *par)
                return ret;
 
        ret = cfg_copy(&cfg, (void *)&info->cfg, 2);
-
        if (ret)
                return ret;
 
index b0e74a3..025f48e 100644 (file)
@@ -410,6 +410,7 @@ static void sctp_packet_gso_append(struct sk_buff *head, struct sk_buff *skb)
        head->truesize += skb->truesize;
        head->data_len += skb->len;
        head->len += skb->len;
+       refcount_add(skb->truesize, &head->sk->sk_wmem_alloc);
 
        __skb_header_release(skb);
 }
index 2afc4f8..4880197 100644 (file)
@@ -584,12 +584,15 @@ static void  tipc_node_clear_links(struct tipc_node *node)
 /* tipc_node_cleanup - delete nodes that does not
  * have active links for NODE_CLEANUP_AFTER time
  */
-static int tipc_node_cleanup(struct tipc_node *peer)
+static bool tipc_node_cleanup(struct tipc_node *peer)
 {
        struct tipc_net *tn = tipc_net(peer->net);
        bool deleted = false;
 
-       spin_lock_bh(&tn->node_list_lock);
+       /* If lock held by tipc_node_stop() the node will be deleted anyway */
+       if (!spin_trylock_bh(&tn->node_list_lock))
+               return false;
+
        tipc_node_write_lock(peer);
 
        if (!node_is_up(peer) && time_after(jiffies, peer->delete_at)) {
index a8e7ba9..6a6be9f 100644 (file)
@@ -236,10 +236,8 @@ ifdef CONFIG_GCOV_KERNEL
 objtool_args += --no-unreachable
 endif
 ifdef CONFIG_RETPOLINE
-ifneq ($(RETPOLINE_CFLAGS),)
   objtool_args += --retpoline
 endif
-endif
 
 
 ifdef CONFIG_MODVERSIONS
index 7493c0e..db00e3e 100644 (file)
@@ -395,7 +395,7 @@ usage(void)
  * When we have processed a group that starts off with a known-false
  * #if/#elif sequence (which has therefore been deleted) followed by a
  * #elif that we don't understand and therefore must keep, we edit the
- * latter into a #if to keep the nesting correct. We use strncpy() to
+ * latter into a #if to keep the nesting correct. We use memcpy() to
  * overwrite the 4 byte token "elif" with "if  " without a '\0' byte.
  *
  * When we find a true #elif in a group, the following block will
@@ -450,7 +450,7 @@ static void Idrop (void) { Fdrop();  ignoreon(); }
 static void Itrue (void) { Ftrue();  ignoreon(); }
 static void Ifalse(void) { Ffalse(); ignoreon(); }
 /* modify this line */
-static void Mpass (void) { strncpy(keyword, "if  ", 4); Pelif(); }
+static void Mpass (void) { memcpy(keyword, "if  ", 4); Pelif(); }
 static void Mtrue (void) { keywordedit("else");  state(IS_TRUE_MIDDLE); }
 static void Melif (void) { keywordedit("endif"); state(IS_FALSE_TRAILER); }
 static void Melse (void) { keywordedit("endif"); state(IS_FALSE_ELSE); }
index 74b951f..9cec812 100644 (file)
@@ -80,6 +80,9 @@ static const struct nlmsg_perm nlmsg_route_perms[] =
        { RTM_NEWSTATS,         NETLINK_ROUTE_SOCKET__NLMSG_READ },
        { RTM_GETSTATS,         NETLINK_ROUTE_SOCKET__NLMSG_READ  },
        { RTM_NEWCACHEREPORT,   NETLINK_ROUTE_SOCKET__NLMSG_READ },
+       { RTM_NEWCHAIN,         NETLINK_ROUTE_SOCKET__NLMSG_WRITE },
+       { RTM_DELCHAIN,         NETLINK_ROUTE_SOCKET__NLMSG_WRITE },
+       { RTM_GETCHAIN,         NETLINK_ROUTE_SOCKET__NLMSG_READ  },
 };
 
 static const struct nlmsg_perm nlmsg_tcpdiag_perms[] =
@@ -158,7 +161,11 @@ int selinux_nlmsg_lookup(u16 sclass, u16 nlmsg_type, u32 *perm)
 
        switch (sclass) {
        case SECCLASS_NETLINK_ROUTE_SOCKET:
-               /* RTM_MAX always point to RTM_SETxxxx, ie RTM_NEWxxx + 3 */
+               /* RTM_MAX always points to RTM_SETxxxx, ie RTM_NEWxxx + 3.
+                * If the BUILD_BUG_ON() below fails you must update the
+                * structures at the top of this file with the new mappings
+                * before updating the BUILD_BUG_ON() macro!
+                */
                BUILD_BUG_ON(RTM_MAX != (RTM_NEWCHAIN + 3));
                err = nlmsg_perm(nlmsg_type, perm, nlmsg_route_perms,
                                 sizeof(nlmsg_route_perms));
@@ -170,6 +177,10 @@ int selinux_nlmsg_lookup(u16 sclass, u16 nlmsg_type, u32 *perm)
                break;
 
        case SECCLASS_NETLINK_XFRM_SOCKET:
+               /* If the BUILD_BUG_ON() below fails you must update the
+                * structures at the top of this file with the new mappings
+                * before updating the BUILD_BUG_ON() macro!
+                */
                BUILD_BUG_ON(XFRM_MSG_MAX != XFRM_MSG_MAPPING);
                err = nlmsg_perm(nlmsg_type, perm, nlmsg_xfrm_perms,
                                 sizeof(nlmsg_xfrm_perms));
index 9aa15bf..649d321 100644 (file)
@@ -348,6 +348,40 @@ static int snd_ctl_find_hole(struct snd_card *card, unsigned int count)
        return 0;
 }
 
+/* add a new kcontrol object; call with card->controls_rwsem locked */
+static int __snd_ctl_add(struct snd_card *card, struct snd_kcontrol *kcontrol)
+{
+       struct snd_ctl_elem_id id;
+       unsigned int idx;
+       unsigned int count;
+
+       id = kcontrol->id;
+       if (id.index > UINT_MAX - kcontrol->count)
+               return -EINVAL;
+
+       if (snd_ctl_find_id(card, &id)) {
+               dev_err(card->dev,
+                       "control %i:%i:%i:%s:%i is already present\n",
+                       id.iface, id.device, id.subdevice, id.name, id.index);
+               return -EBUSY;
+       }
+
+       if (snd_ctl_find_hole(card, kcontrol->count) < 0)
+               return -ENOMEM;
+
+       list_add_tail(&kcontrol->list, &card->controls);
+       card->controls_count += kcontrol->count;
+       kcontrol->id.numid = card->last_numid + 1;
+       card->last_numid += kcontrol->count;
+
+       id = kcontrol->id;
+       count = kcontrol->count;
+       for (idx = 0; idx < count; idx++, id.index++, id.numid++)
+               snd_ctl_notify(card, SNDRV_CTL_EVENT_MASK_ADD, &id);
+
+       return 0;
+}
+
 /**
  * snd_ctl_add - add the control instance to the card
  * @card: the card instance
@@ -364,45 +398,18 @@ static int snd_ctl_find_hole(struct snd_card *card, unsigned int count)
  */
 int snd_ctl_add(struct snd_card *card, struct snd_kcontrol *kcontrol)
 {
-       struct snd_ctl_elem_id id;
-       unsigned int idx;
-       unsigned int count;
        int err = -EINVAL;
 
        if (! kcontrol)
                return err;
        if (snd_BUG_ON(!card || !kcontrol->info))
                goto error;
-       id = kcontrol->id;
-       if (id.index > UINT_MAX - kcontrol->count)
-               goto error;
 
        down_write(&card->controls_rwsem);
-       if (snd_ctl_find_id(card, &id)) {
-               up_write(&card->controls_rwsem);
-               dev_err(card->dev, "control %i:%i:%i:%s:%i is already present\n",
-                                       id.iface,
-                                       id.device,
-                                       id.subdevice,
-                                       id.name,
-                                       id.index);
-               err = -EBUSY;
-               goto error;
-       }
-       if (snd_ctl_find_hole(card, kcontrol->count) < 0) {
-               up_write(&card->controls_rwsem);
-               err = -ENOMEM;
-               goto error;
-       }
-       list_add_tail(&kcontrol->list, &card->controls);
-       card->controls_count += kcontrol->count;
-       kcontrol->id.numid = card->last_numid + 1;
-       card->last_numid += kcontrol->count;
-       id = kcontrol->id;
-       count = kcontrol->count;
+       err = __snd_ctl_add(card, kcontrol);
        up_write(&card->controls_rwsem);
-       for (idx = 0; idx < count; idx++, id.index++, id.numid++)
-               snd_ctl_notify(card, SNDRV_CTL_EVENT_MASK_ADD, &id);
+       if (err < 0)
+               goto error;
        return 0;
 
  error:
@@ -1361,9 +1368,12 @@ static int snd_ctl_elem_add(struct snd_ctl_file *file,
                kctl->tlv.c = snd_ctl_elem_user_tlv;
 
        /* This function manage to free the instance on failure. */
-       err = snd_ctl_add(card, kctl);
-       if (err < 0)
-               return err;
+       down_write(&card->controls_rwsem);
+       err = __snd_ctl_add(card, kctl);
+       if (err < 0) {
+               snd_ctl_free_one(kctl);
+               goto unlock;
+       }
        offset = snd_ctl_get_ioff(kctl, &info->id);
        snd_ctl_build_ioff(&info->id, kctl, offset);
        /*
@@ -1374,10 +1384,10 @@ static int snd_ctl_elem_add(struct snd_ctl_file *file,
         * which locks the element.
         */
 
-       down_write(&card->controls_rwsem);
        card->user_ctl_count++;
-       up_write(&card->controls_rwsem);
 
+ unlock:
+       up_write(&card->controls_rwsem);
        return 0;
 }
 
index 32453f8..3a50088 100644 (file)
@@ -1531,7 +1531,6 @@ static int snd_wss_playback_open(struct snd_pcm_substream *substream)
        if (err < 0) {
                if (chip->release_dma)
                        chip->release_dma(chip, chip->dma_private_data, chip->dma1);
-               snd_free_pages(runtime->dma_area, runtime->dma_bytes);
                return err;
        }
        chip->playback_substream = substream;
@@ -1572,7 +1571,6 @@ static int snd_wss_capture_open(struct snd_pcm_substream *substream)
        if (err < 0) {
                if (chip->release_dma)
                        chip->release_dma(chip, chip->dma_private_data, chip->dma2);
-               snd_free_pages(runtime->dma_area, runtime->dma_bytes);
                return err;
        }
        chip->capture_substream = substream;
index f4459d1..27b468f 100644 (file)
@@ -824,7 +824,7 @@ static int snd_ac97_put_spsa(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_
 {
        struct snd_ac97 *ac97 = snd_kcontrol_chip(kcontrol);
        int reg = kcontrol->private_value & 0xff;
-       int shift = (kcontrol->private_value >> 8) & 0xff;
+       int shift = (kcontrol->private_value >> 8) & 0x0f;
        int mask = (kcontrol->private_value >> 16) & 0xff;
        // int invert = (kcontrol->private_value >> 24) & 0xff;
        unsigned short value, old, new;
index d8eb2b5..0bbdf1a 100644 (file)
@@ -2169,6 +2169,8 @@ static struct snd_pci_quirk power_save_blacklist[] = {
        /* https://bugzilla.redhat.com/show_bug.cgi?id=1525104 */
        SND_PCI_QUIRK(0x1849, 0xc892, "Asrock B85M-ITX", 0),
        /* https://bugzilla.redhat.com/show_bug.cgi?id=1525104 */
+       SND_PCI_QUIRK(0x1849, 0x0397, "Asrock N68C-S UCC", 0),
+       /* https://bugzilla.redhat.com/show_bug.cgi?id=1525104 */
        SND_PCI_QUIRK(0x1849, 0x7662, "Asrock H81M-HDS", 0),
        /* https://bugzilla.redhat.com/show_bug.cgi?id=1525104 */
        SND_PCI_QUIRK(0x1043, 0x8733, "Asus Prime X370-Pro", 0),
index 970bc44..06f9303 100644 (file)
@@ -388,6 +388,7 @@ static void alc_fill_eapd_coef(struct hda_codec *codec)
        case 0x10ec0285:
        case 0x10ec0298:
        case 0x10ec0289:
+       case 0x10ec0300:
                alc_update_coef_idx(codec, 0x10, 1<<9, 0);
                break;
        case 0x10ec0275:
@@ -2830,6 +2831,7 @@ enum {
        ALC269_TYPE_ALC215,
        ALC269_TYPE_ALC225,
        ALC269_TYPE_ALC294,
+       ALC269_TYPE_ALC300,
        ALC269_TYPE_ALC700,
 };
 
@@ -2864,6 +2866,7 @@ static int alc269_parse_auto_config(struct hda_codec *codec)
        case ALC269_TYPE_ALC215:
        case ALC269_TYPE_ALC225:
        case ALC269_TYPE_ALC294:
+       case ALC269_TYPE_ALC300:
        case ALC269_TYPE_ALC700:
                ssids = alc269_ssids;
                break;
@@ -5358,6 +5361,16 @@ static void alc274_fixup_bind_dacs(struct hda_codec *codec,
        spec->gen.preferred_dacs = preferred_pairs;
 }
 
+/* The DAC of NID 0x3 will introduce click/pop noise on headphones, so invalidate it */
+static void alc285_fixup_invalidate_dacs(struct hda_codec *codec,
+                             const struct hda_fixup *fix, int action)
+{
+       if (action != HDA_FIXUP_ACT_PRE_PROBE)
+               return;
+
+       snd_hda_override_wcaps(codec, 0x03, 0);
+}
+
 /* for hda_fixup_thinkpad_acpi() */
 #include "thinkpad_helper.c"
 
@@ -5495,6 +5508,8 @@ enum {
        ALC255_FIXUP_DELL_HEADSET_MIC,
        ALC295_FIXUP_HP_X360,
        ALC221_FIXUP_HP_HEADSET_MIC,
+       ALC285_FIXUP_LENOVO_HEADPHONE_NOISE,
+       ALC295_FIXUP_HP_AUTO_MUTE,
 };
 
 static const struct hda_fixup alc269_fixups[] = {
@@ -5659,6 +5674,8 @@ static const struct hda_fixup alc269_fixups[] = {
        [ALC269_FIXUP_HP_MUTE_LED_MIC3] = {
                .type = HDA_FIXUP_FUNC,
                .v.func = alc269_fixup_hp_mute_led_mic3,
+               .chained = true,
+               .chain_id = ALC295_FIXUP_HP_AUTO_MUTE
        },
        [ALC269_FIXUP_HP_GPIO_LED] = {
                .type = HDA_FIXUP_FUNC,
@@ -6362,6 +6379,14 @@ static const struct hda_fixup alc269_fixups[] = {
                .chained = true,
                .chain_id = ALC269_FIXUP_HEADSET_MIC
        },
+       [ALC285_FIXUP_LENOVO_HEADPHONE_NOISE] = {
+               .type = HDA_FIXUP_FUNC,
+               .v.func = alc285_fixup_invalidate_dacs,
+       },
+       [ALC295_FIXUP_HP_AUTO_MUTE] = {
+               .type = HDA_FIXUP_FUNC,
+               .v.func = alc_fixup_auto_mute_via_amp,
+       },
 };
 
 static const struct snd_pci_quirk alc269_fixup_tbl[] = {
@@ -6532,6 +6557,7 @@ static const struct snd_pci_quirk alc269_fixup_tbl[] = {
        SND_PCI_QUIRK(0x144d, 0xc740, "Samsung Ativ book 8 (NP870Z5G)", ALC269_FIXUP_ATIV_BOOK_8),
        SND_PCI_QUIRK(0x1458, 0xfa53, "Gigabyte BXBT-2807", ALC283_FIXUP_HEADSET_MIC),
        SND_PCI_QUIRK(0x1462, 0xb120, "MSI Cubi MS-B120", ALC283_FIXUP_HEADSET_MIC),
+       SND_PCI_QUIRK(0x1462, 0xb171, "Cubi N 8GL (MS-B171)", ALC283_FIXUP_HEADSET_MIC),
        SND_PCI_QUIRK(0x17aa, 0x1036, "Lenovo P520", ALC233_FIXUP_LENOVO_MULTI_CODECS),
        SND_PCI_QUIRK(0x17aa, 0x20f2, "Thinkpad SL410/510", ALC269_FIXUP_SKU_IGNORE),
        SND_PCI_QUIRK(0x17aa, 0x215e, "Thinkpad L512", ALC269_FIXUP_SKU_IGNORE),
@@ -7034,6 +7060,11 @@ static const struct snd_hda_pin_quirk alc269_pin_fixup_tbl[] = {
                {0x12, 0x90a60130},
                {0x19, 0x03a11020},
                {0x21, 0x0321101f}),
+       SND_HDA_PIN_QUIRK(0x10ec0285, 0x17aa, "Lenovo", ALC285_FIXUP_LENOVO_HEADPHONE_NOISE,
+               {0x12, 0x90a60130},
+               {0x14, 0x90170110},
+               {0x19, 0x04a11040},
+               {0x21, 0x04211020}),
        SND_HDA_PIN_QUIRK(0x10ec0288, 0x1028, "Dell", ALC288_FIXUP_DELL1_MIC_NO_PRESENCE,
                {0x12, 0x90a60120},
                {0x14, 0x90170110},
@@ -7295,6 +7326,10 @@ static int patch_alc269(struct hda_codec *codec)
                spec->gen.mixer_nid = 0; /* ALC2x4 does not have any loopback mixer path */
                alc_update_coef_idx(codec, 0x6b, 0x0018, (1<<4) | (1<<3)); /* UAJ MIC Vref control by verb */
                break;
+       case 0x10ec0300:
+               spec->codec_variant = ALC269_TYPE_ALC300;
+               spec->gen.mixer_nid = 0; /* no loopback on ALC300 */
+               break;
        case 0x10ec0700:
        case 0x10ec0701:
        case 0x10ec0703:
@@ -8405,6 +8440,7 @@ static const struct hda_device_id snd_hda_id_realtek[] = {
        HDA_CODEC_ENTRY(0x10ec0295, "ALC295", patch_alc269),
        HDA_CODEC_ENTRY(0x10ec0298, "ALC298", patch_alc269),
        HDA_CODEC_ENTRY(0x10ec0299, "ALC299", patch_alc269),
+       HDA_CODEC_ENTRY(0x10ec0300, "ALC300", patch_alc269),
        HDA_CODEC_REV_ENTRY(0x10ec0861, 0x100340, "ALC660", patch_alc861),
        HDA_CODEC_ENTRY(0x10ec0660, "ALC660-VD", patch_alc861vd),
        HDA_CODEC_ENTRY(0x10ec0861, "ALC861", patch_alc861),
index 4e98548..e63d6e3 100644 (file)
@@ -2187,11 +2187,6 @@ static int hdac_hdmi_runtime_suspend(struct device *dev)
         */
        snd_hdac_codec_read(hdev, hdev->afg, 0, AC_VERB_SET_POWER_STATE,
                                                        AC_PWRST_D3);
-       err = snd_hdac_display_power(bus, false);
-       if (err < 0) {
-               dev_err(dev, "Cannot turn on display power on i915\n");
-               return err;
-       }
 
        hlink = snd_hdac_ext_bus_get_link(bus, dev_name(dev));
        if (!hlink) {
@@ -2201,7 +2196,11 @@ static int hdac_hdmi_runtime_suspend(struct device *dev)
 
        snd_hdac_ext_bus_link_put(bus, hlink);
 
-       return 0;
+       err = snd_hdac_display_power(bus, false);
+       if (err < 0)
+               dev_err(dev, "Cannot turn off display power on i915\n");
+
+       return err;
 }
 
 static int hdac_hdmi_runtime_resume(struct device *dev)
index 2c6ba55..bb3f0c4 100644 (file)
@@ -139,7 +139,7 @@ enum pcm186x_type {
 #define PCM186X_MAX_REGISTER           PCM186X_CURR_TRIM_CTRL
 
 /* PCM186X_PAGE */
-#define PCM186X_RESET                  0xff
+#define PCM186X_RESET                  0xfe
 
 /* PCM186X_ADCX_INPUT_SEL_X */
 #define PCM186X_ADC_INPUT_SEL_POL      BIT(7)
index 494d9d6..771b46e 100644 (file)
@@ -198,20 +198,16 @@ static const struct snd_kcontrol_new pcm3060_dapm_controls[] = {
 };
 
 static const struct snd_soc_dapm_widget pcm3060_dapm_widgets[] = {
-       SND_SOC_DAPM_OUTPUT("OUTL+"),
-       SND_SOC_DAPM_OUTPUT("OUTR+"),
-       SND_SOC_DAPM_OUTPUT("OUTL-"),
-       SND_SOC_DAPM_OUTPUT("OUTR-"),
+       SND_SOC_DAPM_OUTPUT("OUTL"),
+       SND_SOC_DAPM_OUTPUT("OUTR"),
 
        SND_SOC_DAPM_INPUT("INL"),
        SND_SOC_DAPM_INPUT("INR"),
 };
 
 static const struct snd_soc_dapm_route pcm3060_dapm_map[] = {
-       { "OUTL+", NULL, "Playback" },
-       { "OUTR+", NULL, "Playback" },
-       { "OUTL-", NULL, "Playback" },
-       { "OUTR-", NULL, "Playback" },
+       { "OUTL", NULL, "Playback" },
+       { "OUTR", NULL, "Playback" },
 
        { "Capture", NULL, "INL" },
        { "Capture", NULL, "INR" },
index a53dc17..66501b8 100644 (file)
@@ -765,38 +765,41 @@ static unsigned int wm_adsp_region_to_reg(struct wm_adsp_region const *mem,
 
 static void wm_adsp2_show_fw_status(struct wm_adsp *dsp)
 {
-       u16 scratch[4];
+       unsigned int scratch[4];
+       unsigned int addr = dsp->base + ADSP2_SCRATCH0;
+       unsigned int i;
        int ret;
 
-       ret = regmap_raw_read(dsp->regmap, dsp->base + ADSP2_SCRATCH0,
-                               scratch, sizeof(scratch));
-       if (ret) {
-               adsp_err(dsp, "Failed to read SCRATCH regs: %d\n", ret);
-               return;
+       for (i = 0; i < ARRAY_SIZE(scratch); ++i) {
+               ret = regmap_read(dsp->regmap, addr + i, &scratch[i]);
+               if (ret) {
+                       adsp_err(dsp, "Failed to read SCRATCH%u: %d\n", i, ret);
+                       return;
+               }
        }
 
        adsp_dbg(dsp, "FW SCRATCH 0:0x%x 1:0x%x 2:0x%x 3:0x%x\n",
-                be16_to_cpu(scratch[0]),
-                be16_to_cpu(scratch[1]),
-                be16_to_cpu(scratch[2]),
-                be16_to_cpu(scratch[3]));
+                scratch[0], scratch[1], scratch[2], scratch[3]);
 }
 
 static void wm_adsp2v2_show_fw_status(struct wm_adsp *dsp)
 {
-       u32 scratch[2];
+       unsigned int scratch[2];
        int ret;
 
-       ret = regmap_raw_read(dsp->regmap, dsp->base + ADSP2V2_SCRATCH0_1,
-                             scratch, sizeof(scratch));
-
+       ret = regmap_read(dsp->regmap, dsp->base + ADSP2V2_SCRATCH0_1,
+                         &scratch[0]);
        if (ret) {
-               adsp_err(dsp, "Failed to read SCRATCH regs: %d\n", ret);
+               adsp_err(dsp, "Failed to read SCRATCH0_1: %d\n", ret);
                return;
        }
 
-       scratch[0] = be32_to_cpu(scratch[0]);
-       scratch[1] = be32_to_cpu(scratch[1]);
+       ret = regmap_read(dsp->regmap, dsp->base + ADSP2V2_SCRATCH2_3,
+                         &scratch[1]);
+       if (ret) {
+               adsp_err(dsp, "Failed to read SCRATCH2_3: %d\n", ret);
+               return;
+       }
 
        adsp_dbg(dsp, "FW SCRATCH 0:0x%x 1:0x%x 2:0x%x 3:0x%x\n",
                 scratch[0] & 0xFFFF,
index 0caa1f4..18e7177 100644 (file)
@@ -101,22 +101,42 @@ config SND_SST_ATOM_HIFI2_PLATFORM_ACPI
          codec, then enable this option by saying Y or m. This is a
          recommended option
 
-config SND_SOC_INTEL_SKYLAKE_SSP_CLK
-       tristate
-
 config SND_SOC_INTEL_SKYLAKE
        tristate "SKL/BXT/KBL/GLK/CNL... Platforms"
        depends on PCI && ACPI
+       select SND_SOC_INTEL_SKYLAKE_COMMON
+       help
+         If you have a Intel Skylake/Broxton/ApolloLake/KabyLake/
+         GeminiLake or CannonLake platform with the DSP enabled in the BIOS
+         then enable this option by saying Y or m.
+
+if  SND_SOC_INTEL_SKYLAKE
+
+config SND_SOC_INTEL_SKYLAKE_SSP_CLK
+       tristate
+
+config SND_SOC_INTEL_SKYLAKE_HDAUDIO_CODEC
+       bool "HDAudio codec support"
+       help
+         If you have a Intel Skylake/Broxton/ApolloLake/KabyLake/
+         GeminiLake or CannonLake platform with an HDaudio codec
+         then enable this option by saying Y
+
+config SND_SOC_INTEL_SKYLAKE_COMMON
+       tristate
        select SND_HDA_EXT_CORE
        select SND_HDA_DSP_LOADER
        select SND_SOC_TOPOLOGY
        select SND_SOC_INTEL_SST
+       select SND_SOC_HDAC_HDA if SND_SOC_INTEL_SKYLAKE_HDAUDIO_CODEC
        select SND_SOC_ACPI_INTEL_MATCH
        help
          If you have a Intel Skylake/Broxton/ApolloLake/KabyLake/
          GeminiLake or CannonLake platform with the DSP enabled in the BIOS
          then enable this option by saying Y or m.
 
+endif ## SND_SOC_INTEL_SKYLAKE
+
 config SND_SOC_ACPI_INTEL_MATCH
        tristate
        select SND_SOC_ACPI if ACPI
index 73ca135..b177db2 100644 (file)
@@ -293,16 +293,6 @@ config SND_SOC_INTEL_KBL_DA7219_MAX98927_MACH
          Say Y if you have such a device.
          If unsure select "N".
 
-config SND_SOC_INTEL_SKL_HDA_DSP_GENERIC_MACH
-       tristate "SKL/KBL/BXT/APL with HDA Codecs"
-       select SND_SOC_HDAC_HDMI
-       select SND_SOC_HDAC_HDA
-       help
-         This adds support for ASoC machine driver for Intel platforms
-         SKL/KBL/BXT/APL with iDisp, HDA audio codecs.
-          Say Y or m if you have such a device. This is a recommended option.
-         If unsure select "N".
-
 config SND_SOC_INTEL_GLK_RT5682_MAX98357A_MACH
        tristate "GLK with RT5682 and MAX98357A in I2S Mode"
        depends on MFD_INTEL_LPSS && I2C && ACPI
@@ -319,4 +309,18 @@ config SND_SOC_INTEL_GLK_RT5682_MAX98357A_MACH
 
 endif ## SND_SOC_INTEL_SKYLAKE
 
+if SND_SOC_INTEL_SKYLAKE_HDAUDIO_CODEC
+
+config SND_SOC_INTEL_SKL_HDA_DSP_GENERIC_MACH
+       tristate "SKL/KBL/BXT/APL with HDA Codecs"
+       select SND_SOC_HDAC_HDMI
+       # SND_SOC_HDAC_HDA is already selected
+       help
+         This adds support for ASoC machine driver for Intel platforms
+         SKL/KBL/BXT/APL with iDisp, HDA audio codecs.
+          Say Y or m if you have such a device. This is a recommended option.
+         If unsure select "N".
+
+endif ## SND_SOC_INTEL_SKYLAKE_HDAUDIO_CODEC
+
 endif ## SND_SOC_INTEL_MACH
index db6976f..9d9f6e4 100644 (file)
@@ -19,6 +19,7 @@
  * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  */
 
+#include <linux/dmi.h>
 #include <linux/module.h>
 #include <linux/platform_device.h>
 #include <linux/slab.h>
@@ -35,6 +36,8 @@
 #define CHT_PLAT_CLK_3_HZ      19200000
 #define CHT_CODEC_DAI  "HiFi"
 
+#define QUIRK_PMC_PLT_CLK_0                            0x01
+
 struct cht_mc_private {
        struct clk *mclk;
        struct snd_soc_jack jack;
@@ -385,11 +388,29 @@ static struct snd_soc_card snd_soc_card_cht = {
        .num_controls = ARRAY_SIZE(cht_mc_controls),
 };
 
+static const struct dmi_system_id cht_max98090_quirk_table[] = {
+       {
+               /* Swanky model Chromebook (Toshiba Chromebook 2) */
+               .matches = {
+                       DMI_MATCH(DMI_PRODUCT_NAME, "Swanky"),
+               },
+               .driver_data = (void *)QUIRK_PMC_PLT_CLK_0,
+       },
+       {}
+};
+
 static int snd_cht_mc_probe(struct platform_device *pdev)
 {
+       const struct dmi_system_id *dmi_id;
        struct device *dev = &pdev->dev;
        int ret_val = 0;
        struct cht_mc_private *drv;
+       const char *mclk_name;
+       int quirks = 0;
+
+       dmi_id = dmi_first_match(cht_max98090_quirk_table);
+       if (dmi_id)
+               quirks = (unsigned long)dmi_id->driver_data;
 
        drv = devm_kzalloc(&pdev->dev, sizeof(*drv), GFP_KERNEL);
        if (!drv)
@@ -411,11 +432,16 @@ static int snd_cht_mc_probe(struct platform_device *pdev)
        snd_soc_card_cht.dev = &pdev->dev;
        snd_soc_card_set_drvdata(&snd_soc_card_cht, drv);
 
-       drv->mclk = devm_clk_get(&pdev->dev, "pmc_plt_clk_3");
+       if (quirks & QUIRK_PMC_PLT_CLK_0)
+               mclk_name = "pmc_plt_clk_0";
+       else
+               mclk_name = "pmc_plt_clk_3";
+
+       drv->mclk = devm_clk_get(&pdev->dev, mclk_name);
        if (IS_ERR(drv->mclk)) {
                dev_err(&pdev->dev,
-                       "Failed to get MCLK from pmc_plt_clk_3: %ld\n",
-                       PTR_ERR(drv->mclk));
+                       "Failed to get MCLK from %s: %ld\n",
+                       mclk_name, PTR_ERR(drv->mclk));
                return PTR_ERR(drv->mclk);
        }
 
index 2922562..7487f38 100644 (file)
@@ -37,7 +37,9 @@
 #include "skl.h"
 #include "skl-sst-dsp.h"
 #include "skl-sst-ipc.h"
+#if IS_ENABLED(CONFIG_SND_SOC_INTEL_SKYLAKE_HDAUDIO_CODEC)
 #include "../../../soc/codecs/hdac_hda.h"
+#endif
 
 /*
  * initialize the PCI registers
@@ -658,6 +660,8 @@ static void skl_clock_device_unregister(struct skl *skl)
                platform_device_unregister(skl->clk_dev);
 }
 
+#if IS_ENABLED(CONFIG_SND_SOC_INTEL_SKYLAKE_HDAUDIO_CODEC)
+
 #define IDISP_INTEL_VENDOR_ID  0x80860000
 
 /*
@@ -676,6 +680,8 @@ static void load_codec_module(struct hda_codec *codec)
 #endif
 }
 
+#endif /* CONFIG_SND_SOC_INTEL_SKYLAKE_HDAUDIO_CODEC */
+
 /*
  * Probe the given codec address
  */
@@ -685,9 +691,11 @@ static int probe_codec(struct hdac_bus *bus, int addr)
                (AC_VERB_PARAMETERS << 8) | AC_PAR_VENDOR_ID;
        unsigned int res = -1;
        struct skl *skl = bus_to_skl(bus);
+#if IS_ENABLED(CONFIG_SND_SOC_INTEL_SKYLAKE_HDAUDIO_CODEC)
        struct hdac_hda_priv *hda_codec;
-       struct hdac_device *hdev;
        int err;
+#endif
+       struct hdac_device *hdev;
 
        mutex_lock(&bus->cmd_mutex);
        snd_hdac_bus_send_cmd(bus, cmd);
@@ -697,6 +705,7 @@ static int probe_codec(struct hdac_bus *bus, int addr)
                return -EIO;
        dev_dbg(bus->dev, "codec #%d probed OK: %x\n", addr, res);
 
+#if IS_ENABLED(CONFIG_SND_SOC_INTEL_SKYLAKE_HDAUDIO_CODEC)
        hda_codec = devm_kzalloc(&skl->pci->dev, sizeof(*hda_codec),
                                 GFP_KERNEL);
        if (!hda_codec)
@@ -715,6 +724,13 @@ static int probe_codec(struct hdac_bus *bus, int addr)
                load_codec_module(&hda_codec->codec);
        }
        return 0;
+#else
+       hdev = devm_kzalloc(&skl->pci->dev, sizeof(*hdev), GFP_KERNEL);
+       if (!hdev)
+               return -ENOMEM;
+
+       return snd_hdac_ext_bus_device_init(bus, addr, hdev);
+#endif /* CONFIG_SND_SOC_INTEL_SKYLAKE_HDAUDIO_CODEC */
 }
 
 /* Codec initialization */
@@ -815,6 +831,12 @@ static void skl_probe_work(struct work_struct *work)
                }
        }
 
+       /*
+        * we are done probing so decrement link counts
+        */
+       list_for_each_entry(hlink, &bus->hlink_list, list)
+               snd_hdac_ext_bus_link_put(bus, hlink);
+
        if (IS_ENABLED(CONFIG_SND_SOC_HDAC_HDMI)) {
                err = snd_hdac_display_power(bus, false);
                if (err < 0) {
@@ -824,12 +846,6 @@ static void skl_probe_work(struct work_struct *work)
                }
        }
 
-       /*
-        * we are done probing so decrement link counts
-        */
-       list_for_each_entry(hlink, &bus->hlink_list, list)
-               snd_hdac_ext_bus_link_put(bus, hlink);
-
        /* configure PM */
        pm_runtime_put_noidle(bus->dev);
        pm_runtime_allow(bus->dev);
@@ -870,7 +886,7 @@ static int skl_create(struct pci_dev *pci,
        hbus = skl_to_hbus(skl);
        bus = skl_to_bus(skl);
 
-#if IS_ENABLED(CONFIG_SND_SOC_HDAC_HDA)
+#if IS_ENABLED(CONFIG_SND_SOC_INTEL_SKYLAKE_HDAUDIO_CODEC)
        ext_ops = snd_soc_hdac_hda_get_ops();
 #endif
        snd_hdac_ext_bus_init(bus, &pci->dev, &bus_core_ops, io_ops, ext_ops);
index d5ae9eb..fed45b4 100644 (file)
@@ -36,6 +36,8 @@
 #include "../codecs/twl6040.h"
 
 struct abe_twl6040 {
+       struct snd_soc_card card;
+       struct snd_soc_dai_link dai_links[2];
        int     jack_detection; /* board can detect jack events */
        int     mclk_freq;      /* MCLK frequency speed for twl6040 */
 };
@@ -208,40 +210,10 @@ static int omap_abe_dmic_init(struct snd_soc_pcm_runtime *rtd)
                                ARRAY_SIZE(dmic_audio_map));
 }
 
-/* Digital audio interface glue - connects codec <--> CPU */
-static struct snd_soc_dai_link abe_twl6040_dai_links[] = {
-       {
-               .name = "TWL6040",
-               .stream_name = "TWL6040",
-               .codec_dai_name = "twl6040-legacy",
-               .codec_name = "twl6040-codec",
-               .init = omap_abe_twl6040_init,
-               .ops = &omap_abe_ops,
-       },
-       {
-               .name = "DMIC",
-               .stream_name = "DMIC Capture",
-               .codec_dai_name = "dmic-hifi",
-               .codec_name = "dmic-codec",
-               .init = omap_abe_dmic_init,
-               .ops = &omap_abe_dmic_ops,
-       },
-};
-
-/* Audio machine driver */
-static struct snd_soc_card omap_abe_card = {
-       .owner = THIS_MODULE,
-
-       .dapm_widgets = twl6040_dapm_widgets,
-       .num_dapm_widgets = ARRAY_SIZE(twl6040_dapm_widgets),
-       .dapm_routes = audio_map,
-       .num_dapm_routes = ARRAY_SIZE(audio_map),
-};
-
 static int omap_abe_probe(struct platform_device *pdev)
 {
        struct device_node *node = pdev->dev.of_node;
-       struct snd_soc_card *card = &omap_abe_card;
+       struct snd_soc_card *card;
        struct device_node *dai_node;
        struct abe_twl6040 *priv;
        int num_links = 0;
@@ -252,12 +224,18 @@ static int omap_abe_probe(struct platform_device *pdev)
                return -ENODEV;
        }
 
-       card->dev = &pdev->dev;
-
        priv = devm_kzalloc(&pdev->dev, sizeof(struct abe_twl6040), GFP_KERNEL);
        if (priv == NULL)
                return -ENOMEM;
 
+       card = &priv->card;
+       card->dev = &pdev->dev;
+       card->owner = THIS_MODULE;
+       card->dapm_widgets = twl6040_dapm_widgets;
+       card->num_dapm_widgets = ARRAY_SIZE(twl6040_dapm_widgets);
+       card->dapm_routes = audio_map;
+       card->num_dapm_routes = ARRAY_SIZE(audio_map);
+
        if (snd_soc_of_parse_card_name(card, "ti,model")) {
                dev_err(&pdev->dev, "Card name is not provided\n");
                return -ENODEV;
@@ -274,14 +252,27 @@ static int omap_abe_probe(struct platform_device *pdev)
                dev_err(&pdev->dev, "McPDM node is not provided\n");
                return -EINVAL;
        }
-       abe_twl6040_dai_links[0].cpu_of_node = dai_node;
-       abe_twl6040_dai_links[0].platform_of_node = dai_node;
+
+       priv->dai_links[0].name = "DMIC";
+       priv->dai_links[0].stream_name = "TWL6040";
+       priv->dai_links[0].cpu_of_node = dai_node;
+       priv->dai_links[0].platform_of_node = dai_node;
+       priv->dai_links[0].codec_dai_name = "twl6040-legacy";
+       priv->dai_links[0].codec_name = "twl6040-codec";
+       priv->dai_links[0].init = omap_abe_twl6040_init;
+       priv->dai_links[0].ops = &omap_abe_ops;
 
        dai_node = of_parse_phandle(node, "ti,dmic", 0);
        if (dai_node) {
                num_links = 2;
-               abe_twl6040_dai_links[1].cpu_of_node = dai_node;
-               abe_twl6040_dai_links[1].platform_of_node = dai_node;
+               priv->dai_links[1].name = "TWL6040";
+               priv->dai_links[1].stream_name = "DMIC Capture";
+               priv->dai_links[1].cpu_of_node = dai_node;
+               priv->dai_links[1].platform_of_node = dai_node;
+               priv->dai_links[1].codec_dai_name = "dmic-hifi";
+               priv->dai_links[1].codec_name = "dmic-codec";
+               priv->dai_links[1].init = omap_abe_dmic_init;
+               priv->dai_links[1].ops = &omap_abe_dmic_ops;
        } else {
                num_links = 1;
        }
@@ -300,7 +291,7 @@ static int omap_abe_probe(struct platform_device *pdev)
                return -ENODEV;
        }
 
-       card->dai_link = abe_twl6040_dai_links;
+       card->dai_link = priv->dai_links;
        card->num_links = num_links;
 
        snd_soc_card_set_drvdata(card, priv);
index fe96627..cba9645 100644 (file)
@@ -48,6 +48,8 @@ struct omap_dmic {
        struct device *dev;
        void __iomem *io_base;
        struct clk *fclk;
+       struct pm_qos_request pm_qos_req;
+       int latency;
        int fclk_freq;
        int out_freq;
        int clk_div;
@@ -124,6 +126,8 @@ static void omap_dmic_dai_shutdown(struct snd_pcm_substream *substream,
 
        mutex_lock(&dmic->mutex);
 
+       pm_qos_remove_request(&dmic->pm_qos_req);
+
        if (!dai->active)
                dmic->active = 0;
 
@@ -228,6 +232,8 @@ static int omap_dmic_dai_hw_params(struct snd_pcm_substream *substream,
        /* packet size is threshold * channels */
        dma_data = snd_soc_dai_get_dma_data(dai, substream);
        dma_data->maxburst = dmic->threshold * channels;
+       dmic->latency = (OMAP_DMIC_THRES_MAX - dmic->threshold) * USEC_PER_SEC /
+                       params_rate(params);
 
        return 0;
 }
@@ -238,6 +244,9 @@ static int omap_dmic_dai_prepare(struct snd_pcm_substream *substream,
        struct omap_dmic *dmic = snd_soc_dai_get_drvdata(dai);
        u32 ctrl;
 
+       if (pm_qos_request_active(&dmic->pm_qos_req))
+               pm_qos_update_request(&dmic->pm_qos_req, dmic->latency);
+
        /* Configure uplink threshold */
        omap_dmic_write(dmic, OMAP_DMIC_FIFO_CTRL_REG, dmic->threshold);
 
index d0ebb6b..2d6decb 100644 (file)
@@ -308,9 +308,9 @@ static int omap_mcbsp_dai_hw_params(struct snd_pcm_substream *substream,
                        pkt_size = channels;
                }
 
-               latency = ((((buffer_size - pkt_size) / channels) * 1000)
-                                / (params->rate_num / params->rate_den));
-
+               latency = (buffer_size - pkt_size) / channels;
+               latency = latency * USEC_PER_SEC /
+                         (params->rate_num / params->rate_den);
                mcbsp->latency[substream->stream] = latency;
 
                omap_mcbsp_set_threshold(substream, pkt_size);
index 4c1be36..7d5bdc5 100644 (file)
@@ -54,6 +54,8 @@ struct omap_mcpdm {
        unsigned long phys_base;
        void __iomem *io_base;
        int irq;
+       struct pm_qos_request pm_qos_req;
+       int latency[2];
 
        struct mutex mutex;
 
@@ -277,6 +279,9 @@ static void omap_mcpdm_dai_shutdown(struct snd_pcm_substream *substream,
                                  struct snd_soc_dai *dai)
 {
        struct omap_mcpdm *mcpdm = snd_soc_dai_get_drvdata(dai);
+       int tx = (substream->stream == SNDRV_PCM_STREAM_PLAYBACK);
+       int stream1 = tx ? SNDRV_PCM_STREAM_PLAYBACK : SNDRV_PCM_STREAM_CAPTURE;
+       int stream2 = tx ? SNDRV_PCM_STREAM_CAPTURE : SNDRV_PCM_STREAM_PLAYBACK;
 
        mutex_lock(&mcpdm->mutex);
 
@@ -289,6 +294,14 @@ static void omap_mcpdm_dai_shutdown(struct snd_pcm_substream *substream,
                }
        }
 
+       if (mcpdm->latency[stream2])
+               pm_qos_update_request(&mcpdm->pm_qos_req,
+                                     mcpdm->latency[stream2]);
+       else if (mcpdm->latency[stream1])
+               pm_qos_remove_request(&mcpdm->pm_qos_req);
+
+       mcpdm->latency[stream1] = 0;
+
        mutex_unlock(&mcpdm->mutex);
 }
 
@@ -300,7 +313,7 @@ static int omap_mcpdm_dai_hw_params(struct snd_pcm_substream *substream,
        int stream = substream->stream;
        struct snd_dmaengine_dai_dma_data *dma_data;
        u32 threshold;
-       int channels;
+       int channels, latency;
        int link_mask = 0;
 
        channels = params_channels(params);
@@ -344,14 +357,25 @@ static int omap_mcpdm_dai_hw_params(struct snd_pcm_substream *substream,
 
                dma_data->maxburst =
                                (MCPDM_DN_THRES_MAX - threshold) * channels;
+               latency = threshold;
        } else {
                /* If playback is not running assume a stereo stream to come */
                if (!mcpdm->config[!stream].link_mask)
                        mcpdm->config[!stream].link_mask = (0x3 << 3);
 
                dma_data->maxburst = threshold * channels;
+               latency = (MCPDM_DN_THRES_MAX - threshold);
        }
 
+       /*
+        * The DMA must act to a DMA request within latency time (usec) to avoid
+        * under/overflow
+        */
+       mcpdm->latency[stream] = latency * USEC_PER_SEC / params_rate(params);
+
+       if (!mcpdm->latency[stream])
+               mcpdm->latency[stream] = 10;
+
        /* Check if we need to restart McPDM with this stream */
        if (mcpdm->config[stream].link_mask &&
            mcpdm->config[stream].link_mask != link_mask)
@@ -366,6 +390,20 @@ static int omap_mcpdm_prepare(struct snd_pcm_substream *substream,
                                  struct snd_soc_dai *dai)
 {
        struct omap_mcpdm *mcpdm = snd_soc_dai_get_drvdata(dai);
+       struct pm_qos_request *pm_qos_req = &mcpdm->pm_qos_req;
+       int tx = (substream->stream == SNDRV_PCM_STREAM_PLAYBACK);
+       int stream1 = tx ? SNDRV_PCM_STREAM_PLAYBACK : SNDRV_PCM_STREAM_CAPTURE;
+       int stream2 = tx ? SNDRV_PCM_STREAM_CAPTURE : SNDRV_PCM_STREAM_PLAYBACK;
+       int latency = mcpdm->latency[stream2];
+
+       /* Prevent omap hardware from hitting off between FIFO fills */
+       if (!latency || mcpdm->latency[stream1] < latency)
+               latency = mcpdm->latency[stream1];
+
+       if (pm_qos_request_active(pm_qos_req))
+               pm_qos_update_request(pm_qos_req, latency);
+       else if (latency)
+               pm_qos_add_request(pm_qos_req, PM_QOS_CPU_DMA_LATENCY, latency);
 
        if (!omap_mcpdm_active(mcpdm)) {
                omap_mcpdm_start(mcpdm);
@@ -427,6 +465,9 @@ static int omap_mcpdm_remove(struct snd_soc_dai *dai)
        free_irq(mcpdm->irq, (void *)mcpdm);
        pm_runtime_disable(mcpdm->dev);
 
+       if (pm_qos_request_active(&mcpdm->pm_qos_req))
+               pm_qos_remove_request(&mcpdm->pm_qos_req);
+
        return 0;
 }
 
index eb1b9da..4715527 100644 (file)
@@ -13,6 +13,7 @@ int qcom_snd_parse_of(struct snd_soc_card *card)
        struct device_node *cpu = NULL;
        struct device *dev = card->dev;
        struct snd_soc_dai_link *link;
+       struct of_phandle_args args;
        int ret, num_links;
 
        ret = snd_soc_of_parse_card_name(card, "model");
@@ -47,12 +48,14 @@ int qcom_snd_parse_of(struct snd_soc_card *card)
                        goto err;
                }
 
-               link->cpu_of_node = of_parse_phandle(cpu, "sound-dai", 0);
-               if (!link->cpu_of_node) {
+               ret = of_parse_phandle_with_args(cpu, "sound-dai",
+                                       "#sound-dai-cells", 0, &args);
+               if (ret) {
                        dev_err(card->dev, "error getting cpu phandle\n");
-                       ret = -EINVAL;
                        goto err;
                }
+               link->cpu_of_node = args.np;
+               link->id = args.args[0];
 
                ret = snd_soc_of_get_dai_name(cpu, &link->cpu_dai_name);
                if (ret) {
index 60ff4a2..8f6c8fc 100644 (file)
@@ -1112,204 +1112,204 @@ static int q6afe_of_xlate_dai_name(struct snd_soc_component *component,
 }
 
 static const struct snd_soc_dapm_widget q6afe_dai_widgets[] = {
-       SND_SOC_DAPM_AIF_OUT("HDMI_RX", "HDMI Playback", 0, 0, 0, 0),
-       SND_SOC_DAPM_AIF_OUT("SLIMBUS_0_RX", "Slimbus Playback", 0, 0, 0, 0),
-       SND_SOC_DAPM_AIF_OUT("SLIMBUS_1_RX", "Slimbus1 Playback", 0, 0, 0, 0),
-       SND_SOC_DAPM_AIF_OUT("SLIMBUS_2_RX", "Slimbus2 Playback", 0, 0, 0, 0),
-       SND_SOC_DAPM_AIF_OUT("SLIMBUS_3_RX", "Slimbus3 Playback", 0, 0, 0, 0),
-       SND_SOC_DAPM_AIF_OUT("SLIMBUS_4_RX", "Slimbus4 Playback", 0, 0, 0, 0),
-       SND_SOC_DAPM_AIF_OUT("SLIMBUS_5_RX", "Slimbus5 Playback", 0, 0, 0, 0),
-       SND_SOC_DAPM_AIF_OUT("SLIMBUS_6_RX", "Slimbus6 Playback", 0, 0, 0, 0),
-       SND_SOC_DAPM_AIF_IN("SLIMBUS_0_TX", "Slimbus Capture", 0, 0, 0, 0),
-       SND_SOC_DAPM_AIF_IN("SLIMBUS_1_TX", "Slimbus1 Capture", 0, 0, 0, 0),
-       SND_SOC_DAPM_AIF_IN("SLIMBUS_2_TX", "Slimbus2 Capture", 0, 0, 0, 0),
-       SND_SOC_DAPM_AIF_IN("SLIMBUS_3_TX", "Slimbus3 Capture", 0, 0, 0, 0),
-       SND_SOC_DAPM_AIF_IN("SLIMBUS_4_TX", "Slimbus4 Capture", 0, 0, 0, 0),
-       SND_SOC_DAPM_AIF_IN("SLIMBUS_5_TX", "Slimbus5 Capture", 0, 0, 0, 0),
-       SND_SOC_DAPM_AIF_IN("SLIMBUS_6_TX", "Slimbus6 Capture", 0, 0, 0, 0),
-       SND_SOC_DAPM_AIF_OUT("QUAT_MI2S_RX", "Quaternary MI2S Playback",
+       SND_SOC_DAPM_AIF_IN("HDMI_RX", NULL, 0, 0, 0, 0),
+       SND_SOC_DAPM_AIF_IN("SLIMBUS_0_RX", NULL, 0, 0, 0, 0),
+       SND_SOC_DAPM_AIF_IN("SLIMBUS_1_RX", NULL, 0, 0, 0, 0),
+       SND_SOC_DAPM_AIF_IN("SLIMBUS_2_RX", NULL, 0, 0, 0, 0),
+       SND_SOC_DAPM_AIF_IN("SLIMBUS_3_RX", NULL, 0, 0, 0, 0),
+       SND_SOC_DAPM_AIF_IN("SLIMBUS_4_RX", NULL, 0, 0, 0, 0),
+       SND_SOC_DAPM_AIF_IN("SLIMBUS_5_RX", NULL, 0, 0, 0, 0),
+       SND_SOC_DAPM_AIF_IN("SLIMBUS_6_RX", NULL, 0, 0, 0, 0),
+       SND_SOC_DAPM_AIF_OUT("SLIMBUS_0_TX", NULL, 0, 0, 0, 0),
+       SND_SOC_DAPM_AIF_OUT("SLIMBUS_1_TX", NULL, 0, 0, 0, 0),
+       SND_SOC_DAPM_AIF_OUT("SLIMBUS_2_TX", NULL, 0, 0, 0, 0),
+       SND_SOC_DAPM_AIF_OUT("SLIMBUS_3_TX", NULL, 0, 0, 0, 0),
+       SND_SOC_DAPM_AIF_OUT("SLIMBUS_4_TX", NULL, 0, 0, 0, 0),
+       SND_SOC_DAPM_AIF_OUT("SLIMBUS_5_TX", NULL, 0, 0, 0, 0),
+       SND_SOC_DAPM_AIF_OUT("SLIMBUS_6_TX", NULL, 0, 0, 0, 0),
+       SND_SOC_DAPM_AIF_IN("QUAT_MI2S_RX", NULL,
                                                0, 0, 0, 0),
-       SND_SOC_DAPM_AIF_IN("QUAT_MI2S_TX", "Quaternary MI2S Capture",
+       SND_SOC_DAPM_AIF_OUT("QUAT_MI2S_TX", NULL,
                                                0, 0, 0, 0),
-       SND_SOC_DAPM_AIF_OUT("TERT_MI2S_RX", "Tertiary MI2S Playback",
+       SND_SOC_DAPM_AIF_IN("TERT_MI2S_RX", NULL,
                                                0, 0, 0, 0),
-       SND_SOC_DAPM_AIF_IN("TERT_MI2S_TX", "Tertiary MI2S Capture",
+       SND_SOC_DAPM_AIF_OUT("TERT_MI2S_TX", NULL,
                                                0, 0, 0, 0),
-       SND_SOC_DAPM_AIF_OUT("SEC_MI2S_RX", "Secondary MI2S Playback",
+       SND_SOC_DAPM_AIF_IN("SEC_MI2S_RX", NULL,
                             0, 0, 0, 0),
-       SND_SOC_DAPM_AIF_IN("SEC_MI2S_TX", "Secondary MI2S Capture",
+       SND_SOC_DAPM_AIF_OUT("SEC_MI2S_TX", NULL,
                                                0, 0, 0, 0),
-       SND_SOC_DAPM_AIF_OUT("SEC_MI2S_RX_SD1",
+       SND_SOC_DAPM_AIF_IN("SEC_MI2S_RX_SD1",
                        "Secondary MI2S Playback SD1",
                        0, 0, 0, 0),
-       SND_SOC_DAPM_AIF_OUT("PRI_MI2S_RX", "Primary MI2S Playback",
+       SND_SOC_DAPM_AIF_IN("PRI_MI2S_RX", NULL,
                             0, 0, 0, 0),
-       SND_SOC_DAPM_AIF_IN("PRI_MI2S_TX", "Primary MI2S Capture",
+       SND_SOC_DAPM_AIF_OUT("PRI_MI2S_TX", NULL,
                                                0, 0, 0, 0),
 
-       SND_SOC_DAPM_AIF_OUT("PRIMARY_TDM_RX_0", "Primary TDM0 Playback",
+       SND_SOC_DAPM_AIF_IN("PRIMARY_TDM_RX_0", NULL,
                             0, 0, 0, 0),
-       SND_SOC_DAPM_AIF_OUT("PRIMARY_TDM_RX_1", "Primary TDM1 Playback",
+       SND_SOC_DAPM_AIF_IN("PRIMARY_TDM_RX_1", NULL,
                             0, 0, 0, 0),
-       SND_SOC_DAPM_AIF_OUT("PRIMARY_TDM_RX_2", "Primary TDM2 Playback",
+       SND_SOC_DAPM_AIF_IN("PRIMARY_TDM_RX_2", NULL,
                             0, 0, 0, 0),
-       SND_SOC_DAPM_AIF_OUT("PRIMARY_TDM_RX_3", "Primary TDM3 Playback",
+       SND_SOC_DAPM_AIF_IN("PRIMARY_TDM_RX_3", NULL,
                             0, 0, 0, 0),
-       SND_SOC_DAPM_AIF_OUT("PRIMARY_TDM_RX_4", "Primary TDM4 Playback",
+       SND_SOC_DAPM_AIF_IN("PRIMARY_TDM_RX_4", NULL,
                             0, 0, 0, 0),
-       SND_SOC_DAPM_AIF_OUT("PRIMARY_TDM_RX_5", "Primary TDM5 Playback",
+       SND_SOC_DAPM_AIF_IN("PRIMARY_TDM_RX_5", NULL,
                             0, 0, 0, 0),
-       SND_SOC_DAPM_AIF_OUT("PRIMARY_TDM_RX_6", "Primary TDM6 Playback",
+       SND_SOC_DAPM_AIF_IN("PRIMARY_TDM_RX_6", NULL,
                             0, 0, 0, 0),
-       SND_SOC_DAPM_AIF_OUT("PRIMARY_TDM_RX_7", "Primary TDM7 Playback",
+       SND_SOC_DAPM_AIF_IN("PRIMARY_TDM_RX_7", NULL,
                             0, 0, 0, 0),
-       SND_SOC_DAPM_AIF_IN("PRIMARY_TDM_TX_0", "Primary TDM0 Capture",
+       SND_SOC_DAPM_AIF_OUT("PRIMARY_TDM_TX_0", NULL,
                                                0, 0, 0, 0),
-       SND_SOC_DAPM_AIF_IN("PRIMARY_TDM_TX_1", "Primary TDM1 Capture",
+       SND_SOC_DAPM_AIF_OUT("PRIMARY_TDM_TX_1", NULL,
                                                0, 0, 0, 0),
-       SND_SOC_DAPM_AIF_IN("PRIMARY_TDM_TX_2", "Primary TDM2 Capture",
+       SND_SOC_DAPM_AIF_OUT("PRIMARY_TDM_TX_2", NULL,
                                                0, 0, 0, 0),
-       SND_SOC_DAPM_AIF_IN("PRIMARY_TDM_TX_3", "Primary TDM3 Capture",
+       SND_SOC_DAPM_AIF_OUT("PRIMARY_TDM_TX_3", NULL,
                                                0, 0, 0, 0),
-       SND_SOC_DAPM_AIF_IN("PRIMARY_TDM_TX_4", "Primary TDM4 Capture",
+       SND_SOC_DAPM_AIF_OUT("PRIMARY_TDM_TX_4", NULL,
                                                0, 0, 0, 0),
-       SND_SOC_DAPM_AIF_IN("PRIMARY_TDM_TX_5", "Primary TDM5 Capture",
+       SND_SOC_DAPM_AIF_OUT("PRIMARY_TDM_TX_5", NULL,
                                                0, 0, 0, 0),
-       SND_SOC_DAPM_AIF_IN("PRIMARY_TDM_TX_6", "Primary TDM6 Capture",
+       SND_SOC_DAPM_AIF_OUT("PRIMARY_TDM_TX_6", NULL,
                                                0, 0, 0, 0),
-       SND_SOC_DAPM_AIF_IN("PRIMARY_TDM_TX_7", "Primary TDM7 Capture",
+       SND_SOC_DAPM_AIF_OUT("PRIMARY_TDM_TX_7", NULL,
                                                0, 0, 0, 0),
 
-       SND_SOC_DAPM_AIF_OUT("SEC_TDM_RX_0", "Secondary TDM0 Playback",
+       SND_SOC_DAPM_AIF_IN("SEC_TDM_RX_0", NULL,
                             0, 0, 0, 0),
-       SND_SOC_DAPM_AIF_OUT("SEC_TDM_RX_1", "Secondary TDM1 Playback",
+       SND_SOC_DAPM_AIF_IN("SEC_TDM_RX_1", NULL,
                             0, 0, 0, 0),
-       SND_SOC_DAPM_AIF_OUT("SEC_TDM_RX_2", "Secondary TDM2 Playback",
+       SND_SOC_DAPM_AIF_IN("SEC_TDM_RX_2", NULL,
                             0, 0, 0, 0),
-       SND_SOC_DAPM_AIF_OUT("SEC_TDM_RX_3", "Secondary TDM3 Playback",
+       SND_SOC_DAPM_AIF_IN("SEC_TDM_RX_3", NULL,
                             0, 0, 0, 0),
-       SND_SOC_DAPM_AIF_OUT("SEC_TDM_RX_4", "Secondary TDM4 Playback",
+       SND_SOC_DAPM_AIF_IN("SEC_TDM_RX_4", NULL,
                             0, 0, 0, 0),
-       SND_SOC_DAPM_AIF_OUT("SEC_TDM_RX_5", "Secondary TDM5 Playback",
+       SND_SOC_DAPM_AIF_IN("SEC_TDM_RX_5", NULL,
                             0, 0, 0, 0),
-       SND_SOC_DAPM_AIF_OUT("SEC_TDM_RX_6", "Secondary TDM6 Playback",
+       SND_SOC_DAPM_AIF_IN("SEC_TDM_RX_6", NULL,
                             0, 0, 0, 0),
-       SND_SOC_DAPM_AIF_OUT("SEC_TDM_RX_7", "Secondary TDM7 Playback",
+       SND_SOC_DAPM_AIF_IN("SEC_TDM_RX_7", NULL,
                             0, 0, 0, 0),
-       SND_SOC_DAPM_AIF_IN("SEC_TDM_TX_0", "Secondary TDM0 Capture",
+       SND_SOC_DAPM_AIF_OUT("SEC_TDM_TX_0", NULL,
                                                0, 0, 0, 0),
-       SND_SOC_DAPM_AIF_IN("SEC_TDM_TX_1", "Secondary TDM1 Capture",
+       SND_SOC_DAPM_AIF_OUT("SEC_TDM_TX_1", NULL,
                                                0, 0, 0, 0),
-       SND_SOC_DAPM_AIF_IN("SEC_TDM_TX_2", "Secondary TDM2 Capture",
+       SND_SOC_DAPM_AIF_OUT("SEC_TDM_TX_2", NULL,
                                                0, 0, 0, 0),
-       SND_SOC_DAPM_AIF_IN("SEC_TDM_TX_3", "Secondary TDM3 Capture",
+       SND_SOC_DAPM_AIF_OUT("SEC_TDM_TX_3", NULL,
                                                0, 0, 0, 0),
-       SND_SOC_DAPM_AIF_IN("SEC_TDM_TX_4", "Secondary TDM4 Capture",
+       SND_SOC_DAPM_AIF_OUT("SEC_TDM_TX_4", NULL,
                                                0, 0, 0, 0),
-       SND_SOC_DAPM_AIF_IN("SEC_TDM_TX_5", "Secondary TDM5 Capture",
+       SND_SOC_DAPM_AIF_OUT("SEC_TDM_TX_5", NULL,
                                                0, 0, 0, 0),
-       SND_SOC_DAPM_AIF_IN("SEC_TDM_TX_6", "Secondary TDM6 Capture",
+       SND_SOC_DAPM_AIF_OUT("SEC_TDM_TX_6", NULL,
                                                0, 0, 0, 0),
-       SND_SOC_DAPM_AIF_IN("SEC_TDM_TX_7", "Secondary TDM7 Capture",
+       SND_SOC_DAPM_AIF_OUT("SEC_TDM_TX_7", NULL,
                                                0, 0, 0, 0),
 
-       SND_SOC_DAPM_AIF_OUT("TERT_TDM_RX_0", "Tertiary TDM0 Playback",
+       SND_SOC_DAPM_AIF_IN("TERT_TDM_RX_0", NULL,
                             0, 0, 0, 0),
-       SND_SOC_DAPM_AIF_OUT("TERT_TDM_RX_1", "Tertiary TDM1 Playback",
+       SND_SOC_DAPM_AIF_IN("TERT_TDM_RX_1", NULL,
                             0, 0, 0, 0),
-       SND_SOC_DAPM_AIF_OUT("TERT_TDM_RX_2", "Tertiary TDM2 Playback",
+       SND_SOC_DAPM_AIF_IN("TERT_TDM_RX_2", NULL,
                             0, 0, 0, 0),
-       SND_SOC_DAPM_AIF_OUT("TERT_TDM_RX_3", "Tertiary TDM3 Playback",
+       SND_SOC_DAPM_AIF_IN("TERT_TDM_RX_3", NULL,
                             0, 0, 0, 0),
-       SND_SOC_DAPM_AIF_OUT("TERT_TDM_RX_4", "Tertiary TDM4 Playback",
+       SND_SOC_DAPM_AIF_IN("TERT_TDM_RX_4", NULL,
                             0, 0, 0, 0),
-       SND_SOC_DAPM_AIF_OUT("TERT_TDM_RX_5", "Tertiary TDM5 Playback",
+       SND_SOC_DAPM_AIF_IN("TERT_TDM_RX_5", NULL,
                             0, 0, 0, 0),
-       SND_SOC_DAPM_AIF_OUT("TERT_TDM_RX_6", "Tertiary TDM6 Playback",
+       SND_SOC_DAPM_AIF_IN("TERT_TDM_RX_6", NULL,
                             0, 0, 0, 0),
-       SND_SOC_DAPM_AIF_OUT("TERT_TDM_RX_7", "Tertiary TDM7 Playback",
+       SND_SOC_DAPM_AIF_IN("TERT_TDM_RX_7", NULL,
                             0, 0, 0, 0),
-       SND_SOC_DAPM_AIF_IN("TERT_TDM_TX_0", "Tertiary TDM0 Capture",
+       SND_SOC_DAPM_AIF_OUT("TERT_TDM_TX_0", NULL,
                                                0, 0, 0, 0),
-       SND_SOC_DAPM_AIF_IN("TERT_TDM_TX_1", "Tertiary TDM1 Capture",
+       SND_SOC_DAPM_AIF_OUT("TERT_TDM_TX_1", NULL,
                                                0, 0, 0, 0),
-       SND_SOC_DAPM_AIF_IN("TERT_TDM_TX_2", "Tertiary TDM2 Capture",
+       SND_SOC_DAPM_AIF_OUT("TERT_TDM_TX_2", NULL,
                                                0, 0, 0, 0),
-       SND_SOC_DAPM_AIF_IN("TERT_TDM_TX_3", "Tertiary TDM3 Capture",
+       SND_SOC_DAPM_AIF_OUT("TERT_TDM_TX_3", NULL,
                                                0, 0, 0, 0),
-       SND_SOC_DAPM_AIF_IN("TERT_TDM_TX_4", "Tertiary TDM4 Capture",
+       SND_SOC_DAPM_AIF_OUT("TERT_TDM_TX_4", NULL,
                                                0, 0, 0, 0),
-       SND_SOC_DAPM_AIF_IN("TERT_TDM_TX_5", "Tertiary TDM5 Capture",
+       SND_SOC_DAPM_AIF_OUT("TERT_TDM_TX_5", NULL,
                                                0, 0, 0, 0),
-       SND_SOC_DAPM_AIF_IN("TERT_TDM_TX_6", "Tertiary TDM6 Capture",
+       SND_SOC_DAPM_AIF_OUT("TERT_TDM_TX_6", NULL,
                                                0, 0, 0, 0),
-       SND_SOC_DAPM_AIF_IN("TERT_TDM_TX_7", "Tertiary TDM7 Capture",
+       SND_SOC_DAPM_AIF_OUT("TERT_TDM_TX_7", NULL,
                                                0, 0, 0, 0),
 
-       SND_SOC_DAPM_AIF_OUT("QUAT_TDM_RX_0", "Quaternary TDM0 Playback",
+       SND_SOC_DAPM_AIF_IN("QUAT_TDM_RX_0", NULL,
                             0, 0, 0, 0),
-       SND_SOC_DAPM_AIF_OUT("QUAT_TDM_RX_1", "Quaternary TDM1 Playback",
+       SND_SOC_DAPM_AIF_IN("QUAT_TDM_RX_1", NULL,
                             0, 0, 0, 0),
-       SND_SOC_DAPM_AIF_OUT("QUAT_TDM_RX_2", "Quaternary TDM2 Playback",
+       SND_SOC_DAPM_AIF_IN("QUAT_TDM_RX_2", NULL,
                             0, 0, 0, 0),
-       SND_SOC_DAPM_AIF_OUT("QUAT_TDM_RX_3", "Quaternary TDM3 Playback",
+       SND_SOC_DAPM_AIF_IN("QUAT_TDM_RX_3", NULL,
                             0, 0, 0, 0),
-       SND_SOC_DAPM_AIF_OUT("QUAT_TDM_RX_4", "Quaternary TDM4 Playback",
+       SND_SOC_DAPM_AIF_IN("QUAT_TDM_RX_4", NULL,
                             0, 0, 0, 0),
-       SND_SOC_DAPM_AIF_OUT("QUAT_TDM_RX_5", "Quaternary TDM5 Playback",
+       SND_SOC_DAPM_AIF_IN("QUAT_TDM_RX_5", NULL,
                             0, 0, 0, 0),
-       SND_SOC_DAPM_AIF_OUT("QUAT_TDM_RX_6", "Quaternary TDM6 Playback",
+       SND_SOC_DAPM_AIF_IN("QUAT_TDM_RX_6", NULL,
                             0, 0, 0, 0),
-       SND_SOC_DAPM_AIF_OUT("QUAT_TDM_RX_7", "Quaternary TDM7 Playback",
+       SND_SOC_DAPM_AIF_IN("QUAT_TDM_RX_7", NULL,
                             0, 0, 0, 0),
-       SND_SOC_DAPM_AIF_IN("QUAT_TDM_TX_0", "Quaternary TDM0 Capture",
+       SND_SOC_DAPM_AIF_OUT("QUAT_TDM_TX_0", NULL,
                                                0, 0, 0, 0),
-       SND_SOC_DAPM_AIF_IN("QUAT_TDM_TX_1", "Quaternary TDM1 Capture",
+       SND_SOC_DAPM_AIF_OUT("QUAT_TDM_TX_1", NULL,
                                                0, 0, 0, 0),
-       SND_SOC_DAPM_AIF_IN("QUAT_TDM_TX_2", "Quaternary TDM2 Capture",
+       SND_SOC_DAPM_AIF_OUT("QUAT_TDM_TX_2", NULL,
                                                0, 0, 0, 0),
-       SND_SOC_DAPM_AIF_IN("QUAT_TDM_TX_3", "Quaternary TDM3 Capture",
+       SND_SOC_DAPM_AIF_OUT("QUAT_TDM_TX_3", NULL,
                                                0, 0, 0, 0),
-       SND_SOC_DAPM_AIF_IN("QUAT_TDM_TX_4", "Quaternary TDM4 Capture",
+       SND_SOC_DAPM_AIF_OUT("QUAT_TDM_TX_4", NULL,
                                                0, 0, 0, 0),
-       SND_SOC_DAPM_AIF_IN("QUAT_TDM_TX_5", "Quaternary TDM5 Capture",
+       SND_SOC_DAPM_AIF_OUT("QUAT_TDM_TX_5", NULL,
                                                0, 0, 0, 0),
-       SND_SOC_DAPM_AIF_IN("QUAT_TDM_TX_6", "Quaternary TDM6 Capture",
+       SND_SOC_DAPM_AIF_OUT("QUAT_TDM_TX_6", NULL,
                                                0, 0, 0, 0),
-       SND_SOC_DAPM_AIF_IN("QUAT_TDM_TX_7", "Quaternary TDM7 Capture",
+       SND_SOC_DAPM_AIF_OUT("QUAT_TDM_TX_7", NULL,
                                                0, 0, 0, 0),
 
-       SND_SOC_DAPM_AIF_OUT("QUIN_TDM_RX_0", "Quinary TDM0 Playback",
+       SND_SOC_DAPM_AIF_IN("QUIN_TDM_RX_0", NULL,
                             0, 0, 0, 0),
-       SND_SOC_DAPM_AIF_OUT("QUIN_TDM_RX_1", "Quinary TDM1 Playback",
+       SND_SOC_DAPM_AIF_IN("QUIN_TDM_RX_1", NULL,
                             0, 0, 0, 0),
-       SND_SOC_DAPM_AIF_OUT("QUIN_TDM_RX_2", "Quinary TDM2 Playback",
+       SND_SOC_DAPM_AIF_IN("QUIN_TDM_RX_2", NULL,
                             0, 0, 0, 0),
-       SND_SOC_DAPM_AIF_OUT("QUIN_TDM_RX_3", "Quinary TDM3 Playback",
+       SND_SOC_DAPM_AIF_IN("QUIN_TDM_RX_3", NULL,
                             0, 0, 0, 0),
-       SND_SOC_DAPM_AIF_OUT("QUIN_TDM_RX_4", "Quinary TDM4 Playback",
+       SND_SOC_DAPM_AIF_IN("QUIN_TDM_RX_4", NULL,
                             0, 0, 0, 0),
-       SND_SOC_DAPM_AIF_OUT("QUIN_TDM_RX_5", "Quinary TDM5 Playback",
+       SND_SOC_DAPM_AIF_IN("QUIN_TDM_RX_5", NULL,
                             0, 0, 0, 0),
-       SND_SOC_DAPM_AIF_OUT("QUIN_TDM_RX_6", "Quinary TDM6 Playback",
+       SND_SOC_DAPM_AIF_IN("QUIN_TDM_RX_6", NULL,
                             0, 0, 0, 0),
-       SND_SOC_DAPM_AIF_OUT("QUIN_TDM_RX_7", "Quinary TDM7 Playback",
+       SND_SOC_DAPM_AIF_IN("QUIN_TDM_RX_7", NULL,
                             0, 0, 0, 0),
-       SND_SOC_DAPM_AIF_IN("QUIN_TDM_TX_0", "Quinary TDM0 Capture",
+       SND_SOC_DAPM_AIF_OUT("QUIN_TDM_TX_0", NULL,
                                                0, 0, 0, 0),
-       SND_SOC_DAPM_AIF_IN("QUIN_TDM_TX_1", "Quinary TDM1 Capture",
+       SND_SOC_DAPM_AIF_OUT("QUIN_TDM_TX_1", NULL,
                                                0, 0, 0, 0),
-       SND_SOC_DAPM_AIF_IN("QUIN_TDM_TX_2", "Quinary TDM2 Capture",
+       SND_SOC_DAPM_AIF_OUT("QUIN_TDM_TX_2", NULL,
                                                0, 0, 0, 0),
-       SND_SOC_DAPM_AIF_IN("QUIN_TDM_TX_3", "Quinary TDM3 Capture",
+       SND_SOC_DAPM_AIF_OUT("QUIN_TDM_TX_3", NULL,
                                                0, 0, 0, 0),
-       SND_SOC_DAPM_AIF_IN("QUIN_TDM_TX_4", "Quinary TDM4 Capture",
+       SND_SOC_DAPM_AIF_OUT("QUIN_TDM_TX_4", NULL,
                                                0, 0, 0, 0),
-       SND_SOC_DAPM_AIF_IN("QUIN_TDM_TX_5", "Quinary TDM5 Capture",
+       SND_SOC_DAPM_AIF_OUT("QUIN_TDM_TX_5", NULL,
                                                0, 0, 0, 0),
-       SND_SOC_DAPM_AIF_IN("QUIN_TDM_TX_6", "Quinary TDM6 Capture",
+       SND_SOC_DAPM_AIF_OUT("QUIN_TDM_TX_6", NULL,
                                                0, 0, 0, 0),
-       SND_SOC_DAPM_AIF_IN("QUIN_TDM_TX_7", "Quinary TDM7 Capture",
+       SND_SOC_DAPM_AIF_OUT("QUIN_TDM_TX_7", NULL,
                                                0, 0, 0, 0),
 };
 
index 000775b..829b5e9 100644 (file)
 #define AFE_PORT_I2S_SD1               0x2
 #define AFE_PORT_I2S_SD2               0x3
 #define AFE_PORT_I2S_SD3               0x4
-#define AFE_PORT_I2S_SD0_MASK          BIT(0x1)
-#define AFE_PORT_I2S_SD1_MASK          BIT(0x2)
-#define AFE_PORT_I2S_SD2_MASK          BIT(0x3)
-#define AFE_PORT_I2S_SD3_MASK          BIT(0x4)
-#define AFE_PORT_I2S_SD0_1_MASK                GENMASK(2, 1)
-#define AFE_PORT_I2S_SD2_3_MASK                GENMASK(4, 3)
-#define AFE_PORT_I2S_SD0_1_2_MASK      GENMASK(3, 1)
-#define AFE_PORT_I2S_SD0_1_2_3_MASK    GENMASK(4, 1)
+#define AFE_PORT_I2S_SD0_MASK          BIT(0x0)
+#define AFE_PORT_I2S_SD1_MASK          BIT(0x1)
+#define AFE_PORT_I2S_SD2_MASK          BIT(0x2)
+#define AFE_PORT_I2S_SD3_MASK          BIT(0x3)
+#define AFE_PORT_I2S_SD0_1_MASK                GENMASK(1, 0)
+#define AFE_PORT_I2S_SD2_3_MASK                GENMASK(3, 2)
+#define AFE_PORT_I2S_SD0_1_2_MASK      GENMASK(2, 0)
+#define AFE_PORT_I2S_SD0_1_2_3_MASK    GENMASK(3, 0)
 #define AFE_PORT_I2S_QUAD01            0x5
 #define AFE_PORT_I2S_QUAD23            0x6
 #define AFE_PORT_I2S_6CHS              0x7
index a16c71c..86115de 100644 (file)
@@ -122,7 +122,6 @@ static struct snd_pcm_hardware q6asm_dai_hardware_playback = {
                        .rate_max =     48000,                          \
                },                                                      \
                .name = "MultiMedia"#num,                               \
-               .probe = fe_dai_probe,                                  \
                .id = MSM_FRONTEND_DAI_MULTIMEDIA##num,                 \
        }
 
@@ -511,38 +510,6 @@ static void q6asm_dai_pcm_free(struct snd_pcm *pcm)
        }
 }
 
-static const struct snd_soc_dapm_route afe_pcm_routes[] = {
-       {"MM_DL1",  NULL, "MultiMedia1 Playback" },
-       {"MM_DL2",  NULL, "MultiMedia2 Playback" },
-       {"MM_DL3",  NULL, "MultiMedia3 Playback" },
-       {"MM_DL4",  NULL, "MultiMedia4 Playback" },
-       {"MM_DL5",  NULL, "MultiMedia5 Playback" },
-       {"MM_DL6",  NULL, "MultiMedia6 Playback" },
-       {"MM_DL7",  NULL, "MultiMedia7 Playback" },
-       {"MM_DL7",  NULL, "MultiMedia8 Playback" },
-       {"MultiMedia1 Capture", NULL, "MM_UL1"},
-       {"MultiMedia2 Capture", NULL, "MM_UL2"},
-       {"MultiMedia3 Capture", NULL, "MM_UL3"},
-       {"MultiMedia4 Capture", NULL, "MM_UL4"},
-       {"MultiMedia5 Capture", NULL, "MM_UL5"},
-       {"MultiMedia6 Capture", NULL, "MM_UL6"},
-       {"MultiMedia7 Capture", NULL, "MM_UL7"},
-       {"MultiMedia8 Capture", NULL, "MM_UL8"},
-
-};
-
-static int fe_dai_probe(struct snd_soc_dai *dai)
-{
-       struct snd_soc_dapm_context *dapm;
-
-       dapm = snd_soc_component_get_dapm(dai->component);
-       snd_soc_dapm_add_routes(dapm, afe_pcm_routes,
-                               ARRAY_SIZE(afe_pcm_routes));
-
-       return 0;
-}
-
-
 static const struct snd_soc_component_driver q6asm_fe_dai_component = {
        .name           = DRV_NAME,
        .ops            = &q6asm_dai_ops,
index c6b5157..d61b840 100644 (file)
@@ -909,6 +909,25 @@ static const struct snd_soc_dapm_route intercon[] = {
        {"MM_UL6", NULL, "MultiMedia6 Mixer"},
        {"MM_UL7", NULL, "MultiMedia7 Mixer"},
        {"MM_UL8", NULL, "MultiMedia8 Mixer"},
+
+       {"MM_DL1",  NULL, "MultiMedia1 Playback" },
+       {"MM_DL2",  NULL, "MultiMedia2 Playback" },
+       {"MM_DL3",  NULL, "MultiMedia3 Playback" },
+       {"MM_DL4",  NULL, "MultiMedia4 Playback" },
+       {"MM_DL5",  NULL, "MultiMedia5 Playback" },
+       {"MM_DL6",  NULL, "MultiMedia6 Playback" },
+       {"MM_DL7",  NULL, "MultiMedia7 Playback" },
+       {"MM_DL8",  NULL, "MultiMedia8 Playback" },
+
+       {"MultiMedia1 Capture", NULL, "MM_UL1"},
+       {"MultiMedia2 Capture", NULL, "MM_UL2"},
+       {"MultiMedia3 Capture", NULL, "MM_UL3"},
+       {"MultiMedia4 Capture", NULL, "MM_UL4"},
+       {"MultiMedia5 Capture", NULL, "MM_UL5"},
+       {"MultiMedia6 Capture", NULL, "MM_UL6"},
+       {"MultiMedia7 Capture", NULL, "MM_UL7"},
+       {"MultiMedia8 Capture", NULL, "MM_UL8"},
+
 };
 
 static int routing_hw_params(struct snd_pcm_substream *substream,
index 9e7b5fa..4ac78d7 100644 (file)
@@ -33,6 +33,7 @@ static const struct snd_pcm_hardware snd_rockchip_hardware = {
 
 static const struct snd_dmaengine_pcm_config rk_dmaengine_pcm_config = {
        .pcm_hardware = &snd_rockchip_hardware,
+       .prepare_slave_config = snd_dmaengine_pcm_prepare_slave_config,
        .prealloc_buffer_size = 32 * 1024,
 };
 
index fcb4df2..6ec78f3 100644 (file)
@@ -306,7 +306,7 @@ static int rsnd_ssi_master_clk_start(struct rsnd_mod *mod,
        if (rsnd_ssi_is_multi_slave(mod, io))
                return 0;
 
-       if (ssi->rate) {
+       if (ssi->usrcnt > 1) {
                if (ssi->rate != rate) {
                        dev_err(dev, "SSI parent/child should use same rate\n");
                        return -EINVAL;
index b8e72b5..4fb29f0 100644 (file)
@@ -10,11 +10,17 @@ struct snd_soc_acpi_mach *
 snd_soc_acpi_find_machine(struct snd_soc_acpi_mach *machines)
 {
        struct snd_soc_acpi_mach *mach;
+       struct snd_soc_acpi_mach *mach_alt;
 
        for (mach = machines; mach->id[0]; mach++) {
                if (acpi_dev_present(mach->id, NULL, -1)) {
-                       if (mach->machine_quirk)
-                               mach = mach->machine_quirk(mach);
+                       if (mach->machine_quirk) {
+                               mach_alt = mach->machine_quirk(mach);
+                               if (!mach_alt)
+                                       continue; /* not full match, ignore */
+                               mach = mach_alt;
+                       }
+
                        return mach;
                }
        }
index 6ddcf12..b29d0f6 100644 (file)
@@ -2131,6 +2131,7 @@ static int snd_soc_instantiate_card(struct snd_soc_card *card)
        }
 
        card->instantiated = 1;
+       dapm_mark_endpoints_dirty(card);
        snd_soc_dapm_sync(&card->dapm);
        mutex_unlock(&card->mutex);
        mutex_unlock(&client_mutex);
index ea05cc9..211589b 100644 (file)
@@ -390,7 +390,7 @@ static int stm32_sai_add_mclk_provider(struct stm32_sai_sub_data *sai)
        char *mclk_name, *p, *s = (char *)pname;
        int ret, i = 0;
 
-       mclk = devm_kzalloc(dev, sizeof(mclk), GFP_KERNEL);
+       mclk = devm_kzalloc(dev, sizeof(*mclk), GFP_KERNEL);
        if (!mclk)
                return -ENOMEM;
 
index 66aad0d..8134c3c 100644 (file)
@@ -31,7 +31,7 @@ config SND_SUN8I_CODEC_ANALOG
 config SND_SUN50I_CODEC_ANALOG
        tristate "Allwinner sun50i Codec Analog Controls Support"
        depends on (ARM64 && ARCH_SUNXI) || COMPILE_TEST
-       select SND_SUNXI_ADDA_PR_REGMAP
+       select SND_SUN8I_ADDA_PR_REGMAP
        help
          Say Y or M if you want to add support for the analog controls for
          the codec embedded in Allwinner A64 SoC.
index 522a72f..92c5de0 100644 (file)
@@ -481,7 +481,11 @@ static const struct snd_soc_dapm_route sun8i_codec_dapm_routes[] = {
        { "Right Digital DAC Mixer", "AIF1 Slot 0 Digital DAC Playback Switch",
          "AIF1 Slot 0 Right"},
 
-       /* ADC routes */
+       /* ADC Routes */
+       { "AIF1 Slot 0 Right ADC", NULL, "ADC" },
+       { "AIF1 Slot 0 Left ADC", NULL, "ADC" },
+
+       /* ADC Mixer Routes */
        { "Left Digital ADC Mixer", "AIF1 Data Digital ADC Capture Switch",
          "AIF1 Slot 0 Left ADC" },
        { "Right Digital ADC Mixer", "AIF1 Data Digital ADC Capture Switch",
@@ -605,16 +609,10 @@ err_pm_disable:
 
 static int sun8i_codec_remove(struct platform_device *pdev)
 {
-       struct snd_soc_card *card = platform_get_drvdata(pdev);
-       struct sun8i_codec *scodec = snd_soc_card_get_drvdata(card);
-
        pm_runtime_disable(&pdev->dev);
        if (!pm_runtime_status_suspended(&pdev->dev))
                sun8i_codec_runtime_suspend(&pdev->dev);
 
-       clk_disable_unprepare(scodec->clk_module);
-       clk_disable_unprepare(scodec->clk_bus);
-
        return 0;
 }
 
index e73c962..079063d 100644 (file)
@@ -1146,10 +1146,8 @@ static int snd_cs4231_playback_open(struct snd_pcm_substream *substream)
        runtime->hw = snd_cs4231_playback;
 
        err = snd_cs4231_open(chip, CS4231_MODE_PLAY);
-       if (err < 0) {
-               snd_free_pages(runtime->dma_area, runtime->dma_bytes);
+       if (err < 0)
                return err;
-       }
        chip->playback_substream = substream;
        chip->p_periods_sent = 0;
        snd_pcm_set_sync(substream);
@@ -1167,10 +1165,8 @@ static int snd_cs4231_capture_open(struct snd_pcm_substream *substream)
        runtime->hw = snd_cs4231_capture;
 
        err = snd_cs4231_open(chip, CS4231_MODE_RECORD);
-       if (err < 0) {
-               snd_free_pages(runtime->dma_area, runtime->dma_bytes);
+       if (err < 0)
                return err;
-       }
        chip->capture_substream = substream;
        chip->c_periods_sent = 0;
        snd_pcm_set_sync(substream);
index 849953e..37fc044 100644 (file)
@@ -3382,5 +3382,15 @@ AU0828_DEVICE(0x2040, 0x7270, "Hauppauge", "HVR-950Q"),
                .ifnum = QUIRK_NO_INTERFACE
        }
 },
+/* Dell WD19 Dock */
+{
+       USB_DEVICE(0x0bda, 0x402e),
+       .driver_info = (unsigned long) & (const struct snd_usb_audio_quirk) {
+               .vendor_name = "Dell",
+               .product_name = "WD19 Dock",
+               .profile_name = "Dell-WD15-Dock",
+               .ifnum = QUIRK_NO_INTERFACE
+       }
+},
 
 #undef USB_DEVICE_VENDOR_SPEC
index 89a048c..28c4a50 100644 (file)
 #define X86_FEATURE_LA57               (16*32+16) /* 5-level page tables */
 #define X86_FEATURE_RDPID              (16*32+22) /* RDPID instruction */
 #define X86_FEATURE_CLDEMOTE           (16*32+25) /* CLDEMOTE instruction */
+#define X86_FEATURE_MOVDIRI            (16*32+27) /* MOVDIRI instruction */
+#define X86_FEATURE_MOVDIR64B          (16*32+28) /* MOVDIR64B instruction */
 
 /* AMD-defined CPU features, CPUID level 0x80000007 (EBX), word 17 */
 #define X86_FEATURE_OVERFLOW_RECOV     (17*32+ 0) /* MCA overflow recovery support */
index edbe815..d07ccf8 100644 (file)
@@ -137,4 +137,10 @@ EXAMPLES
 
 SEE ALSO
 ========
-       **bpftool**\ (8), **bpftool-prog**\ (8), **bpftool-map**\ (8)
+       **bpf**\ (2),
+       **bpf-helpers**\ (7),
+       **bpftool**\ (8),
+       **bpftool-prog**\ (8),
+       **bpftool-map**\ (8),
+       **bpftool-net**\ (8),
+       **bpftool-perf**\ (8)
index f55a2da..7bb787c 100644 (file)
@@ -171,4 +171,10 @@ The following three commands are equivalent:
 
 SEE ALSO
 ========
-       **bpftool**\ (8), **bpftool-prog**\ (8), **bpftool-cgroup**\ (8)
+       **bpf**\ (2),
+       **bpf-helpers**\ (7),
+       **bpftool**\ (8),
+       **bpftool-prog**\ (8),
+       **bpftool-cgroup**\ (8),
+       **bpftool-net**\ (8),
+       **bpftool-perf**\ (8)
index 408ec30..ed87c9b 100644 (file)
@@ -136,4 +136,10 @@ EXAMPLES
 
 SEE ALSO
 ========
-       **bpftool**\ (8), **bpftool-prog**\ (8), **bpftool-map**\ (8)
+       **bpf**\ (2),
+       **bpf-helpers**\ (7),
+       **bpftool**\ (8),
+       **bpftool-prog**\ (8),
+       **bpftool-map**\ (8),
+       **bpftool-cgroup**\ (8),
+       **bpftool-perf**\ (8)
index e3eb0ea..f4c5e55 100644 (file)
@@ -78,4 +78,10 @@ EXAMPLES
 
 SEE ALSO
 ========
-       **bpftool**\ (8), **bpftool-prog**\ (8), **bpftool-map**\ (8)
+       **bpf**\ (2),
+       **bpf-helpers**\ (7),
+       **bpftool**\ (8),
+       **bpftool-prog**\ (8),
+       **bpftool-map**\ (8),
+       **bpftool-cgroup**\ (8),
+       **bpftool-net**\ (8)
index ac4e904..ecf6188 100644 (file)
@@ -124,7 +124,8 @@ OPTIONS
                  Generate human-readable JSON output. Implies **-j**.
 
        -f, --bpffs
-                 Show file names of pinned programs.
+                 When showing BPF programs, show file names of pinned
+                 programs.
 
 EXAMPLES
 ========
@@ -206,4 +207,10 @@ EXAMPLES
 
 SEE ALSO
 ========
-       **bpftool**\ (8), **bpftool-map**\ (8), **bpftool-cgroup**\ (8)
+       **bpf**\ (2),
+       **bpf-helpers**\ (7),
+       **bpftool**\ (8),
+       **bpftool-map**\ (8),
+       **bpftool-cgroup**\ (8),
+       **bpftool-net**\ (8),
+       **bpftool-perf**\ (8)
index 04cd4f9..129b7a9 100644 (file)
@@ -63,5 +63,10 @@ OPTIONS
 
 SEE ALSO
 ========
-       **bpftool-map**\ (8), **bpftool-prog**\ (8), **bpftool-cgroup**\ (8)
-        **bpftool-perf**\ (8), **bpftool-net**\ (8)
+       **bpf**\ (2),
+       **bpf-helpers**\ (7),
+       **bpftool-prog**\ (8),
+       **bpftool-map**\ (8),
+       **bpftool-cgroup**\ (8),
+       **bpftool-net**\ (8),
+       **bpftool-perf**\ (8)
index 25af853..70fd48d 100644 (file)
@@ -130,16 +130,17 @@ static int mnt_bpffs(const char *target, char *buff, size_t bufflen)
        return 0;
 }
 
-int open_obj_pinned(char *path)
+int open_obj_pinned(char *path, bool quiet)
 {
        int fd;
 
        fd = bpf_obj_get(path);
        if (fd < 0) {
-               p_err("bpf obj get (%s): %s", path,
-                     errno == EACCES && !is_bpffs(dirname(path)) ?
-                   "directory not in bpf file system (bpffs)" :
-                   strerror(errno));
+               if (!quiet)
+                       p_err("bpf obj get (%s): %s", path,
+                             errno == EACCES && !is_bpffs(dirname(path)) ?
+                           "directory not in bpf file system (bpffs)" :
+                           strerror(errno));
                return -1;
        }
 
@@ -151,7 +152,7 @@ int open_obj_pinned_any(char *path, enum bpf_obj_type exp_type)
        enum bpf_obj_type type;
        int fd;
 
-       fd = open_obj_pinned(path);
+       fd = open_obj_pinned(path, false);
        if (fd < 0)
                return -1;
 
@@ -304,7 +305,7 @@ char *get_fdinfo(int fd, const char *key)
                return NULL;
        }
 
-       while ((n = getline(&line, &line_n, fdi))) {
+       while ((n = getline(&line, &line_n, fdi)) > 0) {
                char *value;
                int len;
 
@@ -384,7 +385,7 @@ int build_pinned_obj_table(struct pinned_obj_table *tab,
                while ((ftse = fts_read(fts))) {
                        if (!(ftse->fts_info & FTS_F))
                                continue;
-                       fd = open_obj_pinned(ftse->fts_path);
+                       fd = open_obj_pinned(ftse->fts_path, true);
                        if (fd < 0)
                                continue;
 
index 28322ac..a8bf1e2 100644 (file)
@@ -127,7 +127,7 @@ int cmd_select(const struct cmd *cmds, int argc, char **argv,
 int get_fd_type(int fd);
 const char *get_fd_type_name(enum bpf_obj_type type);
 char *get_fdinfo(int fd, const char *key);
-int open_obj_pinned(char *path);
+int open_obj_pinned(char *path, bool quiet);
 int open_obj_pinned_any(char *path, enum bpf_obj_type exp_type);
 int do_pin_any(int argc, char **argv, int (*get_fd_by_id)(__u32));
 int do_pin_fd(int fd, const char *name);
index 5302ee2..ccee180 100644 (file)
@@ -357,10 +357,9 @@ static void print_prog_plain(struct bpf_prog_info *info, int fd)
        if (!hash_empty(prog_table.table)) {
                struct pinned_obj *obj;
 
-               printf("\n");
                hash_for_each_possible(prog_table.table, obj, hash, info->id) {
                        if (obj->id == info->id)
-                               printf("\tpinned %s\n", obj->path);
+                               printf("\n\tpinned %s", obj->path);
                }
        }
 
@@ -845,6 +844,7 @@ static int do_load(int argc, char **argv)
                        }
                        NEXT_ARG();
                } else if (is_prefix(*argv, "map")) {
+                       void *new_map_replace;
                        char *endptr, *name;
                        int fd;
 
@@ -878,12 +878,15 @@ static int do_load(int argc, char **argv)
                        if (fd < 0)
                                goto err_free_reuse_maps;
 
-                       map_replace = reallocarray(map_replace, old_map_fds + 1,
-                                                  sizeof(*map_replace));
-                       if (!map_replace) {
+                       new_map_replace = reallocarray(map_replace,
+                                                      old_map_fds + 1,
+                                                      sizeof(*map_replace));
+                       if (!new_map_replace) {
                                p_err("mem alloc failed");
                                goto err_free_reuse_maps;
                        }
+                       map_replace = new_map_replace;
+
                        map_replace[old_map_fds].idx = idx;
                        map_replace[old_map_fds].name = name;
                        map_replace[old_map_fds].fd = fd;
index f216b2f..d74bb94 100644 (file)
@@ -33,6 +33,7 @@ FEATURE_TESTS_BASIC :=                  \
         dwarf_getlocations              \
         fortify-source                  \
         sync-compare-and-swap           \
+        get_current_dir_name            \
         glibc                           \
         gtk2                            \
         gtk2-infobar                    \
index 0516259..304b984 100644 (file)
@@ -7,6 +7,7 @@ FILES=                                          \
          test-dwarf_getlocations.bin            \
          test-fortify-source.bin                \
          test-sync-compare-and-swap.bin         \
+         test-get_current_dir_name.bin          \
          test-glibc.bin                         \
          test-gtk2.bin                          \
          test-gtk2-infobar.bin                  \
@@ -101,6 +102,9 @@ $(OUTPUT)test-bionic.bin:
 $(OUTPUT)test-libelf.bin:
        $(BUILD) -lelf
 
+$(OUTPUT)test-get_current_dir_name.bin:
+       $(BUILD)
+
 $(OUTPUT)test-glibc.bin:
        $(BUILD)
 
index 8dc20a6..56722bf 100644 (file)
 # include "test-libelf-mmap.c"
 #undef main
 
+#define main main_test_get_current_dir_name
+# include "test-get_current_dir_name.c"
+#undef main
+
 #define main main_test_glibc
 # include "test-glibc.c"
 #undef main
@@ -174,6 +178,7 @@ int main(int argc, char *argv[])
        main_test_hello();
        main_test_libelf();
        main_test_libelf_mmap();
+       main_test_get_current_dir_name();
        main_test_glibc();
        main_test_dwarf();
        main_test_dwarf_getlocations();
diff --git a/tools/build/feature/test-get_current_dir_name.c b/tools/build/feature/test-get_current_dir_name.c
new file mode 100644 (file)
index 0000000..573000f
--- /dev/null
@@ -0,0 +1,10 @@
+// SPDX-License-Identifier: GPL-2.0
+#define _GNU_SOURCE
+#include <unistd.h>
+#include <stdlib.h>
+
+int main(void)
+{
+       free(get_current_dir_name());
+       return 0;
+}
index 0406517..cdc9f4c 100644 (file)
@@ -79,6 +79,8 @@
 #define TIOCGPTLCK     _IOR('T', 0x39, int) /* Get Pty lock state */
 #define TIOCGEXCL      _IOR('T', 0x40, int) /* Get exclusive mode state */
 #define TIOCGPTPEER    _IO('T', 0x41) /* Safely open the slave */
+#define TIOCGISO7816   _IOR('T', 0x42, struct serial_iso7816)
+#define TIOCSISO7816   _IOWR('T', 0x43, struct serial_iso7816)
 
 #define FIONCLEX       0x5450
 #define FIOCLEX                0x5451
index 7f5634c..a4446f4 100644 (file)
@@ -529,6 +529,28 @@ typedef struct drm_i915_irq_wait {
  */
 #define I915_PARAM_CS_TIMESTAMP_FREQUENCY 51
 
+/*
+ * Once upon a time we supposed that writes through the GGTT would be
+ * immediately in physical memory (once flushed out of the CPU path). However,
+ * on a few different processors and chipsets, this is not necessarily the case
+ * as the writes appear to be buffered internally. Thus a read of the backing
+ * storage (physical memory) via a different path (with different physical tags
+ * to the indirect write via the GGTT) will see stale values from before
+ * the GGTT write. Inside the kernel, we can for the most part keep track of
+ * the different read/write domains in use (e.g. set-domain), but the assumption
+ * of coherency is baked into the ABI, hence reporting its true state in this
+ * parameter.
+ *
+ * Reports true when writes via mmap_gtt are immediately visible following an
+ * lfence to flush the WCB.
+ *
+ * Reports false when writes via mmap_gtt are indeterminately delayed in an in
+ * internal buffer and are _not_ immediately visible to third parties accessing
+ * directly via mmap_cpu/mmap_wc. Use of mmap_gtt as part of an IPC
+ * communications channel when reporting false is strongly disadvised.
+ */
+#define I915_PARAM_MMAP_GTT_COHERENT   52
+
 typedef struct drm_i915_getparam {
        __s32 param;
        /*
diff --git a/tools/include/uapi/linux/pkt_cls.h b/tools/include/uapi/linux/pkt_cls.h
new file mode 100644 (file)
index 0000000..401d0c1
--- /dev/null
@@ -0,0 +1,612 @@
+/* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */
+#ifndef __LINUX_PKT_CLS_H
+#define __LINUX_PKT_CLS_H
+
+#include <linux/types.h>
+#include <linux/pkt_sched.h>
+
+#define TC_COOKIE_MAX_SIZE 16
+
+/* Action attributes */
+enum {
+       TCA_ACT_UNSPEC,
+       TCA_ACT_KIND,
+       TCA_ACT_OPTIONS,
+       TCA_ACT_INDEX,
+       TCA_ACT_STATS,
+       TCA_ACT_PAD,
+       TCA_ACT_COOKIE,
+       __TCA_ACT_MAX
+};
+
+#define TCA_ACT_MAX __TCA_ACT_MAX
+#define TCA_OLD_COMPAT (TCA_ACT_MAX+1)
+#define TCA_ACT_MAX_PRIO 32
+#define TCA_ACT_BIND   1
+#define TCA_ACT_NOBIND 0
+#define TCA_ACT_UNBIND 1
+#define TCA_ACT_NOUNBIND       0
+#define TCA_ACT_REPLACE                1
+#define TCA_ACT_NOREPLACE      0
+
+#define TC_ACT_UNSPEC  (-1)
+#define TC_ACT_OK              0
+#define TC_ACT_RECLASSIFY      1
+#define TC_ACT_SHOT            2
+#define TC_ACT_PIPE            3
+#define TC_ACT_STOLEN          4
+#define TC_ACT_QUEUED          5
+#define TC_ACT_REPEAT          6
+#define TC_ACT_REDIRECT                7
+#define TC_ACT_TRAP            8 /* For hw path, this means "trap to cpu"
+                                  * and don't further process the frame
+                                  * in hardware. For sw path, this is
+                                  * equivalent of TC_ACT_STOLEN - drop
+                                  * the skb and act like everything
+                                  * is alright.
+                                  */
+#define TC_ACT_VALUE_MAX       TC_ACT_TRAP
+
+/* There is a special kind of actions called "extended actions",
+ * which need a value parameter. These have a local opcode located in
+ * the highest nibble, starting from 1. The rest of the bits
+ * are used to carry the value. These two parts together make
+ * a combined opcode.
+ */
+#define __TC_ACT_EXT_SHIFT 28
+#define __TC_ACT_EXT(local) ((local) << __TC_ACT_EXT_SHIFT)
+#define TC_ACT_EXT_VAL_MASK ((1 << __TC_ACT_EXT_SHIFT) - 1)
+#define TC_ACT_EXT_OPCODE(combined) ((combined) & (~TC_ACT_EXT_VAL_MASK))
+#define TC_ACT_EXT_CMP(combined, opcode) (TC_ACT_EXT_OPCODE(combined) == opcode)
+
+#define TC_ACT_JUMP __TC_ACT_EXT(1)
+#define TC_ACT_GOTO_CHAIN __TC_ACT_EXT(2)
+#define TC_ACT_EXT_OPCODE_MAX  TC_ACT_GOTO_CHAIN
+
+/* Action type identifiers*/
+enum {
+       TCA_ID_UNSPEC=0,
+       TCA_ID_POLICE=1,
+       /* other actions go here */
+       __TCA_ID_MAX=255
+};
+
+#define TCA_ID_MAX __TCA_ID_MAX
+
+struct tc_police {
+       __u32                   index;
+       int                     action;
+#define TC_POLICE_UNSPEC       TC_ACT_UNSPEC
+#define TC_POLICE_OK           TC_ACT_OK
+#define TC_POLICE_RECLASSIFY   TC_ACT_RECLASSIFY
+#define TC_POLICE_SHOT         TC_ACT_SHOT
+#define TC_POLICE_PIPE         TC_ACT_PIPE
+
+       __u32                   limit;
+       __u32                   burst;
+       __u32                   mtu;
+       struct tc_ratespec      rate;
+       struct tc_ratespec      peakrate;
+       int                     refcnt;
+       int                     bindcnt;
+       __u32                   capab;
+};
+
+struct tcf_t {
+       __u64   install;
+       __u64   lastuse;
+       __u64   expires;
+       __u64   firstuse;
+};
+
+struct tc_cnt {
+       int                   refcnt;
+       int                   bindcnt;
+};
+
+#define tc_gen \
+       __u32                 index; \
+       __u32                 capab; \
+       int                   action; \
+       int                   refcnt; \
+       int                   bindcnt
+
+enum {
+       TCA_POLICE_UNSPEC,
+       TCA_POLICE_TBF,
+       TCA_POLICE_RATE,
+       TCA_POLICE_PEAKRATE,
+       TCA_POLICE_AVRATE,
+       TCA_POLICE_RESULT,
+       TCA_POLICE_TM,
+       TCA_POLICE_PAD,
+       __TCA_POLICE_MAX
+#define TCA_POLICE_RESULT TCA_POLICE_RESULT
+};
+
+#define TCA_POLICE_MAX (__TCA_POLICE_MAX - 1)
+
+/* tca flags definitions */
+#define TCA_CLS_FLAGS_SKIP_HW  (1 << 0) /* don't offload filter to HW */
+#define TCA_CLS_FLAGS_SKIP_SW  (1 << 1) /* don't use filter in SW */
+#define TCA_CLS_FLAGS_IN_HW    (1 << 2) /* filter is offloaded to HW */
+#define TCA_CLS_FLAGS_NOT_IN_HW (1 << 3) /* filter isn't offloaded to HW */
+#define TCA_CLS_FLAGS_VERBOSE  (1 << 4) /* verbose logging */
+
+/* U32 filters */
+
+#define TC_U32_HTID(h) ((h)&0xFFF00000)
+#define TC_U32_USERHTID(h) (TC_U32_HTID(h)>>20)
+#define TC_U32_HASH(h) (((h)>>12)&0xFF)
+#define TC_U32_NODE(h) ((h)&0xFFF)
+#define TC_U32_KEY(h) ((h)&0xFFFFF)
+#define TC_U32_UNSPEC  0
+#define TC_U32_ROOT    (0xFFF00000)
+
+enum {
+       TCA_U32_UNSPEC,
+       TCA_U32_CLASSID,
+       TCA_U32_HASH,
+       TCA_U32_LINK,
+       TCA_U32_DIVISOR,
+       TCA_U32_SEL,
+       TCA_U32_POLICE,
+       TCA_U32_ACT,
+       TCA_U32_INDEV,
+       TCA_U32_PCNT,
+       TCA_U32_MARK,
+       TCA_U32_FLAGS,
+       TCA_U32_PAD,
+       __TCA_U32_MAX
+};
+
+#define TCA_U32_MAX (__TCA_U32_MAX - 1)
+
+struct tc_u32_key {
+       __be32          mask;
+       __be32          val;
+       int             off;
+       int             offmask;
+};
+
+struct tc_u32_sel {
+       unsigned char           flags;
+       unsigned char           offshift;
+       unsigned char           nkeys;
+
+       __be16                  offmask;
+       __u16                   off;
+       short                   offoff;
+
+       short                   hoff;
+       __be32                  hmask;
+       struct tc_u32_key       keys[0];
+};
+
+struct tc_u32_mark {
+       __u32           val;
+       __u32           mask;
+       __u32           success;
+};
+
+struct tc_u32_pcnt {
+       __u64 rcnt;
+       __u64 rhit;
+       __u64 kcnts[0];
+};
+
+/* Flags */
+
+#define TC_U32_TERMINAL                1
+#define TC_U32_OFFSET          2
+#define TC_U32_VAROFFSET       4
+#define TC_U32_EAT             8
+
+#define TC_U32_MAXDEPTH 8
+
+
+/* RSVP filter */
+
+enum {
+       TCA_RSVP_UNSPEC,
+       TCA_RSVP_CLASSID,
+       TCA_RSVP_DST,
+       TCA_RSVP_SRC,
+       TCA_RSVP_PINFO,
+       TCA_RSVP_POLICE,
+       TCA_RSVP_ACT,
+       __TCA_RSVP_MAX
+};
+
+#define TCA_RSVP_MAX (__TCA_RSVP_MAX - 1 )
+
+struct tc_rsvp_gpi {
+       __u32   key;
+       __u32   mask;
+       int     offset;
+};
+
+struct tc_rsvp_pinfo {
+       struct tc_rsvp_gpi dpi;
+       struct tc_rsvp_gpi spi;
+       __u8    protocol;
+       __u8    tunnelid;
+       __u8    tunnelhdr;
+       __u8    pad;
+};
+
+/* ROUTE filter */
+
+enum {
+       TCA_ROUTE4_UNSPEC,
+       TCA_ROUTE4_CLASSID,
+       TCA_ROUTE4_TO,
+       TCA_ROUTE4_FROM,
+       TCA_ROUTE4_IIF,
+       TCA_ROUTE4_POLICE,
+       TCA_ROUTE4_ACT,
+       __TCA_ROUTE4_MAX
+};
+
+#define TCA_ROUTE4_MAX (__TCA_ROUTE4_MAX - 1)
+
+
+/* FW filter */
+
+enum {
+       TCA_FW_UNSPEC,
+       TCA_FW_CLASSID,
+       TCA_FW_POLICE,
+       TCA_FW_INDEV, /*  used by CONFIG_NET_CLS_IND */
+       TCA_FW_ACT, /* used by CONFIG_NET_CLS_ACT */
+       TCA_FW_MASK,
+       __TCA_FW_MAX
+};
+
+#define TCA_FW_MAX (__TCA_FW_MAX - 1)
+
+/* TC index filter */
+
+enum {
+       TCA_TCINDEX_UNSPEC,
+       TCA_TCINDEX_HASH,
+       TCA_TCINDEX_MASK,
+       TCA_TCINDEX_SHIFT,
+       TCA_TCINDEX_FALL_THROUGH,
+       TCA_TCINDEX_CLASSID,
+       TCA_TCINDEX_POLICE,
+       TCA_TCINDEX_ACT,
+       __TCA_TCINDEX_MAX
+};
+
+#define TCA_TCINDEX_MAX     (__TCA_TCINDEX_MAX - 1)
+
+/* Flow filter */
+
+enum {
+       FLOW_KEY_SRC,
+       FLOW_KEY_DST,
+       FLOW_KEY_PROTO,
+       FLOW_KEY_PROTO_SRC,
+       FLOW_KEY_PROTO_DST,
+       FLOW_KEY_IIF,
+       FLOW_KEY_PRIORITY,
+       FLOW_KEY_MARK,
+       FLOW_KEY_NFCT,
+       FLOW_KEY_NFCT_SRC,
+       FLOW_KEY_NFCT_DST,
+       FLOW_KEY_NFCT_PROTO_SRC,
+       FLOW_KEY_NFCT_PROTO_DST,
+       FLOW_KEY_RTCLASSID,
+       FLOW_KEY_SKUID,
+       FLOW_KEY_SKGID,
+       FLOW_KEY_VLAN_TAG,
+       FLOW_KEY_RXHASH,
+       __FLOW_KEY_MAX,
+};
+
+#define FLOW_KEY_MAX   (__FLOW_KEY_MAX - 1)
+
+enum {
+       FLOW_MODE_MAP,
+       FLOW_MODE_HASH,
+};
+
+enum {
+       TCA_FLOW_UNSPEC,
+       TCA_FLOW_KEYS,
+       TCA_FLOW_MODE,
+       TCA_FLOW_BASECLASS,
+       TCA_FLOW_RSHIFT,
+       TCA_FLOW_ADDEND,
+       TCA_FLOW_MASK,
+       TCA_FLOW_XOR,
+       TCA_FLOW_DIVISOR,
+       TCA_FLOW_ACT,
+       TCA_FLOW_POLICE,
+       TCA_FLOW_EMATCHES,
+       TCA_FLOW_PERTURB,
+       __TCA_FLOW_MAX
+};
+
+#define TCA_FLOW_MAX   (__TCA_FLOW_MAX - 1)
+
+/* Basic filter */
+
+enum {
+       TCA_BASIC_UNSPEC,
+       TCA_BASIC_CLASSID,
+       TCA_BASIC_EMATCHES,
+       TCA_BASIC_ACT,
+       TCA_BASIC_POLICE,
+       __TCA_BASIC_MAX
+};
+
+#define TCA_BASIC_MAX (__TCA_BASIC_MAX - 1)
+
+
+/* Cgroup classifier */
+
+enum {
+       TCA_CGROUP_UNSPEC,
+       TCA_CGROUP_ACT,
+       TCA_CGROUP_POLICE,
+       TCA_CGROUP_EMATCHES,
+       __TCA_CGROUP_MAX,
+};
+
+#define TCA_CGROUP_MAX (__TCA_CGROUP_MAX - 1)
+
+/* BPF classifier */
+
+#define TCA_BPF_FLAG_ACT_DIRECT                (1 << 0)
+
+enum {
+       TCA_BPF_UNSPEC,
+       TCA_BPF_ACT,
+       TCA_BPF_POLICE,
+       TCA_BPF_CLASSID,
+       TCA_BPF_OPS_LEN,
+       TCA_BPF_OPS,
+       TCA_BPF_FD,
+       TCA_BPF_NAME,
+       TCA_BPF_FLAGS,
+       TCA_BPF_FLAGS_GEN,
+       TCA_BPF_TAG,
+       TCA_BPF_ID,
+       __TCA_BPF_MAX,
+};
+
+#define TCA_BPF_MAX (__TCA_BPF_MAX - 1)
+
+/* Flower classifier */
+
+enum {
+       TCA_FLOWER_UNSPEC,
+       TCA_FLOWER_CLASSID,
+       TCA_FLOWER_INDEV,
+       TCA_FLOWER_ACT,
+       TCA_FLOWER_KEY_ETH_DST,         /* ETH_ALEN */
+       TCA_FLOWER_KEY_ETH_DST_MASK,    /* ETH_ALEN */
+       TCA_FLOWER_KEY_ETH_SRC,         /* ETH_ALEN */
+       TCA_FLOWER_KEY_ETH_SRC_MASK,    /* ETH_ALEN */
+       TCA_FLOWER_KEY_ETH_TYPE,        /* be16 */
+       TCA_FLOWER_KEY_IP_PROTO,        /* u8 */
+       TCA_FLOWER_KEY_IPV4_SRC,        /* be32 */
+       TCA_FLOWER_KEY_IPV4_SRC_MASK,   /* be32 */
+       TCA_FLOWER_KEY_IPV4_DST,        /* be32 */
+       TCA_FLOWER_KEY_IPV4_DST_MASK,   /* be32 */
+       TCA_FLOWER_KEY_IPV6_SRC,        /* struct in6_addr */
+       TCA_FLOWER_KEY_IPV6_SRC_MASK,   /* struct in6_addr */
+       TCA_FLOWER_KEY_IPV6_DST,        /* struct in6_addr */
+       TCA_FLOWER_KEY_IPV6_DST_MASK,   /* struct in6_addr */
+       TCA_FLOWER_KEY_TCP_SRC,         /* be16 */
+       TCA_FLOWER_KEY_TCP_DST,         /* be16 */
+       TCA_FLOWER_KEY_UDP_SRC,         /* be16 */
+       TCA_FLOWER_KEY_UDP_DST,         /* be16 */
+
+       TCA_FLOWER_FLAGS,
+       TCA_FLOWER_KEY_VLAN_ID,         /* be16 */
+       TCA_FLOWER_KEY_VLAN_PRIO,       /* u8   */
+       TCA_FLOWER_KEY_VLAN_ETH_TYPE,   /* be16 */
+
+       TCA_FLOWER_KEY_ENC_KEY_ID,      /* be32 */
+       TCA_FLOWER_KEY_ENC_IPV4_SRC,    /* be32 */
+       TCA_FLOWER_KEY_ENC_IPV4_SRC_MASK,/* be32 */
+       TCA_FLOWER_KEY_ENC_IPV4_DST,    /* be32 */
+       TCA_FLOWER_KEY_ENC_IPV4_DST_MASK,/* be32 */
+       TCA_FLOWER_KEY_ENC_IPV6_SRC,    /* struct in6_addr */
+       TCA_FLOWER_KEY_ENC_IPV6_SRC_MASK,/* struct in6_addr */
+       TCA_FLOWER_KEY_ENC_IPV6_DST,    /* struct in6_addr */
+       TCA_FLOWER_KEY_ENC_IPV6_DST_MASK,/* struct in6_addr */
+
+       TCA_FLOWER_KEY_TCP_SRC_MASK,    /* be16 */
+       TCA_FLOWER_KEY_TCP_DST_MASK,    /* be16 */
+       TCA_FLOWER_KEY_UDP_SRC_MASK,    /* be16 */
+       TCA_FLOWER_KEY_UDP_DST_MASK,    /* be16 */
+       TCA_FLOWER_KEY_SCTP_SRC_MASK,   /* be16 */
+       TCA_FLOWER_KEY_SCTP_DST_MASK,   /* be16 */
+
+       TCA_FLOWER_KEY_SCTP_SRC,        /* be16 */
+       TCA_FLOWER_KEY_SCTP_DST,        /* be16 */
+
+       TCA_FLOWER_KEY_ENC_UDP_SRC_PORT,        /* be16 */
+       TCA_FLOWER_KEY_ENC_UDP_SRC_PORT_MASK,   /* be16 */
+       TCA_FLOWER_KEY_ENC_UDP_DST_PORT,        /* be16 */
+       TCA_FLOWER_KEY_ENC_UDP_DST_PORT_MASK,   /* be16 */
+
+       TCA_FLOWER_KEY_FLAGS,           /* be32 */
+       TCA_FLOWER_KEY_FLAGS_MASK,      /* be32 */
+
+       TCA_FLOWER_KEY_ICMPV4_CODE,     /* u8 */
+       TCA_FLOWER_KEY_ICMPV4_CODE_MASK,/* u8 */
+       TCA_FLOWER_KEY_ICMPV4_TYPE,     /* u8 */
+       TCA_FLOWER_KEY_ICMPV4_TYPE_MASK,/* u8 */
+       TCA_FLOWER_KEY_ICMPV6_CODE,     /* u8 */
+       TCA_FLOWER_KEY_ICMPV6_CODE_MASK,/* u8 */
+       TCA_FLOWER_KEY_ICMPV6_TYPE,     /* u8 */
+       TCA_FLOWER_KEY_ICMPV6_TYPE_MASK,/* u8 */
+
+       TCA_FLOWER_KEY_ARP_SIP,         /* be32 */
+       TCA_FLOWER_KEY_ARP_SIP_MASK,    /* be32 */
+       TCA_FLOWER_KEY_ARP_TIP,         /* be32 */
+       TCA_FLOWER_KEY_ARP_TIP_MASK,    /* be32 */
+       TCA_FLOWER_KEY_ARP_OP,          /* u8 */
+       TCA_FLOWER_KEY_ARP_OP_MASK,     /* u8 */
+       TCA_FLOWER_KEY_ARP_SHA,         /* ETH_ALEN */
+       TCA_FLOWER_KEY_ARP_SHA_MASK,    /* ETH_ALEN */
+       TCA_FLOWER_KEY_ARP_THA,         /* ETH_ALEN */
+       TCA_FLOWER_KEY_ARP_THA_MASK,    /* ETH_ALEN */
+
+       TCA_FLOWER_KEY_MPLS_TTL,        /* u8 - 8 bits */
+       TCA_FLOWER_KEY_MPLS_BOS,        /* u8 - 1 bit */
+       TCA_FLOWER_KEY_MPLS_TC,         /* u8 - 3 bits */
+       TCA_FLOWER_KEY_MPLS_LABEL,      /* be32 - 20 bits */
+
+       TCA_FLOWER_KEY_TCP_FLAGS,       /* be16 */
+       TCA_FLOWER_KEY_TCP_FLAGS_MASK,  /* be16 */
+
+       TCA_FLOWER_KEY_IP_TOS,          /* u8 */
+       TCA_FLOWER_KEY_IP_TOS_MASK,     /* u8 */
+       TCA_FLOWER_KEY_IP_TTL,          /* u8 */
+       TCA_FLOWER_KEY_IP_TTL_MASK,     /* u8 */
+
+       TCA_FLOWER_KEY_CVLAN_ID,        /* be16 */
+       TCA_FLOWER_KEY_CVLAN_PRIO,      /* u8   */
+       TCA_FLOWER_KEY_CVLAN_ETH_TYPE,  /* be16 */
+
+       TCA_FLOWER_KEY_ENC_IP_TOS,      /* u8 */
+       TCA_FLOWER_KEY_ENC_IP_TOS_MASK, /* u8 */
+       TCA_FLOWER_KEY_ENC_IP_TTL,      /* u8 */
+       TCA_FLOWER_KEY_ENC_IP_TTL_MASK, /* u8 */
+
+       TCA_FLOWER_KEY_ENC_OPTS,
+       TCA_FLOWER_KEY_ENC_OPTS_MASK,
+
+       TCA_FLOWER_IN_HW_COUNT,
+
+       __TCA_FLOWER_MAX,
+};
+
+#define TCA_FLOWER_MAX (__TCA_FLOWER_MAX - 1)
+
+enum {
+       TCA_FLOWER_KEY_ENC_OPTS_UNSPEC,
+       TCA_FLOWER_KEY_ENC_OPTS_GENEVE, /* Nested
+                                        * TCA_FLOWER_KEY_ENC_OPT_GENEVE_
+                                        * attributes
+                                        */
+       __TCA_FLOWER_KEY_ENC_OPTS_MAX,
+};
+
+#define TCA_FLOWER_KEY_ENC_OPTS_MAX (__TCA_FLOWER_KEY_ENC_OPTS_MAX - 1)
+
+enum {
+       TCA_FLOWER_KEY_ENC_OPT_GENEVE_UNSPEC,
+       TCA_FLOWER_KEY_ENC_OPT_GENEVE_CLASS,            /* u16 */
+       TCA_FLOWER_KEY_ENC_OPT_GENEVE_TYPE,             /* u8 */
+       TCA_FLOWER_KEY_ENC_OPT_GENEVE_DATA,             /* 4 to 128 bytes */
+
+       __TCA_FLOWER_KEY_ENC_OPT_GENEVE_MAX,
+};
+
+#define TCA_FLOWER_KEY_ENC_OPT_GENEVE_MAX \
+               (__TCA_FLOWER_KEY_ENC_OPT_GENEVE_MAX - 1)
+
+enum {
+       TCA_FLOWER_KEY_FLAGS_IS_FRAGMENT = (1 << 0),
+       TCA_FLOWER_KEY_FLAGS_FRAG_IS_FIRST = (1 << 1),
+};
+
+/* Match-all classifier */
+
+enum {
+       TCA_MATCHALL_UNSPEC,
+       TCA_MATCHALL_CLASSID,
+       TCA_MATCHALL_ACT,
+       TCA_MATCHALL_FLAGS,
+       __TCA_MATCHALL_MAX,
+};
+
+#define TCA_MATCHALL_MAX (__TCA_MATCHALL_MAX - 1)
+
+/* Extended Matches */
+
+struct tcf_ematch_tree_hdr {
+       __u16           nmatches;
+       __u16           progid;
+};
+
+enum {
+       TCA_EMATCH_TREE_UNSPEC,
+       TCA_EMATCH_TREE_HDR,
+       TCA_EMATCH_TREE_LIST,
+       __TCA_EMATCH_TREE_MAX
+};
+#define TCA_EMATCH_TREE_MAX (__TCA_EMATCH_TREE_MAX - 1)
+
+struct tcf_ematch_hdr {
+       __u16           matchid;
+       __u16           kind;
+       __u16           flags;
+       __u16           pad; /* currently unused */
+};
+
+/*  0                   1
+ *  0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 
+ * +-----------------------+-+-+---+
+ * |         Unused        |S|I| R |
+ * +-----------------------+-+-+---+
+ *
+ * R(2) ::= relation to next ematch
+ *          where: 0 0 END (last ematch)
+ *                 0 1 AND
+ *                 1 0 OR
+ *                 1 1 Unused (invalid)
+ * I(1) ::= invert result
+ * S(1) ::= simple payload
+ */
+#define TCF_EM_REL_END 0
+#define TCF_EM_REL_AND (1<<0)
+#define TCF_EM_REL_OR  (1<<1)
+#define TCF_EM_INVERT  (1<<2)
+#define TCF_EM_SIMPLE  (1<<3)
+
+#define TCF_EM_REL_MASK        3
+#define TCF_EM_REL_VALID(v) (((v) & TCF_EM_REL_MASK) != TCF_EM_REL_MASK)
+
+enum {
+       TCF_LAYER_LINK,
+       TCF_LAYER_NETWORK,
+       TCF_LAYER_TRANSPORT,
+       __TCF_LAYER_MAX
+};
+#define TCF_LAYER_MAX (__TCF_LAYER_MAX - 1)
+
+/* Ematch type assignments
+ *   1..32767          Reserved for ematches inside kernel tree
+ *   32768..65535      Free to use, not reliable
+ */
+#define        TCF_EM_CONTAINER        0
+#define        TCF_EM_CMP              1
+#define        TCF_EM_NBYTE            2
+#define        TCF_EM_U32              3
+#define        TCF_EM_META             4
+#define        TCF_EM_TEXT             5
+#define        TCF_EM_VLAN             6
+#define        TCF_EM_CANID            7
+#define        TCF_EM_IPSET            8
+#define        TCF_EM_IPT              9
+#define        TCF_EM_MAX              9
+
+enum {
+       TCF_EM_PROG_TC
+};
+
+enum {
+       TCF_EM_OPND_EQ,
+       TCF_EM_OPND_GT,
+       TCF_EM_OPND_LT
+};
+
+#endif
index c0d7ea0..b17201e 100644 (file)
@@ -212,6 +212,7 @@ struct prctl_mm_map {
 #define PR_SET_SPECULATION_CTRL                53
 /* Speculation control variants */
 # define PR_SPEC_STORE_BYPASS          0
+# define PR_SPEC_INDIRECT_BRANCH       1
 /* Return and control values for PR_SET/GET_SPECULATION_CTRL */
 # define PR_SPEC_NOT_AFFECTED          0
 # define PR_SPEC_PRCTL                 (1UL << 0)
diff --git a/tools/include/uapi/linux/tc_act/tc_bpf.h b/tools/include/uapi/linux/tc_act/tc_bpf.h
new file mode 100644 (file)
index 0000000..6e89a5d
--- /dev/null
@@ -0,0 +1,37 @@
+/* SPDX-License-Identifier: GPL-2.0+ WITH Linux-syscall-note */
+/*
+ * Copyright (c) 2015 Jiri Pirko <jiri@resnulli.us>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ */
+
+#ifndef __LINUX_TC_BPF_H
+#define __LINUX_TC_BPF_H
+
+#include <linux/pkt_cls.h>
+
+#define TCA_ACT_BPF 13
+
+struct tc_act_bpf {
+       tc_gen;
+};
+
+enum {
+       TCA_ACT_BPF_UNSPEC,
+       TCA_ACT_BPF_TM,
+       TCA_ACT_BPF_PARMS,
+       TCA_ACT_BPF_OPS_LEN,
+       TCA_ACT_BPF_OPS,
+       TCA_ACT_BPF_FD,
+       TCA_ACT_BPF_NAME,
+       TCA_ACT_BPF_PAD,
+       TCA_ACT_BPF_TAG,
+       TCA_ACT_BPF_ID,
+       __TCA_ACT_BPF_MAX,
+};
+#define TCA_ACT_BPF_MAX (__TCA_ACT_BPF_MAX - 1)
+
+#endif
index 6dbb9fa..b8f3cca 100644 (file)
@@ -31,6 +31,8 @@
 #include "elf.h"
 #include "warn.h"
 
+#define MAX_NAME_LEN 128
+
 struct section *find_section_by_name(struct elf *elf, const char *name)
 {
        struct section *sec;
@@ -298,6 +300,8 @@ static int read_symbols(struct elf *elf)
        /* Create parent/child links for any cold subfunctions */
        list_for_each_entry(sec, &elf->sections, list) {
                list_for_each_entry(sym, &sec->symbol_list, list) {
+                       char pname[MAX_NAME_LEN + 1];
+                       size_t pnamelen;
                        if (sym->type != STT_FUNC)
                                continue;
                        sym->pfunc = sym->cfunc = sym;
@@ -305,14 +309,21 @@ static int read_symbols(struct elf *elf)
                        if (!coldstr)
                                continue;
 
-                       coldstr[0] = '\0';
-                       pfunc = find_symbol_by_name(elf, sym->name);
-                       coldstr[0] = '.';
+                       pnamelen = coldstr - sym->name;
+                       if (pnamelen > MAX_NAME_LEN) {
+                               WARN("%s(): parent function name exceeds maximum length of %d characters",
+                                    sym->name, MAX_NAME_LEN);
+                               return -1;
+                       }
+
+                       strncpy(pname, sym->name, pnamelen);
+                       pname[pnamelen] = '\0';
+                       pfunc = find_symbol_by_name(elf, pname);
 
                        if (!pfunc) {
                                WARN("%s(): can't find parent function",
                                     sym->name);
-                               goto err;
+                               return -1;
                        }
 
                        sym->pfunc = pfunc;
index e30d20f..a0e8c23 100644 (file)
@@ -299,6 +299,11 @@ ifndef NO_BIONIC
   endif
 endif
 
+ifeq ($(feature-get_current_dir_name), 1)
+  CFLAGS += -DHAVE_GET_CURRENT_DIR_NAME
+endif
+
+
 ifdef NO_LIBELF
   NO_DWARF := 1
   NO_DEMANGLE := 1
index 3794066..efd0157 100644 (file)
@@ -9,7 +9,7 @@ size=112
 config=0
 sample_period=*
 sample_type=263
-read_format=0
+read_format=0|4
 disabled=1
 inherit=1
 pinned=0
index 5d2a7fd..eae59ad 100644 (file)
@@ -31,6 +31,7 @@ static size_t ioctl__scnprintf_tty_cmd(int nr, int dir, char *bf, size_t size)
        "TCSETSW2", "TCSETSF2", "TIOCGRS48", "TIOCSRS485", "TIOCGPTN", "TIOCSPTLCK",
        "TIOCGDEV", "TCSETX", "TCSETXF", "TCSETXW", "TIOCSIG", "TIOCVHANGUP", "TIOCGPKT",
        "TIOCGPTLCK", [_IOC_NR(TIOCGEXCL)] = "TIOCGEXCL", "TIOCGPTPEER",
+       "TIOCGISO7816", "TIOCSISO7816",
        [_IOC_NR(FIONCLEX)] = "FIONCLEX", "FIOCLEX", "FIOASYNC", "TIOCSERCONFIG",
        "TIOCSERGWILD", "TIOCSERSWILD", "TIOCGLCKTRMIOS", "TIOCSLCKTRMIOS",
        "TIOCSERGSTRUCT", "TIOCSERGETLSR", "TIOCSERGETMULTI", "TIOCSERSETMULTI",
index ecd9f9c..b7bf201 100644 (file)
@@ -10,6 +10,7 @@ libperf-y += evlist.o
 libperf-y += evsel.o
 libperf-y += evsel_fprintf.o
 libperf-y += find_bit.o
+libperf-y += get_current_dir_name.o
 libperf-y += kallsyms.o
 libperf-y += levenshtein.o
 libperf-y += llvm-utils.o
index d37bb15..dbc0466 100644 (file)
@@ -1092,7 +1092,7 @@ void perf_evsel__config(struct perf_evsel *evsel, struct record_opts *opts,
                attr->exclude_user   = 1;
        }
 
-       if (evsel->own_cpus)
+       if (evsel->own_cpus || evsel->unit)
                evsel->attr.read_format |= PERF_FORMAT_ID;
 
        /*
diff --git a/tools/perf/util/get_current_dir_name.c b/tools/perf/util/get_current_dir_name.c
new file mode 100644 (file)
index 0000000..267aa60
--- /dev/null
@@ -0,0 +1,18 @@
+// SPDX-License-Identifier: GPL-2.0
+// Copyright (C) 2018, Red Hat Inc, Arnaldo Carvalho de Melo <acme@redhat.com>
+//
+#ifndef HAVE_GET_CURRENT_DIR_NAME
+#include "util.h"
+#include <unistd.h>
+#include <stdlib.h>
+#include <stdlib.h>
+
+/* Android's 'bionic' library, for one, doesn't have this */
+
+char *get_current_dir_name(void)
+{
+       char pwd[PATH_MAX];
+
+       return getcwd(pwd, sizeof(pwd)) == NULL ? NULL : strdup(pwd);
+}
+#endif // HAVE_GET_CURRENT_DIR_NAME
index cf8bd12..aed170b 100644 (file)
@@ -18,6 +18,7 @@
 #include <stdio.h>
 #include <string.h>
 #include <unistd.h>
+#include <asm/bug.h>
 
 struct namespaces *namespaces__new(struct namespaces_event *event)
 {
@@ -186,6 +187,7 @@ void nsinfo__mountns_enter(struct nsinfo *nsi,
        char curpath[PATH_MAX];
        int oldns = -1;
        int newns = -1;
+       char *oldcwd = NULL;
 
        if (nc == NULL)
                return;
@@ -199,9 +201,13 @@ void nsinfo__mountns_enter(struct nsinfo *nsi,
        if (snprintf(curpath, PATH_MAX, "/proc/self/ns/mnt") >= PATH_MAX)
                return;
 
+       oldcwd = get_current_dir_name();
+       if (!oldcwd)
+               return;
+
        oldns = open(curpath, O_RDONLY);
        if (oldns < 0)
-               return;
+               goto errout;
 
        newns = open(nsi->mntns_path, O_RDONLY);
        if (newns < 0)
@@ -210,11 +216,13 @@ void nsinfo__mountns_enter(struct nsinfo *nsi,
        if (setns(newns, CLONE_NEWNS) < 0)
                goto errout;
 
+       nc->oldcwd = oldcwd;
        nc->oldns = oldns;
        nc->newns = newns;
        return;
 
 errout:
+       free(oldcwd);
        if (oldns > -1)
                close(oldns);
        if (newns > -1)
@@ -223,11 +231,16 @@ errout:
 
 void nsinfo__mountns_exit(struct nscookie *nc)
 {
-       if (nc == NULL || nc->oldns == -1 || nc->newns == -1)
+       if (nc == NULL || nc->oldns == -1 || nc->newns == -1 || !nc->oldcwd)
                return;
 
        setns(nc->oldns, CLONE_NEWNS);
 
+       if (nc->oldcwd) {
+               WARN_ON_ONCE(chdir(nc->oldcwd));
+               zfree(&nc->oldcwd);
+       }
+
        if (nc->oldns > -1) {
                close(nc->oldns);
                nc->oldns = -1;
index cae1a9a..d5f46c0 100644 (file)
@@ -38,6 +38,7 @@ struct nsinfo {
 struct nscookie {
        int                     oldns;
        int                     newns;
+       char                    *oldcwd;
 };
 
 int nsinfo__init(struct nsinfo *nsi);
index 14508ee..ece040b 100644 (file)
@@ -59,6 +59,10 @@ int fetch_kernel_version(unsigned int *puint,
 
 const char *perf_tip(const char *dirpath);
 
+#ifndef HAVE_GET_CURRENT_DIR_NAME
+char *get_current_dir_name(void);
+#endif
+
 #ifndef HAVE_SCHED_GETCPU_SUPPORT
 int sched_getcpu(void);
 #endif
index f1fe492..f0017c8 100644 (file)
@@ -24,6 +24,7 @@ TARGETS += memory-hotplug
 TARGETS += mount
 TARGETS += mqueue
 TARGETS += net
+TARGETS += netfilter
 TARGETS += nsfs
 TARGETS += powerpc
 TARGETS += proc
index 7887df6..44ed7f2 100644 (file)
@@ -81,7 +81,10 @@ int main(int argc, char **argv)
                goto err;
        }
 
-       assert(system("ping localhost -6 -c 10000 -f -q > /dev/null") == 0);
+       if (system("which ping6 &>/dev/null") == 0)
+               assert(!system("ping6 localhost -c 10000 -f -q > /dev/null"));
+       else
+               assert(!system("ping -6 localhost -c 10000 -f -q > /dev/null"));
 
        if (bpf_prog_query(cgroup_fd, BPF_CGROUP_INET_EGRESS, 0, NULL, NULL,
                           &prog_cnt)) {
index 6f61df6..550b7e4 100644 (file)
@@ -13896,6 +13896,25 @@ static struct bpf_test tests[] = {
                .prog_type = BPF_PROG_TYPE_SCHED_CLS,
                .result = ACCEPT,
        },
+       {
+               "calls: ctx read at start of subprog",
+               .insns = {
+                       BPF_MOV64_REG(BPF_REG_6, BPF_REG_1),
+                       BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 1, 0, 5),
+                       BPF_JMP_REG(BPF_JSGT, BPF_REG_0, BPF_REG_0, 0),
+                       BPF_MOV64_REG(BPF_REG_1, BPF_REG_6),
+                       BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 1, 0, 2),
+                       BPF_MOV64_REG(BPF_REG_1, BPF_REG_0),
+                       BPF_EXIT_INSN(),
+                       BPF_LDX_MEM(BPF_B, BPF_REG_9, BPF_REG_1, 0),
+                       BPF_MOV64_IMM(BPF_REG_0, 0),
+                       BPF_EXIT_INSN(),
+               },
+               .prog_type = BPF_PROG_TYPE_SOCKET_FILTER,
+               .errstr_unpriv = "function calls to other bpf functions are allowed for root only",
+               .result_unpriv = REJECT,
+               .result = ACCEPT,
+       },
 };
 
 static int probe_filter_length(const struct bpf_insn *fp)
diff --git a/tools/testing/selftests/netfilter/Makefile b/tools/testing/selftests/netfilter/Makefile
new file mode 100644 (file)
index 0000000..47ed6ce
--- /dev/null
@@ -0,0 +1,6 @@
+# SPDX-License-Identifier: GPL-2.0
+# Makefile for netfilter selftests
+
+TEST_PROGS := nft_trans_stress.sh
+
+include ../lib.mk
diff --git a/tools/testing/selftests/netfilter/config b/tools/testing/selftests/netfilter/config
new file mode 100644 (file)
index 0000000..1017313
--- /dev/null
@@ -0,0 +1,2 @@
+CONFIG_NET_NS=y
+NF_TABLES_INET=y
diff --git a/tools/testing/selftests/netfilter/nft_trans_stress.sh b/tools/testing/selftests/netfilter/nft_trans_stress.sh
new file mode 100755 (executable)
index 0000000..f1affd1
--- /dev/null
@@ -0,0 +1,78 @@
+#!/bin/bash
+#
+# This test is for stress-testing the nf_tables config plane path vs.
+# packet path processing: Make sure we never release rules that are
+# still visible to other cpus.
+#
+# set -e
+
+# Kselftest framework requirement - SKIP code is 4.
+ksft_skip=4
+
+testns=testns1
+tables="foo bar baz quux"
+
+nft --version > /dev/null 2>&1
+if [ $? -ne 0 ];then
+       echo "SKIP: Could not run test without nft tool"
+       exit $ksft_skip
+fi
+
+ip -Version > /dev/null 2>&1
+if [ $? -ne 0 ];then
+       echo "SKIP: Could not run test without ip tool"
+       exit $ksft_skip
+fi
+
+tmp=$(mktemp)
+
+for table in $tables; do
+       echo add table inet "$table" >> "$tmp"
+       echo flush table inet "$table" >> "$tmp"
+
+       echo "add chain inet $table INPUT { type filter hook input priority 0; }" >> "$tmp"
+       echo "add chain inet $table OUTPUT { type filter hook output priority 0; }" >> "$tmp"
+       for c in $(seq 1 400); do
+               chain=$(printf "chain%03u" "$c")
+               echo "add chain inet $table $chain" >> "$tmp"
+       done
+
+       for c in $(seq 1 400); do
+               chain=$(printf "chain%03u" "$c")
+               for BASE in INPUT OUTPUT; do
+                       echo "add rule inet $table $BASE counter jump $chain" >> "$tmp"
+               done
+               echo "add rule inet $table $chain counter return" >> "$tmp"
+       done
+done
+
+ip netns add "$testns"
+ip -netns "$testns" link set lo up
+
+lscpu | grep ^CPU\(s\): | ( read cpu cpunum ;
+cpunum=$((cpunum-1))
+for i in $(seq 0 $cpunum);do
+       mask=$(printf 0x%x $((1<<$i)))
+        ip netns exec "$testns" taskset $mask ping -4 127.0.0.1 -fq > /dev/null &
+        ip netns exec "$testns" taskset $mask ping -6 ::1 -fq > /dev/null &
+done)
+
+sleep 1
+
+for i in $(seq 1 10) ; do ip netns exec "$testns" nft -f "$tmp" & done
+
+for table in $tables;do
+       randsleep=$((RANDOM%10))
+       sleep $randsleep
+       ip netns exec "$testns" nft delete table inet $table 2>/dev/null
+done
+
+randsleep=$((RANDOM%10))
+sleep $randsleep
+
+pkill -9 ping
+
+wait
+
+rm -f "$tmp"
+ip netns del "$testns"
index 6f1f4a6..8574442 100644 (file)
@@ -13,7 +13,7 @@
  * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
  */
-/* Test readlink /proc/self/map_files/... with address 0. */
+/* Test readlink /proc/self/map_files/... with minimum address. */
 #include <errno.h>
 #include <sys/types.h>
 #include <sys/stat.h>
@@ -47,6 +47,11 @@ static void fail(const char *fmt, unsigned long a, unsigned long b)
 int main(void)
 {
        const unsigned int PAGE_SIZE = sysconf(_SC_PAGESIZE);
+#ifdef __arm__
+       unsigned long va = 2 * PAGE_SIZE;
+#else
+       unsigned long va = 0;
+#endif
        void *p;
        int fd;
        unsigned long a, b;
@@ -55,7 +60,7 @@ int main(void)
        if (fd == -1)
                return 1;
 
-       p = mmap(NULL, PAGE_SIZE, PROT_NONE, MAP_PRIVATE|MAP_FILE|MAP_FIXED, fd, 0);
+       p = mmap((void *)va, PAGE_SIZE, PROT_NONE, MAP_PRIVATE|MAP_FILE|MAP_FIXED, fd, 0);
        if (p == MAP_FAILED) {
                if (errno == EPERM)
                        return 2;