Merge tag 'sound-6.0-rc4' of git://git.kernel.org/pub/scm/linux/kernel/git/tiwai...
authorLinus Torvalds <torvalds@linux-foundation.org>
Thu, 1 Sep 2022 16:05:25 +0000 (09:05 -0700)
committerLinus Torvalds <torvalds@linux-foundation.org>
Thu, 1 Sep 2022 16:05:25 +0000 (09:05 -0700)
Pull sound fixes from Takashi Iwai:
 "Just handful changes at this time. The only major change is the
  regression fix about the x86 WC-page buffer allocation.

  The rest are trivial data-race fixes for ALSA sequencer core, the
  possible out-of-bounds access fixes in the new ALSA control hash code,
  and a few device-specific workarounds and fixes"

* tag 'sound-6.0-rc4' of git://git.kernel.org/pub/scm/linux/kernel/git/tiwai/sound:
  ALSA: usb-audio: Add quirk for LH Labs Geek Out HD Audio 1V5
  ALSA: hda/realtek: Add speaker AMP init for Samsung laptops with ALC298
  ALSA: control: Re-order bounds checking in get_ctl_id_hash()
  ALSA: control: Fix an out-of-bounds bug in get_ctl_id_hash()
  ALSA: hda: intel-nhlt: Correct the handling of fmt_config flexible array
  ALSA: seq: Fix data-race at module auto-loading
  ALSA: seq: oss: Fix data-race for max_midi_devs access
  ALSA: memalloc: Revive x86-specific WC page allocations again

405 files changed:
.get_maintainer.ignore
.mailmap
Documentation/ABI/testing/sysfs-devices-system-cpu
Documentation/admin-guide/README.rst
Documentation/admin-guide/hw-vuln/processor_mmio_stale_data.rst
Documentation/admin-guide/kernel-parameters.txt
Documentation/admin-guide/mm/damon/usage.rst
Documentation/admin-guide/sysctl/net.rst
Documentation/arm64/elf_hwcaps.rst
Documentation/arm64/silicon-errata.rst
Documentation/atomic_bitops.txt
Documentation/conf.py
Documentation/devicetree/bindings/thermal/thermal-zones.yaml
Documentation/sphinx/kerneldoc-preamble.sty
Documentation/translations/ja_JP/SubmittingPatches
MAINTAINERS
Makefile
arch/alpha/include/asm/bitops.h
arch/arm64/Kconfig
arch/arm64/include/asm/cache.h
arch/arm64/include/asm/fpsimd.h
arch/arm64/include/asm/setup.h
arch/arm64/include/asm/sysreg.h
arch/arm64/kernel/cacheinfo.c
arch/arm64/kernel/cpu_errata.c
arch/arm64/kernel/cpufeature.c
arch/arm64/kernel/entry.S
arch/arm64/kernel/fpsimd.c
arch/arm64/kernel/pi/kaslr_early.c
arch/arm64/kernel/ptrace.c
arch/arm64/kernel/signal.c
arch/arm64/kernel/topology.c
arch/arm64/mm/mmu.c
arch/arm64/tools/cpucaps
arch/hexagon/include/asm/bitops.h
arch/ia64/include/asm/bitops.h
arch/loongarch/Kconfig
arch/loongarch/include/asm/addrspace.h
arch/loongarch/include/asm/cmpxchg.h
arch/loongarch/include/asm/io.h
arch/loongarch/include/asm/page.h
arch/loongarch/include/asm/percpu.h
arch/loongarch/include/asm/pgtable.h
arch/loongarch/include/asm/reboot.h [deleted file]
arch/loongarch/kernel/reset.c
arch/loongarch/mm/fault.c
arch/loongarch/mm/mmap.c
arch/loongarch/vdso/vgetcpu.c
arch/loongarch/vdso/vgettimeofday.c
arch/m68k/include/asm/bitops.h
arch/parisc/Kconfig
arch/parisc/include/asm/bitops.h
arch/parisc/kernel/head.S
arch/parisc/kernel/unaligned.c
arch/riscv/boot/dts/microchip/mpfs-icicle-kit.dts
arch/riscv/boot/dts/microchip/mpfs-polarberry.dts
arch/riscv/boot/dts/microchip/mpfs.dtsi
arch/riscv/include/asm/signal.h [new file with mode: 0644]
arch/riscv/include/asm/thread_info.h
arch/riscv/kernel/signal.c
arch/riscv/kernel/traps.c
arch/s390/include/asm/bitops.h
arch/s390/kernel/process.c
arch/s390/mm/fault.c
arch/sh/include/asm/bitops-op32.h
arch/x86/boot/compressed/misc.h
arch/x86/boot/compressed/sev.c
arch/x86/configs/xen.config
arch/x86/entry/entry_64_compat.S
arch/x86/events/intel/core.c
arch/x86/events/intel/ds.c
arch/x86/events/intel/lbr.c
arch/x86/events/intel/uncore_snb.c
arch/x86/include/asm/bitops.h
arch/x86/include/asm/cpufeatures.h
arch/x86/include/asm/intel-family.h
arch/x86/include/asm/nospec-branch.h
arch/x86/include/asm/sev.h
arch/x86/kernel/cpu/bugs.c
arch/x86/kernel/cpu/common.c
arch/x86/kernel/sev.c
arch/x86/kernel/unwind_orc.c
arch/x86/mm/pat/memtype.c
block/blk-mq.c
drivers/acpi/processor_thermal.c
drivers/acpi/property.c
drivers/android/binder_alloc.c
drivers/block/loop.c
drivers/block/zram/zram_drv.c
drivers/block/zram/zram_drv.h
drivers/char/mem.c
drivers/cpufreq/cpufreq.c
drivers/firmware/dmi_scan.c
drivers/gpu/drm/amd/amdgpu/amdgpu_device.c
drivers/gpu/drm/amd/amdgpu/amdgpu_psp.c
drivers/gpu/drm/amd/amdgpu/amdgpu_xgmi.c
drivers/gpu/drm/amd/amdgpu/gfx_v11_0.c
drivers/gpu/drm/amd/amdgpu/gfx_v9_0.c
drivers/gpu/drm/amd/amdgpu/mmhub_v1_0.c
drivers/gpu/drm/amd/amdgpu/mmhub_v9_4.c
drivers/gpu/drm/amd/amdgpu/nbio_v7_7.c
drivers/gpu/drm/amd/amdgpu/soc21.c
drivers/gpu/drm/amd/amdkfd/kfd_device.c
drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_plane.c
drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_plane.h
drivers/gpu/drm/amd/display/dc/dcn314/dcn314_resource.c
drivers/gpu/drm/amd/include/asic_reg/nbio/nbio_7_7_0_offset.h
drivers/gpu/drm/amd/include/asic_reg/nbio/nbio_7_7_0_sh_mask.h
drivers/gpu/drm/amd/pm/swsmu/inc/pmfw_if/smu13_driver_if_v13_0_0.h
drivers/gpu/drm/amd/pm/swsmu/inc/smu_v13_0.h
drivers/gpu/drm/drm_gem.c
drivers/gpu/drm/drm_internal.h
drivers/gpu/drm/drm_prime.c
drivers/gpu/drm/nouveau/nouveau_bo.c
drivers/gpu/drm/radeon/radeon_device.c
drivers/gpu/drm/vc4/Kconfig
drivers/gpu/drm/vc4/vc4_hdmi.c
drivers/hid/amd-sfh-hid/amd_sfh_pcie.c
drivers/hid/hid-asus.c
drivers/hid/hid-ids.h
drivers/hid/hid-input.c
drivers/hid/hid-nintendo.c
drivers/hid/hid-quirks.c
drivers/hid/hid-steam.c
drivers/hid/hid-thrustmaster.c
drivers/hid/hidraw.c
drivers/hid/intel-ish-hid/ipc/hw-ish.h
drivers/hid/intel-ish-hid/ipc/pci-ish.c
drivers/hid/intel-ish-hid/ishtp-hid.h
drivers/hid/intel-ish-hid/ishtp/client.c
drivers/md/md.c
drivers/md/raid10.c
drivers/mmc/host/Kconfig
drivers/net/bonding/bond_3ad.c
drivers/net/bonding/bond_main.c
drivers/net/dsa/microchip/ksz_common.c
drivers/net/dsa/microchip/ksz_common.h
drivers/net/ethernet/broadcom/bnxt/bnxt.c
drivers/net/ethernet/broadcom/bnxt/bnxt.h
drivers/net/ethernet/broadcom/bnxt/bnxt_devlink.c
drivers/net/ethernet/broadcom/bnxt/bnxt_sriov.c
drivers/net/ethernet/broadcom/bnxt/bnxt_xdp.c
drivers/net/ethernet/freescale/dpaa/dpaa_eth.c
drivers/net/ethernet/freescale/fec.h
drivers/net/ethernet/freescale/fec_main.c
drivers/net/ethernet/freescale/fec_ptp.c
drivers/net/ethernet/intel/i40e/i40e_ethtool.c
drivers/net/ethernet/intel/ice/ice.h
drivers/net/ethernet/intel/ice/ice_lib.c
drivers/net/ethernet/intel/ice/ice_main.c
drivers/net/ethernet/intel/ice/ice_xsk.c
drivers/net/ethernet/intel/ixgbe/ixgbe_ptp.c
drivers/net/ethernet/lantiq_xrx200.c
drivers/net/ethernet/mediatek/mtk_eth_soc.c
drivers/net/ethernet/mediatek/mtk_eth_soc.h
drivers/net/ethernet/mellanox/mlx5/core/en/tc/act/police.c
drivers/net/ethernet/mellanox/mlx5/core/en_accel/ktls_tx.c
drivers/net/ethernet/mellanox/mlx5/core/en_fs.c
drivers/net/ethernet/mellanox/mlx5/core/en_main.c
drivers/net/ethernet/mellanox/mlx5/core/en_rep.c
drivers/net/ethernet/mellanox/mlx5/core/eswitch_offloads.c
drivers/net/ethernet/mellanox/mlx5/core/lag/lag.c
drivers/net/ethernet/mellanox/mlx5/core/main.c
drivers/net/ethernet/mellanox/mlx5/core/pagealloc.c
drivers/net/ethernet/mellanox/mlx5/core/sriov.c
drivers/net/ethernet/moxa/moxart_ether.c
drivers/net/ethernet/pensando/ionic/ionic_lif.c
drivers/net/ethernet/pensando/ionic/ionic_main.c
drivers/net/ethernet/stmicro/stmmac/dwmac_lib.c
drivers/net/ethernet/stmicro/stmmac/stmmac_main.c
drivers/net/ipa/ipa_mem.c
drivers/net/ipvlan/ipvtap.c
drivers/net/macsec.c
drivers/net/phy/phy_device.c
drivers/net/usb/r8152.c
drivers/nfc/pn533/uart.c
drivers/parisc/ccio-dma.c
drivers/parisc/led.c
drivers/scsi/megaraid/megaraid_sas_base.c
drivers/scsi/megaraid/megaraid_sas_fusion.c
drivers/scsi/qla2xxx/qla_target.c
drivers/scsi/scsi_lib.c
drivers/scsi/sd.c
drivers/scsi/sd.h
drivers/scsi/storvsc_drv.c
drivers/thermal/intel/int340x_thermal/int3400_thermal.c
drivers/thermal/thermal_core.c
drivers/ufs/core/ufshcd.c
drivers/ufs/host/ufs-exynos.c
drivers/video/console/sticore.c
drivers/video/fbdev/aty/atyfb_base.c
drivers/video/fbdev/aty/radeon_base.c
drivers/video/fbdev/bw2.c
drivers/video/fbdev/chipsfb.c
drivers/video/fbdev/cirrusfb.c
drivers/video/fbdev/clps711x-fb.c
drivers/video/fbdev/core/fbcon.c
drivers/video/fbdev/core/fbsysfs.c
drivers/video/fbdev/cyber2000fb.c
drivers/video/fbdev/ffb.c
drivers/video/fbdev/geode/gx1fb_core.c
drivers/video/fbdev/gxt4500.c
drivers/video/fbdev/i740fb.c
drivers/video/fbdev/imxfb.c
drivers/video/fbdev/matrox/matroxfb_base.c
drivers/video/fbdev/omap/omapfb_main.c
drivers/video/fbdev/omap2/omapfb/omapfb-main.c
drivers/video/fbdev/pm2fb.c
drivers/video/fbdev/pxa168fb.c
drivers/video/fbdev/pxafb.c
drivers/video/fbdev/s3fb.c
drivers/video/fbdev/simplefb.c
drivers/video/fbdev/sis/sis_main.c
drivers/video/fbdev/sm501fb.c
drivers/video/fbdev/ssd1307fb.c
drivers/video/fbdev/sstfb.c
drivers/video/fbdev/sunxvr1000.c
drivers/video/fbdev/sunxvr2500.c
drivers/video/fbdev/sunxvr500.c
drivers/video/fbdev/tcx.c
drivers/video/fbdev/tdfxfb.c
drivers/video/fbdev/tgafb.c
drivers/video/fbdev/tridentfb.c
drivers/xen/privcmd.c
drivers/xen/xen-scsiback.c
drivers/xen/xenbus/xenbus_probe_frontend.c
fs/btrfs/block-group.c
fs/btrfs/block-group.h
fs/btrfs/ctree.h
fs/btrfs/dev-replace.c
fs/btrfs/extent-tree.c
fs/btrfs/extent_io.c
fs/btrfs/file.c
fs/btrfs/inode.c
fs/btrfs/root-tree.c
fs/btrfs/volumes.c
fs/btrfs/xattr.c
fs/cachefiles/internal.h
fs/cachefiles/ondemand.c
fs/cifs/cifsencrypt.c
fs/cifs/cifsglob.h
fs/cifs/connect.c
fs/cifs/smb2ops.c
fs/cifs/smb2pdu.c
fs/cifs/transport.c
fs/fs-writeback.c
fs/inode.c
fs/locks.c
fs/namespace.c
fs/nfs/dir.c
fs/nfs/file.c
fs/nfs/inode.c
fs/nfs/nfs4file.c
fs/nfs/pnfs.c
fs/nfs/write.c
fs/ntfs3/xattr.c
fs/ocfs2/dlmglue.c
fs/ocfs2/super.c
fs/overlayfs/inode.c
fs/posix_acl.c
fs/proc/task_mmu.c
fs/squashfs/file.c
fs/squashfs/file_direct.c
fs/squashfs/page_actor.c
fs/squashfs/page_actor.h
fs/userfaultfd.c
include/asm-generic/bitops/generic-non-atomic.h
include/asm-generic/bitops/instrumented-non-atomic.h
include/asm-generic/bitops/non-atomic.h
include/asm-generic/bitops/non-instrumented-non-atomic.h
include/asm-generic/sections.h
include/linux/bitops.h
include/linux/buffer_head.h
include/linux/cgroup.h
include/linux/compiler.h
include/linux/fscache.h
include/linux/lsm_hook_defs.h
include/linux/lsm_hooks.h
include/linux/memcontrol.h
include/linux/mlx5/driver.h
include/linux/mm.h
include/linux/netdevice.h
include/linux/netfilter_bridge/ebtables.h
include/linux/nfs_fs.h
include/linux/overflow.h
include/linux/psi.h
include/linux/rmap.h
include/linux/security.h
include/linux/shmem_fs.h
include/linux/trace_events.h
include/linux/userfaultfd_k.h
include/linux/vm_event_item.h
include/linux/wait_bit.h
include/net/bond_3ad.h
include/net/busy_poll.h
include/net/gro.h
include/net/netfilter/nf_flow_table.h
include/net/netfilter/nf_tables.h
include/uapi/linux/io_uring.h
include/uapi/linux/xfrm.h
include/ufs/ufshci.h
init/main.c
io_uring/cancel.c
io_uring/io_uring.c
io_uring/net.c
io_uring/net.h
io_uring/notif.c
io_uring/opdef.c
io_uring/opdef.h
io_uring/uring_cmd.c
kernel/audit_fsnotify.c
kernel/auditsc.c
kernel/cgroup/cgroup-v1.c
kernel/cgroup/cgroup.c
kernel/cgroup/cpuset.c
kernel/crash_core.c
kernel/kprobes.c
kernel/module/main.c
kernel/sched/psi.c
kernel/sched/wait_bit.c
kernel/sys_ni.c
kernel/trace/ftrace.c
lib/Kconfig.debug
lib/Makefile
lib/cpumask_kunit.c [moved from lib/test_cpumask.c with 58% similarity]
lib/crypto/Kconfig
lib/ratelimit.c
mm/backing-dev.c
mm/bootmem_info.c
mm/damon/dbgfs.c
mm/gup.c
mm/huge_memory.c
mm/hugetlb.c
mm/mmap.c
mm/mprotect.c
mm/page-writeback.c
mm/rmap.c
mm/shmem.c
mm/userfaultfd.c
mm/vmstat.c
mm/zsmalloc.c
net/bridge/netfilter/ebtable_broute.c
net/bridge/netfilter/ebtable_filter.c
net/bridge/netfilter/ebtable_nat.c
net/bridge/netfilter/ebtables.c
net/core/bpf_sk_storage.c
net/core/dev.c
net/core/filter.c
net/core/gro_cells.c
net/core/neighbour.c
net/core/skbuff.c
net/core/sock.c
net/core/sysctl_net_core.c
net/dsa/slave.c
net/ipv4/devinet.c
net/ipv4/ip_output.c
net/ipv4/ip_sockglue.c
net/ipv4/tcp.c
net/ipv4/tcp_output.c
net/ipv6/addrconf.c
net/ipv6/ipv6_sockglue.c
net/ipv6/netfilter/nf_conntrack_reasm.c
net/key/af_key.c
net/mptcp/protocol.c
net/netfilter/ipvs/ip_vs_sync.c
net/netfilter/nf_conntrack_proto_tcp.c
net/netfilter/nf_flow_table_core.c
net/netfilter/nf_flow_table_offload.c
net/netfilter/nf_tables_api.c
net/netfilter/nft_osf.c
net/netfilter/nft_payload.c
net/netfilter/nft_tproxy.c
net/netfilter/nft_tunnel.c
net/rose/rose_loopback.c
net/rxrpc/call_object.c
net/rxrpc/sendmsg.c
net/sched/sch_generic.c
net/socket.c
net/sunrpc/clnt.c
net/xfrm/espintcp.c
net/xfrm/xfrm_input.c
net/xfrm/xfrm_output.c
net/xfrm/xfrm_policy.c
net/xfrm/xfrm_state.c
security/security.c
security/selinux/hooks.c
security/selinux/include/classmap.h
security/smack/smack_lsm.c
tools/arch/arm64/include/uapi/asm/kvm.h
tools/include/linux/compiler_types.h
tools/objtool/check.c
tools/perf/Documentation/intel-hybrid.txt
tools/perf/Documentation/perf-record.txt
tools/perf/Makefile.config
tools/perf/builtin-sched.c
tools/perf/builtin-stat.c
tools/perf/tests/shell/stat.sh
tools/perf/util/stat-shadow.c
tools/testing/selftests/Makefile
tools/testing/selftests/drivers/net/bonding/Makefile [new file with mode: 0644]
tools/testing/selftests/drivers/net/bonding/bond-break-lacpdu-tx.sh [new file with mode: 0755]
tools/testing/selftests/drivers/net/bonding/config [new file with mode: 0644]
tools/testing/selftests/drivers/net/bonding/settings [new file with mode: 0644]
tools/testing/selftests/lib.mk
tools/testing/selftests/sgx/sigstruct.c

index a64d219..c298bab 100644 (file)
@@ -1,2 +1,4 @@
+Alan Cox <alan@lxorguk.ukuu.org.uk>
+Alan Cox <root@hraefn.swansea.linux.org.uk>
 Christoph Hellwig <hch@lst.de>
 Marc Gonzalez <marc.w.gonzalez@free.fr>
index 38255d4..8ded2e7 100644 (file)
--- a/.mailmap
+++ b/.mailmap
@@ -98,8 +98,7 @@ Christian Brauner <brauner@kernel.org> <christian.brauner@ubuntu.com>
 Christian Marangi <ansuelsmth@gmail.com>
 Christophe Ricard <christophe.ricard@gmail.com>
 Christoph Hellwig <hch@lst.de>
-Colin Ian King <colin.king@intel.com> <colin.king@canonical.com>
-Colin Ian King <colin.king@intel.com> <colin.i.king@gmail.com>
+Colin Ian King <colin.i.king@gmail.com> <colin.king@canonical.com>
 Corey Minyard <minyard@acm.org>
 Damian Hobson-Garcia <dhobsong@igel.co.jp>
 Daniel Borkmann <daniel@iogearbox.net> <danborkmann@googlemail.com>
@@ -150,6 +149,8 @@ Greg Kroah-Hartman <gregkh@suse.de>
 Greg Kroah-Hartman <greg@kroah.com>
 Greg Kurz <groug@kaod.org> <gkurz@linux.vnet.ibm.com>
 Gregory CLEMENT <gregory.clement@bootlin.com> <gregory.clement@free-electrons.com>
+Guilherme G. Piccoli <kernel@gpiccoli.net> <gpiccoli@linux.vnet.ibm.com>
+Guilherme G. Piccoli <kernel@gpiccoli.net> <gpiccoli@canonical.com>
 Guo Ren <guoren@kernel.org> <guoren@linux.alibaba.com>
 Guo Ren <guoren@kernel.org> <ren_guo@c-sky.com>
 Gustavo Padovan <gustavo@las.ic.unicamp.br>
@@ -253,6 +254,7 @@ Linus Lüssing <linus.luessing@c0d3.blue> <linus.luessing@web.de>
 Li Yang <leoyang.li@nxp.com> <leoli@freescale.com>
 Li Yang <leoyang.li@nxp.com> <leo@zh-kernel.org>
 Lorenzo Pieralisi <lpieralisi@kernel.org> <lorenzo.pieralisi@arm.com>
+Luca Ceresoli <luca.ceresoli@bootlin.com> <luca@lucaceresoli.net>
 Lukasz Luba <lukasz.luba@arm.com> <l.luba@partner.samsung.com>
 Maciej W. Rozycki <macro@mips.com> <macro@imgtec.com>
 Maciej W. Rozycki <macro@orcam.me.uk> <macro@linux-mips.org>
index 5bf6188..760c889 100644 (file)
@@ -523,6 +523,7 @@ What:               /sys/devices/system/cpu/vulnerabilities
                /sys/devices/system/cpu/vulnerabilities/tsx_async_abort
                /sys/devices/system/cpu/vulnerabilities/itlb_multihit
                /sys/devices/system/cpu/vulnerabilities/mmio_stale_data
+               /sys/devices/system/cpu/vulnerabilities/retbleed
 Date:          January 2018
 Contact:       Linux kernel mailing list <linux-kernel@vger.kernel.org>
 Description:   Information about CPU vulnerabilities
index caa3c09..9eb6b90 100644 (file)
@@ -1,9 +1,9 @@
 .. _readme:
 
-Linux kernel release 5.x <http://kernel.org/>
+Linux kernel release 6.x <http://kernel.org/>
 =============================================
 
-These are the release notes for Linux version 5.  Read them carefully,
+These are the release notes for Linux version 6.  Read them carefully,
 as they tell you what this is all about, explain how to install the
 kernel, and what to do if something goes wrong.
 
@@ -63,7 +63,7 @@ Installing the kernel source
    directory where you have permissions (e.g. your home directory) and
    unpack it::
 
-     xz -cd linux-5.x.tar.xz | tar xvf -
+     xz -cd linux-6.x.tar.xz | tar xvf -
 
    Replace "X" with the version number of the latest kernel.
 
@@ -72,12 +72,12 @@ Installing the kernel source
    files.  They should match the library, and not get messed up by
    whatever the kernel-du-jour happens to be.
 
- - You can also upgrade between 5.x releases by patching.  Patches are
+ - You can also upgrade between 6.x releases by patching.  Patches are
    distributed in the xz format.  To install by patching, get all the
    newer patch files, enter the top level directory of the kernel source
-   (linux-5.x) and execute::
+   (linux-6.x) and execute::
 
-     xz -cd ../patch-5.x.xz | patch -p1
+     xz -cd ../patch-6.x.xz | patch -p1
 
    Replace "x" for all versions bigger than the version "x" of your current
    source tree, **in_order**, and you should be ok.  You may want to remove
@@ -85,13 +85,13 @@ Installing the kernel source
    that there are no failed patches (some-file-name# or some-file-name.rej).
    If there are, either you or I have made a mistake.
 
-   Unlike patches for the 5.x kernels, patches for the 5.x.y kernels
+   Unlike patches for the 6.x kernels, patches for the 6.x.y kernels
    (also known as the -stable kernels) are not incremental but instead apply
-   directly to the base 5.x kernel.  For example, if your base kernel is 5.0
-   and you want to apply the 5.0.3 patch, you must not first apply the 5.0.1
-   and 5.0.2 patches. Similarly, if you are running kernel version 5.0.2 and
-   want to jump to 5.0.3, you must first reverse the 5.0.2 patch (that is,
-   patch -R) **before** applying the 5.0.3 patch. You can read more on this in
+   directly to the base 6.x kernel.  For example, if your base kernel is 6.0
+   and you want to apply the 6.0.3 patch, you must not first apply the 6.0.1
+   and 6.0.2 patches. Similarly, if you are running kernel version 6.0.2 and
+   want to jump to 6.0.3, you must first reverse the 6.0.2 patch (that is,
+   patch -R) **before** applying the 6.0.3 patch. You can read more on this in
    :ref:`Documentation/process/applying-patches.rst <applying_patches>`.
 
    Alternatively, the script patch-kernel can be used to automate this
@@ -114,7 +114,7 @@ Installing the kernel source
 Software requirements
 ---------------------
 
-   Compiling and running the 5.x kernels requires up-to-date
+   Compiling and running the 6.x kernels requires up-to-date
    versions of various software packages.  Consult
    :ref:`Documentation/process/changes.rst <changes>` for the minimum version numbers
    required and how to get updates for these packages.  Beware that using
@@ -132,12 +132,12 @@ Build directory for the kernel
    place for the output files (including .config).
    Example::
 
-     kernel source code: /usr/src/linux-5.x
+     kernel source code: /usr/src/linux-6.x
      build directory:    /home/name/build/kernel
 
    To configure and build the kernel, use::
 
-     cd /usr/src/linux-5.x
+     cd /usr/src/linux-6.x
      make O=/home/name/build/kernel menuconfig
      make O=/home/name/build/kernel
      sudo make O=/home/name/build/kernel modules_install install
index 9393c50..c98fd11 100644 (file)
@@ -230,6 +230,20 @@ The possible values in this file are:
      * - 'Mitigation: Clear CPU buffers'
        - The processor is vulnerable and the CPU buffer clearing mitigation is
          enabled.
+     * - 'Unknown: No mitigations'
+       - The processor vulnerability status is unknown because it is
+        out of Servicing period. Mitigation is not attempted.
+
+Definitions:
+------------
+
+Servicing period: The process of providing functional and security updates to
+Intel processors or platforms, utilizing the Intel Platform Update (IPU)
+process or other similar mechanisms.
+
+End of Servicing Updates (ESU): ESU is the date at which Intel will no
+longer provide Servicing, such as through IPU or other similar update
+processes. ESU dates will typically be aligned to end of quarter.
 
 If the processor is vulnerable then the following information is appended to
 the above information:
index d7f3090..426fa89 100644 (file)
        rodata=         [KNL]
                on      Mark read-only kernel memory as read-only (default).
                off     Leave read-only kernel memory writable for debugging.
+               full    Mark read-only kernel memory and aliases as read-only
+                       [arm64]
 
        rockchip.usb_uart
                        Enable the uart passthrough on the designated usb port
index d52f572..ca91ecc 100644 (file)
@@ -50,10 +50,10 @@ For a short example, users can monitor the virtual address space of a given
 workload as below. ::
 
     # cd /sys/kernel/mm/damon/admin/
-    # echo 1 > kdamonds/nr && echo 1 > kdamonds/0/contexts/nr
+    # echo 1 > kdamonds/nr_kdamonds && echo 1 > kdamonds/0/contexts/nr_contexts
     # echo vaddr > kdamonds/0/contexts/0/operations
-    # echo 1 > kdamonds/0/contexts/0/targets/nr
-    # echo $(pidof <workload>) > kdamonds/0/contexts/0/targets/0/pid
+    # echo 1 > kdamonds/0/contexts/0/targets/nr_targets
+    # echo $(pidof <workload>) > kdamonds/0/contexts/0/targets/0/pid_target
     # echo on > kdamonds/0/state
 
 Files Hierarchy
@@ -366,12 +366,12 @@ memory rate becomes larger than 60%, or lower than 30%". ::
     # echo 1 > kdamonds/0/contexts/0/schemes/nr_schemes
     # cd kdamonds/0/contexts/0/schemes/0
     # # set the basic access pattern and the action
-    # echo 4096 > access_patterns/sz/min
-    # echo 8192 > access_patterns/sz/max
-    # echo 0 > access_patterns/nr_accesses/min
-    # echo 5 > access_patterns/nr_accesses/max
-    # echo 10 > access_patterns/age/min
-    # echo 20 > access_patterns/age/max
+    # echo 4096 > access_pattern/sz/min
+    # echo 8192 > access_pattern/sz/max
+    # echo 0 > access_pattern/nr_accesses/min
+    # echo 5 > access_pattern/nr_accesses/max
+    # echo 10 > access_pattern/age/min
+    # echo 20 > access_pattern/age/max
     # echo pageout > action
     # # set quotas
     # echo 10 > quotas/ms
index 805f228..60d4416 100644 (file)
@@ -271,7 +271,7 @@ poll cycle or the number of packets processed reaches netdev_budget.
 netdev_max_backlog
 ------------------
 
-Maximum number  of  packets,  queued  on  the  INPUT  side, when the interface
+Maximum number of packets, queued on the INPUT side, when the interface
 receives packets faster than kernel can process them.
 
 netdev_rss_key
index 52b75a2..311021f 100644 (file)
@@ -242,44 +242,34 @@ HWCAP2_MTE3
     by Documentation/arm64/memory-tagging-extension.rst.
 
 HWCAP2_SME
-
     Functionality implied by ID_AA64PFR1_EL1.SME == 0b0001, as described
     by Documentation/arm64/sme.rst.
 
 HWCAP2_SME_I16I64
-
     Functionality implied by ID_AA64SMFR0_EL1.I16I64 == 0b1111.
 
 HWCAP2_SME_F64F64
-
     Functionality implied by ID_AA64SMFR0_EL1.F64F64 == 0b1.
 
 HWCAP2_SME_I8I32
-
     Functionality implied by ID_AA64SMFR0_EL1.I8I32 == 0b1111.
 
 HWCAP2_SME_F16F32
-
     Functionality implied by ID_AA64SMFR0_EL1.F16F32 == 0b1.
 
 HWCAP2_SME_B16F32
-
     Functionality implied by ID_AA64SMFR0_EL1.B16F32 == 0b1.
 
 HWCAP2_SME_F32F32
-
     Functionality implied by ID_AA64SMFR0_EL1.F32F32 == 0b1.
 
 HWCAP2_SME_FA64
-
     Functionality implied by ID_AA64SMFR0_EL1.FA64 == 0b1.
 
 HWCAP2_WFXT
-
     Functionality implied by ID_AA64ISAR2_EL1.WFXT == 0b0010.
 
 HWCAP2_EBF16
-
     Functionality implied by ID_AA64ISAR1_EL1.BF16 == 0b0010.
 
 4. Unused AT_HWCAP bits
index 33b04db..fda97b3 100644 (file)
@@ -52,6 +52,8 @@ stable kernels.
 | Allwinner      | A64/R18         | UNKNOWN1        | SUN50I_ERRATUM_UNKNOWN1     |
 +----------------+-----------------+-----------------+-----------------------------+
 +----------------+-----------------+-----------------+-----------------------------+
+| ARM            | Cortex-A510     | #2457168        | ARM64_ERRATUM_2457168       |
++----------------+-----------------+-----------------+-----------------------------+
 | ARM            | Cortex-A510     | #2064142        | ARM64_ERRATUM_2064142       |
 +----------------+-----------------+-----------------+-----------------------------+
 | ARM            | Cortex-A510     | #2038923        | ARM64_ERRATUM_2038923       |
index d8b101c..edea465 100644 (file)
@@ -58,13 +58,11 @@ Like with atomic_t, the rule of thumb is:
 
  - RMW operations that have a return value are fully ordered.
 
- - RMW operations that are conditional are unordered on FAILURE,
-   otherwise the above rules apply. In the case of test_and_set_bit_lock(),
-   if the bit in memory is unchanged by the operation then it is deemed to have
-   failed.
+ - RMW operations that are conditional are fully ordered.
 
-Except for a successful test_and_set_bit_lock() which has ACQUIRE semantics and
-clear_bit_unlock() which has RELEASE semantics.
+Except for a successful test_and_set_bit_lock() which has ACQUIRE semantics,
+clear_bit_unlock() which has RELEASE semantics and test_bit_acquire which has
+ACQUIRE semantics.
 
 Since a platform only has a single means of achieving atomic operations
 the same barriers as for atomic_t are used, see atomic_t.txt.
index 934727e..255384d 100644 (file)
@@ -86,6 +86,7 @@ if major >= 3:
             "__used",
             "__weak",
             "noinline",
+            "__fix_address",
 
             # include/linux/memblock.h:
             "__init_memblock",
index 2d34f3c..8d2c6d7 100644 (file)
@@ -214,6 +214,7 @@ patternProperties:
       - polling-delay
       - polling-delay-passive
       - thermal-sensors
+      - trips
 
     additionalProperties: false
 
index 2a29cbe..9707e03 100644 (file)
 
 % Translations have Asian (CJK) characters which are only displayed if
 % xeCJK is used
+\usepackage{ifthen}
+\newboolean{enablecjk}
+\setboolean{enablecjk}{false}
 \IfFontExistsTF{Noto Sans CJK SC}{
-    % Load xeCJK when CJK font is available
+    \IfFileExists{xeCJK.sty}{
+       \setboolean{enablecjk}{true}
+    }{}
+}{}
+\ifthenelse{\boolean{enablecjk}}{
+    % Load xeCJK when both the Noto Sans CJK font and xeCJK.sty are available.
     \usepackage{xeCJK}
     % Noto CJK fonts don't provide slant shape. [AutoFakeSlant] permits
     % its emulation.
     % Inactivate CJK after tableofcontents
     \apptocmd{\sphinxtableofcontents}{\kerneldocCJKoff}{}{}
     \xeCJKsetup{CJKspace = true}% For inter-phrase space of Korean TOC
-}{ % No CJK font found
+}{ % Don't enable CJK
     % Custom macros to on/off CJK and switch CJK fonts (Dummy)
     \newcommand{\kerneldocCJKon}{}
     \newcommand{\kerneldocCJKoff}{}
     %% and ignore the argument (#1) in their definitions, whole contents of
     %% CJK chapters can be ignored.
     \newcommand{\kerneldocBeginSC}[1]{%
-       %% Put a note on missing CJK fonts in place of zh_CN translation.
-       \begin{sphinxadmonition}{note}{Note on missing fonts:}
+       %% Put a note on missing CJK fonts or the xecjk package in place of
+       %% zh_CN translation.
+       \begin{sphinxadmonition}{note}{Note on missing fonts and a package:}
            Translations of Simplified Chinese (zh\_CN), Traditional Chinese
            (zh\_TW), Korean (ko\_KR), and Japanese (ja\_JP) were skipped
-           due to the lack of suitable font families.
+           due to the lack of suitable font families and/or the texlive-xecjk
+           package.
 
            If you want them, please install ``Noto Sans CJK'' font families
-           by following instructions from
+           along with the texlive-xecjk package by following instructions from
            \sphinxcode{./scripts/sphinx-pre-install}.
            Having optional ``Noto Serif CJK'' font families will improve
            the looks of those translations.
index 66ce0d8..04deb77 100644 (file)
@@ -35,8 +35,7 @@ Linux カーネルに変更を加えたいと思っている個人又は会社
 てもらえやすくする提案を集めたものです。
 
 コードを投稿する前に、Documentation/process/submit-checklist.rst の項目リストに目
-を通してチェックしてください。もしあなたがドライバーを投稿しようとし
-ているなら、Documentation/process/submitting-drivers.rst にも目を通してください。
+を通してチェックしてください。
 
 --------------------------------------------
 セクション1 パッチの作り方と送り方
index 9d7f64d..5895173 100644 (file)
@@ -3612,6 +3612,7 @@ F:        include/linux/find.h
 F:     include/linux/nodemask.h
 F:     lib/bitmap.c
 F:     lib/cpumask.c
+F:     lib/cpumask_kunit.c
 F:     lib/find_bit.c
 F:     lib/find_bit_benchmark.c
 F:     lib/test_bitmap.c
@@ -3679,6 +3680,7 @@ F:        Documentation/networking/bonding.rst
 F:     drivers/net/bonding/
 F:     include/net/bond*
 F:     include/uapi/linux/if_bonding.h
+F:     tools/testing/selftests/drivers/net/bonding/
 
 BOSCH SENSORTEC BMA400 ACCELEROMETER IIO DRIVER
 M:     Dan Robertson <dan@dlrobertson.com>
@@ -9781,7 +9783,7 @@ M:        Christian Brauner <brauner@kernel.org>
 M:     Seth Forshee <sforshee@kernel.org>
 L:     linux-fsdevel@vger.kernel.org
 S:     Maintained
-T:     git git://git.kernel.org/pub/scm/linux/kernel/git/brauner/linux.git
+T:     git://git.kernel.org/pub/scm/linux/kernel/git/vfs/idmapping.git
 F:     Documentation/filesystems/idmappings.rst
 F:     tools/testing/selftests/mount_setattr/
 F:     include/linux/mnt_idmapping.h
@@ -10658,6 +10660,7 @@ T:      git git://git.kernel.dk/linux-block
 T:     git git://git.kernel.dk/liburing
 F:     io_uring/
 F:     include/linux/io_uring.h
+F:     include/linux/io_uring_types.h
 F:     include/uapi/linux/io_uring.h
 F:     tools/io_uring/
 
index c7705f7..952d354 100644 (file)
--- a/Makefile
+++ b/Makefile
@@ -2,7 +2,7 @@
 VERSION = 6
 PATCHLEVEL = 0
 SUBLEVEL = 0
-EXTRAVERSION = -rc2
+EXTRAVERSION = -rc3
 NAME = Hurr durr I'ma ninja sloth
 
 # *DOCUMENTATION*
index 492c771..bafb1c1 100644 (file)
@@ -283,11 +283,8 @@ arch___test_and_change_bit(unsigned long nr, volatile unsigned long *addr)
        return (old & mask) != 0;
 }
 
-static __always_inline bool
-arch_test_bit(unsigned long nr, const volatile unsigned long *addr)
-{
-       return (1UL & (((const int *) addr)[nr >> 5] >> (nr & 31))) != 0UL;
-}
+#define arch_test_bit generic_test_bit
+#define arch_test_bit_acquire generic_test_bit_acquire
 
 /*
  * ffz = Find First Zero in word. Undefined if no zero exists,
index 571cc23..9fb9fff 100644 (file)
@@ -917,6 +917,23 @@ config ARM64_ERRATUM_1902691
 
          If unsure, say Y.
 
+config ARM64_ERRATUM_2457168
+       bool "Cortex-A510: 2457168: workaround for AMEVCNTR01 incrementing incorrectly"
+       depends on ARM64_AMU_EXTN
+       default y
+       help
+         This option adds the workaround for ARM Cortex-A510 erratum 2457168.
+
+         The AMU counter AMEVCNTR01 (constant counter) should increment at the same rate
+         as the system counter. On affected Cortex-A510 cores AMEVCNTR01 increments
+         incorrectly giving a significantly higher output value.
+
+         Work around this problem by returning 0 when reading the affected counter in
+         key locations that results in disabling all users of this counter. This effect
+         is the same to firmware disabling affected counters.
+
+         If unsure, say Y.
+
 config CAVIUM_ERRATUM_22375
        bool "Cavium erratum 22375, 24313"
        default y
index ca9b487..34256bd 100644 (file)
@@ -71,7 +71,7 @@ static __always_inline int icache_is_vpipt(void)
 
 static inline u32 cache_type_cwg(void)
 {
-       return (read_cpuid_cachetype() >> CTR_EL0_CWG_SHIFT) & CTR_EL0_CWG_MASK;
+       return SYS_FIELD_GET(CTR_EL0, CWG, read_cpuid_cachetype());
 }
 
 #define __read_mostly __section(".data..read_mostly")
index 9bb1873..6f86b7a 100644 (file)
@@ -153,7 +153,7 @@ struct vl_info {
 
 #ifdef CONFIG_ARM64_SVE
 
-extern void sve_alloc(struct task_struct *task);
+extern void sve_alloc(struct task_struct *task, bool flush);
 extern void fpsimd_release_task(struct task_struct *task);
 extern void fpsimd_sync_to_sve(struct task_struct *task);
 extern void fpsimd_force_sync_to_sve(struct task_struct *task);
@@ -256,7 +256,7 @@ size_t sve_state_size(struct task_struct const *task);
 
 #else /* ! CONFIG_ARM64_SVE */
 
-static inline void sve_alloc(struct task_struct *task) { }
+static inline void sve_alloc(struct task_struct *task, bool flush) { }
 static inline void fpsimd_release_task(struct task_struct *task) { }
 static inline void sve_sync_to_fpsimd(struct task_struct *task) { }
 static inline void sve_sync_from_fpsimd_zeropad(struct task_struct *task) { }
index 6437df6..f4af547 100644 (file)
@@ -3,6 +3,8 @@
 #ifndef __ARM64_ASM_SETUP_H
 #define __ARM64_ASM_SETUP_H
 
+#include <linux/string.h>
+
 #include <uapi/asm/setup.h>
 
 void *get_early_fdt_ptr(void);
@@ -14,4 +16,19 @@ void early_fdt_map(u64 dt_phys);
 extern phys_addr_t __fdt_pointer __initdata;
 extern u64 __cacheline_aligned boot_args[4];
 
+static inline bool arch_parse_debug_rodata(char *arg)
+{
+       extern bool rodata_enabled;
+       extern bool rodata_full;
+
+       if (arg && !strcmp(arg, "full")) {
+               rodata_enabled = true;
+               rodata_full = true;
+               return true;
+       }
+
+       return false;
+}
+#define arch_parse_debug_rodata arch_parse_debug_rodata
+
 #endif
index 7c71358..818df93 100644 (file)
 
 #else
 
+#include <linux/bitfield.h>
 #include <linux/build_bug.h>
 #include <linux/types.h>
 #include <asm/alternative.h>
        par;                                                            \
 })
 
-#endif
-
 #define SYS_FIELD_GET(reg, field, val)         \
                 FIELD_GET(reg##_##field##_MASK, val)
 
 #define SYS_FIELD_PREP_ENUM(reg, field, val)           \
                 FIELD_PREP(reg##_##field##_MASK, reg##_##field##_##val)
 
+#endif
+
 #endif /* __ASM_SYSREG_H */
index 587543c..97c42be 100644 (file)
@@ -45,7 +45,8 @@ static void ci_leaf_init(struct cacheinfo *this_leaf,
 
 int init_cache_level(unsigned int cpu)
 {
-       unsigned int ctype, level, leaves, fw_level;
+       unsigned int ctype, level, leaves;
+       int fw_level;
        struct cpu_cacheinfo *this_cpu_ci = get_cpu_cacheinfo(cpu);
 
        for (level = 1, leaves = 0; level <= MAX_CACHE_LEVEL; level++) {
@@ -63,6 +64,9 @@ int init_cache_level(unsigned int cpu)
        else
                fw_level = acpi_find_last_cache_level(cpu);
 
+       if (fw_level < 0)
+               return fw_level;
+
        if (level < fw_level) {
                /*
                 * some external caches not specified in CLIDR_EL1
index 7e6289e..53b973b 100644 (file)
@@ -208,6 +208,8 @@ static const struct arm64_cpu_capabilities arm64_repeat_tlbi_list[] = {
 #ifdef CONFIG_ARM64_ERRATUM_1286807
        {
                ERRATA_MIDR_RANGE(MIDR_CORTEX_A76, 0, 0, 3, 0),
+       },
+       {
                /* Kryo4xx Gold (rcpe to rfpe) => (r0p0 to r3p0) */
                ERRATA_MIDR_RANGE(MIDR_QCOM_KRYO_4XX_GOLD, 0xc, 0xe, 0xf, 0xe),
        },
@@ -654,6 +656,16 @@ const struct arm64_cpu_capabilities arm64_errata[] = {
                ERRATA_MIDR_REV_RANGE(MIDR_CORTEX_A510, 0, 0, 2)
        },
 #endif
+#ifdef CONFIG_ARM64_ERRATUM_2457168
+       {
+               .desc = "ARM erratum 2457168",
+               .capability = ARM64_WORKAROUND_2457168,
+               .type = ARM64_CPUCAP_WEAK_LOCAL_CPU_FEATURE,
+
+               /* Cortex-A510 r0p0-r1p1 */
+               CAP_MIDR_RANGE(MIDR_CORTEX_A510, 0, 0, 1, 1)
+       },
+#endif
 #ifdef CONFIG_ARM64_ERRATUM_2038923
        {
                .desc = "ARM erratum 2038923",
index 907401e..af4de81 100644 (file)
@@ -1870,7 +1870,10 @@ static void cpu_amu_enable(struct arm64_cpu_capabilities const *cap)
                pr_info("detected CPU%d: Activity Monitors Unit (AMU)\n",
                        smp_processor_id());
                cpumask_set_cpu(smp_processor_id(), &amu_cpus);
-               update_freq_counters_refs();
+
+               /* 0 reference values signal broken/disabled counters */
+               if (!this_cpu_has_cap(ARM64_WORKAROUND_2457168))
+                       update_freq_counters_refs();
        }
 }
 
index 254fe31..2d73b3e 100644 (file)
@@ -502,7 +502,7 @@ tsk .req    x28             // current thread_info
 SYM_CODE_START(vectors)
        kernel_ventry   1, t, 64, sync          // Synchronous EL1t
        kernel_ventry   1, t, 64, irq           // IRQ EL1t
-       kernel_ventry   1, t, 64, fiq           // FIQ EL1h
+       kernel_ventry   1, t, 64, fiq           // FIQ EL1t
        kernel_ventry   1, t, 64, error         // Error EL1t
 
        kernel_ventry   1, h, 64, sync          // Synchronous EL1h
index dd63ffc..23834d9 100644 (file)
@@ -715,10 +715,12 @@ size_t sve_state_size(struct task_struct const *task)
  * do_sve_acc() case, there is no ABI requirement to hide stale data
  * written previously be task.
  */
-void sve_alloc(struct task_struct *task)
+void sve_alloc(struct task_struct *task, bool flush)
 {
        if (task->thread.sve_state) {
-               memset(task->thread.sve_state, 0, sve_state_size(task));
+               if (flush)
+                       memset(task->thread.sve_state, 0,
+                              sve_state_size(task));
                return;
        }
 
@@ -1388,7 +1390,7 @@ void do_sve_acc(unsigned long esr, struct pt_regs *regs)
                return;
        }
 
-       sve_alloc(current);
+       sve_alloc(current, true);
        if (!current->thread.sve_state) {
                force_sig(SIGKILL);
                return;
@@ -1439,7 +1441,7 @@ void do_sme_acc(unsigned long esr, struct pt_regs *regs)
                return;
        }
 
-       sve_alloc(current);
+       sve_alloc(current, false);
        sme_alloc(current);
        if (!current->thread.sve_state || !current->thread.za_state) {
                force_sig(SIGKILL);
@@ -1460,17 +1462,6 @@ void do_sme_acc(unsigned long esr, struct pt_regs *regs)
                fpsimd_bind_task_to_cpu();
        }
 
-       /*
-        * If SVE was not already active initialise the SVE registers,
-        * any non-shared state between the streaming and regular SVE
-        * registers is architecturally guaranteed to be zeroed when
-        * we enter streaming mode.  We do not need to initialize ZA
-        * since ZA must be disabled at this point and enabling ZA is
-        * architecturally defined to zero ZA.
-        */
-       if (system_supports_sve() && !test_thread_flag(TIF_SVE))
-               sve_init_regs();
-
        put_cpu_fpsimd_context();
 }
 
index 6c3855e..17bff6e 100644 (file)
@@ -94,11 +94,9 @@ asmlinkage u64 kaslr_early_init(void *fdt)
 
        seed = get_kaslr_seed(fdt);
        if (!seed) {
-#ifdef CONFIG_ARCH_RANDOM
-                if (!__early_cpu_has_rndr() ||
-                    !__arm64_rndr((unsigned long *)&seed))
-#endif
-               return 0;
+               if (!__early_cpu_has_rndr() ||
+                   !__arm64_rndr((unsigned long *)&seed))
+                       return 0;
        }
 
        /*
index 21da831..eb7c08d 100644 (file)
@@ -882,7 +882,7 @@ static int sve_set_common(struct task_struct *target,
                 * state and ensure there's storage.
                 */
                if (target->thread.svcr != old_svcr)
-                       sve_alloc(target);
+                       sve_alloc(target, true);
        }
 
        /* Registers: FPSIMD-only case */
@@ -912,7 +912,7 @@ static int sve_set_common(struct task_struct *target,
                goto out;
        }
 
-       sve_alloc(target);
+       sve_alloc(target, true);
        if (!target->thread.sve_state) {
                ret = -ENOMEM;
                clear_tsk_thread_flag(target, TIF_SVE);
@@ -1082,7 +1082,7 @@ static int za_set(struct task_struct *target,
 
        /* Ensure there is some SVE storage for streaming mode */
        if (!target->thread.sve_state) {
-               sve_alloc(target);
+               sve_alloc(target, false);
                if (!target->thread.sve_state) {
                        clear_thread_flag(TIF_SME);
                        ret = -ENOMEM;
index 3e6d035..9ad911f 100644 (file)
@@ -91,7 +91,7 @@ static size_t sigframe_size(struct rt_sigframe_user_layout const *user)
  * not taken into account.  This limit is not a guarantee and is
  * NOT ABI.
  */
-#define SIGFRAME_MAXSZ SZ_64K
+#define SIGFRAME_MAXSZ SZ_256K
 
 static int __sigframe_alloc(struct rt_sigframe_user_layout *user,
                            unsigned long *offset, size_t size, bool extend)
@@ -310,7 +310,7 @@ static int restore_sve_fpsimd_context(struct user_ctxs *user)
        fpsimd_flush_task_state(current);
        /* From now, fpsimd_thread_switch() won't touch thread.sve_state */
 
-       sve_alloc(current);
+       sve_alloc(current, true);
        if (!current->thread.sve_state) {
                clear_thread_flag(TIF_SVE);
                return -ENOMEM;
@@ -926,6 +926,16 @@ static void setup_return(struct pt_regs *regs, struct k_sigaction *ka,
 
        /* Signal handlers are invoked with ZA and streaming mode disabled */
        if (system_supports_sme()) {
+               /*
+                * If we were in streaming mode the saved register
+                * state was SVE but we will exit SM and use the
+                * FPSIMD register state - flush the saved FPSIMD
+                * register state in case it gets loaded.
+                */
+               if (current->thread.svcr & SVCR_SM_MASK)
+                       memset(&current->thread.uw.fpsimd_state, 0,
+                              sizeof(current->thread.uw.fpsimd_state));
+
                current->thread.svcr &= ~(SVCR_ZA_MASK |
                                          SVCR_SM_MASK);
                sme_smstop();
index 869ffc4..ad2bfc7 100644 (file)
@@ -296,12 +296,25 @@ core_initcall(init_amu_fie);
 
 static void cpu_read_corecnt(void *val)
 {
+       /*
+        * A value of 0 can be returned if the current CPU does not support AMUs
+        * or if the counter is disabled for this CPU. A return value of 0 at
+        * counter read is properly handled as an error case by the users of the
+        * counter.
+        */
        *(u64 *)val = read_corecnt();
 }
 
 static void cpu_read_constcnt(void *val)
 {
-       *(u64 *)val = read_constcnt();
+       /*
+        * Return 0 if the current CPU is affected by erratum 2457168. A value
+        * of 0 is also returned if the current CPU does not support AMUs or if
+        * the counter is disabled. A return value of 0 at counter read is
+        * properly handled as an error case by the users of the counter.
+        */
+       *(u64 *)val = this_cpu_has_cap(ARM64_WORKAROUND_2457168) ?
+                     0UL : read_constcnt();
 }
 
 static inline
@@ -328,7 +341,22 @@ int counters_read_on_cpu(int cpu, smp_call_func_t func, u64 *val)
  */
 bool cpc_ffh_supported(void)
 {
-       return freq_counters_valid(get_cpu_with_amu_feat());
+       int cpu = get_cpu_with_amu_feat();
+
+       /*
+        * FFH is considered supported if there is at least one present CPU that
+        * supports AMUs. Using FFH to read core and reference counters for CPUs
+        * that do not support AMUs, have counters disabled or that are affected
+        * by errata, will result in a return value of 0.
+        *
+        * This is done to allow any enabled and valid counters to be read
+        * through FFH, knowing that potentially returning 0 as counter value is
+        * properly handled by the users of these counters.
+        */
+       if ((cpu >= nr_cpu_ids) || !cpumask_test_cpu(cpu, cpu_present_mask))
+               return false;
+
+       return true;
 }
 
 int cpc_read_ffh(int cpu, struct cpc_reg *reg, u64 *val)
index db7c4e6..e7ad445 100644 (file)
@@ -642,24 +642,6 @@ static void __init map_kernel_segment(pgd_t *pgdp, void *va_start, void *va_end,
        vm_area_add_early(vma);
 }
 
-static int __init parse_rodata(char *arg)
-{
-       int ret = strtobool(arg, &rodata_enabled);
-       if (!ret) {
-               rodata_full = false;
-               return 0;
-       }
-
-       /* permit 'full' in addition to boolean options */
-       if (strcmp(arg, "full"))
-               return -EINVAL;
-
-       rodata_enabled = true;
-       rodata_full = true;
-       return 0;
-}
-early_param("rodata", parse_rodata);
-
 #ifdef CONFIG_UNMAP_KERNEL_AT_EL0
 static int __init map_entry_trampoline(void)
 {
index 7796537..63b2484 100644 (file)
@@ -67,6 +67,7 @@ WORKAROUND_1902691
 WORKAROUND_2038923
 WORKAROUND_2064142
 WORKAROUND_2077057
+WORKAROUND_2457168
 WORKAROUND_TRBE_OVERWRITE_FILL_MODE
 WORKAROUND_TSB_FLUSH_FAILURE
 WORKAROUND_TRBE_WRITE_OUT_OF_RANGE
index da50047..160d8f3 100644 (file)
@@ -179,6 +179,21 @@ arch_test_bit(unsigned long nr, const volatile unsigned long *addr)
        return retval;
 }
 
+static __always_inline bool
+arch_test_bit_acquire(unsigned long nr, const volatile unsigned long *addr)
+{
+       int retval;
+
+       asm volatile(
+       "{P0 = tstbit(%1,%2); if (P0.new) %0 = #1; if (!P0.new) %0 = #0;}\n"
+       : "=&r" (retval)
+       : "r" (addr[BIT_WORD(nr)]), "r" (nr % BITS_PER_LONG)
+       : "p0", "memory"
+       );
+
+       return retval;
+}
+
 /*
  * ffz - find first zero in word.
  * @word: The word to search
index 9f62af7..1accb78 100644 (file)
@@ -331,11 +331,8 @@ arch___test_and_change_bit(unsigned long nr, volatile unsigned long *addr)
        return (old & bit) != 0;
 }
 
-static __always_inline bool
-arch_test_bit(unsigned long nr, const volatile unsigned long *addr)
-{
-       return 1 & (((const volatile __u32 *) addr)[nr >> 5] >> (nr & 31));
-}
+#define arch_test_bit generic_test_bit
+#define arch_test_bit_acquire generic_test_bit_acquire
 
 /**
  * ffz - find the first zero bit in a long word
index 4abc9a2..26aeb14 100644 (file)
@@ -111,6 +111,7 @@ config LOONGARCH
        select PCI_ECAM if ACPI
        select PCI_LOONGSON
        select PCI_MSI_ARCH_FALLBACKS
+       select PCI_QUIRKS
        select PERF_USE_VMALLOC
        select RTC_LIB
        select SMP
index b91e073..d342935 100644 (file)
@@ -109,4 +109,20 @@ extern unsigned long vm_map_base;
  */
 #define PHYSADDR(a)            ((_ACAST64_(a)) & TO_PHYS_MASK)
 
+/*
+ * On LoongArch, I/O ports mappring is following:
+ *
+ *              |         ....          |
+ *              |-----------------------|
+ *              | pci io ports(16K~32M) |
+ *              |-----------------------|
+ *              | isa io ports(0  ~16K) |
+ * PCI_IOBASE ->|-----------------------|
+ *              |         ....          |
+ */
+#define PCI_IOBASE     ((void __iomem *)(vm_map_base + (2 * PAGE_SIZE)))
+#define PCI_IOSIZE     SZ_32M
+#define ISA_IOSIZE     SZ_16K
+#define IO_SPACE_LIMIT (PCI_IOSIZE - 1)
+
 #endif /* _ASM_ADDRSPACE_H */
index 0a9b0fa..ae19e33 100644 (file)
@@ -5,8 +5,9 @@
 #ifndef __ASM_CMPXCHG_H
 #define __ASM_CMPXCHG_H
 
-#include <asm/barrier.h>
+#include <linux/bits.h>
 #include <linux/build_bug.h>
+#include <asm/barrier.h>
 
 #define __xchg_asm(amswap_db, m, val)          \
 ({                                             \
                __ret;                          \
 })
 
+static inline unsigned int __xchg_small(volatile void *ptr, unsigned int val,
+                                       unsigned int size)
+{
+       unsigned int shift;
+       u32 old32, mask, temp;
+       volatile u32 *ptr32;
+
+       /* Mask value to the correct size. */
+       mask = GENMASK((size * BITS_PER_BYTE) - 1, 0);
+       val &= mask;
+
+       /*
+        * Calculate a shift & mask that correspond to the value we wish to
+        * exchange within the naturally aligned 4 byte integerthat includes
+        * it.
+        */
+       shift = (unsigned long)ptr & 0x3;
+       shift *= BITS_PER_BYTE;
+       mask <<= shift;
+
+       /*
+        * Calculate a pointer to the naturally aligned 4 byte integer that
+        * includes our byte of interest, and load its value.
+        */
+       ptr32 = (volatile u32 *)((unsigned long)ptr & ~0x3);
+
+       asm volatile (
+       "1:     ll.w            %0, %3          \n"
+       "       andn            %1, %0, %z4     \n"
+       "       or              %1, %1, %z5     \n"
+       "       sc.w            %1, %2          \n"
+       "       beqz            %1, 1b          \n"
+       : "=&r" (old32), "=&r" (temp), "=ZC" (*ptr32)
+       : "ZC" (*ptr32), "Jr" (mask), "Jr" (val << shift)
+       : "memory");
+
+       return (old32 & mask) >> shift;
+}
+
 static inline unsigned long __xchg(volatile void *ptr, unsigned long x,
                                   int size)
 {
        switch (size) {
+       case 1:
+       case 2:
+               return __xchg_small(ptr, x, size);
+
        case 4:
                return __xchg_asm("amswap_db.w", (volatile u32 *)ptr, (u32)x);
 
@@ -67,10 +111,62 @@ static inline unsigned long __xchg(volatile void *ptr, unsigned long x,
        __ret;                                                          \
 })
 
+static inline unsigned int __cmpxchg_small(volatile void *ptr, unsigned int old,
+                                          unsigned int new, unsigned int size)
+{
+       unsigned int shift;
+       u32 old32, mask, temp;
+       volatile u32 *ptr32;
+
+       /* Mask inputs to the correct size. */
+       mask = GENMASK((size * BITS_PER_BYTE) - 1, 0);
+       old &= mask;
+       new &= mask;
+
+       /*
+        * Calculate a shift & mask that correspond to the value we wish to
+        * compare & exchange within the naturally aligned 4 byte integer
+        * that includes it.
+        */
+       shift = (unsigned long)ptr & 0x3;
+       shift *= BITS_PER_BYTE;
+       old <<= shift;
+       new <<= shift;
+       mask <<= shift;
+
+       /*
+        * Calculate a pointer to the naturally aligned 4 byte integer that
+        * includes our byte of interest, and load its value.
+        */
+       ptr32 = (volatile u32 *)((unsigned long)ptr & ~0x3);
+
+       asm volatile (
+       "1:     ll.w            %0, %3          \n"
+       "       and             %1, %0, %z4     \n"
+       "       bne             %1, %z5, 2f     \n"
+       "       andn            %1, %0, %z4     \n"
+       "       or              %1, %1, %z6     \n"
+       "       sc.w            %1, %2          \n"
+       "       beqz            %1, 1b          \n"
+       "       b               3f              \n"
+       "2:                                     \n"
+       __WEAK_LLSC_MB
+       "3:                                     \n"
+       : "=&r" (old32), "=&r" (temp), "=ZC" (*ptr32)
+       : "ZC" (*ptr32), "Jr" (mask), "Jr" (old), "Jr" (new)
+       : "memory");
+
+       return (old32 & mask) >> shift;
+}
+
 static inline unsigned long __cmpxchg(volatile void *ptr, unsigned long old,
                                      unsigned long new, unsigned int size)
 {
        switch (size) {
+       case 1:
+       case 2:
+               return __cmpxchg_small(ptr, old, new, size);
+
        case 4:
                return __cmpxchg_asm("ll.w", "sc.w", (volatile u32 *)ptr,
                                     (u32)old, new);
index 8845997..999944e 100644 (file)
@@ -7,35 +7,16 @@
 
 #define ARCH_HAS_IOREMAP_WC
 
-#include <linux/compiler.h>
 #include <linux/kernel.h>
 #include <linux/types.h>
 
 #include <asm/addrspace.h>
-#include <asm/bug.h>
-#include <asm/byteorder.h>
 #include <asm/cpu.h>
 #include <asm/page.h>
 #include <asm/pgtable-bits.h>
 #include <asm/string.h>
 
 /*
- * On LoongArch, I/O ports mappring is following:
- *
- *              |         ....          |
- *              |-----------------------|
- *              | pci io ports(64K~32M) |
- *              |-----------------------|
- *              | isa io ports(0  ~16K) |
- * PCI_IOBASE ->|-----------------------|
- *              |         ....          |
- */
-#define PCI_IOBASE     ((void __iomem *)(vm_map_base + (2 * PAGE_SIZE)))
-#define PCI_IOSIZE     SZ_32M
-#define ISA_IOSIZE     SZ_16K
-#define IO_SPACE_LIMIT (PCI_IOSIZE - 1)
-
-/*
  * Change "struct page" to physical address.
  */
 #define page_to_phys(page)     ((phys_addr_t)page_to_pfn(page) << PAGE_SHIFT)
index a37324a..53f284a 100644 (file)
@@ -95,7 +95,7 @@ static inline int pfn_valid(unsigned long pfn)
 
 #endif
 
-#define virt_to_pfn(kaddr)     PFN_DOWN(virt_to_phys((void *)(kaddr)))
+#define virt_to_pfn(kaddr)     PFN_DOWN(PHYSADDR(kaddr))
 #define virt_to_page(kaddr)    pfn_to_page(virt_to_pfn(kaddr))
 
 extern int __virt_addr_valid(volatile void *kaddr);
index e6569f1..0bd6b01 100644 (file)
@@ -123,6 +123,10 @@ static inline unsigned long __percpu_xchg(void *ptr, unsigned long val,
                                                int size)
 {
        switch (size) {
+       case 1:
+       case 2:
+               return __xchg_small((volatile void *)ptr, val, size);
+
        case 4:
                return __xchg_asm("amswap.w", (volatile u32 *)ptr, (u32)val);
 
@@ -204,9 +208,13 @@ do {                                                                       \
 #define this_cpu_write_4(pcp, val) _percpu_write(pcp, val)
 #define this_cpu_write_8(pcp, val) _percpu_write(pcp, val)
 
+#define this_cpu_xchg_1(pcp, val) _percpu_xchg(pcp, val)
+#define this_cpu_xchg_2(pcp, val) _percpu_xchg(pcp, val)
 #define this_cpu_xchg_4(pcp, val) _percpu_xchg(pcp, val)
 #define this_cpu_xchg_8(pcp, val) _percpu_xchg(pcp, val)
 
+#define this_cpu_cmpxchg_1(ptr, o, n) _protect_cmpxchg_local(ptr, o, n)
+#define this_cpu_cmpxchg_2(ptr, o, n) _protect_cmpxchg_local(ptr, o, n)
 #define this_cpu_cmpxchg_4(ptr, o, n) _protect_cmpxchg_local(ptr, o, n)
 #define this_cpu_cmpxchg_8(ptr, o, n) _protect_cmpxchg_local(ptr, o, n)
 
index e03443a..8ea57e2 100644 (file)
@@ -59,7 +59,6 @@
 #include <linux/mm_types.h>
 #include <linux/mmzone.h>
 #include <asm/fixmap.h>
-#include <asm/io.h>
 
 struct mm_struct;
 struct vm_area_struct;
@@ -145,7 +144,7 @@ static inline void set_p4d(p4d_t *p4d, p4d_t p4dval)
        *p4d = p4dval;
 }
 
-#define p4d_phys(p4d)          virt_to_phys((void *)p4d_val(p4d))
+#define p4d_phys(p4d)          PHYSADDR(p4d_val(p4d))
 #define p4d_page(p4d)          (pfn_to_page(p4d_phys(p4d) >> PAGE_SHIFT))
 
 #endif
@@ -188,7 +187,7 @@ static inline pmd_t *pud_pgtable(pud_t pud)
 
 #define set_pud(pudptr, pudval) do { *(pudptr) = (pudval); } while (0)
 
-#define pud_phys(pud)          virt_to_phys((void *)pud_val(pud))
+#define pud_phys(pud)          PHYSADDR(pud_val(pud))
 #define pud_page(pud)          (pfn_to_page(pud_phys(pud) >> PAGE_SHIFT))
 
 #endif
@@ -221,7 +220,7 @@ static inline void pmd_clear(pmd_t *pmdp)
 
 #define set_pmd(pmdptr, pmdval) do { *(pmdptr) = (pmdval); } while (0)
 
-#define pmd_phys(pmd)          virt_to_phys((void *)pmd_val(pmd))
+#define pmd_phys(pmd)          PHYSADDR(pmd_val(pmd))
 
 #ifndef CONFIG_TRANSPARENT_HUGEPAGE
 #define pmd_page(pmd)          (pfn_to_page(pmd_phys(pmd) >> PAGE_SHIFT))
diff --git a/arch/loongarch/include/asm/reboot.h b/arch/loongarch/include/asm/reboot.h
deleted file mode 100644 (file)
index 5115174..0000000
+++ /dev/null
@@ -1,10 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0 */
-/*
- * Copyright (C) 2020-2022 Loongson Technology Corporation Limited
- */
-#ifndef _ASM_REBOOT_H
-#define _ASM_REBOOT_H
-
-extern void (*pm_restart)(void);
-
-#endif /* _ASM_REBOOT_H */
index 800c965..8c82021 100644 (file)
 #include <acpi/reboot.h>
 #include <asm/idle.h>
 #include <asm/loongarch.h>
-#include <asm/reboot.h>
 
-static void default_halt(void)
+void (*pm_power_off)(void);
+EXPORT_SYMBOL(pm_power_off);
+
+void machine_halt(void)
 {
+#ifdef CONFIG_SMP
+       preempt_disable();
+       smp_send_stop();
+#endif
        local_irq_disable();
        clear_csr_ecfg(ECFG0_IM);
 
@@ -30,18 +36,29 @@ static void default_halt(void)
        }
 }
 
-static void default_poweroff(void)
+void machine_power_off(void)
 {
+#ifdef CONFIG_SMP
+       preempt_disable();
+       smp_send_stop();
+#endif
+       do_kernel_power_off();
 #ifdef CONFIG_EFI
        efi.reset_system(EFI_RESET_SHUTDOWN, EFI_SUCCESS, 0, NULL);
 #endif
+
        while (true) {
                __arch_cpu_idle();
        }
 }
 
-static void default_restart(void)
+void machine_restart(char *command)
 {
+#ifdef CONFIG_SMP
+       preempt_disable();
+       smp_send_stop();
+#endif
+       do_kernel_restart(command);
 #ifdef CONFIG_EFI
        if (efi_capsule_pending(NULL))
                efi_reboot(REBOOT_WARM, NULL);
@@ -55,47 +72,3 @@ static void default_restart(void)
                __arch_cpu_idle();
        }
 }
-
-void (*pm_restart)(void);
-EXPORT_SYMBOL(pm_restart);
-
-void (*pm_power_off)(void);
-EXPORT_SYMBOL(pm_power_off);
-
-void machine_halt(void)
-{
-#ifdef CONFIG_SMP
-       preempt_disable();
-       smp_send_stop();
-#endif
-       default_halt();
-}
-
-void machine_power_off(void)
-{
-#ifdef CONFIG_SMP
-       preempt_disable();
-       smp_send_stop();
-#endif
-       pm_power_off();
-}
-
-void machine_restart(char *command)
-{
-#ifdef CONFIG_SMP
-       preempt_disable();
-       smp_send_stop();
-#endif
-       do_kernel_restart(command);
-       pm_restart();
-}
-
-static int __init loongarch_reboot_setup(void)
-{
-       pm_restart = default_restart;
-       pm_power_off = default_poweroff;
-
-       return 0;
-}
-
-arch_initcall(loongarch_reboot_setup);
index 605579b..1ccd536 100644 (file)
@@ -216,6 +216,10 @@ good_area:
                return;
        }
 
+       /* The fault is fully completed (including releasing mmap lock) */
+       if (fault & VM_FAULT_COMPLETED)
+               return;
+
        if (unlikely(fault & VM_FAULT_RETRY)) {
                flags |= FAULT_FLAG_TRIED;
 
index 52e40f0..381a569 100644 (file)
@@ -2,16 +2,9 @@
 /*
  * Copyright (C) 2020-2022 Loongson Technology Corporation Limited
  */
-#include <linux/compiler.h>
-#include <linux/elf-randomize.h>
-#include <linux/errno.h>
+#include <linux/export.h>
 #include <linux/mm.h>
 #include <linux/mman.h>
-#include <linux/export.h>
-#include <linux/personality.h>
-#include <linux/random.h>
-#include <linux/sched/signal.h>
-#include <linux/sched/mm.h>
 
 unsigned long shm_align_mask = PAGE_SIZE - 1;  /* Sane caches */
 EXPORT_SYMBOL(shm_align_mask);
@@ -120,6 +113,6 @@ int __virt_addr_valid(volatile void *kaddr)
        if ((vaddr < PAGE_OFFSET) || (vaddr >= vm_map_base))
                return 0;
 
-       return pfn_valid(PFN_DOWN(virt_to_phys(kaddr)));
+       return pfn_valid(PFN_DOWN(PHYSADDR(kaddr)));
 }
 EXPORT_SYMBOL_GPL(__virt_addr_valid);
index 43a0078..e02e775 100644 (file)
@@ -24,6 +24,8 @@ static __always_inline const struct vdso_pcpu_data *get_pcpu_data(void)
        return (struct vdso_pcpu_data *)(get_vdso_base() - VDSO_DATA_SIZE);
 }
 
+extern
+int __vdso_getcpu(unsigned int *cpu, unsigned int *node, struct getcpu_cache *unused);
 int __vdso_getcpu(unsigned int *cpu, unsigned int *node, struct getcpu_cache *unused)
 {
        int cpu_id;
index b1f4548..8f22863 100644 (file)
@@ -6,20 +6,23 @@
  */
 #include <linux/types.h>
 
-int __vdso_clock_gettime(clockid_t clock,
-                        struct __kernel_timespec *ts)
+extern
+int __vdso_clock_gettime(clockid_t clock, struct __kernel_timespec *ts);
+int __vdso_clock_gettime(clockid_t clock, struct __kernel_timespec *ts)
 {
        return __cvdso_clock_gettime(clock, ts);
 }
 
-int __vdso_gettimeofday(struct __kernel_old_timeval *tv,
-                       struct timezone *tz)
+extern
+int __vdso_gettimeofday(struct __kernel_old_timeval *tv, struct timezone *tz);
+int __vdso_gettimeofday(struct __kernel_old_timeval *tv, struct timezone *tz)
 {
        return __cvdso_gettimeofday(tv, tz);
 }
 
-int __vdso_clock_getres(clockid_t clock_id,
-                       struct __kernel_timespec *res)
+extern
+int __vdso_clock_getres(clockid_t clock_id, struct __kernel_timespec *res);
+int __vdso_clock_getres(clockid_t clock_id, struct __kernel_timespec *res)
 {
        return __cvdso_clock_getres(clock_id, res);
 }
index 470aed9..e984af7 100644 (file)
@@ -157,11 +157,8 @@ arch___change_bit(unsigned long nr, volatile unsigned long *addr)
        change_bit(nr, addr);
 }
 
-static __always_inline bool
-arch_test_bit(unsigned long nr, const volatile unsigned long *addr)
-{
-       return (addr[nr >> 5] & (1UL << (nr & 31))) != 0;
-}
+#define arch_test_bit generic_test_bit
+#define arch_test_bit_acquire generic_test_bit_acquire
 
 static inline int bset_reg_test_and_set_bit(int nr,
                                            volatile unsigned long *vaddr)
index 7f059cd..9aede24 100644 (file)
@@ -146,10 +146,10 @@ menu "Processor type and features"
 
 choice
        prompt "Processor type"
-       default PA7000
+       default PA7000 if "$(ARCH)" = "parisc"
 
 config PA7000
-       bool "PA7000/PA7100"
+       bool "PA7000/PA7100" if "$(ARCH)" = "parisc"
        help
          This is the processor type of your CPU.  This information is
          used for optimizing purposes.  In order to compile a kernel
@@ -160,21 +160,21 @@ config PA7000
          which is required on some machines.
 
 config PA7100LC
-       bool "PA7100LC"
+       bool "PA7100LC" if "$(ARCH)" = "parisc"
        help
          Select this option for the PCX-L processor, as used in the
          712, 715/64, 715/80, 715/100, 715/100XC, 725/100, 743, 748,
          D200, D210, D300, D310 and E-class
 
 config PA7200
-       bool "PA7200"
+       bool "PA7200" if "$(ARCH)" = "parisc"
        help
          Select this option for the PCX-T' processor, as used in the
          C100, C110, J100, J110, J210XC, D250, D260, D350, D360,
          K100, K200, K210, K220, K400, K410 and K420
 
 config PA7300LC
-       bool "PA7300LC"
+       bool "PA7300LC" if "$(ARCH)" = "parisc"
        help
          Select this option for the PCX-L2 processor, as used in the
          744, A180, B132L, B160L, B180L, C132L, C160L, C180L,
@@ -224,17 +224,8 @@ config MLONGCALLS
          Enabling this option will probably slow down your kernel.
 
 config 64BIT
-       bool "64-bit kernel"
+       def_bool "$(ARCH)" = "parisc64"
        depends on PA8X00
-       help
-         Enable this if you want to support 64bit kernel on PA-RISC platform.
-
-         At the moment, only people willing to use more than 2GB of RAM,
-         or having a 64bit-only capable PA-RISC machine should say Y here.
-
-         Since there is no 64bit userland on PA-RISC, there is no point to
-         enable this option otherwise. The 64bit kernel is significantly bigger
-         and slower than the 32bit one.
 
 choice
        prompt "Kernel page size"
index 56ffd26..0ec9cfc 100644 (file)
 #include <asm/barrier.h>
 #include <linux/atomic.h>
 
-/* compiler build environment sanity checks: */
-#if !defined(CONFIG_64BIT) && defined(__LP64__)
-#error "Please use 'ARCH=parisc' to build the 32-bit kernel."
-#endif
-#if defined(CONFIG_64BIT) && !defined(__LP64__)
-#error "Please use 'ARCH=parisc64' to build the 64-bit kernel."
-#endif
-
 /* See http://marc.theaimsgroup.com/?t=108826637900003 for discussion
  * on use of volatile and __*_bit() (set/clear/change):
  *     *_bit() want use of volatile.
index e0a9e96..fd15fd4 100644 (file)
@@ -22,7 +22,7 @@
 #include <linux/init.h>
 #include <linux/pgtable.h>
 
-       .level  PA_ASM_LEVEL
+       .level  1.1
 
        __INITDATA
 ENTRY(boot_args)
@@ -70,6 +70,47 @@ $bss_loop:
        stw,ma          %arg2,4(%r1)
        stw,ma          %arg3,4(%r1)
 
+#if !defined(CONFIG_64BIT) && defined(CONFIG_PA20)
+       /* This 32-bit kernel was compiled for PA2.0 CPUs. Check current CPU
+        * and halt kernel if we detect a PA1.x CPU. */
+       ldi             32,%r10
+       mtctl           %r10,%cr11
+       .level 2.0
+       mfctl,w         %cr11,%r10
+       .level 1.1
+       comib,<>,n      0,%r10,$cpu_ok
+
+       load32          PA(msg1),%arg0
+       ldi             msg1_end-msg1,%arg1
+$iodc_panic:
+       copy            %arg0, %r10
+       copy            %arg1, %r11
+       load32          PA(init_stack),%sp
+#define MEM_CONS 0x3A0
+       ldw             MEM_CONS+32(%r0),%arg0  // HPA
+       ldi             ENTRY_IO_COUT,%arg1
+       ldw             MEM_CONS+36(%r0),%arg2  // SPA
+       ldw             MEM_CONS+8(%r0),%arg3   // layers
+       load32          PA(__bss_start),%r1
+       stw             %r1,-52(%sp)            // arg4
+       stw             %r0,-56(%sp)            // arg5
+       stw             %r10,-60(%sp)           // arg6 = ptr to text
+       stw             %r11,-64(%sp)           // arg7 = len
+       stw             %r0,-68(%sp)            // arg8
+       load32          PA(.iodc_panic_ret), %rp
+       ldw             MEM_CONS+40(%r0),%r1    // ENTRY_IODC
+       bv,n            (%r1)
+.iodc_panic_ret:
+       b .                             /* wait endless with ... */
+       or              %r10,%r10,%r10  /* qemu idle sleep */
+msg1:  .ascii "Can't boot kernel which was built for PA8x00 CPUs on this machine.\r\n"
+msg1_end:
+
+$cpu_ok:
+#endif
+
+       .level  PA_ASM_LEVEL
+
        /* Initialize startup VM. Just map first 16/32 MB of memory */
        load32          PA(swapper_pg_dir),%r4
        mtctl           %r4,%cr24       /* Initialize kernel root pointer */
index bac581b..e8a4d77 100644 (file)
@@ -93,7 +93,7 @@
 #define R1(i) (((i)>>21)&0x1f)
 #define R2(i) (((i)>>16)&0x1f)
 #define R3(i) ((i)&0x1f)
-#define FR3(i) ((((i)<<1)&0x1f)|(((i)>>6)&1))
+#define FR3(i) ((((i)&0x1f)<<1)|(((i)>>6)&1))
 #define IM(i,n) (((i)>>1&((1<<(n-1))-1))|((i)&1?((0-1L)<<(n-1)):0))
 #define IM5_2(i) IM((i)>>16,5)
 #define IM5_3(i) IM((i),5)
index 044982a..f3f87ed 100644 (file)
 
        phy1: ethernet-phy@9 {
                reg = <9>;
-               ti,fifo-depth = <0x1>;
        };
 
        phy0: ethernet-phy@8 {
                reg = <8>;
-               ti,fifo-depth = <0x1>;
        };
 };
 
        disable-wp;
        cap-sd-highspeed;
        cap-mmc-highspeed;
-       card-detect-delay = <200>;
        mmc-ddr-1_8v;
        mmc-hs200-1_8v;
        sd-uhs-sdr12;
index 82c93c8..c87cc2d 100644 (file)
 
        phy1: ethernet-phy@5 {
                reg = <5>;
-               ti,fifo-depth = <0x01>;
        };
 
        phy0: ethernet-phy@4 {
                reg = <4>;
-               ti,fifo-depth = <0x01>;
        };
 };
 
@@ -72,7 +70,6 @@
        disable-wp;
        cap-sd-highspeed;
        cap-mmc-highspeed;
-       card-detect-delay = <200>;
        mmc-ddr-1_8v;
        mmc-hs200-1_8v;
        sd-uhs-sdr12;
index 499c2e6..7449334 100644 (file)
                        cache-size = <2097152>;
                        cache-unified;
                        interrupt-parent = <&plic>;
-                       interrupts = <1>, <2>, <3>;
+                       interrupts = <1>, <3>, <4>, <2>;
                };
 
                clint: clint@2000000 {
                        ranges = <0x3000000 0x0 0x8000000 0x20 0x8000000 0x0 0x80000000>;
                        msi-parent = <&pcie>;
                        msi-controller;
-                       microchip,axi-m-atr0 = <0x10 0x0>;
                        status = "disabled";
-                       pcie_intc: legacy-interrupt-controller {
+                       pcie_intc: interrupt-controller {
                                #address-cells = <0>;
                                #interrupt-cells = <1>;
                                interrupt-controller;
diff --git a/arch/riscv/include/asm/signal.h b/arch/riscv/include/asm/signal.h
new file mode 100644 (file)
index 0000000..532c29e
--- /dev/null
@@ -0,0 +1,12 @@
+/* SPDX-License-Identifier: GPL-2.0-only */
+
+#ifndef __ASM_SIGNAL_H
+#define __ASM_SIGNAL_H
+
+#include <uapi/asm/signal.h>
+#include <uapi/asm/ptrace.h>
+
+asmlinkage __visible
+void do_notify_resume(struct pt_regs *regs, unsigned long thread_info_flags);
+
+#endif
index 78933ac..67322f8 100644 (file)
@@ -42,6 +42,8 @@
 
 #ifndef __ASSEMBLY__
 
+extern long shadow_stack[SHADOW_OVERFLOW_STACK_SIZE / sizeof(long)];
+
 #include <asm/processor.h>
 #include <asm/csr.h>
 
index 38b05ca..5a2de6b 100644 (file)
@@ -15,6 +15,7 @@
 
 #include <asm/ucontext.h>
 #include <asm/vdso.h>
+#include <asm/signal.h>
 #include <asm/signal32.h>
 #include <asm/switch_to.h>
 #include <asm/csr.h>
index 39d0f8b..635e6ec 100644 (file)
 
 #include <asm/asm-prototypes.h>
 #include <asm/bug.h>
+#include <asm/csr.h>
 #include <asm/processor.h>
 #include <asm/ptrace.h>
-#include <asm/csr.h>
+#include <asm/thread_info.h>
 
 int show_unhandled_signals = 1;
 
index 9a7d15d..2de74fc 100644 (file)
@@ -176,14 +176,8 @@ arch___test_and_change_bit(unsigned long nr, volatile unsigned long *addr)
        return old & mask;
 }
 
-static __always_inline bool
-arch_test_bit(unsigned long nr, const volatile unsigned long *addr)
-{
-       const volatile unsigned long *p = __bitops_word(nr, addr);
-       unsigned long mask = __bitops_mask(nr);
-
-       return *p & mask;
-}
+#define arch_test_bit generic_test_bit
+#define arch_test_bit_acquire generic_test_bit_acquire
 
 static inline bool arch_test_and_set_bit_lock(unsigned long nr,
                                              volatile unsigned long *ptr)
index 89949b9..d5119e0 100644 (file)
@@ -91,6 +91,18 @@ int arch_dup_task_struct(struct task_struct *dst, struct task_struct *src)
 
        memcpy(dst, src, arch_task_struct_size);
        dst->thread.fpu.regs = dst->thread.fpu.fprs;
+
+       /*
+        * Don't transfer over the runtime instrumentation or the guarded
+        * storage control block pointers. These fields are cleared here instead
+        * of in copy_thread() to avoid premature freeing of associated memory
+        * on fork() failure. Wait to clear the RI flag because ->stack still
+        * refers to the source thread.
+        */
+       dst->thread.ri_cb = NULL;
+       dst->thread.gs_cb = NULL;
+       dst->thread.gs_bc_cb = NULL;
+
        return 0;
 }
 
@@ -150,13 +162,11 @@ int copy_thread(struct task_struct *p, const struct kernel_clone_args *args)
        frame->childregs.flags = 0;
        if (new_stackp)
                frame->childregs.gprs[15] = new_stackp;
-
-       /* Don't copy runtime instrumentation info */
-       p->thread.ri_cb = NULL;
+       /*
+        * Clear the runtime instrumentation flag after the above childregs
+        * copy. The CB pointer was already cleared in arch_dup_task_struct().
+        */
        frame->childregs.psw.mask &= ~PSW_MASK_RI;
-       /* Don't copy guarded storage control block */
-       p->thread.gs_cb = NULL;
-       p->thread.gs_bc_cb = NULL;
 
        /* Set a new TLS ?  */
        if (clone_flags & CLONE_SETTLS) {
index 1344994..09b6e75 100644 (file)
@@ -379,7 +379,9 @@ static inline vm_fault_t do_exception(struct pt_regs *regs, int access)
        flags = FAULT_FLAG_DEFAULT;
        if (user_mode(regs))
                flags |= FAULT_FLAG_USER;
-       if (access == VM_WRITE || is_write)
+       if (is_write)
+               access = VM_WRITE;
+       if (access == VM_WRITE)
                flags |= FAULT_FLAG_WRITE;
        mmap_read_lock(mm);
 
index 565a85d..5ace89b 100644 (file)
@@ -135,16 +135,8 @@ arch___test_and_change_bit(unsigned long nr, volatile unsigned long *addr)
        return (old & mask) != 0;
 }
 
-/**
- * arch_test_bit - Determine whether a bit is set
- * @nr: bit number to test
- * @addr: Address to start counting from
- */
-static __always_inline bool
-arch_test_bit(unsigned long nr, const volatile unsigned long *addr)
-{
-       return 1UL & (addr[BIT_WORD(nr)] >> (nr & (BITS_PER_LONG-1)));
-}
+#define arch_test_bit generic_test_bit
+#define arch_test_bit_acquire generic_test_bit_acquire
 
 #include <asm-generic/bitops/non-instrumented-non-atomic.h>
 
index 4910bf2..62208ec 100644 (file)
@@ -132,7 +132,17 @@ void snp_set_page_private(unsigned long paddr);
 void snp_set_page_shared(unsigned long paddr);
 void sev_prep_identity_maps(unsigned long top_level_pgt);
 #else
-static inline void sev_enable(struct boot_params *bp) { }
+static inline void sev_enable(struct boot_params *bp)
+{
+       /*
+        * bp->cc_blob_address should only be set by boot/compressed kernel.
+        * Initialize it to 0 unconditionally (thus here in this stub too) to
+        * ensure that uninitialized values from buggy bootloaders aren't
+        * propagated.
+        */
+       if (bp)
+               bp->cc_blob_address = 0;
+}
 static inline void sev_es_shutdown_ghcb(void) { }
 static inline bool sev_es_check_ghcb_fault(unsigned long address)
 {
index 52f989f..c93930d 100644 (file)
@@ -277,6 +277,14 @@ void sev_enable(struct boot_params *bp)
        bool snp;
 
        /*
+        * bp->cc_blob_address should only be set by boot/compressed kernel.
+        * Initialize it to 0 to ensure that uninitialized values from
+        * buggy bootloaders aren't propagated.
+        */
+       if (bp)
+               bp->cc_blob_address = 0;
+
+       /*
         * Setup/preliminary detection of SNP. This will be sanity-checked
         * against CPUID/MSR values later.
         */
index d9fc713..5812962 100644 (file)
@@ -14,7 +14,6 @@ CONFIG_CPU_FREQ=y
 
 # x86 xen specific config options
 CONFIG_XEN_PVH=y
-CONFIG_XEN_MAX_DOMAIN_MEMORY=500
 CONFIG_XEN_SAVE_RESTORE=y
 # CONFIG_XEN_DEBUG_FS is not set
 CONFIG_XEN_MCE_LOG=y
index 682338e..4dd1981 100644 (file)
@@ -311,7 +311,7 @@ SYM_CODE_START(entry_INT80_compat)
         * Interrupts are off on entry.
         */
        ASM_CLAC                        /* Do this early to minimize exposure */
-       SWAPGS
+       ALTERNATIVE "swapgs", "", X86_FEATURE_XENPV
 
        /*
         * User tracing code (ptrace or signal handlers) might assume that
index 2db9349..cb98a05 100644 (file)
@@ -6291,10 +6291,8 @@ __init int intel_pmu_init(void)
                x86_pmu.pebs_aliases = NULL;
                x86_pmu.pebs_prec_dist = true;
                x86_pmu.pebs_block = true;
-               x86_pmu.pebs_capable = ~0ULL;
                x86_pmu.flags |= PMU_FL_HAS_RSP_1;
                x86_pmu.flags |= PMU_FL_NO_HT_SHARING;
-               x86_pmu.flags |= PMU_FL_PEBS_ALL;
                x86_pmu.flags |= PMU_FL_INSTR_LATENCY;
                x86_pmu.flags |= PMU_FL_MEM_LOADS_AUX;
 
@@ -6337,10 +6335,8 @@ __init int intel_pmu_init(void)
                x86_pmu.pebs_aliases = NULL;
                x86_pmu.pebs_prec_dist = true;
                x86_pmu.pebs_block = true;
-               x86_pmu.pebs_capable = ~0ULL;
                x86_pmu.flags |= PMU_FL_HAS_RSP_1;
                x86_pmu.flags |= PMU_FL_NO_HT_SHARING;
-               x86_pmu.flags |= PMU_FL_PEBS_ALL;
                x86_pmu.flags |= PMU_FL_INSTR_LATENCY;
                x86_pmu.flags |= PMU_FL_MEM_LOADS_AUX;
                x86_pmu.lbr_pt_coexist = true;
index ba60427..de1f55d 100644 (file)
@@ -291,6 +291,7 @@ static u64 load_latency_data(struct perf_event *event, u64 status)
 static u64 store_latency_data(struct perf_event *event, u64 status)
 {
        union intel_x86_pebs_dse dse;
+       union perf_mem_data_src src;
        u64 val;
 
        dse.val = status;
@@ -304,7 +305,14 @@ static u64 store_latency_data(struct perf_event *event, u64 status)
 
        val |= P(BLK, NA);
 
-       return val;
+       /*
+        * the pebs_data_source table is only for loads
+        * so override the mem_op to say STORE instead
+        */
+       src.val = val;
+       src.mem_op = P(OP,STORE);
+
+       return src.val;
 }
 
 struct pebs_record_core {
@@ -822,7 +830,7 @@ struct event_constraint intel_glm_pebs_event_constraints[] = {
 
 struct event_constraint intel_grt_pebs_event_constraints[] = {
        /* Allow all events as PEBS with no flags */
-       INTEL_HYBRID_LAT_CONSTRAINT(0x5d0, 0xf),
+       INTEL_HYBRID_LAT_CONSTRAINT(0x5d0, 0x3),
        INTEL_HYBRID_LAT_CONSTRAINT(0x6d0, 0xf),
        EVENT_CONSTRAINT_END
 };
@@ -2262,6 +2270,7 @@ void __init intel_ds_init(void)
                                        PERF_SAMPLE_BRANCH_STACK |
                                        PERF_SAMPLE_TIME;
                                x86_pmu.flags |= PMU_FL_PEBS_ALL;
+                               x86_pmu.pebs_capable = ~0ULL;
                                pebs_qual = "-baseline";
                                x86_get_pmu(smp_processor_id())->capabilities |= PERF_PMU_CAP_EXTENDED_REGS;
                        } else {
index 4f70fb6..47fca6a 100644 (file)
@@ -1097,6 +1097,14 @@ static int intel_pmu_setup_hw_lbr_filter(struct perf_event *event)
 
        if (static_cpu_has(X86_FEATURE_ARCH_LBR)) {
                reg->config = mask;
+
+               /*
+                * The Arch LBR HW can retrieve the common branch types
+                * from the LBR_INFO. It doesn't require the high overhead
+                * SW disassemble.
+                * Enable the branch type by default for the Arch LBR.
+                */
+               reg->reg |= X86_BR_TYPE_SAVE;
                return 0;
        }
 
index ce44001..1ef4f78 100644 (file)
@@ -841,6 +841,22 @@ int snb_pci2phy_map_init(int devid)
        return 0;
 }
 
+static u64 snb_uncore_imc_read_counter(struct intel_uncore_box *box, struct perf_event *event)
+{
+       struct hw_perf_event *hwc = &event->hw;
+
+       /*
+        * SNB IMC counters are 32-bit and are laid out back to back
+        * in MMIO space. Therefore we must use a 32-bit accessor function
+        * using readq() from uncore_mmio_read_counter() causes problems
+        * because it is reading 64-bit at a time. This is okay for the
+        * uncore_perf_event_update() function because it drops the upper
+        * 32-bits but not okay for plain uncore_read_counter() as invoked
+        * in uncore_pmu_event_start().
+        */
+       return (u64)readl(box->io_addr + hwc->event_base);
+}
+
 static struct pmu snb_uncore_imc_pmu = {
        .task_ctx_nr    = perf_invalid_context,
        .event_init     = snb_uncore_imc_event_init,
@@ -860,7 +876,7 @@ static struct intel_uncore_ops snb_uncore_imc_ops = {
        .disable_event  = snb_uncore_imc_disable_event,
        .enable_event   = snb_uncore_imc_enable_event,
        .hw_config      = snb_uncore_imc_hw_config,
-       .read_counter   = uncore_mmio_read_counter,
+       .read_counter   = snb_uncore_imc_read_counter,
 };
 
 static struct intel_uncore_type snb_uncore_imc = {
index 973c6bd..0fe9de5 100644 (file)
@@ -207,6 +207,20 @@ static __always_inline bool constant_test_bit(long nr, const volatile unsigned l
                (addr[nr >> _BITOPS_LONG_SHIFT])) != 0;
 }
 
+static __always_inline bool constant_test_bit_acquire(long nr, const volatile unsigned long *addr)
+{
+       bool oldbit;
+
+       asm volatile("testb %2,%1"
+                    CC_SET(nz)
+                    : CC_OUT(nz) (oldbit)
+                    : "m" (((unsigned char *)addr)[nr >> 3]),
+                      "i" (1 << (nr & 7))
+                    :"memory");
+
+       return oldbit;
+}
+
 static __always_inline bool variable_test_bit(long nr, volatile const unsigned long *addr)
 {
        bool oldbit;
@@ -226,6 +240,13 @@ arch_test_bit(unsigned long nr, const volatile unsigned long *addr)
                                          variable_test_bit(nr, addr);
 }
 
+static __always_inline bool
+arch_test_bit_acquire(unsigned long nr, const volatile unsigned long *addr)
+{
+       return __builtin_constant_p(nr) ? constant_test_bit_acquire(nr, addr) :
+                                         variable_test_bit(nr, addr);
+}
+
 /**
  * __ffs - find first set bit in word
  * @word: The word to search
index 235dc85..ef4775c 100644 (file)
 #define X86_BUG_ITLB_MULTIHIT          X86_BUG(23) /* CPU may incur MCE during certain page attribute changes */
 #define X86_BUG_SRBDS                  X86_BUG(24) /* CPU may leak RNG bits if not mitigated */
 #define X86_BUG_MMIO_STALE_DATA                X86_BUG(25) /* CPU is affected by Processor MMIO Stale Data vulnerabilities */
-#define X86_BUG_RETBLEED               X86_BUG(26) /* CPU is affected by RETBleed */
-#define X86_BUG_EIBRS_PBRSB            X86_BUG(27) /* EIBRS is vulnerable to Post Barrier RSB Predictions */
+#define X86_BUG_MMIO_UNKNOWN           X86_BUG(26) /* CPU is too old and its MMIO Stale Data status is unknown */
+#define X86_BUG_RETBLEED               X86_BUG(27) /* CPU is affected by RETBleed */
+#define X86_BUG_EIBRS_PBRSB            X86_BUG(28) /* EIBRS is vulnerable to Post Barrier RSB Predictions */
 
 #endif /* _ASM_X86_CPUFEATURES_H */
index def6ca1..aeb3802 100644 (file)
@@ -27,6 +27,7 @@
  *             _X      - regular server parts
  *             _D      - micro server parts
  *             _N,_P   - other mobile parts
+ *             _S      - other client parts
  *
  *             Historical OPTDIFFs:
  *
 
 #define INTEL_FAM6_RAPTORLAKE          0xB7
 #define INTEL_FAM6_RAPTORLAKE_P                0xBA
+#define INTEL_FAM6_RAPTORLAKE_S                0xBF
 
 /* "Small Core" Processors (Atom) */
 
index e64fd20..c936ce9 100644 (file)
 #define RSB_CLEAR_LOOPS                32      /* To forcibly overwrite all entries */
 
 /*
+ * Common helper for __FILL_RETURN_BUFFER and __FILL_ONE_RETURN.
+ */
+#define __FILL_RETURN_SLOT                     \
+       ANNOTATE_INTRA_FUNCTION_CALL;           \
+       call    772f;                           \
+       int3;                                   \
+772:
+
+/*
+ * Stuff the entire RSB.
+ *
  * Google experimented with loop-unrolling and this turned out to be
  * the optimal version - two calls, each with their own speculation
  * trap should their return address end up getting used, in a loop.
  */
-#define __FILL_RETURN_BUFFER(reg, nr, sp)      \
-       mov     $(nr/2), reg;                   \
-771:                                           \
-       ANNOTATE_INTRA_FUNCTION_CALL;           \
-       call    772f;                           \
-773:   /* speculation trap */                  \
-       UNWIND_HINT_EMPTY;                      \
-       pause;                                  \
-       lfence;                                 \
-       jmp     773b;                           \
-772:                                           \
-       ANNOTATE_INTRA_FUNCTION_CALL;           \
-       call    774f;                           \
-775:   /* speculation trap */                  \
-       UNWIND_HINT_EMPTY;                      \
-       pause;                                  \
-       lfence;                                 \
-       jmp     775b;                           \
-774:                                           \
-       add     $(BITS_PER_LONG/8) * 2, sp;     \
-       dec     reg;                            \
-       jnz     771b;                           \
-       /* barrier for jnz misprediction */     \
+#ifdef CONFIG_X86_64
+#define __FILL_RETURN_BUFFER(reg, nr)                  \
+       mov     $(nr/2), reg;                           \
+771:                                                   \
+       __FILL_RETURN_SLOT                              \
+       __FILL_RETURN_SLOT                              \
+       add     $(BITS_PER_LONG/8) * 2, %_ASM_SP;       \
+       dec     reg;                                    \
+       jnz     771b;                                   \
+       /* barrier for jnz misprediction */             \
+       lfence;
+#else
+/*
+ * i386 doesn't unconditionally have LFENCE, as such it can't
+ * do a loop.
+ */
+#define __FILL_RETURN_BUFFER(reg, nr)                  \
+       .rept nr;                                       \
+       __FILL_RETURN_SLOT;                             \
+       .endr;                                          \
+       add     $(BITS_PER_LONG/8) * nr, %_ASM_SP;
+#endif
+
+/*
+ * Stuff a single RSB slot.
+ *
+ * To mitigate Post-Barrier RSB speculation, one CALL instruction must be
+ * forced to retire before letting a RET instruction execute.
+ *
+ * On PBRSB-vulnerable CPUs, it is not safe for a RET to be executed
+ * before this point.
+ */
+#define __FILL_ONE_RETURN                              \
+       __FILL_RETURN_SLOT                              \
+       add     $(BITS_PER_LONG/8), %_ASM_SP;           \
        lfence;
 
 #ifdef __ASSEMBLY__
 #endif
 .endm
 
-.macro ISSUE_UNBALANCED_RET_GUARD
-       ANNOTATE_INTRA_FUNCTION_CALL
-       call .Lunbalanced_ret_guard_\@
-       int3
-.Lunbalanced_ret_guard_\@:
-       add $(BITS_PER_LONG/8), %_ASM_SP
-       lfence
-.endm
-
  /*
   * A simpler FILL_RETURN_BUFFER macro. Don't make people use the CPP
   * monstrosity above, manually.
   */
-.macro FILL_RETURN_BUFFER reg:req nr:req ftr:req ftr2
-.ifb \ftr2
-       ALTERNATIVE "jmp .Lskip_rsb_\@", "", \ftr
-.else
-       ALTERNATIVE_2 "jmp .Lskip_rsb_\@", "", \ftr, "jmp .Lunbalanced_\@", \ftr2
-.endif
-       __FILL_RETURN_BUFFER(\reg,\nr,%_ASM_SP)
-.Lunbalanced_\@:
-       ISSUE_UNBALANCED_RET_GUARD
+.macro FILL_RETURN_BUFFER reg:req nr:req ftr:req ftr2=ALT_NOT(X86_FEATURE_ALWAYS)
+       ALTERNATIVE_2 "jmp .Lskip_rsb_\@", \
+               __stringify(__FILL_RETURN_BUFFER(\reg,\nr)), \ftr, \
+               __stringify(__FILL_ONE_RETURN), \ftr2
+
 .Lskip_rsb_\@:
 .endm
 
index 4a23e52..ebc271b 100644 (file)
@@ -195,7 +195,7 @@ void snp_set_memory_shared(unsigned long vaddr, unsigned int npages);
 void snp_set_memory_private(unsigned long vaddr, unsigned int npages);
 void snp_set_wakeup_secondary_cpu(void);
 bool snp_init(struct boot_params *bp);
-void snp_abort(void);
+void __init __noreturn snp_abort(void);
 int snp_issue_guest_request(u64 exit_code, struct snp_req_data *input, unsigned long *fw_err);
 #else
 static inline void sev_es_ist_enter(struct pt_regs *regs) { }
index 510d852..da7c361 100644 (file)
@@ -433,7 +433,8 @@ static void __init mmio_select_mitigation(void)
        u64 ia32_cap;
 
        if (!boot_cpu_has_bug(X86_BUG_MMIO_STALE_DATA) ||
-           cpu_mitigations_off()) {
+            boot_cpu_has_bug(X86_BUG_MMIO_UNKNOWN) ||
+            cpu_mitigations_off()) {
                mmio_mitigation = MMIO_MITIGATION_OFF;
                return;
        }
@@ -538,6 +539,8 @@ out:
                pr_info("TAA: %s\n", taa_strings[taa_mitigation]);
        if (boot_cpu_has_bug(X86_BUG_MMIO_STALE_DATA))
                pr_info("MMIO Stale Data: %s\n", mmio_strings[mmio_mitigation]);
+       else if (boot_cpu_has_bug(X86_BUG_MMIO_UNKNOWN))
+               pr_info("MMIO Stale Data: Unknown: No mitigations\n");
 }
 
 static void __init md_clear_select_mitigation(void)
@@ -2275,6 +2278,9 @@ static ssize_t tsx_async_abort_show_state(char *buf)
 
 static ssize_t mmio_stale_data_show_state(char *buf)
 {
+       if (boot_cpu_has_bug(X86_BUG_MMIO_UNKNOWN))
+               return sysfs_emit(buf, "Unknown: No mitigations\n");
+
        if (mmio_mitigation == MMIO_MITIGATION_OFF)
                return sysfs_emit(buf, "%s\n", mmio_strings[mmio_mitigation]);
 
@@ -2421,6 +2427,7 @@ static ssize_t cpu_show_common(struct device *dev, struct device_attribute *attr
                return srbds_show_state(buf);
 
        case X86_BUG_MMIO_STALE_DATA:
+       case X86_BUG_MMIO_UNKNOWN:
                return mmio_stale_data_show_state(buf);
 
        case X86_BUG_RETBLEED:
@@ -2480,7 +2487,10 @@ ssize_t cpu_show_srbds(struct device *dev, struct device_attribute *attr, char *
 
 ssize_t cpu_show_mmio_stale_data(struct device *dev, struct device_attribute *attr, char *buf)
 {
-       return cpu_show_common(dev, attr, buf, X86_BUG_MMIO_STALE_DATA);
+       if (boot_cpu_has_bug(X86_BUG_MMIO_UNKNOWN))
+               return cpu_show_common(dev, attr, buf, X86_BUG_MMIO_UNKNOWN);
+       else
+               return cpu_show_common(dev, attr, buf, X86_BUG_MMIO_STALE_DATA);
 }
 
 ssize_t cpu_show_retbleed(struct device *dev, struct device_attribute *attr, char *buf)
index 64a73f4..3e508f2 100644 (file)
@@ -1135,7 +1135,8 @@ static void identify_cpu_without_cpuid(struct cpuinfo_x86 *c)
 #define NO_SWAPGS              BIT(6)
 #define NO_ITLB_MULTIHIT       BIT(7)
 #define NO_SPECTRE_V2          BIT(8)
-#define NO_EIBRS_PBRSB         BIT(9)
+#define NO_MMIO                        BIT(9)
+#define NO_EIBRS_PBRSB         BIT(10)
 
 #define VULNWL(vendor, family, model, whitelist)       \
        X86_MATCH_VENDOR_FAM_MODEL(vendor, family, model, whitelist)
@@ -1158,6 +1159,11 @@ static const __initconst struct x86_cpu_id cpu_vuln_whitelist[] = {
        VULNWL(VORTEX,  6, X86_MODEL_ANY,       NO_SPECULATION),
 
        /* Intel Family 6 */
+       VULNWL_INTEL(TIGERLAKE,                 NO_MMIO),
+       VULNWL_INTEL(TIGERLAKE_L,               NO_MMIO),
+       VULNWL_INTEL(ALDERLAKE,                 NO_MMIO),
+       VULNWL_INTEL(ALDERLAKE_L,               NO_MMIO),
+
        VULNWL_INTEL(ATOM_SALTWELL,             NO_SPECULATION | NO_ITLB_MULTIHIT),
        VULNWL_INTEL(ATOM_SALTWELL_TABLET,      NO_SPECULATION | NO_ITLB_MULTIHIT),
        VULNWL_INTEL(ATOM_SALTWELL_MID,         NO_SPECULATION | NO_ITLB_MULTIHIT),
@@ -1176,9 +1182,9 @@ static const __initconst struct x86_cpu_id cpu_vuln_whitelist[] = {
        VULNWL_INTEL(ATOM_AIRMONT_MID,          NO_L1TF | MSBDS_ONLY | NO_SWAPGS | NO_ITLB_MULTIHIT),
        VULNWL_INTEL(ATOM_AIRMONT_NP,           NO_L1TF | NO_SWAPGS | NO_ITLB_MULTIHIT),
 
-       VULNWL_INTEL(ATOM_GOLDMONT,             NO_MDS | NO_L1TF | NO_SWAPGS | NO_ITLB_MULTIHIT),
-       VULNWL_INTEL(ATOM_GOLDMONT_D,           NO_MDS | NO_L1TF | NO_SWAPGS | NO_ITLB_MULTIHIT),
-       VULNWL_INTEL(ATOM_GOLDMONT_PLUS,        NO_MDS | NO_L1TF | NO_SWAPGS | NO_ITLB_MULTIHIT | NO_EIBRS_PBRSB),
+       VULNWL_INTEL(ATOM_GOLDMONT,             NO_MDS | NO_L1TF | NO_SWAPGS | NO_ITLB_MULTIHIT | NO_MMIO),
+       VULNWL_INTEL(ATOM_GOLDMONT_D,           NO_MDS | NO_L1TF | NO_SWAPGS | NO_ITLB_MULTIHIT | NO_MMIO),
+       VULNWL_INTEL(ATOM_GOLDMONT_PLUS,        NO_MDS | NO_L1TF | NO_SWAPGS | NO_ITLB_MULTIHIT | NO_MMIO | NO_EIBRS_PBRSB),
 
        /*
         * Technically, swapgs isn't serializing on AMD (despite it previously
@@ -1193,18 +1199,18 @@ static const __initconst struct x86_cpu_id cpu_vuln_whitelist[] = {
        VULNWL_INTEL(ATOM_TREMONT_D,            NO_ITLB_MULTIHIT | NO_EIBRS_PBRSB),
 
        /* AMD Family 0xf - 0x12 */
-       VULNWL_AMD(0x0f,        NO_MELTDOWN | NO_SSB | NO_L1TF | NO_MDS | NO_SWAPGS | NO_ITLB_MULTIHIT),
-       VULNWL_AMD(0x10,        NO_MELTDOWN | NO_SSB | NO_L1TF | NO_MDS | NO_SWAPGS | NO_ITLB_MULTIHIT),
-       VULNWL_AMD(0x11,        NO_MELTDOWN | NO_SSB | NO_L1TF | NO_MDS | NO_SWAPGS | NO_ITLB_MULTIHIT),
-       VULNWL_AMD(0x12,        NO_MELTDOWN | NO_SSB | NO_L1TF | NO_MDS | NO_SWAPGS | NO_ITLB_MULTIHIT),
+       VULNWL_AMD(0x0f,        NO_MELTDOWN | NO_SSB | NO_L1TF | NO_MDS | NO_SWAPGS | NO_ITLB_MULTIHIT | NO_MMIO),
+       VULNWL_AMD(0x10,        NO_MELTDOWN | NO_SSB | NO_L1TF | NO_MDS | NO_SWAPGS | NO_ITLB_MULTIHIT | NO_MMIO),
+       VULNWL_AMD(0x11,        NO_MELTDOWN | NO_SSB | NO_L1TF | NO_MDS | NO_SWAPGS | NO_ITLB_MULTIHIT | NO_MMIO),
+       VULNWL_AMD(0x12,        NO_MELTDOWN | NO_SSB | NO_L1TF | NO_MDS | NO_SWAPGS | NO_ITLB_MULTIHIT | NO_MMIO),
 
        /* FAMILY_ANY must be last, otherwise 0x0f - 0x12 matches won't work */
-       VULNWL_AMD(X86_FAMILY_ANY,      NO_MELTDOWN | NO_L1TF | NO_MDS | NO_SWAPGS | NO_ITLB_MULTIHIT),
-       VULNWL_HYGON(X86_FAMILY_ANY,    NO_MELTDOWN | NO_L1TF | NO_MDS | NO_SWAPGS | NO_ITLB_MULTIHIT),
+       VULNWL_AMD(X86_FAMILY_ANY,      NO_MELTDOWN | NO_L1TF | NO_MDS | NO_SWAPGS | NO_ITLB_MULTIHIT | NO_MMIO),
+       VULNWL_HYGON(X86_FAMILY_ANY,    NO_MELTDOWN | NO_L1TF | NO_MDS | NO_SWAPGS | NO_ITLB_MULTIHIT | NO_MMIO),
 
        /* Zhaoxin Family 7 */
-       VULNWL(CENTAUR, 7, X86_MODEL_ANY,       NO_SPECTRE_V2 | NO_SWAPGS),
-       VULNWL(ZHAOXIN, 7, X86_MODEL_ANY,       NO_SPECTRE_V2 | NO_SWAPGS),
+       VULNWL(CENTAUR, 7, X86_MODEL_ANY,       NO_SPECTRE_V2 | NO_SWAPGS | NO_MMIO),
+       VULNWL(ZHAOXIN, 7, X86_MODEL_ANY,       NO_SPECTRE_V2 | NO_SWAPGS | NO_MMIO),
        {}
 };
 
@@ -1358,10 +1364,16 @@ static void __init cpu_set_bug_bits(struct cpuinfo_x86 *c)
         * Affected CPU list is generally enough to enumerate the vulnerability,
         * but for virtualization case check for ARCH_CAP MSR bits also, VMM may
         * not want the guest to enumerate the bug.
+        *
+        * Set X86_BUG_MMIO_UNKNOWN for CPUs that are neither in the blacklist,
+        * nor in the whitelist and also don't enumerate MSR ARCH_CAP MMIO bits.
         */
-       if (cpu_matches(cpu_vuln_blacklist, MMIO) &&
-           !arch_cap_mmio_immune(ia32_cap))
-               setup_force_cpu_bug(X86_BUG_MMIO_STALE_DATA);
+       if (!arch_cap_mmio_immune(ia32_cap)) {
+               if (cpu_matches(cpu_vuln_blacklist, MMIO))
+                       setup_force_cpu_bug(X86_BUG_MMIO_STALE_DATA);
+               else if (!cpu_matches(cpu_vuln_whitelist, NO_MMIO))
+                       setup_force_cpu_bug(X86_BUG_MMIO_UNKNOWN);
+       }
 
        if (!cpu_has(c, X86_FEATURE_BTC_NO)) {
                if (cpu_matches(cpu_vuln_blacklist, RETBLEED) || (ia32_cap & ARCH_CAP_RSBA))
index 63dc626..a428c62 100644 (file)
@@ -701,7 +701,13 @@ e_term:
 void __init early_snp_set_memory_private(unsigned long vaddr, unsigned long paddr,
                                         unsigned int npages)
 {
-       if (!cc_platform_has(CC_ATTR_GUEST_SEV_SNP))
+       /*
+        * This can be invoked in early boot while running identity mapped, so
+        * use an open coded check for SNP instead of using cc_platform_has().
+        * This eliminates worries about jump tables or checking boot_cpu_data
+        * in the cc_platform_has() function.
+        */
+       if (!(sev_status & MSR_AMD64_SEV_SNP_ENABLED))
                return;
 
         /*
@@ -717,7 +723,13 @@ void __init early_snp_set_memory_private(unsigned long vaddr, unsigned long padd
 void __init early_snp_set_memory_shared(unsigned long vaddr, unsigned long paddr,
                                        unsigned int npages)
 {
-       if (!cc_platform_has(CC_ATTR_GUEST_SEV_SNP))
+       /*
+        * This can be invoked in early boot while running identity mapped, so
+        * use an open coded check for SNP instead of using cc_platform_has().
+        * This eliminates worries about jump tables or checking boot_cpu_data
+        * in the cc_platform_has() function.
+        */
+       if (!(sev_status & MSR_AMD64_SEV_SNP_ENABLED))
                return;
 
        /* Invalidate the memory pages before they are marked shared in the RMP table. */
@@ -2100,7 +2112,7 @@ bool __init snp_init(struct boot_params *bp)
        return true;
 }
 
-void __init snp_abort(void)
+void __init __noreturn snp_abort(void)
 {
        sev_es_terminate(SEV_TERM_SET_GEN, GHCB_SNP_UNSUPPORTED);
 }
index 38185ae..0ea57da 100644 (file)
@@ -93,22 +93,27 @@ static struct orc_entry *orc_find(unsigned long ip);
 static struct orc_entry *orc_ftrace_find(unsigned long ip)
 {
        struct ftrace_ops *ops;
-       unsigned long caller;
+       unsigned long tramp_addr, offset;
 
        ops = ftrace_ops_trampoline(ip);
        if (!ops)
                return NULL;
 
+       /* Set tramp_addr to the start of the code copied by the trampoline */
        if (ops->flags & FTRACE_OPS_FL_SAVE_REGS)
-               caller = (unsigned long)ftrace_regs_call;
+               tramp_addr = (unsigned long)ftrace_regs_caller;
        else
-               caller = (unsigned long)ftrace_call;
+               tramp_addr = (unsigned long)ftrace_caller;
+
+       /* Now place tramp_addr to the location within the trampoline ip is at */
+       offset = ip - ops->trampoline;
+       tramp_addr += offset;
 
        /* Prevent unlikely recursion */
-       if (ip == caller)
+       if (ip == tramp_addr)
                return NULL;
 
-       return orc_find(caller);
+       return orc_find(tramp_addr);
 }
 #else
 static struct orc_entry *orc_ftrace_find(unsigned long ip)
index d5ef64d..66a209f 100644 (file)
@@ -62,6 +62,7 @@
 
 static bool __read_mostly pat_bp_initialized;
 static bool __read_mostly pat_disabled = !IS_ENABLED(CONFIG_X86_PAT);
+static bool __initdata pat_force_disabled = !IS_ENABLED(CONFIG_X86_PAT);
 static bool __read_mostly pat_bp_enabled;
 static bool __read_mostly pat_cm_initialized;
 
@@ -86,6 +87,7 @@ void pat_disable(const char *msg_reason)
 static int __init nopat(char *str)
 {
        pat_disable("PAT support disabled via boot option.");
+       pat_force_disabled = true;
        return 0;
 }
 early_param("nopat", nopat);
@@ -272,7 +274,7 @@ static void pat_ap_init(u64 pat)
        wrmsrl(MSR_IA32_CR_PAT, pat);
 }
 
-void init_cache_modes(void)
+void __init init_cache_modes(void)
 {
        u64 pat = 0;
 
@@ -313,6 +315,12 @@ void init_cache_modes(void)
                 */
                pat = PAT(0, WB) | PAT(1, WT) | PAT(2, UC_MINUS) | PAT(3, UC) |
                      PAT(4, WB) | PAT(5, WT) | PAT(6, UC_MINUS) | PAT(7, UC);
+       } else if (!pat_force_disabled && cpu_feature_enabled(X86_FEATURE_HYPERVISOR)) {
+               /*
+                * Clearly PAT is enabled underneath. Allow pat_enabled() to
+                * reflect this.
+                */
+               pat_bp_enabled = true;
        }
 
        __init_cache_modes(pat);
index 3c1e6b6..c96c8c4 100644 (file)
@@ -1931,7 +1931,8 @@ out:
        /* If we didn't flush the entire list, we could have told the driver
         * there was more coming, but that turned out to be a lie.
         */
-       if ((!list_empty(list) || errors) && q->mq_ops->commit_rqs && queued)
+       if ((!list_empty(list) || errors || needs_resource ||
+            ret == BLK_STS_DEV_RESOURCE) && q->mq_ops->commit_rqs && queued)
                q->mq_ops->commit_rqs(hctx);
        /*
         * Any items that need requeuing? Stuff them into hctx->dispatch,
@@ -2660,6 +2661,7 @@ void blk_mq_try_issue_list_directly(struct blk_mq_hw_ctx *hctx,
                list_del_init(&rq->queuelist);
                ret = blk_mq_request_issue_directly(rq, list_empty(list));
                if (ret != BLK_STS_OK) {
+                       errors++;
                        if (ret == BLK_STS_RESOURCE ||
                                        ret == BLK_STS_DEV_RESOURCE) {
                                blk_mq_request_bypass_insert(rq, false,
@@ -2667,7 +2669,6 @@ void blk_mq_try_issue_list_directly(struct blk_mq_hw_ctx *hctx,
                                break;
                        }
                        blk_mq_end_request(rq, ret);
-                       errors++;
                } else
                        queued++;
        }
index db6ac54..e534fd4 100644 (file)
@@ -151,7 +151,7 @@ void acpi_thermal_cpufreq_exit(struct cpufreq_policy *policy)
        unsigned int cpu;
 
        for_each_cpu(cpu, policy->related_cpus) {
-               struct acpi_processor *pr = per_cpu(processors, policy->cpu);
+               struct acpi_processor *pr = per_cpu(processors, cpu);
 
                if (pr)
                        freq_qos_remove_request(&pr->thermal_req);
index 7b3ad8e..d4c168c 100644 (file)
@@ -370,7 +370,7 @@ static bool acpi_tie_nondev_subnodes(struct acpi_device_data *data)
                bool ret;
 
                status = acpi_attach_data(dn->handle, acpi_nondev_subnode_tag, dn);
-               if (ACPI_FAILURE(status)) {
+               if (ACPI_FAILURE(status) && status != AE_ALREADY_EXISTS) {
                        acpi_handle_err(dn->handle, "Can't tag data node\n");
                        return false;
                }
@@ -1043,11 +1043,10 @@ static int acpi_data_prop_read_single(const struct acpi_device_data *data,
                                break;                                  \
                        }                                               \
                        if (__items[i].integer.value > _Generic(__val,  \
-                                                               u8: U8_MAX, \
-                                                               u16: U16_MAX, \
-                                                               u32: U32_MAX, \
-                                                               u64: U64_MAX, \
-                                                               default: 0U)) { \
+                                                               u8 *: U8_MAX, \
+                                                               u16 *: U16_MAX, \
+                                                               u32 *: U32_MAX, \
+                                                               u64 *: U64_MAX)) { \
                                ret = -EOVERFLOW;                       \
                                break;                                  \
                        }                                               \
index 1014beb..51f4e1c 100644 (file)
@@ -402,12 +402,15 @@ static struct binder_buffer *binder_alloc_new_buf_locked(
        size_t size, data_offsets_size;
        int ret;
 
+       mmap_read_lock(alloc->vma_vm_mm);
        if (!binder_alloc_get_vma(alloc)) {
+               mmap_read_unlock(alloc->vma_vm_mm);
                binder_alloc_debug(BINDER_DEBUG_USER_ERROR,
                                   "%d: binder_alloc_buf, no vma\n",
                                   alloc->pid);
                return ERR_PTR(-ESRCH);
        }
+       mmap_read_unlock(alloc->vma_vm_mm);
 
        data_offsets_size = ALIGN(data_size, sizeof(void *)) +
                ALIGN(offsets_size, sizeof(void *));
@@ -929,17 +932,25 @@ void binder_alloc_print_pages(struct seq_file *m,
         * Make sure the binder_alloc is fully initialized, otherwise we might
         * read inconsistent state.
         */
-       if (binder_alloc_get_vma(alloc) != NULL) {
-               for (i = 0; i < alloc->buffer_size / PAGE_SIZE; i++) {
-                       page = &alloc->pages[i];
-                       if (!page->page_ptr)
-                               free++;
-                       else if (list_empty(&page->lru))
-                               active++;
-                       else
-                               lru++;
-               }
+
+       mmap_read_lock(alloc->vma_vm_mm);
+       if (binder_alloc_get_vma(alloc) == NULL) {
+               mmap_read_unlock(alloc->vma_vm_mm);
+               goto uninitialized;
        }
+
+       mmap_read_unlock(alloc->vma_vm_mm);
+       for (i = 0; i < alloc->buffer_size / PAGE_SIZE; i++) {
+               page = &alloc->pages[i];
+               if (!page->page_ptr)
+                       free++;
+               else if (list_empty(&page->lru))
+                       active++;
+               else
+                       lru++;
+       }
+
+uninitialized:
        mutex_unlock(&alloc->mutex);
        seq_printf(m, "  pages: %d:%d:%d\n", active, lru, free);
        seq_printf(m, "  pages high watermark: %zu\n", alloc->pages_high);
index e3c0ba9..ad92192 100644 (file)
@@ -979,6 +979,11 @@ loop_set_status_from_info(struct loop_device *lo,
 
        lo->lo_offset = info->lo_offset;
        lo->lo_sizelimit = info->lo_sizelimit;
+
+       /* loff_t vars have been assigned __u64 */
+       if (lo->lo_offset < 0 || lo->lo_sizelimit < 0)
+               return -EOVERFLOW;
+
        memcpy(lo->lo_file_name, info->lo_file_name, LO_NAME_SIZE);
        lo->lo_file_name[LO_NAME_SIZE-1] = 0;
        lo->lo_flags = info->lo_flags;
index 92cb929..226ea76 100644 (file)
@@ -1146,14 +1146,15 @@ static ssize_t bd_stat_show(struct device *dev,
 static ssize_t debug_stat_show(struct device *dev,
                struct device_attribute *attr, char *buf)
 {
-       int version = 2;
+       int version = 1;
        struct zram *zram = dev_to_zram(dev);
        ssize_t ret;
 
        down_read(&zram->init_lock);
        ret = scnprintf(buf, PAGE_SIZE,
-                       "version: %d\n%8llu\n",
+                       "version: %d\n%8llu %8llu\n",
                        version,
+                       (u64)atomic64_read(&zram->stats.writestall),
                        (u64)atomic64_read(&zram->stats.miss_free));
        up_read(&zram->init_lock);
 
@@ -1351,7 +1352,7 @@ static int __zram_bvec_write(struct zram *zram, struct bio_vec *bvec,
 {
        int ret = 0;
        unsigned long alloced_pages;
-       unsigned long handle = 0;
+       unsigned long handle = -ENOMEM;
        unsigned int comp_len = 0;
        void *src, *dst, *mem;
        struct zcomp_strm *zstrm;
@@ -1369,6 +1370,7 @@ static int __zram_bvec_write(struct zram *zram, struct bio_vec *bvec,
        }
        kunmap_atomic(mem);
 
+compress_again:
        zstrm = zcomp_stream_get(zram->comp);
        src = kmap_atomic(page);
        ret = zcomp_compress(zstrm, src, &comp_len);
@@ -1377,20 +1379,39 @@ static int __zram_bvec_write(struct zram *zram, struct bio_vec *bvec,
        if (unlikely(ret)) {
                zcomp_stream_put(zram->comp);
                pr_err("Compression failed! err=%d\n", ret);
+               zs_free(zram->mem_pool, handle);
                return ret;
        }
 
        if (comp_len >= huge_class_size)
                comp_len = PAGE_SIZE;
-
-       handle = zs_malloc(zram->mem_pool, comp_len,
-                       __GFP_KSWAPD_RECLAIM |
-                       __GFP_NOWARN |
-                       __GFP_HIGHMEM |
-                       __GFP_MOVABLE);
-
+       /*
+        * handle allocation has 2 paths:
+        * a) fast path is executed with preemption disabled (for
+        *  per-cpu streams) and has __GFP_DIRECT_RECLAIM bit clear,
+        *  since we can't sleep;
+        * b) slow path enables preemption and attempts to allocate
+        *  the page with __GFP_DIRECT_RECLAIM bit set. we have to
+        *  put per-cpu compression stream and, thus, to re-do
+        *  the compression once handle is allocated.
+        *
+        * if we have a 'non-null' handle here then we are coming
+        * from the slow path and handle has already been allocated.
+        */
+       if (IS_ERR((void *)handle))
+               handle = zs_malloc(zram->mem_pool, comp_len,
+                               __GFP_KSWAPD_RECLAIM |
+                               __GFP_NOWARN |
+                               __GFP_HIGHMEM |
+                               __GFP_MOVABLE);
        if (IS_ERR((void *)handle)) {
                zcomp_stream_put(zram->comp);
+               atomic64_inc(&zram->stats.writestall);
+               handle = zs_malloc(zram->mem_pool, comp_len,
+                               GFP_NOIO | __GFP_HIGHMEM |
+                               __GFP_MOVABLE);
+               if (!IS_ERR((void *)handle))
+                       goto compress_again;
                return PTR_ERR((void *)handle);
        }
 
@@ -1948,6 +1969,7 @@ static int zram_add(void)
        if (ZRAM_LOGICAL_BLOCK_SIZE == PAGE_SIZE)
                blk_queue_max_write_zeroes_sectors(zram->disk->queue, UINT_MAX);
 
+       blk_queue_flag_set(QUEUE_FLAG_STABLE_WRITES, zram->disk->queue);
        ret = device_add_disk(NULL, zram->disk, zram_disk_groups);
        if (ret)
                goto out_cleanup_disk;
index 158c91e..80c3b43 100644 (file)
@@ -81,6 +81,7 @@ struct zram_stats {
        atomic64_t huge_pages_since;    /* no. of huge pages since zram set up */
        atomic64_t pages_stored;        /* no. of pages currently stored */
        atomic_long_t max_used_pages;   /* no. of maximum pages stored */
+       atomic64_t writestall;          /* no. of write slow paths */
        atomic64_t miss_free;           /* no. of missed free */
 #ifdef CONFIG_ZRAM_WRITEBACK
        atomic64_t bd_count;            /* no. of pages in backing device */
index 84ca98e..32a932a 100644 (file)
@@ -480,6 +480,11 @@ static ssize_t splice_write_null(struct pipe_inode_info *pipe, struct file *out,
        return splice_from_pipe(pipe, out, ppos, len, flags, pipe_to_null);
 }
 
+static int uring_cmd_null(struct io_uring_cmd *ioucmd, unsigned int issue_flags)
+{
+       return 0;
+}
+
 static ssize_t read_iter_zero(struct kiocb *iocb, struct iov_iter *iter)
 {
        size_t written = 0;
@@ -663,6 +668,7 @@ static const struct file_operations null_fops = {
        .read_iter      = read_iter_null,
        .write_iter     = write_iter_null,
        .splice_write   = splice_write_null,
+       .uring_cmd      = uring_cmd_null,
 };
 
 static const struct file_operations __maybe_unused port_fops = {
index 7820c4e..69b3d61 100644 (file)
@@ -532,7 +532,7 @@ static unsigned int __resolve_freq(struct cpufreq_policy *policy,
 
        target_freq = clamp_val(target_freq, policy->min, policy->max);
 
-       if (!cpufreq_driver->target_index)
+       if (!policy->freq_table)
                return target_freq;
 
        idx = cpufreq_frequency_table_target(policy, target_freq, relation);
index f191a1f..0eb6b61 100644 (file)
@@ -630,7 +630,7 @@ static int __init dmi_smbios3_present(const u8 *buf)
 {
        if (memcmp(buf, "_SM3_", 5) == 0 &&
            buf[6] < 32 && dmi_checksum(buf, buf[6])) {
-               dmi_ver = get_unaligned_be32(buf + 6) & 0xFFFFFF;
+               dmi_ver = get_unaligned_be24(buf + 7);
                dmi_num = 0;                    /* No longer specified */
                dmi_len = get_unaligned_le32(buf + 12);
                dmi_base = get_unaligned_le64(buf + 16);
index e8a0b19..f095a25 100644 (file)
@@ -2456,12 +2456,14 @@ static int amdgpu_device_ip_init(struct amdgpu_device *adev)
                        if (!hive->reset_domain ||
                            !amdgpu_reset_get_reset_domain(hive->reset_domain)) {
                                r = -ENOENT;
+                               amdgpu_put_xgmi_hive(hive);
                                goto init_failed;
                        }
 
                        /* Drop the early temporary reset domain we created for device */
                        amdgpu_reset_put_reset_domain(adev->reset_domain);
                        adev->reset_domain = hive->reset_domain;
+                       amdgpu_put_xgmi_hive(hive);
                }
        }
 
@@ -4413,8 +4415,6 @@ static int amdgpu_device_reset_sriov(struct amdgpu_device *adev,
 retry:
        amdgpu_amdkfd_pre_reset(adev);
 
-       amdgpu_amdkfd_pre_reset(adev);
-
        if (from_hypervisor)
                r = amdgpu_virt_request_full_gpu(adev, true);
        else
index b067ce4..1036446 100644 (file)
@@ -2641,6 +2641,9 @@ static int psp_hw_fini(void *handle)
                psp_rap_terminate(psp);
                psp_dtm_terminate(psp);
                psp_hdcp_terminate(psp);
+
+               if (adev->gmc.xgmi.num_physical_nodes > 1)
+                       psp_xgmi_terminate(psp);
        }
 
        psp_asd_terminate(psp);
index 1b108d0..f2aebbf 100644 (file)
@@ -742,7 +742,7 @@ int amdgpu_xgmi_remove_device(struct amdgpu_device *adev)
                amdgpu_put_xgmi_hive(hive);
        }
 
-       return psp_xgmi_terminate(&adev->psp);
+       return 0;
 }
 
 static int amdgpu_xgmi_ras_late_init(struct amdgpu_device *adev, struct ras_common_if *ras_block)
index 158d87e..f6b1bb4 100644 (file)
@@ -131,6 +131,8 @@ static void gfx_v11_0_ring_invalidate_tlbs(struct amdgpu_ring *ring,
                                           bool all_hub, uint8_t dst_sel);
 static void gfx_v11_0_set_safe_mode(struct amdgpu_device *adev);
 static void gfx_v11_0_unset_safe_mode(struct amdgpu_device *adev);
+static void gfx_v11_0_update_perf_clk(struct amdgpu_device *adev,
+                                     bool enable);
 
 static void gfx11_kiq_set_resources(struct amdgpu_ring *kiq_ring, uint64_t queue_mask)
 {
@@ -1139,6 +1141,7 @@ static const struct amdgpu_gfx_funcs gfx_v11_0_gfx_funcs = {
        .read_wave_vgprs = &gfx_v11_0_read_wave_vgprs,
        .select_me_pipe_q = &gfx_v11_0_select_me_pipe_q,
        .init_spm_golden = &gfx_v11_0_init_spm_golden_registers,
+       .update_perfmon_mgcg = &gfx_v11_0_update_perf_clk,
 };
 
 static int gfx_v11_0_gpu_early_init(struct amdgpu_device *adev)
@@ -5182,9 +5185,12 @@ static void gfx_v11_0_update_coarse_grain_clock_gating(struct amdgpu_device *ade
                data = REG_SET_FIELD(data, SDMA0_RLC_CGCG_CTRL, CGCG_INT_ENABLE, 1);
                WREG32_SOC15(GC, 0, regSDMA0_RLC_CGCG_CTRL, data);
 
-               data = RREG32_SOC15(GC, 0, regSDMA1_RLC_CGCG_CTRL);
-               data = REG_SET_FIELD(data, SDMA1_RLC_CGCG_CTRL, CGCG_INT_ENABLE, 1);
-               WREG32_SOC15(GC, 0, regSDMA1_RLC_CGCG_CTRL, data);
+               /* Some ASICs only have one SDMA instance, not need to configure SDMA1 */
+               if (adev->sdma.num_instances > 1) {
+                       data = RREG32_SOC15(GC, 0, regSDMA1_RLC_CGCG_CTRL);
+                       data = REG_SET_FIELD(data, SDMA1_RLC_CGCG_CTRL, CGCG_INT_ENABLE, 1);
+                       WREG32_SOC15(GC, 0, regSDMA1_RLC_CGCG_CTRL, data);
+               }
        } else {
                /* Program RLC_CGCG_CGLS_CTRL */
                def = data = RREG32_SOC15(GC, 0, regRLC_CGCG_CGLS_CTRL);
@@ -5213,9 +5219,12 @@ static void gfx_v11_0_update_coarse_grain_clock_gating(struct amdgpu_device *ade
                data &= ~SDMA0_RLC_CGCG_CTRL__CGCG_INT_ENABLE_MASK;
                WREG32_SOC15(GC, 0, regSDMA0_RLC_CGCG_CTRL, data);
 
-               data = RREG32_SOC15(GC, 0, regSDMA1_RLC_CGCG_CTRL);
-               data &= ~SDMA1_RLC_CGCG_CTRL__CGCG_INT_ENABLE_MASK;
-               WREG32_SOC15(GC, 0, regSDMA1_RLC_CGCG_CTRL, data);
+               /* Some ASICs only have one SDMA instance, not need to configure SDMA1 */
+               if (adev->sdma.num_instances > 1) {
+                       data = RREG32_SOC15(GC, 0, regSDMA1_RLC_CGCG_CTRL);
+                       data &= ~SDMA1_RLC_CGCG_CTRL__CGCG_INT_ENABLE_MASK;
+                       WREG32_SOC15(GC, 0, regSDMA1_RLC_CGCG_CTRL, data);
+               }
        }
 }
 
@@ -5328,8 +5337,7 @@ static int gfx_v11_0_set_powergating_state(void *handle,
                break;
        case IP_VERSION(11, 0, 1):
                gfx_v11_cntl_pg(adev, enable);
-               /* TODO: Enable this when GFXOFF is ready */
-               // amdgpu_gfx_off_ctrl(adev, enable);
+               amdgpu_gfx_off_ctrl(adev, enable);
                break;
        default:
                break;
index c6e0f93..fc9c104 100644 (file)
@@ -2587,7 +2587,8 @@ static void gfx_v9_0_constants_init(struct amdgpu_device *adev)
 
        gfx_v9_0_tiling_mode_table_init(adev);
 
-       gfx_v9_0_setup_rb(adev);
+       if (adev->gfx.num_gfx_rings)
+               gfx_v9_0_setup_rb(adev);
        gfx_v9_0_get_cu_info(adev, &adev->gfx.cu_info);
        adev->gfx.config.db_debug2 = RREG32_SOC15(GC, 0, mmDB_DEBUG2);
 
index 3f44a09..3e51e77 100644 (file)
@@ -176,6 +176,7 @@ static void mmhub_v1_0_init_cache_regs(struct amdgpu_device *adev)
        tmp = REG_SET_FIELD(tmp, VM_L2_CNTL2, INVALIDATE_L2_CACHE, 1);
        WREG32_SOC15(MMHUB, 0, mmVM_L2_CNTL2, tmp);
 
+       tmp = mmVM_L2_CNTL3_DEFAULT;
        if (adev->gmc.translate_further) {
                tmp = REG_SET_FIELD(tmp, VM_L2_CNTL3, BANK_SELECT, 12);
                tmp = REG_SET_FIELD(tmp, VM_L2_CNTL3,
index 6e0145b..445cb06 100644 (file)
@@ -295,9 +295,17 @@ static void mmhub_v9_4_disable_identity_aperture(struct amdgpu_device *adev,
 static void mmhub_v9_4_setup_vmid_config(struct amdgpu_device *adev, int hubid)
 {
        struct amdgpu_vmhub *hub = &adev->vmhub[AMDGPU_MMHUB_0];
+       unsigned int num_level, block_size;
        uint32_t tmp;
        int i;
 
+       num_level = adev->vm_manager.num_level;
+       block_size = adev->vm_manager.block_size;
+       if (adev->gmc.translate_further)
+               num_level -= 1;
+       else
+               block_size -= 9;
+
        for (i = 0; i <= 14; i++) {
                tmp = RREG32_SOC15_OFFSET(MMHUB, 0, mmVML2VC0_VM_CONTEXT1_CNTL,
                                hubid * MMHUB_INSTANCE_REGISTER_OFFSET + i);
@@ -305,7 +313,7 @@ static void mmhub_v9_4_setup_vmid_config(struct amdgpu_device *adev, int hubid)
                                    ENABLE_CONTEXT, 1);
                tmp = REG_SET_FIELD(tmp, VML2VC0_VM_CONTEXT1_CNTL,
                                    PAGE_TABLE_DEPTH,
-                                   adev->vm_manager.num_level);
+                                   num_level);
                tmp = REG_SET_FIELD(tmp, VML2VC0_VM_CONTEXT1_CNTL,
                                    RANGE_PROTECTION_FAULT_ENABLE_DEFAULT, 1);
                tmp = REG_SET_FIELD(tmp, VML2VC0_VM_CONTEXT1_CNTL,
@@ -323,7 +331,7 @@ static void mmhub_v9_4_setup_vmid_config(struct amdgpu_device *adev, int hubid)
                                    EXECUTE_PROTECTION_FAULT_ENABLE_DEFAULT, 1);
                tmp = REG_SET_FIELD(tmp, VML2VC0_VM_CONTEXT1_CNTL,
                                    PAGE_TABLE_BLOCK_SIZE,
-                                   adev->vm_manager.block_size - 9);
+                                   block_size);
                /* Send no-retry XNACK on fault to suppress VM fault storm. */
                tmp = REG_SET_FIELD(tmp, VML2VC0_VM_CONTEXT1_CNTL,
                                    RETRY_PERMISSION_OR_INVALID_PAGE_FAULT,
index 01e8288..1dc95ef 100644 (file)
@@ -247,6 +247,81 @@ static void nbio_v7_7_init_registers(struct amdgpu_device *adev)
 
 }
 
+static void nbio_v7_7_update_medium_grain_clock_gating(struct amdgpu_device *adev,
+                                                      bool enable)
+{
+       uint32_t def, data;
+
+       if (enable && !(adev->cg_flags & AMD_CG_SUPPORT_BIF_MGCG))
+               return;
+
+       def = data = RREG32_SOC15(NBIO, 0, regBIF0_CPM_CONTROL);
+       if (enable) {
+               data |= (BIF0_CPM_CONTROL__LCLK_DYN_GATE_ENABLE_MASK |
+                        BIF0_CPM_CONTROL__TXCLK_DYN_GATE_ENABLE_MASK |
+                        BIF0_CPM_CONTROL__TXCLK_LCNT_GATE_ENABLE_MASK |
+                        BIF0_CPM_CONTROL__TXCLK_REGS_GATE_ENABLE_MASK |
+                        BIF0_CPM_CONTROL__TXCLK_PRBS_GATE_ENABLE_MASK |
+                        BIF0_CPM_CONTROL__REFCLK_REGS_GATE_ENABLE_MASK);
+       } else {
+               data &= ~(BIF0_CPM_CONTROL__LCLK_DYN_GATE_ENABLE_MASK |
+                         BIF0_CPM_CONTROL__TXCLK_DYN_GATE_ENABLE_MASK |
+                         BIF0_CPM_CONTROL__TXCLK_LCNT_GATE_ENABLE_MASK |
+                         BIF0_CPM_CONTROL__TXCLK_REGS_GATE_ENABLE_MASK |
+                         BIF0_CPM_CONTROL__TXCLK_PRBS_GATE_ENABLE_MASK |
+                         BIF0_CPM_CONTROL__REFCLK_REGS_GATE_ENABLE_MASK);
+       }
+
+       if (def != data)
+               WREG32_SOC15(NBIO, 0, regBIF0_CPM_CONTROL, data);
+}
+
+static void nbio_v7_7_update_medium_grain_light_sleep(struct amdgpu_device *adev,
+                                                     bool enable)
+{
+       uint32_t def, data;
+
+       if (enable && !(adev->cg_flags & AMD_CG_SUPPORT_BIF_LS))
+               return;
+
+       def = data = RREG32_SOC15(NBIO, 0, regBIF0_PCIE_CNTL2);
+       if (enable)
+               data |= BIF0_PCIE_CNTL2__SLV_MEM_LS_EN_MASK;
+       else
+               data &= ~BIF0_PCIE_CNTL2__SLV_MEM_LS_EN_MASK;
+
+       if (def != data)
+               WREG32_SOC15(NBIO, 0, regBIF0_PCIE_CNTL2, data);
+
+       def = data = RREG32_SOC15(NBIO, 0, regBIF0_PCIE_TX_POWER_CTRL_1);
+       if (enable) {
+               data |= (BIF0_PCIE_TX_POWER_CTRL_1__MST_MEM_LS_EN_MASK |
+                       BIF0_PCIE_TX_POWER_CTRL_1__REPLAY_MEM_LS_EN_MASK);
+       } else {
+               data &= ~(BIF0_PCIE_TX_POWER_CTRL_1__MST_MEM_LS_EN_MASK |
+                       BIF0_PCIE_TX_POWER_CTRL_1__REPLAY_MEM_LS_EN_MASK);
+       }
+
+       if (def != data)
+               WREG32_SOC15(NBIO, 0, regBIF0_PCIE_TX_POWER_CTRL_1, data);
+}
+
+static void nbio_v7_7_get_clockgating_state(struct amdgpu_device *adev,
+                                           u64 *flags)
+{
+       uint32_t data;
+
+       /* AMD_CG_SUPPORT_BIF_MGCG */
+       data = RREG32_SOC15(NBIO, 0, regBIF0_CPM_CONTROL);
+       if (data & BIF0_CPM_CONTROL__LCLK_DYN_GATE_ENABLE_MASK)
+               *flags |= AMD_CG_SUPPORT_BIF_MGCG;
+
+       /* AMD_CG_SUPPORT_BIF_LS */
+       data = RREG32_SOC15(NBIO, 0, regBIF0_PCIE_CNTL2);
+       if (data & BIF0_PCIE_CNTL2__SLV_MEM_LS_EN_MASK)
+               *flags |= AMD_CG_SUPPORT_BIF_LS;
+}
+
 const struct amdgpu_nbio_funcs nbio_v7_7_funcs = {
        .get_hdp_flush_req_offset = nbio_v7_7_get_hdp_flush_req_offset,
        .get_hdp_flush_done_offset = nbio_v7_7_get_hdp_flush_done_offset,
@@ -262,6 +337,9 @@ const struct amdgpu_nbio_funcs nbio_v7_7_funcs = {
        .enable_doorbell_aperture = nbio_v7_7_enable_doorbell_aperture,
        .enable_doorbell_selfring_aperture = nbio_v7_7_enable_doorbell_selfring_aperture,
        .ih_doorbell_range = nbio_v7_7_ih_doorbell_range,
+       .update_medium_grain_clock_gating = nbio_v7_7_update_medium_grain_clock_gating,
+       .update_medium_grain_light_sleep = nbio_v7_7_update_medium_grain_light_sleep,
+       .get_clockgating_state = nbio_v7_7_get_clockgating_state,
        .ih_control = nbio_v7_7_ih_control,
        .init_registers = nbio_v7_7_init_registers,
 };
index 1ff7fc7..55284b2 100644 (file)
@@ -494,6 +494,20 @@ static void soc21_pre_asic_init(struct amdgpu_device *adev)
 {
 }
 
+static int soc21_update_umd_stable_pstate(struct amdgpu_device *adev,
+                                         bool enter)
+{
+       if (enter)
+               amdgpu_gfx_rlc_enter_safe_mode(adev);
+       else
+               amdgpu_gfx_rlc_exit_safe_mode(adev);
+
+       if (adev->gfx.funcs->update_perfmon_mgcg)
+               adev->gfx.funcs->update_perfmon_mgcg(adev, !enter);
+
+       return 0;
+}
+
 static const struct amdgpu_asic_funcs soc21_asic_funcs =
 {
        .read_disabled_bios = &soc21_read_disabled_bios,
@@ -513,6 +527,7 @@ static const struct amdgpu_asic_funcs soc21_asic_funcs =
        .supports_baco = &amdgpu_dpm_is_baco_supported,
        .pre_asic_init = &soc21_pre_asic_init,
        .query_video_codecs = &soc21_query_video_codecs,
+       .update_umd_stable_pstate = &soc21_update_umd_stable_pstate,
 };
 
 static int soc21_common_early_init(void *handle)
@@ -603,6 +618,8 @@ static int soc21_common_early_init(void *handle)
                        AMD_CG_SUPPORT_ATHUB_MGCG |
                        AMD_CG_SUPPORT_ATHUB_LS |
                        AMD_CG_SUPPORT_IH_CG |
+                       AMD_CG_SUPPORT_BIF_MGCG |
+                       AMD_CG_SUPPORT_BIF_LS |
                        AMD_CG_SUPPORT_VCN_MGCG |
                        AMD_CG_SUPPORT_JPEG_MGCG;
                adev->pg_flags =
@@ -702,6 +719,7 @@ static int soc21_common_set_clockgating_state(void *handle,
        switch (adev->ip_versions[NBIO_HWIP][0]) {
        case IP_VERSION(4, 3, 0):
        case IP_VERSION(4, 3, 1):
+       case IP_VERSION(7, 7, 0):
                adev->nbio.funcs->update_medium_grain_clock_gating(adev,
                                state == AMD_CG_STATE_GATE);
                adev->nbio.funcs->update_medium_grain_light_sleep(adev,
@@ -709,10 +727,6 @@ static int soc21_common_set_clockgating_state(void *handle,
                adev->hdp.funcs->update_clock_gating(adev,
                                state == AMD_CG_STATE_GATE);
                break;
-       case IP_VERSION(7, 7, 0):
-               adev->hdp.funcs->update_clock_gating(adev,
-                               state == AMD_CG_STATE_GATE);
-               break;
        default:
                break;
        }
index 357298e..22c0929 100644 (file)
@@ -382,12 +382,8 @@ struct kfd_dev *kgd2kfd_probe(struct amdgpu_device *adev, bool vf)
                                f2g = &gfx_v10_3_kfd2kgd;
                        break;
                case IP_VERSION(10, 3, 6):
-                       gfx_target_version = 100306;
-                       if (!vf)
-                               f2g = &gfx_v10_3_kfd2kgd;
-                       break;
                case IP_VERSION(10, 3, 7):
-                       gfx_target_version = 100307;
+                       gfx_target_version = 100306;
                        if (!vf)
                                f2g = &gfx_v10_3_kfd2kgd;
                        break;
index fca7cf9..987bde4 100644 (file)
@@ -34,6 +34,7 @@
 #include "dal_asic_id.h"
 #include "amdgpu_display.h"
 #include "amdgpu_dm_trace.h"
+#include "amdgpu_dm_plane.h"
 #include "gc/gc_11_0_0_offset.h"
 #include "gc/gc_11_0_0_sh_mask.h"
 
@@ -149,12 +150,12 @@ static void add_modifier(uint64_t **mods, uint64_t *size, uint64_t *cap, uint64_
        *size += 1;
 }
 
-bool modifier_has_dcc(uint64_t modifier)
+static bool modifier_has_dcc(uint64_t modifier)
 {
        return IS_AMD_FMT_MOD(modifier) && AMD_FMT_MOD_GET(DCC, modifier);
 }
 
-unsigned modifier_gfx9_swizzle_mode(uint64_t modifier)
+static unsigned modifier_gfx9_swizzle_mode(uint64_t modifier)
 {
        if (modifier == DRM_FORMAT_MOD_LINEAR)
                return 0;
index 95168c2..286981a 100644 (file)
@@ -36,17 +36,9 @@ int fill_dc_scaling_info(struct amdgpu_device *adev,
                         const struct drm_plane_state *state,
                         struct dc_scaling_info *scaling_info);
 
-void get_min_max_dc_plane_scaling(struct drm_device *dev,
-                                 struct drm_framebuffer *fb,
-                                 int *min_downscale, int *max_upscale);
-
 int dm_plane_helper_check_state(struct drm_plane_state *state,
                                struct drm_crtc_state *new_crtc_state);
 
-bool modifier_has_dcc(uint64_t modifier);
-
-unsigned int modifier_gfx9_swizzle_mode(uint64_t modifier);
-
 int fill_plane_buffer_attributes(struct amdgpu_device *adev,
                                 const struct amdgpu_framebuffer *afb,
                                 const enum surface_pixel_format format,
index 85f3220..3a9e387 100644 (file)
@@ -1750,6 +1750,7 @@ static bool dcn314_resource_construct(
        dc->caps.post_blend_color_processing = true;
        dc->caps.force_dp_tps4_for_cp2520 = true;
        dc->caps.dp_hpo = true;
+       dc->caps.dp_hdmi21_pcon_support = true;
        dc->caps.edp_dsc_support = true;
        dc->caps.extended_aux_timeout_support = true;
        dc->caps.dmcub_support = true;
index 2ed9579..cf8d60c 100644 (file)
 #define regBIF0_PCIE_TX_TRACKING_ADDR_HI_BASE_IDX                                                       5
 #define regBIF0_PCIE_TX_TRACKING_CTRL_STATUS                                                            0x420186
 #define regBIF0_PCIE_TX_TRACKING_CTRL_STATUS_BASE_IDX                                                   5
+#define regBIF0_PCIE_TX_POWER_CTRL_1                                                                    0x420187
+#define regBIF0_PCIE_TX_POWER_CTRL_1_BASE_IDX                                                           5
 #define regBIF0_PCIE_TX_CTRL_4                                                                          0x42018b
 #define regBIF0_PCIE_TX_CTRL_4_BASE_IDX                                                                 5
 #define regBIF0_PCIE_TX_STATUS                                                                          0x420194
index eb62a18..3d60c9e 100644 (file)
 #define BIF0_PCIE_TX_TRACKING_CTRL_STATUS__TX_TRACKING_PORT_MASK                                              0x0000000EL
 #define BIF0_PCIE_TX_TRACKING_CTRL_STATUS__TX_TRACKING_UNIT_ID_MASK                                           0x00007F00L
 #define BIF0_PCIE_TX_TRACKING_CTRL_STATUS__TX_TRACKING_STATUS_VALID_MASK                                      0x00008000L
+//BIF0_PCIE_TX_POWER_CTRL_1
+#define BIF0_PCIE_TX_POWER_CTRL_1__MST_MEM_LS_EN__SHIFT                                                       0x0
+#define BIF0_PCIE_TX_POWER_CTRL_1__MST_MEM_DS_EN__SHIFT                                                       0x1
+#define BIF0_PCIE_TX_POWER_CTRL_1__MST_MEM_SD_EN__SHIFT                                                       0x2
+#define BIF0_PCIE_TX_POWER_CTRL_1__REPLAY_MEM_LS_EN__SHIFT                                                    0x3
+#define BIF0_PCIE_TX_POWER_CTRL_1__REPLAY_MEM_DS_EN__SHIFT                                                    0x4
+#define BIF0_PCIE_TX_POWER_CTRL_1__REPLAY_MEM_SD_EN__SHIFT                                                    0x5
+#define BIF0_PCIE_TX_POWER_CTRL_1__MST_MEM_LS_EN_MASK                                                         0x00000001L
+#define BIF0_PCIE_TX_POWER_CTRL_1__MST_MEM_DS_EN_MASK                                                         0x00000002L
+#define BIF0_PCIE_TX_POWER_CTRL_1__MST_MEM_SD_EN_MASK                                                         0x00000004L
+#define BIF0_PCIE_TX_POWER_CTRL_1__REPLAY_MEM_LS_EN_MASK                                                      0x00000008L
+#define BIF0_PCIE_TX_POWER_CTRL_1__REPLAY_MEM_DS_EN_MASK                                                      0x00000010L
+#define BIF0_PCIE_TX_POWER_CTRL_1__REPLAY_MEM_SD_EN_MASK                                                      0x00000020L
 //BIF0_PCIE_TX_CTRL_4
 #define BIF0_PCIE_TX_CTRL_4__TX_PORT_ACCESS_TIMER_SKEW__SHIFT                                                 0x0
 #define BIF0_PCIE_TX_CTRL_4__TX_PORT_ACCESS_TIMER_SKEW_MASK                                                   0x0000000FL
index 78620b0..f745cd8 100644 (file)
 #ifndef SMU13_DRIVER_IF_V13_0_0_H
 #define SMU13_DRIVER_IF_V13_0_0_H
 
-// *** IMPORTANT ***
-// PMFW TEAM: Always increment the interface version on any change to this file
-#define SMU13_DRIVER_IF_VERSION  0x23
-
 //Increment this version if SkuTable_t or BoardTable_t change
-#define PPTABLE_VERSION 0x1D
+#define PPTABLE_VERSION 0x22
 
 #define NUM_GFXCLK_DPM_LEVELS    16
 #define NUM_SOCCLK_DPM_LEVELS    8
@@ -1193,8 +1189,17 @@ typedef struct {
   // SECTION: Advanced Options
   uint32_t          DebugOverrides;
 
+  // Section: Total Board Power idle vs active coefficients
+  uint8_t     TotalBoardPowerSupport;
+  uint8_t     TotalBoardPowerPadding[3];
+
+  int16_t     TotalIdleBoardPowerM;
+  int16_t     TotalIdleBoardPowerB;
+  int16_t     TotalBoardPowerM;
+  int16_t     TotalBoardPowerB;
+
   // SECTION: Sku Reserved
-  uint32_t         Spare[64];
+  uint32_t         Spare[61];
 
   // Padding for MMHUB - do not modify this
   uint32_t     MmHubPadding[8];
@@ -1259,7 +1264,8 @@ typedef struct {
   // SECTION: Clock Spread Spectrum
 
   // UCLK Spread Spectrum
-  uint16_t     UclkSpreadPadding;
+  uint8_t      UclkTrainingModeSpreadPercent;
+  uint8_t      UclkSpreadPadding;
   uint16_t     UclkSpreadFreq;      // kHz
 
   // UCLK Spread Spectrum
@@ -1272,11 +1278,7 @@ typedef struct {
 
   // Section: Memory Config
   uint8_t      DramWidth; // Width of interface to the channel for each DRAM module. See DRAM_BIT_WIDTH_TYPE_e
-  uint8_t      PaddingMem1[3];
-
-  // Section: Total Board Power
-  uint16_t     TotalBoardPower;     //Only needed for TCP Estimated case, where TCP = TGP+Total Board Power
-  uint16_t     BoardPowerPadding;
+  uint8_t      PaddingMem1[7];
 
   // SECTION: UMC feature flags
   uint8_t      HsrEnabled;
@@ -1375,8 +1377,11 @@ typedef struct {
   uint16_t Vcn1ActivityPercentage  ;
 
   uint32_t EnergyAccumulator;
-  uint16_t AverageSocketPower    ;
+  uint16_t AverageSocketPower;
+  uint16_t AverageTotalBoardPower;
+
   uint16_t AvgTemperature[TEMP_COUNT];
+  uint16_t TempPadding;
 
   uint8_t  PcieRate               ;
   uint8_t  PcieWidth              ;
index 6fe2fe9..ac308e7 100644 (file)
@@ -30,7 +30,7 @@
 #define SMU13_DRIVER_IF_VERSION_ALDE 0x08
 #define SMU13_DRIVER_IF_VERSION_SMU_V13_0_4 0x05
 #define SMU13_DRIVER_IF_VERSION_SMU_V13_0_5 0x04
-#define SMU13_DRIVER_IF_VERSION_SMU_V13_0_0 0x2C
+#define SMU13_DRIVER_IF_VERSION_SMU_V13_0_0 0x2E
 #define SMU13_DRIVER_IF_VERSION_SMU_V13_0_7 0x2C
 
 #define SMU13_MODE1_RESET_WAIT_TIME_IN_MS 500  //500ms
index 86d670c..ad06886 100644 (file)
@@ -168,21 +168,6 @@ void drm_gem_private_object_init(struct drm_device *dev,
 }
 EXPORT_SYMBOL(drm_gem_private_object_init);
 
-static void
-drm_gem_remove_prime_handles(struct drm_gem_object *obj, struct drm_file *filp)
-{
-       /*
-        * Note: obj->dma_buf can't disappear as long as we still hold a
-        * handle reference in obj->handle_count.
-        */
-       mutex_lock(&filp->prime.lock);
-       if (obj->dma_buf) {
-               drm_prime_remove_buf_handle_locked(&filp->prime,
-                                                  obj->dma_buf);
-       }
-       mutex_unlock(&filp->prime.lock);
-}
-
 /**
  * drm_gem_object_handle_free - release resources bound to userspace handles
  * @obj: GEM object to clean up.
@@ -253,7 +238,7 @@ drm_gem_object_release_handle(int id, void *ptr, void *data)
        if (obj->funcs->close)
                obj->funcs->close(obj, file_priv);
 
-       drm_gem_remove_prime_handles(obj, file_priv);
+       drm_prime_remove_buf_handle(&file_priv->prime, id);
        drm_vma_node_revoke(&obj->vma_node, file_priv);
 
        drm_gem_object_handle_put_unlocked(obj);
index 1fbbc19..7bb98e6 100644 (file)
@@ -74,8 +74,8 @@ int drm_prime_fd_to_handle_ioctl(struct drm_device *dev, void *data,
 
 void drm_prime_init_file_private(struct drm_prime_file_private *prime_fpriv);
 void drm_prime_destroy_file_private(struct drm_prime_file_private *prime_fpriv);
-void drm_prime_remove_buf_handle_locked(struct drm_prime_file_private *prime_fpriv,
-                                       struct dma_buf *dma_buf);
+void drm_prime_remove_buf_handle(struct drm_prime_file_private *prime_fpriv,
+                                uint32_t handle);
 
 /* drm_drv.c */
 struct drm_minor *drm_minor_acquire(unsigned int minor_id);
index a3f1806..eb09e86 100644 (file)
@@ -190,29 +190,33 @@ static int drm_prime_lookup_buf_handle(struct drm_prime_file_private *prime_fpri
        return -ENOENT;
 }
 
-void drm_prime_remove_buf_handle_locked(struct drm_prime_file_private *prime_fpriv,
-                                       struct dma_buf *dma_buf)
+void drm_prime_remove_buf_handle(struct drm_prime_file_private *prime_fpriv,
+                                uint32_t handle)
 {
        struct rb_node *rb;
 
-       rb = prime_fpriv->dmabufs.rb_node;
+       mutex_lock(&prime_fpriv->lock);
+
+       rb = prime_fpriv->handles.rb_node;
        while (rb) {
                struct drm_prime_member *member;
 
-               member = rb_entry(rb, struct drm_prime_member, dmabuf_rb);
-               if (member->dma_buf == dma_buf) {
+               member = rb_entry(rb, struct drm_prime_member, handle_rb);
+               if (member->handle == handle) {
                        rb_erase(&member->handle_rb, &prime_fpriv->handles);
                        rb_erase(&member->dmabuf_rb, &prime_fpriv->dmabufs);
 
-                       dma_buf_put(dma_buf);
+                       dma_buf_put(member->dma_buf);
                        kfree(member);
-                       return;
-               } else if (member->dma_buf < dma_buf) {
+                       break;
+               } else if (member->handle < handle) {
                        rb = rb->rb_right;
                } else {
                        rb = rb->rb_left;
                }
        }
+
+       mutex_unlock(&prime_fpriv->lock);
 }
 
 void drm_prime_init_file_private(struct drm_prime_file_private *prime_fpriv)
index 05076e5..e29175e 100644 (file)
@@ -820,6 +820,15 @@ nouveau_bo_move_m2mf(struct ttm_buffer_object *bo, int evict,
                if (ret == 0) {
                        ret = nouveau_fence_new(chan, false, &fence);
                        if (ret == 0) {
+                               /* TODO: figure out a better solution here
+                                *
+                                * wait on the fence here explicitly as going through
+                                * ttm_bo_move_accel_cleanup somehow doesn't seem to do it.
+                                *
+                                * Without this the operation can timeout and we'll fallback to a
+                                * software copy, which might take several minutes to finish.
+                                */
+                               nouveau_fence_wait(fence, false, false);
                                ret = ttm_bo_move_accel_cleanup(bo,
                                                                &fence->base,
                                                                evict, false,
index 2b12389..ee01656 100644 (file)
@@ -1605,6 +1605,9 @@ int radeon_suspend_kms(struct drm_device *dev, bool suspend,
                if (r) {
                        /* delay GPU reset to resume */
                        radeon_fence_driver_force_completion(rdev, i);
+               } else {
+                       /* finish executing delayed work */
+                       flush_delayed_work(&rdev->fence_drv[i].lockup_work);
                }
        }
 
index 061be9a..b0f3117 100644 (file)
@@ -8,6 +8,7 @@ config DRM_VC4
        depends on DRM
        depends on SND && SND_SOC
        depends on COMMON_CLK
+       depends on PM
        select DRM_DISPLAY_HDMI_HELPER
        select DRM_DISPLAY_HELPER
        select DRM_KMS_HELPER
index 592c3b5..1e5f687 100644 (file)
@@ -2855,7 +2855,7 @@ static int vc5_hdmi_init_resources(struct vc4_hdmi *vc4_hdmi)
        return 0;
 }
 
-static int __maybe_unused vc4_hdmi_runtime_suspend(struct device *dev)
+static int vc4_hdmi_runtime_suspend(struct device *dev)
 {
        struct vc4_hdmi *vc4_hdmi = dev_get_drvdata(dev);
 
@@ -2972,17 +2972,15 @@ static int vc4_hdmi_bind(struct device *dev, struct device *master, void *data)
                        vc4_hdmi->disable_4kp60 = true;
        }
 
+       pm_runtime_enable(dev);
+
        /*
-        * We need to have the device powered up at this point to call
-        * our reset hook and for the CEC init.
+        *  We need to have the device powered up at this point to call
+        *  our reset hook and for the CEC init.
         */
-       ret = vc4_hdmi_runtime_resume(dev);
+       ret = pm_runtime_resume_and_get(dev);
        if (ret)
-               goto err_put_ddc;
-
-       pm_runtime_get_noresume(dev);
-       pm_runtime_set_active(dev);
-       pm_runtime_enable(dev);
+               goto err_disable_runtime_pm;
 
        if ((of_device_is_compatible(dev->of_node, "brcm,bcm2711-hdmi0") ||
             of_device_is_compatible(dev->of_node, "brcm,bcm2711-hdmi1")) &&
@@ -3028,6 +3026,7 @@ err_destroy_conn:
 err_destroy_encoder:
        drm_encoder_cleanup(encoder);
        pm_runtime_put_sync(dev);
+err_disable_runtime_pm:
        pm_runtime_disable(dev);
 err_put_ddc:
        put_device(&vc4_hdmi->ddc->dev);
index 4b90c86..47774b9 100644 (file)
@@ -288,11 +288,29 @@ int amd_sfh_irq_init(struct amd_mp2_dev *privdata)
        return 0;
 }
 
+static const struct dmi_system_id dmi_nodevs[] = {
+       {
+               /*
+                * Google Chromebooks use Chrome OS Embedded Controller Sensor
+                * Hub instead of Sensor Hub Fusion and leaves MP2
+                * uninitialized, which disables all functionalities, even
+                * including the registers necessary for feature detections.
+                */
+               .matches = {
+                       DMI_MATCH(DMI_SYS_VENDOR, "Google"),
+               },
+       },
+       { }
+};
+
 static int amd_mp2_pci_probe(struct pci_dev *pdev, const struct pci_device_id *id)
 {
        struct amd_mp2_dev *privdata;
        int rc;
 
+       if (dmi_first_match(dmi_nodevs))
+               return -ENODEV;
+
        privdata = devm_kzalloc(&pdev->dev, sizeof(*privdata), GFP_KERNEL);
        if (!privdata)
                return -ENOMEM;
index 08c9a9a..b59c3da 100644 (file)
@@ -1212,6 +1212,13 @@ static __u8 *asus_report_fixup(struct hid_device *hdev, __u8 *rdesc,
                rdesc = new_rdesc;
        }
 
+       if (drvdata->quirks & QUIRK_ROG_NKEY_KEYBOARD &&
+                       *rsize == 331 && rdesc[190] == 0x85 && rdesc[191] == 0x5a &&
+                       rdesc[204] == 0x95 && rdesc[205] == 0x05) {
+               hid_info(hdev, "Fixing up Asus N-KEY keyb report descriptor\n");
+               rdesc[205] = 0x01;
+       }
+
        return rdesc;
 }
 
index 0fb720a..f80d619 100644 (file)
 #define USB_DEVICE_ID_APPLE_MAGIC_KEYBOARD_2021   0x029c
 #define USB_DEVICE_ID_APPLE_MAGIC_KEYBOARD_FINGERPRINT_2021   0x029a
 #define USB_DEVICE_ID_APPLE_MAGIC_KEYBOARD_NUMPAD_2021   0x029f
+#define USB_DEVICE_ID_APPLE_TOUCHBAR_BACKLIGHT 0x8102
+#define USB_DEVICE_ID_APPLE_TOUCHBAR_DISPLAY 0x8302
 
 #define USB_VENDOR_ID_ASUS             0x0486
 #define USB_DEVICE_ID_ASUS_T91MT       0x0185
 #define USB_DEVICE_ID_ASUS_UX550_TOUCHSCREEN   0x2706
 #define I2C_DEVICE_ID_SURFACE_GO_TOUCHSCREEN   0x261A
 #define I2C_DEVICE_ID_SURFACE_GO2_TOUCHSCREEN  0x2A1C
+#define I2C_DEVICE_ID_LENOVO_YOGA_C630_TOUCHSCREEN     0x279F
 
 #define USB_VENDOR_ID_ELECOM           0x056e
 #define USB_DEVICE_ID_ELECOM_BM084     0x0061
index 48c1c02..859aeb0 100644 (file)
@@ -383,6 +383,8 @@ static const struct hid_device_id hid_battery_quirks[] = {
          HID_BATTERY_QUIRK_IGNORE },
        { HID_I2C_DEVICE(USB_VENDOR_ID_ELAN, I2C_DEVICE_ID_SURFACE_GO2_TOUCHSCREEN),
          HID_BATTERY_QUIRK_IGNORE },
+       { HID_I2C_DEVICE(USB_VENDOR_ID_ELAN, I2C_DEVICE_ID_LENOVO_YOGA_C630_TOUCHSCREEN),
+         HID_BATTERY_QUIRK_IGNORE },
        {}
 };
 
@@ -1532,7 +1534,10 @@ void hidinput_hid_event(struct hid_device *hid, struct hid_field *field, struct
                         * assume ours
                         */
                        if (!report->tool)
-                               hid_report_set_tool(report, input, usage->code);
+                               report->tool = usage->code;
+
+                       /* drivers may have changed the value behind our back, resend it */
+                       hid_report_set_tool(report, input, report->tool);
                } else {
                        hid_report_release_tool(report, input, usage->code);
                }
index 92ac4f6..6028af3 100644 (file)
@@ -1221,6 +1221,7 @@ static void joycon_parse_report(struct joycon_ctlr *ctlr,
 
        spin_lock_irqsave(&ctlr->lock, flags);
        if (IS_ENABLED(CONFIG_NINTENDO_FF) && rep->vibrator_report &&
+           ctlr->ctlr_state != JOYCON_CTLR_STATE_REMOVED &&
            (msecs - ctlr->rumble_msecs) >= JC_RUMBLE_PERIOD_MS &&
            (ctlr->rumble_queue_head != ctlr->rumble_queue_tail ||
             ctlr->rumble_zero_countdown > 0)) {
@@ -1545,12 +1546,13 @@ static int joycon_set_rumble(struct joycon_ctlr *ctlr, u16 amp_r, u16 amp_l,
                ctlr->rumble_queue_head = 0;
        memcpy(ctlr->rumble_data[ctlr->rumble_queue_head], data,
               JC_RUMBLE_DATA_SIZE);
-       spin_unlock_irqrestore(&ctlr->lock, flags);
 
        /* don't wait for the periodic send (reduces latency) */
-       if (schedule_now)
+       if (schedule_now && ctlr->ctlr_state != JOYCON_CTLR_STATE_REMOVED)
                queue_work(ctlr->rumble_queue, &ctlr->rumble_worker);
 
+       spin_unlock_irqrestore(&ctlr->lock, flags);
+
        return 0;
 }
 
index dc67717..70f602c 100644 (file)
@@ -314,6 +314,8 @@ static const struct hid_device_id hid_have_special_driver[] = {
        { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_GEYSER1_TP_ONLY) },
        { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_MAGIC_KEYBOARD_2021) },
        { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_MAGIC_KEYBOARD_FINGERPRINT_2021) },
+       { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_TOUCHBAR_BACKLIGHT) },
+       { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_TOUCHBAR_DISPLAY) },
 #endif
 #if IS_ENABLED(CONFIG_HID_APPLEIR)
        { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_IRCONTROL) },
index a3b151b..fc616db 100644 (file)
@@ -134,6 +134,11 @@ static int steam_recv_report(struct steam_device *steam,
        int ret;
 
        r = steam->hdev->report_enum[HID_FEATURE_REPORT].report_id_hash[0];
+       if (!r) {
+               hid_err(steam->hdev, "No HID_FEATURE_REPORT submitted -  nothing to read\n");
+               return -EINVAL;
+       }
+
        if (hid_report_len(r) < 64)
                return -EINVAL;
 
@@ -165,6 +170,11 @@ static int steam_send_report(struct steam_device *steam,
        int ret;
 
        r = steam->hdev->report_enum[HID_FEATURE_REPORT].report_id_hash[0];
+       if (!r) {
+               hid_err(steam->hdev, "No HID_FEATURE_REPORT submitted -  nothing to read\n");
+               return -EINVAL;
+       }
+
        if (hid_report_len(r) < 64)
                return -EINVAL;
 
index c3e6d69..cf1679b 100644 (file)
@@ -67,12 +67,13 @@ static const struct tm_wheel_info tm_wheels_infos[] = {
        {0x0200, 0x0005, "Thrustmaster T300RS (Missing Attachment)"},
        {0x0206, 0x0005, "Thrustmaster T300RS"},
        {0x0209, 0x0005, "Thrustmaster T300RS (Open Wheel Attachment)"},
+       {0x020a, 0x0005, "Thrustmaster T300RS (Sparco R383 Mod)"},
        {0x0204, 0x0005, "Thrustmaster T300 Ferrari Alcantara Edition"},
        {0x0002, 0x0002, "Thrustmaster T500RS"}
        //{0x0407, 0x0001, "Thrustmaster TMX"}
 };
 
-static const uint8_t tm_wheels_infos_length = 4;
+static const uint8_t tm_wheels_infos_length = 7;
 
 /*
  * This structs contains (in little endian) the response data
index 681614a..197b1e7 100644 (file)
@@ -350,6 +350,8 @@ static int hidraw_release(struct inode * inode, struct file * file)
        down_write(&minors_rwsem);
 
        spin_lock_irqsave(&hidraw_table[minor]->list_lock, flags);
+       for (int i = list->tail; i < list->head; i++)
+               kfree(list->buffer[i].value);
        list_del(&list->node);
        spin_unlock_irqrestore(&hidraw_table[minor]->list_lock, flags);
        kfree(list);
index e600dbf..fc108f1 100644 (file)
@@ -32,6 +32,7 @@
 #define ADL_P_DEVICE_ID                0x51FC
 #define ADL_N_DEVICE_ID                0x54FC
 #define RPL_S_DEVICE_ID                0x7A78
+#define MTL_P_DEVICE_ID                0x7E45
 
 #define        REVISION_ID_CHT_A0      0x6
 #define        REVISION_ID_CHT_Ax_SI   0x0
index 2c67ec1..7120b30 100644 (file)
@@ -43,6 +43,7 @@ static const struct pci_device_id ish_pci_tbl[] = {
        {PCI_DEVICE(PCI_VENDOR_ID_INTEL, ADL_P_DEVICE_ID)},
        {PCI_DEVICE(PCI_VENDOR_ID_INTEL, ADL_N_DEVICE_ID)},
        {PCI_DEVICE(PCI_VENDOR_ID_INTEL, RPL_S_DEVICE_ID)},
+       {PCI_DEVICE(PCI_VENDOR_ID_INTEL, MTL_P_DEVICE_ID)},
        {0, }
 };
 MODULE_DEVICE_TABLE(pci, ish_pci_tbl);
index 6a5cc11..35dddc5 100644 (file)
@@ -105,7 +105,7 @@ struct report_list {
  * @multi_packet_cnt:  Count of fragmented packet count
  *
  * This structure is used to store completion flags and per client data like
- * like report description, number of HID devices etc.
+ * report description, number of HID devices etc.
  */
 struct ishtp_cl_data {
        /* completion flags */
index 405e0d5..df0a825 100644 (file)
@@ -626,13 +626,14 @@ static void ishtp_cl_read_complete(struct ishtp_cl_rb *rb)
 }
 
 /**
- * ipc_tx_callback() - IPC tx callback function
+ * ipc_tx_send() - IPC tx send function
  * @prm: Pointer to client device instance
  *
- * Send message over IPC either first time or on callback on previous message
- * completion
+ * Send message over IPC. Message will be split into fragments
+ * if message size is bigger than IPC FIFO size, and all
+ * fragments will be sent one by one.
  */
-static void ipc_tx_callback(void *prm)
+static void ipc_tx_send(void *prm)
 {
        struct ishtp_cl *cl = prm;
        struct ishtp_cl_tx_ring *cl_msg;
@@ -677,32 +678,41 @@ static void ipc_tx_callback(void *prm)
                            list);
        rem = cl_msg->send_buf.size - cl->tx_offs;
 
-       ishtp_hdr.host_addr = cl->host_client_id;
-       ishtp_hdr.fw_addr = cl->fw_client_id;
-       ishtp_hdr.reserved = 0;
-       pmsg = cl_msg->send_buf.data + cl->tx_offs;
+       while (rem > 0) {
+               ishtp_hdr.host_addr = cl->host_client_id;
+               ishtp_hdr.fw_addr = cl->fw_client_id;
+               ishtp_hdr.reserved = 0;
+               pmsg = cl_msg->send_buf.data + cl->tx_offs;
+
+               if (rem <= dev->mtu) {
+                       /* Last fragment or only one packet */
+                       ishtp_hdr.length = rem;
+                       ishtp_hdr.msg_complete = 1;
+                       /* Submit to IPC queue with no callback */
+                       ishtp_write_message(dev, &ishtp_hdr, pmsg);
+                       cl->tx_offs = 0;
+                       cl->sending = 0;
 
-       if (rem <= dev->mtu) {
-               ishtp_hdr.length = rem;
-               ishtp_hdr.msg_complete = 1;
-               cl->sending = 0;
-               list_del_init(&cl_msg->list);   /* Must be before write */
-               spin_unlock_irqrestore(&cl->tx_list_spinlock, tx_flags);
-               /* Submit to IPC queue with no callback */
-               ishtp_write_message(dev, &ishtp_hdr, pmsg);
-               spin_lock_irqsave(&cl->tx_free_list_spinlock, tx_free_flags);
-               list_add_tail(&cl_msg->list, &cl->tx_free_list.list);
-               ++cl->tx_ring_free_size;
-               spin_unlock_irqrestore(&cl->tx_free_list_spinlock,
-                       tx_free_flags);
-       } else {
-               /* Send IPC fragment */
-               spin_unlock_irqrestore(&cl->tx_list_spinlock, tx_flags);
-               cl->tx_offs += dev->mtu;
-               ishtp_hdr.length = dev->mtu;
-               ishtp_hdr.msg_complete = 0;
-               ishtp_send_msg(dev, &ishtp_hdr, pmsg, ipc_tx_callback, cl);
+                       break;
+               } else {
+                       /* Send ipc fragment */
+                       ishtp_hdr.length = dev->mtu;
+                       ishtp_hdr.msg_complete = 0;
+                       /* All fregments submitted to IPC queue with no callback */
+                       ishtp_write_message(dev, &ishtp_hdr, pmsg);
+                       cl->tx_offs += dev->mtu;
+                       rem = cl_msg->send_buf.size - cl->tx_offs;
+               }
        }
+
+       list_del_init(&cl_msg->list);
+       spin_unlock_irqrestore(&cl->tx_list_spinlock, tx_flags);
+
+       spin_lock_irqsave(&cl->tx_free_list_spinlock, tx_free_flags);
+       list_add_tail(&cl_msg->list, &cl->tx_free_list.list);
+       ++cl->tx_ring_free_size;
+       spin_unlock_irqrestore(&cl->tx_free_list_spinlock,
+               tx_free_flags);
 }
 
 /**
@@ -720,7 +730,7 @@ static void ishtp_cl_send_msg_ipc(struct ishtp_device *dev,
                return;
 
        cl->tx_offs = 0;
-       ipc_tx_callback(cl);
+       ipc_tx_send(cl);
        ++cl->send_msg_cnt_ipc;
 }
 
index afaf36b..729be2c 100644 (file)
@@ -5620,6 +5620,7 @@ struct mddev *md_alloc(dev_t dev, char *name)
         * removed (mddev_delayed_delete).
         */
        flush_workqueue(md_misc_wq);
+       flush_workqueue(md_rdev_misc_wq);
 
        mutex_lock(&disks_mutex);
        mddev = mddev_alloc(dev);
@@ -6238,11 +6239,11 @@ static void mddev_detach(struct mddev *mddev)
 static void __md_stop(struct mddev *mddev)
 {
        struct md_personality *pers = mddev->pers;
+       md_bitmap_destroy(mddev);
        mddev_detach(mddev);
        /* Ensure ->event_work is done */
        if (mddev->event_work.func)
                flush_workqueue(md_misc_wq);
-       md_bitmap_destroy(mddev);
        spin_lock(&mddev->lock);
        mddev->pers = NULL;
        spin_unlock(&mddev->lock);
@@ -6260,6 +6261,7 @@ void md_stop(struct mddev *mddev)
        /* stop the array and free an attached data structures.
         * This is called from dm-raid
         */
+       __md_stop_writes(mddev);
        __md_stop(mddev);
        bioset_exit(&mddev->bio_set);
        bioset_exit(&mddev->sync_set);
index 9117fcd..64d6e4c 100644 (file)
@@ -2639,18 +2639,18 @@ static void check_decay_read_errors(struct mddev *mddev, struct md_rdev *rdev)
 }
 
 static int r10_sync_page_io(struct md_rdev *rdev, sector_t sector,
-                           int sectors, struct page *page, int rw)
+                           int sectors, struct page *page, enum req_op op)
 {
        sector_t first_bad;
        int bad_sectors;
 
        if (is_badblock(rdev, sector, sectors, &first_bad, &bad_sectors)
-           && (rw == READ || test_bit(WriteErrorSeen, &rdev->flags)))
+           && (op == REQ_OP_READ || test_bit(WriteErrorSeen, &rdev->flags)))
                return -1;
-       if (sync_page_io(rdev, sector, sectors << 9, page, rw, false))
+       if (sync_page_io(rdev, sector, sectors << 9, page, op, false))
                /* success */
                return 1;
-       if (rw == WRITE) {
+       if (op == REQ_OP_WRITE) {
                set_bit(WriteErrorSeen, &rdev->flags);
                if (!test_and_set_bit(WantReplacement, &rdev->flags))
                        set_bit(MD_RECOVERY_NEEDED,
@@ -2780,7 +2780,7 @@ static void fix_read_error(struct r10conf *conf, struct mddev *mddev, struct r10
                        if (r10_sync_page_io(rdev,
                                             r10_bio->devs[sl].addr +
                                             sect,
-                                            s, conf->tmppage, WRITE)
+                                            s, conf->tmppage, REQ_OP_WRITE)
                            == 0) {
                                /* Well, this device is dead */
                                pr_notice("md/raid10:%s: read correction write failed (%d sectors at %llu on %pg)\n",
@@ -2814,8 +2814,7 @@ static void fix_read_error(struct r10conf *conf, struct mddev *mddev, struct r10
                        switch (r10_sync_page_io(rdev,
                                             r10_bio->devs[sl].addr +
                                             sect,
-                                            s, conf->tmppage,
-                                                READ)) {
+                                            s, conf->tmppage, REQ_OP_READ)) {
                        case 0:
                                /* Well, this device is dead */
                                pr_notice("md/raid10:%s: unable to read back corrected sectors (%d sectors at %llu on %pg)\n",
index 10c5639..e636088 100644 (file)
@@ -171,6 +171,7 @@ config MMC_SDHCI_OF_ASPEED
 config MMC_SDHCI_OF_ASPEED_TEST
        bool "Tests for the ASPEED SDHCI driver" if !KUNIT_ALL_TESTS
        depends on MMC_SDHCI_OF_ASPEED && KUNIT
+       depends on (MMC_SDHCI_OF_ASPEED=m || KUNIT=y)
        default KUNIT_ALL_TESTS
        help
          Enable KUnit tests for the ASPEED SDHCI driver. Select this
index d7fb33c..184608b 100644 (file)
@@ -84,7 +84,8 @@ enum ad_link_speed_type {
 static const u8 null_mac_addr[ETH_ALEN + 2] __long_aligned = {
        0, 0, 0, 0, 0, 0
 };
-static u16 ad_ticks_per_sec;
+
+static const u16 ad_ticks_per_sec = 1000 / AD_TIMER_INTERVAL;
 static const int ad_delta_in_ticks = (AD_TIMER_INTERVAL * HZ) / 1000;
 
 static const u8 lacpdu_mcast_addr[ETH_ALEN + 2] __long_aligned =
@@ -2001,36 +2002,24 @@ void bond_3ad_initiate_agg_selection(struct bonding *bond, int timeout)
 /**
  * bond_3ad_initialize - initialize a bond's 802.3ad parameters and structures
  * @bond: bonding struct to work on
- * @tick_resolution: tick duration (millisecond resolution)
  *
  * Can be called only after the mac address of the bond is set.
  */
-void bond_3ad_initialize(struct bonding *bond, u16 tick_resolution)
+void bond_3ad_initialize(struct bonding *bond)
 {
-       /* check that the bond is not initialized yet */
-       if (!MAC_ADDRESS_EQUAL(&(BOND_AD_INFO(bond).system.sys_mac_addr),
-                               bond->dev->dev_addr)) {
-
-               BOND_AD_INFO(bond).aggregator_identifier = 0;
-
-               BOND_AD_INFO(bond).system.sys_priority =
-                       bond->params.ad_actor_sys_prio;
-               if (is_zero_ether_addr(bond->params.ad_actor_system))
-                       BOND_AD_INFO(bond).system.sys_mac_addr =
-                           *((struct mac_addr *)bond->dev->dev_addr);
-               else
-                       BOND_AD_INFO(bond).system.sys_mac_addr =
-                           *((struct mac_addr *)bond->params.ad_actor_system);
-
-               /* initialize how many times this module is called in one
-                * second (should be about every 100ms)
-                */
-               ad_ticks_per_sec = tick_resolution;
+       BOND_AD_INFO(bond).aggregator_identifier = 0;
+       BOND_AD_INFO(bond).system.sys_priority =
+               bond->params.ad_actor_sys_prio;
+       if (is_zero_ether_addr(bond->params.ad_actor_system))
+               BOND_AD_INFO(bond).system.sys_mac_addr =
+                   *((struct mac_addr *)bond->dev->dev_addr);
+       else
+               BOND_AD_INFO(bond).system.sys_mac_addr =
+                   *((struct mac_addr *)bond->params.ad_actor_system);
 
-               bond_3ad_initiate_agg_selection(bond,
-                                               AD_AGGREGATOR_SELECTION_TIMER *
-                                               ad_ticks_per_sec);
-       }
+       bond_3ad_initiate_agg_selection(bond,
+                                       AD_AGGREGATOR_SELECTION_TIMER *
+                                       ad_ticks_per_sec);
 }
 
 /**
index 50e6084..2f4da2c 100644 (file)
@@ -2081,7 +2081,7 @@ int bond_enslave(struct net_device *bond_dev, struct net_device *slave_dev,
                        /* Initialize AD with the number of times that the AD timer is called in 1 second
                         * can be called only after the mac address of the bond is set
                         */
-                       bond_3ad_initialize(bond, 1000/AD_TIMER_INTERVAL);
+                       bond_3ad_initialize(bond);
                } else {
                        SLAVE_AD_INFO(new_slave)->id =
                                SLAVE_AD_INFO(prev_slave)->id + 1;
index ed7d137..6bd69a7 100644 (file)
@@ -803,9 +803,15 @@ static void ksz_phylink_get_caps(struct dsa_switch *ds, int port,
        if (dev->info->supports_rgmii[port])
                phy_interface_set_rgmii(config->supported_interfaces);
 
-       if (dev->info->internal_phy[port])
+       if (dev->info->internal_phy[port]) {
                __set_bit(PHY_INTERFACE_MODE_INTERNAL,
                          config->supported_interfaces);
+               /* Compatibility for phylib's default interface type when the
+                * phy-mode property is absent
+                */
+               __set_bit(PHY_INTERFACE_MODE_GMII,
+                         config->supported_interfaces);
+       }
 
        if (dev->dev_ops->get_caps)
                dev->dev_ops->get_caps(dev, port, config);
@@ -962,6 +968,7 @@ static void ksz_update_port_member(struct ksz_device *dev, int port)
 static int ksz_setup(struct dsa_switch *ds)
 {
        struct ksz_device *dev = ds->priv;
+       struct ksz_port *p;
        const u16 *regs;
        int ret;
 
@@ -1001,6 +1008,14 @@ static int ksz_setup(struct dsa_switch *ds)
                        return ret;
        }
 
+       /* Start with learning disabled on standalone user ports, and enabled
+        * on the CPU port. In lack of other finer mechanisms, learning on the
+        * CPU port will avoid flooding bridge local addresses on the network
+        * in some cases.
+        */
+       p = &dev->ports[dev->cpu_port];
+       p->learning = true;
+
        /* start switch */
        regmap_update_bits(dev->regmap[0], regs[S_START_CTRL],
                           SW_START, SW_START);
@@ -1277,6 +1292,8 @@ void ksz_port_stp_state_set(struct dsa_switch *ds, int port, u8 state)
        ksz_pread8(dev, port, regs[P_STP_CTRL], &data);
        data &= ~(PORT_TX_ENABLE | PORT_RX_ENABLE | PORT_LEARN_DISABLE);
 
+       p = &dev->ports[port];
+
        switch (state) {
        case BR_STATE_DISABLED:
                data |= PORT_LEARN_DISABLE;
@@ -1286,9 +1303,13 @@ void ksz_port_stp_state_set(struct dsa_switch *ds, int port, u8 state)
                break;
        case BR_STATE_LEARNING:
                data |= PORT_RX_ENABLE;
+               if (!p->learning)
+                       data |= PORT_LEARN_DISABLE;
                break;
        case BR_STATE_FORWARDING:
                data |= (PORT_TX_ENABLE | PORT_RX_ENABLE);
+               if (!p->learning)
+                       data |= PORT_LEARN_DISABLE;
                break;
        case BR_STATE_BLOCKING:
                data |= PORT_LEARN_DISABLE;
@@ -1300,12 +1321,38 @@ void ksz_port_stp_state_set(struct dsa_switch *ds, int port, u8 state)
 
        ksz_pwrite8(dev, port, regs[P_STP_CTRL], data);
 
-       p = &dev->ports[port];
        p->stp_state = state;
 
        ksz_update_port_member(dev, port);
 }
 
+static int ksz_port_pre_bridge_flags(struct dsa_switch *ds, int port,
+                                    struct switchdev_brport_flags flags,
+                                    struct netlink_ext_ack *extack)
+{
+       if (flags.mask & ~BR_LEARNING)
+               return -EINVAL;
+
+       return 0;
+}
+
+static int ksz_port_bridge_flags(struct dsa_switch *ds, int port,
+                                struct switchdev_brport_flags flags,
+                                struct netlink_ext_ack *extack)
+{
+       struct ksz_device *dev = ds->priv;
+       struct ksz_port *p = &dev->ports[port];
+
+       if (flags.mask & BR_LEARNING) {
+               p->learning = !!(flags.val & BR_LEARNING);
+
+               /* Make the change take effect immediately */
+               ksz_port_stp_state_set(ds, port, p->stp_state);
+       }
+
+       return 0;
+}
+
 static enum dsa_tag_protocol ksz_get_tag_protocol(struct dsa_switch *ds,
                                                  int port,
                                                  enum dsa_tag_protocol mp)
@@ -1719,6 +1766,8 @@ static const struct dsa_switch_ops ksz_switch_ops = {
        .port_bridge_join       = ksz_port_bridge_join,
        .port_bridge_leave      = ksz_port_bridge_leave,
        .port_stp_state_set     = ksz_port_stp_state_set,
+       .port_pre_bridge_flags  = ksz_port_pre_bridge_flags,
+       .port_bridge_flags      = ksz_port_bridge_flags,
        .port_fast_age          = ksz_port_fast_age,
        .port_vlan_filtering    = ksz_port_vlan_filtering,
        .port_vlan_add          = ksz_port_vlan_add,
index 764ada3..0d9520d 100644 (file)
@@ -65,6 +65,7 @@ struct ksz_chip_data {
 
 struct ksz_port {
        bool remove_tag;                /* Remove Tag flag set, for ksz8795 only */
+       bool learning;
        int stp_state;
        struct phy_device phydev;
 
index ba0f1ff..f46eefb 100644 (file)
@@ -11178,10 +11178,7 @@ static netdev_features_t bnxt_fix_features(struct net_device *dev,
        if ((features & NETIF_F_NTUPLE) && !bnxt_rfs_capable(bp))
                features &= ~NETIF_F_NTUPLE;
 
-       if (bp->flags & BNXT_FLAG_NO_AGG_RINGS)
-               features &= ~(NETIF_F_LRO | NETIF_F_GRO_HW);
-
-       if (!(bp->flags & BNXT_FLAG_TPA))
+       if ((bp->flags & BNXT_FLAG_NO_AGG_RINGS) || bp->xdp_prog)
                features &= ~(NETIF_F_LRO | NETIF_F_GRO_HW);
 
        if (!(features & NETIF_F_GRO))
index 075c620..b1b17f9 100644 (file)
@@ -2130,6 +2130,7 @@ struct bnxt {
 #define BNXT_DUMP_CRASH                1
 
        struct bpf_prog         *xdp_prog;
+       u8                      xdp_has_frags;
 
        struct bnxt_ptp_cfg     *ptp_cfg;
        u8                      ptp_all_rx_tstamp;
index 059f96f..a36803e 100644 (file)
@@ -1306,6 +1306,7 @@ int bnxt_dl_register(struct bnxt *bp)
        if (rc)
                goto err_dl_port_unreg;
 
+       devlink_set_features(dl, DEVLINK_F_RELOAD);
 out:
        devlink_register(dl);
        return 0;
index 730febd..a4cba7c 100644 (file)
@@ -623,7 +623,7 @@ static int bnxt_hwrm_func_vf_resc_cfg(struct bnxt *bp, int num_vfs, bool reset)
                hw_resc->max_stat_ctxs -= le16_to_cpu(req->min_stat_ctx) * n;
                hw_resc->max_vnics -= le16_to_cpu(req->min_vnics) * n;
                if (bp->flags & BNXT_FLAG_CHIP_P5)
-                       hw_resc->max_irqs -= vf_msix * n;
+                       hw_resc->max_nqs -= vf_msix;
 
                rc = pf->active_vfs;
        }
index f53387e..c3065ec 100644 (file)
@@ -181,6 +181,7 @@ void bnxt_xdp_buff_init(struct bnxt *bp, struct bnxt_rx_ring_info *rxr,
                        struct xdp_buff *xdp)
 {
        struct bnxt_sw_rx_bd *rx_buf;
+       u32 buflen = PAGE_SIZE;
        struct pci_dev *pdev;
        dma_addr_t mapping;
        u32 offset;
@@ -192,7 +193,10 @@ void bnxt_xdp_buff_init(struct bnxt *bp, struct bnxt_rx_ring_info *rxr,
        mapping = rx_buf->mapping - bp->rx_dma_offset;
        dma_sync_single_for_cpu(&pdev->dev, mapping + offset, *len, bp->rx_dir);
 
-       xdp_init_buff(xdp, BNXT_PAGE_MODE_BUF_SIZE + offset, &rxr->xdp_rxq);
+       if (bp->xdp_has_frags)
+               buflen = BNXT_PAGE_MODE_BUF_SIZE + offset;
+
+       xdp_init_buff(xdp, buflen, &rxr->xdp_rxq);
        xdp_prepare_buff(xdp, *data_ptr - offset, offset, *len, false);
 }
 
@@ -397,8 +401,10 @@ static int bnxt_xdp_set(struct bnxt *bp, struct bpf_prog *prog)
                netdev_warn(dev, "ethtool rx/tx channels must be combined to support XDP.\n");
                return -EOPNOTSUPP;
        }
-       if (prog)
+       if (prog) {
                tx_xdp = bp->rx_nr_rings;
+               bp->xdp_has_frags = prog->aux->xdp_has_frags;
+       }
 
        tc = netdev_get_num_tc(dev);
        if (!tc)
index 4563457..a770bab 100644 (file)
@@ -2886,6 +2886,7 @@ static void dpaa_adjust_link(struct net_device *net_dev)
 
 /* The Aquantia PHYs are capable of performing rate adaptation */
 #define PHY_VEND_AQUANTIA      0x03a1b400
+#define PHY_VEND_AQUANTIA2     0x31c31c00
 
 static int dpaa_phy_init(struct net_device *net_dev)
 {
@@ -2893,6 +2894,7 @@ static int dpaa_phy_init(struct net_device *net_dev)
        struct mac_device *mac_dev;
        struct phy_device *phy_dev;
        struct dpaa_priv *priv;
+       u32 phy_vendor;
 
        priv = netdev_priv(net_dev);
        mac_dev = priv->mac_dev;
@@ -2905,9 +2907,11 @@ static int dpaa_phy_init(struct net_device *net_dev)
                return -ENODEV;
        }
 
+       phy_vendor = phy_dev->drv->phy_id & GENMASK(31, 10);
        /* Unless the PHY is capable of rate adaptation */
        if (mac_dev->phy_if != PHY_INTERFACE_MODE_XGMII ||
-           ((phy_dev->drv->phy_id & GENMASK(31, 10)) != PHY_VEND_AQUANTIA)) {
+           (phy_vendor != PHY_VEND_AQUANTIA &&
+            phy_vendor != PHY_VEND_AQUANTIA2)) {
                /* remove any features not supported by the controller */
                ethtool_convert_legacy_u32_to_link_mode(mask,
                                                        mac_dev->if_support);
index ed7301b..0cebe4b 100644 (file)
@@ -634,6 +634,13 @@ struct fec_enet_private {
        int pps_enable;
        unsigned int next_counter;
 
+       struct {
+               struct timespec64 ts_phc;
+               u64 ns_sys;
+               u32 at_corr;
+               u8 at_inc_corr;
+       } ptp_saved_state;
+
        u64 ethtool_stats[];
 };
 
@@ -644,5 +651,8 @@ void fec_ptp_disable_hwts(struct net_device *ndev);
 int fec_ptp_set(struct net_device *ndev, struct ifreq *ifr);
 int fec_ptp_get(struct net_device *ndev, struct ifreq *ifr);
 
+void fec_ptp_save_state(struct fec_enet_private *fep);
+int fec_ptp_restore_state(struct fec_enet_private *fep);
+
 /****************************************************************************/
 #endif /* FEC_H */
index e8e2aa1..b0d60f8 100644 (file)
@@ -285,8 +285,11 @@ MODULE_PARM_DESC(macaddr, "FEC Ethernet MAC address");
 #define FEC_MMFR_TA            (2 << 16)
 #define FEC_MMFR_DATA(v)       (v & 0xffff)
 /* FEC ECR bits definition */
-#define FEC_ECR_MAGICEN                (1 << 2)
-#define FEC_ECR_SLEEP          (1 << 3)
+#define FEC_ECR_RESET   BIT(0)
+#define FEC_ECR_ETHEREN BIT(1)
+#define FEC_ECR_MAGICEN BIT(2)
+#define FEC_ECR_SLEEP   BIT(3)
+#define FEC_ECR_EN1588  BIT(4)
 
 #define FEC_MII_TIMEOUT                30000 /* us */
 
@@ -982,6 +985,9 @@ fec_restart(struct net_device *ndev)
        u32 temp_mac[2];
        u32 rcntl = OPT_FRAME_SIZE | 0x04;
        u32 ecntl = 0x2; /* ETHEREN */
+       struct ptp_clock_request ptp_rq = { .type = PTP_CLK_REQ_PPS };
+
+       fec_ptp_save_state(fep);
 
        /* Whack a reset.  We should wait for this.
         * For i.MX6SX SOC, enet use AXI bus, we use disable MAC
@@ -1135,7 +1141,7 @@ fec_restart(struct net_device *ndev)
        }
 
        if (fep->bufdesc_ex)
-               ecntl |= (1 << 4);
+               ecntl |= FEC_ECR_EN1588;
 
        if (fep->quirks & FEC_QUIRK_DELAYED_CLKS_SUPPORT &&
            fep->rgmii_txc_dly)
@@ -1156,6 +1162,14 @@ fec_restart(struct net_device *ndev)
        if (fep->bufdesc_ex)
                fec_ptp_start_cyclecounter(ndev);
 
+       /* Restart PPS if needed */
+       if (fep->pps_enable) {
+               /* Clear flag so fec_ptp_enable_pps() doesn't return immediately */
+               fep->pps_enable = 0;
+               fec_ptp_restore_state(fep);
+               fep->ptp_caps.enable(&fep->ptp_caps, &ptp_rq, 1);
+       }
+
        /* Enable interrupts we wish to service */
        if (fep->link)
                writel(FEC_DEFAULT_IMASK, fep->hwp + FEC_IMASK);
@@ -1206,6 +1220,8 @@ fec_stop(struct net_device *ndev)
        struct fec_enet_private *fep = netdev_priv(ndev);
        u32 rmii_mode = readl(fep->hwp + FEC_R_CNTRL) & (1 << 8);
        u32 val;
+       struct ptp_clock_request ptp_rq = { .type = PTP_CLK_REQ_PPS };
+       u32 ecntl = 0;
 
        /* We cannot expect a graceful transmit stop without link !!! */
        if (fep->link) {
@@ -1215,6 +1231,8 @@ fec_stop(struct net_device *ndev)
                        netdev_err(ndev, "Graceful transmit stop did not complete!\n");
        }
 
+       fec_ptp_save_state(fep);
+
        /* Whack a reset.  We should wait for this.
         * For i.MX6SX SOC, enet use AXI bus, we use disable MAC
         * instead of reset MAC itself.
@@ -1234,12 +1252,28 @@ fec_stop(struct net_device *ndev)
        writel(fep->phy_speed, fep->hwp + FEC_MII_SPEED);
        writel(FEC_DEFAULT_IMASK, fep->hwp + FEC_IMASK);
 
+       if (fep->bufdesc_ex)
+               ecntl |= FEC_ECR_EN1588;
+
        /* We have to keep ENET enabled to have MII interrupt stay working */
        if (fep->quirks & FEC_QUIRK_ENET_MAC &&
                !(fep->wol_flag & FEC_WOL_FLAG_SLEEP_ON)) {
-               writel(2, fep->hwp + FEC_ECNTRL);
+               ecntl |= FEC_ECR_ETHEREN;
                writel(rmii_mode, fep->hwp + FEC_R_CNTRL);
        }
+
+       writel(ecntl, fep->hwp + FEC_ECNTRL);
+
+       if (fep->bufdesc_ex)
+               fec_ptp_start_cyclecounter(ndev);
+
+       /* Restart PPS if needed */
+       if (fep->pps_enable) {
+               /* Clear flag so fec_ptp_enable_pps() doesn't return immediately */
+               fep->pps_enable = 0;
+               fec_ptp_restore_state(fep);
+               fep->ptp_caps.enable(&fep->ptp_caps, &ptp_rq, 1);
+       }
 }
 
 
index 3dc3c0b..c74d04f 100644 (file)
@@ -633,7 +633,36 @@ void fec_ptp_stop(struct platform_device *pdev)
        struct net_device *ndev = platform_get_drvdata(pdev);
        struct fec_enet_private *fep = netdev_priv(ndev);
 
+       if (fep->pps_enable)
+               fec_ptp_enable_pps(fep, 0);
+
        cancel_delayed_work_sync(&fep->time_keep);
        if (fep->ptp_clock)
                ptp_clock_unregister(fep->ptp_clock);
 }
+
+void fec_ptp_save_state(struct fec_enet_private *fep)
+{
+       u32 atime_inc_corr;
+
+       fec_ptp_gettime(&fep->ptp_caps, &fep->ptp_saved_state.ts_phc);
+       fep->ptp_saved_state.ns_sys = ktime_get_ns();
+
+       fep->ptp_saved_state.at_corr = readl(fep->hwp + FEC_ATIME_CORR);
+       atime_inc_corr = readl(fep->hwp + FEC_ATIME_INC) & FEC_T_INC_CORR_MASK;
+       fep->ptp_saved_state.at_inc_corr = (u8)(atime_inc_corr >> FEC_T_INC_CORR_OFFSET);
+}
+
+int fec_ptp_restore_state(struct fec_enet_private *fep)
+{
+       u32 atime_inc = readl(fep->hwp + FEC_ATIME_INC) & FEC_T_INC_MASK;
+       u64 ns_sys;
+
+       writel(fep->ptp_saved_state.at_corr, fep->hwp + FEC_ATIME_CORR);
+       atime_inc |= ((u32)fep->ptp_saved_state.at_inc_corr) << FEC_T_INC_CORR_OFFSET;
+       writel(atime_inc, fep->hwp + FEC_ATIME_INC);
+
+       ns_sys = ktime_get_ns() - fep->ptp_saved_state.ns_sys;
+       timespec64_add_ns(&fep->ptp_saved_state.ts_phc, ns_sys);
+       return fec_ptp_settime(&fep->ptp_caps, &fep->ptp_saved_state.ts_phc);
+}
index 156e92c..e9cd0fa 100644 (file)
@@ -4485,7 +4485,7 @@ static int i40e_check_fdir_input_set(struct i40e_vsi *vsi,
                                    (struct in6_addr *)&ipv6_full_mask))
                        new_mask |= I40E_L3_V6_DST_MASK;
                else if (ipv6_addr_any((struct in6_addr *)
-                                      &usr_ip6_spec->ip6src))
+                                      &usr_ip6_spec->ip6dst))
                        new_mask &= ~I40E_L3_V6_DST_MASK;
                else
                        return -EOPNOTSUPP;
index cc5b85a..841fa14 100644 (file)
@@ -684,8 +684,8 @@ static inline void ice_set_ring_xdp(struct ice_tx_ring *ring)
  * ice_xsk_pool - get XSK buffer pool bound to a ring
  * @ring: Rx ring to use
  *
- * Returns a pointer to xdp_umem structure if there is a buffer pool present,
- * NULL otherwise.
+ * Returns a pointer to xsk_buff_pool structure if there is a buffer pool
+ * present, NULL otherwise.
  */
 static inline struct xsk_buff_pool *ice_xsk_pool(struct ice_rx_ring *ring)
 {
@@ -699,23 +699,33 @@ static inline struct xsk_buff_pool *ice_xsk_pool(struct ice_rx_ring *ring)
 }
 
 /**
- * ice_tx_xsk_pool - get XSK buffer pool bound to a ring
- * @ring: Tx ring to use
+ * ice_tx_xsk_pool - assign XSK buff pool to XDP ring
+ * @vsi: pointer to VSI
+ * @qid: index of a queue to look at XSK buff pool presence
  *
- * Returns a pointer to xdp_umem structure if there is a buffer pool present,
- * NULL otherwise. Tx equivalent of ice_xsk_pool.
+ * Sets XSK buff pool pointer on XDP ring.
+ *
+ * XDP ring is picked from Rx ring, whereas Rx ring is picked based on provided
+ * queue id. Reason for doing so is that queue vectors might have assigned more
+ * than one XDP ring, e.g. when user reduced the queue count on netdev; Rx ring
+ * carries a pointer to one of these XDP rings for its own purposes, such as
+ * handling XDP_TX action, therefore we can piggyback here on the
+ * rx_ring->xdp_ring assignment that was done during XDP rings initialization.
  */
-static inline struct xsk_buff_pool *ice_tx_xsk_pool(struct ice_tx_ring *ring)
+static inline void ice_tx_xsk_pool(struct ice_vsi *vsi, u16 qid)
 {
-       struct ice_vsi *vsi = ring->vsi;
-       u16 qid;
+       struct ice_tx_ring *ring;
 
-       qid = ring->q_index - vsi->alloc_txq;
+       ring = vsi->rx_rings[qid]->xdp_ring;
+       if (!ring)
+               return;
 
-       if (!ice_is_xdp_ena_vsi(vsi) || !test_bit(qid, vsi->af_xdp_zc_qps))
-               return NULL;
+       if (!ice_is_xdp_ena_vsi(vsi) || !test_bit(qid, vsi->af_xdp_zc_qps)) {
+               ring->xsk_pool = NULL;
+               return;
+       }
 
-       return xsk_get_pool_from_qid(vsi->netdev, qid);
+       ring->xsk_pool = xsk_get_pool_from_qid(vsi->netdev, qid);
 }
 
 /**
index 733c455..0c4ec92 100644 (file)
@@ -1986,8 +1986,8 @@ int ice_vsi_cfg_xdp_txqs(struct ice_vsi *vsi)
        if (ret)
                return ret;
 
-       ice_for_each_xdp_txq(vsi, i)
-               vsi->xdp_rings[i]->xsk_pool = ice_tx_xsk_pool(vsi->xdp_rings[i]);
+       ice_for_each_rxq(vsi, i)
+               ice_tx_xsk_pool(vsi, i);
 
        return ret;
 }
index 4ecaf40..173fe6c 100644 (file)
@@ -2581,7 +2581,6 @@ static int ice_xdp_alloc_setup_rings(struct ice_vsi *vsi)
                if (ice_setup_tx_ring(xdp_ring))
                        goto free_xdp_rings;
                ice_set_ring_xdp(xdp_ring);
-               xdp_ring->xsk_pool = ice_tx_xsk_pool(xdp_ring);
                spin_lock_init(&xdp_ring->tx_lock);
                for (j = 0; j < xdp_ring->count; j++) {
                        tx_desc = ICE_TX_DESC(xdp_ring, j);
@@ -2589,13 +2588,6 @@ static int ice_xdp_alloc_setup_rings(struct ice_vsi *vsi)
                }
        }
 
-       ice_for_each_rxq(vsi, i) {
-               if (static_key_enabled(&ice_xdp_locking_key))
-                       vsi->rx_rings[i]->xdp_ring = vsi->xdp_rings[i % vsi->num_xdp_txq];
-               else
-                       vsi->rx_rings[i]->xdp_ring = vsi->xdp_rings[i];
-       }
-
        return 0;
 
 free_xdp_rings:
@@ -2685,6 +2677,23 @@ int ice_prepare_xdp_rings(struct ice_vsi *vsi, struct bpf_prog *prog)
                xdp_rings_rem -= xdp_rings_per_v;
        }
 
+       ice_for_each_rxq(vsi, i) {
+               if (static_key_enabled(&ice_xdp_locking_key)) {
+                       vsi->rx_rings[i]->xdp_ring = vsi->xdp_rings[i % vsi->num_xdp_txq];
+               } else {
+                       struct ice_q_vector *q_vector = vsi->rx_rings[i]->q_vector;
+                       struct ice_tx_ring *ring;
+
+                       ice_for_each_tx_ring(ring, q_vector->tx) {
+                               if (ice_ring_is_xdp(ring)) {
+                                       vsi->rx_rings[i]->xdp_ring = ring;
+                                       break;
+                               }
+                       }
+               }
+               ice_tx_xsk_pool(vsi, i);
+       }
+
        /* omit the scheduler update if in reset path; XDP queues will be
         * taken into account at the end of ice_vsi_rebuild, where
         * ice_cfg_vsi_lan is being called
index 49ba8bf..e48e292 100644 (file)
@@ -243,7 +243,7 @@ static int ice_qp_ena(struct ice_vsi *vsi, u16 q_idx)
                if (err)
                        goto free_buf;
                ice_set_ring_xdp(xdp_ring);
-               xdp_ring->xsk_pool = ice_tx_xsk_pool(xdp_ring);
+               ice_tx_xsk_pool(vsi, q_idx);
        }
 
        err = ice_vsi_cfg_rxq(rx_ring);
@@ -329,6 +329,12 @@ int ice_xsk_pool_setup(struct ice_vsi *vsi, struct xsk_buff_pool *pool, u16 qid)
        bool if_running, pool_present = !!pool;
        int ret = 0, pool_failure = 0;
 
+       if (qid >= vsi->num_rxq || qid >= vsi->num_txq) {
+               netdev_err(vsi->netdev, "Please use queue id in scope of combined queues count\n");
+               pool_failure = -EINVAL;
+               goto failure;
+       }
+
        if (!is_power_of_2(vsi->rx_rings[qid]->count) ||
            !is_power_of_2(vsi->tx_rings[qid]->count)) {
                netdev_err(vsi->netdev, "Please align ring sizes to power of 2\n");
@@ -353,7 +359,7 @@ xsk_pool_if_up:
        if (if_running) {
                ret = ice_qp_ena(vsi, qid);
                if (!ret && pool_present)
-                       napi_schedule(&vsi->xdp_rings[qid]->q_vector->napi);
+                       napi_schedule(&vsi->rx_rings[qid]->xdp_ring->q_vector->napi);
                else if (ret)
                        netdev_err(vsi->netdev, "ice_qp_ena error = %d\n", ret);
        }
@@ -944,13 +950,13 @@ ice_xsk_wakeup(struct net_device *netdev, u32 queue_id,
        if (!ice_is_xdp_ena_vsi(vsi))
                return -EINVAL;
 
-       if (queue_id >= vsi->num_txq)
+       if (queue_id >= vsi->num_txq || queue_id >= vsi->num_rxq)
                return -EINVAL;
 
-       if (!vsi->xdp_rings[queue_id]->xsk_pool)
-               return -EINVAL;
+       ring = vsi->rx_rings[queue_id]->xdp_ring;
 
-       ring = vsi->xdp_rings[queue_id];
+       if (!ring->xsk_pool)
+               return -EINVAL;
 
        /* The idea here is that if NAPI is running, mark a miss, so
         * it will run again. If not, trigger an interrupt and
index 9f06896..f8605f5 100644 (file)
@@ -1214,7 +1214,6 @@ void ixgbe_ptp_start_cyclecounter(struct ixgbe_adapter *adapter)
        struct cyclecounter cc;
        unsigned long flags;
        u32 incval = 0;
-       u32 tsauxc = 0;
        u32 fuse0 = 0;
 
        /* For some of the boards below this mask is technically incorrect.
@@ -1249,18 +1248,6 @@ void ixgbe_ptp_start_cyclecounter(struct ixgbe_adapter *adapter)
        case ixgbe_mac_x550em_a:
        case ixgbe_mac_X550:
                cc.read = ixgbe_ptp_read_X550;
-
-               /* enable SYSTIME counter */
-               IXGBE_WRITE_REG(hw, IXGBE_SYSTIMR, 0);
-               IXGBE_WRITE_REG(hw, IXGBE_SYSTIML, 0);
-               IXGBE_WRITE_REG(hw, IXGBE_SYSTIMH, 0);
-               tsauxc = IXGBE_READ_REG(hw, IXGBE_TSAUXC);
-               IXGBE_WRITE_REG(hw, IXGBE_TSAUXC,
-                               tsauxc & ~IXGBE_TSAUXC_DISABLE_SYSTIME);
-               IXGBE_WRITE_REG(hw, IXGBE_TSIM, IXGBE_TSIM_TXTS);
-               IXGBE_WRITE_REG(hw, IXGBE_EIMS, IXGBE_EIMS_TIMESYNC);
-
-               IXGBE_WRITE_FLUSH(hw);
                break;
        case ixgbe_mac_X540:
                cc.read = ixgbe_ptp_read_82599;
@@ -1293,6 +1280,50 @@ void ixgbe_ptp_start_cyclecounter(struct ixgbe_adapter *adapter)
 }
 
 /**
+ * ixgbe_ptp_init_systime - Initialize SYSTIME registers
+ * @adapter: the ixgbe private board structure
+ *
+ * Initialize and start the SYSTIME registers.
+ */
+static void ixgbe_ptp_init_systime(struct ixgbe_adapter *adapter)
+{
+       struct ixgbe_hw *hw = &adapter->hw;
+       u32 tsauxc;
+
+       switch (hw->mac.type) {
+       case ixgbe_mac_X550EM_x:
+       case ixgbe_mac_x550em_a:
+       case ixgbe_mac_X550:
+               tsauxc = IXGBE_READ_REG(hw, IXGBE_TSAUXC);
+
+               /* Reset SYSTIME registers to 0 */
+               IXGBE_WRITE_REG(hw, IXGBE_SYSTIMR, 0);
+               IXGBE_WRITE_REG(hw, IXGBE_SYSTIML, 0);
+               IXGBE_WRITE_REG(hw, IXGBE_SYSTIMH, 0);
+
+               /* Reset interrupt settings */
+               IXGBE_WRITE_REG(hw, IXGBE_TSIM, IXGBE_TSIM_TXTS);
+               IXGBE_WRITE_REG(hw, IXGBE_EIMS, IXGBE_EIMS_TIMESYNC);
+
+               /* Activate the SYSTIME counter */
+               IXGBE_WRITE_REG(hw, IXGBE_TSAUXC,
+                               tsauxc & ~IXGBE_TSAUXC_DISABLE_SYSTIME);
+               break;
+       case ixgbe_mac_X540:
+       case ixgbe_mac_82599EB:
+               /* Reset SYSTIME registers to 0 */
+               IXGBE_WRITE_REG(hw, IXGBE_SYSTIML, 0);
+               IXGBE_WRITE_REG(hw, IXGBE_SYSTIMH, 0);
+               break;
+       default:
+               /* Other devices aren't supported */
+               return;
+       };
+
+       IXGBE_WRITE_FLUSH(hw);
+}
+
+/**
  * ixgbe_ptp_reset
  * @adapter: the ixgbe private board structure
  *
@@ -1318,6 +1349,8 @@ void ixgbe_ptp_reset(struct ixgbe_adapter *adapter)
 
        ixgbe_ptp_start_cyclecounter(adapter);
 
+       ixgbe_ptp_init_systime(adapter);
+
        spin_lock_irqsave(&adapter->tmreg_lock, flags);
        timecounter_init(&adapter->hw_tc, &adapter->hw_cc,
                         ktime_to_ns(ktime_get_real()));
index 5edb68a..57f27cc 100644 (file)
@@ -193,6 +193,7 @@ static int xrx200_alloc_buf(struct xrx200_chan *ch, void *(*alloc)(unsigned int
 
        ch->rx_buff[ch->dma.desc] = alloc(priv->rx_skb_size);
        if (!ch->rx_buff[ch->dma.desc]) {
+               ch->rx_buff[ch->dma.desc] = buf;
                ret = -ENOMEM;
                goto skip;
        }
@@ -239,6 +240,12 @@ static int xrx200_hw_receive(struct xrx200_chan *ch)
        }
 
        skb = build_skb(buf, priv->rx_skb_size);
+       if (!skb) {
+               skb_free_frag(buf);
+               net_dev->stats.rx_dropped++;
+               return -ENOMEM;
+       }
+
        skb_reserve(skb, NET_SKB_PAD);
        skb_put(skb, len);
 
@@ -288,7 +295,7 @@ static int xrx200_poll_rx(struct napi_struct *napi, int budget)
                        if (ret == XRX200_DMA_PACKET_IN_PROGRESS)
                                continue;
                        if (ret != XRX200_DMA_PACKET_COMPLETE)
-                               return ret;
+                               break;
                        rx++;
                } else {
                        break;
index 8aff4c0..5ace460 100644 (file)
@@ -1891,10 +1891,19 @@ static int mtk_poll_rx(struct napi_struct *napi, int budget,
                skb->dev = netdev;
                bytes += skb->len;
 
-               if (MTK_HAS_CAPS(eth->soc->caps, MTK_NETSYS_V2))
+               if (MTK_HAS_CAPS(eth->soc->caps, MTK_NETSYS_V2)) {
+                       hash = trxd.rxd5 & MTK_RXD5_FOE_ENTRY;
+                       if (hash != MTK_RXD5_FOE_ENTRY)
+                               skb_set_hash(skb, jhash_1word(hash, 0),
+                                            PKT_HASH_TYPE_L4);
                        rxdcsum = &trxd.rxd3;
-               else
+               } else {
+                       hash = trxd.rxd4 & MTK_RXD4_FOE_ENTRY;
+                       if (hash != MTK_RXD4_FOE_ENTRY)
+                               skb_set_hash(skb, jhash_1word(hash, 0),
+                                            PKT_HASH_TYPE_L4);
                        rxdcsum = &trxd.rxd4;
+               }
 
                if (*rxdcsum & eth->soc->txrx.rx_dma_l4_valid)
                        skb->ip_summed = CHECKSUM_UNNECESSARY;
@@ -1902,16 +1911,9 @@ static int mtk_poll_rx(struct napi_struct *napi, int budget,
                        skb_checksum_none_assert(skb);
                skb->protocol = eth_type_trans(skb, netdev);
 
-               hash = trxd.rxd4 & MTK_RXD4_FOE_ENTRY;
-               if (hash != MTK_RXD4_FOE_ENTRY) {
-                       hash = jhash_1word(hash, 0);
-                       skb_set_hash(skb, hash, PKT_HASH_TYPE_L4);
-               }
-
                reason = FIELD_GET(MTK_RXD4_PPE_CPU_REASON, trxd.rxd4);
                if (reason == MTK_PPE_CPU_REASON_HIT_UNBIND_RATE_REACHED)
-                       mtk_ppe_check_skb(eth->ppe, skb,
-                                         trxd.rxd4 & MTK_RXD4_FOE_ENTRY);
+                       mtk_ppe_check_skb(eth->ppe, skb, hash);
 
                if (netdev->features & NETIF_F_HW_VLAN_CTAG_RX) {
                        if (MTK_HAS_CAPS(eth->soc->caps, MTK_NETSYS_V2)) {
index 7405c97..ecf85e9 100644 (file)
 #define RX_DMA_L4_VALID_PDMA   BIT(30)         /* when PDMA is used */
 #define RX_DMA_SPECIAL_TAG     BIT(22)
 
+/* PDMA descriptor rxd5 */
+#define MTK_RXD5_FOE_ENTRY     GENMASK(14, 0)
+#define MTK_RXD5_PPE_CPU_REASON        GENMASK(22, 18)
+#define MTK_RXD5_SRC_PORT      GENMASK(29, 26)
+
 #define RX_DMA_GET_SPORT(x)    (((x) >> 19) & 0xf)
 #define RX_DMA_GET_SPORT_V2(x) (((x) >> 26) & 0x7)
 
index 3752235..c8e5ca6 100644 (file)
@@ -79,6 +79,10 @@ tc_act_police_offload(struct mlx5e_priv *priv,
        struct mlx5e_flow_meter_handle *meter;
        int err = 0;
 
+       err = mlx5e_policer_validate(&fl_act->action, act, fl_act->extack);
+       if (err)
+               return err;
+
        err = fill_meter_params_from_act(act, &params);
        if (err)
                return err;
index 0aef695..3a1f76e 100644 (file)
@@ -246,7 +246,7 @@ static void mlx5e_tls_priv_tx_cleanup(struct mlx5e_ktls_offload_context_tx *priv
 static void mlx5e_tls_priv_tx_list_cleanup(struct mlx5_core_dev *mdev,
                                           struct list_head *list, int size)
 {
-       struct mlx5e_ktls_offload_context_tx *obj;
+       struct mlx5e_ktls_offload_context_tx *obj, *n;
        struct mlx5e_async_ctx *bulk_async;
        int i;
 
@@ -255,7 +255,7 @@ static void mlx5e_tls_priv_tx_list_cleanup(struct mlx5_core_dev *mdev,
                return;
 
        i = 0;
-       list_for_each_entry(obj, list, list_node) {
+       list_for_each_entry_safe(obj, n, list, list_node) {
                mlx5e_tls_priv_tx_cleanup(obj, &bulk_async[i]);
                i++;
        }
index e2a9b9b..e0ce5a2 100644 (file)
@@ -1395,10 +1395,11 @@ struct mlx5e_flow_steering *mlx5e_fs_init(const struct mlx5e_profile *profile,
        }
 
        return fs;
-err_free_fs:
-       kvfree(fs);
+
 err_free_vlan:
        mlx5e_fs_vlan_free(fs);
+err_free_fs:
+       kvfree(fs);
 err:
        return NULL;
 }
index d858667..02eb2f0 100644 (file)
@@ -3682,7 +3682,9 @@ static int set_feature_hw_tc(struct net_device *netdev, bool enable)
        int err = 0;
 
 #if IS_ENABLED(CONFIG_MLX5_CLS_ACT)
-       if (!enable && mlx5e_tc_num_filters(priv, MLX5_TC_FLAG(NIC_OFFLOAD))) {
+       int tc_flag = mlx5e_is_uplink_rep(priv) ? MLX5_TC_FLAG(ESW_OFFLOAD) :
+                                                 MLX5_TC_FLAG(NIC_OFFLOAD);
+       if (!enable && mlx5e_tc_num_filters(priv, tc_flag)) {
                netdev_err(netdev,
                           "Active offloaded tc filters, can't turn hw_tc_offload off\n");
                return -EINVAL;
@@ -4769,14 +4771,6 @@ void mlx5e_build_nic_params(struct mlx5e_priv *priv, struct mlx5e_xsk *xsk, u16
        /* RQ */
        mlx5e_build_rq_params(mdev, params);
 
-       /* HW LRO */
-       if (MLX5_CAP_ETH(mdev, lro_cap) &&
-           params->rq_wq_type == MLX5_WQ_TYPE_LINKED_LIST_STRIDING_RQ) {
-               /* No XSK params: checking the availability of striding RQ in general. */
-               if (!mlx5e_rx_mpwqe_is_linear_skb(mdev, params, NULL))
-                       params->packet_merge.type = slow_pci_heuristic(mdev) ?
-                               MLX5E_PACKET_MERGE_NONE : MLX5E_PACKET_MERGE_LRO;
-       }
        params->packet_merge.timeout = mlx5e_choose_lro_timeout(mdev, MLX5E_DEFAULT_LRO_TIMEOUT);
 
        /* CQ moderation params */
index 0c66774..759f7d3 100644 (file)
@@ -662,6 +662,8 @@ static void mlx5e_build_rep_params(struct net_device *netdev)
 
        params->mqprio.num_tc       = 1;
        params->tunneled_offload_en = false;
+       if (rep->vport != MLX5_VPORT_UPLINK)
+               params->vlan_strip_disable = true;
 
        mlx5_query_min_inline(mdev, &params->tx_min_inline_mode);
 }
index ed73132..a9f4c65 100644 (file)
@@ -427,7 +427,8 @@ esw_setup_vport_dest(struct mlx5_flow_destination *dest, struct mlx5_flow_act *f
                dest[dest_idx].vport.vhca_id =
                        MLX5_CAP_GEN(esw_attr->dests[attr_idx].mdev, vhca_id);
                dest[dest_idx].vport.flags |= MLX5_FLOW_DEST_VPORT_VHCA_ID;
-               if (mlx5_lag_mpesw_is_activated(esw->dev))
+               if (dest[dest_idx].vport.num == MLX5_VPORT_UPLINK &&
+                   mlx5_lag_mpesw_is_activated(esw->dev))
                        dest[dest_idx].type = MLX5_FLOW_DESTINATION_TYPE_UPLINK;
        }
        if (esw_attr->dests[attr_idx].flags & MLX5_ESW_DEST_ENCAP) {
@@ -3115,8 +3116,10 @@ esw_vfs_changed_event_handler(struct mlx5_eswitch *esw, const u32 *out)
 
                err = mlx5_eswitch_load_vf_vports(esw, new_num_vfs,
                                                  MLX5_VPORT_UC_ADDR_CHANGE);
-               if (err)
+               if (err) {
+                       devl_unlock(devlink);
                        return;
+               }
        }
        esw->esw_funcs.num_vfs = new_num_vfs;
        devl_unlock(devlink);
index 0f34e3c..0651022 100644 (file)
@@ -1067,30 +1067,32 @@ static void mlx5_ldev_add_netdev(struct mlx5_lag *ldev,
                                 struct net_device *netdev)
 {
        unsigned int fn = mlx5_get_dev_index(dev);
+       unsigned long flags;
 
        if (fn >= ldev->ports)
                return;
 
-       spin_lock(&lag_lock);
+       spin_lock_irqsave(&lag_lock, flags);
        ldev->pf[fn].netdev = netdev;
        ldev->tracker.netdev_state[fn].link_up = 0;
        ldev->tracker.netdev_state[fn].tx_enabled = 0;
-       spin_unlock(&lag_lock);
+       spin_unlock_irqrestore(&lag_lock, flags);
 }
 
 static void mlx5_ldev_remove_netdev(struct mlx5_lag *ldev,
                                    struct net_device *netdev)
 {
+       unsigned long flags;
        int i;
 
-       spin_lock(&lag_lock);
+       spin_lock_irqsave(&lag_lock, flags);
        for (i = 0; i < ldev->ports; i++) {
                if (ldev->pf[i].netdev == netdev) {
                        ldev->pf[i].netdev = NULL;
                        break;
                }
        }
-       spin_unlock(&lag_lock);
+       spin_unlock_irqrestore(&lag_lock, flags);
 }
 
 static void mlx5_ldev_add_mdev(struct mlx5_lag *ldev,
@@ -1234,7 +1236,7 @@ void mlx5_lag_add_netdev(struct mlx5_core_dev *dev,
        mlx5_ldev_add_netdev(ldev, dev, netdev);
 
        for (i = 0; i < ldev->ports; i++)
-               if (!ldev->pf[i].dev)
+               if (!ldev->pf[i].netdev)
                        break;
 
        if (i >= ldev->ports)
@@ -1246,12 +1248,13 @@ void mlx5_lag_add_netdev(struct mlx5_core_dev *dev,
 bool mlx5_lag_is_roce(struct mlx5_core_dev *dev)
 {
        struct mlx5_lag *ldev;
+       unsigned long flags;
        bool res;
 
-       spin_lock(&lag_lock);
+       spin_lock_irqsave(&lag_lock, flags);
        ldev = mlx5_lag_dev(dev);
        res  = ldev && __mlx5_lag_is_roce(ldev);
-       spin_unlock(&lag_lock);
+       spin_unlock_irqrestore(&lag_lock, flags);
 
        return res;
 }
@@ -1260,12 +1263,13 @@ EXPORT_SYMBOL(mlx5_lag_is_roce);
 bool mlx5_lag_is_active(struct mlx5_core_dev *dev)
 {
        struct mlx5_lag *ldev;
+       unsigned long flags;
        bool res;
 
-       spin_lock(&lag_lock);
+       spin_lock_irqsave(&lag_lock, flags);
        ldev = mlx5_lag_dev(dev);
        res  = ldev && __mlx5_lag_is_active(ldev);
-       spin_unlock(&lag_lock);
+       spin_unlock_irqrestore(&lag_lock, flags);
 
        return res;
 }
@@ -1274,13 +1278,14 @@ EXPORT_SYMBOL(mlx5_lag_is_active);
 bool mlx5_lag_is_master(struct mlx5_core_dev *dev)
 {
        struct mlx5_lag *ldev;
+       unsigned long flags;
        bool res;
 
-       spin_lock(&lag_lock);
+       spin_lock_irqsave(&lag_lock, flags);
        ldev = mlx5_lag_dev(dev);
        res = ldev && __mlx5_lag_is_active(ldev) &&
                dev == ldev->pf[MLX5_LAG_P1].dev;
-       spin_unlock(&lag_lock);
+       spin_unlock_irqrestore(&lag_lock, flags);
 
        return res;
 }
@@ -1289,12 +1294,13 @@ EXPORT_SYMBOL(mlx5_lag_is_master);
 bool mlx5_lag_is_sriov(struct mlx5_core_dev *dev)
 {
        struct mlx5_lag *ldev;
+       unsigned long flags;
        bool res;
 
-       spin_lock(&lag_lock);
+       spin_lock_irqsave(&lag_lock, flags);
        ldev = mlx5_lag_dev(dev);
        res  = ldev && __mlx5_lag_is_sriov(ldev);
-       spin_unlock(&lag_lock);
+       spin_unlock_irqrestore(&lag_lock, flags);
 
        return res;
 }
@@ -1303,13 +1309,14 @@ EXPORT_SYMBOL(mlx5_lag_is_sriov);
 bool mlx5_lag_is_shared_fdb(struct mlx5_core_dev *dev)
 {
        struct mlx5_lag *ldev;
+       unsigned long flags;
        bool res;
 
-       spin_lock(&lag_lock);
+       spin_lock_irqsave(&lag_lock, flags);
        ldev = mlx5_lag_dev(dev);
        res = ldev && __mlx5_lag_is_sriov(ldev) &&
              test_bit(MLX5_LAG_MODE_FLAG_SHARED_FDB, &ldev->mode_flags);
-       spin_unlock(&lag_lock);
+       spin_unlock_irqrestore(&lag_lock, flags);
 
        return res;
 }
@@ -1352,9 +1359,10 @@ struct net_device *mlx5_lag_get_roce_netdev(struct mlx5_core_dev *dev)
 {
        struct net_device *ndev = NULL;
        struct mlx5_lag *ldev;
+       unsigned long flags;
        int i;
 
-       spin_lock(&lag_lock);
+       spin_lock_irqsave(&lag_lock, flags);
        ldev = mlx5_lag_dev(dev);
 
        if (!(ldev && __mlx5_lag_is_roce(ldev)))
@@ -1373,7 +1381,7 @@ struct net_device *mlx5_lag_get_roce_netdev(struct mlx5_core_dev *dev)
                dev_hold(ndev);
 
 unlock:
-       spin_unlock(&lag_lock);
+       spin_unlock_irqrestore(&lag_lock, flags);
 
        return ndev;
 }
@@ -1383,10 +1391,11 @@ u8 mlx5_lag_get_slave_port(struct mlx5_core_dev *dev,
                           struct net_device *slave)
 {
        struct mlx5_lag *ldev;
+       unsigned long flags;
        u8 port = 0;
        int i;
 
-       spin_lock(&lag_lock);
+       spin_lock_irqsave(&lag_lock, flags);
        ldev = mlx5_lag_dev(dev);
        if (!(ldev && __mlx5_lag_is_roce(ldev)))
                goto unlock;
@@ -1401,7 +1410,7 @@ u8 mlx5_lag_get_slave_port(struct mlx5_core_dev *dev,
        port = ldev->v2p_map[port * ldev->buckets];
 
 unlock:
-       spin_unlock(&lag_lock);
+       spin_unlock_irqrestore(&lag_lock, flags);
        return port;
 }
 EXPORT_SYMBOL(mlx5_lag_get_slave_port);
@@ -1422,8 +1431,9 @@ struct mlx5_core_dev *mlx5_lag_get_peer_mdev(struct mlx5_core_dev *dev)
 {
        struct mlx5_core_dev *peer_dev = NULL;
        struct mlx5_lag *ldev;
+       unsigned long flags;
 
-       spin_lock(&lag_lock);
+       spin_lock_irqsave(&lag_lock, flags);
        ldev = mlx5_lag_dev(dev);
        if (!ldev)
                goto unlock;
@@ -1433,7 +1443,7 @@ struct mlx5_core_dev *mlx5_lag_get_peer_mdev(struct mlx5_core_dev *dev)
                           ldev->pf[MLX5_LAG_P1].dev;
 
 unlock:
-       spin_unlock(&lag_lock);
+       spin_unlock_irqrestore(&lag_lock, flags);
        return peer_dev;
 }
 EXPORT_SYMBOL(mlx5_lag_get_peer_mdev);
@@ -1446,6 +1456,7 @@ int mlx5_lag_query_cong_counters(struct mlx5_core_dev *dev,
        int outlen = MLX5_ST_SZ_BYTES(query_cong_statistics_out);
        struct mlx5_core_dev **mdev;
        struct mlx5_lag *ldev;
+       unsigned long flags;
        int num_ports;
        int ret, i, j;
        void *out;
@@ -1462,7 +1473,7 @@ int mlx5_lag_query_cong_counters(struct mlx5_core_dev *dev,
 
        memset(values, 0, sizeof(*values) * num_counters);
 
-       spin_lock(&lag_lock);
+       spin_lock_irqsave(&lag_lock, flags);
        ldev = mlx5_lag_dev(dev);
        if (ldev && __mlx5_lag_is_active(ldev)) {
                num_ports = ldev->ports;
@@ -1472,7 +1483,7 @@ int mlx5_lag_query_cong_counters(struct mlx5_core_dev *dev,
                num_ports = 1;
                mdev[MLX5_LAG_P1] = dev;
        }
-       spin_unlock(&lag_lock);
+       spin_unlock_irqrestore(&lag_lock, flags);
 
        for (i = 0; i < num_ports; ++i) {
                u32 in[MLX5_ST_SZ_DW(query_cong_statistics_in)] = {};
index bec8d6d..c085b03 100644 (file)
@@ -1530,7 +1530,9 @@ int mlx5_mdev_init(struct mlx5_core_dev *dev, int profile_idx)
        memcpy(&dev->profile, &profile[profile_idx], sizeof(dev->profile));
        INIT_LIST_HEAD(&priv->ctx_list);
        spin_lock_init(&priv->ctx_lock);
+       lockdep_register_key(&dev->lock_key);
        mutex_init(&dev->intf_state_mutex);
+       lockdep_set_class(&dev->intf_state_mutex, &dev->lock_key);
 
        mutex_init(&priv->bfregs.reg_head.lock);
        mutex_init(&priv->bfregs.wc_head.lock);
@@ -1597,6 +1599,7 @@ err_timeout_init:
        mutex_destroy(&priv->bfregs.wc_head.lock);
        mutex_destroy(&priv->bfregs.reg_head.lock);
        mutex_destroy(&dev->intf_state_mutex);
+       lockdep_unregister_key(&dev->lock_key);
        return err;
 }
 
@@ -1618,6 +1621,7 @@ void mlx5_mdev_uninit(struct mlx5_core_dev *dev)
        mutex_destroy(&priv->bfregs.wc_head.lock);
        mutex_destroy(&priv->bfregs.reg_head.lock);
        mutex_destroy(&dev->intf_state_mutex);
+       lockdep_unregister_key(&dev->lock_key);
 }
 
 static int probe_one(struct pci_dev *pdev, const struct pci_device_id *id)
index ec76a8b..6059635 100644 (file)
@@ -376,8 +376,8 @@ retry:
                        goto out_dropped;
                }
        }
+       err = mlx5_cmd_check(dev, err, in, out);
        if (err) {
-               err = mlx5_cmd_check(dev, err, in, out);
                mlx5_core_warn(dev, "func_id 0x%x, npages %d, err %d\n",
                               func_id, npages, err);
                goto out_dropped;
@@ -524,10 +524,13 @@ static int reclaim_pages(struct mlx5_core_dev *dev, u16 func_id, int npages,
                dev->priv.reclaim_pages_discard += npages;
        }
        /* if triggered by FW event and failed by FW then ignore */
-       if (event && err == -EREMOTEIO)
+       if (event && err == -EREMOTEIO) {
                err = 0;
+               goto out_free;
+       }
+
+       err = mlx5_cmd_check(dev, err, in, out);
        if (err) {
-               err = mlx5_cmd_check(dev, err, in, out);
                mlx5_core_err(dev, "failed reclaiming pages: err %d\n", err);
                goto out_free;
        }
index ee2e1b7..c0e6c48 100644 (file)
@@ -159,11 +159,11 @@ static int mlx5_sriov_enable(struct pci_dev *pdev, int num_vfs)
 
        devl_lock(devlink);
        err = mlx5_device_enable_sriov(dev, num_vfs);
+       devl_unlock(devlink);
        if (err) {
                mlx5_core_warn(dev, "mlx5_device_enable_sriov failed : %d\n", err);
                return err;
        }
-       devl_unlock(devlink);
 
        err = pci_enable_sriov(pdev, num_vfs);
        if (err) {
index 19009a6..9e57d23 100644 (file)
@@ -71,11 +71,6 @@ static int moxart_set_mac_address(struct net_device *ndev, void *addr)
 static void moxart_mac_free_memory(struct net_device *ndev)
 {
        struct moxart_mac_priv_t *priv = netdev_priv(ndev);
-       int i;
-
-       for (i = 0; i < RX_DESC_NUM; i++)
-               dma_unmap_single(&priv->pdev->dev, priv->rx_mapping[i],
-                                priv->rx_buf_size, DMA_FROM_DEVICE);
 
        if (priv->tx_desc_base)
                dma_free_coherent(&priv->pdev->dev,
@@ -187,6 +182,7 @@ static int moxart_mac_open(struct net_device *ndev)
 static int moxart_mac_stop(struct net_device *ndev)
 {
        struct moxart_mac_priv_t *priv = netdev_priv(ndev);
+       int i;
 
        napi_disable(&priv->napi);
 
@@ -198,6 +194,11 @@ static int moxart_mac_stop(struct net_device *ndev)
        /* disable all functions */
        writel(0, priv->base + REG_MAC_CTRL);
 
+       /* unmap areas mapped in moxart_mac_setup_desc_ring() */
+       for (i = 0; i < RX_DESC_NUM; i++)
+               dma_unmap_single(&priv->pdev->dev, priv->rx_mapping[i],
+                                priv->rx_buf_size, DMA_FROM_DEVICE);
+
        return 0;
 }
 
index 1443f78..0be79c5 100644 (file)
@@ -1564,8 +1564,67 @@ static int ionic_set_features(struct net_device *netdev,
        return err;
 }
 
+static int ionic_set_attr_mac(struct ionic_lif *lif, u8 *mac)
+{
+       struct ionic_admin_ctx ctx = {
+               .work = COMPLETION_INITIALIZER_ONSTACK(ctx.work),
+               .cmd.lif_setattr = {
+                       .opcode = IONIC_CMD_LIF_SETATTR,
+                       .index = cpu_to_le16(lif->index),
+                       .attr = IONIC_LIF_ATTR_MAC,
+               },
+       };
+
+       ether_addr_copy(ctx.cmd.lif_setattr.mac, mac);
+       return ionic_adminq_post_wait(lif, &ctx);
+}
+
+static int ionic_get_attr_mac(struct ionic_lif *lif, u8 *mac_addr)
+{
+       struct ionic_admin_ctx ctx = {
+               .work = COMPLETION_INITIALIZER_ONSTACK(ctx.work),
+               .cmd.lif_getattr = {
+                       .opcode = IONIC_CMD_LIF_GETATTR,
+                       .index = cpu_to_le16(lif->index),
+                       .attr = IONIC_LIF_ATTR_MAC,
+               },
+       };
+       int err;
+
+       err = ionic_adminq_post_wait(lif, &ctx);
+       if (err)
+               return err;
+
+       ether_addr_copy(mac_addr, ctx.comp.lif_getattr.mac);
+       return 0;
+}
+
+static int ionic_program_mac(struct ionic_lif *lif, u8 *mac)
+{
+       u8  get_mac[ETH_ALEN];
+       int err;
+
+       err = ionic_set_attr_mac(lif, mac);
+       if (err)
+               return err;
+
+       err = ionic_get_attr_mac(lif, get_mac);
+       if (err)
+               return err;
+
+       /* To deal with older firmware that silently ignores the set attr mac:
+        * doesn't actually change the mac and doesn't return an error, so we
+        * do the get attr to verify whether or not the set actually happened
+        */
+       if (!ether_addr_equal(get_mac, mac))
+               return 1;
+
+       return 0;
+}
+
 static int ionic_set_mac_address(struct net_device *netdev, void *sa)
 {
+       struct ionic_lif *lif = netdev_priv(netdev);
        struct sockaddr *addr = sa;
        u8 *mac;
        int err;
@@ -1574,6 +1633,14 @@ static int ionic_set_mac_address(struct net_device *netdev, void *sa)
        if (ether_addr_equal(netdev->dev_addr, mac))
                return 0;
 
+       err = ionic_program_mac(lif, mac);
+       if (err < 0)
+               return err;
+
+       if (err > 0)
+               netdev_dbg(netdev, "%s: SET and GET ATTR Mac are not equal-due to old FW running\n",
+                          __func__);
+
        err = eth_prepare_mac_addr_change(netdev, addr);
        if (err)
                return err;
@@ -2963,6 +3030,9 @@ static void ionic_lif_handle_fw_up(struct ionic_lif *lif)
 
        mutex_lock(&lif->queue_lock);
 
+       if (test_and_clear_bit(IONIC_LIF_F_BROKEN, lif->state))
+               dev_info(ionic->dev, "FW Up: clearing broken state\n");
+
        err = ionic_qcqs_alloc(lif);
        if (err)
                goto err_unlock;
@@ -3169,6 +3239,7 @@ static int ionic_station_set(struct ionic_lif *lif)
                        .attr = IONIC_LIF_ATTR_MAC,
                },
        };
+       u8 mac_address[ETH_ALEN];
        struct sockaddr addr;
        int err;
 
@@ -3177,8 +3248,23 @@ static int ionic_station_set(struct ionic_lif *lif)
                return err;
        netdev_dbg(lif->netdev, "found initial MAC addr %pM\n",
                   ctx.comp.lif_getattr.mac);
-       if (is_zero_ether_addr(ctx.comp.lif_getattr.mac))
-               return 0;
+       ether_addr_copy(mac_address, ctx.comp.lif_getattr.mac);
+
+       if (is_zero_ether_addr(mac_address)) {
+               eth_hw_addr_random(netdev);
+               netdev_dbg(netdev, "Random Mac generated: %pM\n", netdev->dev_addr);
+               ether_addr_copy(mac_address, netdev->dev_addr);
+
+               err = ionic_program_mac(lif, mac_address);
+               if (err < 0)
+                       return err;
+
+               if (err > 0) {
+                       netdev_dbg(netdev, "%s:SET/GET ATTR Mac are not same-due to old FW running\n",
+                                  __func__);
+                       return 0;
+               }
+       }
 
        if (!is_zero_ether_addr(netdev->dev_addr)) {
                /* If the netdev mac is non-zero and doesn't match the default
@@ -3186,12 +3272,11 @@ static int ionic_station_set(struct ionic_lif *lif)
                 * likely here again after a fw-upgrade reset.  We need to be
                 * sure the netdev mac is in our filter list.
                 */
-               if (!ether_addr_equal(ctx.comp.lif_getattr.mac,
-                                     netdev->dev_addr))
+               if (!ether_addr_equal(mac_address, netdev->dev_addr))
                        ionic_lif_addr_add(lif, netdev->dev_addr);
        } else {
                /* Update the netdev mac with the device's mac */
-               memcpy(addr.sa_data, ctx.comp.lif_getattr.mac, netdev->addr_len);
+               ether_addr_copy(addr.sa_data, mac_address);
                addr.sa_family = AF_INET;
                err = eth_prepare_mac_addr_change(netdev, &addr);
                if (err) {
index 4029b4e..56f93b0 100644 (file)
@@ -474,8 +474,8 @@ try_again:
                                ionic_opcode_to_str(opcode), opcode,
                                ionic_error_to_str(err), err);
 
-                       msleep(1000);
                        iowrite32(0, &idev->dev_cmd_regs->done);
+                       msleep(1000);
                        iowrite32(1, &idev->dev_cmd_regs->doorbell);
                        goto try_again;
                }
@@ -488,6 +488,8 @@ try_again:
                return ionic_error_to_errno(err);
        }
 
+       ionic_dev_cmd_clean(ionic);
+
        return 0;
 }
 
index caa4bfc..9b6138b 100644 (file)
@@ -258,14 +258,18 @@ EXPORT_SYMBOL_GPL(stmmac_set_mac_addr);
 /* Enable disable MAC RX/TX */
 void stmmac_set_mac(void __iomem *ioaddr, bool enable)
 {
-       u32 value = readl(ioaddr + MAC_CTRL_REG);
+       u32 old_val, value;
+
+       old_val = readl(ioaddr + MAC_CTRL_REG);
+       value = old_val;
 
        if (enable)
                value |= MAC_ENABLE_RX | MAC_ENABLE_TX;
        else
                value &= ~(MAC_ENABLE_TX | MAC_ENABLE_RX);
 
-       writel(value, ioaddr + MAC_CTRL_REG);
+       if (value != old_val)
+               writel(value, ioaddr + MAC_CTRL_REG);
 }
 
 void stmmac_get_mac_addr(void __iomem *ioaddr, unsigned char *addr,
index 070b5ef..592d29a 100644 (file)
@@ -986,10 +986,10 @@ static void stmmac_mac_link_up(struct phylink_config *config,
                               bool tx_pause, bool rx_pause)
 {
        struct stmmac_priv *priv = netdev_priv(to_net_dev(config->dev));
-       u32 ctrl;
+       u32 old_ctrl, ctrl;
 
-       ctrl = readl(priv->ioaddr + MAC_CTRL_REG);
-       ctrl &= ~priv->hw->link.speed_mask;
+       old_ctrl = readl(priv->ioaddr + MAC_CTRL_REG);
+       ctrl = old_ctrl & ~priv->hw->link.speed_mask;
 
        if (interface == PHY_INTERFACE_MODE_USXGMII) {
                switch (speed) {
@@ -1064,7 +1064,8 @@ static void stmmac_mac_link_up(struct phylink_config *config,
        if (tx_pause && rx_pause)
                stmmac_mac_flow_ctrl(priv, duplex);
 
-       writel(ctrl, priv->ioaddr + MAC_CTRL_REG);
+       if (ctrl != old_ctrl)
+               writel(ctrl, priv->ioaddr + MAC_CTRL_REG);
 
        stmmac_mac_set(priv, priv->ioaddr, true);
        if (phy && priv->dma_cap.eee) {
index 1e9eae2..53a1dbe 100644 (file)
@@ -568,7 +568,7 @@ static int ipa_smem_init(struct ipa *ipa, u32 item, size_t size)
        }
 
        /* Align the address down and the size up to a page boundary */
-       addr = qcom_smem_virt_to_phys(virt) & PAGE_MASK;
+       addr = qcom_smem_virt_to_phys(virt);
        phys = addr & PAGE_MASK;
        size = PAGE_ALIGN(size + addr - phys);
        iova = phys;    /* We just want a direct mapping */
index ef02f2c..cbabca1 100644 (file)
@@ -194,7 +194,7 @@ static struct notifier_block ipvtap_notifier_block __read_mostly = {
        .notifier_call  = ipvtap_device_event,
 };
 
-static int ipvtap_init(void)
+static int __init ipvtap_init(void)
 {
        int err;
 
@@ -228,7 +228,7 @@ out1:
 }
 module_init(ipvtap_init);
 
-static void ipvtap_exit(void)
+static void __exit ipvtap_exit(void)
 {
        rtnl_link_unregister(&ipvtap_link_ops);
        unregister_netdevice_notifier(&ipvtap_notifier_block);
index ee6087e..c6d271e 100644 (file)
@@ -462,11 +462,6 @@ static struct macsec_eth_header *macsec_ethhdr(struct sk_buff *skb)
        return (struct macsec_eth_header *)skb_mac_header(skb);
 }
 
-static sci_t dev_to_sci(struct net_device *dev, __be16 port)
-{
-       return make_sci(dev->dev_addr, port);
-}
-
 static void __macsec_pn_wrapped(struct macsec_secy *secy,
                                struct macsec_tx_sa *tx_sa)
 {
@@ -3661,7 +3656,6 @@ static int macsec_set_mac_address(struct net_device *dev, void *p)
 
 out:
        eth_hw_addr_set(dev, addr->sa_data);
-       macsec->secy.sci = dev_to_sci(dev, MACSEC_PORT_ES);
 
        /* If h/w offloading is available, propagate to the device */
        if (macsec_is_offloaded(macsec)) {
@@ -4000,6 +3994,11 @@ static bool sci_exists(struct net_device *dev, sci_t sci)
        return false;
 }
 
+static sci_t dev_to_sci(struct net_device *dev, __be16 port)
+{
+       return make_sci(dev->dev_addr, port);
+}
+
 static int macsec_add_dev(struct net_device *dev, sci_t sci, u8 icv_len)
 {
        struct macsec_dev *macsec = macsec_priv(dev);
index 0c6efd7..12ff276 100644 (file)
@@ -316,11 +316,11 @@ static __maybe_unused int mdio_bus_phy_resume(struct device *dev)
 
        phydev->suspended_by_mdio_bus = 0;
 
-       /* If we managed to get here with the PHY state machine in a state other
-        * than PHY_HALTED this is an indication that something went wrong and
-        * we should most likely be using MAC managed PM and we are not.
+       /* If we manged to get here with the PHY state machine in a state neither
+        * PHY_HALTED nor PHY_READY this is an indication that something went wrong
+        * and we should most likely be using MAC managed PM and we are not.
         */
-       WARN_ON(phydev->state != PHY_HALTED && !phydev->mac_managed_pm);
+       WARN_ON(phydev->state != PHY_HALTED && phydev->state != PHY_READY);
 
        ret = phy_init_hw(phydev);
        if (ret < 0)
index 0f6efaa..d142ac8 100644 (file)
@@ -5906,6 +5906,11 @@ static void r8153_enter_oob(struct r8152 *tp)
        ocp_data &= ~NOW_IS_OOB;
        ocp_write_byte(tp, MCU_TYPE_PLA, PLA_OOB_CTRL, ocp_data);
 
+       /* RX FIFO settings for OOB */
+       ocp_write_dword(tp, MCU_TYPE_PLA, PLA_RXFIFO_CTRL0, RXFIFO_THR1_OOB);
+       ocp_write_word(tp, MCU_TYPE_PLA, PLA_RXFIFO_CTRL1, RXFIFO_THR2_OOB);
+       ocp_write_word(tp, MCU_TYPE_PLA, PLA_RXFIFO_CTRL2, RXFIFO_THR3_OOB);
+
        rtl_disable(tp);
        rtl_reset_bmu(tp);
 
@@ -6431,21 +6436,8 @@ static void r8156_fc_parameter(struct r8152 *tp)
        u32 pause_on = tp->fc_pause_on ? tp->fc_pause_on : fc_pause_on_auto(tp);
        u32 pause_off = tp->fc_pause_off ? tp->fc_pause_off : fc_pause_off_auto(tp);
 
-       switch (tp->version) {
-       case RTL_VER_10:
-       case RTL_VER_11:
-               ocp_write_word(tp, MCU_TYPE_PLA, PLA_RX_FIFO_FULL, pause_on / 8);
-               ocp_write_word(tp, MCU_TYPE_PLA, PLA_RX_FIFO_EMPTY, pause_off / 8);
-               break;
-       case RTL_VER_12:
-       case RTL_VER_13:
-       case RTL_VER_15:
-               ocp_write_word(tp, MCU_TYPE_PLA, PLA_RX_FIFO_FULL, pause_on / 16);
-               ocp_write_word(tp, MCU_TYPE_PLA, PLA_RX_FIFO_EMPTY, pause_off / 16);
-               break;
-       default:
-               break;
-       }
+       ocp_write_word(tp, MCU_TYPE_PLA, PLA_RX_FIFO_FULL, pause_on / 16);
+       ocp_write_word(tp, MCU_TYPE_PLA, PLA_RX_FIFO_EMPTY, pause_off / 16);
 }
 
 static void rtl8156_change_mtu(struct r8152 *tp)
@@ -6557,6 +6549,11 @@ static void rtl8156_down(struct r8152 *tp)
        ocp_data &= ~NOW_IS_OOB;
        ocp_write_byte(tp, MCU_TYPE_PLA, PLA_OOB_CTRL, ocp_data);
 
+       /* RX FIFO settings for OOB */
+       ocp_write_word(tp, MCU_TYPE_PLA, PLA_RXFIFO_FULL, 64 / 16);
+       ocp_write_word(tp, MCU_TYPE_PLA, PLA_RX_FIFO_FULL, 1024 / 16);
+       ocp_write_word(tp, MCU_TYPE_PLA, PLA_RX_FIFO_EMPTY, 4096 / 16);
+
        rtl_disable(tp);
        rtl_reset_bmu(tp);
 
index 2caf997..07596bf 100644 (file)
@@ -310,6 +310,7 @@ static void pn532_uart_remove(struct serdev_device *serdev)
        pn53x_unregister_nfc(pn532->priv);
        serdev_device_close(serdev);
        pn53x_common_clean(pn532->priv);
+       del_timer_sync(&pn532->cmd_timeout);
        kfree_skb(pn532->recv_skb);
        kfree(pn532);
 }
index 9be007c..f223afe 100644 (file)
@@ -268,7 +268,7 @@ static int ioc_count;
 *   Each bit can represent a number of pages.
 *   LSbs represent lower addresses (IOVA's).
 *
-*   This was was copied from sba_iommu.c. Don't try to unify
+*   This was copied from sba_iommu.c. Don't try to unify
 *   the two resource managers unless a way to have different
 *   allocation policies is also adjusted. We'd like to avoid
 *   I/O TLB thrashing by having resource allocation policy
@@ -1380,15 +1380,17 @@ ccio_init_resource(struct resource *res, char *name, void __iomem *ioaddr)
        }
 }
 
-static void __init ccio_init_resources(struct ioc *ioc)
+static int __init ccio_init_resources(struct ioc *ioc)
 {
        struct resource *res = ioc->mmio_region;
        char *name = kmalloc(14, GFP_KERNEL);
-
+       if (unlikely(!name))
+               return -ENOMEM;
        snprintf(name, 14, "GSC Bus [%d/]", ioc->hw_path);
 
        ccio_init_resource(res, name, &ioc->ioc_regs->io_io_low);
        ccio_init_resource(res + 1, name, &ioc->ioc_regs->io_io_low_hv);
+       return 0;
 }
 
 static int new_ioc_area(struct resource *res, unsigned long size,
@@ -1543,7 +1545,10 @@ static int __init ccio_probe(struct parisc_device *dev)
                return -ENOMEM;
        }
        ccio_ioc_init(ioc);
-       ccio_init_resources(ioc);
+       if (ccio_init_resources(ioc)) {
+               kfree(ioc);
+               return -ENOMEM;
+       }
        hppa_dma_ops = &ccio_ops;
 
        hba = kzalloc(sizeof(*hba), GFP_KERNEL);
index 1e4a566..d4be9d2 100644 (file)
@@ -646,7 +646,7 @@ int lcd_print( const char *str )
                cancel_delayed_work_sync(&led_task);
 
        /* copy display string to buffer for procfs */
-       strlcpy(lcd_text, str, sizeof(lcd_text));
+       strscpy(lcd_text, str, sizeof(lcd_text));
 
        /* Set LCD Cursor to 1st character */
        gsc_writeb(lcd_info.reset_cmd1, LCD_CMD_REG);
index a3e117a..f6c37a9 100644 (file)
@@ -7153,22 +7153,18 @@ static int megasas_alloc_ctrl_mem(struct megasas_instance *instance)
        switch (instance->adapter_type) {
        case MFI_SERIES:
                if (megasas_alloc_mfi_ctrl_mem(instance))
-                       goto fail;
+                       return -ENOMEM;
                break;
        case AERO_SERIES:
        case VENTURA_SERIES:
        case THUNDERBOLT_SERIES:
        case INVADER_SERIES:
                if (megasas_alloc_fusion_context(instance))
-                       goto fail;
+                       return -ENOMEM;
                break;
        }
 
        return 0;
- fail:
-       kfree(instance->reply_map);
-       instance->reply_map = NULL;
-       return -ENOMEM;
 }
 
 /*
index e48d426..09c5fe3 100644 (file)
@@ -5310,7 +5310,6 @@ megasas_alloc_fusion_context(struct megasas_instance *instance)
                if (!fusion->log_to_span) {
                        dev_err(&instance->pdev->dev, "Failed from %s %d\n",
                                __func__, __LINE__);
-                       kfree(instance->ctrl_context);
                        return -ENOMEM;
                }
        }
index 2b2f682..62666df 100644 (file)
@@ -6935,14 +6935,8 @@ qlt_24xx_config_rings(struct scsi_qla_host *vha)
 
        if (ha->flags.msix_enabled) {
                if (IS_QLA83XX(ha) || IS_QLA27XX(ha) || IS_QLA28XX(ha)) {
-                       if (IS_QLA2071(ha)) {
-                               /* 4 ports Baker: Enable Interrupt Handshake */
-                               icb->msix_atio = 0;
-                               icb->firmware_options_2 |= cpu_to_le32(BIT_26);
-                       } else {
-                               icb->msix_atio = cpu_to_le16(msix->entry);
-                               icb->firmware_options_2 &= cpu_to_le32(~BIT_26);
-                       }
+                       icb->msix_atio = cpu_to_le16(msix->entry);
+                       icb->firmware_options_2 &= cpu_to_le32(~BIT_26);
                        ql_dbg(ql_dbg_init, vha, 0xf072,
                            "Registering ICB vector 0x%x for atio que.\n",
                            msix->entry);
index 4dbd29a..ef08029 100644 (file)
@@ -111,7 +111,7 @@ scsi_set_blocked(struct scsi_cmnd *cmd, int reason)
        }
 }
 
-static void scsi_mq_requeue_cmd(struct scsi_cmnd *cmd)
+static void scsi_mq_requeue_cmd(struct scsi_cmnd *cmd, unsigned long msecs)
 {
        struct request *rq = scsi_cmd_to_rq(cmd);
 
@@ -121,7 +121,12 @@ static void scsi_mq_requeue_cmd(struct scsi_cmnd *cmd)
        } else {
                WARN_ON_ONCE(true);
        }
-       blk_mq_requeue_request(rq, true);
+
+       if (msecs) {
+               blk_mq_requeue_request(rq, false);
+               blk_mq_delay_kick_requeue_list(rq->q, msecs);
+       } else
+               blk_mq_requeue_request(rq, true);
 }
 
 /**
@@ -651,14 +656,6 @@ static unsigned int scsi_rq_err_bytes(const struct request *rq)
        return bytes;
 }
 
-/* Helper for scsi_io_completion() when "reprep" action required. */
-static void scsi_io_completion_reprep(struct scsi_cmnd *cmd,
-                                     struct request_queue *q)
-{
-       /* A new command will be prepared and issued. */
-       scsi_mq_requeue_cmd(cmd);
-}
-
 static bool scsi_cmd_runtime_exceeced(struct scsi_cmnd *cmd)
 {
        struct request *req = scsi_cmd_to_rq(cmd);
@@ -676,14 +673,21 @@ static bool scsi_cmd_runtime_exceeced(struct scsi_cmnd *cmd)
        return false;
 }
 
+/*
+ * When ALUA transition state is returned, reprep the cmd to
+ * use the ALUA handler's transition timeout. Delay the reprep
+ * 1 sec to avoid aggressive retries of the target in that
+ * state.
+ */
+#define ALUA_TRANSITION_REPREP_DELAY   1000
+
 /* Helper for scsi_io_completion() when special action required. */
 static void scsi_io_completion_action(struct scsi_cmnd *cmd, int result)
 {
-       struct request_queue *q = cmd->device->request_queue;
        struct request *req = scsi_cmd_to_rq(cmd);
        int level = 0;
-       enum {ACTION_FAIL, ACTION_REPREP, ACTION_RETRY,
-             ACTION_DELAYED_RETRY} action;
+       enum {ACTION_FAIL, ACTION_REPREP, ACTION_DELAYED_REPREP,
+             ACTION_RETRY, ACTION_DELAYED_RETRY} action;
        struct scsi_sense_hdr sshdr;
        bool sense_valid;
        bool sense_current = true;      /* false implies "deferred sense" */
@@ -772,8 +776,8 @@ static void scsi_io_completion_action(struct scsi_cmnd *cmd, int result)
                                        action = ACTION_DELAYED_RETRY;
                                        break;
                                case 0x0a: /* ALUA state transition */
-                                       blk_stat = BLK_STS_TRANSPORT;
-                                       fallthrough;
+                                       action = ACTION_DELAYED_REPREP;
+                                       break;
                                default:
                                        action = ACTION_FAIL;
                                        break;
@@ -832,7 +836,10 @@ static void scsi_io_completion_action(struct scsi_cmnd *cmd, int result)
                        return;
                fallthrough;
        case ACTION_REPREP:
-               scsi_io_completion_reprep(cmd, q);
+               scsi_mq_requeue_cmd(cmd, 0);
+               break;
+       case ACTION_DELAYED_REPREP:
+               scsi_mq_requeue_cmd(cmd, ALUA_TRANSITION_REPREP_DELAY);
                break;
        case ACTION_RETRY:
                /* Retry the same command immediately */
@@ -926,7 +933,7 @@ static int scsi_io_completion_nz_result(struct scsi_cmnd *cmd, int result,
  * command block will be released and the queue function will be goosed. If we
  * are not done then we have to figure out what to do next:
  *
- *   a) We can call scsi_io_completion_reprep().  The request will be
+ *   a) We can call scsi_mq_requeue_cmd().  The request will be
  *     unprepared and put back on the queue.  Then a new command will
  *     be created for it.  This should be used if we made forward
  *     progress, or if we want to switch from READ(10) to READ(6) for
@@ -942,7 +949,6 @@ static int scsi_io_completion_nz_result(struct scsi_cmnd *cmd, int result,
 void scsi_io_completion(struct scsi_cmnd *cmd, unsigned int good_bytes)
 {
        int result = cmd->result;
-       struct request_queue *q = cmd->device->request_queue;
        struct request *req = scsi_cmd_to_rq(cmd);
        blk_status_t blk_stat = BLK_STS_OK;
 
@@ -979,7 +985,7 @@ void scsi_io_completion(struct scsi_cmnd *cmd, unsigned int good_bytes)
         * request just queue the command up again.
         */
        if (likely(result == 0))
-               scsi_io_completion_reprep(cmd, q);
+               scsi_mq_requeue_cmd(cmd, 0);
        else
                scsi_io_completion_action(cmd, result);
 }
@@ -1542,7 +1548,6 @@ static blk_status_t scsi_prepare_cmd(struct request *req)
        scsi_init_command(sdev, cmd);
 
        cmd->eh_eflags = 0;
-       cmd->allowed = 0;
        cmd->prot_type = 0;
        cmd->prot_flags = 0;
        cmd->submitter = 0;
@@ -1593,6 +1598,8 @@ static blk_status_t scsi_prepare_cmd(struct request *req)
                        return ret;
        }
 
+       /* Usually overridden by the ULP */
+       cmd->allowed = 0;
        memset(cmd->cmnd, 0, sizeof(cmd->cmnd));
        return scsi_cmd_to_driver(cmd)->init_command(cmd);
 }
index 8f79fa6..eb76ba0 100644 (file)
@@ -103,7 +103,6 @@ static void sd_config_discard(struct scsi_disk *, unsigned int);
 static void sd_config_write_same(struct scsi_disk *);
 static int  sd_revalidate_disk(struct gendisk *);
 static void sd_unlock_native_capacity(struct gendisk *disk);
-static void sd_start_done_work(struct work_struct *work);
 static int  sd_probe(struct device *);
 static int  sd_remove(struct device *);
 static void sd_shutdown(struct device *);
@@ -3471,7 +3470,6 @@ static int sd_probe(struct device *dev)
        sdkp->max_retries = SD_MAX_RETRIES;
        atomic_set(&sdkp->openers, 0);
        atomic_set(&sdkp->device->ioerr_cnt, 0);
-       INIT_WORK(&sdkp->start_done_work, sd_start_done_work);
 
        if (!sdp->request_queue->rq_timeout) {
                if (sdp->type != TYPE_MOD)
@@ -3594,69 +3592,12 @@ static void scsi_disk_release(struct device *dev)
        kfree(sdkp);
 }
 
-/* Process sense data after a START command finished. */
-static void sd_start_done_work(struct work_struct *work)
-{
-       struct scsi_disk *sdkp = container_of(work, typeof(*sdkp),
-                                             start_done_work);
-       struct scsi_sense_hdr sshdr;
-       int res = sdkp->start_result;
-
-       if (res == 0)
-               return;
-
-       sd_print_result(sdkp, "Start/Stop Unit failed", res);
-
-       if (res < 0)
-               return;
-
-       if (scsi_normalize_sense(sdkp->start_sense_buffer,
-                                sdkp->start_sense_len, &sshdr))
-               sd_print_sense_hdr(sdkp, &sshdr);
-}
-
-/* A START command finished. May be called from interrupt context. */
-static void sd_start_done(struct request *req, blk_status_t status)
-{
-       const struct scsi_cmnd *scmd = blk_mq_rq_to_pdu(req);
-       struct scsi_disk *sdkp = scsi_disk(req->q->disk);
-
-       sdkp->start_result = scmd->result;
-       WARN_ON_ONCE(scmd->sense_len > SCSI_SENSE_BUFFERSIZE);
-       sdkp->start_sense_len = scmd->sense_len;
-       memcpy(sdkp->start_sense_buffer, scmd->sense_buffer,
-              ARRAY_SIZE(sdkp->start_sense_buffer));
-       WARN_ON_ONCE(!schedule_work(&sdkp->start_done_work));
-}
-
-/* Submit a START command asynchronously. */
-static int sd_submit_start(struct scsi_disk *sdkp, u8 cmd[], u8 cmd_len)
-{
-       struct scsi_device *sdev = sdkp->device;
-       struct request_queue *q = sdev->request_queue;
-       struct request *req;
-       struct scsi_cmnd *scmd;
-
-       req = scsi_alloc_request(q, REQ_OP_DRV_IN, BLK_MQ_REQ_PM);
-       if (IS_ERR(req))
-               return PTR_ERR(req);
-
-       scmd = blk_mq_rq_to_pdu(req);
-       scmd->cmd_len = cmd_len;
-       memcpy(scmd->cmnd, cmd, cmd_len);
-       scmd->allowed = sdkp->max_retries;
-       req->timeout = SD_TIMEOUT;
-       req->rq_flags |= RQF_PM | RQF_QUIET;
-       req->end_io = sd_start_done;
-       blk_execute_rq_nowait(req, /*at_head=*/true);
-
-       return 0;
-}
-
 static int sd_start_stop_device(struct scsi_disk *sdkp, int start)
 {
        unsigned char cmd[6] = { START_STOP };  /* START_VALID */
+       struct scsi_sense_hdr sshdr;
        struct scsi_device *sdp = sdkp->device;
+       int res;
 
        if (start)
                cmd[4] |= 1;    /* START */
@@ -3667,10 +3608,23 @@ static int sd_start_stop_device(struct scsi_disk *sdkp, int start)
        if (!scsi_device_online(sdp))
                return -ENODEV;
 
-       /* Wait until processing of sense data has finished. */
-       flush_work(&sdkp->start_done_work);
+       res = scsi_execute(sdp, cmd, DMA_NONE, NULL, 0, NULL, &sshdr,
+                       SD_TIMEOUT, sdkp->max_retries, 0, RQF_PM, NULL);
+       if (res) {
+               sd_print_result(sdkp, "Start/Stop Unit failed", res);
+               if (res > 0 && scsi_sense_valid(&sshdr)) {
+                       sd_print_sense_hdr(sdkp, &sshdr);
+                       /* 0x3a is medium not present */
+                       if (sshdr.asc == 0x3a)
+                               res = 0;
+               }
+       }
 
-       return sd_submit_start(sdkp, cmd, sizeof(cmd));
+       /* SCSI error codes must not go to the generic layer */
+       if (res)
+               return -EIO;
+
+       return 0;
 }
 
 /*
@@ -3697,8 +3651,6 @@ static void sd_shutdown(struct device *dev)
                sd_printk(KERN_NOTICE, sdkp, "Stopping disk\n");
                sd_start_stop_device(sdkp, 0);
        }
-
-       flush_work(&sdkp->start_done_work);
 }
 
 static int sd_suspend_common(struct device *dev, bool ignore_stop_errors)
index b891877..5eea762 100644 (file)
@@ -150,11 +150,6 @@ struct scsi_disk {
        unsigned        urswrz : 1;
        unsigned        security : 1;
        unsigned        ignore_medium_access_errors : 1;
-
-       int             start_result;
-       u32             start_sense_len;
-       u8              start_sense_buffer[SCSI_SENSE_BUFFERSIZE];
-       struct work_struct start_done_work;
 };
 #define to_scsi_disk(obj) container_of(obj, struct scsi_disk, disk_dev)
 
index fe000da..8ced292 100644 (file)
@@ -2012,7 +2012,7 @@ static int storvsc_probe(struct hv_device *device,
         */
        host_dev->handle_error_wq =
                        alloc_ordered_workqueue("storvsc_error_wq_%d",
-                                               WQ_MEM_RECLAIM,
+                                               0,
                                                host->host_no);
        if (!host_dev->handle_error_wq) {
                ret = -ENOMEM;
index 80d4e06..365489b 100644 (file)
@@ -527,7 +527,7 @@ static void int3400_setup_gddv(struct int3400_thermal_priv *priv)
        priv->data_vault = kmemdup(obj->package.elements[0].buffer.pointer,
                                   obj->package.elements[0].buffer.length,
                                   GFP_KERNEL);
-       if (!priv->data_vault)
+       if (ZERO_OR_NULL_PTR(priv->data_vault))
                goto out_free;
 
        bin_attr_data_vault.private = priv->data_vault;
@@ -597,7 +597,7 @@ static int int3400_thermal_probe(struct platform_device *pdev)
                        goto free_imok;
        }
 
-       if (priv->data_vault) {
+       if (!ZERO_OR_NULL_PTR(priv->data_vault)) {
                result = sysfs_create_group(&pdev->dev.kobj,
                                            &data_attribute_group);
                if (result)
@@ -615,7 +615,8 @@ static int int3400_thermal_probe(struct platform_device *pdev)
 free_sysfs:
        cleanup_odvp(priv);
        if (priv->data_vault) {
-               sysfs_remove_group(&pdev->dev.kobj, &data_attribute_group);
+               if (!ZERO_OR_NULL_PTR(priv->data_vault))
+                       sysfs_remove_group(&pdev->dev.kobj, &data_attribute_group);
                kfree(priv->data_vault);
        }
 free_uuid:
@@ -647,7 +648,7 @@ static int int3400_thermal_remove(struct platform_device *pdev)
        if (!priv->rel_misc_dev_res)
                acpi_thermal_rel_misc_device_remove(priv->adev->handle);
 
-       if (priv->data_vault)
+       if (!ZERO_OR_NULL_PTR(priv->data_vault))
                sysfs_remove_group(&pdev->dev.kobj, &data_attribute_group);
        sysfs_remove_group(&pdev->dev.kobj, &uuid_attribute_group);
        sysfs_remove_group(&pdev->dev.kobj, &imok_attribute_group);
index 6a5d0ae..50d50ce 100644 (file)
@@ -1329,6 +1329,7 @@ free_tz:
        kfree(tz);
        return ERR_PTR(result);
 }
+EXPORT_SYMBOL_GPL(thermal_zone_device_register_with_trips);
 
 struct thermal_zone_device *thermal_zone_device_register(const char *type, int ntrips, int mask,
                                                         void *devdata, struct thermal_zone_device_ops *ops,
index 6bc679d..a202d7d 100644 (file)
@@ -8741,6 +8741,8 @@ static int ufshcd_set_dev_pwr_mode(struct ufs_hba *hba,
        struct scsi_device *sdp;
        unsigned long flags;
        int ret, retries;
+       unsigned long deadline;
+       int32_t remaining;
 
        spin_lock_irqsave(hba->host->host_lock, flags);
        sdp = hba->ufs_device_wlun;
@@ -8773,9 +8775,14 @@ static int ufshcd_set_dev_pwr_mode(struct ufs_hba *hba,
         * callbacks hence set the RQF_PM flag so that it doesn't resume the
         * already suspended childs.
         */
+       deadline = jiffies + 10 * HZ;
        for (retries = 3; retries > 0; --retries) {
+               ret = -ETIMEDOUT;
+               remaining = deadline - jiffies;
+               if (remaining <= 0)
+                       break;
                ret = scsi_execute(sdp, cmd, DMA_NONE, NULL, 0, NULL, &sshdr,
-                               START_STOP_TIMEOUT, 0, 0, RQF_PM, NULL);
+                                  remaining / HZ, 0, 0, RQF_PM, NULL);
                if (!scsi_status_is_check_condition(ret) ||
                                !scsi_sense_valid(&sshdr) ||
                                sshdr.sense_key != UNIT_ATTENTION)
index eced975..c3628a8 100644 (file)
@@ -1711,7 +1711,7 @@ static struct exynos_ufs_uic_attr fsd_uic_attr = {
        .pa_dbg_option_suite            = 0x2E820183,
 };
 
-struct exynos_ufs_drv_data fsd_ufs_drvs = {
+static const struct exynos_ufs_drv_data fsd_ufs_drvs = {
        .uic_attr               = &fsd_uic_attr,
        .quirks                 = UFSHCD_QUIRK_PRDT_BYTE_GRAN |
                                  UFSHCI_QUIRK_BROKEN_REQ_LIST_CLR |
index bd4dc97..db568f6 100644 (file)
@@ -290,7 +290,7 @@ static char default_sti_path[21] __read_mostly;
 static int __init sti_setup(char *str)
 {
        if (str)
-               strlcpy (default_sti_path, str, sizeof (default_sti_path));
+               strscpy(default_sti_path, str, sizeof(default_sti_path));
        
        return 1;
 }
index a3e6fae..14eb718 100644 (file)
@@ -3891,7 +3891,7 @@ static int __init atyfb_setup(char *options)
                         && (!strncmp(this_opt, "Mach64:", 7))) {
                        static unsigned char m64_num;
                        static char mach64_str[80];
-                       strlcpy(mach64_str, this_opt + 7, sizeof(mach64_str));
+                       strscpy(mach64_str, this_opt + 7, sizeof(mach64_str));
                        if (!store_video_par(mach64_str, m64_num)) {
                                m64_num++;
                                mach64_count = m64_num;
index 6851f47..a14a8d7 100644 (file)
@@ -1980,7 +1980,7 @@ static int radeon_set_fbinfo(struct radeonfb_info *rinfo)
        info->screen_base = rinfo->fb_base;
        info->screen_size = rinfo->mapped_vram;
        /* Fill fix common fields */
-       strlcpy(info->fix.id, rinfo->name, sizeof(info->fix.id));
+       strscpy(info->fix.id, rinfo->name, sizeof(info->fix.id));
         info->fix.smem_start = rinfo->fb_base_phys;
         info->fix.smem_len = rinfo->video_ram;
         info->fix.type = FB_TYPE_PACKED_PIXELS;
@@ -2094,34 +2094,34 @@ static void radeon_identify_vram(struct radeonfb_info *rinfo)
        u32 tmp;
 
        /* framebuffer size */
-        if ((rinfo->family == CHIP_FAMILY_RS100) ||
+       if ((rinfo->family == CHIP_FAMILY_RS100) ||
             (rinfo->family == CHIP_FAMILY_RS200) ||
             (rinfo->family == CHIP_FAMILY_RS300) ||
             (rinfo->family == CHIP_FAMILY_RC410) ||
             (rinfo->family == CHIP_FAMILY_RS400) ||
            (rinfo->family == CHIP_FAMILY_RS480) ) {
-          u32 tom = INREG(NB_TOM);
-          tmp = ((((tom >> 16) - (tom & 0xffff) + 1) << 6) * 1024);
-
-               radeon_fifo_wait(6);
-          OUTREG(MC_FB_LOCATION, tom);
-          OUTREG(DISPLAY_BASE_ADDR, (tom & 0xffff) << 16);
-          OUTREG(CRTC2_DISPLAY_BASE_ADDR, (tom & 0xffff) << 16);
-          OUTREG(OV0_BASE_ADDR, (tom & 0xffff) << 16);
-
-          /* This is supposed to fix the crtc2 noise problem. */
-          OUTREG(GRPH2_BUFFER_CNTL, INREG(GRPH2_BUFFER_CNTL) & ~0x7f0000);
-
-          if ((rinfo->family == CHIP_FAMILY_RS100) ||
-              (rinfo->family == CHIP_FAMILY_RS200)) {
-             /* This is to workaround the asic bug for RMX, some versions
-                of BIOS doesn't have this register initialized correctly.
-             */
-             OUTREGP(CRTC_MORE_CNTL, CRTC_H_CUTOFF_ACTIVE_EN,
-                     ~CRTC_H_CUTOFF_ACTIVE_EN);
-          }
-        } else {
-          tmp = INREG(CNFG_MEMSIZE);
+               u32 tom = INREG(NB_TOM);
+
+               tmp = ((((tom >> 16) - (tom & 0xffff) + 1) << 6) * 1024);
+               radeon_fifo_wait(6);
+               OUTREG(MC_FB_LOCATION, tom);
+               OUTREG(DISPLAY_BASE_ADDR, (tom & 0xffff) << 16);
+               OUTREG(CRTC2_DISPLAY_BASE_ADDR, (tom & 0xffff) << 16);
+               OUTREG(OV0_BASE_ADDR, (tom & 0xffff) << 16);
+
+               /* This is supposed to fix the crtc2 noise problem. */
+               OUTREG(GRPH2_BUFFER_CNTL, INREG(GRPH2_BUFFER_CNTL) & ~0x7f0000);
+
+               if ((rinfo->family == CHIP_FAMILY_RS100) ||
+                   (rinfo->family == CHIP_FAMILY_RS200)) {
+                       /* This is to workaround the asic bug for RMX, some versions
+                        * of BIOS doesn't have this register initialized correctly.
+                        */
+                       OUTREGP(CRTC_MORE_CNTL, CRTC_H_CUTOFF_ACTIVE_EN,
+                               ~CRTC_H_CUTOFF_ACTIVE_EN);
+               }
+       } else {
+               tmp = INREG(CNFG_MEMSIZE);
         }
 
        /* mem size is bits [28:0], mask off the rest */
index e7702fe..6403ae0 100644 (file)
@@ -182,7 +182,7 @@ static int bw2_ioctl(struct fb_info *info, unsigned int cmd, unsigned long arg)
 
 static void bw2_init_fix(struct fb_info *info, int linebytes)
 {
-       strlcpy(info->fix.id, "bwtwo", sizeof(info->fix.id));
+       strscpy(info->fix.id, "bwtwo", sizeof(info->fix.id));
 
        info->fix.type = FB_TYPE_PACKED_PIXELS;
        info->fix.visual = FB_VISUAL_MONO01;
index 393894a..2b00a9d 100644 (file)
@@ -430,6 +430,7 @@ static int chipsfb_pci_init(struct pci_dev *dp, const struct pci_device_id *ent)
  err_release_fb:
        framebuffer_release(p);
  err_disable:
+       pci_disable_device(dp);
  err_out:
        return rc;
 }
index a41a758..2a9fa06 100644 (file)
@@ -1999,7 +1999,7 @@ static int cirrusfb_set_fbinfo(struct fb_info *info)
        }
 
        /* Fill fix common fields */
-       strlcpy(info->fix.id, cirrusfb_board_info[cinfo->btype].name,
+       strscpy(info->fix.id, cirrusfb_board_info[cinfo->btype].name,
                sizeof(info->fix.id));
 
        /* monochrome: only 1 memory plane */
index 771ce1f..a1061c2 100644 (file)
@@ -326,7 +326,7 @@ static int clps711x_fb_probe(struct platform_device *pdev)
        info->var.vmode = FB_VMODE_NONINTERLACED;
        info->fix.type = FB_TYPE_PACKED_PIXELS;
        info->fix.accel = FB_ACCEL_NONE;
-       strlcpy(info->fix.id, CLPS711X_FB_NAME, sizeof(info->fix.id));
+       strscpy(info->fix.id, CLPS711X_FB_NAME, sizeof(info->fix.id));
        fb_videomode_to_var(&info->var, &cfb->mode);
 
        ret = fb_alloc_cmap(&info->cmap, BIT(CLPS711X_FB_BPP_MAX), 0);
index cf9ac4d..098b62f 100644 (file)
@@ -412,7 +412,7 @@ static int __init fb_console_setup(char *this_opt)
 
        while ((options = strsep(&this_opt, ",")) != NULL) {
                if (!strncmp(options, "font:", 5)) {
-                       strlcpy(fontname, options + 5, sizeof(fontname));
+                       strscpy(fontname, options + 5, sizeof(fontname));
                        continue;
                }
                
@@ -2401,15 +2401,21 @@ static int fbcon_do_set_font(struct vc_data *vc, int w, int h, int charcount,
        struct fb_info *info = fbcon_info_from_console(vc->vc_num);
        struct fbcon_ops *ops = info->fbcon_par;
        struct fbcon_display *p = &fb_display[vc->vc_num];
-       int resize;
+       int resize, ret, old_userfont, old_width, old_height, old_charcount;
        char *old_data = NULL;
 
        resize = (w != vc->vc_font.width) || (h != vc->vc_font.height);
        if (p->userfont)
                old_data = vc->vc_font.data;
        vc->vc_font.data = (void *)(p->fontdata = data);
+       old_userfont = p->userfont;
        if ((p->userfont = userfont))
                REFCOUNT(data)++;
+
+       old_width = vc->vc_font.width;
+       old_height = vc->vc_font.height;
+       old_charcount = vc->vc_font.charcount;
+
        vc->vc_font.width = w;
        vc->vc_font.height = h;
        vc->vc_font.charcount = charcount;
@@ -2425,7 +2431,9 @@ static int fbcon_do_set_font(struct vc_data *vc, int w, int h, int charcount,
                rows = FBCON_SWAP(ops->rotate, info->var.yres, info->var.xres);
                cols /= w;
                rows /= h;
-               vc_resize(vc, cols, rows);
+               ret = vc_resize(vc, cols, rows);
+               if (ret)
+                       goto err_out;
        } else if (con_is_visible(vc)
                   && vc->vc_mode == KD_TEXT) {
                fbcon_clear_margins(vc, 0);
@@ -2435,6 +2443,21 @@ static int fbcon_do_set_font(struct vc_data *vc, int w, int h, int charcount,
        if (old_data && (--REFCOUNT(old_data) == 0))
                kfree(old_data - FONT_EXTRA_WORDS * sizeof(int));
        return 0;
+
+err_out:
+       p->fontdata = old_data;
+       vc->vc_font.data = (void *)old_data;
+
+       if (userfont) {
+               p->userfont = old_userfont;
+               REFCOUNT(data)--;
+       }
+
+       vc->vc_font.width = old_width;
+       vc->vc_font.height = old_height;
+       vc->vc_font.charcount = old_charcount;
+
+       return ret;
 }
 
 /*
index c2a60b1..4d7f638 100644 (file)
@@ -84,6 +84,10 @@ void framebuffer_release(struct fb_info *info)
        if (WARN_ON(refcount_read(&info->count)))
                return;
 
+#if IS_ENABLED(CONFIG_FB_BACKLIGHT)
+       mutex_destroy(&info->bl_curve_mutex);
+#endif
+
        kfree(info->apertures);
        kfree(info);
 }
index d45355b..8f041f9 100644 (file)
@@ -1134,7 +1134,7 @@ int cyber2000fb_attach(struct cyberpro_info *info, int idx)
                info->fb_size         = int_cfb_info->fb.fix.smem_len;
                info->info            = int_cfb_info;
 
-               strlcpy(info->dev_name, int_cfb_info->fb.fix.id,
+               strscpy(info->dev_name, int_cfb_info->fb.fix.id,
                        sizeof(info->dev_name));
        }
 
@@ -1229,7 +1229,7 @@ static int cyber2000fb_ddc_getsda(void *data)
 
 static int cyber2000fb_setup_ddc_bus(struct cfb_info *cfb)
 {
-       strlcpy(cfb->ddc_adapter.name, cfb->fb.fix.id,
+       strscpy(cfb->ddc_adapter.name, cfb->fb.fix.id,
                sizeof(cfb->ddc_adapter.name));
        cfb->ddc_adapter.owner          = THIS_MODULE;
        cfb->ddc_adapter.class          = I2C_CLASS_DDC;
@@ -1304,7 +1304,7 @@ static int cyber2000fb_i2c_getscl(void *data)
 
 static int cyber2000fb_i2c_register(struct cfb_info *cfb)
 {
-       strlcpy(cfb->i2c_adapter.name, cfb->fb.fix.id,
+       strscpy(cfb->i2c_adapter.name, cfb->fb.fix.id,
                sizeof(cfb->i2c_adapter.name));
        cfb->i2c_adapter.owner = THIS_MODULE;
        cfb->i2c_adapter.algo_data = &cfb->i2c_algo;
@@ -1500,7 +1500,7 @@ static int cyber2000fb_setup(char *options)
                if (strncmp(opt, "font:", 5) == 0) {
                        static char default_font_storage[40];
 
-                       strlcpy(default_font_storage, opt + 5,
+                       strscpy(default_font_storage, opt + 5,
                                sizeof(default_font_storage));
                        default_font = default_font_storage;
                        continue;
index b3d580e..7cba396 100644 (file)
@@ -883,7 +883,7 @@ static void ffb_init_fix(struct fb_info *info)
        } else
                ffb_type_name = "Elite 3D";
 
-       strlcpy(info->fix.id, ffb_type_name, sizeof(info->fix.id));
+       strscpy(info->fix.id, ffb_type_name, sizeof(info->fix.id));
 
        info->fix.type = FB_TYPE_PACKED_PIXELS;
        info->fix.visual = FB_VISUAL_TRUECOLOR;
index 5d34d89..e41204e 100644 (file)
@@ -410,13 +410,13 @@ static void __init gx1fb_setup(char *options)
                        continue;
 
                if (!strncmp(this_opt, "mode:", 5))
-                       strlcpy(mode_option, this_opt + 5, sizeof(mode_option));
+                       strscpy(mode_option, this_opt + 5, sizeof(mode_option));
                else if (!strncmp(this_opt, "crt:", 4))
                        crt_option = !!simple_strtoul(this_opt + 4, NULL, 0);
                else if (!strncmp(this_opt, "panel:", 6))
-                       strlcpy(panel_option, this_opt + 6, sizeof(panel_option));
+                       strscpy(panel_option, this_opt + 6, sizeof(panel_option));
                else
-                       strlcpy(mode_option, this_opt, sizeof(mode_option));
+                       strscpy(mode_option, this_opt, sizeof(mode_option));
        }
 }
 #endif
index e5475ae..94588b8 100644 (file)
@@ -650,7 +650,7 @@ static int gxt4500_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
        cardtype = ent->driver_data;
        par->refclk_ps = cardinfo[cardtype].refclk_ps;
        info->fix = gxt4500_fix;
-       strlcpy(info->fix.id, cardinfo[cardtype].cardname,
+       strscpy(info->fix.id, cardinfo[cardtype].cardname,
                sizeof(info->fix.id));
        info->pseudo_palette = par->pseudo_palette;
 
index 7f09a0d..bd30d83 100644 (file)
@@ -159,7 +159,7 @@ static int i740fb_setup_ddc_bus(struct fb_info *info)
 {
        struct i740fb_par *par = info->par;
 
-       strlcpy(par->ddc_adapter.name, info->fix.id,
+       strscpy(par->ddc_adapter.name, info->fix.id,
                sizeof(par->ddc_adapter.name));
        par->ddc_adapter.owner          = THIS_MODULE;
        par->ddc_adapter.class          = I2C_CLASS_DDC;
index d97d745..94f3bc6 100644 (file)
@@ -681,7 +681,7 @@ static int imxfb_init_fbinfo(struct platform_device *pdev)
 
        fbi->devtype = pdev->id_entry->driver_data;
 
-       strlcpy(info->fix.id, IMX_NAME, sizeof(info->fix.id));
+       strscpy(info->fix.id, IMX_NAME, sizeof(info->fix.id));
 
        info->fix.type                  = FB_TYPE_PACKED_PIXELS;
        info->fix.type_aux              = 0;
index 236521b..68bba26 100644 (file)
@@ -2383,9 +2383,9 @@ static int __init matroxfb_setup(char *options) {
                else if (!strncmp(this_opt, "mem:", 4))
                        mem = simple_strtoul(this_opt+4, NULL, 0);
                else if (!strncmp(this_opt, "mode:", 5))
-                       strlcpy(videomode, this_opt+5, sizeof(videomode));
+                       strscpy(videomode, this_opt + 5, sizeof(videomode));
                else if (!strncmp(this_opt, "outputs:", 8))
-                       strlcpy(outputs, this_opt+8, sizeof(outputs));
+                       strscpy(outputs, this_opt + 8, sizeof(outputs));
                else if (!strncmp(this_opt, "dfp:", 4)) {
                        dfp_type = simple_strtoul(this_opt+4, NULL, 0);
                        dfp = 1;
@@ -2455,7 +2455,7 @@ static int __init matroxfb_setup(char *options) {
                        else if (!strcmp(this_opt, "dfp"))
                                dfp = value;
                        else {
-                               strlcpy(videomode, this_opt, sizeof(videomode));
+                               strscpy(videomode, this_opt, sizeof(videomode));
                        }
                }
        }
index dfb4ddc..17cda57 100644 (file)
@@ -1642,15 +1642,13 @@ static int omapfb_do_probe(struct platform_device *pdev,
                goto cleanup;
        }
        fbdev->int_irq = platform_get_irq(pdev, 0);
-       if (!fbdev->int_irq) {
-               dev_err(&pdev->dev, "unable to get irq\n");
+       if (fbdev->int_irq < 0) {
                r = ENXIO;
                goto cleanup;
        }
 
        fbdev->ext_irq = platform_get_irq(pdev, 1);
-       if (!fbdev->ext_irq) {
-               dev_err(&pdev->dev, "unable to get irq\n");
+       if (fbdev->ext_irq < 0) {
                r = ENXIO;
                goto cleanup;
        }
index afa688e..5ccddcf 100644 (file)
@@ -1331,7 +1331,7 @@ static void clear_fb_info(struct fb_info *fbi)
 {
        memset(&fbi->var, 0, sizeof(fbi->var));
        memset(&fbi->fix, 0, sizeof(fbi->fix));
-       strlcpy(fbi->fix.id, MODULE_NAME, sizeof(fbi->fix.id));
+       strscpy(fbi->fix.id, MODULE_NAME, sizeof(fbi->fix.id));
 }
 
 static int omapfb_free_all_fbmem(struct omapfb2_device *fbdev)
index d3be2c6..8fd79de 100644 (file)
@@ -617,6 +617,11 @@ static int pm2fb_check_var(struct fb_var_screeninfo *var, struct fb_info *info)
                return -EINVAL;
        }
 
+       if (!var->pixclock) {
+               DPRINTK("pixclock is zero\n");
+               return -EINVAL;
+       }
+
        if (PICOS2KHZ(var->pixclock) > PM2_MAX_PIXCLOCK) {
                DPRINTK("pixclock too high (%ldKHz)\n",
                        PICOS2KHZ(var->pixclock));
index e943300..d5d0bbd 100644 (file)
@@ -640,7 +640,7 @@ static int pxa168fb_probe(struct platform_device *pdev)
        info->flags = FBINFO_DEFAULT | FBINFO_PARTIAL_PAN_OK |
                      FBINFO_HWACCEL_XPAN | FBINFO_HWACCEL_YPAN;
        info->node = -1;
-       strlcpy(info->fix.id, mi->id, 16);
+       strscpy(info->fix.id, mi->id, 16);
        info->fix.type = FB_TYPE_PACKED_PIXELS;
        info->fix.type_aux = 0;
        info->fix.xpanstep = 0;
index 66cfc3e..696ac54 100644 (file)
@@ -2042,7 +2042,7 @@ static int __init pxafb_setup_options(void)
                return -ENODEV;
 
        if (options)
-               strlcpy(g_options, options, sizeof(g_options));
+               strscpy(g_options, options, sizeof(g_options));
 
        return 0;
 }
index 5069f6f..67b63a7 100644 (file)
@@ -248,7 +248,7 @@ static int s3fb_setup_ddc_bus(struct fb_info *info)
 {
        struct s3fb_info *par = info->par;
 
-       strlcpy(par->ddc_adapter.name, info->fix.id,
+       strscpy(par->ddc_adapter.name, info->fix.id,
                sizeof(par->ddc_adapter.name));
        par->ddc_adapter.owner          = THIS_MODULE;
        par->ddc_adapter.class          = I2C_CLASS_DDC;
index cf2a90e..e770b4a 100644 (file)
@@ -355,7 +355,7 @@ static int simplefb_regulators_get(struct simplefb_par *par,
                if (!p || p == prop->name)
                        continue;
 
-               strlcpy(name, prop->name,
+               strscpy(name, prop->name,
                        strlen(prop->name) - strlen(SUPPLY_SUFFIX) + 1);
                regulator = devm_regulator_get_optional(&pdev->dev, name);
                if (IS_ERR(regulator)) {
index f28fd69..c9e7742 100644 (file)
@@ -649,37 +649,37 @@ sisfb_validate_mode(struct sis_video_info *ivideo, int myindex, u32 vbflags)
        u16 xres=0, yres, myres;
 
 #ifdef CONFIG_FB_SIS_300
-       if(ivideo->sisvga_engine == SIS_300_VGA) {
-               if(!(sisbios_mode[myindex].chipset & MD_SIS300))
+       if (ivideo->sisvga_engine == SIS_300_VGA) {
+               if (!(sisbios_mode[myindex].chipset & MD_SIS300))
                        return -1 ;
        }
 #endif
 #ifdef CONFIG_FB_SIS_315
-       if(ivideo->sisvga_engine == SIS_315_VGA) {
-               if(!(sisbios_mode[myindex].chipset & MD_SIS315))
+       if (ivideo->sisvga_engine == SIS_315_VGA) {
+               if (!(sisbios_mode[myindex].chipset & MD_SIS315))
                        return -1;
        }
 #endif
 
        myres = sisbios_mode[myindex].yres;
 
-       switch(vbflags & VB_DISPTYPE_DISP2) {
+       switch (vbflags & VB_DISPTYPE_DISP2) {
 
        case CRT2_LCD:
                xres = ivideo->lcdxres; yres = ivideo->lcdyres;
 
-               if((ivideo->SiS_Pr.SiS_CustomT != CUT_PANEL848) &&
-                  (ivideo->SiS_Pr.SiS_CustomT != CUT_PANEL856)) {
-                       if(sisbios_mode[myindex].xres > xres)
+               if ((ivideo->SiS_Pr.SiS_CustomT != CUT_PANEL848) &&
+                   (ivideo->SiS_Pr.SiS_CustomT != CUT_PANEL856)) {
+                       if (sisbios_mode[myindex].xres > xres)
                                return -1;
-                       if(myres > yres)
+                       if (myres > yres)
                                return -1;
                }
 
-               if(ivideo->sisfb_fstn) {
-                       if(sisbios_mode[myindex].xres == 320) {
-                               if(myres == 240) {
-                                       switch(sisbios_mode[myindex].mode_no[1]) {
+               if (ivideo->sisfb_fstn) {
+                       if (sisbios_mode[myindex].xres == 320) {
+                               if (myres == 240) {
+                                       switch (sisbios_mode[myindex].mode_no[1]) {
                                                case 0x50: myindex = MODE_FSTN_8;  break;
                                                case 0x56: myindex = MODE_FSTN_16; break;
                                                case 0x53: return -1;
@@ -688,7 +688,7 @@ sisfb_validate_mode(struct sis_video_info *ivideo, int myindex, u32 vbflags)
                        }
                }
 
-               if(SiS_GetModeID_LCD(ivideo->sisvga_engine, vbflags, sisbios_mode[myindex].xres,
+               if (SiS_GetModeID_LCD(ivideo->sisvga_engine, vbflags, sisbios_mode[myindex].xres,
                                sisbios_mode[myindex].yres, 0, ivideo->sisfb_fstn,
                                ivideo->SiS_Pr.SiS_CustomT, xres, yres, ivideo->vbflags2) < 0x14) {
                        return -1;
@@ -696,14 +696,14 @@ sisfb_validate_mode(struct sis_video_info *ivideo, int myindex, u32 vbflags)
                break;
 
        case CRT2_TV:
-               if(SiS_GetModeID_TV(ivideo->sisvga_engine, vbflags, sisbios_mode[myindex].xres,
+               if (SiS_GetModeID_TV(ivideo->sisvga_engine, vbflags, sisbios_mode[myindex].xres,
                                sisbios_mode[myindex].yres, 0, ivideo->vbflags2) < 0x14) {
                        return -1;
                }
                break;
 
        case CRT2_VGA:
-               if(SiS_GetModeID_VGA2(ivideo->sisvga_engine, vbflags, sisbios_mode[myindex].xres,
+               if (SiS_GetModeID_VGA2(ivideo->sisvga_engine, vbflags, sisbios_mode[myindex].xres,
                                sisbios_mode[myindex].yres, 0, ivideo->vbflags2) < 0x14) {
                        return -1;
                }
@@ -1872,7 +1872,7 @@ sisfb_get_fix(struct fb_fix_screeninfo *fix, int con, struct fb_info *info)
 
        memset(fix, 0, sizeof(struct fb_fix_screeninfo));
 
-       strlcpy(fix->id, ivideo->myid, sizeof(fix->id));
+       strscpy(fix->id, ivideo->myid, sizeof(fix->id));
 
        mutex_lock(&info->mm_lock);
        fix->smem_start  = ivideo->video_base + ivideo->video_offset;
@@ -2204,82 +2204,88 @@ static bool sisfb_test_DDC1(struct sis_video_info *ivideo)
 
 static void sisfb_sense_crt1(struct sis_video_info *ivideo)
 {
-    bool mustwait = false;
-    u8  sr1F, cr17;
+       bool mustwait = false;
+       u8  sr1F, cr17;
 #ifdef CONFIG_FB_SIS_315
-    u8  cr63=0;
+       u8  cr63 = 0;
 #endif
-    u16 temp = 0xffff;
-    int i;
+       u16 temp = 0xffff;
+       int i;
+
+       sr1F = SiS_GetReg(SISSR, 0x1F);
+       SiS_SetRegOR(SISSR, 0x1F, 0x04);
+       SiS_SetRegAND(SISSR, 0x1F, 0x3F);
 
-    sr1F = SiS_GetReg(SISSR, 0x1F);
-    SiS_SetRegOR(SISSR, 0x1F, 0x04);
-    SiS_SetRegAND(SISSR, 0x1F, 0x3F);
-    if(sr1F & 0xc0) mustwait = true;
+       if (sr1F & 0xc0)
+               mustwait = true;
 
 #ifdef CONFIG_FB_SIS_315
-    if(ivideo->sisvga_engine == SIS_315_VGA) {
-       cr63 = SiS_GetReg(SISCR, ivideo->SiS_Pr.SiS_MyCR63);
-       cr63 &= 0x40;
-       SiS_SetRegAND(SISCR, ivideo->SiS_Pr.SiS_MyCR63, 0xBF);
-    }
+       if (ivideo->sisvga_engine == SIS_315_VGA) {
+               cr63 = SiS_GetReg(SISCR, ivideo->SiS_Pr.SiS_MyCR63);
+               cr63 &= 0x40;
+               SiS_SetRegAND(SISCR, ivideo->SiS_Pr.SiS_MyCR63, 0xBF);
+       }
 #endif
 
-    cr17 = SiS_GetReg(SISCR, 0x17);
-    cr17 &= 0x80;
-    if(!cr17) {
-       SiS_SetRegOR(SISCR, 0x17, 0x80);
-       mustwait = true;
-       SiS_SetReg(SISSR, 0x00, 0x01);
-       SiS_SetReg(SISSR, 0x00, 0x03);
-    }
+       cr17 = SiS_GetReg(SISCR, 0x17);
+       cr17 &= 0x80;
 
-    if(mustwait) {
-       for(i=0; i < 10; i++) sisfbwaitretracecrt1(ivideo);
-    }
+       if (!cr17) {
+               SiS_SetRegOR(SISCR, 0x17, 0x80);
+               mustwait = true;
+               SiS_SetReg(SISSR, 0x00, 0x01);
+               SiS_SetReg(SISSR, 0x00, 0x03);
+       }
 
+       if (mustwait) {
+               for (i = 0; i < 10; i++)
+                       sisfbwaitretracecrt1(ivideo);
+       }
 #ifdef CONFIG_FB_SIS_315
-    if(ivideo->chip >= SIS_330) {
-       SiS_SetRegAND(SISCR, 0x32, ~0x20);
-       if(ivideo->chip >= SIS_340) {
-          SiS_SetReg(SISCR, 0x57, 0x4a);
-       } else {
-          SiS_SetReg(SISCR, 0x57, 0x5f);
-       }
-       SiS_SetRegOR(SISCR, 0x53, 0x02);
-       while ((SiS_GetRegByte(SISINPSTAT)) & 0x01)    break;
-       while (!((SiS_GetRegByte(SISINPSTAT)) & 0x01)) break;
-       if ((SiS_GetRegByte(SISMISCW)) & 0x10) temp = 1;
-       SiS_SetRegAND(SISCR, 0x53, 0xfd);
-       SiS_SetRegAND(SISCR, 0x57, 0x00);
-    }
+       if (ivideo->chip >= SIS_330) {
+               SiS_SetRegAND(SISCR, 0x32, ~0x20);
+               if (ivideo->chip >= SIS_340)
+                       SiS_SetReg(SISCR, 0x57, 0x4a);
+               else
+                       SiS_SetReg(SISCR, 0x57, 0x5f);
+
+               SiS_SetRegOR(SISCR, 0x53, 0x02);
+               while ((SiS_GetRegByte(SISINPSTAT)) & 0x01)
+                       break;
+               while (!((SiS_GetRegByte(SISINPSTAT)) & 0x01))
+                       break;
+               if ((SiS_GetRegByte(SISMISCW)) & 0x10)
+                       temp = 1;
+
+               SiS_SetRegAND(SISCR, 0x53, 0xfd);
+               SiS_SetRegAND(SISCR, 0x57, 0x00);
+       }
 #endif
 
-    if(temp == 0xffff) {
-       i = 3;
-       do {
-         temp = SiS_HandleDDC(&ivideo->SiS_Pr, ivideo->vbflags,
-               ivideo->sisvga_engine, 0, 0, NULL, ivideo->vbflags2);
-       } while(((temp == 0) || (temp == 0xffff)) && i--);
+       if (temp == 0xffff) {
+               i = 3;
 
-       if((temp == 0) || (temp == 0xffff)) {
-          if(sisfb_test_DDC1(ivideo)) temp = 1;
-       }
-    }
+               do {
+                       temp = SiS_HandleDDC(&ivideo->SiS_Pr, ivideo->vbflags,
+                       ivideo->sisvga_engine, 0, 0, NULL, ivideo->vbflags2);
+               } while (((temp == 0) || (temp == 0xffff)) && i--);
 
-    if((temp) && (temp != 0xffff)) {
-       SiS_SetRegOR(SISCR, 0x32, 0x20);
-    }
+               if ((temp == 0) || (temp == 0xffff)) {
+                       if (sisfb_test_DDC1(ivideo))
+                               temp = 1;
+               }
+       }
+
+       if ((temp) && (temp != 0xffff))
+               SiS_SetRegOR(SISCR, 0x32, 0x20);
 
 #ifdef CONFIG_FB_SIS_315
-    if(ivideo->sisvga_engine == SIS_315_VGA) {
-       SiS_SetRegANDOR(SISCR, ivideo->SiS_Pr.SiS_MyCR63, 0xBF, cr63);
-    }
+       if (ivideo->sisvga_engine == SIS_315_VGA)
+               SiS_SetRegANDOR(SISCR, ivideo->SiS_Pr.SiS_MyCR63, 0xBF, cr63);
 #endif
 
-    SiS_SetRegANDOR(SISCR, 0x17, 0x7F, cr17);
-
-    SiS_SetReg(SISSR, 0x1F, sr1F);
+       SiS_SetRegANDOR(SISCR, 0x17, 0x7F, cr17);
+       SiS_SetReg(SISSR, 0x1F, sr1F);
 }
 
 /* Determine and detect attached devices on SiS30x */
@@ -2293,25 +2299,25 @@ static void SiS_SenseLCD(struct sis_video_info *ivideo)
        ivideo->SiS_Pr.PanelSelfDetected = false;
 
        /* LCD detection only for TMDS bridges */
-       if(!(ivideo->vbflags2 & VB2_SISTMDSBRIDGE))
+       if (!(ivideo->vbflags2 & VB2_SISTMDSBRIDGE))
                return;
-       if(ivideo->vbflags2 & VB2_30xBDH)
+       if (ivideo->vbflags2 & VB2_30xBDH)
                return;
 
        /* If LCD already set up by BIOS, skip it */
        reg = SiS_GetReg(SISCR, 0x32);
-       if(reg & 0x08)
+       if (reg & 0x08)
                return;
 
        realcrtno = 1;
-       if(ivideo->SiS_Pr.DDCPortMixup)
+       if (ivideo->SiS_Pr.DDCPortMixup)
                realcrtno = 0;
 
        /* Check DDC capabilities */
        temp = SiS_HandleDDC(&ivideo->SiS_Pr, ivideo->vbflags, ivideo->sisvga_engine,
                                realcrtno, 0, &buffer[0], ivideo->vbflags2);
 
-       if((!temp) || (temp == 0xffff) || (!(temp & 0x02)))
+       if ((!temp) || (temp == 0xffff) || (!(temp & 0x02)))
                return;
 
        /* Read DDC data */
@@ -2320,17 +2326,17 @@ static void SiS_SenseLCD(struct sis_video_info *ivideo)
                temp = SiS_HandleDDC(&ivideo->SiS_Pr, ivideo->vbflags,
                                ivideo->sisvga_engine, realcrtno, 1,
                                &buffer[0], ivideo->vbflags2);
-       } while((temp) && i--);
+       } while ((temp) && i--);
 
-       if(temp)
+       if (temp)
                return;
 
        /* No digital device */
-       if(!(buffer[0x14] & 0x80))
+       if (!(buffer[0x14] & 0x80))
                return;
 
        /* First detailed timing preferred timing? */
-       if(!(buffer[0x18] & 0x02))
+       if (!(buffer[0x18] & 0x02))
                return;
 
        xres = buffer[0x38] | ((buffer[0x3a] & 0xf0) << 4);
@@ -2338,26 +2344,26 @@ static void SiS_SenseLCD(struct sis_video_info *ivideo)
 
        switch(xres) {
                case 1024:
-                       if(yres == 768)
+                       if (yres == 768)
                                paneltype = 0x02;
                        break;
                case 1280:
-                       if(yres == 1024)
+                       if (yres == 1024)
                                paneltype = 0x03;
                        break;
                case 1600:
-                       if((yres == 1200) && (ivideo->vbflags2 & VB2_30xC))
+                       if ((yres == 1200) && (ivideo->vbflags2 & VB2_30xC))
                                paneltype = 0x0b;
                        break;
        }
 
-       if(!paneltype)
+       if (!paneltype)
                return;
 
-       if(buffer[0x23])
+       if (buffer[0x23])
                cr37 |= 0x10;
 
-       if((buffer[0x47] & 0x18) == 0x18)
+       if ((buffer[0x47] & 0x18) == 0x18)
                cr37 |= ((((buffer[0x47] & 0x06) ^ 0x06) << 5) | 0x20);
        else
                cr37 |= 0xc0;
@@ -2372,31 +2378,34 @@ static void SiS_SenseLCD(struct sis_video_info *ivideo)
 
 static int SISDoSense(struct sis_video_info *ivideo, u16 type, u16 test)
 {
-    int temp, mytest, result, i, j;
-
-    for(j = 0; j < 10; j++) {
-       result = 0;
-       for(i = 0; i < 3; i++) {
-          mytest = test;
-          SiS_SetReg(SISPART4, 0x11, (type & 0x00ff));
-          temp = (type >> 8) | (mytest & 0x00ff);
-         SiS_SetRegANDOR(SISPART4, 0x10, 0xe0, temp);
-          SiS_DDC2Delay(&ivideo->SiS_Pr, 0x1500);
-          mytest >>= 8;
-          mytest &= 0x7f;
-          temp = SiS_GetReg(SISPART4, 0x03);
-          temp ^= 0x0e;
-          temp &= mytest;
-          if(temp == mytest) result++;
+       int temp, mytest, result, i, j;
+
+       for (j = 0; j < 10; j++) {
+               result = 0;
+               for (i = 0; i < 3; i++) {
+                       mytest = test;
+                       SiS_SetReg(SISPART4, 0x11, (type & 0x00ff));
+                       temp = (type >> 8) | (mytest & 0x00ff);
+                       SiS_SetRegANDOR(SISPART4, 0x10, 0xe0, temp);
+                       SiS_DDC2Delay(&ivideo->SiS_Pr, 0x1500);
+                       mytest >>= 8;
+                       mytest &= 0x7f;
+                       temp = SiS_GetReg(SISPART4, 0x03);
+                       temp ^= 0x0e;
+                       temp &= mytest;
+                       if (temp == mytest)
+                               result++;
 #if 1
-         SiS_SetReg(SISPART4, 0x11, 0x00);
-         SiS_SetRegAND(SISPART4, 0x10, 0xe0);
-         SiS_DDC2Delay(&ivideo->SiS_Pr, 0x1000);
+                       SiS_SetReg(SISPART4, 0x11, 0x00);
+                       SiS_SetRegAND(SISPART4, 0x10, 0xe0);
+                       SiS_DDC2Delay(&ivideo->SiS_Pr, 0x1000);
 #endif
-       }
-       if((result == 0) || (result >= 2)) break;
-    }
-    return result;
+               }
+
+               if ((result == 0) || (result >= 2))
+                       break;
+       }
+       return result;
 }
 
 static void SiS_Sense30x(struct sis_video_info *ivideo)
@@ -4262,18 +4271,17 @@ static int sisfb_post_300_rwtest(struct sis_video_info *ivideo, int iteration,
        unsigned int k, RankCapacity, PageCapacity, BankNumHigh, BankNumMid;
        unsigned int PhysicalAdrOtherPage, PhysicalAdrHigh, PhysicalAdrHalfPage;
 
-        for(k = 0; k < ARRAY_SIZE(SiS_DRAMType); k++) {
-
+       for (k = 0; k < ARRAY_SIZE(SiS_DRAMType); k++) {
                RankCapacity = buswidth * SiS_DRAMType[k][3];
 
-               if(RankCapacity != PseudoRankCapacity)
+               if (RankCapacity != PseudoRankCapacity)
                        continue;
 
-               if((SiS_DRAMType[k][2] + SiS_DRAMType[k][0]) > PseudoAdrPinCount)
+               if ((SiS_DRAMType[k][2] + SiS_DRAMType[k][0]) > PseudoAdrPinCount)
                        continue;
 
                BankNumHigh = RankCapacity * 16 * iteration - 1;
-               if(iteration == 3) {             /* Rank No */
+               if (iteration == 3) {             /* Rank No */
                        BankNumMid  = RankCapacity * 16 - 1;
                } else {
                        BankNumMid  = RankCapacity * 16 * iteration / 2 - 1;
@@ -4287,18 +4295,22 @@ static int sisfb_post_300_rwtest(struct sis_video_info *ivideo, int iteration,
                SiS_SetRegAND(SISSR, 0x15, 0xFB); /* Test */
                SiS_SetRegOR(SISSR, 0x15, 0x04);  /* Test */
                sr14 = (SiS_DRAMType[k][3] * buswidth) - 1;
-               if(buswidth == 4)      sr14 |= 0x80;
-               else if(buswidth == 2) sr14 |= 0x40;
+
+               if (buswidth == 4)
+                       sr14 |= 0x80;
+               else if (buswidth == 2)
+                       sr14 |= 0x40;
+
                SiS_SetReg(SISSR, 0x13, SiS_DRAMType[k][4]);
                SiS_SetReg(SISSR, 0x14, sr14);
 
                BankNumHigh <<= 16;
                BankNumMid <<= 16;
 
-               if((BankNumHigh + PhysicalAdrHigh      >= mapsize) ||
-                  (BankNumMid  + PhysicalAdrHigh      >= mapsize) ||
-                  (BankNumHigh + PhysicalAdrHalfPage  >= mapsize) ||
-                  (BankNumHigh + PhysicalAdrOtherPage >= mapsize))
+               if ((BankNumHigh + PhysicalAdrHigh >= mapsize) ||
+                   (BankNumMid  + PhysicalAdrHigh >= mapsize) ||
+                   (BankNumHigh + PhysicalAdrHalfPage  >= mapsize) ||
+                   (BankNumHigh + PhysicalAdrOtherPage >= mapsize))
                        continue;
 
                /* Write data */
@@ -4312,7 +4324,7 @@ static int sisfb_post_300_rwtest(struct sis_video_info *ivideo, int iteration,
                                (FBAddr + BankNumHigh + PhysicalAdrOtherPage));
 
                /* Read data */
-               if(readw(FBAddr + BankNumHigh + PhysicalAdrHigh) == PhysicalAdrHigh)
+               if (readw(FBAddr + BankNumHigh + PhysicalAdrHigh) == PhysicalAdrHigh)
                        return 1;
        }
 
@@ -5867,7 +5879,7 @@ static int sisfb_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
                        ivideo->cardnumber++;
        }
 
-       strlcpy(ivideo->myid, chipinfo->chip_name, sizeof(ivideo->myid));
+       strscpy(ivideo->myid, chipinfo->chip_name, sizeof(ivideo->myid));
 
        ivideo->warncount = 0;
        ivideo->chip_id = pdev->device;
@@ -6150,24 +6162,20 @@ static int sisfb_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
 #endif
 
 #ifdef CONFIG_FB_SIS_315
-               if(ivideo->sisvga_engine == SIS_315_VGA) {
+               if (ivideo->sisvga_engine == SIS_315_VGA) {
                        int result = 1;
-               /*      if((ivideo->chip == SIS_315H)   ||
-                          (ivideo->chip == SIS_315)    ||
-                          (ivideo->chip == SIS_315PRO) ||
-                          (ivideo->chip == SIS_330)) {
-                               sisfb_post_sis315330(pdev);
-                       } else */ if(ivideo->chip == XGI_20) {
+
+                       if (ivideo->chip == XGI_20) {
                                result = sisfb_post_xgi(pdev);
                                ivideo->sisfb_can_post = 1;
-                       } else if((ivideo->chip == XGI_40) && ivideo->haveXGIROM) {
+                       } else if ((ivideo->chip == XGI_40) && ivideo->haveXGIROM) {
                                result = sisfb_post_xgi(pdev);
                                ivideo->sisfb_can_post = 1;
                        } else {
                                printk(KERN_INFO "sisfb: Card is not "
                                        "POSTed and sisfb can't do this either.\n");
                        }
-                       if(!result) {
+                       if (!result) {
                                printk(KERN_ERR "sisfb: Failed to POST card\n");
                                ret = -ENODEV;
                                goto error_3;
index 6a52eba..fce6cfb 100644 (file)
@@ -1719,7 +1719,7 @@ static int sm501fb_init_fb(struct fb_info *fb, enum sm501_controller head,
                enable = 0;
        }
 
-       strlcpy(fb->fix.id, fbname, sizeof(fb->fix.id));
+       strscpy(fb->fix.id, fbname, sizeof(fb->fix.id));
 
        memcpy(&par->ops,
               (head == HEAD_CRT) ? &sm501fb_ops_crt : &sm501fb_ops_pnl,
index 5c76565..52e4ed9 100644 (file)
@@ -450,7 +450,7 @@ static int ssd1307fb_init(struct ssd1307fb_par *par)
        if (ret < 0)
                return ret;
 
-       /* Set Set Area Color Mode ON/OFF & Low Power Display Mode */
+       /* Set Area Color Mode ON/OFF & Low Power Display Mode */
        if (par->area_color_enable || par->low_power) {
                u32 mode;
 
index 27d4b0a..cd4d640 100644 (file)
@@ -1382,7 +1382,7 @@ static int sstfb_probe(struct pci_dev *pdev, const struct pci_device_id *id)
                goto fail;
        }
        sst_get_memsize(info, &fix->smem_len);
-       strlcpy(fix->id, spec->name, sizeof(fix->id));
+       strscpy(fix->id, spec->name, sizeof(fix->id));
 
        printk(KERN_INFO "%s (revision %d) with %s dac\n",
                fix->id, par->revision, par->dac_sw.name);
index 15b0795..490bd9a 100644 (file)
@@ -80,7 +80,7 @@ static int gfb_set_fbinfo(struct gfb_info *gp)
        info->pseudo_palette = gp->pseudo_palette;
 
        /* Fill fix common fields */
-       strlcpy(info->fix.id, "gfb", sizeof(info->fix.id));
+       strscpy(info->fix.id, "gfb", sizeof(info->fix.id));
         info->fix.smem_start = gp->fb_base_phys;
         info->fix.smem_len = gp->fb_size;
         info->fix.type = FB_TYPE_PACKED_PIXELS;
index 1d3bacd..1279b02 100644 (file)
@@ -84,7 +84,7 @@ static int s3d_set_fbinfo(struct s3d_info *sp)
        info->pseudo_palette = sp->pseudo_palette;
 
        /* Fill fix common fields */
-       strlcpy(info->fix.id, "s3d", sizeof(info->fix.id));
+       strscpy(info->fix.id, "s3d", sizeof(info->fix.id));
         info->fix.smem_start = sp->fb_base_phys;
         info->fix.smem_len = sp->fb_size;
         info->fix.type = FB_TYPE_PACKED_PIXELS;
index 9daf17b..f7b4636 100644 (file)
@@ -207,7 +207,7 @@ static int e3d_set_fbinfo(struct e3d_info *ep)
        info->pseudo_palette = ep->pseudo_palette;
 
        /* Fill fix common fields */
-       strlcpy(info->fix.id, "e3d", sizeof(info->fix.id));
+       strscpy(info->fix.id, "e3d", sizeof(info->fix.id));
         info->fix.smem_start = ep->fb_base_phys;
         info->fix.smem_len = ep->fb_size;
         info->fix.type = FB_TYPE_PACKED_PIXELS;
index 1638a40..01d87f5 100644 (file)
@@ -333,7 +333,7 @@ tcx_init_fix(struct fb_info *info, int linebytes)
        else
                tcx_name = "TCX24";
 
-       strlcpy(info->fix.id, tcx_name, sizeof(info->fix.id));
+       strscpy(info->fix.id, tcx_name, sizeof(info->fix.id));
 
        info->fix.type = FB_TYPE_PACKED_PIXELS;
        info->fix.visual = FB_VISUAL_PSEUDOCOLOR;
index 67e37a6..8a8122f 100644 (file)
@@ -1264,7 +1264,7 @@ static int tdfxfb_setup_ddc_bus(struct tdfxfb_i2c_chan *chan, const char *name,
 {
        int rc;
 
-       strlcpy(chan->adapter.name, name, sizeof(chan->adapter.name));
+       strscpy(chan->adapter.name, name, sizeof(chan->adapter.name));
        chan->adapter.owner             = THIS_MODULE;
        chan->adapter.class             = I2C_CLASS_DDC;
        chan->adapter.algo_data         = &chan->algo;
@@ -1293,7 +1293,7 @@ static int tdfxfb_setup_i2c_bus(struct tdfxfb_i2c_chan *chan, const char *name,
 {
        int rc;
 
-       strlcpy(chan->adapter.name, name, sizeof(chan->adapter.name));
+       strscpy(chan->adapter.name, name, sizeof(chan->adapter.name));
        chan->adapter.owner             = THIS_MODULE;
        chan->adapter.algo_data         = &chan->algo;
        chan->adapter.dev.parent        = dev;
index ae0cf55..1fff5fd 100644 (file)
@@ -1344,7 +1344,7 @@ tgafb_init_fix(struct fb_info *info)
                memory_size = 16777216;
        }
 
-       strlcpy(info->fix.id, tga_type_name, sizeof(info->fix.id));
+       strscpy(info->fix.id, tga_type_name, sizeof(info->fix.id));
 
        info->fix.type = FB_TYPE_PACKED_PIXELS;
        info->fix.type_aux = 0;
index 319131b..cda0954 100644 (file)
@@ -270,7 +270,7 @@ static int tridentfb_setup_ddc_bus(struct fb_info *info)
 {
        struct tridentfb_par *par = info->par;
 
-       strlcpy(par->ddc_adapter.name, info->fix.id,
+       strscpy(par->ddc_adapter.name, info->fix.id,
                sizeof(par->ddc_adapter.name));
        par->ddc_adapter.owner          = THIS_MODULE;
        par->ddc_adapter.class          = I2C_CLASS_DDC;
index 3369734..e88e8f6 100644 (file)
@@ -581,27 +581,30 @@ static int lock_pages(
        struct privcmd_dm_op_buf kbufs[], unsigned int num,
        struct page *pages[], unsigned int nr_pages, unsigned int *pinned)
 {
-       unsigned int i;
+       unsigned int i, off = 0;
 
-       for (i = 0; i < num; i++) {
+       for (i = 0; i < num; ) {
                unsigned int requested;
                int page_count;
 
                requested = DIV_ROUND_UP(
                        offset_in_page(kbufs[i].uptr) + kbufs[i].size,
-                       PAGE_SIZE);
+                       PAGE_SIZE) - off;
                if (requested > nr_pages)
                        return -ENOSPC;
 
                page_count = pin_user_pages_fast(
-                       (unsigned long) kbufs[i].uptr,
+                       (unsigned long)kbufs[i].uptr + off * PAGE_SIZE,
                        requested, FOLL_WRITE, pages);
-               if (page_count < 0)
-                       return page_count;
+               if (page_count <= 0)
+                       return page_count ? : -EFAULT;
 
                *pinned += page_count;
                nr_pages -= page_count;
                pages += page_count;
+
+               off = (requested == page_count) ? 0 : off + page_count;
+               i += !off;
        }
 
        return 0;
@@ -677,10 +680,8 @@ static long privcmd_ioctl_dm_op(struct file *file, void __user *udata)
        }
 
        rc = lock_pages(kbufs, kdata.num, pages, nr_pages, &pinned);
-       if (rc < 0) {
-               nr_pages = pinned;
+       if (rc < 0)
                goto out;
-       }
 
        for (i = 0; i < kdata.num; i++) {
                set_xen_guest_handle(xbufs[i].h, kbufs[i].uptr);
@@ -692,7 +693,7 @@ static long privcmd_ioctl_dm_op(struct file *file, void __user *udata)
        xen_preemptible_hcall_end();
 
 out:
-       unlock_pages(pages, nr_pages);
+       unlock_pages(pages, pinned);
        kfree(xbufs);
        kfree(pages);
        kfree(kbufs);
index 7a0c93a..d3dcda3 100644 (file)
@@ -1121,7 +1121,7 @@ static void scsiback_do_1lun_hotplug(struct vscsibk_info *info, int op,
                                "%s: writing %s", __func__, state);
                return;
        }
-       strlcpy(phy, val, VSCSI_NAMELEN);
+       strscpy(phy, val, VSCSI_NAMELEN);
        kfree(val);
 
        /* virtual SCSI device */
index 07b010a..f44d5a6 100644 (file)
@@ -40,7 +40,7 @@ static int frontend_bus_id(char bus_id[XEN_BUS_ID_SIZE], const char *nodename)
                return -EINVAL;
        }
 
-       strlcpy(bus_id, nodename + 1, XEN_BUS_ID_SIZE);
+       strscpy(bus_id, nodename + 1, XEN_BUS_ID_SIZE);
        if (!strchr(bus_id, '/')) {
                pr_warn("bus_id %s no slash\n", bus_id);
                return -EINVAL;
index 993aca2..e0375ba 100644 (file)
@@ -440,39 +440,26 @@ void btrfs_wait_block_group_cache_progress(struct btrfs_block_group *cache,
        btrfs_put_caching_control(caching_ctl);
 }
 
-int btrfs_wait_block_group_cache_done(struct btrfs_block_group *cache)
+static int btrfs_caching_ctl_wait_done(struct btrfs_block_group *cache,
+                                      struct btrfs_caching_control *caching_ctl)
+{
+       wait_event(caching_ctl->wait, btrfs_block_group_done(cache));
+       return cache->cached == BTRFS_CACHE_ERROR ? -EIO : 0;
+}
+
+static int btrfs_wait_block_group_cache_done(struct btrfs_block_group *cache)
 {
        struct btrfs_caching_control *caching_ctl;
-       int ret = 0;
+       int ret;
 
        caching_ctl = btrfs_get_caching_control(cache);
        if (!caching_ctl)
                return (cache->cached == BTRFS_CACHE_ERROR) ? -EIO : 0;
-
-       wait_event(caching_ctl->wait, btrfs_block_group_done(cache));
-       if (cache->cached == BTRFS_CACHE_ERROR)
-               ret = -EIO;
+       ret = btrfs_caching_ctl_wait_done(cache, caching_ctl);
        btrfs_put_caching_control(caching_ctl);
        return ret;
 }
 
-static bool space_cache_v1_done(struct btrfs_block_group *cache)
-{
-       bool ret;
-
-       spin_lock(&cache->lock);
-       ret = cache->cached != BTRFS_CACHE_FAST;
-       spin_unlock(&cache->lock);
-
-       return ret;
-}
-
-void btrfs_wait_space_cache_v1_finished(struct btrfs_block_group *cache,
-                               struct btrfs_caching_control *caching_ctl)
-{
-       wait_event(caching_ctl->wait, space_cache_v1_done(cache));
-}
-
 #ifdef CONFIG_BTRFS_DEBUG
 static void fragment_free_space(struct btrfs_block_group *block_group)
 {
@@ -750,9 +737,8 @@ done:
        btrfs_put_block_group(block_group);
 }
 
-int btrfs_cache_block_group(struct btrfs_block_group *cache, int load_cache_only)
+int btrfs_cache_block_group(struct btrfs_block_group *cache, bool wait)
 {
-       DEFINE_WAIT(wait);
        struct btrfs_fs_info *fs_info = cache->fs_info;
        struct btrfs_caching_control *caching_ctl = NULL;
        int ret = 0;
@@ -785,10 +771,7 @@ int btrfs_cache_block_group(struct btrfs_block_group *cache, int load_cache_only
        }
        WARN_ON(cache->caching_ctl);
        cache->caching_ctl = caching_ctl;
-       if (btrfs_test_opt(fs_info, SPACE_CACHE))
-               cache->cached = BTRFS_CACHE_FAST;
-       else
-               cache->cached = BTRFS_CACHE_STARTED;
+       cache->cached = BTRFS_CACHE_STARTED;
        cache->has_caching_ctl = 1;
        spin_unlock(&cache->lock);
 
@@ -801,8 +784,8 @@ int btrfs_cache_block_group(struct btrfs_block_group *cache, int load_cache_only
 
        btrfs_queue_work(fs_info->caching_workers, &caching_ctl->work);
 out:
-       if (load_cache_only && caching_ctl)
-               btrfs_wait_space_cache_v1_finished(cache, caching_ctl);
+       if (wait && caching_ctl)
+               ret = btrfs_caching_ctl_wait_done(cache, caching_ctl);
        if (caching_ctl)
                btrfs_put_caching_control(caching_ctl);
 
@@ -3312,7 +3295,7 @@ int btrfs_update_block_group(struct btrfs_trans_handle *trans,
                 * space back to the block group, otherwise we will leak space.
                 */
                if (!alloc && !btrfs_block_group_done(cache))
-                       btrfs_cache_block_group(cache, 1);
+                       btrfs_cache_block_group(cache, true);
 
                byte_in_group = bytenr - cache->start;
                WARN_ON(byte_in_group > cache->length);
index 35e0e86..6b3cdc4 100644 (file)
@@ -263,9 +263,7 @@ void btrfs_dec_nocow_writers(struct btrfs_block_group *bg);
 void btrfs_wait_nocow_writers(struct btrfs_block_group *bg);
 void btrfs_wait_block_group_cache_progress(struct btrfs_block_group *cache,
                                           u64 num_bytes);
-int btrfs_wait_block_group_cache_done(struct btrfs_block_group *cache);
-int btrfs_cache_block_group(struct btrfs_block_group *cache,
-                           int load_cache_only);
+int btrfs_cache_block_group(struct btrfs_block_group *cache, bool wait);
 void btrfs_put_caching_control(struct btrfs_caching_control *ctl);
 struct btrfs_caching_control *btrfs_get_caching_control(
                struct btrfs_block_group *cache);
index 4edb4bf..9ef162d 100644 (file)
@@ -505,7 +505,6 @@ struct btrfs_free_cluster {
 enum btrfs_caching_type {
        BTRFS_CACHE_NO,
        BTRFS_CACHE_STARTED,
-       BTRFS_CACHE_FAST,
        BTRFS_CACHE_FINISHED,
        BTRFS_CACHE_ERROR,
 };
index f43196a..41cddd3 100644 (file)
@@ -165,7 +165,7 @@ no_valid_dev_replace_entry_found:
                 */
                if (btrfs_find_device(fs_info->fs_devices, &args)) {
                        btrfs_err(fs_info,
-                       "replace devid present without an active replace item");
+"replace without active item, run 'device scan --forget' on the target device");
                        ret = -EUCLEAN;
                } else {
                        dev_replace->srcdev = NULL;
@@ -1129,8 +1129,7 @@ int btrfs_dev_replace_cancel(struct btrfs_fs_info *fs_info)
                up_write(&dev_replace->rwsem);
 
                /* Scrub for replace must not be running in suspended state */
-               ret = btrfs_scrub_cancel(fs_info);
-               ASSERT(ret != -ENOTCONN);
+               btrfs_scrub_cancel(fs_info);
 
                trans = btrfs_start_transaction(root, 0);
                if (IS_ERR(trans)) {
index ab944d1..6914cd8 100644 (file)
@@ -2551,17 +2551,10 @@ int btrfs_pin_extent_for_log_replay(struct btrfs_trans_handle *trans,
                return -EINVAL;
 
        /*
-        * pull in the free space cache (if any) so that our pin
-        * removes the free space from the cache.  We have load_only set
-        * to one because the slow code to read in the free extents does check
-        * the pinned extents.
+        * Fully cache the free space first so that our pin removes the free space
+        * from the cache.
         */
-       btrfs_cache_block_group(cache, 1);
-       /*
-        * Make sure we wait until the cache is completely built in case it is
-        * missing or is invalid and therefore needs to be rebuilt.
-        */
-       ret = btrfs_wait_block_group_cache_done(cache);
+       ret = btrfs_cache_block_group(cache, true);
        if (ret)
                goto out;
 
@@ -2584,12 +2577,7 @@ static int __exclude_logged_extent(struct btrfs_fs_info *fs_info,
        if (!block_group)
                return -EINVAL;
 
-       btrfs_cache_block_group(block_group, 1);
-       /*
-        * Make sure we wait until the cache is completely built in case it is
-        * missing or is invalid and therefore needs to be rebuilt.
-        */
-       ret = btrfs_wait_block_group_cache_done(block_group);
+       ret = btrfs_cache_block_group(block_group, true);
        if (ret)
                goto out;
 
@@ -4399,7 +4387,7 @@ have_block_group:
                ffe_ctl->cached = btrfs_block_group_done(block_group);
                if (unlikely(!ffe_ctl->cached)) {
                        ffe_ctl->have_caching_bg = true;
-                       ret = btrfs_cache_block_group(block_group, 0);
+                       ret = btrfs_cache_block_group(block_group, false);
 
                        /*
                         * If we get ENOMEM here or something else we want to
@@ -6169,13 +6157,7 @@ int btrfs_trim_fs(struct btrfs_fs_info *fs_info, struct fstrim_range *range)
 
                if (end - start >= range->minlen) {
                        if (!btrfs_block_group_done(cache)) {
-                               ret = btrfs_cache_block_group(cache, 0);
-                               if (ret) {
-                                       bg_failed++;
-                                       bg_ret = ret;
-                                       continue;
-                               }
-                               ret = btrfs_wait_block_group_cache_done(cache);
+                               ret = btrfs_cache_block_group(cache, true);
                                if (ret) {
                                        bg_failed++;
                                        bg_ret = ret;
index eed81a7..cf4f19e 100644 (file)
@@ -3233,7 +3233,7 @@ static int btrfs_bio_add_page(struct btrfs_bio_ctrl *bio_ctrl,
        u32 bio_size = bio->bi_iter.bi_size;
        u32 real_size;
        const sector_t sector = disk_bytenr >> SECTOR_SHIFT;
-       bool contig;
+       bool contig = false;
        int ret;
 
        ASSERT(bio);
@@ -3242,10 +3242,35 @@ static int btrfs_bio_add_page(struct btrfs_bio_ctrl *bio_ctrl,
        if (bio_ctrl->compress_type != compress_type)
                return 0;
 
-       if (bio_ctrl->compress_type != BTRFS_COMPRESS_NONE)
+
+       if (bio->bi_iter.bi_size == 0) {
+               /* We can always add a page into an empty bio. */
+               contig = true;
+       } else if (bio_ctrl->compress_type == BTRFS_COMPRESS_NONE) {
+               struct bio_vec *bvec = bio_last_bvec_all(bio);
+
+               /*
+                * The contig check requires the following conditions to be met:
+                * 1) The pages are belonging to the same inode
+                *    This is implied by the call chain.
+                *
+                * 2) The range has adjacent logical bytenr
+                *
+                * 3) The range has adjacent file offset
+                *    This is required for the usage of btrfs_bio->file_offset.
+                */
+               if (bio_end_sector(bio) == sector &&
+                   page_offset(bvec->bv_page) + bvec->bv_offset +
+                   bvec->bv_len == page_offset(page) + pg_offset)
+                       contig = true;
+       } else {
+               /*
+                * For compression, all IO should have its logical bytenr
+                * set to the starting bytenr of the compressed extent.
+                */
                contig = bio->bi_iter.bi_sector == sector;
-       else
-               contig = bio_end_sector(bio) == sector;
+       }
+
        if (!contig)
                return 0;
 
index 66c8221..5a3f6e0 100644 (file)
@@ -2482,6 +2482,7 @@ static int fill_holes(struct btrfs_trans_handle *trans,
                btrfs_set_file_extent_num_bytes(leaf, fi, num_bytes);
                btrfs_set_file_extent_ram_bytes(leaf, fi, num_bytes);
                btrfs_set_file_extent_offset(leaf, fi, 0);
+               btrfs_set_file_extent_generation(leaf, fi, trans->transid);
                btrfs_mark_buffer_dirty(leaf);
                goto out;
        }
@@ -2498,6 +2499,7 @@ static int fill_holes(struct btrfs_trans_handle *trans,
                btrfs_set_file_extent_num_bytes(leaf, fi, num_bytes);
                btrfs_set_file_extent_ram_bytes(leaf, fi, num_bytes);
                btrfs_set_file_extent_offset(leaf, fi, 0);
+               btrfs_set_file_extent_generation(leaf, fi, trans->transid);
                btrfs_mark_buffer_dirty(leaf);
                goto out;
        }
index f0c97d2..ad25089 100644 (file)
@@ -7694,6 +7694,20 @@ static int btrfs_dio_iomap_begin(struct inode *inode, loff_t start,
        bool unlock_extents = false;
 
        /*
+        * We could potentially fault if we have a buffer > PAGE_SIZE, and if
+        * we're NOWAIT we may submit a bio for a partial range and return
+        * EIOCBQUEUED, which would result in an errant short read.
+        *
+        * The best way to handle this would be to allow for partial completions
+        * of iocb's, so we could submit the partial bio, return and fault in
+        * the rest of the pages, and then submit the io for the rest of the
+        * range.  However we don't have that currently, so simply return
+        * -EAGAIN at this point so that the normal path is used.
+        */
+       if (!write && (flags & IOMAP_NOWAIT) && length > PAGE_SIZE)
+               return -EAGAIN;
+
+       /*
         * Cap the size of reads to that usually seen in buffered I/O as we need
         * to allocate a contiguous array for the checksums.
         */
index a64b26b..d647cb2 100644 (file)
@@ -349,9 +349,10 @@ int btrfs_del_root_ref(struct btrfs_trans_handle *trans, u64 root_id,
        key.offset = ref_id;
 again:
        ret = btrfs_search_slot(trans, tree_root, &key, path, -1, 1);
-       if (ret < 0)
+       if (ret < 0) {
+               err = ret;
                goto out;
-       if (ret == 0) {
+       } else if (ret == 0) {
                leaf = path->nodes[0];
                ref = btrfs_item_ptr(leaf, path->slots[0],
                                     struct btrfs_root_ref);
index 2729015..064ab2a 100644 (file)
@@ -2345,8 +2345,11 @@ int btrfs_get_dev_args_from_path(struct btrfs_fs_info *fs_info,
 
        ret = btrfs_get_bdev_and_sb(path, FMODE_READ, fs_info->bdev_holder, 0,
                                    &bdev, &disk_super);
-       if (ret)
+       if (ret) {
+               btrfs_put_dev_args_from_path(args);
                return ret;
+       }
+
        args->devid = btrfs_stack_device_id(&disk_super->dev_item);
        memcpy(args->uuid, disk_super->dev_item.uuid, BTRFS_UUID_SIZE);
        if (btrfs_fs_incompat(fs_info, METADATA_UUID))
index 7421abc..5bb8d8c 100644 (file)
@@ -371,6 +371,9 @@ static int btrfs_xattr_handler_set(const struct xattr_handler *handler,
                                   const char *name, const void *buffer,
                                   size_t size, int flags)
 {
+       if (btrfs_root_readonly(BTRFS_I(inode)->root))
+               return -EROFS;
+
        name = xattr_full_name(handler, name);
        return btrfs_setxattr_trans(inode, name, buffer, size, flags);
 }
index 6cba2c6..2ad58c4 100644 (file)
@@ -111,6 +111,7 @@ struct cachefiles_cache {
        char                            *tag;           /* cache binding tag */
        refcount_t                      unbind_pincount;/* refcount to do daemon unbind */
        struct xarray                   reqs;           /* xarray of pending on-demand requests */
+       unsigned long                   req_id_next;
        struct xarray                   ondemand_ids;   /* xarray for ondemand_id allocation */
        u32                             ondemand_id_next;
 };
index 1fee702..0254ed3 100644 (file)
@@ -158,9 +158,13 @@ int cachefiles_ondemand_copen(struct cachefiles_cache *cache, char *args)
 
        /* fail OPEN request if daemon reports an error */
        if (size < 0) {
-               if (!IS_ERR_VALUE(size))
-                       size = -EINVAL;
-               req->error = size;
+               if (!IS_ERR_VALUE(size)) {
+                       req->error = -EINVAL;
+                       ret = -EINVAL;
+               } else {
+                       req->error = size;
+                       ret = 0;
+               }
                goto out;
        }
 
@@ -238,14 +242,19 @@ ssize_t cachefiles_ondemand_daemon_read(struct cachefiles_cache *cache,
        unsigned long id = 0;
        size_t n;
        int ret = 0;
-       XA_STATE(xas, &cache->reqs, 0);
+       XA_STATE(xas, &cache->reqs, cache->req_id_next);
 
        /*
-        * Search for a request that has not ever been processed, to prevent
-        * requests from being processed repeatedly.
+        * Cyclically search for a request that has not ever been processed,
+        * to prevent requests from being processed repeatedly, and make
+        * request distribution fair.
         */
        xa_lock(&cache->reqs);
        req = xas_find_marked(&xas, UINT_MAX, CACHEFILES_REQ_NEW);
+       if (!req && cache->req_id_next > 0) {
+               xas_set(&xas, 0);
+               req = xas_find_marked(&xas, cache->req_id_next - 1, CACHEFILES_REQ_NEW);
+       }
        if (!req) {
                xa_unlock(&cache->reqs);
                return 0;
@@ -260,6 +269,7 @@ ssize_t cachefiles_ondemand_daemon_read(struct cachefiles_cache *cache,
        }
 
        xas_clear_mark(&xas, CACHEFILES_REQ_NEW);
+       cache->req_id_next = xas.xa_index + 1;
        xa_unlock(&cache->reqs);
 
        id = xas.xa_index;
index 8f7835c..46f5718 100644 (file)
@@ -32,10 +32,9 @@ int __cifs_calc_signature(struct smb_rqst *rqst,
        int rc;
        struct kvec *iov = rqst->rq_iov;
        int n_vec = rqst->rq_nvec;
-       int is_smb2 = server->vals->header_preamble_size == 0;
 
        /* iov[0] is actual data and not the rfc1002 length for SMB2+ */
-       if (is_smb2) {
+       if (!is_smb1(server)) {
                if (iov[0].iov_len <= 4)
                        return -EIO;
                i = 0;
index f15d7b0..ae7f571 100644 (file)
@@ -557,6 +557,8 @@ struct smb_version_values {
 
 #define HEADER_SIZE(server) (server->vals->header_size)
 #define MAX_HEADER_SIZE(server) (server->vals->max_header_size)
+#define HEADER_PREAMBLE_SIZE(server) (server->vals->header_preamble_size)
+#define MID_HEADER_SIZE(server) (HEADER_SIZE(server) - 1 - HEADER_PREAMBLE_SIZE(server))
 
 /**
  * CIFS superblock mount flags (mnt_cifs_flags) to consider when
@@ -750,6 +752,11 @@ struct TCP_Server_Info {
 #endif
 };
 
+static inline bool is_smb1(struct TCP_Server_Info *server)
+{
+       return HEADER_PREAMBLE_SIZE(server) != 0;
+}
+
 static inline void cifs_server_lock(struct TCP_Server_Info *server)
 {
        unsigned int nofs_flag = memalloc_nofs_save();
index 3da5da9..a0a06b6 100644 (file)
@@ -871,7 +871,7 @@ smb2_get_credits_from_hdr(char *buffer, struct TCP_Server_Info *server)
        /*
         * SMB1 does not use credits.
         */
-       if (server->vals->header_preamble_size)
+       if (is_smb1(server))
                return 0;
 
        return le16_to_cpu(shdr->CreditRequest);
@@ -1050,7 +1050,7 @@ standard_receive3(struct TCP_Server_Info *server, struct mid_q_entry *mid)
 
        /* make sure this will fit in a large buffer */
        if (pdu_length > CIFSMaxBufSize + MAX_HEADER_SIZE(server) -
-               server->vals->header_preamble_size) {
+           HEADER_PREAMBLE_SIZE(server)) {
                cifs_server_dbg(VFS, "SMB response too long (%u bytes)\n", pdu_length);
                cifs_reconnect(server, true);
                return -ECONNABORTED;
@@ -1065,8 +1065,7 @@ standard_receive3(struct TCP_Server_Info *server, struct mid_q_entry *mid)
 
        /* now read the rest */
        length = cifs_read_from_socket(server, buf + HEADER_SIZE(server) - 1,
-                                      pdu_length - HEADER_SIZE(server) + 1
-                                      + server->vals->header_preamble_size);
+                                      pdu_length - MID_HEADER_SIZE(server));
 
        if (length < 0)
                return length;
@@ -1122,7 +1121,7 @@ smb2_add_credits_from_hdr(char *buffer, struct TCP_Server_Info *server)
        /*
         * SMB1 does not use credits.
         */
-       if (server->vals->header_preamble_size)
+       if (is_smb1(server))
                return;
 
        if (shdr->CreditRequest) {
@@ -1180,10 +1179,10 @@ cifs_demultiplex_thread(void *p)
                if (length < 0)
                        continue;
 
-               if (server->vals->header_preamble_size == 0)
-                       server->total_read = 0;
-               else
+               if (is_smb1(server))
                        server->total_read = length;
+               else
+                       server->total_read = 0;
 
                /*
                 * The right amount was read from socket - 4 bytes,
@@ -1198,8 +1197,7 @@ next_pdu:
                server->pdu_size = pdu_length;
 
                /* make sure we have enough to get to the MID */
-               if (server->pdu_size < HEADER_SIZE(server) - 1 -
-                   server->vals->header_preamble_size) {
+               if (server->pdu_size < MID_HEADER_SIZE(server)) {
                        cifs_server_dbg(VFS, "SMB response too short (%u bytes)\n",
                                 server->pdu_size);
                        cifs_reconnect(server, true);
@@ -1208,9 +1206,8 @@ next_pdu:
 
                /* read down to the MID */
                length = cifs_read_from_socket(server,
-                            buf + server->vals->header_preamble_size,
-                            HEADER_SIZE(server) - 1
-                            - server->vals->header_preamble_size);
+                            buf + HEADER_PREAMBLE_SIZE(server),
+                            MID_HEADER_SIZE(server));
                if (length < 0)
                        continue;
                server->total_read += length;
index 96f3b05..4810bd6 100644 (file)
@@ -3307,26 +3307,43 @@ get_smb2_acl(struct cifs_sb_info *cifs_sb,
        return pntsd;
 }
 
+static long smb3_zero_data(struct file *file, struct cifs_tcon *tcon,
+                            loff_t offset, loff_t len, unsigned int xid)
+{
+       struct cifsFileInfo *cfile = file->private_data;
+       struct file_zero_data_information fsctl_buf;
+
+       cifs_dbg(FYI, "Offset %lld len %lld\n", offset, len);
+
+       fsctl_buf.FileOffset = cpu_to_le64(offset);
+       fsctl_buf.BeyondFinalZero = cpu_to_le64(offset + len);
+
+       return SMB2_ioctl(xid, tcon, cfile->fid.persistent_fid,
+                         cfile->fid.volatile_fid, FSCTL_SET_ZERO_DATA,
+                         (char *)&fsctl_buf,
+                         sizeof(struct file_zero_data_information),
+                         0, NULL, NULL);
+}
+
 static long smb3_zero_range(struct file *file, struct cifs_tcon *tcon,
                            loff_t offset, loff_t len, bool keep_size)
 {
        struct cifs_ses *ses = tcon->ses;
-       struct inode *inode;
-       struct cifsInodeInfo *cifsi;
+       struct inode *inode = file_inode(file);
+       struct cifsInodeInfo *cifsi = CIFS_I(inode);
        struct cifsFileInfo *cfile = file->private_data;
-       struct file_zero_data_information fsctl_buf;
        long rc;
        unsigned int xid;
        __le64 eof;
 
        xid = get_xid();
 
-       inode = d_inode(cfile->dentry);
-       cifsi = CIFS_I(inode);
-
        trace_smb3_zero_enter(xid, cfile->fid.persistent_fid, tcon->tid,
                              ses->Suid, offset, len);
 
+       inode_lock(inode);
+       filemap_invalidate_lock(inode->i_mapping);
+
        /*
         * We zero the range through ioctl, so we need remove the page caches
         * first, otherwise the data may be inconsistent with the server.
@@ -3334,26 +3351,12 @@ static long smb3_zero_range(struct file *file, struct cifs_tcon *tcon,
        truncate_pagecache_range(inode, offset, offset + len - 1);
 
        /* if file not oplocked can't be sure whether asking to extend size */
-       if (!CIFS_CACHE_READ(cifsi))
-               if (keep_size == false) {
-                       rc = -EOPNOTSUPP;
-                       trace_smb3_zero_err(xid, cfile->fid.persistent_fid,
-                               tcon->tid, ses->Suid, offset, len, rc);
-                       free_xid(xid);
-                       return rc;
-               }
-
-       cifs_dbg(FYI, "Offset %lld len %lld\n", offset, len);
-
-       fsctl_buf.FileOffset = cpu_to_le64(offset);
-       fsctl_buf.BeyondFinalZero = cpu_to_le64(offset + len);
+       rc = -EOPNOTSUPP;
+       if (keep_size == false && !CIFS_CACHE_READ(cifsi))
+               goto zero_range_exit;
 
-       rc = SMB2_ioctl(xid, tcon, cfile->fid.persistent_fid,
-                       cfile->fid.volatile_fid, FSCTL_SET_ZERO_DATA,
-                       (char *)&fsctl_buf,
-                       sizeof(struct file_zero_data_information),
-                       0, NULL, NULL);
-       if (rc)
+       rc = smb3_zero_data(file, tcon, offset, len, xid);
+       if (rc < 0)
                goto zero_range_exit;
 
        /*
@@ -3366,6 +3369,8 @@ static long smb3_zero_range(struct file *file, struct cifs_tcon *tcon,
        }
 
  zero_range_exit:
+       filemap_invalidate_unlock(inode->i_mapping);
+       inode_unlock(inode);
        free_xid(xid);
        if (rc)
                trace_smb3_zero_err(xid, cfile->fid.persistent_fid, tcon->tid,
@@ -3379,7 +3384,7 @@ static long smb3_zero_range(struct file *file, struct cifs_tcon *tcon,
 static long smb3_punch_hole(struct file *file, struct cifs_tcon *tcon,
                            loff_t offset, loff_t len)
 {
-       struct inode *inode;
+       struct inode *inode = file_inode(file);
        struct cifsFileInfo *cfile = file->private_data;
        struct file_zero_data_information fsctl_buf;
        long rc;
@@ -3388,14 +3393,12 @@ static long smb3_punch_hole(struct file *file, struct cifs_tcon *tcon,
 
        xid = get_xid();
 
-       inode = d_inode(cfile->dentry);
-
+       inode_lock(inode);
        /* Need to make file sparse, if not already, before freeing range. */
        /* Consider adding equivalent for compressed since it could also work */
        if (!smb2_set_sparse(xid, tcon, cfile, inode, set_sparse)) {
                rc = -EOPNOTSUPP;
-               free_xid(xid);
-               return rc;
+               goto out;
        }
 
        filemap_invalidate_lock(inode->i_mapping);
@@ -3415,8 +3418,10 @@ static long smb3_punch_hole(struct file *file, struct cifs_tcon *tcon,
                        (char *)&fsctl_buf,
                        sizeof(struct file_zero_data_information),
                        CIFSMaxBufSize, NULL, NULL);
-       free_xid(xid);
        filemap_invalidate_unlock(inode->i_mapping);
+out:
+       inode_unlock(inode);
+       free_xid(xid);
        return rc;
 }
 
index 91cfc5b..128e44e 100644 (file)
@@ -2572,19 +2572,15 @@ alloc_path_with_tree_prefix(__le16 **out_path, int *out_size, int *out_len,
 
        path_len = UniStrnlen((wchar_t *)path, PATH_MAX);
 
-       /*
-        * make room for one path separator between the treename and
-        * path
-        */
-       *out_len = treename_len + 1 + path_len;
+       /* make room for one path separator only if @path isn't empty */
+       *out_len = treename_len + (path[0] ? 1 : 0) + path_len;
 
        /*
-        * final path needs to be null-terminated UTF16 with a
-        * size aligned to 8
+        * final path needs to be 8-byte aligned as specified in
+        * MS-SMB2 2.2.13 SMB2 CREATE Request.
         */
-
-       *out_size = roundup((*out_len+1)*2, 8);
-       *out_path = kzalloc(*out_size, GFP_KERNEL);
+       *out_size = roundup(*out_len * sizeof(__le16), 8);
+       *out_path = kzalloc(*out_size + sizeof(__le16) /* null */, GFP_KERNEL);
        if (!*out_path)
                return -ENOMEM;
 
index de7aece..c2fe035 100644 (file)
@@ -261,8 +261,8 @@ smb_rqst_len(struct TCP_Server_Info *server, struct smb_rqst *rqst)
        int nvec;
        unsigned long buflen = 0;
 
-       if (server->vals->header_preamble_size == 0 &&
-           rqst->rq_nvec >= 2 && rqst->rq_iov[0].iov_len == 4) {
+       if (!is_smb1(server) && rqst->rq_nvec >= 2 &&
+           rqst->rq_iov[0].iov_len == 4) {
                iov = &rqst->rq_iov[1];
                nvec = rqst->rq_nvec - 1;
        } else {
@@ -346,7 +346,7 @@ __smb_send_rqst(struct TCP_Server_Info *server, int num_rqst,
        sigprocmask(SIG_BLOCK, &mask, &oldmask);
 
        /* Generate a rfc1002 marker for SMB2+ */
-       if (server->vals->header_preamble_size == 0) {
+       if (!is_smb1(server)) {
                struct kvec hiov = {
                        .iov_base = &rfc1002_marker,
                        .iov_len  = 4
@@ -1238,7 +1238,7 @@ compound_send_recv(const unsigned int xid, struct cifs_ses *ses,
                buf = (char *)midQ[i]->resp_buf;
                resp_iov[i].iov_base = buf;
                resp_iov[i].iov_len = midQ[i]->resp_buf_size +
-                       server->vals->header_preamble_size;
+                       HEADER_PREAMBLE_SIZE(server);
 
                if (midQ[i]->large_buf)
                        resp_buf_type[i] = CIFS_LARGE_BUFFER;
@@ -1643,7 +1643,7 @@ int
 cifs_discard_remaining_data(struct TCP_Server_Info *server)
 {
        unsigned int rfclen = server->pdu_size;
-       int remaining = rfclen + server->vals->header_preamble_size -
+       int remaining = rfclen + HEADER_PREAMBLE_SIZE(server) -
                server->total_read;
 
        while (remaining > 0) {
@@ -1689,8 +1689,7 @@ cifs_readv_receive(struct TCP_Server_Info *server, struct mid_q_entry *mid)
        unsigned int data_offset, data_len;
        struct cifs_readdata *rdata = mid->callback_data;
        char *buf = server->smallbuf;
-       unsigned int buflen = server->pdu_size +
-               server->vals->header_preamble_size;
+       unsigned int buflen = server->pdu_size + HEADER_PREAMBLE_SIZE(server);
        bool use_rdma_mr = false;
 
        cifs_dbg(FYI, "%s: mid=%llu offset=%llu bytes=%u\n",
@@ -1724,10 +1723,10 @@ cifs_readv_receive(struct TCP_Server_Info *server, struct mid_q_entry *mid)
 
        /* set up first two iov for signature check and to get credits */
        rdata->iov[0].iov_base = buf;
-       rdata->iov[0].iov_len = server->vals->header_preamble_size;
-       rdata->iov[1].iov_base = buf + server->vals->header_preamble_size;
+       rdata->iov[0].iov_len = HEADER_PREAMBLE_SIZE(server);
+       rdata->iov[1].iov_base = buf + HEADER_PREAMBLE_SIZE(server);
        rdata->iov[1].iov_len =
-               server->total_read - server->vals->header_preamble_size;
+               server->total_read - HEADER_PREAMBLE_SIZE(server);
        cifs_dbg(FYI, "0: iov_base=%p iov_len=%zu\n",
                 rdata->iov[0].iov_base, rdata->iov[0].iov_len);
        cifs_dbg(FYI, "1: iov_base=%p iov_len=%zu\n",
@@ -1752,7 +1751,7 @@ cifs_readv_receive(struct TCP_Server_Info *server, struct mid_q_entry *mid)
        }
 
        data_offset = server->ops->read_data_offset(buf) +
-               server->vals->header_preamble_size;
+               HEADER_PREAMBLE_SIZE(server);
        if (data_offset < server->total_read) {
                /*
                 * win2k8 sometimes sends an offset of 0 when the read
index 0522136..08a1993 100644 (file)
@@ -134,10 +134,10 @@ static bool inode_io_list_move_locked(struct inode *inode,
 
 static void wb_wakeup(struct bdi_writeback *wb)
 {
-       spin_lock_bh(&wb->work_lock);
+       spin_lock_irq(&wb->work_lock);
        if (test_bit(WB_registered, &wb->state))
                mod_delayed_work(bdi_wq, &wb->dwork, 0);
-       spin_unlock_bh(&wb->work_lock);
+       spin_unlock_irq(&wb->work_lock);
 }
 
 static void finish_writeback_work(struct bdi_writeback *wb,
@@ -164,7 +164,7 @@ static void wb_queue_work(struct bdi_writeback *wb,
        if (work->done)
                atomic_inc(&work->done->cnt);
 
-       spin_lock_bh(&wb->work_lock);
+       spin_lock_irq(&wb->work_lock);
 
        if (test_bit(WB_registered, &wb->state)) {
                list_add_tail(&work->list, &wb->work_list);
@@ -172,7 +172,7 @@ static void wb_queue_work(struct bdi_writeback *wb,
        } else
                finish_writeback_work(wb, work);
 
-       spin_unlock_bh(&wb->work_lock);
+       spin_unlock_irq(&wb->work_lock);
 }
 
 /**
@@ -2082,13 +2082,13 @@ static struct wb_writeback_work *get_next_work_item(struct bdi_writeback *wb)
 {
        struct wb_writeback_work *work = NULL;
 
-       spin_lock_bh(&wb->work_lock);
+       spin_lock_irq(&wb->work_lock);
        if (!list_empty(&wb->work_list)) {
                work = list_entry(wb->work_list.next,
                                  struct wb_writeback_work, list);
                list_del_init(&work->list);
        }
-       spin_unlock_bh(&wb->work_lock);
+       spin_unlock_irq(&wb->work_lock);
        return work;
 }
 
index 6462276..ba1de23 100644 (file)
@@ -2018,23 +2018,25 @@ static int __file_remove_privs(struct file *file, unsigned int flags)
 {
        struct dentry *dentry = file_dentry(file);
        struct inode *inode = file_inode(file);
-       int error;
+       int error = 0;
        int kill;
 
        if (IS_NOSEC(inode) || !S_ISREG(inode->i_mode))
                return 0;
 
        kill = dentry_needs_remove_privs(dentry);
-       if (kill <= 0)
+       if (kill < 0)
                return kill;
 
-       if (flags & IOCB_NOWAIT)
-               return -EAGAIN;
+       if (kill) {
+               if (flags & IOCB_NOWAIT)
+                       return -EAGAIN;
+
+               error = __remove_privs(file_mnt_user_ns(file), dentry, kill);
+       }
 
-       error = __remove_privs(file_mnt_user_ns(file), dentry, kill);
        if (!error)
                inode_has_no_xattr(inode);
-
        return error;
 }
 
index c266cfd..607f94a 100644 (file)
@@ -2129,6 +2129,7 @@ SYSCALL_DEFINE2(flock, unsigned int, fd, unsigned int, cmd)
        else
                error = locks_lock_file_wait(f.file, &fl);
 
+       locks_release_private(&fl);
  out_putf:
        fdput(f);
 
index 68789f8..df137ba 100644 (file)
@@ -4238,6 +4238,13 @@ static int build_mount_idmapped(const struct mount_attr *attr, size_t usize,
                err = -EPERM;
                goto out_fput;
        }
+
+       /* We're not controlling the target namespace. */
+       if (!ns_capable(mnt_userns, CAP_SYS_ADMIN)) {
+               err = -EPERM;
+               goto out_fput;
+       }
+
        kattr->mnt_userns = get_user_ns(mnt_userns);
 
 out_fput:
index dbab3ca..5d6c2dd 100644 (file)
@@ -2382,7 +2382,8 @@ static void nfs_dentry_remove_handle_error(struct inode *dir,
 {
        switch (error) {
        case -ENOENT:
-               d_delete(dentry);
+               if (d_really_is_positive(dentry))
+                       d_delete(dentry);
                nfs_set_verifier(dentry, nfs_save_change_attribute(dir));
                break;
        case 0:
@@ -2484,8 +2485,10 @@ int nfs_unlink(struct inode *dir, struct dentry *dentry)
         */
        error = -ETXTBSY;
        if (WARN_ON(dentry->d_flags & DCACHE_NFSFS_RENAMED) ||
-           WARN_ON(dentry->d_fsdata == NFS_FSDATA_BLOCKED))
+           WARN_ON(dentry->d_fsdata == NFS_FSDATA_BLOCKED)) {
+               spin_unlock(&dentry->d_lock);
                goto out;
+       }
        if (dentry->d_fsdata)
                /* old devname */
                kfree(dentry->d_fsdata);
index d2bcd48..e032fe2 100644 (file)
@@ -221,8 +221,10 @@ nfs_file_fsync_commit(struct file *file, int datasync)
 int
 nfs_file_fsync(struct file *file, loff_t start, loff_t end, int datasync)
 {
-       struct nfs_open_context *ctx = nfs_file_open_context(file);
        struct inode *inode = file_inode(file);
+       struct nfs_inode *nfsi = NFS_I(inode);
+       long save_nredirtied = atomic_long_read(&nfsi->redirtied_pages);
+       long nredirtied;
        int ret;
 
        trace_nfs_fsync_enter(inode);
@@ -237,15 +239,10 @@ nfs_file_fsync(struct file *file, loff_t start, loff_t end, int datasync)
                ret = pnfs_sync_inode(inode, !!datasync);
                if (ret != 0)
                        break;
-               if (!test_and_clear_bit(NFS_CONTEXT_RESEND_WRITES, &ctx->flags))
+               nredirtied = atomic_long_read(&nfsi->redirtied_pages);
+               if (nredirtied == save_nredirtied)
                        break;
-               /*
-                * If nfs_file_fsync_commit detected a server reboot, then
-                * resend all dirty pages that might have been covered by
-                * the NFS_CONTEXT_RESEND_WRITES flag
-                */
-               start = 0;
-               end = LLONG_MAX;
+               save_nredirtied = nredirtied;
        }
 
        trace_nfs_fsync_exit(inode, ret);
index b4e46b0..bea7c00 100644 (file)
@@ -426,6 +426,7 @@ nfs_ilookup(struct super_block *sb, struct nfs_fattr *fattr, struct nfs_fh *fh)
 static void nfs_inode_init_regular(struct nfs_inode *nfsi)
 {
        atomic_long_set(&nfsi->nrequests, 0);
+       atomic_long_set(&nfsi->redirtied_pages, 0);
        INIT_LIST_HEAD(&nfsi->commit_info.list);
        atomic_long_set(&nfsi->commit_info.ncommit, 0);
        atomic_set(&nfsi->commit_info.rpcs_out, 0);
index e88f6b1..9eb1812 100644 (file)
@@ -340,6 +340,11 @@ static struct file *__nfs42_ssc_open(struct vfsmount *ss_mnt,
                goto out;
        }
 
+       if (!S_ISREG(fattr->mode)) {
+               res = ERR_PTR(-EBADF);
+               goto out;
+       }
+
        res = ERR_PTR(-ENOMEM);
        len = strlen(SSC_READ_NAME_BODY) + 16;
        read_name = kzalloc(len, GFP_KERNEL);
@@ -357,6 +362,7 @@ static struct file *__nfs42_ssc_open(struct vfsmount *ss_mnt,
                                     r_ino->i_fop);
        if (IS_ERR(filep)) {
                res = ERR_CAST(filep);
+               iput(r_ino);
                goto out_free_name;
        }
 
index 41a9b6b..2613b7e 100644 (file)
@@ -2817,7 +2817,6 @@ int pnfs_write_done_resend_to_mds(struct nfs_pgio_header *hdr)
        /* Resend all requests through the MDS */
        nfs_pageio_init_write(&pgio, hdr->inode, FLUSH_STABLE, true,
                              hdr->completion_ops);
-       set_bit(NFS_CONTEXT_RESEND_WRITES, &hdr->args.context->flags);
        return nfs_pageio_resend(&pgio, hdr);
 }
 EXPORT_SYMBOL_GPL(pnfs_write_done_resend_to_mds);
index 51a7e20..1843fa2 100644 (file)
@@ -1420,10 +1420,12 @@ static void nfs_initiate_write(struct nfs_pgio_header *hdr,
  */
 static void nfs_redirty_request(struct nfs_page *req)
 {
+       struct nfs_inode *nfsi = NFS_I(page_file_mapping(req->wb_page)->host);
+
        /* Bump the transmission count */
        req->wb_nio++;
        nfs_mark_request_dirty(req);
-       set_bit(NFS_CONTEXT_RESEND_WRITES, &nfs_req_openctx(req)->flags);
+       atomic_long_inc(&nfsi->redirtied_pages);
        nfs_end_page_writeback(req);
        nfs_release_request(req);
 }
@@ -1904,7 +1906,7 @@ static void nfs_commit_release_pages(struct nfs_commit_data *data)
                /* We have a mismatch. Write the page again */
                dprintk_cont(" mismatch\n");
                nfs_mark_request_dirty(req);
-               set_bit(NFS_CONTEXT_RESEND_WRITES, &nfs_req_openctx(req)->flags);
+               atomic_long_inc(&NFS_I(data->inode)->redirtied_pages);
        next:
                nfs_unlock_and_release_request(req);
                /* Latency breaker */
index 5bdff12..6ae1f56 100644 (file)
@@ -483,8 +483,7 @@ out:
 }
 
 #ifdef CONFIG_NTFS3_FS_POSIX_ACL
-static struct posix_acl *ntfs_get_acl_ex(struct user_namespace *mnt_userns,
-                                        struct inode *inode, int type,
+static struct posix_acl *ntfs_get_acl_ex(struct inode *inode, int type,
                                         int locked)
 {
        struct ntfs_inode *ni = ntfs_i(inode);
@@ -519,7 +518,7 @@ static struct posix_acl *ntfs_get_acl_ex(struct user_namespace *mnt_userns,
 
        /* Translate extended attribute to acl. */
        if (err >= 0) {
-               acl = posix_acl_from_xattr(mnt_userns, buf, err);
+               acl = posix_acl_from_xattr(&init_user_ns, buf, err);
        } else if (err == -ENODATA) {
                acl = NULL;
        } else {
@@ -542,8 +541,7 @@ struct posix_acl *ntfs_get_acl(struct inode *inode, int type, bool rcu)
        if (rcu)
                return ERR_PTR(-ECHILD);
 
-       /* TODO: init_user_ns? */
-       return ntfs_get_acl_ex(&init_user_ns, inode, type, 0);
+       return ntfs_get_acl_ex(inode, type, 0);
 }
 
 static noinline int ntfs_set_acl_ex(struct user_namespace *mnt_userns,
@@ -595,7 +593,7 @@ static noinline int ntfs_set_acl_ex(struct user_namespace *mnt_userns,
                value = kmalloc(size, GFP_NOFS);
                if (!value)
                        return -ENOMEM;
-               err = posix_acl_to_xattr(mnt_userns, acl, value, size);
+               err = posix_acl_to_xattr(&init_user_ns, acl, value, size);
                if (err < 0)
                        goto out;
                flags = 0;
@@ -646,7 +644,7 @@ static int ntfs_xattr_get_acl(struct user_namespace *mnt_userns,
        if (!acl)
                return -ENODATA;
 
-       err = posix_acl_to_xattr(mnt_userns, acl, buffer, size);
+       err = posix_acl_to_xattr(&init_user_ns, acl, buffer, size);
        posix_acl_release(acl);
 
        return err;
@@ -670,12 +668,12 @@ static int ntfs_xattr_set_acl(struct user_namespace *mnt_userns,
        if (!value) {
                acl = NULL;
        } else {
-               acl = posix_acl_from_xattr(mnt_userns, value, size);
+               acl = posix_acl_from_xattr(&init_user_ns, value, size);
                if (IS_ERR(acl))
                        return PTR_ERR(acl);
 
                if (acl) {
-                       err = posix_acl_valid(mnt_userns, acl);
+                       err = posix_acl_valid(&init_user_ns, acl);
                        if (err)
                                goto release_and_out;
                }
index 801e60b..c28bc98 100644 (file)
@@ -3403,10 +3403,12 @@ void ocfs2_dlm_shutdown(struct ocfs2_super *osb,
        ocfs2_lock_res_free(&osb->osb_nfs_sync_lockres);
        ocfs2_lock_res_free(&osb->osb_orphan_scan.os_lockres);
 
-       ocfs2_cluster_disconnect(osb->cconn, hangup_pending);
-       osb->cconn = NULL;
+       if (osb->cconn) {
+               ocfs2_cluster_disconnect(osb->cconn, hangup_pending);
+               osb->cconn = NULL;
 
-       ocfs2_dlm_shutdown_debug(osb);
+               ocfs2_dlm_shutdown_debug(osb);
+       }
 }
 
 static int ocfs2_drop_lock(struct ocfs2_super *osb,
index 013a727..e2cc9ee 100644 (file)
@@ -1914,8 +1914,7 @@ static void ocfs2_dismount_volume(struct super_block *sb, int mnt_err)
            !ocfs2_is_hard_readonly(osb))
                hangup_needed = 1;
 
-       if (osb->cconn)
-               ocfs2_dlm_shutdown(osb, hangup_needed);
+       ocfs2_dlm_shutdown(osb, hangup_needed);
 
        ocfs2_blockcheck_stats_debugfs_remove(&osb->osb_ecc_stats);
        debugfs_remove_recursive(osb->osb_debug_root);
index b45fea6..0fbcb59 100644 (file)
@@ -460,9 +460,12 @@ ssize_t ovl_listxattr(struct dentry *dentry, char *list, size_t size)
  * of the POSIX ACLs retrieved from the lower layer to this function to not
  * alter the POSIX ACLs for the underlying filesystem.
  */
-static void ovl_idmap_posix_acl(struct user_namespace *mnt_userns,
+static void ovl_idmap_posix_acl(struct inode *realinode,
+                               struct user_namespace *mnt_userns,
                                struct posix_acl *acl)
 {
+       struct user_namespace *fs_userns = i_user_ns(realinode);
+
        for (unsigned int i = 0; i < acl->a_count; i++) {
                vfsuid_t vfsuid;
                vfsgid_t vfsgid;
@@ -470,11 +473,11 @@ static void ovl_idmap_posix_acl(struct user_namespace *mnt_userns,
                struct posix_acl_entry *e = &acl->a_entries[i];
                switch (e->e_tag) {
                case ACL_USER:
-                       vfsuid = make_vfsuid(mnt_userns, &init_user_ns, e->e_uid);
+                       vfsuid = make_vfsuid(mnt_userns, fs_userns, e->e_uid);
                        e->e_uid = vfsuid_into_kuid(vfsuid);
                        break;
                case ACL_GROUP:
-                       vfsgid = make_vfsgid(mnt_userns, &init_user_ns, e->e_gid);
+                       vfsgid = make_vfsgid(mnt_userns, fs_userns, e->e_gid);
                        e->e_gid = vfsgid_into_kgid(vfsgid);
                        break;
                }
@@ -536,7 +539,7 @@ struct posix_acl *ovl_get_acl(struct inode *inode, int type, bool rcu)
        if (!clone)
                clone = ERR_PTR(-ENOMEM);
        else
-               ovl_idmap_posix_acl(mnt_user_ns(realpath.mnt), clone);
+               ovl_idmap_posix_acl(realinode, mnt_user_ns(realpath.mnt), clone);
        /*
         * Since we're not in RCU path walk we always need to release the
         * original ACLs.
index 1d17d7b..5af3380 100644 (file)
@@ -361,6 +361,7 @@ posix_acl_permission(struct user_namespace *mnt_userns, struct inode *inode,
                     const struct posix_acl *acl, int want)
 {
        const struct posix_acl_entry *pa, *pe, *mask_obj;
+       struct user_namespace *fs_userns = i_user_ns(inode);
        int found = 0;
        vfsuid_t vfsuid;
        vfsgid_t vfsgid;
@@ -376,7 +377,7 @@ posix_acl_permission(struct user_namespace *mnt_userns, struct inode *inode,
                                         goto check_perm;
                                 break;
                         case ACL_USER:
-                               vfsuid = make_vfsuid(mnt_userns, &init_user_ns,
+                               vfsuid = make_vfsuid(mnt_userns, fs_userns,
                                                     pa->e_uid);
                                if (vfsuid_eq_kuid(vfsuid, current_fsuid()))
                                         goto mask;
@@ -390,7 +391,7 @@ posix_acl_permission(struct user_namespace *mnt_userns, struct inode *inode,
                                 }
                                break;
                         case ACL_GROUP:
-                               vfsgid = make_vfsgid(mnt_userns, &init_user_ns,
+                               vfsgid = make_vfsgid(mnt_userns, fs_userns,
                                                     pa->e_gid);
                                if (vfsgid_in_group_p(vfsgid)) {
                                        found = 1;
@@ -736,6 +737,7 @@ void posix_acl_getxattr_idmapped_mnt(struct user_namespace *mnt_userns,
 {
        struct posix_acl_xattr_header *header = value;
        struct posix_acl_xattr_entry *entry = (void *)(header + 1), *end;
+       struct user_namespace *fs_userns = i_user_ns(inode);
        int count;
        vfsuid_t vfsuid;
        vfsgid_t vfsgid;
@@ -753,13 +755,13 @@ void posix_acl_getxattr_idmapped_mnt(struct user_namespace *mnt_userns,
                switch (le16_to_cpu(entry->e_tag)) {
                case ACL_USER:
                        uid = make_kuid(&init_user_ns, le32_to_cpu(entry->e_id));
-                       vfsuid = make_vfsuid(mnt_userns, &init_user_ns, uid);
+                       vfsuid = make_vfsuid(mnt_userns, fs_userns, uid);
                        entry->e_id = cpu_to_le32(from_kuid(&init_user_ns,
                                                vfsuid_into_kuid(vfsuid)));
                        break;
                case ACL_GROUP:
                        gid = make_kgid(&init_user_ns, le32_to_cpu(entry->e_id));
-                       vfsgid = make_vfsgid(mnt_userns, &init_user_ns, gid);
+                       vfsgid = make_vfsgid(mnt_userns, fs_userns, gid);
                        entry->e_id = cpu_to_le32(from_kgid(&init_user_ns,
                                                vfsgid_into_kgid(vfsgid)));
                        break;
@@ -775,6 +777,7 @@ void posix_acl_setxattr_idmapped_mnt(struct user_namespace *mnt_userns,
 {
        struct posix_acl_xattr_header *header = value;
        struct posix_acl_xattr_entry *entry = (void *)(header + 1), *end;
+       struct user_namespace *fs_userns = i_user_ns(inode);
        int count;
        vfsuid_t vfsuid;
        vfsgid_t vfsgid;
@@ -793,13 +796,13 @@ void posix_acl_setxattr_idmapped_mnt(struct user_namespace *mnt_userns,
                case ACL_USER:
                        uid = make_kuid(&init_user_ns, le32_to_cpu(entry->e_id));
                        vfsuid = VFSUIDT_INIT(uid);
-                       uid = from_vfsuid(mnt_userns, &init_user_ns, vfsuid);
+                       uid = from_vfsuid(mnt_userns, fs_userns, vfsuid);
                        entry->e_id = cpu_to_le32(from_kuid(&init_user_ns, uid));
                        break;
                case ACL_GROUP:
                        gid = make_kgid(&init_user_ns, le32_to_cpu(entry->e_id));
                        vfsgid = VFSGIDT_INIT(gid);
-                       gid = from_vfsgid(mnt_userns, &init_user_ns, vfsgid);
+                       gid = from_vfsgid(mnt_userns, fs_userns, vfsgid);
                        entry->e_id = cpu_to_le32(from_kgid(&init_user_ns, gid));
                        break;
                default:
index a3398d0..4e00236 100644 (file)
@@ -527,10 +527,12 @@ static void smaps_pte_entry(pte_t *pte, unsigned long addr,
        struct vm_area_struct *vma = walk->vma;
        bool locked = !!(vma->vm_flags & VM_LOCKED);
        struct page *page = NULL;
-       bool migration = false;
+       bool migration = false, young = false, dirty = false;
 
        if (pte_present(*pte)) {
                page = vm_normal_page(vma, addr, *pte);
+               young = pte_young(*pte);
+               dirty = pte_dirty(*pte);
        } else if (is_swap_pte(*pte)) {
                swp_entry_t swpent = pte_to_swp_entry(*pte);
 
@@ -560,8 +562,7 @@ static void smaps_pte_entry(pte_t *pte, unsigned long addr,
        if (!page)
                return;
 
-       smaps_account(mss, page, false, pte_young(*pte), pte_dirty(*pte),
-                     locked, migration);
+       smaps_account(mss, page, false, young, dirty, locked, migration);
 }
 
 #ifdef CONFIG_TRANSPARENT_HUGEPAGE
index 98e64fe..e565109 100644 (file)
@@ -593,7 +593,7 @@ static void squashfs_readahead(struct readahead_control *ractl)
 
                res = squashfs_read_data(inode->i_sb, block, bsize, NULL, actor);
 
-               kfree(actor);
+               squashfs_page_actor_free(actor);
 
                if (res == expected) {
                        int bytes;
index be4b12d..f1ccad5 100644 (file)
@@ -74,7 +74,7 @@ int squashfs_readpage_block(struct page *target_page, u64 block, int bsize,
        /* Decompress directly into the page cache buffers */
        res = squashfs_read_data(inode->i_sb, block, bsize, NULL, actor);
 
-       kfree(actor);
+       squashfs_page_actor_free(actor);
 
        if (res < 0)
                goto mark_errored;
index b23b780..54b93bf 100644 (file)
@@ -52,6 +52,7 @@ struct squashfs_page_actor *squashfs_page_actor_init(void **buffer,
        actor->buffer = buffer;
        actor->pages = pages;
        actor->next_page = 0;
+       actor->tmp_buffer = NULL;
        actor->squashfs_first_page = cache_first_page;
        actor->squashfs_next_page = cache_next_page;
        actor->squashfs_finish_page = cache_finish_page;
@@ -68,20 +69,9 @@ static void *handle_next_page(struct squashfs_page_actor *actor)
 
        if ((actor->next_page == actor->pages) ||
                        (actor->next_index != actor->page[actor->next_page]->index)) {
-               if (actor->alloc_buffer) {
-                       void *tmp_buffer = kmalloc(PAGE_SIZE, GFP_KERNEL);
-
-                       if (tmp_buffer) {
-                               actor->tmp_buffer = tmp_buffer;
-                               actor->next_index++;
-                               actor->returned_pages++;
-                               return tmp_buffer;
-                       }
-               }
-
                actor->next_index++;
                actor->returned_pages++;
-               return ERR_PTR(-ENOMEM);
+               return actor->alloc_buffer ? actor->tmp_buffer : ERR_PTR(-ENOMEM);
        }
 
        actor->next_index++;
@@ -96,11 +86,10 @@ static void *direct_first_page(struct squashfs_page_actor *actor)
 
 static void *direct_next_page(struct squashfs_page_actor *actor)
 {
-       if (actor->pageaddr)
+       if (actor->pageaddr) {
                kunmap_local(actor->pageaddr);
-
-       kfree(actor->tmp_buffer);
-       actor->pageaddr = actor->tmp_buffer = NULL;
+               actor->pageaddr = NULL;
+       }
 
        return handle_next_page(actor);
 }
@@ -109,8 +98,6 @@ static void direct_finish_page(struct squashfs_page_actor *actor)
 {
        if (actor->pageaddr)
                kunmap_local(actor->pageaddr);
-
-       kfree(actor->tmp_buffer);
 }
 
 struct squashfs_page_actor *squashfs_page_actor_init_special(struct squashfs_sb_info *msblk,
@@ -121,6 +108,16 @@ struct squashfs_page_actor *squashfs_page_actor_init_special(struct squashfs_sb_
        if (actor == NULL)
                return NULL;
 
+       if (msblk->decompressor->alloc_buffer) {
+               actor->tmp_buffer = kmalloc(PAGE_SIZE, GFP_KERNEL);
+
+               if (actor->tmp_buffer == NULL) {
+                       kfree(actor);
+                       return NULL;
+               }
+       } else
+               actor->tmp_buffer = NULL;
+
        actor->length = length ? : pages * PAGE_SIZE;
        actor->page = page;
        actor->pages = pages;
@@ -128,7 +125,6 @@ struct squashfs_page_actor *squashfs_page_actor_init_special(struct squashfs_sb_
        actor->returned_pages = 0;
        actor->next_index = page[0]->index & ~((1 << (msblk->block_log - PAGE_SHIFT)) - 1);
        actor->pageaddr = NULL;
-       actor->tmp_buffer = NULL;
        actor->alloc_buffer = msblk->decompressor->alloc_buffer;
        actor->squashfs_first_page = direct_first_page;
        actor->squashfs_next_page = direct_next_page;
index 24841d2..95ffbb5 100644 (file)
@@ -29,6 +29,11 @@ extern struct squashfs_page_actor *squashfs_page_actor_init(void **buffer,
 extern struct squashfs_page_actor *squashfs_page_actor_init_special(
                                struct squashfs_sb_info *msblk,
                                struct page **page, int pages, int length);
+static inline void squashfs_page_actor_free(struct squashfs_page_actor *actor)
+{
+       kfree(actor->tmp_buffer);
+       kfree(actor);
+}
 static inline void *squashfs_first_page(struct squashfs_page_actor *actor)
 {
        return actor->squashfs_first_page(actor);
index 1c44bf7..175de70 100644 (file)
@@ -1601,6 +1601,10 @@ static int userfaultfd_unregister(struct userfaultfd_ctx *ctx,
                        wake_userfault(vma->vm_userfaultfd_ctx.ctx, &range);
                }
 
+               /* Reset ptes for the whole vma range if wr-protected */
+               if (userfaultfd_wp(vma))
+                       uffd_wp_range(mm, vma, start, vma_end - start, false);
+
                new_flags = vma->vm_flags & ~__VM_UFFD_FLAGS;
                prev = vma_merge(mm, prev, start, vma_end, new_flags,
                                 vma->anon_vma, vma->vm_file, vma->vm_pgoff,
index 3d5ebd2..564a8c6 100644 (file)
@@ -4,6 +4,7 @@
 #define __ASM_GENERIC_BITOPS_GENERIC_NON_ATOMIC_H
 
 #include <linux/bits.h>
+#include <asm/barrier.h>
 
 #ifndef _LINUX_BITOPS_H
 #error only <linux/bitops.h> can be included directly
@@ -127,6 +128,18 @@ generic_test_bit(unsigned long nr, const volatile unsigned long *addr)
        return 1UL & (addr[BIT_WORD(nr)] >> (nr & (BITS_PER_LONG-1)));
 }
 
+/**
+ * generic_test_bit_acquire - Determine, with acquire semantics, whether a bit is set
+ * @nr: bit number to test
+ * @addr: Address to start counting from
+ */
+static __always_inline bool
+generic_test_bit_acquire(unsigned long nr, const volatile unsigned long *addr)
+{
+       unsigned long *p = ((unsigned long *)addr) + BIT_WORD(nr);
+       return 1UL & (smp_load_acquire(p) >> (nr & (BITS_PER_LONG-1)));
+}
+
 /*
  * const_*() definitions provide good compile-time optimizations when
  * the passed arguments can be resolved at compile time.
@@ -137,6 +150,7 @@ generic_test_bit(unsigned long nr, const volatile unsigned long *addr)
 #define const___test_and_set_bit       generic___test_and_set_bit
 #define const___test_and_clear_bit     generic___test_and_clear_bit
 #define const___test_and_change_bit    generic___test_and_change_bit
+#define const_test_bit_acquire         generic_test_bit_acquire
 
 /**
  * const_test_bit - Determine whether a bit is set
index 988a3bb..2b238b1 100644 (file)
@@ -142,4 +142,16 @@ _test_bit(unsigned long nr, const volatile unsigned long *addr)
        return arch_test_bit(nr, addr);
 }
 
+/**
+ * _test_bit_acquire - Determine, with acquire semantics, whether a bit is set
+ * @nr: bit number to test
+ * @addr: Address to start counting from
+ */
+static __always_inline bool
+_test_bit_acquire(unsigned long nr, const volatile unsigned long *addr)
+{
+       instrument_atomic_read(addr + BIT_WORD(nr), sizeof(long));
+       return arch_test_bit_acquire(nr, addr);
+}
+
 #endif /* _ASM_GENERIC_BITOPS_INSTRUMENTED_NON_ATOMIC_H */
index 5c37ced..71f8d54 100644 (file)
@@ -13,6 +13,7 @@
 #define arch___test_and_change_bit generic___test_and_change_bit
 
 #define arch_test_bit generic_test_bit
+#define arch_test_bit_acquire generic_test_bit_acquire
 
 #include <asm-generic/bitops/non-instrumented-non-atomic.h>
 
index bdb9b1f..0ddc78d 100644 (file)
@@ -12,5 +12,6 @@
 #define ___test_and_change_bit arch___test_and_change_bit
 
 #define _test_bit              arch_test_bit
+#define _test_bit_acquire      arch_test_bit_acquire
 
 #endif /* __ASM_GENERIC_BITOPS_NON_INSTRUMENTED_NON_ATOMIC_H */
index d0f7bdd..db13bb6 100644 (file)
@@ -97,7 +97,7 @@ static inline bool memory_contains(void *begin, void *end, void *virt,
 /**
  * memory_intersects - checks if the region occupied by an object intersects
  *                     with another memory region
- * @begin: virtual address of the beginning of the memory regien
+ * @begin: virtual address of the beginning of the memory region
  * @end: virtual address of the end of the memory region
  * @virt: virtual address of the memory object
  * @size: size of the memory object
@@ -110,7 +110,10 @@ static inline bool memory_intersects(void *begin, void *end, void *virt,
 {
        void *vend = virt + size;
 
-       return (virt >= begin && virt < end) || (vend >= begin && vend < end);
+       if (virt < end && vend > begin)
+               return true;
+
+       return false;
 }
 
 /**
index cf9bf65..3b89c64 100644 (file)
@@ -59,6 +59,7 @@ extern unsigned long __sw_hweight64(__u64 w);
 #define __test_and_clear_bit(nr, addr) bitop(___test_and_clear_bit, nr, addr)
 #define __test_and_change_bit(nr, addr)        bitop(___test_and_change_bit, nr, addr)
 #define test_bit(nr, addr)             bitop(_test_bit, nr, addr)
+#define test_bit_acquire(nr, addr)     bitop(_test_bit_acquire, nr, addr)
 
 /*
  * Include this here because some architectures need generic_ffs/fls in
index def8b8d..089c9ad 100644 (file)
@@ -156,7 +156,7 @@ static __always_inline int buffer_uptodate(const struct buffer_head *bh)
         * make it consistent with folio_test_uptodate
         * pairs with smp_mb__before_atomic in set_buffer_uptodate
         */
-       return (smp_load_acquire(&bh->b_state) & (1UL << BH_Uptodate)) != 0;
+       return test_bit_acquire(BH_Uptodate, &bh->b_state);
 }
 
 #define bh_offset(bh)          ((unsigned long)(bh)->b_data & ~PAGE_MASK)
index ed53bfe..ac5d051 100644 (file)
@@ -734,11 +734,6 @@ static inline struct cgroup *cgroup_parent(struct cgroup *cgrp)
        return NULL;
 }
 
-static inline struct psi_group *cgroup_psi(struct cgroup *cgrp)
-{
-       return NULL;
-}
-
 static inline bool cgroup_psi_enabled(void)
 {
        return false;
index 01ce94b..7713d7b 100644 (file)
@@ -240,6 +240,12 @@ static inline void *offset_to_ptr(const int *off)
 #define __must_be_array(a)     BUILD_BUG_ON_ZERO(__same_type((a), &(a)[0]))
 
 /*
+ * Whether 'type' is a signed type or an unsigned type. Supports scalar types,
+ * bool and also pointer types.
+ */
+#define is_signed_type(type) (((type)(-1)) < (__force type)1)
+
+/*
  * This is needed in functions which generate the stack canary, see
  * arch/x86/kernel/smpboot.c::start_secondary() for an example.
  */
index 720874e..36e5dd8 100644 (file)
@@ -258,7 +258,7 @@ struct fscache_cookie *fscache_acquire_cookie(struct fscache_volume *volume,
 
 /**
  * fscache_use_cookie - Request usage of cookie attached to an object
- * @object: Object description
+ * @cookie: The cookie representing the cache object
  * @will_modify: If cache is expected to be modified locally
  *
  * Request usage of the cookie attached to an object.  The caller should tell
@@ -274,7 +274,7 @@ static inline void fscache_use_cookie(struct fscache_cookie *cookie,
 
 /**
  * fscache_unuse_cookie - Cease usage of cookie attached to an object
- * @object: Object description
+ * @cookie: The cookie representing the cache object
  * @aux_data: Updated auxiliary data (or NULL)
  * @object_size: Revised size of the object (or NULL)
  *
index 8064481..60fff13 100644 (file)
@@ -407,4 +407,5 @@ LSM_HOOK(int, 0, perf_event_write, struct perf_event *event)
 #ifdef CONFIG_IO_URING
 LSM_HOOK(int, 0, uring_override_creds, const struct cred *new)
 LSM_HOOK(int, 0, uring_sqpoll, void)
+LSM_HOOK(int, 0, uring_cmd, struct io_uring_cmd *ioucmd)
 #endif /* CONFIG_IO_URING */
index 84a0d7e..3aa6030 100644 (file)
  *      Check whether the current task is allowed to spawn a io_uring polling
  *      thread (IORING_SETUP_SQPOLL).
  *
+ * @uring_cmd:
+ *      Check whether the file_operations uring_cmd is allowed to run.
+ *
  */
 union security_list_options {
        #define LSM_HOOK(RET, DEFAULT, NAME, ...) RET (*NAME)(__VA_ARGS__);
index 4d31ce5..6257867 100644 (file)
@@ -987,19 +987,30 @@ static inline void mod_memcg_page_state(struct page *page,
 
 static inline unsigned long memcg_page_state(struct mem_cgroup *memcg, int idx)
 {
-       return READ_ONCE(memcg->vmstats.state[idx]);
+       long x = READ_ONCE(memcg->vmstats.state[idx]);
+#ifdef CONFIG_SMP
+       if (x < 0)
+               x = 0;
+#endif
+       return x;
 }
 
 static inline unsigned long lruvec_page_state(struct lruvec *lruvec,
                                              enum node_stat_item idx)
 {
        struct mem_cgroup_per_node *pn;
+       long x;
 
        if (mem_cgroup_disabled())
                return node_page_state(lruvec_pgdat(lruvec), idx);
 
        pn = container_of(lruvec, struct mem_cgroup_per_node, lruvec);
-       return READ_ONCE(pn->lruvec_stats.state[idx]);
+       x = READ_ONCE(pn->lruvec_stats.state[idx]);
+#ifdef CONFIG_SMP
+       if (x < 0)
+               x = 0;
+#endif
+       return x;
 }
 
 static inline unsigned long lruvec_page_state_local(struct lruvec *lruvec,
index 96b16fb..7b7ce60 100644 (file)
@@ -779,6 +779,7 @@ struct mlx5_core_dev {
        enum mlx5_device_state  state;
        /* sync interface state */
        struct mutex            intf_state_mutex;
+       struct lock_class_key   lock_key;
        unsigned long           intf_state;
        struct mlx5_priv        priv;
        struct mlx5_profile     profile;
index 3bedc44..21f8b27 100644 (file)
@@ -1544,9 +1544,16 @@ static inline bool is_longterm_pinnable_page(struct page *page)
        if (mt == MIGRATE_CMA || mt == MIGRATE_ISOLATE)
                return false;
 #endif
-       return !(is_device_coherent_page(page) ||
-                is_zone_movable_page(page) ||
-                is_zero_pfn(page_to_pfn(page)));
+       /* The zero page may always be pinned */
+       if (is_zero_pfn(page_to_pfn(page)))
+               return true;
+
+       /* Coherent device memory must always allow eviction. */
+       if (is_device_coherent_page(page))
+               return false;
+
+       /* Otherwise, non-movable zone pages can be pinned. */
+       return !is_zone_movable_page(page);
 }
 #else
 static inline bool is_longterm_pinnable_page(struct page *page)
@@ -2885,7 +2892,6 @@ struct page *follow_page(struct vm_area_struct *vma, unsigned long address,
 #define FOLL_MIGRATION 0x400   /* wait for page to replace migration entry */
 #define FOLL_TRIED     0x800   /* a retry, previous pass started an IO */
 #define FOLL_REMOTE    0x2000  /* we are working on non-current tsk/mm */
-#define FOLL_COW       0x4000  /* internal GUP flag */
 #define FOLL_ANON      0x8000  /* don't do file mappings */
 #define FOLL_LONGTERM  0x10000 /* mapping lifetime is indefinite: see below */
 #define FOLL_SPLIT_PMD 0x20000 /* split huge pmd before returning */
index 1a3cb93..05d6f3f 100644 (file)
@@ -640,9 +640,23 @@ extern int sysctl_devconf_inherit_init_net;
  */
 static inline bool net_has_fallback_tunnels(const struct net *net)
 {
-       return !IS_ENABLED(CONFIG_SYSCTL) ||
-              !sysctl_fb_tunnels_only_for_init_net ||
-              (net == &init_net && sysctl_fb_tunnels_only_for_init_net == 1);
+#if IS_ENABLED(CONFIG_SYSCTL)
+       int fb_tunnels_only_for_init_net = READ_ONCE(sysctl_fb_tunnels_only_for_init_net);
+
+       return !fb_tunnels_only_for_init_net ||
+               (net_eq(net, &init_net) && fb_tunnels_only_for_init_net == 1);
+#else
+       return true;
+#endif
+}
+
+static inline int net_inherit_devconf(void)
+{
+#if IS_ENABLED(CONFIG_SYSCTL)
+       return READ_ONCE(sysctl_devconf_inherit_init_net);
+#else
+       return 0;
+#endif
 }
 
 static inline int netdev_queue_numa_node_read(const struct netdev_queue *q)
index a13296d..fd53355 100644 (file)
@@ -94,10 +94,6 @@ struct ebt_table {
        struct ebt_replace_kernel *table;
        unsigned int valid_hooks;
        rwlock_t lock;
-       /* e.g. could be the table explicitly only allows certain
-        * matches, targets, ... 0 == let it in */
-       int (*check)(const struct ebt_table_info *info,
-          unsigned int valid_hooks);
        /* the data used by the kernel */
        struct ebt_table_info *private;
        struct nf_hook_ops *ops;
index b32ed68..7931fa4 100644 (file)
@@ -83,7 +83,6 @@ struct nfs_open_context {
        fmode_t mode;
 
        unsigned long flags;
-#define NFS_CONTEXT_RESEND_WRITES      (1)
 #define NFS_CONTEXT_BAD                        (2)
 #define NFS_CONTEXT_UNLOCK     (3)
 #define NFS_CONTEXT_FILE_OPEN          (4)
@@ -182,6 +181,7 @@ struct nfs_inode {
                /* Regular file */
                struct {
                        atomic_long_t   nrequests;
+                       atomic_long_t   redirtied_pages;
                        struct nfs_mds_commit_info commit_info;
                        struct mutex    commit_mutex;
                };
index f1221d1..0eb3b19 100644 (file)
@@ -30,7 +30,6 @@
  * https://mail-index.netbsd.org/tech-misc/2007/02/05/0000.html -
  * credit to Christian Biere.
  */
-#define is_signed_type(type)       (((type)(-1)) < (type)1)
 #define __type_half_max(type) ((type)1 << (8*sizeof(type) - 1 - is_signed_type(type)))
 #define type_max(T) ((T)((__type_half_max(T) - 1) + __type_half_max(T)))
 #define type_min(T) ((T)((T)-type_max(T)-(T)1))
index 8978476..dd74411 100644 (file)
@@ -27,7 +27,7 @@ void psi_memstall_leave(unsigned long *flags);
 
 int psi_show(struct seq_file *s, struct psi_group *group, enum psi_res res);
 struct psi_trigger *psi_trigger_create(struct psi_group *group,
-                       char *buf, size_t nbytes, enum psi_res res);
+                       char *buf, enum psi_res res);
 void psi_trigger_destroy(struct psi_trigger *t);
 
 __poll_t psi_trigger_poll(void **trigger_ptr, struct file *file,
index bf80adc..b89b4b8 100644 (file)
@@ -41,12 +41,15 @@ struct anon_vma {
        atomic_t refcount;
 
        /*
-        * Count of child anon_vmas and VMAs which points to this anon_vma.
+        * Count of child anon_vmas. Equals to the count of all anon_vmas that
+        * have ->parent pointing to this one, including itself.
         *
         * This counter is used for making decision about reusing anon_vma
         * instead of forking new one. See comments in function anon_vma_clone.
         */
-       unsigned degree;
+       unsigned long num_children;
+       /* Count of VMAs whose ->anon_vma pointer points to this object. */
+       unsigned long num_active_vmas;
 
        struct anon_vma *parent;        /* Parent of this anon_vma */
 
index 1bc362c..7bd0c49 100644 (file)
@@ -2060,6 +2060,7 @@ static inline int security_perf_event_write(struct perf_event *event)
 #ifdef CONFIG_SECURITY
 extern int security_uring_override_creds(const struct cred *new);
 extern int security_uring_sqpoll(void);
+extern int security_uring_cmd(struct io_uring_cmd *ioucmd);
 #else
 static inline int security_uring_override_creds(const struct cred *new)
 {
@@ -2069,6 +2070,10 @@ static inline int security_uring_sqpoll(void)
 {
        return 0;
 }
+static inline int security_uring_cmd(struct io_uring_cmd *ioucmd)
+{
+       return 0;
+}
 #endif /* CONFIG_SECURITY */
 #endif /* CONFIG_IO_URING */
 
index 1b6c401..ff0b990 100644 (file)
@@ -29,15 +29,10 @@ struct shmem_inode_info {
        struct inode            vfs_inode;
 };
 
-#define SHMEM_FL_USER_VISIBLE FS_FL_USER_VISIBLE
-#define SHMEM_FL_USER_MODIFIABLE FS_FL_USER_MODIFIABLE
-#define SHMEM_FL_INHERITED FS_FL_USER_MODIFIABLE
-
-/* Flags that are appropriate for regular files (all but dir-specific ones). */
-#define SHMEM_REG_FLMASK (~(FS_DIRSYNC_FL | FS_TOPDIR_FL))
-
-/* Flags that are appropriate for non-directories/regular files. */
-#define SHMEM_OTHER_FLMASK (FS_NODUMP_FL | FS_NOATIME_FL)
+#define SHMEM_FL_USER_VISIBLE          FS_FL_USER_VISIBLE
+#define SHMEM_FL_USER_MODIFIABLE \
+       (FS_IMMUTABLE_FL | FS_APPEND_FL | FS_NODUMP_FL | FS_NOATIME_FL)
+#define SHMEM_FL_INHERITED             (FS_NODUMP_FL | FS_NOATIME_FL)
 
 struct shmem_sb_info {
        unsigned long max_blocks;   /* How many blocks are allowed */
index b18759a..8401dec 100644 (file)
@@ -814,8 +814,6 @@ extern int trace_add_event_call(struct trace_event_call *call);
 extern int trace_remove_event_call(struct trace_event_call *call);
 extern int trace_event_get_offsets(struct trace_event_call *call);
 
-#define is_signed_type(type)   (((type)(-1)) < (type)1)
-
 int ftrace_set_clr_event(struct trace_array *tr, char *buf, int set);
 int trace_set_clr_event(const char *system, const char *event, int set);
 int trace_array_set_clr_event(struct trace_array *tr, const char *system,
index 732b522..e1b8a91 100644 (file)
@@ -73,6 +73,8 @@ extern ssize_t mcopy_continue(struct mm_struct *dst_mm, unsigned long dst_start,
 extern int mwriteprotect_range(struct mm_struct *dst_mm,
                               unsigned long start, unsigned long len,
                               bool enable_wp, atomic_t *mmap_changing);
+extern void uffd_wp_range(struct mm_struct *dst_mm, struct vm_area_struct *vma,
+                         unsigned long start, unsigned long len, bool enable_wp);
 
 /* mm helpers */
 static inline bool is_mergeable_vm_userfaultfd_ctx(struct vm_area_struct *vma,
index 4040244..f3fc36c 100644 (file)
 #define HIGHMEM_ZONE(xx)
 #endif
 
-#define FOR_ALL_ZONES(xx) DMA_ZONE(xx) DMA32_ZONE(xx) xx##_NORMAL, HIGHMEM_ZONE(xx) xx##_MOVABLE
+#ifdef CONFIG_ZONE_DEVICE
+#define DEVICE_ZONE(xx) xx##_DEVICE,
+#else
+#define DEVICE_ZONE(xx)
+#endif
+
+#define FOR_ALL_ZONES(xx) DMA_ZONE(xx) DMA32_ZONE(xx) xx##_NORMAL, \
+       HIGHMEM_ZONE(xx) xx##_MOVABLE, DEVICE_ZONE(xx)
 
 enum vm_event_item { PGPGIN, PGPGOUT, PSWPIN, PSWPOUT,
-               FOR_ALL_ZONES(PGALLOC),
-               FOR_ALL_ZONES(ALLOCSTALL),
-               FOR_ALL_ZONES(PGSCAN_SKIP),
+               FOR_ALL_ZONES(PGALLOC)
+               FOR_ALL_ZONES(ALLOCSTALL)
+               FOR_ALL_ZONES(PGSCAN_SKIP)
                PGFREE, PGACTIVATE, PGDEACTIVATE, PGLAZYFREE,
                PGFAULT, PGMAJFAULT,
                PGLAZYFREED,
index 7dec36a..7725b75 100644 (file)
@@ -71,7 +71,7 @@ static inline int
 wait_on_bit(unsigned long *word, int bit, unsigned mode)
 {
        might_sleep();
-       if (!test_bit(bit, word))
+       if (!test_bit_acquire(bit, word))
                return 0;
        return out_of_line_wait_on_bit(word, bit,
                                       bit_wait,
@@ -96,7 +96,7 @@ static inline int
 wait_on_bit_io(unsigned long *word, int bit, unsigned mode)
 {
        might_sleep();
-       if (!test_bit(bit, word))
+       if (!test_bit_acquire(bit, word))
                return 0;
        return out_of_line_wait_on_bit(word, bit,
                                       bit_wait_io,
@@ -123,7 +123,7 @@ wait_on_bit_timeout(unsigned long *word, int bit, unsigned mode,
                    unsigned long timeout)
 {
        might_sleep();
-       if (!test_bit(bit, word))
+       if (!test_bit_acquire(bit, word))
                return 0;
        return out_of_line_wait_on_bit_timeout(word, bit,
                                               bit_wait_timeout,
@@ -151,7 +151,7 @@ wait_on_bit_action(unsigned long *word, int bit, wait_bit_action_f *action,
                   unsigned mode)
 {
        might_sleep();
-       if (!test_bit(bit, word))
+       if (!test_bit_acquire(bit, word))
                return 0;
        return out_of_line_wait_on_bit(word, bit, action, mode);
 }
index 184105d..be2992e 100644 (file)
@@ -290,7 +290,7 @@ static inline const char *bond_3ad_churn_desc(churn_state_t state)
 }
 
 /* ========== AD Exported functions to the main bonding code ========== */
-void bond_3ad_initialize(struct bonding *bond, u16 tick_resolution);
+void bond_3ad_initialize(struct bonding *bond);
 void bond_3ad_bind_slave(struct slave *slave);
 void bond_3ad_unbind_slave(struct slave *slave);
 void bond_3ad_state_machine_handler(struct work_struct *);
index c4898fc..f90f002 100644 (file)
@@ -33,7 +33,7 @@ extern unsigned int sysctl_net_busy_poll __read_mostly;
 
 static inline bool net_busy_loop_on(void)
 {
-       return sysctl_net_busy_poll;
+       return READ_ONCE(sysctl_net_busy_poll);
 }
 
 static inline bool sk_can_busy_loop(const struct sock *sk)
index 867656b..24003de 100644 (file)
@@ -439,7 +439,7 @@ static inline void gro_normal_one(struct napi_struct *napi, struct sk_buff *skb,
 {
        list_add_tail(&skb->list, &napi->rx_list);
        napi->rx_count += segs;
-       if (napi->rx_count >= gro_normal_batch)
+       if (napi->rx_count >= READ_ONCE(gro_normal_batch))
                gro_normal_list(napi);
 }
 
index d5326c4..cd982f4 100644 (file)
@@ -270,6 +270,7 @@ void flow_offload_refresh(struct nf_flowtable *flow_table,
 
 struct flow_offload_tuple_rhash *flow_offload_lookup(struct nf_flowtable *flow_table,
                                                     struct flow_offload_tuple *tuple);
+void nf_flow_table_gc_run(struct nf_flowtable *flow_table);
 void nf_flow_table_gc_cleanup(struct nf_flowtable *flowtable,
                              struct net_device *dev);
 void nf_flow_table_cleanup(struct net_device *dev);
@@ -306,6 +307,8 @@ void nf_flow_offload_stats(struct nf_flowtable *flowtable,
                           struct flow_offload *flow);
 
 void nf_flow_table_offload_flush(struct nf_flowtable *flowtable);
+void nf_flow_table_offload_flush_cleanup(struct nf_flowtable *flowtable);
+
 int nf_flow_table_offload_setup(struct nf_flowtable *flowtable,
                                struct net_device *dev,
                                enum flow_block_command cmd);
index 99aae36..cdb7db9 100644 (file)
@@ -1652,6 +1652,7 @@ struct nftables_pernet {
        struct list_head        module_list;
        struct list_head        notify_list;
        struct mutex            commit_mutex;
+       u64                     table_handle;
        unsigned int            base_seq;
        u8                      validate_state;
 };
index 1463cfe..9e0b5c8 100644 (file)
 #include <linux/types.h>
 #include <linux/time_types.h>
 
+#ifdef __cplusplus
+extern "C" {
+#endif
+
 /*
  * IO submission data structure (Submission Queue Entry)
  */
@@ -661,4 +665,8 @@ struct io_uring_recvmsg_out {
        __u32 flags;
 };
 
+#ifdef __cplusplus
+}
+#endif
+
 #endif
index b1f3e6a..4f84ea7 100644 (file)
@@ -296,7 +296,7 @@ enum xfrm_attr_type_t {
        XFRMA_ETIMER_THRESH,
        XFRMA_SRCADDR,          /* xfrm_address_t */
        XFRMA_COADDR,           /* xfrm_address_t */
-       XFRMA_LASTUSED,         /* unsigned long  */
+       XFRMA_LASTUSED,         /* __u64 */
        XFRMA_POLICY_TYPE,      /* struct xfrm_userpolicy_type */
        XFRMA_MIGRATE,
        XFRMA_ALG_AEAD,         /* struct xfrm_algo_aead */
index f81aa95..f525566 100644 (file)
@@ -135,11 +135,7 @@ static inline u32 ufshci_version(u32 major, u32 minor)
 
 #define UFSHCD_UIC_MASK                (UIC_COMMAND_COMPL | UFSHCD_UIC_PWR_MASK)
 
-#define UFSHCD_ERROR_MASK      (UIC_ERROR |\
-                               DEVICE_FATAL_ERROR |\
-                               CONTROLLER_FATAL_ERROR |\
-                               SYSTEM_BUS_FATAL_ERROR |\
-                               CRYPTO_ENGINE_FATAL_ERROR)
+#define UFSHCD_ERROR_MASK      (UIC_ERROR | INT_FATAL_ERRORS)
 
 #define INT_FATAL_ERRORS       (DEVICE_FATAL_ERROR |\
                                CONTROLLER_FATAL_ERROR |\
index 91642a4..1fe7942 100644 (file)
@@ -1446,13 +1446,25 @@ static noinline void __init kernel_init_freeable(void);
 
 #if defined(CONFIG_STRICT_KERNEL_RWX) || defined(CONFIG_STRICT_MODULE_RWX)
 bool rodata_enabled __ro_after_init = true;
+
+#ifndef arch_parse_debug_rodata
+static inline bool arch_parse_debug_rodata(char *str) { return false; }
+#endif
+
 static int __init set_debug_rodata(char *str)
 {
-       if (strtobool(str, &rodata_enabled))
+       if (arch_parse_debug_rodata(str))
+               return 0;
+
+       if (str && !strcmp(str, "on"))
+               rodata_enabled = true;
+       else if (str && !strcmp(str, "off"))
+               rodata_enabled = false;
+       else
                pr_warn("Invalid option string for rodata: '%s'\n", str);
-       return 1;
+       return 0;
 }
-__setup("rodata=", set_debug_rodata);
+early_param("rodata", set_debug_rodata);
 #endif
 
 #ifdef CONFIG_STRICT_KERNEL_RWX
index e4e1dc0..5fc5d3e 100644 (file)
@@ -218,7 +218,7 @@ static int __io_sync_cancel(struct io_uring_task *tctx,
            (cd->flags & IORING_ASYNC_CANCEL_FD_FIXED)) {
                unsigned long file_ptr;
 
-               if (unlikely(fd > ctx->nr_user_files))
+               if (unlikely(fd >= ctx->nr_user_files))
                        return -EBADF;
                fd = array_index_nospec(fd, ctx->nr_user_files);
                file_ptr = io_fixed_file_slot(&ctx->file_table, fd)->file_ptr;
index ebfdb22..7761627 100644 (file)
@@ -1450,9 +1450,10 @@ int io_req_prep_async(struct io_kiocb *req)
                return 0;
        if (WARN_ON_ONCE(req_has_async_data(req)))
                return -EFAULT;
-       if (io_alloc_async_data(req))
-               return -EAGAIN;
-
+       if (!io_op_defs[req->opcode].manual_alloc) {
+               if (io_alloc_async_data(req))
+                       return -EAGAIN;
+       }
        return def->prep_async(req);
 }
 
index f8cdf1d..0af8a02 100644 (file)
@@ -182,6 +182,37 @@ static int io_sendmsg_copy_hdr(struct io_kiocb *req,
                                        &iomsg->free_iov);
 }
 
+int io_sendzc_prep_async(struct io_kiocb *req)
+{
+       struct io_sendzc *zc = io_kiocb_to_cmd(req, struct io_sendzc);
+       struct io_async_msghdr *io;
+       int ret;
+
+       if (!zc->addr || req_has_async_data(req))
+               return 0;
+       if (io_alloc_async_data(req))
+               return -ENOMEM;
+
+       io = req->async_data;
+       ret = move_addr_to_kernel(zc->addr, zc->addr_len, &io->addr);
+       return ret;
+}
+
+static int io_setup_async_addr(struct io_kiocb *req,
+                             struct sockaddr_storage *addr,
+                             unsigned int issue_flags)
+{
+       struct io_async_msghdr *io;
+
+       if (!addr || req_has_async_data(req))
+               return -EAGAIN;
+       if (io_alloc_async_data(req))
+               return -ENOMEM;
+       io = req->async_data;
+       memcpy(&io->addr, addr, sizeof(io->addr));
+       return -EAGAIN;
+}
+
 int io_sendmsg_prep_async(struct io_kiocb *req)
 {
        int ret;
@@ -944,7 +975,7 @@ static int io_sg_from_iter(struct sock *sk, struct sk_buff *skb,
 
 int io_sendzc(struct io_kiocb *req, unsigned int issue_flags)
 {
-       struct sockaddr_storage address;
+       struct sockaddr_storage __address, *addr = NULL;
        struct io_ring_ctx *ctx = req->ctx;
        struct io_sendzc *zc = io_kiocb_to_cmd(req, struct io_sendzc);
        struct io_notif_slot *notif_slot;
@@ -978,10 +1009,17 @@ int io_sendzc(struct io_kiocb *req, unsigned int issue_flags)
        msg.msg_namelen = 0;
 
        if (zc->addr) {
-               ret = move_addr_to_kernel(zc->addr, zc->addr_len, &address);
-               if (unlikely(ret < 0))
-                       return ret;
-               msg.msg_name = (struct sockaddr *)&address;
+               if (req_has_async_data(req)) {
+                       struct io_async_msghdr *io = req->async_data;
+
+                       msg.msg_name = addr = &io->addr;
+               } else {
+                       ret = move_addr_to_kernel(zc->addr, zc->addr_len, &__address);
+                       if (unlikely(ret < 0))
+                               return ret;
+                       msg.msg_name = (struct sockaddr *)&__address;
+                       addr = &__address;
+               }
                msg.msg_namelen = zc->addr_len;
        }
 
@@ -989,7 +1027,7 @@ int io_sendzc(struct io_kiocb *req, unsigned int issue_flags)
                ret = io_import_fixed(WRITE, &msg.msg_iter, req->imu,
                                        (u64)(uintptr_t)zc->buf, zc->len);
                if (unlikely(ret))
-                               return ret;
+                       return ret;
        } else {
                ret = import_single_range(WRITE, zc->buf, zc->len, &iov,
                                          &msg.msg_iter);
@@ -1013,16 +1051,18 @@ int io_sendzc(struct io_kiocb *req, unsigned int issue_flags)
 
        if (unlikely(ret < min_ret)) {
                if (ret == -EAGAIN && (issue_flags & IO_URING_F_NONBLOCK))
-                       return -EAGAIN;
+                       return io_setup_async_addr(req, addr, issue_flags);
+
                if (ret > 0 && io_net_retry(sock, msg.msg_flags)) {
                        zc->len -= ret;
                        zc->buf += ret;
                        zc->done_io += ret;
                        req->flags |= REQ_F_PARTIAL_IO;
-                       return -EAGAIN;
+                       return io_setup_async_addr(req, addr, issue_flags);
                }
                if (ret == -ERESTARTSYS)
                        ret = -EINTR;
+               req_set_fail(req);
        } else if (zc->flags & IORING_RECVSEND_NOTIF_FLUSH) {
                io_notif_slot_flush_submit(notif_slot, 0);
        }
index 7c438d3..f91f56c 100644 (file)
@@ -31,6 +31,7 @@ struct io_async_connect {
 int io_shutdown_prep(struct io_kiocb *req, const struct io_uring_sqe *sqe);
 int io_shutdown(struct io_kiocb *req, unsigned int issue_flags);
 
+int io_sendzc_prep_async(struct io_kiocb *req);
 int io_sendmsg_prep_async(struct io_kiocb *req);
 void io_sendmsg_recvmsg_cleanup(struct io_kiocb *req);
 int io_sendmsg_prep(struct io_kiocb *req, const struct io_uring_sqe *sqe);
index 977736e..96f076b 100644 (file)
@@ -73,7 +73,7 @@ struct io_kiocb *io_alloc_notif(struct io_ring_ctx *ctx,
 }
 
 void io_notif_slot_flush(struct io_notif_slot *slot)
-       __must_hold(&ctx->uring_lock)
+       __must_hold(&slot->notif->ctx->uring_lock)
 {
        struct io_kiocb *notif = slot->notif;
        struct io_notif_data *nd = io_notif_to_data(notif);
@@ -81,8 +81,10 @@ void io_notif_slot_flush(struct io_notif_slot *slot)
        slot->notif = NULL;
 
        /* drop slot's master ref */
-       if (refcount_dec_and_test(&nd->uarg.refcnt))
-               io_notif_complete(notif);
+       if (refcount_dec_and_test(&nd->uarg.refcnt)) {
+               notif->io_task_work.func = __io_notif_complete_tw;
+               io_req_task_work_add(notif);
+       }
 }
 
 __cold int io_notif_unregister(struct io_ring_ctx *ctx)
index 72dd2b2..4141012 100644 (file)
@@ -478,13 +478,15 @@ const struct io_op_def io_op_defs[] = {
                .pollout                = 1,
                .audit_skip             = 1,
                .ioprio                 = 1,
+               .manual_alloc           = 1,
 #if defined(CONFIG_NET)
+               .async_size             = sizeof(struct io_async_msghdr),
                .prep                   = io_sendzc_prep,
                .issue                  = io_sendzc,
+               .prep_async             = io_sendzc_prep_async,
 #else
                .prep                   = io_eopnotsupp_prep,
 #endif
-
        },
 };
 
index ece8ed4..763c6e5 100644 (file)
@@ -25,6 +25,8 @@ struct io_op_def {
        unsigned                ioprio : 1;
        /* supports iopoll */
        unsigned                iopoll : 1;
+       /* opcode specific path will handle ->async_data allocation if needed */
+       unsigned                manual_alloc : 1;
        /* size of async data needed, if any */
        unsigned short          async_size;
 
index 8e0cc2d..e78b6f9 100644 (file)
@@ -3,6 +3,7 @@
 #include <linux/errno.h>
 #include <linux/file.h>
 #include <linux/io_uring.h>
+#include <linux/security.h>
 
 #include <uapi/linux/io_uring.h>
 
@@ -88,6 +89,10 @@ int io_uring_cmd(struct io_kiocb *req, unsigned int issue_flags)
        if (!req->file->f_op->uring_cmd)
                return -EOPNOTSUPP;
 
+       ret = security_uring_cmd(ioucmd);
+       if (ret)
+               return ret;
+
        if (ctx->flags & IORING_SETUP_SQE128)
                issue_flags |= IO_URING_F_SQE128;
        if (ctx->flags & IORING_SETUP_CQE32)
@@ -112,7 +117,7 @@ int io_uring_cmd(struct io_kiocb *req, unsigned int issue_flags)
                if (ret < 0)
                        req_set_fail(req);
                io_req_set_res(req, ret, 0);
-               return IOU_OK;
+               return ret;
        }
 
        return IOU_ISSUE_SKIP_COMPLETE;
index 6432a37..c565fbf 100644 (file)
@@ -102,6 +102,7 @@ struct audit_fsnotify_mark *audit_alloc_mark(struct audit_krule *krule, char *pa
 
        ret = fsnotify_add_inode_mark(&audit_mark->mark, inode, 0);
        if (ret < 0) {
+               audit_mark->path = NULL;
                fsnotify_put_mark(&audit_mark->mark);
                audit_mark = ERR_PTR(ret);
        }
index dd8d9ab..79a5da1 100644 (file)
@@ -1940,6 +1940,7 @@ void __audit_uring_exit(int success, long code)
                goto out;
        }
 
+       audit_return_fixup(ctx, success, code);
        if (ctx->context == AUDIT_CTX_SYSCALL) {
                /*
                 * NOTE: See the note in __audit_uring_entry() about the case
@@ -1981,7 +1982,6 @@ void __audit_uring_exit(int success, long code)
        audit_filter_inodes(current, ctx);
        if (ctx->current_state != AUDIT_STATE_RECORD)
                goto out;
-       audit_return_fixup(ctx, success, code);
        audit_log_exit();
 
 out:
@@ -2065,13 +2065,13 @@ void __audit_syscall_exit(int success, long return_code)
        if (!list_empty(&context->killed_trees))
                audit_kill_trees(context);
 
+       audit_return_fixup(context, success, return_code);
        /* run through both filters to ensure we set the filterkey properly */
        audit_filter_syscall(current, context);
        audit_filter_inodes(current, context);
        if (context->current_state < AUDIT_STATE_RECORD)
                goto out;
 
-       audit_return_fixup(context, success, return_code);
        audit_log_exit();
 
 out:
index 2ade21b..ff6a809 100644 (file)
@@ -59,6 +59,7 @@ int cgroup_attach_task_all(struct task_struct *from, struct task_struct *tsk)
        int retval = 0;
 
        mutex_lock(&cgroup_mutex);
+       cpus_read_lock();
        percpu_down_write(&cgroup_threadgroup_rwsem);
        for_each_root(root) {
                struct cgroup *from_cgrp;
@@ -72,6 +73,7 @@ int cgroup_attach_task_all(struct task_struct *from, struct task_struct *tsk)
                        break;
        }
        percpu_up_write(&cgroup_threadgroup_rwsem);
+       cpus_read_unlock();
        mutex_unlock(&cgroup_mutex);
 
        return retval;
index ffaccd6..e4bb5d5 100644 (file)
@@ -1820,6 +1820,7 @@ int rebind_subsystems(struct cgroup_root *dst_root, u16 ss_mask)
 
                if (ss->css_rstat_flush) {
                        list_del_rcu(&css->rstat_css_node);
+                       synchronize_rcu();
                        list_add_rcu(&css->rstat_css_node,
                                     &dcgrp->rstat_css_list);
                }
@@ -2370,6 +2371,47 @@ int task_cgroup_path(struct task_struct *task, char *buf, size_t buflen)
 EXPORT_SYMBOL_GPL(task_cgroup_path);
 
 /**
+ * cgroup_attach_lock - Lock for ->attach()
+ * @lock_threadgroup: whether to down_write cgroup_threadgroup_rwsem
+ *
+ * cgroup migration sometimes needs to stabilize threadgroups against forks and
+ * exits by write-locking cgroup_threadgroup_rwsem. However, some ->attach()
+ * implementations (e.g. cpuset), also need to disable CPU hotplug.
+ * Unfortunately, letting ->attach() operations acquire cpus_read_lock() can
+ * lead to deadlocks.
+ *
+ * Bringing up a CPU may involve creating and destroying tasks which requires
+ * read-locking threadgroup_rwsem, so threadgroup_rwsem nests inside
+ * cpus_read_lock(). If we call an ->attach() which acquires the cpus lock while
+ * write-locking threadgroup_rwsem, the locking order is reversed and we end up
+ * waiting for an on-going CPU hotplug operation which in turn is waiting for
+ * the threadgroup_rwsem to be released to create new tasks. For more details:
+ *
+ *   http://lkml.kernel.org/r/20220711174629.uehfmqegcwn2lqzu@wubuntu
+ *
+ * Resolve the situation by always acquiring cpus_read_lock() before optionally
+ * write-locking cgroup_threadgroup_rwsem. This allows ->attach() to assume that
+ * CPU hotplug is disabled on entry.
+ */
+static void cgroup_attach_lock(bool lock_threadgroup)
+{
+       cpus_read_lock();
+       if (lock_threadgroup)
+               percpu_down_write(&cgroup_threadgroup_rwsem);
+}
+
+/**
+ * cgroup_attach_unlock - Undo cgroup_attach_lock()
+ * @lock_threadgroup: whether to up_write cgroup_threadgroup_rwsem
+ */
+static void cgroup_attach_unlock(bool lock_threadgroup)
+{
+       if (lock_threadgroup)
+               percpu_up_write(&cgroup_threadgroup_rwsem);
+       cpus_read_unlock();
+}
+
+/**
  * cgroup_migrate_add_task - add a migration target task to a migration context
  * @task: target task
  * @mgctx: target migration context
@@ -2841,8 +2883,7 @@ int cgroup_attach_task(struct cgroup *dst_cgrp, struct task_struct *leader,
 }
 
 struct task_struct *cgroup_procs_write_start(char *buf, bool threadgroup,
-                                            bool *locked)
-       __acquires(&cgroup_threadgroup_rwsem)
+                                            bool *threadgroup_locked)
 {
        struct task_struct *tsk;
        pid_t pid;
@@ -2859,12 +2900,8 @@ struct task_struct *cgroup_procs_write_start(char *buf, bool threadgroup,
         * Therefore, we can skip the global lock.
         */
        lockdep_assert_held(&cgroup_mutex);
-       if (pid || threadgroup) {
-               percpu_down_write(&cgroup_threadgroup_rwsem);
-               *locked = true;
-       } else {
-               *locked = false;
-       }
+       *threadgroup_locked = pid || threadgroup;
+       cgroup_attach_lock(*threadgroup_locked);
 
        rcu_read_lock();
        if (pid) {
@@ -2895,17 +2932,14 @@ struct task_struct *cgroup_procs_write_start(char *buf, bool threadgroup,
        goto out_unlock_rcu;
 
 out_unlock_threadgroup:
-       if (*locked) {
-               percpu_up_write(&cgroup_threadgroup_rwsem);
-               *locked = false;
-       }
+       cgroup_attach_unlock(*threadgroup_locked);
+       *threadgroup_locked = false;
 out_unlock_rcu:
        rcu_read_unlock();
        return tsk;
 }
 
-void cgroup_procs_write_finish(struct task_struct *task, bool locked)
-       __releases(&cgroup_threadgroup_rwsem)
+void cgroup_procs_write_finish(struct task_struct *task, bool threadgroup_locked)
 {
        struct cgroup_subsys *ss;
        int ssid;
@@ -2913,8 +2947,8 @@ void cgroup_procs_write_finish(struct task_struct *task, bool locked)
        /* release reference from cgroup_procs_write_start() */
        put_task_struct(task);
 
-       if (locked)
-               percpu_up_write(&cgroup_threadgroup_rwsem);
+       cgroup_attach_unlock(threadgroup_locked);
+
        for_each_subsys(ss, ssid)
                if (ss->post_attach)
                        ss->post_attach();
@@ -3000,8 +3034,7 @@ static int cgroup_update_dfl_csses(struct cgroup *cgrp)
         * write-locking can be skipped safely.
         */
        has_tasks = !list_empty(&mgctx.preloaded_src_csets);
-       if (has_tasks)
-               percpu_down_write(&cgroup_threadgroup_rwsem);
+       cgroup_attach_lock(has_tasks);
 
        /* NULL dst indicates self on default hierarchy */
        ret = cgroup_migrate_prepare_dst(&mgctx);
@@ -3022,8 +3055,7 @@ static int cgroup_update_dfl_csses(struct cgroup *cgrp)
        ret = cgroup_migrate_execute(&mgctx);
 out_finish:
        cgroup_migrate_finish(&mgctx);
-       if (has_tasks)
-               percpu_up_write(&cgroup_threadgroup_rwsem);
+       cgroup_attach_unlock(has_tasks);
        return ret;
 }
 
@@ -3698,7 +3730,7 @@ static ssize_t cgroup_pressure_write(struct kernfs_open_file *of, char *buf,
        }
 
        psi = cgroup_ino(cgrp) == 1 ? &psi_system : cgrp->psi;
-       new = psi_trigger_create(psi, buf, nbytes, res);
+       new = psi_trigger_create(psi, buf, res);
        if (IS_ERR(new)) {
                cgroup_put(cgrp);
                return PTR_ERR(new);
@@ -4971,13 +5003,13 @@ static ssize_t __cgroup_procs_write(struct kernfs_open_file *of, char *buf,
        struct task_struct *task;
        const struct cred *saved_cred;
        ssize_t ret;
-       bool locked;
+       bool threadgroup_locked;
 
        dst_cgrp = cgroup_kn_lock_live(of->kn, false);
        if (!dst_cgrp)
                return -ENODEV;
 
-       task = cgroup_procs_write_start(buf, threadgroup, &locked);
+       task = cgroup_procs_write_start(buf, threadgroup, &threadgroup_locked);
        ret = PTR_ERR_OR_ZERO(task);
        if (ret)
                goto out_unlock;
@@ -5003,7 +5035,7 @@ static ssize_t __cgroup_procs_write(struct kernfs_open_file *of, char *buf,
        ret = cgroup_attach_task(dst_cgrp, task, threadgroup);
 
 out_finish:
-       cgroup_procs_write_finish(task, locked);
+       cgroup_procs_write_finish(task, threadgroup_locked);
 out_unlock:
        cgroup_kn_unlock(of->kn);
 
index 58aadfd..1f3a552 100644 (file)
@@ -2289,7 +2289,7 @@ static void cpuset_attach(struct cgroup_taskset *tset)
        cgroup_taskset_first(tset, &css);
        cs = css_cs(css);
 
-       cpus_read_lock();
+       lockdep_assert_cpus_held();     /* see cgroup_attach_lock() */
        percpu_down_write(&cpuset_rwsem);
 
        guarantee_online_mems(cs, &cpuset_attach_nodemask_to);
@@ -2343,7 +2343,6 @@ static void cpuset_attach(struct cgroup_taskset *tset)
                wake_up(&cpuset_attach_wq);
 
        percpu_up_write(&cpuset_rwsem);
-       cpus_read_unlock();
 }
 
 /* The various types of files and directories in a cpuset file system */
index 07b26df..a0eb4d5 100644 (file)
@@ -494,6 +494,7 @@ static int __init crash_save_vmcoreinfo_init(void)
 
 #ifdef CONFIG_KALLSYMS
        VMCOREINFO_SYMBOL(kallsyms_names);
+       VMCOREINFO_SYMBOL(kallsyms_num_syms);
        VMCOREINFO_SYMBOL(kallsyms_token_table);
        VMCOREINFO_SYMBOL(kallsyms_token_index);
 #ifdef CONFIG_KALLSYMS_BASE_RELATIVE
index 80697e5..08350e3 100644 (file)
@@ -1707,11 +1707,12 @@ static struct kprobe *__disable_kprobe(struct kprobe *p)
                /* Try to disarm and disable this/parent probe */
                if (p == orig_p || aggr_kprobe_disabled(orig_p)) {
                        /*
-                        * If 'kprobes_all_disarmed' is set, 'orig_p'
-                        * should have already been disarmed, so
-                        * skip unneed disarming process.
+                        * Don't be lazy here.  Even if 'kprobes_all_disarmed'
+                        * is false, 'orig_p' might not have been armed yet.
+                        * Note arm_all_kprobes() __tries__ to arm all kprobes
+                        * on the best effort basis.
                         */
-                       if (!kprobes_all_disarmed) {
+                       if (!kprobes_all_disarmed && !kprobe_disabled(orig_p)) {
                                ret = disarm_kprobe(orig_p, true);
                                if (ret) {
                                        p->flags &= ~KPROBE_FLAG_DISABLED;
index 6a477c6..a4e4d84 100644 (file)
@@ -2099,7 +2099,7 @@ static int find_module_sections(struct module *mod, struct load_info *info)
                                              sizeof(*mod->static_call_sites),
                                              &mod->num_static_call_sites);
 #endif
-#ifdef CONFIG_KUNIT
+#if IS_ENABLED(CONFIG_KUNIT)
        mod->kunit_suites = section_objs(info, ".kunit_test_suites",
                                              sizeof(*mod->kunit_suites),
                                              &mod->num_kunit_suites);
index ec66b40..ecb4b4f 100644 (file)
@@ -190,12 +190,8 @@ static void group_init(struct psi_group *group)
        /* Init trigger-related members */
        mutex_init(&group->trigger_lock);
        INIT_LIST_HEAD(&group->triggers);
-       memset(group->nr_triggers, 0, sizeof(group->nr_triggers));
-       group->poll_states = 0;
        group->poll_min_period = U32_MAX;
-       memset(group->polling_total, 0, sizeof(group->polling_total));
        group->polling_next_update = ULLONG_MAX;
-       group->polling_until = 0;
        init_waitqueue_head(&group->poll_wait);
        timer_setup(&group->poll_timer, poll_timer_fn, 0);
        rcu_assign_pointer(group->poll_task, NULL);
@@ -957,7 +953,7 @@ int psi_cgroup_alloc(struct cgroup *cgroup)
        if (static_branch_likely(&psi_disabled))
                return 0;
 
-       cgroup->psi = kmalloc(sizeof(struct psi_group), GFP_KERNEL);
+       cgroup->psi = kzalloc(sizeof(struct psi_group), GFP_KERNEL);
        if (!cgroup->psi)
                return -ENOMEM;
 
@@ -1091,7 +1087,7 @@ int psi_show(struct seq_file *m, struct psi_group *group, enum psi_res res)
 }
 
 struct psi_trigger *psi_trigger_create(struct psi_group *group,
-                       char *buf, size_t nbytes, enum psi_res res)
+                       char *buf, enum psi_res res)
 {
        struct psi_trigger *t;
        enum psi_states state;
@@ -1320,7 +1316,7 @@ static ssize_t psi_write(struct file *file, const char __user *user_buf,
                return -EBUSY;
        }
 
-       new = psi_trigger_create(&psi_system, buf, nbytes, res);
+       new = psi_trigger_create(&psi_system, buf, res);
        if (IS_ERR(new)) {
                mutex_unlock(&seq->lock);
                return PTR_ERR(new);
index d4788f8..0b1cd98 100644 (file)
@@ -47,7 +47,7 @@ __wait_on_bit(struct wait_queue_head *wq_head, struct wait_bit_queue_entry *wbq_
                prepare_to_wait(wq_head, &wbq_entry->wq_entry, mode);
                if (test_bit(wbq_entry->key.bit_nr, wbq_entry->key.flags))
                        ret = (*action)(&wbq_entry->key, mode);
-       } while (test_bit(wbq_entry->key.bit_nr, wbq_entry->key.flags) && !ret);
+       } while (test_bit_acquire(wbq_entry->key.bit_nr, wbq_entry->key.flags) && !ret);
 
        finish_wait(wq_head, &wbq_entry->wq_entry);
 
index a492f15..860b2dc 100644 (file)
@@ -277,6 +277,7 @@ COND_SYSCALL(landlock_restrict_self);
 
 /* mm/fadvise.c */
 COND_SYSCALL(fadvise64_64);
+COND_SYSCALL_COMPAT(fadvise64_64);
 
 /* mm/, CONFIG_MMU only */
 COND_SYSCALL(swapon);
index 126c769..439e2ab 100644 (file)
@@ -1861,8 +1861,6 @@ static void ftrace_hash_rec_enable_modify(struct ftrace_ops *ops,
        ftrace_hash_rec_update_modify(ops, filter_hash, 1);
 }
 
-static bool ops_references_ip(struct ftrace_ops *ops, unsigned long ip);
-
 /*
  * Try to update IPMODIFY flag on each ftrace_rec. Return 0 if it is OK
  * or no-needed to update, -EBUSY if it detects a conflict of the flag
@@ -3118,49 +3116,6 @@ static inline int ops_traces_mod(struct ftrace_ops *ops)
                ftrace_hash_empty(ops->func_hash->notrace_hash);
 }
 
-/*
- * Check if the current ops references the given ip.
- *
- * If the ops traces all functions, then it was already accounted for.
- * If the ops does not trace the current record function, skip it.
- * If the ops ignores the function via notrace filter, skip it.
- */
-static bool
-ops_references_ip(struct ftrace_ops *ops, unsigned long ip)
-{
-       /* If ops isn't enabled, ignore it */
-       if (!(ops->flags & FTRACE_OPS_FL_ENABLED))
-               return false;
-
-       /* If ops traces all then it includes this function */
-       if (ops_traces_mod(ops))
-               return true;
-
-       /* The function must be in the filter */
-       if (!ftrace_hash_empty(ops->func_hash->filter_hash) &&
-           !__ftrace_lookup_ip(ops->func_hash->filter_hash, ip))
-               return false;
-
-       /* If in notrace hash, we ignore it too */
-       if (ftrace_lookup_ip(ops->func_hash->notrace_hash, ip))
-               return false;
-
-       return true;
-}
-
-/*
- * Check if the current ops references the record.
- *
- * If the ops traces all functions, then it was already accounted for.
- * If the ops does not trace the current record function, skip it.
- * If the ops ignores the function via notrace filter, skip it.
- */
-static bool
-ops_references_rec(struct ftrace_ops *ops, struct dyn_ftrace *rec)
-{
-       return ops_references_ip(ops, rec->ip);
-}
-
 static int ftrace_update_code(struct module *mod, struct ftrace_page *new_pgs)
 {
        bool init_nop = ftrace_need_init_nop();
@@ -6822,6 +6777,38 @@ static int ftrace_get_trampoline_kallsym(unsigned int symnum,
        return -ERANGE;
 }
 
+#if defined(CONFIG_DYNAMIC_FTRACE_WITH_DIRECT_CALLS) || defined(CONFIG_MODULES)
+/*
+ * Check if the current ops references the given ip.
+ *
+ * If the ops traces all functions, then it was already accounted for.
+ * If the ops does not trace the current record function, skip it.
+ * If the ops ignores the function via notrace filter, skip it.
+ */
+static bool
+ops_references_ip(struct ftrace_ops *ops, unsigned long ip)
+{
+       /* If ops isn't enabled, ignore it */
+       if (!(ops->flags & FTRACE_OPS_FL_ENABLED))
+               return false;
+
+       /* If ops traces all then it includes this function */
+       if (ops_traces_mod(ops))
+               return true;
+
+       /* The function must be in the filter */
+       if (!ftrace_hash_empty(ops->func_hash->filter_hash) &&
+           !__ftrace_lookup_ip(ops->func_hash->filter_hash, ip))
+               return false;
+
+       /* If in notrace hash, we ignore it too */
+       if (ftrace_lookup_ip(ops->func_hash->notrace_hash, ip))
+               return false;
+
+       return true;
+}
+#endif
+
 #ifdef CONFIG_MODULES
 
 #define next_to_ftrace_page(p) container_of(p, struct ftrace_page, next)
@@ -6834,7 +6821,7 @@ static int referenced_filters(struct dyn_ftrace *rec)
        int cnt = 0;
 
        for (ops = ftrace_ops_list; ops != &ftrace_list_end; ops = ops->next) {
-               if (ops_references_rec(ops, rec)) {
+               if (ops_references_ip(ops, rec->ip)) {
                        if (WARN_ON_ONCE(ops->flags & FTRACE_OPS_FL_DIRECT))
                                continue;
                        if (WARN_ON_ONCE(ops->flags & FTRACE_OPS_FL_IPMODIFY))
index 072e4b2..bcbe60d 100644 (file)
@@ -2029,13 +2029,16 @@ config LKDTM
        Documentation on how to use the module can be found in
        Documentation/fault-injection/provoke-crashes.rst
 
-config TEST_CPUMASK
-       tristate "cpumask tests" if !KUNIT_ALL_TESTS
+config CPUMASK_KUNIT_TEST
+       tristate "KUnit test for cpumask" if !KUNIT_ALL_TESTS
        depends on KUNIT
        default KUNIT_ALL_TESTS
        help
          Enable to turn on cpumask tests, running at boot or module load time.
 
+         For more information on KUnit and unit tests in general, please refer
+         to the KUnit documentation in Documentation/dev-tools/kunit/.
+
          If unsure, say N.
 
 config TEST_LIST_SORT
index 5927d7f..ffabc30 100644 (file)
@@ -60,6 +60,7 @@ obj-$(CONFIG_TEST_BPF) += test_bpf.o
 obj-$(CONFIG_TEST_FIRMWARE) += test_firmware.o
 obj-$(CONFIG_TEST_BITOPS) += test_bitops.o
 CFLAGS_test_bitops.o += -Werror
+obj-$(CONFIG_CPUMASK_KUNIT_TEST) += cpumask_kunit.o
 obj-$(CONFIG_TEST_SYSCTL) += test_sysctl.o
 obj-$(CONFIG_TEST_SIPHASH) += test_siphash.o
 obj-$(CONFIG_HASH_KUNIT_TEST) += test_hash.o
@@ -100,7 +101,6 @@ obj-$(CONFIG_TEST_HMM) += test_hmm.o
 obj-$(CONFIG_TEST_FREE_PAGES) += test_free_pages.o
 obj-$(CONFIG_KPROBES_SANITY_TEST) += test_kprobes.o
 obj-$(CONFIG_TEST_REF_TRACKER) += test_ref_tracker.o
-obj-$(CONFIG_TEST_CPUMASK) += test_cpumask.o
 CFLAGS_test_fprobe.o += $(CC_FLAGS_FTRACE)
 obj-$(CONFIG_FPROBE_SANITY_TEST) += test_fprobe.o
 #
similarity index 58%
rename from lib/test_cpumask.c
rename to lib/cpumask_kunit.c
index a31a162..ecbeec7 100644 (file)
@@ -9,6 +9,10 @@
 #include <linux/cpu.h>
 #include <linux/cpumask.h>
 
+#define MASK_MSG(m) \
+       "%s contains %sCPUs %*pbl", #m, (cpumask_weight(m) ? "" : "no "), \
+       nr_cpumask_bits, cpumask_bits(m)
+
 #define EXPECT_FOR_EACH_CPU_EQ(test, mask)                     \
        do {                                                    \
                const cpumask_t *m = (mask);                    \
@@ -16,7 +20,7 @@
                int cpu, iter = 0;                              \
                for_each_cpu(cpu, m)                            \
                        iter++;                                 \
-               KUNIT_EXPECT_EQ((test), mask_weight, iter);     \
+               KUNIT_EXPECT_EQ_MSG((test), mask_weight, iter, MASK_MSG(mask)); \
        } while (0)
 
 #define EXPECT_FOR_EACH_CPU_NOT_EQ(test, mask)                                 \
@@ -26,7 +30,7 @@
                int cpu, iter = 0;                                              \
                for_each_cpu_not(cpu, m)                                        \
                        iter++;                                                 \
-               KUNIT_EXPECT_EQ((test), nr_cpu_ids - mask_weight, iter);        \
+               KUNIT_EXPECT_EQ_MSG((test), nr_cpu_ids - mask_weight, iter, MASK_MSG(mask));    \
        } while (0)
 
 #define EXPECT_FOR_EACH_CPU_WRAP_EQ(test, mask)                        \
@@ -36,7 +40,7 @@
                int cpu, iter = 0;                              \
                for_each_cpu_wrap(cpu, m, nr_cpu_ids / 2)       \
                        iter++;                                 \
-               KUNIT_EXPECT_EQ((test), mask_weight, iter);     \
+               KUNIT_EXPECT_EQ_MSG((test), mask_weight, iter, MASK_MSG(mask)); \
        } while (0)
 
 #define EXPECT_FOR_EACH_CPU_BUILTIN_EQ(test, name)             \
@@ -45,7 +49,7 @@
                int cpu, iter = 0;                              \
                for_each_##name##_cpu(cpu)                      \
                        iter++;                                 \
-               KUNIT_EXPECT_EQ((test), mask_weight, iter);     \
+               KUNIT_EXPECT_EQ_MSG((test), mask_weight, iter, MASK_MSG(cpu_##name##_mask));    \
        } while (0)
 
 static cpumask_t mask_empty;
@@ -53,37 +57,43 @@ static cpumask_t mask_all;
 
 static void test_cpumask_weight(struct kunit *test)
 {
-       KUNIT_EXPECT_TRUE(test, cpumask_empty(&mask_empty));
-       KUNIT_EXPECT_TRUE(test, cpumask_full(cpu_possible_mask));
-       KUNIT_EXPECT_TRUE(test, cpumask_full(&mask_all));
+       KUNIT_EXPECT_TRUE_MSG(test, cpumask_empty(&mask_empty), MASK_MSG(&mask_empty));
+       KUNIT_EXPECT_TRUE_MSG(test, cpumask_full(&mask_all), MASK_MSG(&mask_all));
 
-       KUNIT_EXPECT_EQ(test, 0, cpumask_weight(&mask_empty));
-       KUNIT_EXPECT_EQ(test, nr_cpu_ids, cpumask_weight(cpu_possible_mask));
-       KUNIT_EXPECT_EQ(test, nr_cpumask_bits, cpumask_weight(&mask_all));
+       KUNIT_EXPECT_EQ_MSG(test, 0, cpumask_weight(&mask_empty), MASK_MSG(&mask_empty));
+       KUNIT_EXPECT_EQ_MSG(test, nr_cpu_ids, cpumask_weight(cpu_possible_mask),
+                           MASK_MSG(cpu_possible_mask));
+       KUNIT_EXPECT_EQ_MSG(test, nr_cpumask_bits, cpumask_weight(&mask_all), MASK_MSG(&mask_all));
 }
 
 static void test_cpumask_first(struct kunit *test)
 {
-       KUNIT_EXPECT_LE(test, nr_cpu_ids, cpumask_first(&mask_empty));
-       KUNIT_EXPECT_EQ(test, 0, cpumask_first(cpu_possible_mask));
+       KUNIT_EXPECT_LE_MSG(test, nr_cpu_ids, cpumask_first(&mask_empty), MASK_MSG(&mask_empty));
+       KUNIT_EXPECT_EQ_MSG(test, 0, cpumask_first(cpu_possible_mask), MASK_MSG(cpu_possible_mask));
 
-       KUNIT_EXPECT_EQ(test, 0, cpumask_first_zero(&mask_empty));
-       KUNIT_EXPECT_LE(test, nr_cpu_ids, cpumask_first_zero(cpu_possible_mask));
+       KUNIT_EXPECT_EQ_MSG(test, 0, cpumask_first_zero(&mask_empty), MASK_MSG(&mask_empty));
+       KUNIT_EXPECT_LE_MSG(test, nr_cpu_ids, cpumask_first_zero(cpu_possible_mask),
+                           MASK_MSG(cpu_possible_mask));
 }
 
 static void test_cpumask_last(struct kunit *test)
 {
-       KUNIT_EXPECT_LE(test, nr_cpumask_bits, cpumask_last(&mask_empty));
-       KUNIT_EXPECT_EQ(test, nr_cpumask_bits - 1, cpumask_last(cpu_possible_mask));
+       KUNIT_EXPECT_LE_MSG(test, nr_cpumask_bits, cpumask_last(&mask_empty),
+                           MASK_MSG(&mask_empty));
+       KUNIT_EXPECT_EQ_MSG(test, nr_cpu_ids - 1, cpumask_last(cpu_possible_mask),
+                           MASK_MSG(cpu_possible_mask));
 }
 
 static void test_cpumask_next(struct kunit *test)
 {
-       KUNIT_EXPECT_EQ(test, 0, cpumask_next_zero(-1, &mask_empty));
-       KUNIT_EXPECT_LE(test, nr_cpu_ids, cpumask_next_zero(-1, cpu_possible_mask));
-
-       KUNIT_EXPECT_LE(test, nr_cpu_ids, cpumask_next(-1, &mask_empty));
-       KUNIT_EXPECT_EQ(test, 0, cpumask_next(-1, cpu_possible_mask));
+       KUNIT_EXPECT_EQ_MSG(test, 0, cpumask_next_zero(-1, &mask_empty), MASK_MSG(&mask_empty));
+       KUNIT_EXPECT_LE_MSG(test, nr_cpu_ids, cpumask_next_zero(-1, cpu_possible_mask),
+                           MASK_MSG(cpu_possible_mask));
+
+       KUNIT_EXPECT_LE_MSG(test, nr_cpu_ids, cpumask_next(-1, &mask_empty),
+                           MASK_MSG(&mask_empty));
+       KUNIT_EXPECT_EQ_MSG(test, 0, cpumask_next(-1, cpu_possible_mask),
+                           MASK_MSG(cpu_possible_mask));
 }
 
 static void test_cpumask_iterators(struct kunit *test)
index 9ff549f..47816af 100644 (file)
@@ -33,7 +33,6 @@ config CRYPTO_ARCH_HAVE_LIB_CHACHA
 
 config CRYPTO_LIB_CHACHA_GENERIC
        tristate
-       select XOR_BLOCKS
        help
          This symbol can be depended upon by arch implementations of the
          ChaCha library interface that require the generic code as a
index e01a93f..ce945c1 100644 (file)
  */
 int ___ratelimit(struct ratelimit_state *rs, const char *func)
 {
+       /* Paired with WRITE_ONCE() in .proc_handler().
+        * Changing two values seperately could be inconsistent
+        * and some message could be lost.  (See: net_ratelimit_state).
+        */
+       int interval = READ_ONCE(rs->interval);
+       int burst = READ_ONCE(rs->burst);
        unsigned long flags;
        int ret;
 
-       if (!rs->interval)
+       if (!interval)
                return 1;
 
        /*
@@ -44,7 +50,7 @@ int ___ratelimit(struct ratelimit_state *rs, const char *func)
        if (!rs->begin)
                rs->begin = jiffies;
 
-       if (time_is_before_jiffies(rs->begin + rs->interval)) {
+       if (time_is_before_jiffies(rs->begin + interval)) {
                if (rs->missed) {
                        if (!(rs->flags & RATELIMIT_MSG_ON_RELEASE)) {
                                printk_deferred(KERN_WARNING
@@ -56,7 +62,7 @@ int ___ratelimit(struct ratelimit_state *rs, const char *func)
                rs->begin   = jiffies;
                rs->printed = 0;
        }
-       if (rs->burst && rs->burst > rs->printed) {
+       if (burst && burst > rs->printed) {
                rs->printed++;
                ret = 1;
        } else {
index 95550b8..de65cb1 100644 (file)
@@ -260,10 +260,10 @@ void wb_wakeup_delayed(struct bdi_writeback *wb)
        unsigned long timeout;
 
        timeout = msecs_to_jiffies(dirty_writeback_interval * 10);
-       spin_lock_bh(&wb->work_lock);
+       spin_lock_irq(&wb->work_lock);
        if (test_bit(WB_registered, &wb->state))
                queue_delayed_work(bdi_wq, &wb->dwork, timeout);
-       spin_unlock_bh(&wb->work_lock);
+       spin_unlock_irq(&wb->work_lock);
 }
 
 static void wb_update_bandwidth_workfn(struct work_struct *work)
@@ -334,12 +334,12 @@ static void cgwb_remove_from_bdi_list(struct bdi_writeback *wb);
 static void wb_shutdown(struct bdi_writeback *wb)
 {
        /* Make sure nobody queues further work */
-       spin_lock_bh(&wb->work_lock);
+       spin_lock_irq(&wb->work_lock);
        if (!test_and_clear_bit(WB_registered, &wb->state)) {
-               spin_unlock_bh(&wb->work_lock);
+               spin_unlock_irq(&wb->work_lock);
                return;
        }
-       spin_unlock_bh(&wb->work_lock);
+       spin_unlock_irq(&wb->work_lock);
 
        cgwb_remove_from_bdi_list(wb);
        /*
index f18a631..b1efebf 100644 (file)
@@ -12,6 +12,7 @@
 #include <linux/memblock.h>
 #include <linux/bootmem_info.h>
 #include <linux/memory_hotplug.h>
+#include <linux/kmemleak.h>
 
 void get_page_bootmem(unsigned long info, struct page *page, unsigned long type)
 {
@@ -33,6 +34,7 @@ void put_page_bootmem(struct page *page)
                ClearPagePrivate(page);
                set_page_private(page, 0);
                INIT_LIST_HEAD(&page->lru);
+               kmemleak_free_part(page_to_virt(page), PAGE_SIZE);
                free_reserved_page(page);
        }
 }
index cb8a7e9..cfdf631 100644 (file)
@@ -818,6 +818,9 @@ static int dbgfs_mk_context(char *name)
                return -ENOENT;
 
        new_dir = debugfs_create_dir(name, root);
+       /* Below check is required for a potential duplicated name case */
+       if (IS_ERR(new_dir))
+               return PTR_ERR(new_dir);
        dbgfs_dirs[dbgfs_nr_ctxs] = new_dir;
 
        new_ctx = dbgfs_new_ctx();
index 7328251..5abdaf4 100644 (file)
--- a/mm/gup.c
+++ b/mm/gup.c
@@ -478,14 +478,42 @@ static int follow_pfn_pte(struct vm_area_struct *vma, unsigned long address,
        return -EEXIST;
 }
 
-/*
- * FOLL_FORCE can write to even unwritable pte's, but only
- * after we've gone through a COW cycle and they are dirty.
- */
-static inline bool can_follow_write_pte(pte_t pte, unsigned int flags)
+/* FOLL_FORCE can write to even unwritable PTEs in COW mappings. */
+static inline bool can_follow_write_pte(pte_t pte, struct page *page,
+                                       struct vm_area_struct *vma,
+                                       unsigned int flags)
 {
-       return pte_write(pte) ||
-               ((flags & FOLL_FORCE) && (flags & FOLL_COW) && pte_dirty(pte));
+       /* If the pte is writable, we can write to the page. */
+       if (pte_write(pte))
+               return true;
+
+       /* Maybe FOLL_FORCE is set to override it? */
+       if (!(flags & FOLL_FORCE))
+               return false;
+
+       /* But FOLL_FORCE has no effect on shared mappings */
+       if (vma->vm_flags & (VM_MAYSHARE | VM_SHARED))
+               return false;
+
+       /* ... or read-only private ones */
+       if (!(vma->vm_flags & VM_MAYWRITE))
+               return false;
+
+       /* ... or already writable ones that just need to take a write fault */
+       if (vma->vm_flags & VM_WRITE)
+               return false;
+
+       /*
+        * See can_change_pte_writable(): we broke COW and could map the page
+        * writable if we have an exclusive anonymous page ...
+        */
+       if (!page || !PageAnon(page) || !PageAnonExclusive(page))
+               return false;
+
+       /* ... and a write-fault isn't required for other reasons. */
+       if (vma_soft_dirty_enabled(vma) && !pte_soft_dirty(pte))
+               return false;
+       return !userfaultfd_pte_wp(vma, pte);
 }
 
 static struct page *follow_page_pte(struct vm_area_struct *vma,
@@ -528,12 +556,19 @@ retry:
        }
        if ((flags & FOLL_NUMA) && pte_protnone(pte))
                goto no_page;
-       if ((flags & FOLL_WRITE) && !can_follow_write_pte(pte, flags)) {
-               pte_unmap_unlock(ptep, ptl);
-               return NULL;
-       }
 
        page = vm_normal_page(vma, address, pte);
+
+       /*
+        * We only care about anon pages in can_follow_write_pte() and don't
+        * have to worry about pte_devmap() because they are never anon.
+        */
+       if ((flags & FOLL_WRITE) &&
+           !can_follow_write_pte(pte, page, vma, flags)) {
+               page = NULL;
+               goto out;
+       }
+
        if (!page && pte_devmap(pte) && (flags & (FOLL_GET | FOLL_PIN))) {
                /*
                 * Only return device mapping pages in the FOLL_GET or FOLL_PIN
@@ -986,17 +1021,6 @@ static int faultin_page(struct vm_area_struct *vma,
                return -EBUSY;
        }
 
-       /*
-        * The VM_FAULT_WRITE bit tells us that do_wp_page has broken COW when
-        * necessary, even if maybe_mkwrite decided not to set pte_write. We
-        * can thus safely do subsequent page lookups as if they were reads.
-        * But only do so when looping for pte_write is futile: in some cases
-        * userspace may also be wanting to write to the gotten user page,
-        * which a read fault here might prevent (a readonly page might get
-        * reCOWed by userspace write).
-        */
-       if ((ret & VM_FAULT_WRITE) && !(vma->vm_flags & VM_WRITE))
-               *flags |= FOLL_COW;
        return 0;
 }
 
index 8a7c1b3..e9414ee 100644 (file)
@@ -1040,12 +1040,6 @@ struct page *follow_devmap_pmd(struct vm_area_struct *vma, unsigned long addr,
 
        assert_spin_locked(pmd_lockptr(mm, pmd));
 
-       /*
-        * When we COW a devmap PMD entry, we split it into PTEs, so we should
-        * not be in this function with `flags & FOLL_COW` set.
-        */
-       WARN_ONCE(flags & FOLL_COW, "mm: In follow_devmap_pmd with FOLL_COW set");
-
        /* FOLL_GET and FOLL_PIN are mutually exclusive. */
        if (WARN_ON_ONCE((flags & (FOLL_PIN | FOLL_GET)) ==
                         (FOLL_PIN | FOLL_GET)))
@@ -1395,14 +1389,42 @@ fallback:
        return VM_FAULT_FALLBACK;
 }
 
-/*
- * FOLL_FORCE can write to even unwritable pmd's, but only
- * after we've gone through a COW cycle and they are dirty.
- */
-static inline bool can_follow_write_pmd(pmd_t pmd, unsigned int flags)
+/* FOLL_FORCE can write to even unwritable PMDs in COW mappings. */
+static inline bool can_follow_write_pmd(pmd_t pmd, struct page *page,
+                                       struct vm_area_struct *vma,
+                                       unsigned int flags)
 {
-       return pmd_write(pmd) ||
-              ((flags & FOLL_FORCE) && (flags & FOLL_COW) && pmd_dirty(pmd));
+       /* If the pmd is writable, we can write to the page. */
+       if (pmd_write(pmd))
+               return true;
+
+       /* Maybe FOLL_FORCE is set to override it? */
+       if (!(flags & FOLL_FORCE))
+               return false;
+
+       /* But FOLL_FORCE has no effect on shared mappings */
+       if (vma->vm_flags & (VM_MAYSHARE | VM_SHARED))
+               return false;
+
+       /* ... or read-only private ones */
+       if (!(vma->vm_flags & VM_MAYWRITE))
+               return false;
+
+       /* ... or already writable ones that just need to take a write fault */
+       if (vma->vm_flags & VM_WRITE)
+               return false;
+
+       /*
+        * See can_change_pte_writable(): we broke COW and could map the page
+        * writable if we have an exclusive anonymous page ...
+        */
+       if (!page || !PageAnon(page) || !PageAnonExclusive(page))
+               return false;
+
+       /* ... and a write-fault isn't required for other reasons. */
+       if (vma_soft_dirty_enabled(vma) && !pmd_soft_dirty(pmd))
+               return false;
+       return !userfaultfd_huge_pmd_wp(vma, pmd);
 }
 
 struct page *follow_trans_huge_pmd(struct vm_area_struct *vma,
@@ -1411,12 +1433,16 @@ struct page *follow_trans_huge_pmd(struct vm_area_struct *vma,
                                   unsigned int flags)
 {
        struct mm_struct *mm = vma->vm_mm;
-       struct page *page = NULL;
+       struct page *page;
 
        assert_spin_locked(pmd_lockptr(mm, pmd));
 
-       if (flags & FOLL_WRITE && !can_follow_write_pmd(*pmd, flags))
-               goto out;
+       page = pmd_page(*pmd);
+       VM_BUG_ON_PAGE(!PageHead(page) && !is_zone_device_page(page), page);
+
+       if ((flags & FOLL_WRITE) &&
+           !can_follow_write_pmd(*pmd, page, vma, flags))
+               return NULL;
 
        /* Avoid dumping huge zero page */
        if ((flags & FOLL_DUMP) && is_huge_zero_pmd(*pmd))
@@ -1424,10 +1450,7 @@ struct page *follow_trans_huge_pmd(struct vm_area_struct *vma,
 
        /* Full NUMA hinting faults to serialise migration in fault paths */
        if ((flags & FOLL_NUMA) && pmd_protnone(*pmd))
-               goto out;
-
-       page = pmd_page(*pmd);
-       VM_BUG_ON_PAGE(!PageHead(page) && !is_zone_device_page(page), page);
+               return NULL;
 
        if (!pmd_write(*pmd) && gup_must_unshare(flags, page))
                return ERR_PTR(-EMLINK);
@@ -1444,7 +1467,6 @@ struct page *follow_trans_huge_pmd(struct vm_area_struct *vma,
        page += (addr & ~HPAGE_PMD_MASK) >> PAGE_SHIFT;
        VM_BUG_ON_PAGE(!PageCompound(page) && !is_zone_device_page(page), page);
 
-out:
        return page;
 }
 
index 0aee2f3..e070b85 100644 (file)
@@ -5241,6 +5241,21 @@ static vm_fault_t hugetlb_wp(struct mm_struct *mm, struct vm_area_struct *vma,
        VM_BUG_ON(unshare && (flags & FOLL_WRITE));
        VM_BUG_ON(!unshare && !(flags & FOLL_WRITE));
 
+       /*
+        * hugetlb does not support FOLL_FORCE-style write faults that keep the
+        * PTE mapped R/O such as maybe_mkwrite() would do.
+        */
+       if (WARN_ON_ONCE(!unshare && !(vma->vm_flags & VM_WRITE)))
+               return VM_FAULT_SIGSEGV;
+
+       /* Let's take out MAP_SHARED mappings first. */
+       if (vma->vm_flags & VM_MAYSHARE) {
+               if (unlikely(unshare))
+                       return 0;
+               set_huge_ptep_writable(vma, haddr, ptep);
+               return 0;
+       }
+
        pte = huge_ptep_get(ptep);
        old_page = pte_page(pte);
 
@@ -5781,12 +5796,11 @@ vm_fault_t hugetlb_fault(struct mm_struct *mm, struct vm_area_struct *vma,
         * If we are going to COW/unshare the mapping later, we examine the
         * pending reservations for this page now. This will ensure that any
         * allocations necessary to record that reservation occur outside the
-        * spinlock. For private mappings, we also lookup the pagecache
-        * page now as it is used to determine if a reservation has been
-        * consumed.
+        * spinlock. Also lookup the pagecache page now as it is used to
+        * determine if a reservation has been consumed.
         */
        if ((flags & (FAULT_FLAG_WRITE|FAULT_FLAG_UNSHARE)) &&
-           !huge_pte_write(entry)) {
+           !(vma->vm_flags & VM_MAYSHARE) && !huge_pte_write(entry)) {
                if (vma_needs_reservation(h, vma, haddr) < 0) {
                        ret = VM_FAULT_OOM;
                        goto out_mutex;
@@ -5794,9 +5808,7 @@ vm_fault_t hugetlb_fault(struct mm_struct *mm, struct vm_area_struct *vma,
                /* Just decrements count, does not deallocate */
                vma_end_reservation(h, vma, haddr);
 
-               if (!(vma->vm_flags & VM_MAYSHARE))
-                       pagecache_page = hugetlbfs_pagecache_page(h,
-                                                               vma, haddr);
+               pagecache_page = hugetlbfs_pagecache_page(h, vma, haddr);
        }
 
        ptl = huge_pte_lock(h, mm, ptep);
@@ -6029,7 +6041,7 @@ int hugetlb_mcopy_atomic_pte(struct mm_struct *dst_mm,
        if (!huge_pte_none_mostly(huge_ptep_get(dst_pte)))
                goto out_release_unlock;
 
-       if (vm_shared) {
+       if (page_in_pagecache) {
                page_dup_file_rmap(page, true);
        } else {
                ClearHPageRestoreReserve(page);
index c035020..9d780f4 100644 (file)
--- a/mm/mmap.c
+++ b/mm/mmap.c
@@ -1646,8 +1646,11 @@ int vma_wants_writenotify(struct vm_area_struct *vma, pgprot_t vm_page_prot)
            pgprot_val(vm_pgprot_modify(vm_page_prot, vm_flags)))
                return 0;
 
-       /* Do we need to track softdirty? */
-       if (vma_soft_dirty_enabled(vma))
+       /*
+        * Do we need to track softdirty? hugetlb does not support softdirty
+        * tracking yet.
+        */
+       if (vma_soft_dirty_enabled(vma) && !is_vm_hugetlb_page(vma))
                return 1;
 
        /* Specialty mapping? */
index 3a23dde..bc6bddd 100644 (file)
@@ -196,10 +196,11 @@ static unsigned long change_pte_range(struct mmu_gather *tlb,
                        pages++;
                } else if (is_swap_pte(oldpte)) {
                        swp_entry_t entry = pte_to_swp_entry(oldpte);
-                       struct page *page = pfn_swap_entry_to_page(entry);
                        pte_t newpte;
 
                        if (is_writable_migration_entry(entry)) {
+                               struct page *page = pfn_swap_entry_to_page(entry);
+
                                /*
                                 * A protection check is difficult so
                                 * just be safe and disable write
index d0d466a..032a7bf 100644 (file)
@@ -2892,6 +2892,7 @@ static void wb_inode_writeback_start(struct bdi_writeback *wb)
 
 static void wb_inode_writeback_end(struct bdi_writeback *wb)
 {
+       unsigned long flags;
        atomic_dec(&wb->writeback_inodes);
        /*
         * Make sure estimate of writeback throughput gets updated after
@@ -2900,7 +2901,10 @@ static void wb_inode_writeback_end(struct bdi_writeback *wb)
         * that if multiple inodes end writeback at a similar time, they get
         * batched into one bandwidth update.
         */
-       queue_delayed_work(bdi_wq, &wb->bw_dwork, BANDWIDTH_INTERVAL);
+       spin_lock_irqsave(&wb->work_lock, flags);
+       if (test_bit(WB_registered, &wb->state))
+               queue_delayed_work(bdi_wq, &wb->bw_dwork, BANDWIDTH_INTERVAL);
+       spin_unlock_irqrestore(&wb->work_lock, flags);
 }
 
 bool __folio_end_writeback(struct folio *folio)
index edc06c5..93d5a6f 100644 (file)
--- a/mm/rmap.c
+++ b/mm/rmap.c
@@ -93,7 +93,8 @@ static inline struct anon_vma *anon_vma_alloc(void)
        anon_vma = kmem_cache_alloc(anon_vma_cachep, GFP_KERNEL);
        if (anon_vma) {
                atomic_set(&anon_vma->refcount, 1);
-               anon_vma->degree = 1;   /* Reference for first vma */
+               anon_vma->num_children = 0;
+               anon_vma->num_active_vmas = 0;
                anon_vma->parent = anon_vma;
                /*
                 * Initialise the anon_vma root to point to itself. If called
@@ -201,6 +202,7 @@ int __anon_vma_prepare(struct vm_area_struct *vma)
                anon_vma = anon_vma_alloc();
                if (unlikely(!anon_vma))
                        goto out_enomem_free_avc;
+               anon_vma->num_children++; /* self-parent link for new root */
                allocated = anon_vma;
        }
 
@@ -210,8 +212,7 @@ int __anon_vma_prepare(struct vm_area_struct *vma)
        if (likely(!vma->anon_vma)) {
                vma->anon_vma = anon_vma;
                anon_vma_chain_link(vma, avc, anon_vma);
-               /* vma reference or self-parent link for new root */
-               anon_vma->degree++;
+               anon_vma->num_active_vmas++;
                allocated = NULL;
                avc = NULL;
        }
@@ -296,19 +297,19 @@ int anon_vma_clone(struct vm_area_struct *dst, struct vm_area_struct *src)
                anon_vma_chain_link(dst, avc, anon_vma);
 
                /*
-                * Reuse existing anon_vma if its degree lower than two,
-                * that means it has no vma and only one anon_vma child.
+                * Reuse existing anon_vma if it has no vma and only one
+                * anon_vma child.
                 *
-                * Do not choose parent anon_vma, otherwise first child
-                * will always reuse it. Root anon_vma is never reused:
+                * Root anon_vma is never reused:
                 * it has self-parent reference and at least one child.
                 */
                if (!dst->anon_vma && src->anon_vma &&
-                   anon_vma != src->anon_vma && anon_vma->degree < 2)
+                   anon_vma->num_children < 2 &&
+                   anon_vma->num_active_vmas == 0)
                        dst->anon_vma = anon_vma;
        }
        if (dst->anon_vma)
-               dst->anon_vma->degree++;
+               dst->anon_vma->num_active_vmas++;
        unlock_anon_vma_root(root);
        return 0;
 
@@ -358,6 +359,7 @@ int anon_vma_fork(struct vm_area_struct *vma, struct vm_area_struct *pvma)
        anon_vma = anon_vma_alloc();
        if (!anon_vma)
                goto out_error;
+       anon_vma->num_active_vmas++;
        avc = anon_vma_chain_alloc(GFP_KERNEL);
        if (!avc)
                goto out_error_free_anon_vma;
@@ -378,7 +380,7 @@ int anon_vma_fork(struct vm_area_struct *vma, struct vm_area_struct *pvma)
        vma->anon_vma = anon_vma;
        anon_vma_lock_write(anon_vma);
        anon_vma_chain_link(vma, avc, anon_vma);
-       anon_vma->parent->degree++;
+       anon_vma->parent->num_children++;
        anon_vma_unlock_write(anon_vma);
 
        return 0;
@@ -410,7 +412,7 @@ void unlink_anon_vmas(struct vm_area_struct *vma)
                 * to free them outside the lock.
                 */
                if (RB_EMPTY_ROOT(&anon_vma->rb_root.rb_root)) {
-                       anon_vma->parent->degree--;
+                       anon_vma->parent->num_children--;
                        continue;
                }
 
@@ -418,7 +420,7 @@ void unlink_anon_vmas(struct vm_area_struct *vma)
                anon_vma_chain_free(avc);
        }
        if (vma->anon_vma) {
-               vma->anon_vma->degree--;
+               vma->anon_vma->num_active_vmas--;
 
                /*
                 * vma would still be needed after unlink, and anon_vma will be prepared
@@ -436,7 +438,8 @@ void unlink_anon_vmas(struct vm_area_struct *vma)
        list_for_each_entry_safe(avc, next, &vma->anon_vma_chain, same_vma) {
                struct anon_vma *anon_vma = avc->anon_vma;
 
-               VM_WARN_ON(anon_vma->degree);
+               VM_WARN_ON(anon_vma->num_children);
+               VM_WARN_ON(anon_vma->num_active_vmas);
                put_anon_vma(anon_vma);
 
                list_del(&avc->same_vma);
index 5783f11..42e5888 100644 (file)
@@ -1659,7 +1659,9 @@ static int shmem_replace_page(struct page **pagep, gfp_t gfp,
                new = page_folio(newpage);
                mem_cgroup_migrate(old, new);
                __inc_lruvec_page_state(newpage, NR_FILE_PAGES);
+               __inc_lruvec_page_state(newpage, NR_SHMEM);
                __dec_lruvec_page_state(oldpage, NR_FILE_PAGES);
+               __dec_lruvec_page_state(oldpage, NR_SHMEM);
        }
        xa_unlock_irq(&swap_mapping->i_pages);
 
@@ -1780,6 +1782,7 @@ static int shmem_swapin_folio(struct inode *inode, pgoff_t index,
 
        if (shmem_should_replace_folio(folio, gfp)) {
                error = shmem_replace_page(&page, gfp, info, index);
+               folio = page_folio(page);
                if (error)
                        goto failed;
        }
@@ -2281,16 +2284,34 @@ static int shmem_mmap(struct file *file, struct vm_area_struct *vma)
        return 0;
 }
 
-/* Mask out flags that are inappropriate for the given type of inode. */
-static unsigned shmem_mask_flags(umode_t mode, __u32 flags)
+#ifdef CONFIG_TMPFS_XATTR
+static int shmem_initxattrs(struct inode *, const struct xattr *, void *);
+
+/*
+ * chattr's fsflags are unrelated to extended attributes,
+ * but tmpfs has chosen to enable them under the same config option.
+ */
+static void shmem_set_inode_flags(struct inode *inode, unsigned int fsflags)
+{
+       unsigned int i_flags = 0;
+
+       if (fsflags & FS_NOATIME_FL)
+               i_flags |= S_NOATIME;
+       if (fsflags & FS_APPEND_FL)
+               i_flags |= S_APPEND;
+       if (fsflags & FS_IMMUTABLE_FL)
+               i_flags |= S_IMMUTABLE;
+       /*
+        * But FS_NODUMP_FL does not require any action in i_flags.
+        */
+       inode_set_flags(inode, i_flags, S_NOATIME | S_APPEND | S_IMMUTABLE);
+}
+#else
+static void shmem_set_inode_flags(struct inode *inode, unsigned int fsflags)
 {
-       if (S_ISDIR(mode))
-               return flags;
-       else if (S_ISREG(mode))
-               return flags & SHMEM_REG_FLMASK;
-       else
-               return flags & SHMEM_OTHER_FLMASK;
 }
+#define shmem_initxattrs NULL
+#endif
 
 static struct inode *shmem_get_inode(struct super_block *sb, struct inode *dir,
                                     umode_t mode, dev_t dev, unsigned long flags)
@@ -2319,7 +2340,8 @@ static struct inode *shmem_get_inode(struct super_block *sb, struct inode *dir,
                info->i_crtime = inode->i_mtime;
                info->fsflags = (dir == NULL) ? 0 :
                        SHMEM_I(dir)->fsflags & SHMEM_FL_INHERITED;
-               info->fsflags = shmem_mask_flags(mode, info->fsflags);
+               if (info->fsflags)
+                       shmem_set_inode_flags(inode, info->fsflags);
                INIT_LIST_HEAD(&info->shrinklist);
                INIT_LIST_HEAD(&info->swaplist);
                simple_xattrs_init(&info->xattrs);
@@ -2468,12 +2490,6 @@ out_unacct_blocks:
 static const struct inode_operations shmem_symlink_inode_operations;
 static const struct inode_operations shmem_short_symlink_operations;
 
-#ifdef CONFIG_TMPFS_XATTR
-static int shmem_initxattrs(struct inode *, const struct xattr *, void *);
-#else
-#define shmem_initxattrs NULL
-#endif
-
 static int
 shmem_write_begin(struct file *file, struct address_space *mapping,
                        loff_t pos, unsigned len,
@@ -2826,12 +2842,13 @@ static long shmem_fallocate(struct file *file, int mode, loff_t offset,
 
        if (!(mode & FALLOC_FL_KEEP_SIZE) && offset + len > inode->i_size)
                i_size_write(inode, offset + len);
-       inode->i_ctime = current_time(inode);
 undone:
        spin_lock(&inode->i_lock);
        inode->i_private = NULL;
        spin_unlock(&inode->i_lock);
 out:
+       if (!error)
+               file_modified(file);
        inode_unlock(inode);
        return error;
 }
@@ -3179,18 +3196,13 @@ static int shmem_fileattr_set(struct user_namespace *mnt_userns,
 
        if (fileattr_has_fsx(fa))
                return -EOPNOTSUPP;
+       if (fa->flags & ~SHMEM_FL_USER_MODIFIABLE)
+               return -EOPNOTSUPP;
 
        info->fsflags = (info->fsflags & ~SHMEM_FL_USER_MODIFIABLE) |
                (fa->flags & SHMEM_FL_USER_MODIFIABLE);
 
-       inode->i_flags &= ~(S_APPEND | S_IMMUTABLE | S_NOATIME);
-       if (info->fsflags & FS_APPEND_FL)
-               inode->i_flags |= S_APPEND;
-       if (info->fsflags & FS_IMMUTABLE_FL)
-               inode->i_flags |= S_IMMUTABLE;
-       if (info->fsflags & FS_NOATIME_FL)
-               inode->i_flags |= S_NOATIME;
-
+       shmem_set_inode_flags(inode, info->fsflags);
        inode->i_ctime = current_time(inode);
        return 0;
 }
index 07d3bef..7327b25 100644 (file)
@@ -703,14 +703,29 @@ ssize_t mcopy_continue(struct mm_struct *dst_mm, unsigned long start,
                              mmap_changing, 0);
 }
 
+void uffd_wp_range(struct mm_struct *dst_mm, struct vm_area_struct *dst_vma,
+                  unsigned long start, unsigned long len, bool enable_wp)
+{
+       struct mmu_gather tlb;
+       pgprot_t newprot;
+
+       if (enable_wp)
+               newprot = vm_get_page_prot(dst_vma->vm_flags & ~(VM_WRITE));
+       else
+               newprot = vm_get_page_prot(dst_vma->vm_flags);
+
+       tlb_gather_mmu(&tlb, dst_mm);
+       change_protection(&tlb, dst_vma, start, start + len, newprot,
+                         enable_wp ? MM_CP_UFFD_WP : MM_CP_UFFD_WP_RESOLVE);
+       tlb_finish_mmu(&tlb);
+}
+
 int mwriteprotect_range(struct mm_struct *dst_mm, unsigned long start,
                        unsigned long len, bool enable_wp,
                        atomic_t *mmap_changing)
 {
        struct vm_area_struct *dst_vma;
        unsigned long page_mask;
-       struct mmu_gather tlb;
-       pgprot_t newprot;
        int err;
 
        /*
@@ -750,15 +765,7 @@ int mwriteprotect_range(struct mm_struct *dst_mm, unsigned long start,
                        goto out_unlock;
        }
 
-       if (enable_wp)
-               newprot = vm_get_page_prot(dst_vma->vm_flags & ~(VM_WRITE));
-       else
-               newprot = vm_get_page_prot(dst_vma->vm_flags);
-
-       tlb_gather_mmu(&tlb, dst_mm);
-       change_protection(&tlb, dst_vma, start, start + len, newprot,
-                         enable_wp ? MM_CP_UFFD_WP : MM_CP_UFFD_WP_RESOLVE);
-       tlb_finish_mmu(&tlb);
+       uffd_wp_range(dst_mm, dst_vma, start, len, enable_wp);
 
        err = 0;
 out_unlock:
index 373d273..90af9a8 100644 (file)
@@ -1168,8 +1168,15 @@ int fragmentation_index(struct zone *zone, unsigned int order)
 #define TEXT_FOR_HIGHMEM(xx)
 #endif
 
+#ifdef CONFIG_ZONE_DEVICE
+#define TEXT_FOR_DEVICE(xx) xx "_device",
+#else
+#define TEXT_FOR_DEVICE(xx)
+#endif
+
 #define TEXTS_FOR_ZONES(xx) TEXT_FOR_DMA(xx) TEXT_FOR_DMA32(xx) xx "_normal", \
-                                       TEXT_FOR_HIGHMEM(xx) xx "_movable",
+                                       TEXT_FOR_HIGHMEM(xx) xx "_movable", \
+                                       TEXT_FOR_DEVICE(xx)
 
 const char * const vmstat_text[] = {
        /* enum zone_stat_item counters */
index 34f784a..907c9b1 100644 (file)
@@ -1487,7 +1487,7 @@ void zs_free(struct zs_pool *pool, unsigned long handle)
        struct size_class *class;
        enum fullness_group fullness;
 
-       if (unlikely(!handle))
+       if (IS_ERR_OR_NULL((void *)handle))
                return;
 
        /*
index 1a11064..8f19253 100644 (file)
@@ -36,18 +36,10 @@ static struct ebt_replace_kernel initial_table = {
        .entries        = (char *)&initial_chain,
 };
 
-static int check(const struct ebt_table_info *info, unsigned int valid_hooks)
-{
-       if (valid_hooks & ~(1 << NF_BR_BROUTING))
-               return -EINVAL;
-       return 0;
-}
-
 static const struct ebt_table broute_table = {
        .name           = "broute",
        .table          = &initial_table,
        .valid_hooks    = 1 << NF_BR_BROUTING,
-       .check          = check,
        .me             = THIS_MODULE,
 };
 
index cb94943..278f324 100644 (file)
@@ -43,18 +43,10 @@ static struct ebt_replace_kernel initial_table = {
        .entries        = (char *)initial_chains,
 };
 
-static int check(const struct ebt_table_info *info, unsigned int valid_hooks)
-{
-       if (valid_hooks & ~FILTER_VALID_HOOKS)
-               return -EINVAL;
-       return 0;
-}
-
 static const struct ebt_table frame_filter = {
        .name           = "filter",
        .table          = &initial_table,
        .valid_hooks    = FILTER_VALID_HOOKS,
-       .check          = check,
        .me             = THIS_MODULE,
 };
 
index 5ee0531..9066f7f 100644 (file)
@@ -43,18 +43,10 @@ static struct ebt_replace_kernel initial_table = {
        .entries        = (char *)initial_chains,
 };
 
-static int check(const struct ebt_table_info *info, unsigned int valid_hooks)
-{
-       if (valid_hooks & ~NAT_VALID_HOOKS)
-               return -EINVAL;
-       return 0;
-}
-
 static const struct ebt_table frame_nat = {
        .name           = "nat",
        .table          = &initial_table,
        .valid_hooks    = NAT_VALID_HOOKS,
-       .check          = check,
        .me             = THIS_MODULE,
 };
 
index f2dbefb..9a0ae59 100644 (file)
@@ -1040,8 +1040,7 @@ static int do_replace_finish(struct net *net, struct ebt_replace *repl,
                goto free_iterate;
        }
 
-       /* the table doesn't like it */
-       if (t->check && (ret = t->check(newinfo, repl->valid_hooks)))
+       if (repl->valid_hooks != t->valid_hooks)
                goto free_unlock;
 
        if (repl->num_counters && repl->num_counters != t->private->nentries) {
@@ -1231,11 +1230,6 @@ int ebt_register_table(struct net *net, const struct ebt_table *input_table,
        if (ret != 0)
                goto free_chainstack;
 
-       if (table->check && table->check(newinfo, table->valid_hooks)) {
-               ret = -EINVAL;
-               goto free_chainstack;
-       }
-
        table->private = newinfo;
        rwlock_init(&table->lock);
        mutex_lock(&ebt_mutex);
index 1b7f385..94374d5 100644 (file)
@@ -310,11 +310,12 @@ BPF_CALL_2(bpf_sk_storage_delete, struct bpf_map *, map, struct sock *, sk)
 static int bpf_sk_storage_charge(struct bpf_local_storage_map *smap,
                                 void *owner, u32 size)
 {
+       int optmem_max = READ_ONCE(sysctl_optmem_max);
        struct sock *sk = (struct sock *)owner;
 
        /* same check as in sock_kmalloc() */
-       if (size <= sysctl_optmem_max &&
-           atomic_read(&sk->sk_omem_alloc) + size < sysctl_optmem_max) {
+       if (size <= optmem_max &&
+           atomic_read(&sk->sk_omem_alloc) + size < optmem_max) {
                atomic_add(size, &sk->sk_omem_alloc);
                return 0;
        }
index 716df64..56c8b09 100644 (file)
@@ -4624,7 +4624,7 @@ static bool skb_flow_limit(struct sk_buff *skb, unsigned int qlen)
        struct softnet_data *sd;
        unsigned int old_flow, new_flow;
 
-       if (qlen < (netdev_max_backlog >> 1))
+       if (qlen < (READ_ONCE(netdev_max_backlog) >> 1))
                return false;
 
        sd = this_cpu_ptr(&softnet_data);
@@ -4672,7 +4672,7 @@ static int enqueue_to_backlog(struct sk_buff *skb, int cpu,
        if (!netif_running(skb->dev))
                goto drop;
        qlen = skb_queue_len(&sd->input_pkt_queue);
-       if (qlen <= netdev_max_backlog && !skb_flow_limit(skb, qlen)) {
+       if (qlen <= READ_ONCE(netdev_max_backlog) && !skb_flow_limit(skb, qlen)) {
                if (qlen) {
 enqueue:
                        __skb_queue_tail(&sd->input_pkt_queue, skb);
@@ -4928,7 +4928,7 @@ static int netif_rx_internal(struct sk_buff *skb)
 {
        int ret;
 
-       net_timestamp_check(netdev_tstamp_prequeue, skb);
+       net_timestamp_check(READ_ONCE(netdev_tstamp_prequeue), skb);
 
        trace_netif_rx(skb);
 
@@ -5281,7 +5281,7 @@ static int __netif_receive_skb_core(struct sk_buff **pskb, bool pfmemalloc,
        int ret = NET_RX_DROP;
        __be16 type;
 
-       net_timestamp_check(!netdev_tstamp_prequeue, skb);
+       net_timestamp_check(!READ_ONCE(netdev_tstamp_prequeue), skb);
 
        trace_netif_receive_skb(skb);
 
@@ -5664,7 +5664,7 @@ static int netif_receive_skb_internal(struct sk_buff *skb)
 {
        int ret;
 
-       net_timestamp_check(netdev_tstamp_prequeue, skb);
+       net_timestamp_check(READ_ONCE(netdev_tstamp_prequeue), skb);
 
        if (skb_defer_rx_timestamp(skb))
                return NET_RX_SUCCESS;
@@ -5694,7 +5694,7 @@ void netif_receive_skb_list_internal(struct list_head *head)
 
        INIT_LIST_HEAD(&sublist);
        list_for_each_entry_safe(skb, next, head, list) {
-               net_timestamp_check(netdev_tstamp_prequeue, skb);
+               net_timestamp_check(READ_ONCE(netdev_tstamp_prequeue), skb);
                skb_list_del_init(skb);
                if (!skb_defer_rx_timestamp(skb))
                        list_add_tail(&skb->list, &sublist);
@@ -5918,7 +5918,7 @@ static int process_backlog(struct napi_struct *napi, int quota)
                net_rps_action_and_irq_enable(sd);
        }
 
-       napi->weight = dev_rx_weight;
+       napi->weight = READ_ONCE(dev_rx_weight);
        while (again) {
                struct sk_buff *skb;
 
@@ -6665,8 +6665,8 @@ static __latent_entropy void net_rx_action(struct softirq_action *h)
 {
        struct softnet_data *sd = this_cpu_ptr(&softnet_data);
        unsigned long time_limit = jiffies +
-               usecs_to_jiffies(netdev_budget_usecs);
-       int budget = netdev_budget;
+               usecs_to_jiffies(READ_ONCE(netdev_budget_usecs));
+       int budget = READ_ONCE(netdev_budget);
        LIST_HEAD(list);
        LIST_HEAD(repoll);
 
@@ -10284,7 +10284,7 @@ static struct net_device *netdev_wait_allrefs_any(struct list_head *list)
                                return dev;
 
                if (time_after(jiffies, warning_time +
-                              netdev_unregister_timeout_secs * HZ)) {
+                              READ_ONCE(netdev_unregister_timeout_secs) * HZ)) {
                        list_for_each_entry(dev, list, todo_list) {
                                pr_emerg("unregister_netdevice: waiting for %s to become free. Usage count = %d\n",
                                         dev->name, netdev_refcnt_read(dev));
index e8508aa..c191db8 100644 (file)
@@ -1214,10 +1214,11 @@ void sk_filter_uncharge(struct sock *sk, struct sk_filter *fp)
 static bool __sk_filter_charge(struct sock *sk, struct sk_filter *fp)
 {
        u32 filter_size = bpf_prog_size(fp->prog->len);
+       int optmem_max = READ_ONCE(sysctl_optmem_max);
 
        /* same check as in sock_kmalloc() */
-       if (filter_size <= sysctl_optmem_max &&
-           atomic_read(&sk->sk_omem_alloc) + filter_size < sysctl_optmem_max) {
+       if (filter_size <= optmem_max &&
+           atomic_read(&sk->sk_omem_alloc) + filter_size < optmem_max) {
                atomic_add(filter_size, &sk->sk_omem_alloc);
                return true;
        }
@@ -1548,7 +1549,7 @@ int sk_reuseport_attach_filter(struct sock_fprog *fprog, struct sock *sk)
        if (IS_ERR(prog))
                return PTR_ERR(prog);
 
-       if (bpf_prog_size(prog->len) > sysctl_optmem_max)
+       if (bpf_prog_size(prog->len) > READ_ONCE(sysctl_optmem_max))
                err = -ENOMEM;
        else
                err = reuseport_attach_prog(sk, prog);
@@ -1615,7 +1616,7 @@ int sk_reuseport_attach_bpf(u32 ufd, struct sock *sk)
                }
        } else {
                /* BPF_PROG_TYPE_SOCKET_FILTER */
-               if (bpf_prog_size(prog->len) > sysctl_optmem_max) {
+               if (bpf_prog_size(prog->len) > READ_ONCE(sysctl_optmem_max)) {
                        err = -ENOMEM;
                        goto err_prog_put;
                }
@@ -5034,14 +5035,14 @@ static int __bpf_setsockopt(struct sock *sk, int level, int optname,
                /* Only some socketops are supported */
                switch (optname) {
                case SO_RCVBUF:
-                       val = min_t(u32, val, sysctl_rmem_max);
+                       val = min_t(u32, val, READ_ONCE(sysctl_rmem_max));
                        val = min_t(int, val, INT_MAX / 2);
                        sk->sk_userlocks |= SOCK_RCVBUF_LOCK;
                        WRITE_ONCE(sk->sk_rcvbuf,
                                   max_t(int, val * 2, SOCK_MIN_RCVBUF));
                        break;
                case SO_SNDBUF:
-                       val = min_t(u32, val, sysctl_wmem_max);
+                       val = min_t(u32, val, READ_ONCE(sysctl_wmem_max));
                        val = min_t(int, val, INT_MAX / 2);
                        sk->sk_userlocks |= SOCK_SNDBUF_LOCK;
                        WRITE_ONCE(sk->sk_sndbuf,
index 541c7a7..21619c7 100644 (file)
@@ -26,7 +26,7 @@ int gro_cells_receive(struct gro_cells *gcells, struct sk_buff *skb)
 
        cell = this_cpu_ptr(gcells->cells);
 
-       if (skb_queue_len(&cell->napi_skbs) > netdev_max_backlog) {
+       if (skb_queue_len(&cell->napi_skbs) > READ_ONCE(netdev_max_backlog)) {
 drop:
                dev_core_stats_rx_dropped_inc(dev);
                kfree_skb(skb);
index 5b669eb..78cc8fb 100644 (file)
@@ -309,14 +309,17 @@ static int neigh_del_timer(struct neighbour *n)
 
 static void pneigh_queue_purge(struct sk_buff_head *list, struct net *net)
 {
+       struct sk_buff_head tmp;
        unsigned long flags;
        struct sk_buff *skb;
 
+       skb_queue_head_init(&tmp);
        spin_lock_irqsave(&list->lock, flags);
        skb = skb_peek(list);
        while (skb != NULL) {
                struct sk_buff *skb_next = skb_peek_next(skb, list);
                struct net_device *dev = skb->dev;
+
                if (net == NULL || net_eq(dev_net(dev), net)) {
                        struct in_device *in_dev;
 
@@ -326,13 +329,16 @@ static void pneigh_queue_purge(struct sk_buff_head *list, struct net *net)
                                in_dev->arp_parms->qlen--;
                        rcu_read_unlock();
                        __skb_unlink(skb, list);
-
-                       dev_put(dev);
-                       kfree_skb(skb);
+                       __skb_queue_tail(&tmp, skb);
                }
                skb = skb_next;
        }
        spin_unlock_irqrestore(&list->lock, flags);
+
+       while ((skb = __skb_dequeue(&tmp))) {
+               dev_put(skb->dev);
+               kfree_skb(skb);
+       }
 }
 
 static void neigh_flush_dev(struct neigh_table *tbl, struct net_device *dev,
index 974bbbb..84bb5e1 100644 (file)
@@ -4205,9 +4205,8 @@ normal:
                                SKB_GSO_CB(nskb)->csum_start =
                                        skb_headroom(nskb) + doffset;
                        } else {
-                               skb_copy_bits(head_skb, offset,
-                                             skb_put(nskb, len),
-                                             len);
+                               if (skb_copy_bits(head_skb, offset, skb_put(nskb, len), len))
+                                       goto err;
                        }
                        continue;
                }
@@ -4798,7 +4797,7 @@ static bool skb_may_tx_timestamp(struct sock *sk, bool tsonly)
 {
        bool ret;
 
-       if (likely(sysctl_tstamp_allow_data || tsonly))
+       if (likely(READ_ONCE(sysctl_tstamp_allow_data) || tsonly))
                return true;
 
        read_lock_bh(&sk->sk_callback_lock);
index 4cb957d..788c137 100644 (file)
@@ -1101,7 +1101,7 @@ int sock_setsockopt(struct socket *sock, int level, int optname,
                 * play 'guess the biggest size' games. RCVBUF/SNDBUF
                 * are treated in BSD as hints
                 */
-               val = min_t(u32, val, sysctl_wmem_max);
+               val = min_t(u32, val, READ_ONCE(sysctl_wmem_max));
 set_sndbuf:
                /* Ensure val * 2 fits into an int, to prevent max_t()
                 * from treating it as a negative value.
@@ -1133,7 +1133,7 @@ set_sndbuf:
                 * play 'guess the biggest size' games. RCVBUF/SNDBUF
                 * are treated in BSD as hints
                 */
-               __sock_set_rcvbuf(sk, min_t(u32, val, sysctl_rmem_max));
+               __sock_set_rcvbuf(sk, min_t(u32, val, READ_ONCE(sysctl_rmem_max)));
                break;
 
        case SO_RCVBUFFORCE:
@@ -2536,7 +2536,7 @@ struct sk_buff *sock_omalloc(struct sock *sk, unsigned long size,
 
        /* small safe race: SKB_TRUESIZE may differ from final skb->truesize */
        if (atomic_read(&sk->sk_omem_alloc) + SKB_TRUESIZE(size) >
-           sysctl_optmem_max)
+           READ_ONCE(sysctl_optmem_max))
                return NULL;
 
        skb = alloc_skb(size, priority);
@@ -2554,8 +2554,10 @@ struct sk_buff *sock_omalloc(struct sock *sk, unsigned long size,
  */
 void *sock_kmalloc(struct sock *sk, int size, gfp_t priority)
 {
-       if ((unsigned int)size <= sysctl_optmem_max &&
-           atomic_read(&sk->sk_omem_alloc) + size < sysctl_optmem_max) {
+       int optmem_max = READ_ONCE(sysctl_optmem_max);
+
+       if ((unsigned int)size <= optmem_max &&
+           atomic_read(&sk->sk_omem_alloc) + size < optmem_max) {
                void *mem;
                /* First do the add, to avoid the race if kmalloc
                 * might sleep.
@@ -3309,8 +3311,8 @@ void sock_init_data(struct socket *sock, struct sock *sk)
        timer_setup(&sk->sk_timer, NULL, 0);
 
        sk->sk_allocation       =       GFP_KERNEL;
-       sk->sk_rcvbuf           =       sysctl_rmem_default;
-       sk->sk_sndbuf           =       sysctl_wmem_default;
+       sk->sk_rcvbuf           =       READ_ONCE(sysctl_rmem_default);
+       sk->sk_sndbuf           =       READ_ONCE(sysctl_wmem_default);
        sk->sk_state            =       TCP_CLOSE;
        sk_set_socket(sk, sock);
 
@@ -3365,7 +3367,7 @@ void sock_init_data(struct socket *sock, struct sock *sk)
 
 #ifdef CONFIG_NET_RX_BUSY_POLL
        sk->sk_napi_id          =       0;
-       sk->sk_ll_usec          =       sysctl_net_busy_read;
+       sk->sk_ll_usec          =       READ_ONCE(sysctl_net_busy_read);
 #endif
 
        sk->sk_max_pacing_rate = ~0UL;
index 71a1359..7258915 100644 (file)
@@ -234,14 +234,17 @@ static int set_default_qdisc(struct ctl_table *table, int write,
 static int proc_do_dev_weight(struct ctl_table *table, int write,
                           void *buffer, size_t *lenp, loff_t *ppos)
 {
-       int ret;
+       static DEFINE_MUTEX(dev_weight_mutex);
+       int ret, weight;
 
+       mutex_lock(&dev_weight_mutex);
        ret = proc_dointvec(table, write, buffer, lenp, ppos);
-       if (ret != 0)
-               return ret;
-
-       dev_rx_weight = weight_p * dev_weight_rx_bias;
-       dev_tx_weight = weight_p * dev_weight_tx_bias;
+       if (!ret && write) {
+               weight = READ_ONCE(weight_p);
+               WRITE_ONCE(dev_rx_weight, weight * dev_weight_rx_bias);
+               WRITE_ONCE(dev_tx_weight, weight * dev_weight_tx_bias);
+       }
+       mutex_unlock(&dev_weight_mutex);
 
        return ret;
 }
index ad6a666..1291c24 100644 (file)
@@ -2484,7 +2484,7 @@ static int dsa_slave_changeupper(struct net_device *dev,
                        if (!err)
                                dsa_bridge_mtu_normalization(dp);
                        if (err == -EOPNOTSUPP) {
-                               if (!extack->_msg)
+                               if (extack && !extack->_msg)
                                        NL_SET_ERR_MSG_MOD(extack,
                                                           "Offloading not supported");
                                err = 0;
index 92b778e..e8b9a92 100644 (file)
@@ -2682,23 +2682,27 @@ static __net_init int devinet_init_net(struct net *net)
 #endif
 
        if (!net_eq(net, &init_net)) {
-               if (IS_ENABLED(CONFIG_SYSCTL) &&
-                   sysctl_devconf_inherit_init_net == 3) {
+               switch (net_inherit_devconf()) {
+               case 3:
                        /* copy from the current netns */
                        memcpy(all, current->nsproxy->net_ns->ipv4.devconf_all,
                               sizeof(ipv4_devconf));
                        memcpy(dflt,
                               current->nsproxy->net_ns->ipv4.devconf_dflt,
                               sizeof(ipv4_devconf_dflt));
-               } else if (!IS_ENABLED(CONFIG_SYSCTL) ||
-                          sysctl_devconf_inherit_init_net != 2) {
-                       /* inherit == 0 or 1: copy from init_net */
+                       break;
+               case 0:
+               case 1:
+                       /* copy from init_net */
                        memcpy(all, init_net.ipv4.devconf_all,
                               sizeof(ipv4_devconf));
                        memcpy(dflt, init_net.ipv4.devconf_dflt,
                               sizeof(ipv4_devconf_dflt));
+                       break;
+               case 2:
+                       /* use compiled values */
+                       break;
                }
-               /* else inherit == 2: use compiled values */
        }
 
 #ifdef CONFIG_SYSCTL
index d7bd1da..04e2034 100644 (file)
@@ -1730,7 +1730,7 @@ void ip_send_unicast_reply(struct sock *sk, struct sk_buff *skb,
 
        sk->sk_protocol = ip_hdr(skb)->protocol;
        sk->sk_bound_dev_if = arg->bound_dev_if;
-       sk->sk_sndbuf = sysctl_wmem_default;
+       sk->sk_sndbuf = READ_ONCE(sysctl_wmem_default);
        ipc.sockc.mark = fl4.flowi4_mark;
        err = ip_append_data(sk, &fl4, ip_reply_glue_bits, arg->iov->iov_base,
                             len, 0, &ipc, &rt, MSG_DONTWAIT);
index a8a323e..e49a61a 100644 (file)
@@ -772,7 +772,7 @@ static int ip_set_mcast_msfilter(struct sock *sk, sockptr_t optval, int optlen)
 
        if (optlen < GROUP_FILTER_SIZE(0))
                return -EINVAL;
-       if (optlen > sysctl_optmem_max)
+       if (optlen > READ_ONCE(sysctl_optmem_max))
                return -ENOBUFS;
 
        gsf = memdup_sockptr(optval, optlen);
@@ -808,7 +808,7 @@ static int compat_ip_set_mcast_msfilter(struct sock *sk, sockptr_t optval,
 
        if (optlen < size0)
                return -EINVAL;
-       if (optlen > sysctl_optmem_max - 4)
+       if (optlen > READ_ONCE(sysctl_optmem_max) - 4)
                return -ENOBUFS;
 
        p = kmalloc(optlen + 4, GFP_KERNEL);
@@ -1233,7 +1233,7 @@ static int do_ip_setsockopt(struct sock *sk, int level, int optname,
 
                if (optlen < IP_MSFILTER_SIZE(0))
                        goto e_inval;
-               if (optlen > sysctl_optmem_max) {
+               if (optlen > READ_ONCE(sysctl_optmem_max)) {
                        err = -ENOBUFS;
                        break;
                }
index bbe2187..e5011c1 100644 (file)
@@ -1000,7 +1000,7 @@ new_segment:
 
        i = skb_shinfo(skb)->nr_frags;
        can_coalesce = skb_can_coalesce(skb, i, page, offset);
-       if (!can_coalesce && i >= sysctl_max_skb_frags) {
+       if (!can_coalesce && i >= READ_ONCE(sysctl_max_skb_frags)) {
                tcp_mark_push(tp, skb);
                goto new_segment;
        }
@@ -1354,7 +1354,7 @@ new_segment:
 
                        if (!skb_can_coalesce(skb, i, pfrag->page,
                                              pfrag->offset)) {
-                               if (i >= sysctl_max_skb_frags) {
+                               if (i >= READ_ONCE(sysctl_max_skb_frags)) {
                                        tcp_mark_push(tp, skb);
                                        goto new_segment;
                                }
index 78b654f..290019d 100644 (file)
@@ -239,7 +239,7 @@ void tcp_select_initial_window(const struct sock *sk, int __space, __u32 mss,
        if (wscale_ok) {
                /* Set window scaling on max possible window */
                space = max_t(u32, space, READ_ONCE(sock_net(sk)->ipv4.sysctl_tcp_rmem[2]));
-               space = max_t(u32, space, sysctl_rmem_max);
+               space = max_t(u32, space, READ_ONCE(sysctl_rmem_max));
                space = min_t(u32, space, *window_clamp);
                *rcv_wscale = clamp_t(int, ilog2(space) - 15,
                                      0, TCP_MAX_WSCALE);
index b624e3d..e15f64f 100644 (file)
@@ -7162,9 +7162,8 @@ static int __net_init addrconf_init_net(struct net *net)
        if (!dflt)
                goto err_alloc_dflt;
 
-       if (IS_ENABLED(CONFIG_SYSCTL) &&
-           !net_eq(net, &init_net)) {
-               switch (sysctl_devconf_inherit_init_net) {
+       if (!net_eq(net, &init_net)) {
+               switch (net_inherit_devconf()) {
                case 1:  /* copy from init_net */
                        memcpy(all, init_net.ipv6.devconf_all,
                               sizeof(ipv6_devconf));
index 222f6bf..e0dcc7a 100644 (file)
@@ -210,7 +210,7 @@ static int ipv6_set_mcast_msfilter(struct sock *sk, sockptr_t optval,
 
        if (optlen < GROUP_FILTER_SIZE(0))
                return -EINVAL;
-       if (optlen > sysctl_optmem_max)
+       if (optlen > READ_ONCE(sysctl_optmem_max))
                return -ENOBUFS;
 
        gsf = memdup_sockptr(optval, optlen);
@@ -244,7 +244,7 @@ static int compat_ipv6_set_mcast_msfilter(struct sock *sk, sockptr_t optval,
 
        if (optlen < size0)
                return -EINVAL;
-       if (optlen > sysctl_optmem_max - 4)
+       if (optlen > READ_ONCE(sysctl_optmem_max) - 4)
                return -ENOBUFS;
 
        p = kmalloc(optlen + 4, GFP_KERNEL);
index 7dd3629..38db006 100644 (file)
@@ -86,7 +86,6 @@ static int nf_ct_frag6_sysctl_register(struct net *net)
        table[1].extra2 = &nf_frag->fqdir->high_thresh;
        table[2].data   = &nf_frag->fqdir->high_thresh;
        table[2].extra1 = &nf_frag->fqdir->low_thresh;
-       table[2].extra2 = &nf_frag->fqdir->high_thresh;
 
        hdr = register_net_sysctl(net, "net/netfilter", table);
        if (hdr == NULL)
index fda2dcc..c85df5b 100644 (file)
@@ -1697,9 +1697,12 @@ static int pfkey_register(struct sock *sk, struct sk_buff *skb, const struct sad
                pfk->registered |= (1<<hdr->sadb_msg_satype);
        }
 
+       mutex_lock(&pfkey_mutex);
        xfrm_probe_algs();
 
        supp_skb = compose_sadb_supported(hdr, GFP_KERNEL | __GFP_ZERO);
+       mutex_unlock(&pfkey_mutex);
+
        if (!supp_skb) {
                if (hdr->sadb_msg_satype != SADB_SATYPE_UNSPEC)
                        pfk->registered &= ~(1<<hdr->sadb_msg_satype);
index da42575..d398f38 100644 (file)
@@ -1263,7 +1263,7 @@ static int mptcp_sendmsg_frag(struct sock *sk, struct sock *ssk,
 
                i = skb_shinfo(skb)->nr_frags;
                can_coalesce = skb_can_coalesce(skb, i, dfrag->page, offset);
-               if (!can_coalesce && i >= sysctl_max_skb_frags) {
+               if (!can_coalesce && i >= READ_ONCE(sysctl_max_skb_frags)) {
                        tcp_mark_push(tcp_sk(ssk), skb);
                        goto alloc_skb;
                }
index 9d43277..a56fd0b 100644 (file)
@@ -1280,12 +1280,12 @@ static void set_sock_size(struct sock *sk, int mode, int val)
        lock_sock(sk);
        if (mode) {
                val = clamp_t(int, val, (SOCK_MIN_SNDBUF + 1) / 2,
-                             sysctl_wmem_max);
+                             READ_ONCE(sysctl_wmem_max));
                sk->sk_sndbuf = val * 2;
                sk->sk_userlocks |= SOCK_SNDBUF_LOCK;
        } else {
                val = clamp_t(int, val, (SOCK_MIN_RCVBUF + 1) / 2,
-                             sysctl_rmem_max);
+                             READ_ONCE(sysctl_rmem_max));
                sk->sk_rcvbuf = val * 2;
                sk->sk_userlocks |= SOCK_RCVBUF_LOCK;
        }
index a63b51d..a634c72 100644 (file)
@@ -655,6 +655,37 @@ static bool tcp_in_window(struct nf_conn *ct,
                    tn->tcp_be_liberal)
                        res = true;
                if (!res) {
+                       bool seq_ok = before(seq, sender->td_maxend + 1);
+
+                       if (!seq_ok) {
+                               u32 overshot = end - sender->td_maxend + 1;
+                               bool ack_ok;
+
+                               ack_ok = after(sack, receiver->td_end - MAXACKWINDOW(sender) - 1);
+
+                               if (in_recv_win &&
+                                   ack_ok &&
+                                   overshot <= receiver->td_maxwin &&
+                                   before(sack, receiver->td_end + 1)) {
+                                       /* Work around TCPs that send more bytes than allowed by
+                                        * the receive window.
+                                        *
+                                        * If the (marked as invalid) packet is allowed to pass by
+                                        * the ruleset and the peer acks this data, then its possible
+                                        * all future packets will trigger 'ACK is over upper bound' check.
+                                        *
+                                        * Thus if only the sequence check fails then do update td_end so
+                                        * possible ACK for this data can update internal state.
+                                        */
+                                       sender->td_end = end;
+                                       sender->flags |= IP_CT_TCP_FLAG_DATA_UNACKNOWLEDGED;
+
+                                       nf_ct_l4proto_log_invalid(skb, ct, hook_state,
+                                                                 "%u bytes more than expected", overshot);
+                                       return res;
+                               }
+                       }
+
                        nf_ct_l4proto_log_invalid(skb, ct, hook_state,
                        "%s",
                        before(seq, sender->td_maxend + 1) ?
index 765ac77..81c26a9 100644 (file)
@@ -437,12 +437,17 @@ static void nf_flow_offload_gc_step(struct nf_flowtable *flow_table,
        }
 }
 
+void nf_flow_table_gc_run(struct nf_flowtable *flow_table)
+{
+       nf_flow_table_iterate(flow_table, nf_flow_offload_gc_step, NULL);
+}
+
 static void nf_flow_offload_work_gc(struct work_struct *work)
 {
        struct nf_flowtable *flow_table;
 
        flow_table = container_of(work, struct nf_flowtable, gc_work.work);
-       nf_flow_table_iterate(flow_table, nf_flow_offload_gc_step, NULL);
+       nf_flow_table_gc_run(flow_table);
        queue_delayed_work(system_power_efficient_wq, &flow_table->gc_work, HZ);
 }
 
@@ -600,11 +605,11 @@ void nf_flow_table_free(struct nf_flowtable *flow_table)
        mutex_unlock(&flowtable_lock);
 
        cancel_delayed_work_sync(&flow_table->gc_work);
-       nf_flow_table_iterate(flow_table, nf_flow_table_do_cleanup, NULL);
-       nf_flow_table_iterate(flow_table, nf_flow_offload_gc_step, NULL);
        nf_flow_table_offload_flush(flow_table);
-       if (nf_flowtable_hw_offload(flow_table))
-               nf_flow_table_iterate(flow_table, nf_flow_offload_gc_step, NULL);
+       /* ... no more pending work after this stage ... */
+       nf_flow_table_iterate(flow_table, nf_flow_table_do_cleanup, NULL);
+       nf_flow_table_gc_run(flow_table);
+       nf_flow_table_offload_flush_cleanup(flow_table);
        rhashtable_destroy(&flow_table->rhashtable);
 }
 EXPORT_SYMBOL_GPL(nf_flow_table_free);
index 103b6cb..b04645c 100644 (file)
@@ -1074,6 +1074,14 @@ void nf_flow_offload_stats(struct nf_flowtable *flowtable,
        flow_offload_queue_work(offload);
 }
 
+void nf_flow_table_offload_flush_cleanup(struct nf_flowtable *flowtable)
+{
+       if (nf_flowtable_hw_offload(flowtable)) {
+               flush_workqueue(nf_flow_offload_del_wq);
+               nf_flow_table_gc_run(flowtable);
+       }
+}
+
 void nf_flow_table_offload_flush(struct nf_flowtable *flowtable)
 {
        if (nf_flowtable_hw_offload(flowtable)) {
index 62cfb0e..2ee50e2 100644 (file)
@@ -32,7 +32,6 @@ static LIST_HEAD(nf_tables_objects);
 static LIST_HEAD(nf_tables_flowtables);
 static LIST_HEAD(nf_tables_destroy_list);
 static DEFINE_SPINLOCK(nf_tables_destroy_list_lock);
-static u64 table_handle;
 
 enum {
        NFT_VALIDATE_SKIP       = 0,
@@ -1235,7 +1234,7 @@ static int nf_tables_newtable(struct sk_buff *skb, const struct nfnl_info *info,
        INIT_LIST_HEAD(&table->flowtables);
        table->family = family;
        table->flags = flags;
-       table->handle = ++table_handle;
+       table->handle = ++nft_net->table_handle;
        if (table->flags & NFT_TABLE_F_OWNER)
                table->nlpid = NETLINK_CB(skb).portid;
 
@@ -2196,9 +2195,9 @@ static int nf_tables_addchain(struct nft_ctx *ctx, u8 family, u8 genmask,
                              struct netlink_ext_ack *extack)
 {
        const struct nlattr * const *nla = ctx->nla;
+       struct nft_stats __percpu *stats = NULL;
        struct nft_table *table = ctx->table;
        struct nft_base_chain *basechain;
-       struct nft_stats __percpu *stats;
        struct net *net = ctx->net;
        char name[NFT_NAME_MAXLEN];
        struct nft_rule_blob *blob;
@@ -2236,7 +2235,6 @@ static int nf_tables_addchain(struct nft_ctx *ctx, u8 family, u8 genmask,
                                return PTR_ERR(stats);
                        }
                        rcu_assign_pointer(basechain->stats, stats);
-                       static_branch_inc(&nft_counters_enabled);
                }
 
                err = nft_basechain_init(basechain, family, &hook, flags);
@@ -2319,6 +2317,9 @@ static int nf_tables_addchain(struct nft_ctx *ctx, u8 family, u8 genmask,
                goto err_unregister_hook;
        }
 
+       if (stats)
+               static_branch_inc(&nft_counters_enabled);
+
        table->use++;
 
        return 0;
@@ -2574,6 +2575,9 @@ static int nf_tables_newchain(struct sk_buff *skb, const struct nfnl_info *info,
        nft_ctx_init(&ctx, net, skb, info->nlh, family, table, chain, nla);
 
        if (chain != NULL) {
+               if (chain->flags & NFT_CHAIN_BINDING)
+                       return -EINVAL;
+
                if (info->nlh->nlmsg_flags & NLM_F_EXCL) {
                        NL_SET_BAD_ATTR(extack, attr);
                        return -EEXIST;
@@ -9707,6 +9711,8 @@ static int nft_verdict_init(const struct nft_ctx *ctx, struct nft_data *data,
                        return PTR_ERR(chain);
                if (nft_is_base_chain(chain))
                        return -EOPNOTSUPP;
+               if (nft_chain_is_bound(chain))
+                       return -EINVAL;
                if (desc->flags & NFT_DATA_DESC_SETELEM &&
                    chain->flags & NFT_CHAIN_BINDING)
                        return -EINVAL;
index 0053a69..89342cc 100644 (file)
@@ -115,9 +115,21 @@ static int nft_osf_validate(const struct nft_ctx *ctx,
                            const struct nft_expr *expr,
                            const struct nft_data **data)
 {
-       return nft_chain_validate_hooks(ctx->chain, (1 << NF_INET_LOCAL_IN) |
-                                                   (1 << NF_INET_PRE_ROUTING) |
-                                                   (1 << NF_INET_FORWARD));
+       unsigned int hooks;
+
+       switch (ctx->family) {
+       case NFPROTO_IPV4:
+       case NFPROTO_IPV6:
+       case NFPROTO_INET:
+               hooks = (1 << NF_INET_LOCAL_IN) |
+                       (1 << NF_INET_PRE_ROUTING) |
+                       (1 << NF_INET_FORWARD);
+               break;
+       default:
+               return -EOPNOTSUPP;
+       }
+
+       return nft_chain_validate_hooks(ctx->chain, hooks);
 }
 
 static bool nft_osf_reduce(struct nft_regs_track *track,
index 2e7ac00..eb0e40c 100644 (file)
@@ -740,17 +740,23 @@ static int nft_payload_set_init(const struct nft_ctx *ctx,
                                const struct nlattr * const tb[])
 {
        struct nft_payload_set *priv = nft_expr_priv(expr);
+       u32 csum_offset, csum_type = NFT_PAYLOAD_CSUM_NONE;
+       int err;
 
        priv->base        = ntohl(nla_get_be32(tb[NFTA_PAYLOAD_BASE]));
        priv->offset      = ntohl(nla_get_be32(tb[NFTA_PAYLOAD_OFFSET]));
        priv->len         = ntohl(nla_get_be32(tb[NFTA_PAYLOAD_LEN]));
 
        if (tb[NFTA_PAYLOAD_CSUM_TYPE])
-               priv->csum_type =
-                       ntohl(nla_get_be32(tb[NFTA_PAYLOAD_CSUM_TYPE]));
-       if (tb[NFTA_PAYLOAD_CSUM_OFFSET])
-               priv->csum_offset =
-                       ntohl(nla_get_be32(tb[NFTA_PAYLOAD_CSUM_OFFSET]));
+               csum_type = ntohl(nla_get_be32(tb[NFTA_PAYLOAD_CSUM_TYPE]));
+       if (tb[NFTA_PAYLOAD_CSUM_OFFSET]) {
+               err = nft_parse_u32_check(tb[NFTA_PAYLOAD_CSUM_OFFSET], U8_MAX,
+                                         &csum_offset);
+               if (err < 0)
+                       return err;
+
+               priv->csum_offset = csum_offset;
+       }
        if (tb[NFTA_PAYLOAD_CSUM_FLAGS]) {
                u32 flags;
 
@@ -761,7 +767,7 @@ static int nft_payload_set_init(const struct nft_ctx *ctx,
                priv->csum_flags = flags;
        }
 
-       switch (priv->csum_type) {
+       switch (csum_type) {
        case NFT_PAYLOAD_CSUM_NONE:
        case NFT_PAYLOAD_CSUM_INET:
                break;
@@ -775,6 +781,7 @@ static int nft_payload_set_init(const struct nft_ctx *ctx,
        default:
                return -EOPNOTSUPP;
        }
+       priv->csum_type = csum_type;
 
        return nft_parse_register_load(tb[NFTA_PAYLOAD_SREG], &priv->sreg,
                                       priv->len);
@@ -833,6 +840,7 @@ nft_payload_select_ops(const struct nft_ctx *ctx,
 {
        enum nft_payload_bases base;
        unsigned int offset, len;
+       int err;
 
        if (tb[NFTA_PAYLOAD_BASE] == NULL ||
            tb[NFTA_PAYLOAD_OFFSET] == NULL ||
@@ -859,8 +867,13 @@ nft_payload_select_ops(const struct nft_ctx *ctx,
        if (tb[NFTA_PAYLOAD_DREG] == NULL)
                return ERR_PTR(-EINVAL);
 
-       offset = ntohl(nla_get_be32(tb[NFTA_PAYLOAD_OFFSET]));
-       len    = ntohl(nla_get_be32(tb[NFTA_PAYLOAD_LEN]));
+       err = nft_parse_u32_check(tb[NFTA_PAYLOAD_OFFSET], U8_MAX, &offset);
+       if (err < 0)
+               return ERR_PTR(err);
+
+       err = nft_parse_u32_check(tb[NFTA_PAYLOAD_LEN], U8_MAX, &len);
+       if (err < 0)
+               return ERR_PTR(err);
 
        if (len <= 4 && is_power_of_2(len) && IS_ALIGNED(offset, len) &&
            base != NFT_PAYLOAD_LL_HEADER && base != NFT_PAYLOAD_INNER_HEADER)
index 68b2eed..62da25a 100644 (file)
@@ -312,6 +312,13 @@ static int nft_tproxy_dump(struct sk_buff *skb,
        return 0;
 }
 
+static int nft_tproxy_validate(const struct nft_ctx *ctx,
+                              const struct nft_expr *expr,
+                              const struct nft_data **data)
+{
+       return nft_chain_validate_hooks(ctx->chain, 1 << NF_INET_PRE_ROUTING);
+}
+
 static struct nft_expr_type nft_tproxy_type;
 static const struct nft_expr_ops nft_tproxy_ops = {
        .type           = &nft_tproxy_type,
@@ -321,6 +328,7 @@ static const struct nft_expr_ops nft_tproxy_ops = {
        .destroy        = nft_tproxy_destroy,
        .dump           = nft_tproxy_dump,
        .reduce         = NFT_REDUCE_READONLY,
+       .validate       = nft_tproxy_validate,
 };
 
 static struct nft_expr_type nft_tproxy_type __read_mostly = {
index 5edaade..983ade4 100644 (file)
@@ -161,6 +161,7 @@ static const struct nft_expr_ops nft_tunnel_get_ops = {
 
 static struct nft_expr_type nft_tunnel_type __read_mostly = {
        .name           = "tunnel",
+       .family         = NFPROTO_NETDEV,
        .ops            = &nft_tunnel_get_ops,
        .policy         = nft_tunnel_policy,
        .maxattr        = NFTA_TUNNEL_MAX,
index 11c45c8..036d92c 100644 (file)
@@ -96,7 +96,8 @@ static void rose_loopback_timer(struct timer_list *unused)
                }
 
                if (frametype == ROSE_CALL_REQUEST) {
-                       if (!rose_loopback_neigh->dev) {
+                       if (!rose_loopback_neigh->dev &&
+                           !rose_loopback_neigh->loopback) {
                                kfree_skb(skb);
                                continue;
                        }
index 84d0a41..6401cdf 100644 (file)
@@ -285,8 +285,10 @@ struct rxrpc_call *rxrpc_new_client_call(struct rxrpc_sock *rx,
        _enter("%p,%lx", rx, p->user_call_ID);
 
        limiter = rxrpc_get_call_slot(p, gfp);
-       if (!limiter)
+       if (!limiter) {
+               release_sock(&rx->sk);
                return ERR_PTR(-ERESTARTSYS);
+       }
 
        call = rxrpc_alloc_client_call(rx, srx, gfp, debug_id);
        if (IS_ERR(call)) {
index 1d38e27..3c3a626 100644 (file)
@@ -51,10 +51,7 @@ static int rxrpc_wait_for_tx_window_intr(struct rxrpc_sock *rx,
                        return sock_intr_errno(*timeo);
 
                trace_rxrpc_transmit(call, rxrpc_transmit_wait);
-               mutex_unlock(&call->user_mutex);
                *timeo = schedule_timeout(*timeo);
-               if (mutex_lock_interruptible(&call->user_mutex) < 0)
-                       return sock_intr_errno(*timeo);
        }
 }
 
@@ -290,37 +287,48 @@ out:
 static int rxrpc_send_data(struct rxrpc_sock *rx,
                           struct rxrpc_call *call,
                           struct msghdr *msg, size_t len,
-                          rxrpc_notify_end_tx_t notify_end_tx)
+                          rxrpc_notify_end_tx_t notify_end_tx,
+                          bool *_dropped_lock)
 {
        struct rxrpc_skb_priv *sp;
        struct sk_buff *skb;
        struct sock *sk = &rx->sk;
+       enum rxrpc_call_state state;
        long timeo;
-       bool more;
-       int ret, copied;
+       bool more = msg->msg_flags & MSG_MORE;
+       int ret, copied = 0;
 
        timeo = sock_sndtimeo(sk, msg->msg_flags & MSG_DONTWAIT);
 
        /* this should be in poll */
        sk_clear_bit(SOCKWQ_ASYNC_NOSPACE, sk);
 
+reload:
+       ret = -EPIPE;
        if (sk->sk_shutdown & SEND_SHUTDOWN)
-               return -EPIPE;
-
-       more = msg->msg_flags & MSG_MORE;
-
+               goto maybe_error;
+       state = READ_ONCE(call->state);
+       ret = -ESHUTDOWN;
+       if (state >= RXRPC_CALL_COMPLETE)
+               goto maybe_error;
+       ret = -EPROTO;
+       if (state != RXRPC_CALL_CLIENT_SEND_REQUEST &&
+           state != RXRPC_CALL_SERVER_ACK_REQUEST &&
+           state != RXRPC_CALL_SERVER_SEND_REPLY)
+               goto maybe_error;
+
+       ret = -EMSGSIZE;
        if (call->tx_total_len != -1) {
-               if (len > call->tx_total_len)
-                       return -EMSGSIZE;
-               if (!more && len != call->tx_total_len)
-                       return -EMSGSIZE;
+               if (len - copied > call->tx_total_len)
+                       goto maybe_error;
+               if (!more && len - copied != call->tx_total_len)
+                       goto maybe_error;
        }
 
        skb = call->tx_pending;
        call->tx_pending = NULL;
        rxrpc_see_skb(skb, rxrpc_skb_seen);
 
-       copied = 0;
        do {
                /* Check to see if there's a ping ACK to reply to. */
                if (call->ackr_reason == RXRPC_ACK_PING_RESPONSE)
@@ -331,16 +339,8 @@ static int rxrpc_send_data(struct rxrpc_sock *rx,
 
                        _debug("alloc");
 
-                       if (!rxrpc_check_tx_space(call, NULL)) {
-                               ret = -EAGAIN;
-                               if (msg->msg_flags & MSG_DONTWAIT)
-                                       goto maybe_error;
-                               ret = rxrpc_wait_for_tx_window(rx, call,
-                                                              &timeo,
-                                                              msg->msg_flags & MSG_WAITALL);
-                               if (ret < 0)
-                                       goto maybe_error;
-                       }
+                       if (!rxrpc_check_tx_space(call, NULL))
+                               goto wait_for_space;
 
                        /* Work out the maximum size of a packet.  Assume that
                         * the security header is going to be in the padded
@@ -468,6 +468,27 @@ maybe_error:
 efault:
        ret = -EFAULT;
        goto out;
+
+wait_for_space:
+       ret = -EAGAIN;
+       if (msg->msg_flags & MSG_DONTWAIT)
+               goto maybe_error;
+       mutex_unlock(&call->user_mutex);
+       *_dropped_lock = true;
+       ret = rxrpc_wait_for_tx_window(rx, call, &timeo,
+                                      msg->msg_flags & MSG_WAITALL);
+       if (ret < 0)
+               goto maybe_error;
+       if (call->interruptibility == RXRPC_INTERRUPTIBLE) {
+               if (mutex_lock_interruptible(&call->user_mutex) < 0) {
+                       ret = sock_intr_errno(timeo);
+                       goto maybe_error;
+               }
+       } else {
+               mutex_lock(&call->user_mutex);
+       }
+       *_dropped_lock = false;
+       goto reload;
 }
 
 /*
@@ -629,6 +650,7 @@ int rxrpc_do_sendmsg(struct rxrpc_sock *rx, struct msghdr *msg, size_t len)
        enum rxrpc_call_state state;
        struct rxrpc_call *call;
        unsigned long now, j;
+       bool dropped_lock = false;
        int ret;
 
        struct rxrpc_send_params p = {
@@ -737,21 +759,13 @@ int rxrpc_do_sendmsg(struct rxrpc_sock *rx, struct msghdr *msg, size_t len)
                        ret = rxrpc_send_abort_packet(call);
        } else if (p.command != RXRPC_CMD_SEND_DATA) {
                ret = -EINVAL;
-       } else if (rxrpc_is_client_call(call) &&
-                  state != RXRPC_CALL_CLIENT_SEND_REQUEST) {
-               /* request phase complete for this client call */
-               ret = -EPROTO;
-       } else if (rxrpc_is_service_call(call) &&
-                  state != RXRPC_CALL_SERVER_ACK_REQUEST &&
-                  state != RXRPC_CALL_SERVER_SEND_REPLY) {
-               /* Reply phase not begun or not complete for service call. */
-               ret = -EPROTO;
        } else {
-               ret = rxrpc_send_data(rx, call, msg, len, NULL);
+               ret = rxrpc_send_data(rx, call, msg, len, NULL, &dropped_lock);
        }
 
 out_put_unlock:
-       mutex_unlock(&call->user_mutex);
+       if (!dropped_lock)
+               mutex_unlock(&call->user_mutex);
 error_put:
        rxrpc_put_call(call, rxrpc_call_put);
        _leave(" = %d", ret);
@@ -779,6 +793,7 @@ int rxrpc_kernel_send_data(struct socket *sock, struct rxrpc_call *call,
                           struct msghdr *msg, size_t len,
                           rxrpc_notify_end_tx_t notify_end_tx)
 {
+       bool dropped_lock = false;
        int ret;
 
        _enter("{%d,%s},", call->debug_id, rxrpc_call_states[call->state]);
@@ -796,7 +811,7 @@ int rxrpc_kernel_send_data(struct socket *sock, struct rxrpc_call *call,
        case RXRPC_CALL_SERVER_ACK_REQUEST:
        case RXRPC_CALL_SERVER_SEND_REPLY:
                ret = rxrpc_send_data(rxrpc_sk(sock->sk), call, msg, len,
-                                     notify_end_tx);
+                                     notify_end_tx, &dropped_lock);
                break;
        case RXRPC_CALL_COMPLETE:
                read_lock_bh(&call->state_lock);
@@ -810,7 +825,8 @@ int rxrpc_kernel_send_data(struct socket *sock, struct rxrpc_call *call,
                break;
        }
 
-       mutex_unlock(&call->user_mutex);
+       if (!dropped_lock)
+               mutex_unlock(&call->user_mutex);
        _leave(" = %d", ret);
        return ret;
 }
index d47b968..99b697a 100644 (file)
@@ -409,7 +409,7 @@ static inline bool qdisc_restart(struct Qdisc *q, int *packets)
 
 void __qdisc_run(struct Qdisc *q)
 {
-       int quota = dev_tx_weight;
+       int quota = READ_ONCE(dev_tx_weight);
        int packets;
 
        while (qdisc_restart(q, &packets)) {
index 9b27c5e..7378375 100644 (file)
@@ -1801,7 +1801,7 @@ int __sys_listen(int fd, int backlog)
 
        sock = sockfd_lookup_light(fd, &err, &fput_needed);
        if (sock) {
-               somaxconn = sock_net(sock->sk)->core.sysctl_somaxconn;
+               somaxconn = READ_ONCE(sock_net(sock->sk)->core.sysctl_somaxconn);
                if ((unsigned int)backlog > somaxconn)
                        backlog = somaxconn;
 
index b098e70..7d268a2 100644 (file)
@@ -1902,7 +1902,7 @@ call_encode(struct rpc_task *task)
                        break;
                case -EKEYEXPIRED:
                        if (!task->tk_cred_retry) {
-                               rpc_exit(task, task->tk_status);
+                               rpc_call_rpcerror(task, task->tk_status);
                        } else {
                                task->tk_action = call_refresh;
                                task->tk_cred_retry--;
index 82d14ee..974eb97 100644 (file)
@@ -168,7 +168,7 @@ int espintcp_queue_out(struct sock *sk, struct sk_buff *skb)
 {
        struct espintcp_ctx *ctx = espintcp_getctx(sk);
 
-       if (skb_queue_len(&ctx->out_queue) >= netdev_max_backlog)
+       if (skb_queue_len(&ctx->out_queue) >= READ_ONCE(netdev_max_backlog))
                return -ENOBUFS;
 
        __skb_queue_tail(&ctx->out_queue, skb);
index 144238a..b2f4ec9 100644 (file)
@@ -669,7 +669,6 @@ resume:
 
                x->curlft.bytes += skb->len;
                x->curlft.packets++;
-               x->curlft.use_time = ktime_get_real_seconds();
 
                spin_unlock(&x->lock);
 
@@ -783,7 +782,7 @@ int xfrm_trans_queue_net(struct net *net, struct sk_buff *skb,
 
        trans = this_cpu_ptr(&xfrm_trans_tasklet);
 
-       if (skb_queue_len(&trans->queue) >= netdev_max_backlog)
+       if (skb_queue_len(&trans->queue) >= READ_ONCE(netdev_max_backlog))
                return -ENOBUFS;
 
        BUILD_BUG_ON(sizeof(struct xfrm_trans_cb) > sizeof(skb->cb));
index 555ab35..9a5e79a 100644 (file)
@@ -534,7 +534,6 @@ static int xfrm_output_one(struct sk_buff *skb, int err)
 
                x->curlft.bytes += skb->len;
                x->curlft.packets++;
-               x->curlft.use_time = ktime_get_real_seconds();
 
                spin_unlock_bh(&x->lock);
 
index f1a0bab..cc6ab79 100644 (file)
@@ -3162,7 +3162,7 @@ ok:
        return dst;
 
 nopol:
-       if (!(dst_orig->dev->flags & IFF_LOOPBACK) &&
+       if ((!dst_orig->dev || !(dst_orig->dev->flags & IFF_LOOPBACK)) &&
            net->xfrm.policy_default[dir] == XFRM_USERPOLICY_BLOCK) {
                err = -EPERM;
                goto error;
@@ -3599,6 +3599,7 @@ int __xfrm_policy_check(struct sock *sk, int dir, struct sk_buff *skb,
                if (pols[1]) {
                        if (IS_ERR(pols[1])) {
                                XFRM_INC_STATS(net, LINUX_MIB_XFRMINPOLERROR);
+                               xfrm_pol_put(pols[0]);
                                return 0;
                        }
                        pols[1]->curlft.use_time = ktime_get_real_seconds();
index 52e60e6..91c32a3 100644 (file)
@@ -1592,6 +1592,7 @@ static struct xfrm_state *xfrm_state_clone(struct xfrm_state *orig,
        x->replay = orig->replay;
        x->preplay = orig->preplay;
        x->mapping_maxage = orig->mapping_maxage;
+       x->lastused = orig->lastused;
        x->new_mapping = 0;
        x->new_mapping_sport = 0;
 
index 14d30fe..4b95de2 100644 (file)
@@ -2660,4 +2660,8 @@ int security_uring_sqpoll(void)
 {
        return call_int_hook(uring_sqpoll, 0);
 }
+int security_uring_cmd(struct io_uring_cmd *ioucmd)
+{
+       return call_int_hook(uring_cmd, 0, ioucmd);
+}
 #endif /* CONFIG_IO_URING */
index 7957350..03bca97 100644 (file)
@@ -91,6 +91,7 @@
 #include <uapi/linux/mount.h>
 #include <linux/fsnotify.h>
 #include <linux/fanotify.h>
+#include <linux/io_uring.h>
 
 #include "avc.h"
 #include "objsec.h"
@@ -6987,6 +6988,28 @@ static int selinux_uring_sqpoll(void)
        return avc_has_perm(&selinux_state, sid, sid,
                            SECCLASS_IO_URING, IO_URING__SQPOLL, NULL);
 }
+
+/**
+ * selinux_uring_cmd - check if IORING_OP_URING_CMD is allowed
+ * @ioucmd: the io_uring command structure
+ *
+ * Check to see if the current domain is allowed to execute an
+ * IORING_OP_URING_CMD against the device/file specified in @ioucmd.
+ *
+ */
+static int selinux_uring_cmd(struct io_uring_cmd *ioucmd)
+{
+       struct file *file = ioucmd->file;
+       struct inode *inode = file_inode(file);
+       struct inode_security_struct *isec = selinux_inode(inode);
+       struct common_audit_data ad;
+
+       ad.type = LSM_AUDIT_DATA_FILE;
+       ad.u.file = file;
+
+       return avc_has_perm(&selinux_state, current_sid(), isec->sid,
+                           SECCLASS_IO_URING, IO_URING__CMD, &ad);
+}
 #endif /* CONFIG_IO_URING */
 
 /*
@@ -7231,6 +7254,7 @@ static struct security_hook_list selinux_hooks[] __lsm_ro_after_init = {
 #ifdef CONFIG_IO_URING
        LSM_HOOK_INIT(uring_override_creds, selinux_uring_override_creds),
        LSM_HOOK_INIT(uring_sqpoll, selinux_uring_sqpoll),
+       LSM_HOOK_INIT(uring_cmd, selinux_uring_cmd),
 #endif
 
        /*
index ff757ae..1c2f41f 100644 (file)
@@ -253,7 +253,7 @@ const struct security_class_mapping secclass_map[] = {
        { "anon_inode",
          { COMMON_FILE_PERMS, NULL } },
        { "io_uring",
-         { "override_creds", "sqpoll", NULL } },
+         { "override_creds", "sqpoll", "cmd", NULL } },
        { NULL }
   };
 
index 0018314..bffccdc 100644 (file)
@@ -42,6 +42,7 @@
 #include <linux/fs_context.h>
 #include <linux/fs_parser.h>
 #include <linux/watch_queue.h>
+#include <linux/io_uring.h>
 #include "smack.h"
 
 #define TRANS_TRUE     "TRUE"
@@ -4732,6 +4733,36 @@ static int smack_uring_sqpoll(void)
        return -EPERM;
 }
 
+/**
+ * smack_uring_cmd - check on file operations for io_uring
+ * @ioucmd: the command in question
+ *
+ * Make a best guess about whether a io_uring "command" should
+ * be allowed. Use the same logic used for determining if the
+ * file could be opened for read in the absence of better criteria.
+ */
+static int smack_uring_cmd(struct io_uring_cmd *ioucmd)
+{
+       struct file *file = ioucmd->file;
+       struct smk_audit_info ad;
+       struct task_smack *tsp;
+       struct inode *inode;
+       int rc;
+
+       if (!file)
+               return -EINVAL;
+
+       tsp = smack_cred(file->f_cred);
+       inode = file_inode(file);
+
+       smk_ad_init(&ad, __func__, LSM_AUDIT_DATA_PATH);
+       smk_ad_setfield_u_fs_path(&ad, file->f_path);
+       rc = smk_tskacc(tsp, smk_of_inode(inode), MAY_READ, &ad);
+       rc = smk_bu_credfile(file->f_cred, file, MAY_READ, rc);
+
+       return rc;
+}
+
 #endif /* CONFIG_IO_URING */
 
 struct lsm_blob_sizes smack_blob_sizes __lsm_ro_after_init = {
@@ -4889,6 +4920,7 @@ static struct security_hook_list smack_hooks[] __lsm_ro_after_init = {
 #ifdef CONFIG_IO_URING
        LSM_HOOK_INIT(uring_override_creds, smack_uring_override_creds),
        LSM_HOOK_INIT(uring_sqpoll, smack_uring_sqpoll),
+       LSM_HOOK_INIT(uring_cmd, smack_uring_cmd),
 #endif
 };
 
index 3bb1343..316917b 100644 (file)
@@ -75,9 +75,11 @@ struct kvm_regs {
 
 /* KVM_ARM_SET_DEVICE_ADDR ioctl id encoding */
 #define KVM_ARM_DEVICE_TYPE_SHIFT      0
-#define KVM_ARM_DEVICE_TYPE_MASK       (0xffff << KVM_ARM_DEVICE_TYPE_SHIFT)
+#define KVM_ARM_DEVICE_TYPE_MASK       GENMASK(KVM_ARM_DEVICE_TYPE_SHIFT + 15, \
+                                               KVM_ARM_DEVICE_TYPE_SHIFT)
 #define KVM_ARM_DEVICE_ID_SHIFT                16
-#define KVM_ARM_DEVICE_ID_MASK         (0xffff << KVM_ARM_DEVICE_ID_SHIFT)
+#define KVM_ARM_DEVICE_ID_MASK         GENMASK(KVM_ARM_DEVICE_ID_SHIFT + 15, \
+                                               KVM_ARM_DEVICE_ID_SHIFT)
 
 /* Supported device IDs */
 #define KVM_ARM_DEVICE_VGIC_V2         0
index 24ae305..1bdd834 100644 (file)
@@ -36,4 +36,8 @@
 #include <linux/compiler-gcc.h>
 #endif
 
+#ifndef asm_volatile_goto
+#define asm_volatile_goto(x...) asm goto(x)
+#endif
+
 #endif /* __LINUX_COMPILER_TYPES_H */
index 9167825..e55fdf9 100644 (file)
@@ -162,32 +162,34 @@ static bool __dead_end_function(struct objtool_file *file, struct symbol *func,
 
        /*
         * Unfortunately these have to be hard coded because the noreturn
-        * attribute isn't provided in ELF data.
+        * attribute isn't provided in ELF data. Keep 'em sorted.
         */
        static const char * const global_noreturns[] = {
+               "__invalid_creds",
+               "__module_put_and_kthread_exit",
+               "__reiserfs_panic",
                "__stack_chk_fail",
-               "panic",
+               "__ubsan_handle_builtin_unreachable",
+               "cpu_bringup_and_idle",
+               "cpu_startup_entry",
                "do_exit",
+               "do_group_exit",
                "do_task_dead",
-               "kthread_exit",
-               "make_task_dead",
-               "__module_put_and_kthread_exit",
+               "ex_handler_msr_mce",
+               "fortify_panic",
                "kthread_complete_and_exit",
-               "__reiserfs_panic",
+               "kthread_exit",
+               "kunit_try_catch_throw",
                "lbug_with_loc",
-               "fortify_panic",
-               "usercopy_abort",
                "machine_real_restart",
+               "make_task_dead",
+               "panic",
                "rewind_stack_and_make_dead",
-               "kunit_try_catch_throw",
-               "xen_start_kernel",
-               "cpu_bringup_and_idle",
-               "do_group_exit",
+               "sev_es_terminate",
+               "snp_abort",
                "stop_this_cpu",
-               "__invalid_creds",
-               "cpu_startup_entry",
-               "__ubsan_handle_builtin_unreachable",
-               "ex_handler_msr_mce",
+               "usercopy_abort",
+               "xen_start_kernel",
        };
 
        if (!func)
index c930209..e7a776a 100644 (file)
@@ -21,11 +21,6 @@ cat /sys/devices/cpu_atom/cpus
 
 It indicates cpu0-cpu15 are core cpus and cpu16-cpu23 are atom cpus.
 
-Quickstart
-
-List hybrid event
------------------
-
 As before, use perf-list to list the symbolic event.
 
 perf list
@@ -40,7 +35,6 @@ the event is belong to. Same event name but with different pmu can
 be supported.
 
 Enable hybrid event with a specific pmu
----------------------------------------
 
 To enable a core only event or atom only event, following syntax is supported:
 
@@ -53,7 +47,6 @@ For example, count the 'cycles' event on core cpus.
        perf stat -e cpu_core/cycles/
 
 Create two events for one hardware event automatically
-------------------------------------------------------
 
 When creating one event and the event is available on both atom and core,
 two events are created automatically. One is for atom, the other is for
@@ -132,7 +125,6 @@ For perf-stat result, it displays two events:
 The first 'cycles' is core event, the second 'cycles' is atom event.
 
 Thread mode example:
---------------------
 
 perf-stat reports the scaled counts for hybrid event and with a percentage
 displayed. The percentage is the event's running time/enabling time.
@@ -176,14 +168,12 @@ perf_event_attr:
        604,097,080      cpu_atom/cycles/                                              (99.57%)
 
 perf-record:
-------------
 
 If there is no '-e' specified in perf record, on hybrid platform,
 it creates two default 'cycles' and adds them to event list. One
 is for core, the other is for atom.
 
 perf-stat:
-----------
 
 If there is no '-e' specified in perf stat, on hybrid platform,
 besides of software events, following events are created and
index 099817e..0228efc 100644 (file)
@@ -397,6 +397,9 @@ following filters are defined:
        - abort_tx: only when the target is a hardware transaction abort
        - cond: conditional branches
        - save_type: save branch type during sampling in case binary is not available later
+                    For the platforms with Intel Arch LBR support (12th-Gen+ client or
+                    4th-Gen Xeon+ server), the save branch type is unconditionally enabled
+                    when the taken branch stack sampling is enabled.
 
 +
 The option requires at least one branch type among any, any_call, any_ret, ind_call, cond.
@@ -757,8 +760,6 @@ events in data directory files. Option specified with no or empty value
 defaults to CPU layout. Masks defined or provided by the option value are
 filtered through the mask provided by -C option.
 
-include::intel-hybrid.txt[]
-
 --debuginfod[=URLs]::
        Specify debuginfod URL to be used when cacheing perf.data binaries,
        it follows the same syntax as the DEBUGINFOD_URLS variable, like:
@@ -778,6 +779,8 @@ include::intel-hybrid.txt[]
        only, as of now.  So the applications built without the frame
        pointer might see bogus addresses.
 
+include::intel-hybrid.txt[]
+
 SEE ALSO
 --------
 linkperf:perf-stat[1], linkperf:perf-list[1], linkperf:perf-intel-pt[1]
index 0661a1c..2171f02 100644 (file)
@@ -265,7 +265,7 @@ endif
 # defined. get-executable-or-default fails with an error if the first argument is supplied but
 # doesn't exist.
 override PYTHON_CONFIG := $(call get-executable-or-default,PYTHON_CONFIG,$(PYTHON_AUTO))
-override PYTHON := $(call get-executable-or-default,PYTHON,$(subst -config,,$(PYTHON_AUTO)))
+override PYTHON := $(call get-executable-or-default,PYTHON,$(subst -config,,$(PYTHON_CONFIG)))
 
 grep-libs  = $(filter -l%,$(1))
 strip-libs  = $(filter-out -l%,$(1))
index 2f6cd1b..a5cf243 100644 (file)
@@ -3355,7 +3355,8 @@ static bool schedstat_events_exposed(void)
 static int __cmd_record(int argc, const char **argv)
 {
        unsigned int rec_argc, i, j;
-       const char **rec_argv;
+       char **rec_argv;
+       const char **rec_argv_copy;
        const char * const record_args[] = {
                "record",
                "-a",
@@ -3384,6 +3385,7 @@ static int __cmd_record(int argc, const char **argv)
                ARRAY_SIZE(schedstat_args) : 0;
 
        struct tep_event *waking_event;
+       int ret;
 
        /*
         * +2 for either "-e", "sched:sched_wakeup" or
@@ -3391,14 +3393,18 @@ static int __cmd_record(int argc, const char **argv)
         */
        rec_argc = ARRAY_SIZE(record_args) + 2 + schedstat_argc + argc - 1;
        rec_argv = calloc(rec_argc + 1, sizeof(char *));
-
        if (rec_argv == NULL)
                return -ENOMEM;
+       rec_argv_copy = calloc(rec_argc + 1, sizeof(char *));
+       if (rec_argv_copy == NULL) {
+               free(rec_argv);
+               return -ENOMEM;
+       }
 
        for (i = 0; i < ARRAY_SIZE(record_args); i++)
                rec_argv[i] = strdup(record_args[i]);
 
-       rec_argv[i++] = "-e";
+       rec_argv[i++] = strdup("-e");
        waking_event = trace_event__tp_format("sched", "sched_waking");
        if (!IS_ERR(waking_event))
                rec_argv[i++] = strdup("sched:sched_waking");
@@ -3409,11 +3415,19 @@ static int __cmd_record(int argc, const char **argv)
                rec_argv[i++] = strdup(schedstat_args[j]);
 
        for (j = 1; j < (unsigned int)argc; j++, i++)
-               rec_argv[i] = argv[j];
+               rec_argv[i] = strdup(argv[j]);
 
        BUG_ON(i != rec_argc);
 
-       return cmd_record(i, rec_argv);
+       memcpy(rec_argv_copy, rec_argv, sizeof(char *) * rec_argc);
+       ret = cmd_record(rec_argc, rec_argv_copy);
+
+       for (i = 0; i < rec_argc; i++)
+               free(rec_argv[i]);
+       free(rec_argv);
+       free(rec_argv_copy);
+
+       return ret;
 }
 
 int cmd_sched(int argc, const char **argv)
index 7fb81a4..54cd29d 100644 (file)
@@ -826,6 +826,7 @@ static int __run_perf_stat(int argc, const char **argv, int run_idx)
        }
 
        evlist__for_each_entry(evsel_list, counter) {
+               counter->reset_group = false;
                if (bpf_counter__load(counter, &target))
                        return -1;
                if (!evsel__is_bpf(counter))
index 9313ef2..26a51b4 100755 (executable)
@@ -28,6 +28,24 @@ test_stat_record_report() {
   echo "stat record and report test [Success]"
 }
 
+test_stat_repeat_weak_groups() {
+  echo "stat repeat weak groups test"
+  if ! perf stat -e '{cycles,cycles,cycles,cycles,cycles,cycles,cycles,cycles,cycles,cycles}' \
+     true 2>&1 | grep -q 'seconds time elapsed'
+  then
+    echo "stat repeat weak groups test [Skipped event parsing failed]"
+    return
+  fi
+  if ! perf stat -r2 -e '{cycles,cycles,cycles,cycles,cycles,cycles,cycles,cycles,cycles,cycles}:W' \
+    true > /dev/null 2>&1
+  then
+    echo "stat repeat weak groups test [Failed]"
+    err=1
+    return
+  fi
+  echo "stat repeat weak groups test [Success]"
+}
+
 test_topdown_groups() {
   # Topdown events must be grouped with the slots event first. Test that
   # parse-events reorders this.
@@ -75,6 +93,7 @@ test_topdown_weak_groups() {
 
 test_default_stat
 test_stat_record_report
+test_stat_repeat_weak_groups
 test_topdown_groups
 test_topdown_weak_groups
 exit $err
index 979c8cb..788ce5e 100644 (file)
@@ -1193,7 +1193,7 @@ void perf_stat__print_shadow_stats(struct perf_stat_config *config,
                                                  &rsd);
                if (retiring > 0.7)
                        color = PERF_COLOR_GREEN;
-               print_metric(config, ctxp, color, "%8.1f%%", "retiring",
+               print_metric(config, ctxp, color, "%8.1f%%", "Retiring",
                                retiring * 100.);
        } else if (perf_stat_evsel__is(evsel, TOPDOWN_FE_BOUND) &&
                   full_td(cpu_map_idx, st, &rsd)) {
@@ -1202,7 +1202,7 @@ void perf_stat__print_shadow_stats(struct perf_stat_config *config,
                                                  &rsd);
                if (fe_bound > 0.2)
                        color = PERF_COLOR_RED;
-               print_metric(config, ctxp, color, "%8.1f%%", "frontend bound",
+               print_metric(config, ctxp, color, "%8.1f%%", "Frontend Bound",
                                fe_bound * 100.);
        } else if (perf_stat_evsel__is(evsel, TOPDOWN_BE_BOUND) &&
                   full_td(cpu_map_idx, st, &rsd)) {
@@ -1211,7 +1211,7 @@ void perf_stat__print_shadow_stats(struct perf_stat_config *config,
                                                  &rsd);
                if (be_bound > 0.2)
                        color = PERF_COLOR_RED;
-               print_metric(config, ctxp, color, "%8.1f%%", "backend bound",
+               print_metric(config, ctxp, color, "%8.1f%%", "Backend Bound",
                                be_bound * 100.);
        } else if (perf_stat_evsel__is(evsel, TOPDOWN_BAD_SPEC) &&
                   full_td(cpu_map_idx, st, &rsd)) {
@@ -1220,7 +1220,7 @@ void perf_stat__print_shadow_stats(struct perf_stat_config *config,
                                                  &rsd);
                if (bad_spec > 0.1)
                        color = PERF_COLOR_RED;
-               print_metric(config, ctxp, color, "%8.1f%%", "bad speculation",
+               print_metric(config, ctxp, color, "%8.1f%%", "Bad Speculation",
                                bad_spec * 100.);
        } else if (perf_stat_evsel__is(evsel, TOPDOWN_HEAVY_OPS) &&
                        full_td(cpu_map_idx, st, &rsd) && (config->topdown_level > 1)) {
@@ -1234,13 +1234,13 @@ void perf_stat__print_shadow_stats(struct perf_stat_config *config,
 
                if (retiring > 0.7 && heavy_ops > 0.1)
                        color = PERF_COLOR_GREEN;
-               print_metric(config, ctxp, color, "%8.1f%%", "heavy operations",
+               print_metric(config, ctxp, color, "%8.1f%%", "Heavy Operations",
                                heavy_ops * 100.);
                if (retiring > 0.7 && light_ops > 0.6)
                        color = PERF_COLOR_GREEN;
                else
                        color = NULL;
-               print_metric(config, ctxp, color, "%8.1f%%", "light operations",
+               print_metric(config, ctxp, color, "%8.1f%%", "Light Operations",
                                light_ops * 100.);
        } else if (perf_stat_evsel__is(evsel, TOPDOWN_BR_MISPREDICT) &&
                        full_td(cpu_map_idx, st, &rsd) && (config->topdown_level > 1)) {
@@ -1254,13 +1254,13 @@ void perf_stat__print_shadow_stats(struct perf_stat_config *config,
 
                if (bad_spec > 0.1 && br_mis > 0.05)
                        color = PERF_COLOR_RED;
-               print_metric(config, ctxp, color, "%8.1f%%", "branch mispredict",
+               print_metric(config, ctxp, color, "%8.1f%%", "Branch Mispredict",
                                br_mis * 100.);
                if (bad_spec > 0.1 && m_clears > 0.05)
                        color = PERF_COLOR_RED;
                else
                        color = NULL;
-               print_metric(config, ctxp, color, "%8.1f%%", "machine clears",
+               print_metric(config, ctxp, color, "%8.1f%%", "Machine Clears",
                                m_clears * 100.);
        } else if (perf_stat_evsel__is(evsel, TOPDOWN_FETCH_LAT) &&
                        full_td(cpu_map_idx, st, &rsd) && (config->topdown_level > 1)) {
@@ -1274,13 +1274,13 @@ void perf_stat__print_shadow_stats(struct perf_stat_config *config,
 
                if (fe_bound > 0.2 && fetch_lat > 0.15)
                        color = PERF_COLOR_RED;
-               print_metric(config, ctxp, color, "%8.1f%%", "fetch latency",
+               print_metric(config, ctxp, color, "%8.1f%%", "Fetch Latency",
                                fetch_lat * 100.);
                if (fe_bound > 0.2 && fetch_bw > 0.1)
                        color = PERF_COLOR_RED;
                else
                        color = NULL;
-               print_metric(config, ctxp, color, "%8.1f%%", "fetch bandwidth",
+               print_metric(config, ctxp, color, "%8.1f%%", "Fetch Bandwidth",
                                fetch_bw * 100.);
        } else if (perf_stat_evsel__is(evsel, TOPDOWN_MEM_BOUND) &&
                        full_td(cpu_map_idx, st, &rsd) && (config->topdown_level > 1)) {
@@ -1294,13 +1294,13 @@ void perf_stat__print_shadow_stats(struct perf_stat_config *config,
 
                if (be_bound > 0.2 && mem_bound > 0.2)
                        color = PERF_COLOR_RED;
-               print_metric(config, ctxp, color, "%8.1f%%", "memory bound",
+               print_metric(config, ctxp, color, "%8.1f%%", "Memory Bound",
                                mem_bound * 100.);
                if (be_bound > 0.2 && core_bound > 0.1)
                        color = PERF_COLOR_RED;
                else
                        color = NULL;
-               print_metric(config, ctxp, color, "%8.1f%%", "Core bound",
+               print_metric(config, ctxp, color, "%8.1f%%", "Core Bound",
                                core_bound * 100.);
        } else if (evsel->metric_expr) {
                generic_metric(config, evsel->metric_expr, evsel->metric_events, NULL,
index 10b34bb..c2064a3 100644 (file)
@@ -12,6 +12,7 @@ TARGETS += cpu-hotplug
 TARGETS += damon
 TARGETS += drivers/dma-buf
 TARGETS += drivers/s390x/uvdevice
+TARGETS += drivers/net/bonding
 TARGETS += efivarfs
 TARGETS += exec
 TARGETS += filesystems
diff --git a/tools/testing/selftests/drivers/net/bonding/Makefile b/tools/testing/selftests/drivers/net/bonding/Makefile
new file mode 100644 (file)
index 0000000..ab6c54b
--- /dev/null
@@ -0,0 +1,6 @@
+# SPDX-License-Identifier: GPL-2.0
+# Makefile for net selftests
+
+TEST_PROGS := bond-break-lacpdu-tx.sh
+
+include ../../../lib.mk
diff --git a/tools/testing/selftests/drivers/net/bonding/bond-break-lacpdu-tx.sh b/tools/testing/selftests/drivers/net/bonding/bond-break-lacpdu-tx.sh
new file mode 100755 (executable)
index 0000000..47ab905
--- /dev/null
@@ -0,0 +1,81 @@
+#!/bin/sh
+# SPDX-License-Identifier: GPL-2.0
+
+# Regression Test:
+#   Verify LACPDUs get transmitted after setting the MAC address of
+#   the bond.
+#
+# https://bugzilla.redhat.com/show_bug.cgi?id=2020773
+#
+#       +---------+
+#       | fab-br0 |
+#       +---------+
+#            |
+#       +---------+
+#       |  fbond  |
+#       +---------+
+#        |       |
+#    +------+ +------+
+#    |veth1 | |veth2 |
+#    +------+ +------+
+#
+# We use veths instead of physical interfaces
+
+set -e
+tmp=$(mktemp -q dump.XXXXXX)
+cleanup() {
+       ip link del fab-br0 >/dev/null 2>&1 || :
+       ip link del fbond  >/dev/null 2>&1 || :
+       ip link del veth1-bond  >/dev/null 2>&1 || :
+       ip link del veth2-bond  >/dev/null 2>&1 || :
+       modprobe -r bonding  >/dev/null 2>&1 || :
+       rm -f -- ${tmp}
+}
+
+trap cleanup 0 1 2
+cleanup
+sleep 1
+
+# create the bridge
+ip link add fab-br0 address 52:54:00:3B:7C:A6 mtu 1500 type bridge \
+       forward_delay 15
+
+# create the bond
+ip link add fbond type bond mode 4 miimon 200 xmit_hash_policy 1 \
+       ad_actor_sys_prio 65535 lacp_rate fast
+
+# set bond address
+ip link set fbond address 52:54:00:3B:7C:A6
+ip link set fbond up
+
+# set again bond sysfs parameters
+ip link set fbond type bond ad_actor_sys_prio 65535
+
+# create veths
+ip link add name veth1-bond type veth peer name veth1-end
+ip link add name veth2-bond type veth peer name veth2-end
+
+# add ports
+ip link set fbond master fab-br0
+ip link set veth1-bond down master fbond
+ip link set veth2-bond down master fbond
+
+# bring up
+ip link set veth1-end up
+ip link set veth2-end up
+ip link set fab-br0 up
+ip link set fbond up
+ip addr add dev fab-br0 10.0.0.3
+
+tcpdump -n -i veth1-end -e ether proto 0x8809 >${tmp} 2>&1 &
+sleep 15
+pkill tcpdump >/dev/null 2>&1
+rc=0
+num=$(grep "packets captured" ${tmp} | awk '{print $1}')
+if test "$num" -gt 0; then
+       echo "PASS, captured ${num}"
+else
+       echo "FAIL"
+       rc=1
+fi
+exit $rc
diff --git a/tools/testing/selftests/drivers/net/bonding/config b/tools/testing/selftests/drivers/net/bonding/config
new file mode 100644 (file)
index 0000000..dc1c22d
--- /dev/null
@@ -0,0 +1 @@
+CONFIG_BONDING=y
diff --git a/tools/testing/selftests/drivers/net/bonding/settings b/tools/testing/selftests/drivers/net/bonding/settings
new file mode 100644 (file)
index 0000000..867e118
--- /dev/null
@@ -0,0 +1 @@
+timeout=60
index 947fc72..d44c72b 100644 (file)
@@ -40,6 +40,7 @@ ifeq (0,$(MAKELEVEL))
     endif
 endif
 selfdir = $(realpath $(dir $(filter %/lib.mk,$(MAKEFILE_LIST))))
+top_srcdir = $(selfdir)/../../..
 
 # The following are built by lib.mk common compile rules.
 # TEST_CUSTOM_PROGS should be used by tests that require
index 50c5ab1..a07896a 100644 (file)
 #include "defines.h"
 #include "main.h"
 
+/*
+ * FIXME: OpenSSL 3.0 has deprecated some functions. For now just ignore
+ * the warnings.
+ */
+#pragma GCC diagnostic ignored "-Wdeprecated-declarations"
+
 struct q1q2_ctx {
        BN_CTX *bn_ctx;
        BIGNUM *m;