diff options
author | Mike Pagano <mpagano@gentoo.org> | 2023-01-12 07:17:29 -0500 |
---|---|---|
committer | Mike Pagano <mpagano@gentoo.org> | 2023-01-12 07:17:29 -0500 |
commit | 319bd1afecafadce35585a733a6919e656db8780 (patch) | |
tree | 43209523c88189f888fac791bb6ea58f8827b962 | |
parent | Linux patch 6.0.18 (diff) | |
download | linux-patches-6.0.tar.gz linux-patches-6.0.tar.bz2 linux-patches-6.0.zip |
Signed-off-by: Mike Pagano <mpagano@gentoo.org>
-rw-r--r-- | 0000_README | 6 | ||||
-rw-r--r-- | 1018_linux-6.0.19.patch | 7559 |
2 files changed, 7564 insertions, 1 deletions
diff --git a/0000_README b/0000_README index 569afe2e..ceb9effe 100644 --- a/0000_README +++ b/0000_README @@ -111,10 +111,14 @@ Patch: 1016_linux-6.0.17.patch From: http://www.kernel.org Desc: Linux 6.0.17 -Patch: 1017_linux-6.0.19.patch +Patch: 1017_linux-6.0.18.patch From: http://www.kernel.org Desc: Linux 6.0.18 +Patch: 1018_linux-6.0.19.patch +From: http://www.kernel.org +Desc: Linux 6.0.19 + Patch: 1500_XATTR_USER_PREFIX.patch From: https://bugs.gentoo.org/show_bug.cgi?id=470644 Desc: Support for namespace user.pax.* on tmpfs. diff --git a/1018_linux-6.0.19.patch b/1018_linux-6.0.19.patch new file mode 100644 index 00000000..79b68f80 --- /dev/null +++ b/1018_linux-6.0.19.patch @@ -0,0 +1,7559 @@ +diff --git a/Makefile b/Makefile +index 0104f69d30bbd..b978809a1c7cb 100644 +--- a/Makefile ++++ b/Makefile +@@ -1,7 +1,7 @@ + # SPDX-License-Identifier: GPL-2.0 + VERSION = 6 + PATCHLEVEL = 0 +-SUBLEVEL = 18 ++SUBLEVEL = 19 + EXTRAVERSION = + NAME = Hurr durr I'ma ninja sloth + +diff --git a/arch/arm/include/asm/thread_info.h b/arch/arm/include/asm/thread_info.h +index aecc403b28804..7f092cb55a417 100644 +--- a/arch/arm/include/asm/thread_info.h ++++ b/arch/arm/include/asm/thread_info.h +@@ -128,15 +128,16 @@ extern int vfp_restore_user_hwstate(struct user_vfp *, + #define TIF_NEED_RESCHED 1 /* rescheduling necessary */ + #define TIF_NOTIFY_RESUME 2 /* callback before returning to user */ + #define TIF_UPROBE 3 /* breakpointed or singlestepping */ +-#define TIF_SYSCALL_TRACE 4 /* syscall trace active */ +-#define TIF_SYSCALL_AUDIT 5 /* syscall auditing active */ +-#define TIF_SYSCALL_TRACEPOINT 6 /* syscall tracepoint instrumentation */ +-#define TIF_SECCOMP 7 /* seccomp syscall filtering active */ +-#define TIF_NOTIFY_SIGNAL 8 /* signal notifications exist */ ++#define TIF_NOTIFY_SIGNAL 4 /* signal notifications exist */ + + #define TIF_USING_IWMMXT 17 + #define TIF_MEMDIE 18 /* is terminating due to OOM killer */ +-#define TIF_RESTORE_SIGMASK 20 ++#define TIF_RESTORE_SIGMASK 19 ++#define TIF_SYSCALL_TRACE 20 /* syscall trace active */ ++#define TIF_SYSCALL_AUDIT 21 /* syscall auditing active */ ++#define TIF_SYSCALL_TRACEPOINT 22 /* syscall tracepoint instrumentation */ ++#define TIF_SECCOMP 23 /* seccomp syscall filtering active */ ++ + + #define _TIF_SIGPENDING (1 << TIF_SIGPENDING) + #define _TIF_NEED_RESCHED (1 << TIF_NEED_RESCHED) +diff --git a/arch/mips/ralink/of.c b/arch/mips/ralink/of.c +index 01c132bc33d54..4d06de77d92a6 100644 +--- a/arch/mips/ralink/of.c ++++ b/arch/mips/ralink/of.c +@@ -64,7 +64,7 @@ void __init plat_mem_setup(void) + dtb = get_fdt(); + __dt_setup_arch(dtb); + +- if (!early_init_dt_scan_memory()) ++ if (early_init_dt_scan_memory()) + return; + + if (soc_info.mem_detect) +diff --git a/arch/riscv/include/asm/uaccess.h b/arch/riscv/include/asm/uaccess.h +index 855450bed9f52..ec0cab9fbddd0 100644 +--- a/arch/riscv/include/asm/uaccess.h ++++ b/arch/riscv/include/asm/uaccess.h +@@ -165,7 +165,7 @@ do { \ + might_fault(); \ + access_ok(__p, sizeof(*__p)) ? \ + __get_user((x), __p) : \ +- ((x) = 0, -EFAULT); \ ++ ((x) = (__force __typeof__(x))0, -EFAULT); \ + }) + + #define __put_user_asm(insn, x, ptr, err) \ +diff --git a/arch/riscv/kernel/probes/simulate-insn.h b/arch/riscv/kernel/probes/simulate-insn.h +index cb6ff7dccb92e..de8474146a9b6 100644 +--- a/arch/riscv/kernel/probes/simulate-insn.h ++++ b/arch/riscv/kernel/probes/simulate-insn.h +@@ -31,9 +31,9 @@ __RISCV_INSN_FUNCS(fence, 0x7f, 0x0f); + } while (0) + + __RISCV_INSN_FUNCS(c_j, 0xe003, 0xa001); +-__RISCV_INSN_FUNCS(c_jr, 0xf007, 0x8002); ++__RISCV_INSN_FUNCS(c_jr, 0xf07f, 0x8002); + __RISCV_INSN_FUNCS(c_jal, 0xe003, 0x2001); +-__RISCV_INSN_FUNCS(c_jalr, 0xf007, 0x9002); ++__RISCV_INSN_FUNCS(c_jalr, 0xf07f, 0x9002); + __RISCV_INSN_FUNCS(c_beqz, 0xe003, 0xc001); + __RISCV_INSN_FUNCS(c_bnez, 0xe003, 0xe001); + __RISCV_INSN_FUNCS(c_ebreak, 0xffff, 0x9002); +diff --git a/arch/x86/kernel/cpu/bugs.c b/arch/x86/kernel/cpu/bugs.c +index 06ad95ae78ceb..2d6915fe73856 100644 +--- a/arch/x86/kernel/cpu/bugs.c ++++ b/arch/x86/kernel/cpu/bugs.c +@@ -1951,6 +1951,8 @@ static int ib_prctl_set(struct task_struct *task, unsigned long ctrl) + if (ctrl == PR_SPEC_FORCE_DISABLE) + task_set_spec_ib_force_disable(task); + task_update_spec_tif(task); ++ if (task == current) ++ indirect_branch_prediction_barrier(); + break; + default: + return -ERANGE; +diff --git a/arch/x86/kernel/crash.c b/arch/x86/kernel/crash.c +index 9730c88530fc8..305514431f26e 100644 +--- a/arch/x86/kernel/crash.c ++++ b/arch/x86/kernel/crash.c +@@ -401,10 +401,8 @@ int crash_load_segments(struct kimage *image) + kbuf.buf_align = ELF_CORE_HEADER_ALIGN; + kbuf.mem = KEXEC_BUF_MEM_UNKNOWN; + ret = kexec_add_buffer(&kbuf); +- if (ret) { +- vfree((void *)image->elf_headers); ++ if (ret) + return ret; +- } + image->elf_load_addr = kbuf.mem; + pr_debug("Loaded ELF headers at 0x%lx bufsz=0x%lx memsz=0x%lx\n", + image->elf_load_addr, kbuf.bufsz, kbuf.memsz); +diff --git a/block/blk-merge.c b/block/blk-merge.c +index ff04e9290715a..f46c87ef951df 100644 +--- a/block/blk-merge.c ++++ b/block/blk-merge.c +@@ -300,6 +300,16 @@ static struct bio *bio_split_rw(struct bio *bio, struct queue_limits *lim, + *segs = nsegs; + return NULL; + split: ++ /* ++ * We can't sanely support splitting for a REQ_NOWAIT bio. End it ++ * with EAGAIN if splitting is required and return an error pointer. ++ */ ++ if (bio->bi_opf & REQ_NOWAIT) { ++ bio->bi_status = BLK_STS_AGAIN; ++ bio_endio(bio); ++ return ERR_PTR(-EAGAIN); ++ } ++ + *segs = nsegs; + + /* +diff --git a/drivers/block/ublk_drv.c b/drivers/block/ublk_drv.c +index 31a8715d3a4d3..ebb5c846d8260 100644 +--- a/drivers/block/ublk_drv.c ++++ b/drivers/block/ublk_drv.c +@@ -1718,6 +1718,9 @@ static int ublk_ctrl_uring_cmd(struct io_uring_cmd *cmd, + struct ublksrv_ctrl_cmd *header = (struct ublksrv_ctrl_cmd *)cmd->cmd; + int ret = -EINVAL; + ++ if (issue_flags & IO_URING_F_NONBLOCK) ++ return -EAGAIN; ++ + ublk_ctrl_cmd_dump(cmd); + + if (!(issue_flags & IO_URING_F_SQE128)) +diff --git a/drivers/block/virtio_blk.c b/drivers/block/virtio_blk.c +index dd9a05174726b..53931fcef0d58 100644 +--- a/drivers/block/virtio_blk.c ++++ b/drivers/block/virtio_blk.c +@@ -311,22 +311,35 @@ static void virtio_commit_rqs(struct blk_mq_hw_ctx *hctx) + virtqueue_notify(vq->vq); + } + ++static blk_status_t virtblk_fail_to_queue(struct request *req, int rc) ++{ ++ virtblk_cleanup_cmd(req); ++ switch (rc) { ++ case -ENOSPC: ++ return BLK_STS_DEV_RESOURCE; ++ case -ENOMEM: ++ return BLK_STS_RESOURCE; ++ default: ++ return BLK_STS_IOERR; ++ } ++} ++ + static blk_status_t virtblk_prep_rq(struct blk_mq_hw_ctx *hctx, + struct virtio_blk *vblk, + struct request *req, + struct virtblk_req *vbr) + { + blk_status_t status; ++ int num; + + status = virtblk_setup_cmd(vblk->vdev, req, vbr); + if (unlikely(status)) + return status; + +- vbr->sg_table.nents = virtblk_map_data(hctx, req, vbr); +- if (unlikely(vbr->sg_table.nents < 0)) { +- virtblk_cleanup_cmd(req); +- return BLK_STS_RESOURCE; +- } ++ num = virtblk_map_data(hctx, req, vbr); ++ if (unlikely(num < 0)) ++ return virtblk_fail_to_queue(req, -ENOMEM); ++ vbr->sg_table.nents = num; + + blk_mq_start_request(req); + +@@ -360,15 +373,7 @@ static blk_status_t virtio_queue_rq(struct blk_mq_hw_ctx *hctx, + blk_mq_stop_hw_queue(hctx); + spin_unlock_irqrestore(&vblk->vqs[qid].lock, flags); + virtblk_unmap_data(req, vbr); +- virtblk_cleanup_cmd(req); +- switch (err) { +- case -ENOSPC: +- return BLK_STS_DEV_RESOURCE; +- case -ENOMEM: +- return BLK_STS_RESOURCE; +- default: +- return BLK_STS_IOERR; +- } ++ return virtblk_fail_to_queue(req, err); + } + + if (bd->last && virtqueue_kick_prepare(vblk->vqs[qid].vq)) +diff --git a/drivers/crypto/virtio/virtio_crypto_skcipher_algs.c b/drivers/crypto/virtio/virtio_crypto_skcipher_algs.c +index e553ccadbcbc8..e5876286828b8 100644 +--- a/drivers/crypto/virtio/virtio_crypto_skcipher_algs.c ++++ b/drivers/crypto/virtio/virtio_crypto_skcipher_algs.c +@@ -239,7 +239,8 @@ static int virtio_crypto_alg_skcipher_close_session( + pr_err("virtio_crypto: Close session failed status: %u, session_id: 0x%llx\n", + ctrl_status->status, destroy_session->session_id); + +- return -EINVAL; ++ err = -EINVAL; ++ goto out; + } + + err = 0; +diff --git a/drivers/firmware/efi/efi.c b/drivers/firmware/efi/efi.c +index a06decee51e06..a6e9968a2ddc0 100644 +--- a/drivers/firmware/efi/efi.c ++++ b/drivers/firmware/efi/efi.c +@@ -608,7 +608,7 @@ int __init efi_config_parse_tables(const efi_config_table_t *config_tables, + + seed = early_memremap(efi_rng_seed, sizeof(*seed)); + if (seed != NULL) { +- size = min(seed->size, EFI_RANDOM_SEED_SIZE); ++ size = min_t(u32, seed->size, SZ_1K); // sanity check + early_memunmap(seed, sizeof(*seed)); + } else { + pr_err("Could not map UEFI random seed!\n"); +@@ -617,8 +617,8 @@ int __init efi_config_parse_tables(const efi_config_table_t *config_tables, + seed = early_memremap(efi_rng_seed, + sizeof(*seed) + size); + if (seed != NULL) { +- pr_notice("seeding entropy pool\n"); + add_bootloader_randomness(seed->bits, size); ++ memzero_explicit(seed->bits, size); + early_memunmap(seed, sizeof(*seed) + size); + } else { + pr_err("Could not map UEFI random seed!\n"); +diff --git a/drivers/firmware/efi/libstub/efistub.h b/drivers/firmware/efi/libstub/efistub.h +index b0ae0a454404b..0ce2bf4b8b581 100644 +--- a/drivers/firmware/efi/libstub/efistub.h ++++ b/drivers/firmware/efi/libstub/efistub.h +@@ -873,6 +873,8 @@ efi_status_t efi_get_random_bytes(unsigned long size, u8 *out); + efi_status_t efi_random_alloc(unsigned long size, unsigned long align, + unsigned long *addr, unsigned long random_seed); + ++efi_status_t efi_random_get_seed(void); ++ + efi_status_t check_platform_features(void); + + void *get_efi_config_table(efi_guid_t guid); +diff --git a/drivers/firmware/efi/libstub/random.c b/drivers/firmware/efi/libstub/random.c +index 33ab567695951..f85d2c0668777 100644 +--- a/drivers/firmware/efi/libstub/random.c ++++ b/drivers/firmware/efi/libstub/random.c +@@ -67,27 +67,43 @@ efi_status_t efi_random_get_seed(void) + efi_guid_t rng_proto = EFI_RNG_PROTOCOL_GUID; + efi_guid_t rng_algo_raw = EFI_RNG_ALGORITHM_RAW; + efi_guid_t rng_table_guid = LINUX_EFI_RANDOM_SEED_TABLE_GUID; ++ struct linux_efi_random_seed *prev_seed, *seed = NULL; ++ int prev_seed_size = 0, seed_size = EFI_RANDOM_SEED_SIZE; + efi_rng_protocol_t *rng = NULL; +- struct linux_efi_random_seed *seed = NULL; + efi_status_t status; + + status = efi_bs_call(locate_protocol, &rng_proto, NULL, (void **)&rng); + if (status != EFI_SUCCESS) + return status; + ++ /* ++ * Check whether a seed was provided by a prior boot stage. In that ++ * case, instead of overwriting it, let's create a new buffer that can ++ * hold both, and concatenate the existing and the new seeds. ++ * Note that we should read the seed size with caution, in case the ++ * table got corrupted in memory somehow. ++ */ ++ prev_seed = get_efi_config_table(LINUX_EFI_RANDOM_SEED_TABLE_GUID); ++ if (prev_seed && prev_seed->size <= 512U) { ++ prev_seed_size = prev_seed->size; ++ seed_size += prev_seed_size; ++ } ++ + /* + * Use EFI_ACPI_RECLAIM_MEMORY here so that it is guaranteed that the + * allocation will survive a kexec reboot (although we refresh the seed + * beforehand) + */ + status = efi_bs_call(allocate_pool, EFI_ACPI_RECLAIM_MEMORY, +- sizeof(*seed) + EFI_RANDOM_SEED_SIZE, ++ struct_size(seed, bits, seed_size), + (void **)&seed); +- if (status != EFI_SUCCESS) +- return status; ++ if (status != EFI_SUCCESS) { ++ efi_warn("Failed to allocate memory for RNG seed.\n"); ++ goto err_warn; ++ } + + status = efi_call_proto(rng, get_rng, &rng_algo_raw, +- EFI_RANDOM_SEED_SIZE, seed->bits); ++ EFI_RANDOM_SEED_SIZE, seed->bits); + + if (status == EFI_UNSUPPORTED) + /* +@@ -100,14 +116,28 @@ efi_status_t efi_random_get_seed(void) + if (status != EFI_SUCCESS) + goto err_freepool; + +- seed->size = EFI_RANDOM_SEED_SIZE; ++ seed->size = seed_size; ++ if (prev_seed_size) ++ memcpy(seed->bits + EFI_RANDOM_SEED_SIZE, prev_seed->bits, ++ prev_seed_size); ++ + status = efi_bs_call(install_configuration_table, &rng_table_guid, seed); + if (status != EFI_SUCCESS) + goto err_freepool; + ++ if (prev_seed_size) { ++ /* wipe and free the old seed if we managed to install the new one */ ++ memzero_explicit(prev_seed->bits, prev_seed_size); ++ efi_bs_call(free_pool, prev_seed); ++ } + return EFI_SUCCESS; + + err_freepool: ++ memzero_explicit(seed, struct_size(seed, bits, seed_size)); + efi_bs_call(free_pool, seed); ++ efi_warn("Failed to obtain seed from EFI_RNG_PROTOCOL\n"); ++err_warn: ++ if (prev_seed) ++ efi_warn("Retaining bootloader-supplied seed only"); + return status; + } +diff --git a/drivers/gpio/gpio-sifive.c b/drivers/gpio/gpio-sifive.c +index 238f3210970cf..bc5660f61c570 100644 +--- a/drivers/gpio/gpio-sifive.c ++++ b/drivers/gpio/gpio-sifive.c +@@ -215,6 +215,7 @@ static int sifive_gpio_probe(struct platform_device *pdev) + return -ENODEV; + } + parent = irq_find_host(irq_parent); ++ of_node_put(irq_parent); + if (!parent) { + dev_err(dev, "no IRQ parent domain\n"); + return -ENODEV; +diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu.h b/drivers/gpu/drm/amd/amdgpu/amdgpu.h +index d597e2656c475..2fb7bf47f41ac 100644 +--- a/drivers/gpu/drm/amd/amdgpu/amdgpu.h ++++ b/drivers/gpu/drm/amd/amdgpu/amdgpu.h +@@ -196,6 +196,7 @@ extern int amdgpu_emu_mode; + extern uint amdgpu_smu_memory_pool_size; + extern int amdgpu_smu_pptable_id; + extern uint amdgpu_dc_feature_mask; ++extern uint amdgpu_freesync_vid_mode; + extern uint amdgpu_dc_debug_mask; + extern uint amdgpu_dc_visual_confirm; + extern uint amdgpu_dm_abm_level; +diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd.h b/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd.h +index 647220a8762dc..30f145dc8724e 100644 +--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd.h ++++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd.h +@@ -265,8 +265,10 @@ int amdgpu_amdkfd_get_pcie_bandwidth_mbytes(struct amdgpu_device *adev, bool is_ + (&((struct amdgpu_fpriv *) \ + ((struct drm_file *)(drm_priv))->driver_priv)->vm) + ++int amdgpu_amdkfd_gpuvm_set_vm_pasid(struct amdgpu_device *adev, ++ struct file *filp, u32 pasid); + int amdgpu_amdkfd_gpuvm_acquire_process_vm(struct amdgpu_device *adev, +- struct file *filp, u32 pasid, ++ struct file *filp, + void **process_info, + struct dma_fence **ef); + void amdgpu_amdkfd_gpuvm_release_process_vm(struct amdgpu_device *adev, +diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd_gpuvm.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd_gpuvm.c +index 6659630303a38..ba5a09c2b3ce6 100644 +--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd_gpuvm.c ++++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd_gpuvm.c +@@ -1471,10 +1471,9 @@ static void amdgpu_amdkfd_gpuvm_unpin_bo(struct amdgpu_bo *bo) + amdgpu_bo_unreserve(bo); + } + +-int amdgpu_amdkfd_gpuvm_acquire_process_vm(struct amdgpu_device *adev, +- struct file *filp, u32 pasid, +- void **process_info, +- struct dma_fence **ef) ++int amdgpu_amdkfd_gpuvm_set_vm_pasid(struct amdgpu_device *adev, ++ struct file *filp, u32 pasid) ++ + { + struct amdgpu_fpriv *drv_priv; + struct amdgpu_vm *avm; +@@ -1485,10 +1484,6 @@ int amdgpu_amdkfd_gpuvm_acquire_process_vm(struct amdgpu_device *adev, + return ret; + avm = &drv_priv->vm; + +- /* Already a compute VM? */ +- if (avm->process_info) +- return -EINVAL; +- + /* Free the original amdgpu allocated pasid, + * will be replaced with kfd allocated pasid. + */ +@@ -1497,14 +1492,36 @@ int amdgpu_amdkfd_gpuvm_acquire_process_vm(struct amdgpu_device *adev, + amdgpu_vm_set_pasid(adev, avm, 0); + } + +- /* Convert VM into a compute VM */ +- ret = amdgpu_vm_make_compute(adev, avm); ++ ret = amdgpu_vm_set_pasid(adev, avm, pasid); + if (ret) + return ret; + +- ret = amdgpu_vm_set_pasid(adev, avm, pasid); ++ return 0; ++} ++ ++int amdgpu_amdkfd_gpuvm_acquire_process_vm(struct amdgpu_device *adev, ++ struct file *filp, ++ void **process_info, ++ struct dma_fence **ef) ++{ ++ struct amdgpu_fpriv *drv_priv; ++ struct amdgpu_vm *avm; ++ int ret; ++ ++ ret = amdgpu_file_to_fpriv(filp, &drv_priv); + if (ret) + return ret; ++ avm = &drv_priv->vm; ++ ++ /* Already a compute VM? */ ++ if (avm->process_info) ++ return -EINVAL; ++ ++ /* Convert VM into a compute VM */ ++ ret = amdgpu_vm_make_compute(adev, avm); ++ if (ret) ++ return ret; ++ + /* Initialize KFD part of the VM and process info */ + ret = init_kfd_vm(avm, process_info, ef); + if (ret) +diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c +index 379e65ea8afb1..adb369bb7295f 100644 +--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c ++++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c +@@ -177,6 +177,7 @@ int amdgpu_mes_kiq; + int amdgpu_noretry = -1; + int amdgpu_force_asic_type = -1; + int amdgpu_tmz = -1; /* auto */ ++uint amdgpu_freesync_vid_mode; + int amdgpu_reset_method = -1; /* auto */ + int amdgpu_num_kcq = -1; + int amdgpu_smartshift_bias; +@@ -862,6 +863,32 @@ module_param_named(backlight, amdgpu_backlight, bint, 0444); + MODULE_PARM_DESC(tmz, "Enable TMZ feature (-1 = auto (default), 0 = off, 1 = on)"); + module_param_named(tmz, amdgpu_tmz, int, 0444); + ++/** ++ * DOC: freesync_video (uint) ++ * Enable the optimization to adjust front porch timing to achieve seamless ++ * mode change experience when setting a freesync supported mode for which full ++ * modeset is not needed. ++ * ++ * The Display Core will add a set of modes derived from the base FreeSync ++ * video mode into the corresponding connector's mode list based on commonly ++ * used refresh rates and VRR range of the connected display, when users enable ++ * this feature. From the userspace perspective, they can see a seamless mode ++ * change experience when the change between different refresh rates under the ++ * same resolution. Additionally, userspace applications such as Video playback ++ * can read this modeset list and change the refresh rate based on the video ++ * frame rate. Finally, the userspace can also derive an appropriate mode for a ++ * particular refresh rate based on the FreeSync Mode and add it to the ++ * connector's mode list. ++ * ++ * Note: This is an experimental feature. ++ * ++ * The default value: 0 (off). ++ */ ++MODULE_PARM_DESC( ++ freesync_video, ++ "Enable freesync modesetting optimization feature (0 = off (default), 1 = on)"); ++module_param_named(freesync_video, amdgpu_freesync_vid_mode, uint, 0444); ++ + /** + * DOC: reset_method (int) + * GPU reset method (-1 = auto (default), 0 = legacy, 1 = mode0, 2 = mode1, 3 = mode2, 4 = baco) +diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_object.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_object.c +index bfe0fc258fc14..60ab2d952d5c5 100644 +--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_object.c ++++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_object.c +@@ -446,27 +446,24 @@ static bool amdgpu_bo_validate_size(struct amdgpu_device *adev, + + /* + * If GTT is part of requested domains the check must succeed to +- * allow fall back to GTT ++ * allow fall back to GTT. + */ + if (domain & AMDGPU_GEM_DOMAIN_GTT) { + man = ttm_manager_type(&adev->mman.bdev, TTM_PL_TT); + +- if (size < man->size) ++ if (man && size < man->size) + return true; +- else +- goto fail; +- } +- +- if (domain & AMDGPU_GEM_DOMAIN_VRAM) { ++ else if (!man) ++ WARN_ON_ONCE("GTT domain requested but GTT mem manager uninitialized"); ++ goto fail; ++ } else if (domain & AMDGPU_GEM_DOMAIN_VRAM) { + man = ttm_manager_type(&adev->mman.bdev, TTM_PL_VRAM); + +- if (size < man->size) ++ if (man && size < man->size) + return true; +- else +- goto fail; ++ goto fail; + } + +- + /* TODO add more domains checks, such as AMDGPU_GEM_DOMAIN_CPU */ + return true; + +diff --git a/drivers/gpu/drm/amd/amdkfd/kfd_process.c b/drivers/gpu/drm/amd/amdkfd/kfd_process.c +index 6c83a519b3a1b..febf0e9f7af14 100644 +--- a/drivers/gpu/drm/amd/amdkfd/kfd_process.c ++++ b/drivers/gpu/drm/amd/amdkfd/kfd_process.c +@@ -689,13 +689,13 @@ void kfd_process_destroy_wq(void) + } + + static void kfd_process_free_gpuvm(struct kgd_mem *mem, +- struct kfd_process_device *pdd, void *kptr) ++ struct kfd_process_device *pdd, void **kptr) + { + struct kfd_dev *dev = pdd->dev; + +- if (kptr) { ++ if (kptr && *kptr) { + amdgpu_amdkfd_gpuvm_unmap_gtt_bo_from_kernel(mem); +- kptr = NULL; ++ *kptr = NULL; + } + + amdgpu_amdkfd_gpuvm_unmap_memory_from_gpu(dev->adev, mem, pdd->drm_priv); +@@ -795,7 +795,7 @@ static void kfd_process_device_destroy_ib_mem(struct kfd_process_device *pdd) + if (!qpd->ib_kaddr || !qpd->ib_base) + return; + +- kfd_process_free_gpuvm(qpd->ib_mem, pdd, qpd->ib_kaddr); ++ kfd_process_free_gpuvm(qpd->ib_mem, pdd, &qpd->ib_kaddr); + } + + struct kfd_process *kfd_create_process(struct file *filep) +@@ -1277,7 +1277,7 @@ static void kfd_process_device_destroy_cwsr_dgpu(struct kfd_process_device *pdd) + if (!dev->cwsr_enabled || !qpd->cwsr_kaddr || !qpd->cwsr_base) + return; + +- kfd_process_free_gpuvm(qpd->cwsr_mem, pdd, qpd->cwsr_kaddr); ++ kfd_process_free_gpuvm(qpd->cwsr_mem, pdd, &qpd->cwsr_kaddr); + } + + void kfd_process_set_trap_handler(struct qcm_process_device *qpd, +@@ -1581,9 +1581,9 @@ int kfd_process_device_init_vm(struct kfd_process_device *pdd, + p = pdd->process; + dev = pdd->dev; + +- ret = amdgpu_amdkfd_gpuvm_acquire_process_vm( +- dev->adev, drm_file, p->pasid, +- &p->kgd_process_info, &p->ef); ++ ret = amdgpu_amdkfd_gpuvm_acquire_process_vm(dev->adev, drm_file, ++ &p->kgd_process_info, ++ &p->ef); + if (ret) { + pr_err("Failed to create process VM object\n"); + return ret; +@@ -1598,13 +1598,19 @@ int kfd_process_device_init_vm(struct kfd_process_device *pdd, + if (ret) + goto err_init_cwsr; + ++ ret = amdgpu_amdkfd_gpuvm_set_vm_pasid(dev->adev, drm_file, p->pasid); ++ if (ret) ++ goto err_set_pasid; ++ + pdd->drm_file = drm_file; + + return 0; + ++err_set_pasid: ++ kfd_process_device_destroy_cwsr_dgpu(pdd); + err_init_cwsr: ++ kfd_process_device_destroy_ib_mem(pdd); + err_reserve_ib_mem: +- kfd_process_device_free_bos(pdd); + pdd->drm_priv = NULL; + + return ret; +diff --git a/drivers/gpu/drm/amd/amdkfd/kfd_topology.c b/drivers/gpu/drm/amd/amdkfd/kfd_topology.c +index 3f0a4a415907d..35a9b702508af 100644 +--- a/drivers/gpu/drm/amd/amdkfd/kfd_topology.c ++++ b/drivers/gpu/drm/amd/amdkfd/kfd_topology.c +@@ -801,7 +801,7 @@ static int kfd_build_sysfs_node_entry(struct kfd_topology_device *dev, + + p2plink->attr.name = "properties"; + p2plink->attr.mode = KFD_SYSFS_FILE_MODE; +- sysfs_attr_init(&iolink->attr); ++ sysfs_attr_init(&p2plink->attr); + ret = sysfs_create_file(p2plink->kobj, &p2plink->attr); + if (ret < 0) + return ret; +diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c +index 895bbd20dd07a..68f2eb215e81c 100644 +--- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c ++++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c +@@ -5821,7 +5821,8 @@ create_stream_for_sink(struct amdgpu_dm_connector *aconnector, + */ + DRM_DEBUG_DRIVER("No preferred mode found\n"); + } else { +- recalculate_timing = is_freesync_video_mode(&mode, aconnector); ++ recalculate_timing = amdgpu_freesync_vid_mode && ++ is_freesync_video_mode(&mode, aconnector); + if (recalculate_timing) { + freesync_mode = get_highest_refresh_rate_mode(aconnector, false); + drm_mode_copy(&saved_mode, &mode); +@@ -6895,7 +6896,7 @@ static void amdgpu_dm_connector_add_freesync_modes(struct drm_connector *connect + struct amdgpu_dm_connector *amdgpu_dm_connector = + to_amdgpu_dm_connector(connector); + +- if (!edid) ++ if (!(amdgpu_freesync_vid_mode && edid)) + return; + + if (amdgpu_dm_connector->max_vfreq - amdgpu_dm_connector->min_vfreq > 10) +@@ -8766,7 +8767,8 @@ static int dm_update_crtc_state(struct amdgpu_display_manager *dm, + * TODO: Refactor this function to allow this check to work + * in all conditions. + */ +- if (dm_new_crtc_state->stream && ++ if (amdgpu_freesync_vid_mode && ++ dm_new_crtc_state->stream && + is_timing_unchanged_for_freesync(new_crtc_state, old_crtc_state)) + goto skip_modeset; + +@@ -8801,7 +8803,7 @@ static int dm_update_crtc_state(struct amdgpu_display_manager *dm, + if (!dm_old_crtc_state->stream) + goto skip_modeset; + +- if (dm_new_crtc_state->stream && ++ if (amdgpu_freesync_vid_mode && dm_new_crtc_state->stream && + is_timing_unchanged_for_freesync(new_crtc_state, + old_crtc_state)) { + new_crtc_state->mode_changed = false; +@@ -8813,7 +8815,7 @@ static int dm_update_crtc_state(struct amdgpu_display_manager *dm, + set_freesync_fixed_config(dm_new_crtc_state); + + goto skip_modeset; +- } else if (aconnector && ++ } else if (amdgpu_freesync_vid_mode && aconnector && + is_freesync_video_mode(&new_crtc_state->mode, + aconnector)) { + struct drm_display_mode *high_mode; +diff --git a/drivers/gpu/drm/i915/gvt/debugfs.c b/drivers/gpu/drm/i915/gvt/debugfs.c +index 9f1c209d92511..e08ed0e9f1653 100644 +--- a/drivers/gpu/drm/i915/gvt/debugfs.c ++++ b/drivers/gpu/drm/i915/gvt/debugfs.c +@@ -175,8 +175,13 @@ void intel_gvt_debugfs_add_vgpu(struct intel_vgpu *vgpu) + */ + void intel_gvt_debugfs_remove_vgpu(struct intel_vgpu *vgpu) + { +- debugfs_remove_recursive(vgpu->debugfs); +- vgpu->debugfs = NULL; ++ struct intel_gvt *gvt = vgpu->gvt; ++ struct drm_minor *minor = gvt->gt->i915->drm.primary; ++ ++ if (minor->debugfs_root && gvt->debugfs_root) { ++ debugfs_remove_recursive(vgpu->debugfs); ++ vgpu->debugfs = NULL; ++ } + } + + /** +@@ -199,6 +204,10 @@ void intel_gvt_debugfs_init(struct intel_gvt *gvt) + */ + void intel_gvt_debugfs_clean(struct intel_gvt *gvt) + { +- debugfs_remove_recursive(gvt->debugfs_root); +- gvt->debugfs_root = NULL; ++ struct drm_minor *minor = gvt->gt->i915->drm.primary; ++ ++ if (minor->debugfs_root) { ++ debugfs_remove_recursive(gvt->debugfs_root); ++ gvt->debugfs_root = NULL; ++ } + } +diff --git a/drivers/gpu/drm/i915/gvt/gtt.c b/drivers/gpu/drm/i915/gvt/gtt.c +index ce0eb03709c3f..80c60754a5c1c 100644 +--- a/drivers/gpu/drm/i915/gvt/gtt.c ++++ b/drivers/gpu/drm/i915/gvt/gtt.c +@@ -1214,10 +1214,8 @@ static int split_2MB_gtt_entry(struct intel_vgpu *vgpu, + for_each_shadow_entry(sub_spt, &sub_se, sub_index) { + ret = intel_gvt_dma_map_guest_page(vgpu, start_gfn + sub_index, + PAGE_SIZE, &dma_addr); +- if (ret) { +- ppgtt_invalidate_spt(spt); +- return ret; +- } ++ if (ret) ++ goto err; + sub_se.val64 = se->val64; + + /* Copy the PAT field from PDE. */ +@@ -1236,6 +1234,17 @@ static int split_2MB_gtt_entry(struct intel_vgpu *vgpu, + ops->set_pfn(se, sub_spt->shadow_page.mfn); + ppgtt_set_shadow_entry(spt, se, index); + return 0; ++err: ++ /* Cancel the existing addess mappings of DMA addr. */ ++ for_each_present_shadow_entry(sub_spt, &sub_se, sub_index) { ++ gvt_vdbg_mm("invalidate 4K entry\n"); ++ ppgtt_invalidate_pte(sub_spt, &sub_se); ++ } ++ /* Release the new allocated spt. */ ++ trace_spt_change(sub_spt->vgpu->id, "release", sub_spt, ++ sub_spt->guest_page.gfn, sub_spt->shadow_page.type); ++ ppgtt_free_spt(sub_spt); ++ return ret; + } + + static int split_64KB_gtt_entry(struct intel_vgpu *vgpu, +diff --git a/drivers/gpu/drm/i915/gvt/scheduler.c b/drivers/gpu/drm/i915/gvt/scheduler.c +index d6fe94cd0fdb6..8342d95f56cbc 100644 +--- a/drivers/gpu/drm/i915/gvt/scheduler.c ++++ b/drivers/gpu/drm/i915/gvt/scheduler.c +@@ -696,6 +696,7 @@ intel_vgpu_shadow_mm_pin(struct intel_vgpu_workload *workload) + + if (workload->shadow_mm->type != INTEL_GVT_MM_PPGTT || + !workload->shadow_mm->ppgtt_mm.shadowed) { ++ intel_vgpu_unpin_mm(workload->shadow_mm); + gvt_vgpu_err("workload shadow ppgtt isn't ready\n"); + return -EINVAL; + } +diff --git a/drivers/gpu/drm/imx/ipuv3-plane.c b/drivers/gpu/drm/imx/ipuv3-plane.c +index ea5f594955dfe..4b05f310071c0 100644 +--- a/drivers/gpu/drm/imx/ipuv3-plane.c ++++ b/drivers/gpu/drm/imx/ipuv3-plane.c +@@ -615,6 +615,11 @@ static void ipu_plane_atomic_update(struct drm_plane *plane, + break; + } + ++ if (ipu_plane->dp_flow == IPU_DP_FLOW_SYNC_BG) ++ width = ipu_src_rect_width(new_state); ++ else ++ width = drm_rect_width(&new_state->src) >> 16; ++ + eba = drm_plane_state_to_eba(new_state, 0); + + /* +@@ -623,8 +628,7 @@ static void ipu_plane_atomic_update(struct drm_plane *plane, + */ + if (ipu_state->use_pre) { + axi_id = ipu_chan_assign_axi_id(ipu_plane->dma); +- ipu_prg_channel_configure(ipu_plane->ipu_ch, axi_id, +- ipu_src_rect_width(new_state), ++ ipu_prg_channel_configure(ipu_plane->ipu_ch, axi_id, width, + drm_rect_height(&new_state->src) >> 16, + fb->pitches[0], fb->format->format, + fb->modifier, &eba); +@@ -679,9 +683,8 @@ static void ipu_plane_atomic_update(struct drm_plane *plane, + break; + } + +- ipu_dmfc_config_wait4eot(ipu_plane->dmfc, ALIGN(drm_rect_width(dst), 8)); ++ ipu_dmfc_config_wait4eot(ipu_plane->dmfc, width); + +- width = ipu_src_rect_width(new_state); + height = drm_rect_height(&new_state->src) >> 16; + info = drm_format_info(fb->format->format); + ipu_calculate_bursts(width, info->cpp[0], fb->pitches[0], +@@ -745,8 +748,7 @@ static void ipu_plane_atomic_update(struct drm_plane *plane, + ipu_cpmem_set_burstsize(ipu_plane->ipu_ch, 16); + + ipu_cpmem_zero(ipu_plane->alpha_ch); +- ipu_cpmem_set_resolution(ipu_plane->alpha_ch, +- ipu_src_rect_width(new_state), ++ ipu_cpmem_set_resolution(ipu_plane->alpha_ch, width, + drm_rect_height(&new_state->src) >> 16); + ipu_cpmem_set_format_passthrough(ipu_plane->alpha_ch, 8); + ipu_cpmem_set_high_priority(ipu_plane->alpha_ch); +diff --git a/drivers/gpu/drm/meson/meson_viu.c b/drivers/gpu/drm/meson/meson_viu.c +index d4b907889a21d..cd399b0b71814 100644 +--- a/drivers/gpu/drm/meson/meson_viu.c ++++ b/drivers/gpu/drm/meson/meson_viu.c +@@ -436,15 +436,14 @@ void meson_viu_init(struct meson_drm *priv) + + /* Initialize OSD1 fifo control register */ + reg = VIU_OSD_DDR_PRIORITY_URGENT | +- VIU_OSD_HOLD_FIFO_LINES(31) | + VIU_OSD_FIFO_DEPTH_VAL(32) | /* fifo_depth_val: 32*8=256 */ + VIU_OSD_WORDS_PER_BURST(4) | /* 4 words in 1 burst */ + VIU_OSD_FIFO_LIMITS(2); /* fifo_lim: 2*16=32 */ + + if (meson_vpu_is_compatible(priv, VPU_COMPATIBLE_G12A)) +- reg |= VIU_OSD_BURST_LENGTH_32; ++ reg |= (VIU_OSD_BURST_LENGTH_32 | VIU_OSD_HOLD_FIFO_LINES(31)); + else +- reg |= VIU_OSD_BURST_LENGTH_64; ++ reg |= (VIU_OSD_BURST_LENGTH_64 | VIU_OSD_HOLD_FIFO_LINES(4)); + + writel_relaxed(reg, priv->io_base + _REG(VIU_OSD1_FIFO_CTRL_STAT)); + writel_relaxed(reg, priv->io_base + _REG(VIU_OSD2_FIFO_CTRL_STAT)); +diff --git a/drivers/gpu/drm/mgag200/mgag200_pll.c b/drivers/gpu/drm/mgag200/mgag200_pll.c +index 8065ca5d8de9a..4f55961848a84 100644 +--- a/drivers/gpu/drm/mgag200/mgag200_pll.c ++++ b/drivers/gpu/drm/mgag200/mgag200_pll.c +@@ -269,7 +269,8 @@ static void mgag200_pixpll_update_g200se_04(struct mgag200_pll *pixpll, + pixpllcp = pixpllc->p - 1; + pixpllcs = pixpllc->s; + +- xpixpllcm = pixpllcm | ((pixpllcn & BIT(8)) >> 1); ++ // For G200SE A, BIT(7) should be set unconditionally. ++ xpixpllcm = BIT(7) | pixpllcm; + xpixpllcn = pixpllcn; + xpixpllcp = (pixpllcs << 3) | pixpllcp; + +diff --git a/drivers/gpu/drm/panfrost/panfrost_drv.c b/drivers/gpu/drm/panfrost/panfrost_drv.c +index 2fa5afe212889..919e6cc049828 100644 +--- a/drivers/gpu/drm/panfrost/panfrost_drv.c ++++ b/drivers/gpu/drm/panfrost/panfrost_drv.c +@@ -82,6 +82,7 @@ static int panfrost_ioctl_create_bo(struct drm_device *dev, void *data, + struct panfrost_gem_object *bo; + struct drm_panfrost_create_bo *args = data; + struct panfrost_gem_mapping *mapping; ++ int ret; + + if (!args->size || args->pad || + (args->flags & ~(PANFROST_BO_NOEXEC | PANFROST_BO_HEAP))) +@@ -92,21 +93,29 @@ static int panfrost_ioctl_create_bo(struct drm_device *dev, void *data, + !(args->flags & PANFROST_BO_NOEXEC)) + return -EINVAL; + +- bo = panfrost_gem_create_with_handle(file, dev, args->size, args->flags, +- &args->handle); ++ bo = panfrost_gem_create(dev, args->size, args->flags); + if (IS_ERR(bo)) + return PTR_ERR(bo); + ++ ret = drm_gem_handle_create(file, &bo->base.base, &args->handle); ++ if (ret) ++ goto out; ++ + mapping = panfrost_gem_mapping_get(bo, priv); +- if (!mapping) { +- drm_gem_object_put(&bo->base.base); +- return -EINVAL; ++ if (mapping) { ++ args->offset = mapping->mmnode.start << PAGE_SHIFT; ++ panfrost_gem_mapping_put(mapping); ++ } else { ++ /* This can only happen if the handle from ++ * drm_gem_handle_create() has already been guessed and freed ++ * by user space ++ */ ++ ret = -EINVAL; + } + +- args->offset = mapping->mmnode.start << PAGE_SHIFT; +- panfrost_gem_mapping_put(mapping); +- +- return 0; ++out: ++ drm_gem_object_put(&bo->base.base); ++ return ret; + } + + /** +diff --git a/drivers/gpu/drm/panfrost/panfrost_gem.c b/drivers/gpu/drm/panfrost/panfrost_gem.c +index 293e799e2fe81..3c812fbd126fd 100644 +--- a/drivers/gpu/drm/panfrost/panfrost_gem.c ++++ b/drivers/gpu/drm/panfrost/panfrost_gem.c +@@ -235,12 +235,8 @@ struct drm_gem_object *panfrost_gem_create_object(struct drm_device *dev, size_t + } + + struct panfrost_gem_object * +-panfrost_gem_create_with_handle(struct drm_file *file_priv, +- struct drm_device *dev, size_t size, +- u32 flags, +- uint32_t *handle) ++panfrost_gem_create(struct drm_device *dev, size_t size, u32 flags) + { +- int ret; + struct drm_gem_shmem_object *shmem; + struct panfrost_gem_object *bo; + +@@ -256,16 +252,6 @@ panfrost_gem_create_with_handle(struct drm_file *file_priv, + bo->noexec = !!(flags & PANFROST_BO_NOEXEC); + bo->is_heap = !!(flags & PANFROST_BO_HEAP); + +- /* +- * Allocate an id of idr table where the obj is registered +- * and handle has the id what user can see. +- */ +- ret = drm_gem_handle_create(file_priv, &shmem->base, handle); +- /* drop reference from allocate - handle holds it now. */ +- drm_gem_object_put(&shmem->base); +- if (ret) +- return ERR_PTR(ret); +- + return bo; + } + +diff --git a/drivers/gpu/drm/panfrost/panfrost_gem.h b/drivers/gpu/drm/panfrost/panfrost_gem.h +index 8088d5fd8480e..ad2877eeeccdf 100644 +--- a/drivers/gpu/drm/panfrost/panfrost_gem.h ++++ b/drivers/gpu/drm/panfrost/panfrost_gem.h +@@ -69,10 +69,7 @@ panfrost_gem_prime_import_sg_table(struct drm_device *dev, + struct sg_table *sgt); + + struct panfrost_gem_object * +-panfrost_gem_create_with_handle(struct drm_file *file_priv, +- struct drm_device *dev, size_t size, +- u32 flags, +- uint32_t *handle); ++panfrost_gem_create(struct drm_device *dev, size_t size, u32 flags); + + int panfrost_gem_open(struct drm_gem_object *obj, struct drm_file *file_priv); + void panfrost_gem_close(struct drm_gem_object *obj, +diff --git a/drivers/infiniband/hw/mlx5/counters.c b/drivers/infiniband/hw/mlx5/counters.c +index 945758f395236..3e1272695d993 100644 +--- a/drivers/infiniband/hw/mlx5/counters.c ++++ b/drivers/infiniband/hw/mlx5/counters.c +@@ -278,7 +278,6 @@ static int do_get_hw_stats(struct ib_device *ibdev, + const struct mlx5_ib_counters *cnts = get_counters(dev, port_num - 1); + struct mlx5_core_dev *mdev; + int ret, num_counters; +- u32 mdev_port_num; + + if (!stats) + return -EINVAL; +@@ -299,8 +298,9 @@ static int do_get_hw_stats(struct ib_device *ibdev, + } + + if (MLX5_CAP_GEN(dev->mdev, cc_query_allowed)) { +- mdev = mlx5_ib_get_native_port_mdev(dev, port_num, +- &mdev_port_num); ++ if (!port_num) ++ port_num = 1; ++ mdev = mlx5_ib_get_native_port_mdev(dev, port_num, NULL); + if (!mdev) { + /* If port is not affiliated yet, its in down state + * which doesn't have any counters yet, so it would be +diff --git a/drivers/infiniband/hw/mlx5/qp.c b/drivers/infiniband/hw/mlx5/qp.c +index 40d9410ec3033..cf953d23d18da 100644 +--- a/drivers/infiniband/hw/mlx5/qp.c ++++ b/drivers/infiniband/hw/mlx5/qp.c +@@ -4502,6 +4502,40 @@ static bool mlx5_ib_modify_qp_allowed(struct mlx5_ib_dev *dev, + return false; + } + ++static int validate_rd_atomic(struct mlx5_ib_dev *dev, struct ib_qp_attr *attr, ++ int attr_mask, enum ib_qp_type qp_type) ++{ ++ int log_max_ra_res; ++ int log_max_ra_req; ++ ++ if (qp_type == MLX5_IB_QPT_DCI) { ++ log_max_ra_res = 1 << MLX5_CAP_GEN(dev->mdev, ++ log_max_ra_res_dc); ++ log_max_ra_req = 1 << MLX5_CAP_GEN(dev->mdev, ++ log_max_ra_req_dc); ++ } else { ++ log_max_ra_res = 1 << MLX5_CAP_GEN(dev->mdev, ++ log_max_ra_res_qp); ++ log_max_ra_req = 1 << MLX5_CAP_GEN(dev->mdev, ++ log_max_ra_req_qp); ++ } ++ ++ if (attr_mask & IB_QP_MAX_QP_RD_ATOMIC && ++ attr->max_rd_atomic > log_max_ra_res) { ++ mlx5_ib_dbg(dev, "invalid max_rd_atomic value %d\n", ++ attr->max_rd_atomic); ++ return false; ++ } ++ ++ if (attr_mask & IB_QP_MAX_DEST_RD_ATOMIC && ++ attr->max_dest_rd_atomic > log_max_ra_req) { ++ mlx5_ib_dbg(dev, "invalid max_dest_rd_atomic value %d\n", ++ attr->max_dest_rd_atomic); ++ return false; ++ } ++ return true; ++} ++ + int mlx5_ib_modify_qp(struct ib_qp *ibqp, struct ib_qp_attr *attr, + int attr_mask, struct ib_udata *udata) + { +@@ -4589,21 +4623,8 @@ int mlx5_ib_modify_qp(struct ib_qp *ibqp, struct ib_qp_attr *attr, + goto out; + } + +- if (attr_mask & IB_QP_MAX_QP_RD_ATOMIC && +- attr->max_rd_atomic > +- (1 << MLX5_CAP_GEN(dev->mdev, log_max_ra_res_qp))) { +- mlx5_ib_dbg(dev, "invalid max_rd_atomic value %d\n", +- attr->max_rd_atomic); +- goto out; +- } +- +- if (attr_mask & IB_QP_MAX_DEST_RD_ATOMIC && +- attr->max_dest_rd_atomic > +- (1 << MLX5_CAP_GEN(dev->mdev, log_max_ra_req_qp))) { +- mlx5_ib_dbg(dev, "invalid max_dest_rd_atomic value %d\n", +- attr->max_dest_rd_atomic); ++ if (!validate_rd_atomic(dev, attr, attr_mask, qp_type)) + goto out; +- } + + if (cur_state == new_state && cur_state == IB_QPS_RESET) { + err = 0; +diff --git a/drivers/net/bonding/bond_3ad.c b/drivers/net/bonding/bond_3ad.c +index e58a1e0cadd2e..9270977e6c7ff 100644 +--- a/drivers/net/bonding/bond_3ad.c ++++ b/drivers/net/bonding/bond_3ad.c +@@ -1540,6 +1540,7 @@ static void ad_port_selection_logic(struct port *port, bool *update_slave_arr) + slave_err(bond->dev, port->slave->dev, + "Port %d did not find a suitable aggregator\n", + port->actor_port_number); ++ return; + } + } + /* if all aggregator's ports are READY_N == TRUE, set ready=TRUE +diff --git a/drivers/net/bonding/bond_main.c b/drivers/net/bonding/bond_main.c +index 771f2a533d3f6..7807113e09100 100644 +--- a/drivers/net/bonding/bond_main.c ++++ b/drivers/net/bonding/bond_main.c +@@ -2653,10 +2653,12 @@ static void bond_miimon_link_change(struct bonding *bond, + + static void bond_miimon_commit(struct bonding *bond) + { +- struct slave *slave, *primary; ++ struct slave *slave, *primary, *active; + bool do_failover = false; + struct list_head *iter; + ++ ASSERT_RTNL(); ++ + bond_for_each_slave(bond, slave, iter) { + switch (slave->link_new_state) { + case BOND_LINK_NOCHANGE: +@@ -2699,8 +2701,8 @@ static void bond_miimon_commit(struct bonding *bond) + + bond_miimon_link_change(bond, slave, BOND_LINK_UP); + +- if (!rcu_access_pointer(bond->curr_active_slave) || slave == primary || +- slave->prio > rcu_dereference(bond->curr_active_slave)->prio) ++ active = rtnl_dereference(bond->curr_active_slave); ++ if (!active || slave == primary || slave->prio > active->prio) + do_failover = true; + + continue; +diff --git a/drivers/net/dsa/mv88e6xxx/Kconfig b/drivers/net/dsa/mv88e6xxx/Kconfig +index 7a2445a34eb77..e3181d5471dfe 100644 +--- a/drivers/net/dsa/mv88e6xxx/Kconfig ++++ b/drivers/net/dsa/mv88e6xxx/Kconfig +@@ -2,7 +2,6 @@ + config NET_DSA_MV88E6XXX + tristate "Marvell 88E6xxx Ethernet switch fabric support" + depends on NET_DSA +- depends on PTP_1588_CLOCK_OPTIONAL + select IRQ_DOMAIN + select NET_DSA_TAG_EDSA + select NET_DSA_TAG_DSA +@@ -13,7 +12,8 @@ config NET_DSA_MV88E6XXX + config NET_DSA_MV88E6XXX_PTP + bool "PTP support for Marvell 88E6xxx" + default n +- depends on NET_DSA_MV88E6XXX && PTP_1588_CLOCK ++ depends on (NET_DSA_MV88E6XXX = y && PTP_1588_CLOCK = y) || \ ++ (NET_DSA_MV88E6XXX = m && PTP_1588_CLOCK) + help + Say Y to enable PTP hardware timestamping on Marvell 88E6xxx switch + chips that support it. +diff --git a/drivers/net/dsa/qca/qca8k-8xxx.c b/drivers/net/dsa/qca/qca8k-8xxx.c +index 300c9345ee2be..3587f75807d0d 100644 +--- a/drivers/net/dsa/qca/qca8k-8xxx.c ++++ b/drivers/net/dsa/qca/qca8k-8xxx.c +@@ -36,44 +36,6 @@ qca8k_split_addr(u32 regaddr, u16 *r1, u16 *r2, u16 *page) + *page = regaddr & 0x3ff; + } + +-static int +-qca8k_set_lo(struct qca8k_priv *priv, int phy_id, u32 regnum, u16 lo) +-{ +- u16 *cached_lo = &priv->mdio_cache.lo; +- struct mii_bus *bus = priv->bus; +- int ret; +- +- if (lo == *cached_lo) +- return 0; +- +- ret = bus->write(bus, phy_id, regnum, lo); +- if (ret < 0) +- dev_err_ratelimited(&bus->dev, +- "failed to write qca8k 32bit lo register\n"); +- +- *cached_lo = lo; +- return 0; +-} +- +-static int +-qca8k_set_hi(struct qca8k_priv *priv, int phy_id, u32 regnum, u16 hi) +-{ +- u16 *cached_hi = &priv->mdio_cache.hi; +- struct mii_bus *bus = priv->bus; +- int ret; +- +- if (hi == *cached_hi) +- return 0; +- +- ret = bus->write(bus, phy_id, regnum, hi); +- if (ret < 0) +- dev_err_ratelimited(&bus->dev, +- "failed to write qca8k 32bit hi register\n"); +- +- *cached_hi = hi; +- return 0; +-} +- + static int + qca8k_mii_read32(struct mii_bus *bus, int phy_id, u32 regnum, u32 *val) + { +@@ -97,7 +59,7 @@ qca8k_mii_read32(struct mii_bus *bus, int phy_id, u32 regnum, u32 *val) + } + + static void +-qca8k_mii_write32(struct qca8k_priv *priv, int phy_id, u32 regnum, u32 val) ++qca8k_mii_write32(struct mii_bus *bus, int phy_id, u32 regnum, u32 val) + { + u16 lo, hi; + int ret; +@@ -105,9 +67,12 @@ qca8k_mii_write32(struct qca8k_priv *priv, int phy_id, u32 regnum, u32 val) + lo = val & 0xffff; + hi = (u16)(val >> 16); + +- ret = qca8k_set_lo(priv, phy_id, regnum, lo); ++ ret = bus->write(bus, phy_id, regnum, lo); + if (ret >= 0) +- ret = qca8k_set_hi(priv, phy_id, regnum + 1, hi); ++ ret = bus->write(bus, phy_id, regnum + 1, hi); ++ if (ret < 0) ++ dev_err_ratelimited(&bus->dev, ++ "failed to write qca8k 32bit register\n"); + } + + static int +@@ -146,7 +111,16 @@ static void qca8k_rw_reg_ack_handler(struct dsa_switch *ds, struct sk_buff *skb) + + command = get_unaligned_le32(&mgmt_ethhdr->command); + cmd = FIELD_GET(QCA_HDR_MGMT_CMD, command); ++ + len = FIELD_GET(QCA_HDR_MGMT_LENGTH, command); ++ /* Special case for len of 15 as this is the max value for len and needs to ++ * be increased before converting it from word to dword. ++ */ ++ if (len == 15) ++ len++; ++ ++ /* We can ignore odd value, we always round up them in the alloc function. */ ++ len *= sizeof(u16); + + /* Make sure the seq match the requested packet */ + if (get_unaligned_le32(&mgmt_ethhdr->seq) == mgmt_eth_data->seq) +@@ -193,17 +167,33 @@ static struct sk_buff *qca8k_alloc_mdio_header(enum mdio_cmd cmd, u32 reg, u32 * + if (!skb) + return NULL; + +- /* Max value for len reg is 15 (0xf) but the switch actually return 16 byte +- * Actually for some reason the steps are: +- * 0: nothing +- * 1-4: first 4 byte +- * 5-6: first 12 byte +- * 7-15: all 16 byte ++ /* Hdr mgmt length value is in step of word size. ++ * As an example to process 4 byte of data the correct length to set is 2. ++ * To process 8 byte 4, 12 byte 6, 16 byte 8... ++ * ++ * Odd values will always return the next size on the ack packet. ++ * (length of 3 (6 byte) will always return 8 bytes of data) ++ * ++ * This means that a value of 15 (0xf) actually means reading/writing 32 bytes ++ * of data. ++ * ++ * To correctly calculate the length we devide the requested len by word and ++ * round up. ++ * On the ack function we can skip the odd check as we already handle the ++ * case here. ++ */ ++ real_len = DIV_ROUND_UP(len, sizeof(u16)); ++ ++ /* We check if the result len is odd and we round up another time to ++ * the next size. (length of 3 will be increased to 4 as switch will always ++ * return 8 bytes) + */ +- if (len == 16) +- real_len = 15; +- else +- real_len = len; ++ if (real_len % sizeof(u16) != 0) ++ real_len++; ++ ++ /* Max reg value is 0xf(15) but switch will always return the next size (32 byte) */ ++ if (real_len == 16) ++ real_len--; + + skb_reset_mac_header(skb); + skb_set_network_header(skb, skb->len); +@@ -417,7 +407,7 @@ qca8k_regmap_write(void *ctx, uint32_t reg, uint32_t val) + if (ret < 0) + goto exit; + +- qca8k_mii_write32(priv, 0x10 | r2, r1, val); ++ qca8k_mii_write32(bus, 0x10 | r2, r1, val); + + exit: + mutex_unlock(&bus->mdio_lock); +@@ -450,7 +440,7 @@ qca8k_regmap_update_bits(void *ctx, uint32_t reg, uint32_t mask, uint32_t write_ + + val &= ~mask; + val |= write_val; +- qca8k_mii_write32(priv, 0x10 | r2, r1, val); ++ qca8k_mii_write32(bus, 0x10 | r2, r1, val); + + exit: + mutex_unlock(&bus->mdio_lock); +@@ -725,14 +715,14 @@ qca8k_mdio_write(struct qca8k_priv *priv, int phy, int regnum, u16 data) + if (ret) + goto exit; + +- qca8k_mii_write32(priv, 0x10 | r2, r1, val); ++ qca8k_mii_write32(bus, 0x10 | r2, r1, val); + + ret = qca8k_mdio_busy_wait(bus, QCA8K_MDIO_MASTER_CTRL, + QCA8K_MDIO_MASTER_BUSY); + + exit: + /* even if the busy_wait timeouts try to clear the MASTER_EN */ +- qca8k_mii_write32(priv, 0x10 | r2, r1, 0); ++ qca8k_mii_write32(bus, 0x10 | r2, r1, 0); + + mutex_unlock(&bus->mdio_lock); + +@@ -762,7 +752,7 @@ qca8k_mdio_read(struct qca8k_priv *priv, int phy, int regnum) + if (ret) + goto exit; + +- qca8k_mii_write32(priv, 0x10 | r2, r1, val); ++ qca8k_mii_write32(bus, 0x10 | r2, r1, val); + + ret = qca8k_mdio_busy_wait(bus, QCA8K_MDIO_MASTER_CTRL, + QCA8K_MDIO_MASTER_BUSY); +@@ -773,7 +763,7 @@ qca8k_mdio_read(struct qca8k_priv *priv, int phy, int regnum) + + exit: + /* even if the busy_wait timeouts try to clear the MASTER_EN */ +- qca8k_mii_write32(priv, 0x10 | r2, r1, 0); ++ qca8k_mii_write32(bus, 0x10 | r2, r1, 0); + + mutex_unlock(&bus->mdio_lock); + +@@ -1943,8 +1933,6 @@ qca8k_sw_probe(struct mdio_device *mdiodev) + } + + priv->mdio_cache.page = 0xffff; +- priv->mdio_cache.lo = 0xffff; +- priv->mdio_cache.hi = 0xffff; + + /* Check the detected switch id */ + ret = qca8k_read_switch_id(priv); +diff --git a/drivers/net/dsa/qca/qca8k.h b/drivers/net/dsa/qca/qca8k.h +index e36ecc9777f43..342e9d945dfbb 100644 +--- a/drivers/net/dsa/qca/qca8k.h ++++ b/drivers/net/dsa/qca/qca8k.h +@@ -375,11 +375,6 @@ struct qca8k_mdio_cache { + * mdio writes + */ + u16 page; +-/* lo and hi can also be cached and from Documentation we can skip one +- * extra mdio write if lo or hi is didn't change. +- */ +- u16 lo; +- u16 hi; + }; + + struct qca8k_pcs { +diff --git a/drivers/net/ethernet/amazon/ena/ena_com.c b/drivers/net/ethernet/amazon/ena/ena_com.c +index 8c8b4c88c7dea..451c3a1b62553 100644 +--- a/drivers/net/ethernet/amazon/ena/ena_com.c ++++ b/drivers/net/ethernet/amazon/ena/ena_com.c +@@ -2400,29 +2400,18 @@ int ena_com_fill_hash_function(struct ena_com_dev *ena_dev, + return -EOPNOTSUPP; + } + +- switch (func) { +- case ENA_ADMIN_TOEPLITZ: +- if (key) { +- if (key_len != sizeof(hash_key->key)) { +- netdev_err(ena_dev->net_device, +- "key len (%u) doesn't equal the supported size (%zu)\n", +- key_len, sizeof(hash_key->key)); +- return -EINVAL; +- } +- memcpy(hash_key->key, key, key_len); +- rss->hash_init_val = init_val; +- hash_key->key_parts = key_len / sizeof(hash_key->key[0]); ++ if ((func == ENA_ADMIN_TOEPLITZ) && key) { ++ if (key_len != sizeof(hash_key->key)) { ++ netdev_err(ena_dev->net_device, ++ "key len (%u) doesn't equal the supported size (%zu)\n", ++ key_len, sizeof(hash_key->key)); ++ return -EINVAL; + } +- break; +- case ENA_ADMIN_CRC32: +- rss->hash_init_val = init_val; +- break; +- default: +- netdev_err(ena_dev->net_device, "Invalid hash function (%d)\n", +- func); +- return -EINVAL; ++ memcpy(hash_key->key, key, key_len); ++ hash_key->key_parts = key_len / sizeof(hash_key->key[0]); + } + ++ rss->hash_init_val = init_val; + old_func = rss->hash_func; + rss->hash_func = func; + rc = ena_com_set_hash_function(ena_dev); +diff --git a/drivers/net/ethernet/amazon/ena/ena_ethtool.c b/drivers/net/ethernet/amazon/ena/ena_ethtool.c +index 39242c5a17290..108506721bcfd 100644 +--- a/drivers/net/ethernet/amazon/ena/ena_ethtool.c ++++ b/drivers/net/ethernet/amazon/ena/ena_ethtool.c +@@ -887,11 +887,7 @@ static int ena_set_tunable(struct net_device *netdev, + switch (tuna->id) { + case ETHTOOL_RX_COPYBREAK: + len = *(u32 *)data; +- if (len > adapter->netdev->mtu) { +- ret = -EINVAL; +- break; +- } +- adapter->rx_copybreak = len; ++ ret = ena_set_rx_copybreak(adapter, len); + break; + default: + ret = -EINVAL; +diff --git a/drivers/net/ethernet/amazon/ena/ena_netdev.c b/drivers/net/ethernet/amazon/ena/ena_netdev.c +index 41c8213484769..413714f373ffd 100644 +--- a/drivers/net/ethernet/amazon/ena/ena_netdev.c ++++ b/drivers/net/ethernet/amazon/ena/ena_netdev.c +@@ -374,9 +374,9 @@ static int ena_xdp_xmit(struct net_device *dev, int n, + + static int ena_xdp_execute(struct ena_ring *rx_ring, struct xdp_buff *xdp) + { ++ u32 verdict = ENA_XDP_PASS; + struct bpf_prog *xdp_prog; + struct ena_ring *xdp_ring; +- u32 verdict = XDP_PASS; + struct xdp_frame *xdpf; + u64 *xdp_stat; + +@@ -393,7 +393,7 @@ static int ena_xdp_execute(struct ena_ring *rx_ring, struct xdp_buff *xdp) + if (unlikely(!xdpf)) { + trace_xdp_exception(rx_ring->netdev, xdp_prog, verdict); + xdp_stat = &rx_ring->rx_stats.xdp_aborted; +- verdict = XDP_ABORTED; ++ verdict = ENA_XDP_DROP; + break; + } + +@@ -409,29 +409,35 @@ static int ena_xdp_execute(struct ena_ring *rx_ring, struct xdp_buff *xdp) + + spin_unlock(&xdp_ring->xdp_tx_lock); + xdp_stat = &rx_ring->rx_stats.xdp_tx; ++ verdict = ENA_XDP_TX; + break; + case XDP_REDIRECT: + if (likely(!xdp_do_redirect(rx_ring->netdev, xdp, xdp_prog))) { + xdp_stat = &rx_ring->rx_stats.xdp_redirect; ++ verdict = ENA_XDP_REDIRECT; + break; + } + trace_xdp_exception(rx_ring->netdev, xdp_prog, verdict); + xdp_stat = &rx_ring->rx_stats.xdp_aborted; +- verdict = XDP_ABORTED; ++ verdict = ENA_XDP_DROP; + break; + case XDP_ABORTED: + trace_xdp_exception(rx_ring->netdev, xdp_prog, verdict); + xdp_stat = &rx_ring->rx_stats.xdp_aborted; ++ verdict = ENA_XDP_DROP; + break; + case XDP_DROP: + xdp_stat = &rx_ring->rx_stats.xdp_drop; ++ verdict = ENA_XDP_DROP; + break; + case XDP_PASS: + xdp_stat = &rx_ring->rx_stats.xdp_pass; ++ verdict = ENA_XDP_PASS; + break; + default: + bpf_warn_invalid_xdp_action(rx_ring->netdev, xdp_prog, verdict); + xdp_stat = &rx_ring->rx_stats.xdp_invalid; ++ verdict = ENA_XDP_DROP; + } + + ena_increase_stat(xdp_stat, 1, &rx_ring->syncp); +@@ -512,16 +518,18 @@ static void ena_xdp_exchange_program_rx_in_range(struct ena_adapter *adapter, + struct bpf_prog *prog, + int first, int count) + { ++ struct bpf_prog *old_bpf_prog; + struct ena_ring *rx_ring; + int i = 0; + + for (i = first; i < count; i++) { + rx_ring = &adapter->rx_ring[i]; +- xchg(&rx_ring->xdp_bpf_prog, prog); +- if (prog) { ++ old_bpf_prog = xchg(&rx_ring->xdp_bpf_prog, prog); ++ ++ if (!old_bpf_prog && prog) { + ena_xdp_register_rxq_info(rx_ring); + rx_ring->rx_headroom = XDP_PACKET_HEADROOM; +- } else { ++ } else if (old_bpf_prog && !prog) { + ena_xdp_unregister_rxq_info(rx_ring); + rx_ring->rx_headroom = NET_SKB_PAD; + } +@@ -672,6 +680,7 @@ static void ena_init_io_rings_common(struct ena_adapter *adapter, + ring->ena_dev = adapter->ena_dev; + ring->per_napi_packets = 0; + ring->cpu = 0; ++ ring->numa_node = 0; + ring->no_interrupt_event_cnt = 0; + u64_stats_init(&ring->syncp); + } +@@ -775,6 +784,7 @@ static int ena_setup_tx_resources(struct ena_adapter *adapter, int qid) + tx_ring->next_to_use = 0; + tx_ring->next_to_clean = 0; + tx_ring->cpu = ena_irq->cpu; ++ tx_ring->numa_node = node; + return 0; + + err_push_buf_intermediate_buf: +@@ -907,6 +917,7 @@ static int ena_setup_rx_resources(struct ena_adapter *adapter, + rx_ring->next_to_clean = 0; + rx_ring->next_to_use = 0; + rx_ring->cpu = ena_irq->cpu; ++ rx_ring->numa_node = node; + + return 0; + } +@@ -1619,12 +1630,12 @@ static int ena_xdp_handle_buff(struct ena_ring *rx_ring, struct xdp_buff *xdp) + * we expect, then we simply drop it + */ + if (unlikely(rx_ring->ena_bufs[0].len > ENA_XDP_MAX_MTU)) +- return XDP_DROP; ++ return ENA_XDP_DROP; + + ret = ena_xdp_execute(rx_ring, xdp); + + /* The xdp program might expand the headers */ +- if (ret == XDP_PASS) { ++ if (ret == ENA_XDP_PASS) { + rx_info->page_offset = xdp->data - xdp->data_hard_start; + rx_ring->ena_bufs[0].len = xdp->data_end - xdp->data; + } +@@ -1663,7 +1674,7 @@ static int ena_clean_rx_irq(struct ena_ring *rx_ring, struct napi_struct *napi, + xdp_init_buff(&xdp, ENA_PAGE_SIZE, &rx_ring->xdp_rxq); + + do { +- xdp_verdict = XDP_PASS; ++ xdp_verdict = ENA_XDP_PASS; + skb = NULL; + ena_rx_ctx.ena_bufs = rx_ring->ena_bufs; + ena_rx_ctx.max_bufs = rx_ring->sgl_size; +@@ -1691,7 +1702,7 @@ static int ena_clean_rx_irq(struct ena_ring *rx_ring, struct napi_struct *napi, + xdp_verdict = ena_xdp_handle_buff(rx_ring, &xdp); + + /* allocate skb and fill it */ +- if (xdp_verdict == XDP_PASS) ++ if (xdp_verdict == ENA_XDP_PASS) + skb = ena_rx_skb(rx_ring, + rx_ring->ena_bufs, + ena_rx_ctx.descs, +@@ -1709,14 +1720,15 @@ static int ena_clean_rx_irq(struct ena_ring *rx_ring, struct napi_struct *napi, + /* Packets was passed for transmission, unmap it + * from RX side. + */ +- if (xdp_verdict == XDP_TX || xdp_verdict == XDP_REDIRECT) { ++ if (xdp_verdict & ENA_XDP_FORWARDED) { + ena_unmap_rx_buff(rx_ring, + &rx_ring->rx_buffer_info[req_id]); + rx_ring->rx_buffer_info[req_id].page = NULL; + } + } +- if (xdp_verdict != XDP_PASS) { ++ if (xdp_verdict != ENA_XDP_PASS) { + xdp_flags |= xdp_verdict; ++ total_len += ena_rx_ctx.ena_bufs[0].len; + res_budget--; + continue; + } +@@ -1760,7 +1772,7 @@ static int ena_clean_rx_irq(struct ena_ring *rx_ring, struct napi_struct *napi, + ena_refill_rx_bufs(rx_ring, refill_required); + } + +- if (xdp_flags & XDP_REDIRECT) ++ if (xdp_flags & ENA_XDP_REDIRECT) + xdp_do_flush_map(); + + return work_done; +@@ -1814,8 +1826,9 @@ static void ena_adjust_adaptive_rx_intr_moderation(struct ena_napi *ena_napi) + static void ena_unmask_interrupt(struct ena_ring *tx_ring, + struct ena_ring *rx_ring) + { ++ u32 rx_interval = tx_ring->smoothed_interval; + struct ena_eth_io_intr_reg intr_reg; +- u32 rx_interval = 0; ++ + /* Rx ring can be NULL when for XDP tx queues which don't have an + * accompanying rx_ring pair. + */ +@@ -1853,20 +1866,27 @@ static void ena_update_ring_numa_node(struct ena_ring *tx_ring, + if (likely(tx_ring->cpu == cpu)) + goto out; + ++ tx_ring->cpu = cpu; ++ if (rx_ring) ++ rx_ring->cpu = cpu; ++ + numa_node = cpu_to_node(cpu); ++ ++ if (likely(tx_ring->numa_node == numa_node)) ++ goto out; ++ + put_cpu(); + + if (numa_node != NUMA_NO_NODE) { + ena_com_update_numa_node(tx_ring->ena_com_io_cq, numa_node); +- if (rx_ring) ++ tx_ring->numa_node = numa_node; ++ if (rx_ring) { ++ rx_ring->numa_node = numa_node; + ena_com_update_numa_node(rx_ring->ena_com_io_cq, + numa_node); ++ } + } + +- tx_ring->cpu = cpu; +- if (rx_ring) +- rx_ring->cpu = cpu; +- + return; + out: + put_cpu(); +@@ -1987,11 +2007,10 @@ static int ena_io_poll(struct napi_struct *napi, int budget) + if (ena_com_get_adaptive_moderation_enabled(rx_ring->ena_dev)) + ena_adjust_adaptive_rx_intr_moderation(ena_napi); + ++ ena_update_ring_numa_node(tx_ring, rx_ring); + ena_unmask_interrupt(tx_ring, rx_ring); + } + +- ena_update_ring_numa_node(tx_ring, rx_ring); +- + ret = rx_work_done; + } else { + ret = budget; +@@ -2378,7 +2397,7 @@ static int ena_create_io_tx_queue(struct ena_adapter *adapter, int qid) + ctx.mem_queue_type = ena_dev->tx_mem_queue_type; + ctx.msix_vector = msix_vector; + ctx.queue_size = tx_ring->ring_size; +- ctx.numa_node = cpu_to_node(tx_ring->cpu); ++ ctx.numa_node = tx_ring->numa_node; + + rc = ena_com_create_io_queue(ena_dev, &ctx); + if (rc) { +@@ -2446,7 +2465,7 @@ static int ena_create_io_rx_queue(struct ena_adapter *adapter, int qid) + ctx.mem_queue_type = ENA_ADMIN_PLACEMENT_POLICY_HOST; + ctx.msix_vector = msix_vector; + ctx.queue_size = rx_ring->ring_size; +- ctx.numa_node = cpu_to_node(rx_ring->cpu); ++ ctx.numa_node = rx_ring->numa_node; + + rc = ena_com_create_io_queue(ena_dev, &ctx); + if (rc) { +@@ -2807,6 +2826,24 @@ int ena_update_queue_sizes(struct ena_adapter *adapter, + return dev_was_up ? ena_up(adapter) : 0; + } + ++int ena_set_rx_copybreak(struct ena_adapter *adapter, u32 rx_copybreak) ++{ ++ struct ena_ring *rx_ring; ++ int i; ++ ++ if (rx_copybreak > min_t(u16, adapter->netdev->mtu, ENA_PAGE_SIZE)) ++ return -EINVAL; ++ ++ adapter->rx_copybreak = rx_copybreak; ++ ++ for (i = 0; i < adapter->num_io_queues; i++) { ++ rx_ring = &adapter->rx_ring[i]; ++ rx_ring->rx_copybreak = rx_copybreak; ++ } ++ ++ return 0; ++} ++ + int ena_update_queue_count(struct ena_adapter *adapter, u32 new_channel_count) + { + struct ena_com_dev *ena_dev = adapter->ena_dev; +diff --git a/drivers/net/ethernet/amazon/ena/ena_netdev.h b/drivers/net/ethernet/amazon/ena/ena_netdev.h +index 1bdce99bf6888..2cb141079474c 100644 +--- a/drivers/net/ethernet/amazon/ena/ena_netdev.h ++++ b/drivers/net/ethernet/amazon/ena/ena_netdev.h +@@ -262,9 +262,11 @@ struct ena_ring { + bool disable_meta_caching; + u16 no_interrupt_event_cnt; + +- /* cpu for TPH */ ++ /* cpu and NUMA for TPH */ + int cpu; +- /* number of tx/rx_buffer_info's entries */ ++ int numa_node; ++ ++ /* number of tx/rx_buffer_info's entries */ + int ring_size; + + enum ena_admin_placement_policy_type tx_mem_queue_type; +@@ -392,6 +394,8 @@ int ena_update_queue_sizes(struct ena_adapter *adapter, + + int ena_update_queue_count(struct ena_adapter *adapter, u32 new_channel_count); + ++int ena_set_rx_copybreak(struct ena_adapter *adapter, u32 rx_copybreak); ++ + int ena_get_sset_count(struct net_device *netdev, int sset); + + static inline void ena_reset_device(struct ena_adapter *adapter, +@@ -409,6 +413,15 @@ enum ena_xdp_errors_t { + ENA_XDP_NO_ENOUGH_QUEUES, + }; + ++enum ENA_XDP_ACTIONS { ++ ENA_XDP_PASS = 0, ++ ENA_XDP_TX = BIT(0), ++ ENA_XDP_REDIRECT = BIT(1), ++ ENA_XDP_DROP = BIT(2) ++}; ++ ++#define ENA_XDP_FORWARDED (ENA_XDP_TX | ENA_XDP_REDIRECT) ++ + static inline bool ena_xdp_present(struct ena_adapter *adapter) + { + return !!adapter->xdp_bpf_prog; +diff --git a/drivers/net/ethernet/amd/xgbe/xgbe-drv.c b/drivers/net/ethernet/amd/xgbe/xgbe-drv.c +index f342bb8531891..2ee2cd4a1e356 100644 +--- a/drivers/net/ethernet/amd/xgbe/xgbe-drv.c ++++ b/drivers/net/ethernet/amd/xgbe/xgbe-drv.c +@@ -1064,6 +1064,9 @@ static void xgbe_free_irqs(struct xgbe_prv_data *pdata) + + devm_free_irq(pdata->dev, pdata->dev_irq, pdata); + ++ tasklet_kill(&pdata->tasklet_dev); ++ tasklet_kill(&pdata->tasklet_ecc); ++ + if (pdata->vdata->ecc_support && (pdata->dev_irq != pdata->ecc_irq)) + devm_free_irq(pdata->dev, pdata->ecc_irq, pdata); + +diff --git a/drivers/net/ethernet/amd/xgbe/xgbe-i2c.c b/drivers/net/ethernet/amd/xgbe/xgbe-i2c.c +index 22d4fc547a0a3..a9ccc4258ee50 100644 +--- a/drivers/net/ethernet/amd/xgbe/xgbe-i2c.c ++++ b/drivers/net/ethernet/amd/xgbe/xgbe-i2c.c +@@ -447,8 +447,10 @@ static void xgbe_i2c_stop(struct xgbe_prv_data *pdata) + xgbe_i2c_disable(pdata); + xgbe_i2c_clear_all_interrupts(pdata); + +- if (pdata->dev_irq != pdata->i2c_irq) ++ if (pdata->dev_irq != pdata->i2c_irq) { + devm_free_irq(pdata->dev, pdata->i2c_irq, pdata); ++ tasklet_kill(&pdata->tasklet_i2c); ++ } + } + + static int xgbe_i2c_start(struct xgbe_prv_data *pdata) +diff --git a/drivers/net/ethernet/amd/xgbe/xgbe-mdio.c b/drivers/net/ethernet/amd/xgbe/xgbe-mdio.c +index 4e97b48695220..0c5c1b1556830 100644 +--- a/drivers/net/ethernet/amd/xgbe/xgbe-mdio.c ++++ b/drivers/net/ethernet/amd/xgbe/xgbe-mdio.c +@@ -1390,8 +1390,10 @@ static void xgbe_phy_stop(struct xgbe_prv_data *pdata) + /* Disable auto-negotiation */ + xgbe_an_disable_all(pdata); + +- if (pdata->dev_irq != pdata->an_irq) ++ if (pdata->dev_irq != pdata->an_irq) { + devm_free_irq(pdata->dev, pdata->an_irq, pdata); ++ tasklet_kill(&pdata->tasklet_an); ++ } + + pdata->phy_if.phy_impl.stop(pdata); + +diff --git a/drivers/net/ethernet/broadcom/bnxt/bnxt.c b/drivers/net/ethernet/broadcom/bnxt/bnxt.c +index 57cabe20aa122..1b38295254e26 100644 +--- a/drivers/net/ethernet/broadcom/bnxt/bnxt.c ++++ b/drivers/net/ethernet/broadcom/bnxt/bnxt.c +@@ -988,8 +988,7 @@ static struct sk_buff *bnxt_rx_multi_page_skb(struct bnxt *bp, + dma_addr -= bp->rx_dma_offset; + dma_unmap_page_attrs(&bp->pdev->dev, dma_addr, PAGE_SIZE, bp->rx_dir, + DMA_ATTR_WEAK_ORDERING); +- skb = build_skb(page_address(page), BNXT_PAGE_MODE_BUF_SIZE + +- bp->rx_dma_offset); ++ skb = build_skb(page_address(page), PAGE_SIZE); + if (!skb) { + __free_page(page); + return NULL; +@@ -1922,7 +1921,7 @@ static int bnxt_rx_pkt(struct bnxt *bp, struct bnxt_cp_ring_info *cpr, + dma_addr = rx_buf->mapping; + + if (bnxt_xdp_attached(bp, rxr)) { +- bnxt_xdp_buff_init(bp, rxr, cons, &data_ptr, &len, &xdp); ++ bnxt_xdp_buff_init(bp, rxr, cons, data_ptr, len, &xdp); + if (agg_bufs) { + u32 frag_len = bnxt_rx_agg_pages_xdp(bp, cpr, &xdp, + cp_cons, agg_bufs, +@@ -1937,7 +1936,7 @@ static int bnxt_rx_pkt(struct bnxt *bp, struct bnxt_cp_ring_info *cpr, + } + + if (xdp_active) { +- if (bnxt_rx_xdp(bp, rxr, cons, xdp, data, &len, event)) { ++ if (bnxt_rx_xdp(bp, rxr, cons, xdp, data, &data_ptr, &len, event)) { + rc = 1; + goto next_rx; + } +@@ -3966,8 +3965,10 @@ void bnxt_set_ring_params(struct bnxt *bp) + bp->rx_agg_ring_mask = (bp->rx_agg_nr_pages * RX_DESC_CNT) - 1; + + if (BNXT_RX_PAGE_MODE(bp)) { +- rx_space = BNXT_PAGE_MODE_BUF_SIZE; +- rx_size = BNXT_MAX_PAGE_MODE_MTU; ++ rx_space = PAGE_SIZE; ++ rx_size = PAGE_SIZE - ++ ALIGN(max(NET_SKB_PAD, XDP_PACKET_HEADROOM), 8) - ++ SKB_DATA_ALIGN(sizeof(struct skb_shared_info)); + } else { + rx_size = SKB_DATA_ALIGN(BNXT_RX_COPY_THRESH + NET_IP_ALIGN); + rx_space = rx_size + NET_SKB_PAD + +@@ -5370,15 +5371,16 @@ static int bnxt_hwrm_vnic_set_hds(struct bnxt *bp, u16 vnic_id) + req->flags = cpu_to_le32(VNIC_PLCMODES_CFG_REQ_FLAGS_JUMBO_PLACEMENT); + req->enables = cpu_to_le32(VNIC_PLCMODES_CFG_REQ_ENABLES_JUMBO_THRESH_VALID); + +- if (BNXT_RX_PAGE_MODE(bp) && !BNXT_RX_JUMBO_MODE(bp)) { ++ if (BNXT_RX_PAGE_MODE(bp)) { ++ req->jumbo_thresh = cpu_to_le16(bp->rx_buf_use_size); ++ } else { + req->flags |= cpu_to_le32(VNIC_PLCMODES_CFG_REQ_FLAGS_HDS_IPV4 | + VNIC_PLCMODES_CFG_REQ_FLAGS_HDS_IPV6); + req->enables |= + cpu_to_le32(VNIC_PLCMODES_CFG_REQ_ENABLES_HDS_THRESHOLD_VALID); ++ req->jumbo_thresh = cpu_to_le16(bp->rx_copy_thresh); ++ req->hds_threshold = cpu_to_le16(bp->rx_copy_thresh); + } +- /* thresholds not implemented in firmware yet */ +- req->jumbo_thresh = cpu_to_le16(bp->rx_copy_thresh); +- req->hds_threshold = cpu_to_le16(bp->rx_copy_thresh); + req->vnic_id = cpu_to_le32(vnic->fw_vnic_id); + return hwrm_req_send(bp, req); + } +diff --git a/drivers/net/ethernet/broadcom/bnxt/bnxt.h b/drivers/net/ethernet/broadcom/bnxt/bnxt.h +index d5fa43cfe5248..02741d499bf4a 100644 +--- a/drivers/net/ethernet/broadcom/bnxt/bnxt.h ++++ b/drivers/net/ethernet/broadcom/bnxt/bnxt.h +@@ -591,12 +591,20 @@ struct nqe_cn { + #define BNXT_RX_PAGE_SIZE (1 << BNXT_RX_PAGE_SHIFT) + + #define BNXT_MAX_MTU 9500 +-#define BNXT_PAGE_MODE_BUF_SIZE \ ++ ++/* First RX buffer page in XDP multi-buf mode ++ * ++ * +-------------------------------------------------------------------------+ ++ * | XDP_PACKET_HEADROOM | bp->rx_buf_use_size | skb_shared_info| ++ * | (bp->rx_dma_offset) | | | ++ * +-------------------------------------------------------------------------+ ++ */ ++#define BNXT_MAX_PAGE_MODE_MTU_SBUF \ + ((unsigned int)PAGE_SIZE - VLAN_ETH_HLEN - NET_IP_ALIGN - \ + XDP_PACKET_HEADROOM) + #define BNXT_MAX_PAGE_MODE_MTU \ +- BNXT_PAGE_MODE_BUF_SIZE - \ +- SKB_DATA_ALIGN((unsigned int)sizeof(struct skb_shared_info)) ++ (BNXT_MAX_PAGE_MODE_MTU_SBUF - \ ++ SKB_DATA_ALIGN((unsigned int)sizeof(struct skb_shared_info))) + + #define BNXT_MIN_PKT_SIZE 52 + +@@ -2131,7 +2139,6 @@ 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; +diff --git a/drivers/net/ethernet/broadcom/bnxt/bnxt_xdp.c b/drivers/net/ethernet/broadcom/bnxt/bnxt_xdp.c +index c3065ec0a4798..36d5202c0aeec 100644 +--- a/drivers/net/ethernet/broadcom/bnxt/bnxt_xdp.c ++++ b/drivers/net/ethernet/broadcom/bnxt/bnxt_xdp.c +@@ -177,7 +177,7 @@ bool bnxt_xdp_attached(struct bnxt *bp, struct bnxt_rx_ring_info *rxr) + } + + void bnxt_xdp_buff_init(struct bnxt *bp, struct bnxt_rx_ring_info *rxr, +- u16 cons, u8 **data_ptr, unsigned int *len, ++ u16 cons, u8 *data_ptr, unsigned int len, + struct xdp_buff *xdp) + { + struct bnxt_sw_rx_bd *rx_buf; +@@ -191,13 +191,10 @@ void bnxt_xdp_buff_init(struct bnxt *bp, struct bnxt_rx_ring_info *rxr, + offset = bp->rx_offset; + + mapping = rx_buf->mapping - bp->rx_dma_offset; +- dma_sync_single_for_cpu(&pdev->dev, mapping + offset, *len, bp->rx_dir); +- +- if (bp->xdp_has_frags) +- buflen = BNXT_PAGE_MODE_BUF_SIZE + offset; ++ dma_sync_single_for_cpu(&pdev->dev, mapping + offset, len, bp->rx_dir); + + xdp_init_buff(xdp, buflen, &rxr->xdp_rxq); +- xdp_prepare_buff(xdp, *data_ptr - offset, offset, *len, false); ++ xdp_prepare_buff(xdp, data_ptr - offset, offset, len, false); + } + + void bnxt_xdp_buff_frags_free(struct bnxt_rx_ring_info *rxr, +@@ -222,7 +219,8 @@ void bnxt_xdp_buff_frags_free(struct bnxt_rx_ring_info *rxr, + * false - packet should be passed to the stack. + */ + bool bnxt_rx_xdp(struct bnxt *bp, struct bnxt_rx_ring_info *rxr, u16 cons, +- struct xdp_buff xdp, struct page *page, unsigned int *len, u8 *event) ++ struct xdp_buff xdp, struct page *page, u8 **data_ptr, ++ unsigned int *len, u8 *event) + { + struct bpf_prog *xdp_prog = READ_ONCE(rxr->xdp_prog); + struct bnxt_tx_ring_info *txr; +@@ -255,8 +253,10 @@ bool bnxt_rx_xdp(struct bnxt *bp, struct bnxt_rx_ring_info *rxr, u16 cons, + *event &= ~BNXT_RX_EVENT; + + *len = xdp.data_end - xdp.data; +- if (orig_data != xdp.data) ++ if (orig_data != xdp.data) { + offset = xdp.data - xdp.data_hard_start; ++ *data_ptr = xdp.data_hard_start + offset; ++ } + + switch (act) { + case XDP_PASS: +@@ -401,10 +401,8 @@ 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) +diff --git a/drivers/net/ethernet/broadcom/bnxt/bnxt_xdp.h b/drivers/net/ethernet/broadcom/bnxt/bnxt_xdp.h +index 505911ae095d3..ea430d6961df3 100644 +--- a/drivers/net/ethernet/broadcom/bnxt/bnxt_xdp.h ++++ b/drivers/net/ethernet/broadcom/bnxt/bnxt_xdp.h +@@ -18,8 +18,8 @@ struct bnxt_sw_tx_bd *bnxt_xmit_bd(struct bnxt *bp, + struct xdp_buff *xdp); + void bnxt_tx_int_xdp(struct bnxt *bp, struct bnxt_napi *bnapi, int nr_pkts); + bool bnxt_rx_xdp(struct bnxt *bp, struct bnxt_rx_ring_info *rxr, u16 cons, +- struct xdp_buff xdp, struct page *page, unsigned int *len, +- u8 *event); ++ struct xdp_buff xdp, struct page *page, u8 **data_ptr, ++ unsigned int *len, u8 *event); + int bnxt_xdp(struct net_device *dev, struct netdev_bpf *xdp); + int bnxt_xdp_xmit(struct net_device *dev, int num_frames, + struct xdp_frame **frames, u32 flags); +@@ -27,7 +27,7 @@ int bnxt_xdp_xmit(struct net_device *dev, int num_frames, + bool bnxt_xdp_attached(struct bnxt *bp, struct bnxt_rx_ring_info *rxr); + + void bnxt_xdp_buff_init(struct bnxt *bp, struct bnxt_rx_ring_info *rxr, +- u16 cons, u8 **data_ptr, unsigned int *len, ++ u16 cons, u8 *data_ptr, unsigned int len, + struct xdp_buff *xdp); + void bnxt_xdp_buff_frags_free(struct bnxt_rx_ring_info *rxr, + struct xdp_buff *xdp); +diff --git a/drivers/net/ethernet/hisilicon/hns3/hclge_mbx.h b/drivers/net/ethernet/hisilicon/hns3/hclge_mbx.h +index 7d4ae467f3ad4..abcd7877f7d2a 100644 +--- a/drivers/net/ethernet/hisilicon/hns3/hclge_mbx.h ++++ b/drivers/net/ethernet/hisilicon/hns3/hclge_mbx.h +@@ -233,6 +233,17 @@ struct hclgevf_mbx_arq_ring { + __le16 msg_q[HCLGE_MBX_MAX_ARQ_MSG_NUM][HCLGE_MBX_MAX_ARQ_MSG_SIZE]; + }; + ++struct hclge_dev; ++ ++#define HCLGE_MBX_OPCODE_MAX 256 ++struct hclge_mbx_ops_param { ++ struct hclge_vport *vport; ++ struct hclge_mbx_vf_to_pf_cmd *req; ++ struct hclge_respond_to_vf_msg *resp_msg; ++}; ++ ++typedef int (*hclge_mbx_ops_fn)(struct hclge_mbx_ops_param *param); ++ + #define hclge_mbx_ring_ptr_move_crq(crq) \ + (crq->next_to_use = (crq->next_to_use + 1) % crq->desc_num) + #define hclge_mbx_tail_ptr_move_arq(arq) \ +diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3_enet.c b/drivers/net/ethernet/hisilicon/hns3/hns3_enet.c +index 44d4265f109a8..d5d7fae354e7e 100644 +--- a/drivers/net/ethernet/hisilicon/hns3/hns3_enet.c ++++ b/drivers/net/ethernet/hisilicon/hns3/hns3_enet.c +@@ -3813,18 +3813,16 @@ static int hns3_gro_complete(struct sk_buff *skb, u32 l234info) + return 0; + } + +-static bool hns3_checksum_complete(struct hns3_enet_ring *ring, ++static void hns3_checksum_complete(struct hns3_enet_ring *ring, + struct sk_buff *skb, u32 ptype, u16 csum) + { + if (ptype == HNS3_INVALID_PTYPE || + hns3_rx_ptype_tbl[ptype].ip_summed != CHECKSUM_COMPLETE) +- return false; ++ return; + + hns3_ring_stats_update(ring, csum_complete); + skb->ip_summed = CHECKSUM_COMPLETE; + skb->csum = csum_unfold((__force __sum16)csum); +- +- return true; + } + + static void hns3_rx_handle_csum(struct sk_buff *skb, u32 l234info, +@@ -3884,8 +3882,7 @@ static void hns3_rx_checksum(struct hns3_enet_ring *ring, struct sk_buff *skb, + ptype = hnae3_get_field(ol_info, HNS3_RXD_PTYPE_M, + HNS3_RXD_PTYPE_S); + +- if (hns3_checksum_complete(ring, skb, ptype, csum)) +- return; ++ hns3_checksum_complete(ring, skb, ptype, csum); + + /* check if hardware has done checksum */ + if (!(bd_base_info & BIT(HNS3_RXD_L3L4P_B))) +@@ -3894,6 +3891,7 @@ static void hns3_rx_checksum(struct hns3_enet_ring *ring, struct sk_buff *skb, + if (unlikely(l234info & (BIT(HNS3_RXD_L3E_B) | BIT(HNS3_RXD_L4E_B) | + BIT(HNS3_RXD_OL3E_B) | + BIT(HNS3_RXD_OL4E_B)))) { ++ skb->ip_summed = CHECKSUM_NONE; + hns3_ring_stats_update(ring, l3l4_csum_err); + + return; +diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.c b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.c +index 7e8a60f2401c9..d2dde3f1fb884 100644 +--- a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.c ++++ b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.c +@@ -3713,9 +3713,17 @@ static int hclge_set_all_vf_rst(struct hclge_dev *hdev, bool reset) + return ret; + } + +- if (!reset || !test_bit(HCLGE_VPORT_STATE_ALIVE, &vport->state)) ++ if (!reset || ++ !test_bit(HCLGE_VPORT_STATE_INITED, &vport->state)) + continue; + ++ if (!test_bit(HCLGE_VPORT_STATE_ALIVE, &vport->state) && ++ hdev->reset_type == HNAE3_FUNC_RESET) { ++ set_bit(HCLGE_VPORT_NEED_NOTIFY_RESET, ++ &vport->need_notify); ++ continue; ++ } ++ + /* Inform VF to process the reset. + * hclge_inform_reset_assert_to_vf may fail if VF + * driver is not loaded. +@@ -4412,18 +4420,25 @@ static void hclge_reset_service_task(struct hclge_dev *hdev) + + static void hclge_update_vport_alive(struct hclge_dev *hdev) + { ++#define HCLGE_ALIVE_SECONDS_NORMAL 8 ++ ++ unsigned long alive_time = HCLGE_ALIVE_SECONDS_NORMAL * HZ; + int i; + + /* start from vport 1 for PF is always alive */ + for (i = 1; i < hdev->num_alloc_vport; i++) { + struct hclge_vport *vport = &hdev->vport[i]; + +- if (time_after(jiffies, vport->last_active_jiffies + 8 * HZ)) ++ if (!test_bit(HCLGE_VPORT_STATE_INITED, &vport->state) || ++ !test_bit(HCLGE_VPORT_STATE_ALIVE, &vport->state)) ++ continue; ++ if (time_after(jiffies, vport->last_active_jiffies + ++ alive_time)) { + clear_bit(HCLGE_VPORT_STATE_ALIVE, &vport->state); +- +- /* If vf is not alive, set to default value */ +- if (!test_bit(HCLGE_VPORT_STATE_ALIVE, &vport->state)) +- vport->mps = HCLGE_MAC_DEFAULT_FRAME; ++ dev_warn(&hdev->pdev->dev, ++ "VF %u heartbeat timeout\n", ++ i - HCLGE_VF_VPORT_START_NUM); ++ } + } + } + +@@ -7853,9 +7868,11 @@ int hclge_vport_start(struct hclge_vport *vport) + { + struct hclge_dev *hdev = vport->back; + ++ set_bit(HCLGE_VPORT_STATE_INITED, &vport->state); + set_bit(HCLGE_VPORT_STATE_ALIVE, &vport->state); + set_bit(HCLGE_VPORT_STATE_PROMISC_CHANGE, &vport->state); + vport->last_active_jiffies = jiffies; ++ vport->need_notify = 0; + + if (test_bit(vport->vport_id, hdev->vport_config_block)) { + if (vport->vport_id) { +@@ -7873,7 +7890,9 @@ int hclge_vport_start(struct hclge_vport *vport) + + void hclge_vport_stop(struct hclge_vport *vport) + { ++ clear_bit(HCLGE_VPORT_STATE_INITED, &vport->state); + clear_bit(HCLGE_VPORT_STATE_ALIVE, &vport->state); ++ vport->need_notify = 0; + } + + static int hclge_client_start(struct hnae3_handle *handle) +@@ -8997,7 +9016,8 @@ static int hclge_set_vf_mac(struct hnae3_handle *handle, int vf, + return 0; + } + +- dev_info(&hdev->pdev->dev, "MAC of VF %d has been set to %s\n", ++ dev_info(&hdev->pdev->dev, ++ "MAC of VF %d has been set to %s, will be active after VF reset\n", + vf, format_mac_addr); + return 0; + } +@@ -10254,12 +10274,16 @@ static int hclge_set_vf_vlan_filter(struct hnae3_handle *handle, int vfid, + * for DEVICE_VERSION_V3, vf doesn't need to know about the port based + * VLAN state. + */ +- if (ae_dev->dev_version < HNAE3_DEVICE_VERSION_V3 && +- test_bit(HCLGE_VPORT_STATE_ALIVE, &vport->state)) +- (void)hclge_push_vf_port_base_vlan_info(&hdev->vport[0], +- vport->vport_id, +- state, &vlan_info); +- ++ if (ae_dev->dev_version < HNAE3_DEVICE_VERSION_V3) { ++ if (test_bit(HCLGE_VPORT_STATE_ALIVE, &vport->state)) ++ (void)hclge_push_vf_port_base_vlan_info(&hdev->vport[0], ++ vport->vport_id, ++ state, ++ &vlan_info); ++ else ++ set_bit(HCLGE_VPORT_NEED_NOTIFY_VF_VLAN, ++ &vport->need_notify); ++ } + return 0; + } + +@@ -11723,7 +11747,7 @@ static void hclge_reset_vport_state(struct hclge_dev *hdev) + int i; + + for (i = 0; i < hdev->num_alloc_vport; i++) { +- hclge_vport_stop(vport); ++ clear_bit(HCLGE_VPORT_STATE_ALIVE, &vport->state); + vport++; + } + } +@@ -12536,60 +12560,71 @@ static int hclge_gro_en(struct hnae3_handle *handle, bool enable) + return ret; + } + +-static void hclge_sync_promisc_mode(struct hclge_dev *hdev) ++static int hclge_sync_vport_promisc_mode(struct hclge_vport *vport) + { +- struct hclge_vport *vport = &hdev->vport[0]; + struct hnae3_handle *handle = &vport->nic; ++ struct hclge_dev *hdev = vport->back; ++ bool uc_en = false; ++ bool mc_en = false; + u8 tmp_flags; ++ bool bc_en; + int ret; +- u16 i; + + if (vport->last_promisc_flags != vport->overflow_promisc_flags) { + set_bit(HCLGE_VPORT_STATE_PROMISC_CHANGE, &vport->state); + vport->last_promisc_flags = vport->overflow_promisc_flags; + } + +- if (test_bit(HCLGE_VPORT_STATE_PROMISC_CHANGE, &vport->state)) { ++ if (!test_and_clear_bit(HCLGE_VPORT_STATE_PROMISC_CHANGE, ++ &vport->state)) ++ return 0; ++ ++ /* for PF */ ++ if (!vport->vport_id) { + tmp_flags = handle->netdev_flags | vport->last_promisc_flags; + ret = hclge_set_promisc_mode(handle, tmp_flags & HNAE3_UPE, + tmp_flags & HNAE3_MPE); +- if (!ret) { +- clear_bit(HCLGE_VPORT_STATE_PROMISC_CHANGE, +- &vport->state); ++ if (!ret) + set_bit(HCLGE_VPORT_STATE_VLAN_FLTR_CHANGE, + &vport->state); +- } ++ else ++ set_bit(HCLGE_VPORT_STATE_PROMISC_CHANGE, ++ &vport->state); ++ return ret; + } + +- for (i = 1; i < hdev->num_alloc_vport; i++) { +- bool uc_en = false; +- bool mc_en = false; +- bool bc_en; ++ /* for VF */ ++ if (vport->vf_info.trusted) { ++ uc_en = vport->vf_info.request_uc_en > 0 || ++ vport->overflow_promisc_flags & HNAE3_OVERFLOW_UPE; ++ mc_en = vport->vf_info.request_mc_en > 0 || ++ vport->overflow_promisc_flags & HNAE3_OVERFLOW_MPE; ++ } ++ bc_en = vport->vf_info.request_bc_en > 0; + +- vport = &hdev->vport[i]; ++ ret = hclge_cmd_set_promisc_mode(hdev, vport->vport_id, uc_en, ++ mc_en, bc_en); ++ if (ret) { ++ set_bit(HCLGE_VPORT_STATE_PROMISC_CHANGE, &vport->state); ++ return ret; ++ } ++ hclge_set_vport_vlan_fltr_change(vport); + +- if (!test_and_clear_bit(HCLGE_VPORT_STATE_PROMISC_CHANGE, +- &vport->state)) +- continue; ++ return 0; ++} + +- if (vport->vf_info.trusted) { +- uc_en = vport->vf_info.request_uc_en > 0 || +- vport->overflow_promisc_flags & +- HNAE3_OVERFLOW_UPE; +- mc_en = vport->vf_info.request_mc_en > 0 || +- vport->overflow_promisc_flags & +- HNAE3_OVERFLOW_MPE; +- } +- bc_en = vport->vf_info.request_bc_en > 0; ++static void hclge_sync_promisc_mode(struct hclge_dev *hdev) ++{ ++ struct hclge_vport *vport; ++ int ret; ++ u16 i; + +- ret = hclge_cmd_set_promisc_mode(hdev, vport->vport_id, uc_en, +- mc_en, bc_en); +- if (ret) { +- set_bit(HCLGE_VPORT_STATE_PROMISC_CHANGE, +- &vport->state); ++ for (i = 0; i < hdev->num_alloc_vport; i++) { ++ vport = &hdev->vport[i]; ++ ++ ret = hclge_sync_vport_promisc_mode(vport); ++ if (ret) + return; +- } +- hclge_set_vport_vlan_fltr_change(vport); + } + } + +@@ -12726,6 +12761,11 @@ static void hclge_clear_vport_vf_info(struct hclge_vport *vport, int vfid) + struct hclge_vlan_info vlan_info; + int ret; + ++ clear_bit(HCLGE_VPORT_STATE_INITED, &vport->state); ++ clear_bit(HCLGE_VPORT_STATE_ALIVE, &vport->state); ++ vport->need_notify = 0; ++ vport->mps = 0; ++ + /* after disable sriov, clean VF rate configured by PF */ + ret = hclge_tm_qs_shaper_cfg(vport, 0); + if (ret) +diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.h b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.h +index 18caddd541f8a..14473e29fe034 100644 +--- a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.h ++++ b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.h +@@ -972,9 +972,15 @@ enum HCLGE_VPORT_STATE { + HCLGE_VPORT_STATE_MAC_TBL_CHANGE, + HCLGE_VPORT_STATE_PROMISC_CHANGE, + HCLGE_VPORT_STATE_VLAN_FLTR_CHANGE, ++ HCLGE_VPORT_STATE_INITED, + HCLGE_VPORT_STATE_MAX + }; + ++enum HCLGE_VPORT_NEED_NOTIFY { ++ HCLGE_VPORT_NEED_NOTIFY_RESET, ++ HCLGE_VPORT_NEED_NOTIFY_VF_VLAN, ++}; ++ + struct hclge_vlan_info { + u16 vlan_proto; /* so far support 802.1Q only */ + u16 qos; +@@ -1021,6 +1027,7 @@ struct hclge_vport { + struct hnae3_handle roce; + + unsigned long state; ++ unsigned long need_notify; + unsigned long last_active_jiffies; + u32 mps; /* Max packet size */ + struct hclge_vf_info vf_info; +diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_mbx.c b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_mbx.c +index e1012f7f9b734..04ff9bf121853 100644 +--- a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_mbx.c ++++ b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_mbx.c +@@ -124,17 +124,26 @@ static int hclge_send_mbx_msg(struct hclge_vport *vport, u8 *msg, u16 msg_len, + return status; + } + ++static int hclge_inform_vf_reset(struct hclge_vport *vport, u16 reset_type) ++{ ++ __le16 msg_data; ++ u8 dest_vfid; ++ ++ dest_vfid = (u8)vport->vport_id; ++ msg_data = cpu_to_le16(reset_type); ++ ++ /* send this requested info to VF */ ++ return hclge_send_mbx_msg(vport, (u8 *)&msg_data, sizeof(msg_data), ++ HCLGE_MBX_ASSERTING_RESET, dest_vfid); ++} ++ + int hclge_inform_reset_assert_to_vf(struct hclge_vport *vport) + { + struct hclge_dev *hdev = vport->back; +- __le16 msg_data; + u16 reset_type; +- u8 dest_vfid; + + BUILD_BUG_ON(HNAE3_MAX_RESET > U16_MAX); + +- dest_vfid = (u8)vport->vport_id; +- + if (hdev->reset_type == HNAE3_FUNC_RESET) + reset_type = HNAE3_VF_PF_FUNC_RESET; + else if (hdev->reset_type == HNAE3_FLR_RESET) +@@ -142,11 +151,7 @@ int hclge_inform_reset_assert_to_vf(struct hclge_vport *vport) + else + reset_type = HNAE3_VF_FUNC_RESET; + +- msg_data = cpu_to_le16(reset_type); +- +- /* send this requested info to VF */ +- return hclge_send_mbx_msg(vport, (u8 *)&msg_data, sizeof(msg_data), +- HCLGE_MBX_ASSERTING_RESET, dest_vfid); ++ return hclge_inform_vf_reset(vport, reset_type); + } + + static void hclge_free_vector_ring_chain(struct hnae3_ring_chain_node *head) +@@ -652,9 +657,56 @@ static int hclge_reset_vf(struct hclge_vport *vport) + return hclge_func_reset_cmd(hdev, vport->vport_id); + } + ++static void hclge_notify_vf_config(struct hclge_vport *vport) ++{ ++ struct hclge_dev *hdev = vport->back; ++ struct hnae3_ae_dev *ae_dev = pci_get_drvdata(hdev->pdev); ++ struct hclge_port_base_vlan_config *vlan_cfg; ++ int ret; ++ ++ hclge_push_vf_link_status(vport); ++ if (test_bit(HCLGE_VPORT_NEED_NOTIFY_RESET, &vport->need_notify)) { ++ ret = hclge_inform_vf_reset(vport, HNAE3_VF_PF_FUNC_RESET); ++ if (ret) { ++ dev_err(&hdev->pdev->dev, ++ "failed to inform VF %u reset!", ++ vport->vport_id - HCLGE_VF_VPORT_START_NUM); ++ return; ++ } ++ vport->need_notify = 0; ++ return; ++ } ++ ++ if (ae_dev->dev_version < HNAE3_DEVICE_VERSION_V3 && ++ test_bit(HCLGE_VPORT_NEED_NOTIFY_VF_VLAN, &vport->need_notify)) { ++ vlan_cfg = &vport->port_base_vlan_cfg; ++ ret = hclge_push_vf_port_base_vlan_info(&hdev->vport[0], ++ vport->vport_id, ++ vlan_cfg->state, ++ &vlan_cfg->vlan_info); ++ if (ret) { ++ dev_err(&hdev->pdev->dev, ++ "failed to inform VF %u port base vlan!", ++ vport->vport_id - HCLGE_VF_VPORT_START_NUM); ++ return; ++ } ++ clear_bit(HCLGE_VPORT_NEED_NOTIFY_VF_VLAN, &vport->need_notify); ++ } ++} ++ + static void hclge_vf_keep_alive(struct hclge_vport *vport) + { ++ struct hclge_dev *hdev = vport->back; ++ + vport->last_active_jiffies = jiffies; ++ ++ if (test_bit(HCLGE_VPORT_STATE_INITED, &vport->state) && ++ !test_bit(HCLGE_VPORT_STATE_ALIVE, &vport->state)) { ++ set_bit(HCLGE_VPORT_STATE_ALIVE, &vport->state); ++ dev_info(&hdev->pdev->dev, "VF %u is alive!", ++ vport->vport_id - HCLGE_VF_VPORT_START_NUM); ++ hclge_notify_vf_config(vport); ++ } + } + + static int hclge_set_vf_mtu(struct hclge_vport *vport, +@@ -779,17 +831,285 @@ static void hclge_handle_vf_tbl(struct hclge_vport *vport, + } + } + ++static int ++hclge_mbx_map_ring_to_vector_handler(struct hclge_mbx_ops_param *param) ++{ ++ return hclge_map_unmap_ring_to_vf_vector(param->vport, true, ++ param->req); ++} ++ ++static int ++hclge_mbx_unmap_ring_to_vector_handler(struct hclge_mbx_ops_param *param) ++{ ++ return hclge_map_unmap_ring_to_vf_vector(param->vport, false, ++ param->req); ++} ++ ++static int ++hclge_mbx_get_ring_vector_map_handler(struct hclge_mbx_ops_param *param) ++{ ++ int ret; ++ ++ ret = hclge_get_vf_ring_vector_map(param->vport, param->req, ++ param->resp_msg); ++ if (ret) ++ dev_err(¶m->vport->back->pdev->dev, ++ "PF fail(%d) to get VF ring vector map\n", ++ ret); ++ return ret; ++} ++ ++static int hclge_mbx_set_promisc_mode_handler(struct hclge_mbx_ops_param *param) ++{ ++ hclge_set_vf_promisc_mode(param->vport, param->req); ++ return 0; ++} ++ ++static int hclge_mbx_set_unicast_handler(struct hclge_mbx_ops_param *param) ++{ ++ int ret; ++ ++ ret = hclge_set_vf_uc_mac_addr(param->vport, param->req); ++ if (ret) ++ dev_err(¶m->vport->back->pdev->dev, ++ "PF fail(%d) to set VF UC MAC Addr\n", ++ ret); ++ return ret; ++} ++ ++static int hclge_mbx_set_multicast_handler(struct hclge_mbx_ops_param *param) ++{ ++ int ret; ++ ++ ret = hclge_set_vf_mc_mac_addr(param->vport, param->req); ++ if (ret) ++ dev_err(¶m->vport->back->pdev->dev, ++ "PF fail(%d) to set VF MC MAC Addr\n", ++ ret); ++ return ret; ++} ++ ++static int hclge_mbx_set_vlan_handler(struct hclge_mbx_ops_param *param) ++{ ++ int ret; ++ ++ ret = hclge_set_vf_vlan_cfg(param->vport, param->req, param->resp_msg); ++ if (ret) ++ dev_err(¶m->vport->back->pdev->dev, ++ "PF failed(%d) to config VF's VLAN\n", ++ ret); ++ return ret; ++} ++ ++static int hclge_mbx_set_alive_handler(struct hclge_mbx_ops_param *param) ++{ ++ int ret; ++ ++ ret = hclge_set_vf_alive(param->vport, param->req); ++ if (ret) ++ dev_err(¶m->vport->back->pdev->dev, ++ "PF failed(%d) to set VF's ALIVE\n", ++ ret); ++ return ret; ++} ++ ++static int hclge_mbx_get_qinfo_handler(struct hclge_mbx_ops_param *param) ++{ ++ hclge_get_vf_queue_info(param->vport, param->resp_msg); ++ return 0; ++} ++ ++static int hclge_mbx_get_qdepth_handler(struct hclge_mbx_ops_param *param) ++{ ++ hclge_get_vf_queue_depth(param->vport, param->resp_msg); ++ return 0; ++} ++ ++static int hclge_mbx_get_basic_info_handler(struct hclge_mbx_ops_param *param) ++{ ++ hclge_get_basic_info(param->vport, param->resp_msg); ++ return 0; ++} ++ ++static int hclge_mbx_get_link_status_handler(struct hclge_mbx_ops_param *param) ++{ ++ int ret; ++ ++ ret = hclge_push_vf_link_status(param->vport); ++ if (ret) ++ dev_err(¶m->vport->back->pdev->dev, ++ "failed to inform link stat to VF, ret = %d\n", ++ ret); ++ return ret; ++} ++ ++static int hclge_mbx_queue_reset_handler(struct hclge_mbx_ops_param *param) ++{ ++ return hclge_mbx_reset_vf_queue(param->vport, param->req, ++ param->resp_msg); ++} ++ ++static int hclge_mbx_reset_handler(struct hclge_mbx_ops_param *param) ++{ ++ return hclge_reset_vf(param->vport); ++} ++ ++static int hclge_mbx_keep_alive_handler(struct hclge_mbx_ops_param *param) ++{ ++ hclge_vf_keep_alive(param->vport); ++ return 0; ++} ++ ++static int hclge_mbx_set_mtu_handler(struct hclge_mbx_ops_param *param) ++{ ++ int ret; ++ ++ ret = hclge_set_vf_mtu(param->vport, param->req); ++ if (ret) ++ dev_err(¶m->vport->back->pdev->dev, ++ "VF fail(%d) to set mtu\n", ret); ++ return ret; ++} ++ ++static int hclge_mbx_get_qid_in_pf_handler(struct hclge_mbx_ops_param *param) ++{ ++ return hclge_get_queue_id_in_pf(param->vport, param->req, ++ param->resp_msg); ++} ++ ++static int hclge_mbx_get_rss_key_handler(struct hclge_mbx_ops_param *param) ++{ ++ return hclge_get_rss_key(param->vport, param->req, param->resp_msg); ++} ++ ++static int hclge_mbx_get_link_mode_handler(struct hclge_mbx_ops_param *param) ++{ ++ hclge_get_link_mode(param->vport, param->req); ++ return 0; ++} ++ ++static int ++hclge_mbx_get_vf_flr_status_handler(struct hclge_mbx_ops_param *param) ++{ ++ hclge_rm_vport_all_mac_table(param->vport, false, ++ HCLGE_MAC_ADDR_UC); ++ hclge_rm_vport_all_mac_table(param->vport, false, ++ HCLGE_MAC_ADDR_MC); ++ hclge_rm_vport_all_vlan_table(param->vport, false); ++ return 0; ++} ++ ++static int hclge_mbx_vf_uninit_handler(struct hclge_mbx_ops_param *param) ++{ ++ hclge_rm_vport_all_mac_table(param->vport, true, ++ HCLGE_MAC_ADDR_UC); ++ hclge_rm_vport_all_mac_table(param->vport, true, ++ HCLGE_MAC_ADDR_MC); ++ hclge_rm_vport_all_vlan_table(param->vport, true); ++ param->vport->mps = 0; ++ return 0; ++} ++ ++static int hclge_mbx_get_media_type_handler(struct hclge_mbx_ops_param *param) ++{ ++ hclge_get_vf_media_type(param->vport, param->resp_msg); ++ return 0; ++} ++ ++static int hclge_mbx_push_link_status_handler(struct hclge_mbx_ops_param *param) ++{ ++ hclge_handle_link_change_event(param->vport->back, param->req); ++ return 0; ++} ++ ++static int hclge_mbx_get_mac_addr_handler(struct hclge_mbx_ops_param *param) ++{ ++ hclge_get_vf_mac_addr(param->vport, param->resp_msg); ++ return 0; ++} ++ ++static int hclge_mbx_ncsi_error_handler(struct hclge_mbx_ops_param *param) ++{ ++ hclge_handle_ncsi_error(param->vport->back); ++ return 0; ++} ++ ++static int hclge_mbx_handle_vf_tbl_handler(struct hclge_mbx_ops_param *param) ++{ ++ hclge_handle_vf_tbl(param->vport, param->req); ++ return 0; ++} ++ ++static const hclge_mbx_ops_fn hclge_mbx_ops_list[HCLGE_MBX_OPCODE_MAX] = { ++ [HCLGE_MBX_RESET] = hclge_mbx_reset_handler, ++ [HCLGE_MBX_SET_UNICAST] = hclge_mbx_set_unicast_handler, ++ [HCLGE_MBX_SET_MULTICAST] = hclge_mbx_set_multicast_handler, ++ [HCLGE_MBX_SET_VLAN] = hclge_mbx_set_vlan_handler, ++ [HCLGE_MBX_MAP_RING_TO_VECTOR] = hclge_mbx_map_ring_to_vector_handler, ++ [HCLGE_MBX_UNMAP_RING_TO_VECTOR] = hclge_mbx_unmap_ring_to_vector_handler, ++ [HCLGE_MBX_SET_PROMISC_MODE] = hclge_mbx_set_promisc_mode_handler, ++ [HCLGE_MBX_GET_QINFO] = hclge_mbx_get_qinfo_handler, ++ [HCLGE_MBX_GET_QDEPTH] = hclge_mbx_get_qdepth_handler, ++ [HCLGE_MBX_GET_BASIC_INFO] = hclge_mbx_get_basic_info_handler, ++ [HCLGE_MBX_GET_RSS_KEY] = hclge_mbx_get_rss_key_handler, ++ [HCLGE_MBX_GET_MAC_ADDR] = hclge_mbx_get_mac_addr_handler, ++ [HCLGE_MBX_GET_LINK_STATUS] = hclge_mbx_get_link_status_handler, ++ [HCLGE_MBX_QUEUE_RESET] = hclge_mbx_queue_reset_handler, ++ [HCLGE_MBX_KEEP_ALIVE] = hclge_mbx_keep_alive_handler, ++ [HCLGE_MBX_SET_ALIVE] = hclge_mbx_set_alive_handler, ++ [HCLGE_MBX_SET_MTU] = hclge_mbx_set_mtu_handler, ++ [HCLGE_MBX_GET_QID_IN_PF] = hclge_mbx_get_qid_in_pf_handler, ++ [HCLGE_MBX_GET_LINK_MODE] = hclge_mbx_get_link_mode_handler, ++ [HCLGE_MBX_GET_MEDIA_TYPE] = hclge_mbx_get_media_type_handler, ++ [HCLGE_MBX_VF_UNINIT] = hclge_mbx_vf_uninit_handler, ++ [HCLGE_MBX_HANDLE_VF_TBL] = hclge_mbx_handle_vf_tbl_handler, ++ [HCLGE_MBX_GET_RING_VECTOR_MAP] = hclge_mbx_get_ring_vector_map_handler, ++ [HCLGE_MBX_GET_VF_FLR_STATUS] = hclge_mbx_get_vf_flr_status_handler, ++ [HCLGE_MBX_PUSH_LINK_STATUS] = hclge_mbx_push_link_status_handler, ++ [HCLGE_MBX_NCSI_ERROR] = hclge_mbx_ncsi_error_handler, ++}; ++ ++static void hclge_mbx_request_handling(struct hclge_mbx_ops_param *param) ++{ ++ hclge_mbx_ops_fn cmd_func = NULL; ++ struct hclge_dev *hdev; ++ int ret = 0; ++ ++ hdev = param->vport->back; ++ cmd_func = hclge_mbx_ops_list[param->req->msg.code]; ++ if (cmd_func) ++ ret = cmd_func(param); ++ else ++ dev_err(&hdev->pdev->dev, ++ "un-supported mailbox message, code = %u\n", ++ param->req->msg.code); ++ ++ /* PF driver should not reply IMP */ ++ if (hnae3_get_bit(param->req->mbx_need_resp, HCLGE_MBX_NEED_RESP_B) && ++ param->req->msg.code < HCLGE_MBX_GET_VF_FLR_STATUS) { ++ param->resp_msg->status = ret; ++ if (time_is_before_jiffies(hdev->last_mbx_scheduled + ++ HCLGE_MBX_SCHED_TIMEOUT)) ++ dev_warn(&hdev->pdev->dev, ++ "resp vport%u mbx(%u,%u) late\n", ++ param->req->mbx_src_vfid, ++ param->req->msg.code, ++ param->req->msg.subcode); ++ ++ hclge_gen_resp_to_vf(param->vport, param->req, param->resp_msg); ++ } ++} ++ + void hclge_mbx_handler(struct hclge_dev *hdev) + { + struct hclge_comm_cmq_ring *crq = &hdev->hw.hw.cmq.crq; + struct hclge_respond_to_vf_msg resp_msg; + struct hclge_mbx_vf_to_pf_cmd *req; +- struct hclge_vport *vport; ++ struct hclge_mbx_ops_param param; + struct hclge_desc *desc; +- bool is_del = false; + unsigned int flag; +- int ret = 0; + ++ param.resp_msg = &resp_msg; + /* handle all the mailbox requests in the queue */ + while (!hclge_cmd_crq_empty(&hdev->hw)) { + if (test_bit(HCLGE_COMM_STATE_CMD_DISABLE, +@@ -814,152 +1134,16 @@ void hclge_mbx_handler(struct hclge_dev *hdev) + continue; + } + +- vport = &hdev->vport[req->mbx_src_vfid]; +- + trace_hclge_pf_mbx_get(hdev, req); + + /* clear the resp_msg before processing every mailbox message */ + memset(&resp_msg, 0, sizeof(resp_msg)); +- +- switch (req->msg.code) { +- case HCLGE_MBX_MAP_RING_TO_VECTOR: +- ret = hclge_map_unmap_ring_to_vf_vector(vport, true, +- req); +- break; +- case HCLGE_MBX_UNMAP_RING_TO_VECTOR: +- ret = hclge_map_unmap_ring_to_vf_vector(vport, false, +- req); +- break; +- case HCLGE_MBX_GET_RING_VECTOR_MAP: +- ret = hclge_get_vf_ring_vector_map(vport, req, +- &resp_msg); +- if (ret) +- dev_err(&hdev->pdev->dev, +- "PF fail(%d) to get VF ring vector map\n", +- ret); +- break; +- case HCLGE_MBX_SET_PROMISC_MODE: +- hclge_set_vf_promisc_mode(vport, req); +- break; +- case HCLGE_MBX_SET_UNICAST: +- ret = hclge_set_vf_uc_mac_addr(vport, req); +- if (ret) +- dev_err(&hdev->pdev->dev, +- "PF fail(%d) to set VF UC MAC Addr\n", +- ret); +- break; +- case HCLGE_MBX_SET_MULTICAST: +- ret = hclge_set_vf_mc_mac_addr(vport, req); +- if (ret) +- dev_err(&hdev->pdev->dev, +- "PF fail(%d) to set VF MC MAC Addr\n", +- ret); +- break; +- case HCLGE_MBX_SET_VLAN: +- ret = hclge_set_vf_vlan_cfg(vport, req, &resp_msg); +- if (ret) +- dev_err(&hdev->pdev->dev, +- "PF failed(%d) to config VF's VLAN\n", +- ret); +- break; +- case HCLGE_MBX_SET_ALIVE: +- ret = hclge_set_vf_alive(vport, req); +- if (ret) +- dev_err(&hdev->pdev->dev, +- "PF failed(%d) to set VF's ALIVE\n", +- ret); +- break; +- case HCLGE_MBX_GET_QINFO: +- hclge_get_vf_queue_info(vport, &resp_msg); +- break; +- case HCLGE_MBX_GET_QDEPTH: +- hclge_get_vf_queue_depth(vport, &resp_msg); +- break; +- case HCLGE_MBX_GET_BASIC_INFO: +- hclge_get_basic_info(vport, &resp_msg); +- break; +- case HCLGE_MBX_GET_LINK_STATUS: +- ret = hclge_push_vf_link_status(vport); +- if (ret) +- dev_err(&hdev->pdev->dev, +- "failed to inform link stat to VF, ret = %d\n", +- ret); +- break; +- case HCLGE_MBX_QUEUE_RESET: +- ret = hclge_mbx_reset_vf_queue(vport, req, &resp_msg); +- break; +- case HCLGE_MBX_RESET: +- ret = hclge_reset_vf(vport); +- break; +- case HCLGE_MBX_KEEP_ALIVE: +- hclge_vf_keep_alive(vport); +- break; +- case HCLGE_MBX_SET_MTU: +- ret = hclge_set_vf_mtu(vport, req); +- if (ret) +- dev_err(&hdev->pdev->dev, +- "VF fail(%d) to set mtu\n", ret); +- break; +- case HCLGE_MBX_GET_QID_IN_PF: +- ret = hclge_get_queue_id_in_pf(vport, req, &resp_msg); +- break; +- case HCLGE_MBX_GET_RSS_KEY: +- ret = hclge_get_rss_key(vport, req, &resp_msg); +- break; +- case HCLGE_MBX_GET_LINK_MODE: +- hclge_get_link_mode(vport, req); +- break; +- case HCLGE_MBX_GET_VF_FLR_STATUS: +- case HCLGE_MBX_VF_UNINIT: +- is_del = req->msg.code == HCLGE_MBX_VF_UNINIT; +- hclge_rm_vport_all_mac_table(vport, is_del, +- HCLGE_MAC_ADDR_UC); +- hclge_rm_vport_all_mac_table(vport, is_del, +- HCLGE_MAC_ADDR_MC); +- hclge_rm_vport_all_vlan_table(vport, is_del); +- break; +- case HCLGE_MBX_GET_MEDIA_TYPE: +- hclge_get_vf_media_type(vport, &resp_msg); +- break; +- case HCLGE_MBX_PUSH_LINK_STATUS: +- hclge_handle_link_change_event(hdev, req); +- break; +- case HCLGE_MBX_GET_MAC_ADDR: +- hclge_get_vf_mac_addr(vport, &resp_msg); +- break; +- case HCLGE_MBX_NCSI_ERROR: +- hclge_handle_ncsi_error(hdev); +- break; +- case HCLGE_MBX_HANDLE_VF_TBL: +- hclge_handle_vf_tbl(vport, req); +- break; +- default: +- dev_err(&hdev->pdev->dev, +- "un-supported mailbox message, code = %u\n", +- req->msg.code); +- break; +- } +- +- /* PF driver should not reply IMP */ +- if (hnae3_get_bit(req->mbx_need_resp, HCLGE_MBX_NEED_RESP_B) && +- req->msg.code < HCLGE_MBX_GET_VF_FLR_STATUS) { +- resp_msg.status = ret; +- if (time_is_before_jiffies(hdev->last_mbx_scheduled + +- HCLGE_MBX_SCHED_TIMEOUT)) +- dev_warn(&hdev->pdev->dev, +- "resp vport%u mbx(%u,%u) late\n", +- req->mbx_src_vfid, +- req->msg.code, +- req->msg.subcode); +- +- hclge_gen_resp_to_vf(vport, req, &resp_msg); +- } ++ param.vport = &hdev->vport[req->mbx_src_vfid]; ++ param.req = req; ++ hclge_mbx_request_handling(¶m); + + crq->desc[crq->next_to_use].flag = 0; + hclge_mbx_ring_ptr_move_crq(crq); +- +- /* reinitialize ret after complete the mbx message processing */ +- ret = 0; + } + + /* Write back CMDQ_RQ header pointer, M7 need this pointer */ +diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3vf/hclgevf_main.c b/drivers/net/ethernet/hisilicon/hns3/hns3vf/hclgevf_main.c +index 26f87330173eb..c551508e69325 100644 +--- a/drivers/net/ethernet/hisilicon/hns3/hns3vf/hclgevf_main.c ++++ b/drivers/net/ethernet/hisilicon/hns3/hns3vf/hclgevf_main.c +@@ -2767,7 +2767,8 @@ static int hclgevf_pci_reset(struct hclgevf_dev *hdev) + struct pci_dev *pdev = hdev->pdev; + int ret = 0; + +- if (hdev->reset_type == HNAE3_VF_FULL_RESET && ++ if ((hdev->reset_type == HNAE3_VF_FULL_RESET || ++ hdev->reset_type == HNAE3_FLR_RESET) && + test_bit(HCLGEVF_STATE_IRQ_INITED, &hdev->state)) { + hclgevf_misc_irq_uninit(hdev); + hclgevf_uninit_msi(hdev); +diff --git a/drivers/net/ethernet/intel/ice/ice_xsk.c b/drivers/net/ethernet/intel/ice/ice_xsk.c +index 056c904b83ccb..79fa65d1cf201 100644 +--- a/drivers/net/ethernet/intel/ice/ice_xsk.c ++++ b/drivers/net/ethernet/intel/ice/ice_xsk.c +@@ -772,7 +772,7 @@ construct_skb: + static void + ice_clean_xdp_tx_buf(struct ice_tx_ring *xdp_ring, struct ice_tx_buf *tx_buf) + { +- xdp_return_frame((struct xdp_frame *)tx_buf->raw_buf); ++ page_frag_free(tx_buf->raw_buf); + xdp_ring->xdp_tx_active--; + dma_unmap_single(xdp_ring->dev, dma_unmap_addr(tx_buf, dma), + dma_unmap_len(tx_buf, len), DMA_TO_DEVICE); +diff --git a/drivers/net/ethernet/marvell/octeontx2/nic/otx2_common.c b/drivers/net/ethernet/marvell/octeontx2/nic/otx2_common.c +index 9c2baa437c231..2926d754ade8e 100644 +--- a/drivers/net/ethernet/marvell/octeontx2/nic/otx2_common.c ++++ b/drivers/net/ethernet/marvell/octeontx2/nic/otx2_common.c +@@ -977,6 +977,7 @@ static void otx2_pool_refill_task(struct work_struct *work) + rbpool = cq->rbpool; + free_ptrs = cq->pool_ptrs; + ++ get_cpu(); + while (cq->pool_ptrs) { + if (otx2_alloc_rbuf(pfvf, rbpool, &bufptr)) { + /* Schedule a WQ if we fails to free atleast half of the +@@ -996,6 +997,7 @@ static void otx2_pool_refill_task(struct work_struct *work) + pfvf->hw_ops->aura_freeptr(pfvf, qidx, bufptr + OTX2_HEAD_ROOM); + cq->pool_ptrs--; + } ++ put_cpu(); + cq->refill_task_sched = false; + } + +@@ -1333,6 +1335,7 @@ int otx2_sq_aura_pool_init(struct otx2_nic *pfvf) + if (err) + goto fail; + ++ get_cpu(); + /* Allocate pointers and free them to aura/pool */ + for (qidx = 0; qidx < hw->tot_tx_queues; qidx++) { + pool_id = otx2_get_pool_idx(pfvf, AURA_NIX_SQ, qidx); +@@ -1341,18 +1344,24 @@ int otx2_sq_aura_pool_init(struct otx2_nic *pfvf) + sq = &qset->sq[qidx]; + sq->sqb_count = 0; + sq->sqb_ptrs = kcalloc(num_sqbs, sizeof(*sq->sqb_ptrs), GFP_KERNEL); +- if (!sq->sqb_ptrs) +- return -ENOMEM; ++ if (!sq->sqb_ptrs) { ++ err = -ENOMEM; ++ goto err_mem; ++ } + + for (ptr = 0; ptr < num_sqbs; ptr++) { +- if (otx2_alloc_rbuf(pfvf, pool, &bufptr)) +- return -ENOMEM; ++ err = otx2_alloc_rbuf(pfvf, pool, &bufptr); ++ if (err) ++ goto err_mem; + pfvf->hw_ops->aura_freeptr(pfvf, pool_id, bufptr); + sq->sqb_ptrs[sq->sqb_count++] = (u64)bufptr; + } + } + +- return 0; ++err_mem: ++ put_cpu(); ++ return err ? -ENOMEM : 0; ++ + fail: + otx2_mbox_reset(&pfvf->mbox.mbox, 0); + otx2_aura_pool_free(pfvf); +@@ -1391,18 +1400,21 @@ int otx2_rq_aura_pool_init(struct otx2_nic *pfvf) + if (err) + goto fail; + ++ get_cpu(); + /* Allocate pointers and free them to aura/pool */ + for (pool_id = 0; pool_id < hw->rqpool_cnt; pool_id++) { + pool = &pfvf->qset.pool[pool_id]; + for (ptr = 0; ptr < num_ptrs; ptr++) { +- if (otx2_alloc_rbuf(pfvf, pool, &bufptr)) +- return -ENOMEM; ++ err = otx2_alloc_rbuf(pfvf, pool, &bufptr); ++ if (err) ++ goto err_mem; + pfvf->hw_ops->aura_freeptr(pfvf, pool_id, + bufptr + OTX2_HEAD_ROOM); + } + } +- +- return 0; ++err_mem: ++ put_cpu(); ++ return err ? -ENOMEM : 0; + fail: + otx2_mbox_reset(&pfvf->mbox.mbox, 0); + otx2_aura_pool_free(pfvf); +diff --git a/drivers/net/ethernet/mellanox/mlx5/core/devlink.c b/drivers/net/ethernet/mellanox/mlx5/core/devlink.c +index 66c6a7017695d..97e9ec44a759b 100644 +--- a/drivers/net/ethernet/mellanox/mlx5/core/devlink.c ++++ b/drivers/net/ethernet/mellanox/mlx5/core/devlink.c +@@ -468,7 +468,7 @@ static int mlx5_devlink_enable_roce_validate(struct devlink *devlink, u32 id, + bool new_state = val.vbool; + + if (new_state && !MLX5_CAP_GEN(dev, roce) && +- !MLX5_CAP_GEN(dev, roce_rw_supported)) { ++ !(MLX5_CAP_GEN(dev, roce_rw_supported) && MLX5_CAP_GEN_MAX(dev, roce))) { + NL_SET_ERR_MSG_MOD(extack, "Device doesn't support RoCE"); + return -EOPNOTSUPP; + } +@@ -563,7 +563,7 @@ static int mlx5_devlink_eq_depth_validate(struct devlink *devlink, u32 id, + union devlink_param_value val, + struct netlink_ext_ack *extack) + { +- return (val.vu16 >= 64 && val.vu16 <= 4096) ? 0 : -EINVAL; ++ return (val.vu32 >= 64 && val.vu32 <= 4096) ? 0 : -EINVAL; + } + + static const struct devlink_param mlx5_devlink_params[] = { +diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en/tc_ct.c b/drivers/net/ethernet/mellanox/mlx5/core/en/tc_ct.c +index 864ce0c393e61..f01f7dfdbcf88 100644 +--- a/drivers/net/ethernet/mellanox/mlx5/core/en/tc_ct.c ++++ b/drivers/net/ethernet/mellanox/mlx5/core/en/tc_ct.c +@@ -2080,14 +2080,9 @@ out_err: + static void + mlx5_ct_tc_create_dbgfs(struct mlx5_tc_ct_priv *ct_priv) + { +- bool is_fdb = ct_priv->ns_type == MLX5_FLOW_NAMESPACE_FDB; + struct mlx5_tc_ct_debugfs *ct_dbgfs = &ct_priv->debugfs; +- char dirname[16] = {}; + +- if (sscanf(dirname, "ct_%s", is_fdb ? "fdb" : "nic") < 0) +- return; +- +- ct_dbgfs->root = debugfs_create_dir(dirname, mlx5_debugfs_get_dev_root(ct_priv->dev)); ++ ct_dbgfs->root = debugfs_create_dir("ct", mlx5_debugfs_get_dev_root(ct_priv->dev)); + debugfs_create_atomic_t("offloaded", 0400, ct_dbgfs->root, + &ct_dbgfs->stats.offloaded); + debugfs_create_atomic_t("rx_dropped", 0400, ct_dbgfs->root, +diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en/tc_tun_encap.c b/drivers/net/ethernet/mellanox/mlx5/core/en/tc_tun_encap.c +index ff73d25bc6eb8..2aaf8ab857b8f 100644 +--- a/drivers/net/ethernet/mellanox/mlx5/core/en/tc_tun_encap.c ++++ b/drivers/net/ethernet/mellanox/mlx5/core/en/tc_tun_encap.c +@@ -222,7 +222,7 @@ void mlx5e_tc_encap_flows_del(struct mlx5e_priv *priv, + int err; + + list_for_each_entry(flow, flow_list, tmp_list) { +- if (!mlx5e_is_offloaded_flow(flow) || flow_flag_test(flow, SLOW)) ++ if (!mlx5e_is_offloaded_flow(flow)) + continue; + + attr = mlx5e_tc_get_encap_attr(flow); +@@ -231,6 +231,13 @@ void mlx5e_tc_encap_flows_del(struct mlx5e_priv *priv, + esw_attr->dests[flow->tmp_entry_index].flags &= ~MLX5_ESW_DEST_ENCAP_VALID; + esw_attr->dests[flow->tmp_entry_index].pkt_reformat = NULL; + ++ /* Clear pkt_reformat before checking slow path flag. Because ++ * in next iteration, the same flow is already set slow path ++ * flag, but still need to clear the pkt_reformat. ++ */ ++ if (flow_flag_test(flow, SLOW)) ++ continue; ++ + /* update from encap rule to slow path rule */ + spec = &flow->attr->parse_attr->spec; + rule = mlx5e_tc_offload_to_slow_path(esw, flow, spec); +diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en/tc_tun_geneve.c b/drivers/net/ethernet/mellanox/mlx5/core/en/tc_tun_geneve.c +index f5b26f5a7de46..054d80c4e65cf 100644 +--- a/drivers/net/ethernet/mellanox/mlx5/core/en/tc_tun_geneve.c ++++ b/drivers/net/ethernet/mellanox/mlx5/core/en/tc_tun_geneve.c +@@ -273,6 +273,11 @@ static int mlx5e_tc_tun_parse_geneve_options(struct mlx5e_priv *priv, + geneve_tlv_option_0_data, be32_to_cpu(opt_data_key)); + MLX5_SET(fte_match_set_misc3, misc_3_c, + geneve_tlv_option_0_data, be32_to_cpu(opt_data_mask)); ++ if (MLX5_CAP_ESW_FLOWTABLE_FDB(priv->mdev, ++ ft_field_support.geneve_tlv_option_0_exist)) { ++ MLX5_SET_TO_ONES(fte_match_set_misc, misc_c, geneve_tlv_option_0_exist); ++ MLX5_SET_TO_ONES(fte_match_set_misc, misc_v, geneve_tlv_option_0_exist); ++ } + + spec->match_criteria_enable |= MLX5_MATCH_MISC_PARAMETERS_3; + +diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en_main.c b/drivers/net/ethernet/mellanox/mlx5/core/en_main.c +index 6cf6a81775a85..5c16efb8be81d 100644 +--- a/drivers/net/ethernet/mellanox/mlx5/core/en_main.c ++++ b/drivers/net/ethernet/mellanox/mlx5/core/en_main.c +@@ -1146,7 +1146,7 @@ static int mlx5e_alloc_xdpsq(struct mlx5e_channel *c, + sq->channel = c; + sq->uar_map = mdev->mlx5e_res.hw_objs.bfreg.map; + sq->min_inline_mode = params->tx_min_inline_mode; +- sq->hw_mtu = MLX5E_SW2HW_MTU(params, params->sw_mtu); ++ sq->hw_mtu = MLX5E_SW2HW_MTU(params, params->sw_mtu) - ETH_FCS_LEN; + sq->xsk_pool = xsk_pool; + + sq->stats = sq->xsk_pool ? +diff --git a/drivers/net/ethernet/mellanox/mlx5/core/esw/acl/egress_lgcy.c b/drivers/net/ethernet/mellanox/mlx5/core/esw/acl/egress_lgcy.c +index 60a73990017c2..6b4c9ffad95b2 100644 +--- a/drivers/net/ethernet/mellanox/mlx5/core/esw/acl/egress_lgcy.c ++++ b/drivers/net/ethernet/mellanox/mlx5/core/esw/acl/egress_lgcy.c +@@ -67,6 +67,7 @@ static void esw_acl_egress_lgcy_groups_destroy(struct mlx5_vport *vport) + int esw_acl_egress_lgcy_setup(struct mlx5_eswitch *esw, + struct mlx5_vport *vport) + { ++ bool vst_mode_steering = esw_vst_mode_is_steering(esw); + struct mlx5_flow_destination drop_ctr_dst = {}; + struct mlx5_flow_destination *dst = NULL; + struct mlx5_fc *drop_counter = NULL; +@@ -77,6 +78,7 @@ int esw_acl_egress_lgcy_setup(struct mlx5_eswitch *esw, + */ + int table_size = 2; + int dest_num = 0; ++ int actions_flag; + int err = 0; + + if (vport->egress.legacy.drop_counter) { +@@ -119,8 +121,11 @@ int esw_acl_egress_lgcy_setup(struct mlx5_eswitch *esw, + vport->vport, vport->info.vlan, vport->info.qos); + + /* Allowed vlan rule */ ++ actions_flag = MLX5_FLOW_CONTEXT_ACTION_ALLOW; ++ if (vst_mode_steering) ++ actions_flag |= MLX5_FLOW_CONTEXT_ACTION_VLAN_POP; + err = esw_egress_acl_vlan_create(esw, vport, NULL, vport->info.vlan, +- MLX5_FLOW_CONTEXT_ACTION_ALLOW); ++ actions_flag); + if (err) + goto out; + +diff --git a/drivers/net/ethernet/mellanox/mlx5/core/esw/acl/ingress_lgcy.c b/drivers/net/ethernet/mellanox/mlx5/core/esw/acl/ingress_lgcy.c +index b1a5199260f69..093ed86a0acd8 100644 +--- a/drivers/net/ethernet/mellanox/mlx5/core/esw/acl/ingress_lgcy.c ++++ b/drivers/net/ethernet/mellanox/mlx5/core/esw/acl/ingress_lgcy.c +@@ -139,11 +139,14 @@ static void esw_acl_ingress_lgcy_groups_destroy(struct mlx5_vport *vport) + int esw_acl_ingress_lgcy_setup(struct mlx5_eswitch *esw, + struct mlx5_vport *vport) + { ++ bool vst_mode_steering = esw_vst_mode_is_steering(esw); + struct mlx5_flow_destination drop_ctr_dst = {}; + struct mlx5_flow_destination *dst = NULL; + struct mlx5_flow_act flow_act = {}; + struct mlx5_flow_spec *spec = NULL; + struct mlx5_fc *counter = NULL; ++ bool vst_check_cvlan = false; ++ bool vst_push_cvlan = false; + /* The ingress acl table contains 4 groups + * (2 active rules at the same time - + * 1 allow rule from one of the first 3 groups. +@@ -203,7 +206,26 @@ int esw_acl_ingress_lgcy_setup(struct mlx5_eswitch *esw, + goto out; + } + +- if (vport->info.vlan || vport->info.qos) ++ if ((vport->info.vlan || vport->info.qos)) { ++ if (vst_mode_steering) ++ vst_push_cvlan = true; ++ else if (!MLX5_CAP_ESW(esw->dev, vport_cvlan_insert_always)) ++ vst_check_cvlan = true; ++ } ++ ++ if (vst_check_cvlan || vport->info.spoofchk) ++ spec->match_criteria_enable = MLX5_MATCH_OUTER_HEADERS; ++ ++ /* Create ingress allow rule */ ++ flow_act.action = MLX5_FLOW_CONTEXT_ACTION_ALLOW; ++ if (vst_push_cvlan) { ++ flow_act.action |= MLX5_FLOW_CONTEXT_ACTION_VLAN_PUSH; ++ flow_act.vlan[0].prio = vport->info.qos; ++ flow_act.vlan[0].vid = vport->info.vlan; ++ flow_act.vlan[0].ethtype = ETH_P_8021Q; ++ } ++ ++ if (vst_check_cvlan) + MLX5_SET_TO_ONES(fte_match_param, spec->match_criteria, + outer_headers.cvlan_tag); + +@@ -218,9 +240,6 @@ int esw_acl_ingress_lgcy_setup(struct mlx5_eswitch *esw, + ether_addr_copy(smac_v, vport->info.mac); + } + +- /* Create ingress allow rule */ +- spec->match_criteria_enable = MLX5_MATCH_OUTER_HEADERS; +- flow_act.action = MLX5_FLOW_CONTEXT_ACTION_ALLOW; + vport->ingress.allow_rule = mlx5_add_flow_rules(vport->ingress.acl, spec, + &flow_act, NULL, 0); + if (IS_ERR(vport->ingress.allow_rule)) { +@@ -232,6 +251,9 @@ int esw_acl_ingress_lgcy_setup(struct mlx5_eswitch *esw, + goto out; + } + ++ if (!vst_check_cvlan && !vport->info.spoofchk) ++ goto out; ++ + memset(&flow_act, 0, sizeof(flow_act)); + flow_act.action = MLX5_FLOW_CONTEXT_ACTION_DROP; + /* Attach drop flow counter */ +@@ -257,7 +279,8 @@ int esw_acl_ingress_lgcy_setup(struct mlx5_eswitch *esw, + return 0; + + out: +- esw_acl_ingress_lgcy_cleanup(esw, vport); ++ if (err) ++ esw_acl_ingress_lgcy_cleanup(esw, vport); + kvfree(spec); + return err; + } +diff --git a/drivers/net/ethernet/mellanox/mlx5/core/eswitch.c b/drivers/net/ethernet/mellanox/mlx5/core/eswitch.c +index 59cffa49e4b58..940e893f3f097 100644 +--- a/drivers/net/ethernet/mellanox/mlx5/core/eswitch.c ++++ b/drivers/net/ethernet/mellanox/mlx5/core/eswitch.c +@@ -161,10 +161,17 @@ static int modify_esw_vport_cvlan(struct mlx5_core_dev *dev, u16 vport, + esw_vport_context.vport_cvlan_strip, 1); + + if (set_flags & SET_VLAN_INSERT) { +- /* insert only if no vlan in packet */ +- MLX5_SET(modify_esw_vport_context_in, in, +- esw_vport_context.vport_cvlan_insert, 1); +- ++ if (MLX5_CAP_ESW(dev, vport_cvlan_insert_always)) { ++ /* insert either if vlan exist in packet or not */ ++ MLX5_SET(modify_esw_vport_context_in, in, ++ esw_vport_context.vport_cvlan_insert, ++ MLX5_VPORT_CVLAN_INSERT_ALWAYS); ++ } else { ++ /* insert only if no vlan in packet */ ++ MLX5_SET(modify_esw_vport_context_in, in, ++ esw_vport_context.vport_cvlan_insert, ++ MLX5_VPORT_CVLAN_INSERT_WHEN_NO_CVLAN); ++ } + MLX5_SET(modify_esw_vport_context_in, in, + esw_vport_context.cvlan_pcp, qos); + MLX5_SET(modify_esw_vport_context_in, in, +@@ -774,6 +781,7 @@ static void esw_vport_cleanup_acl(struct mlx5_eswitch *esw, + + static int esw_vport_setup(struct mlx5_eswitch *esw, struct mlx5_vport *vport) + { ++ bool vst_mode_steering = esw_vst_mode_is_steering(esw); + u16 vport_num = vport->vport; + int flags; + int err; +@@ -800,8 +808,9 @@ static int esw_vport_setup(struct mlx5_eswitch *esw, struct mlx5_vport *vport) + + flags = (vport->info.vlan || vport->info.qos) ? + SET_VLAN_STRIP | SET_VLAN_INSERT : 0; +- modify_esw_vport_cvlan(esw->dev, vport_num, vport->info.vlan, +- vport->info.qos, flags); ++ if (esw->mode == MLX5_ESWITCH_OFFLOADS || !vst_mode_steering) ++ modify_esw_vport_cvlan(esw->dev, vport_num, vport->info.vlan, ++ vport->info.qos, flags); + + return 0; + } +@@ -1806,6 +1815,7 @@ int __mlx5_eswitch_set_vport_vlan(struct mlx5_eswitch *esw, + u16 vport, u16 vlan, u8 qos, u8 set_flags) + { + struct mlx5_vport *evport = mlx5_eswitch_get_vport(esw, vport); ++ bool vst_mode_steering = esw_vst_mode_is_steering(esw); + int err = 0; + + if (IS_ERR(evport)) +@@ -1813,9 +1823,11 @@ int __mlx5_eswitch_set_vport_vlan(struct mlx5_eswitch *esw, + if (vlan > 4095 || qos > 7) + return -EINVAL; + +- err = modify_esw_vport_cvlan(esw->dev, vport, vlan, qos, set_flags); +- if (err) +- return err; ++ if (esw->mode == MLX5_ESWITCH_OFFLOADS || !vst_mode_steering) { ++ err = modify_esw_vport_cvlan(esw->dev, vport, vlan, qos, set_flags); ++ if (err) ++ return err; ++ } + + evport->info.vlan = vlan; + evport->info.qos = qos; +diff --git a/drivers/net/ethernet/mellanox/mlx5/core/eswitch.h b/drivers/net/ethernet/mellanox/mlx5/core/eswitch.h +index 5ceed4e6c6581..03080e8161cba 100644 +--- a/drivers/net/ethernet/mellanox/mlx5/core/eswitch.h ++++ b/drivers/net/ethernet/mellanox/mlx5/core/eswitch.h +@@ -513,6 +513,12 @@ int mlx5_eswitch_del_vlan_action(struct mlx5_eswitch *esw, + int __mlx5_eswitch_set_vport_vlan(struct mlx5_eswitch *esw, + u16 vport, u16 vlan, u8 qos, u8 set_flags); + ++static inline bool esw_vst_mode_is_steering(struct mlx5_eswitch *esw) ++{ ++ return (MLX5_CAP_ESW_EGRESS_ACL(esw->dev, pop_vlan) && ++ MLX5_CAP_ESW_INGRESS_ACL(esw->dev, push_vlan)); ++} ++ + static inline bool mlx5_eswitch_vlan_actions_supported(struct mlx5_core_dev *dev, + u8 vlan_depth) + { +diff --git a/drivers/net/ethernet/mellanox/mlx5/core/health.c b/drivers/net/ethernet/mellanox/mlx5/core/health.c +index 2cf2c99484467..0ed239eadf394 100644 +--- a/drivers/net/ethernet/mellanox/mlx5/core/health.c ++++ b/drivers/net/ethernet/mellanox/mlx5/core/health.c +@@ -674,6 +674,12 @@ static void mlx5_fw_fatal_reporter_err_work(struct work_struct *work) + dev = container_of(priv, struct mlx5_core_dev, priv); + devlink = priv_to_devlink(dev); + ++ mutex_lock(&dev->intf_state_mutex); ++ if (test_bit(MLX5_DROP_NEW_HEALTH_WORK, &health->flags)) { ++ mlx5_core_err(dev, "health works are not permitted at this stage\n"); ++ return; ++ } ++ mutex_unlock(&dev->intf_state_mutex); + enter_error_state(dev, false); + if (IS_ERR_OR_NULL(health->fw_fatal_reporter)) { + devl_lock(devlink); +diff --git a/drivers/net/ethernet/mellanox/mlx5/core/ipoib/ipoib.c b/drivers/net/ethernet/mellanox/mlx5/core/ipoib/ipoib.c +index c02b7b08fb4c1..2032d5c0ad86a 100644 +--- a/drivers/net/ethernet/mellanox/mlx5/core/ipoib/ipoib.c ++++ b/drivers/net/ethernet/mellanox/mlx5/core/ipoib/ipoib.c +@@ -70,6 +70,10 @@ static void mlx5i_build_nic_params(struct mlx5_core_dev *mdev, + params->packet_merge.type = MLX5E_PACKET_MERGE_NONE; + params->hard_mtu = MLX5_IB_GRH_BYTES + MLX5_IPOIB_HARD_LEN; + params->tunneled_offload_en = false; ++ ++ /* CQE compression is not supported for IPoIB */ ++ params->rx_cqe_compress_def = false; ++ MLX5E_SET_PFLAG(params, MLX5E_PFLAG_RX_CQE_COMPRESS, params->rx_cqe_compress_def); + } + + /* Called directly after IPoIB netdevice was created to initialize SW structs */ +diff --git a/drivers/net/ethernet/mellanox/mlx5/core/lag/lag.c b/drivers/net/ethernet/mellanox/mlx5/core/lag/lag.c +index bbe810f3b373a..c142011d20977 100644 +--- a/drivers/net/ethernet/mellanox/mlx5/core/lag/lag.c ++++ b/drivers/net/ethernet/mellanox/mlx5/core/lag/lag.c +@@ -201,6 +201,7 @@ static void mlx5_ldev_free(struct kref *ref) + if (ldev->nb.notifier_call) + unregister_netdevice_notifier_net(&init_net, &ldev->nb); + mlx5_lag_mp_cleanup(ldev); ++ cancel_delayed_work_sync(&ldev->bond_work); + destroy_workqueue(ldev->wq); + mlx5_lag_mpesw_cleanup(ldev); + mutex_destroy(&ldev->lock); +diff --git a/drivers/net/ethernet/mellanox/mlx5/core/main.c b/drivers/net/ethernet/mellanox/mlx5/core/main.c +index ac178796e484f..0a2f23a7082a8 100644 +--- a/drivers/net/ethernet/mellanox/mlx5/core/main.c ++++ b/drivers/net/ethernet/mellanox/mlx5/core/main.c +@@ -614,7 +614,7 @@ static int handle_hca_cap(struct mlx5_core_dev *dev, void *set_ctx) + MLX5_SET(cmd_hca_cap, set_hca_cap, num_total_dynamic_vf_msix, + MLX5_CAP_GEN_MAX(dev, num_total_dynamic_vf_msix)); + +- if (MLX5_CAP_GEN(dev, roce_rw_supported)) ++ if (MLX5_CAP_GEN(dev, roce_rw_supported) && MLX5_CAP_GEN_MAX(dev, roce)) + MLX5_SET(cmd_hca_cap, set_hca_cap, roce, + mlx5_is_roce_on(dev)); + +@@ -1017,6 +1017,8 @@ err_rl_cleanup: + err_tables_cleanup: + mlx5_geneve_destroy(dev->geneve); + mlx5_vxlan_destroy(dev->vxlan); ++ mlx5_cleanup_clock(dev); ++ mlx5_cleanup_reserved_gids(dev); + mlx5_cq_debugfs_cleanup(dev); + mlx5_fw_reset_cleanup(dev); + err_events_cleanup: +diff --git a/drivers/net/ethernet/microchip/lan966x/lan966x_port.c b/drivers/net/ethernet/microchip/lan966x/lan966x_port.c +index f141644e4372f..26c5cdf373c4d 100644 +--- a/drivers/net/ethernet/microchip/lan966x/lan966x_port.c ++++ b/drivers/net/ethernet/microchip/lan966x/lan966x_port.c +@@ -369,7 +369,7 @@ int lan966x_port_pcs_set(struct lan966x_port *port, + } + + /* Take PCS out of reset */ +- lan_rmw(DEV_CLOCK_CFG_LINK_SPEED_SET(2) | ++ lan_rmw(DEV_CLOCK_CFG_LINK_SPEED_SET(LAN966X_SPEED_1000) | + DEV_CLOCK_CFG_PCS_RX_RST_SET(0) | + DEV_CLOCK_CFG_PCS_TX_RST_SET(0), + DEV_CLOCK_CFG_LINK_SPEED | +diff --git a/drivers/net/ethernet/microchip/sparx5/sparx5_main.c b/drivers/net/ethernet/microchip/sparx5/sparx5_main.c +index e58de119186a6..a2d0631f7ac71 100644 +--- a/drivers/net/ethernet/microchip/sparx5/sparx5_main.c ++++ b/drivers/net/ethernet/microchip/sparx5/sparx5_main.c +@@ -819,7 +819,7 @@ static int mchp_sparx5_probe(struct platform_device *pdev) + if (err) + goto cleanup_config; + +- if (!of_get_mac_address(np, sparx5->base_mac)) { ++ if (of_get_mac_address(np, sparx5->base_mac)) { + dev_info(sparx5->dev, "MAC addr was not set, use random MAC\n"); + eth_random_addr(sparx5->base_mac); + sparx5->base_mac[5] = 0; +diff --git a/drivers/net/ethernet/qlogic/qed/qed_debug.c b/drivers/net/ethernet/qlogic/qed/qed_debug.c +index 86ecb080b1536..cdcead614e9fa 100644 +--- a/drivers/net/ethernet/qlogic/qed/qed_debug.c ++++ b/drivers/net/ethernet/qlogic/qed/qed_debug.c +@@ -1832,7 +1832,8 @@ static enum dbg_status qed_find_nvram_image(struct qed_hwfn *p_hwfn, + struct qed_ptt *p_ptt, + u32 image_type, + u32 *nvram_offset_bytes, +- u32 *nvram_size_bytes) ++ u32 *nvram_size_bytes, ++ bool b_can_sleep) + { + u32 ret_mcp_resp, ret_mcp_param, ret_txn_size; + struct mcp_file_att file_att; +@@ -1846,7 +1847,8 @@ static enum dbg_status qed_find_nvram_image(struct qed_hwfn *p_hwfn, + &ret_mcp_resp, + &ret_mcp_param, + &ret_txn_size, +- (u32 *)&file_att, false); ++ (u32 *)&file_att, ++ b_can_sleep); + + /* Check response */ + if (nvm_result || (ret_mcp_resp & FW_MSG_CODE_MASK) != +@@ -1873,7 +1875,9 @@ static enum dbg_status qed_find_nvram_image(struct qed_hwfn *p_hwfn, + static enum dbg_status qed_nvram_read(struct qed_hwfn *p_hwfn, + struct qed_ptt *p_ptt, + u32 nvram_offset_bytes, +- u32 nvram_size_bytes, u32 *ret_buf) ++ u32 nvram_size_bytes, ++ u32 *ret_buf, ++ bool b_can_sleep) + { + u32 ret_mcp_resp, ret_mcp_param, ret_read_size, bytes_to_copy; + s32 bytes_left = nvram_size_bytes; +@@ -1899,7 +1903,7 @@ static enum dbg_status qed_nvram_read(struct qed_hwfn *p_hwfn, + &ret_mcp_resp, + &ret_mcp_param, &ret_read_size, + (u32 *)((u8 *)ret_buf + read_offset), +- false)) ++ b_can_sleep)) + return DBG_STATUS_NVRAM_READ_FAILED; + + /* Check response */ +@@ -3380,7 +3384,8 @@ static u32 qed_grc_dump_mcp_hw_dump(struct qed_hwfn *p_hwfn, + p_ptt, + NVM_TYPE_HW_DUMP_OUT, + &hw_dump_offset_bytes, +- &hw_dump_size_bytes); ++ &hw_dump_size_bytes, ++ false); + if (status != DBG_STATUS_OK) + return 0; + +@@ -3397,7 +3402,9 @@ static u32 qed_grc_dump_mcp_hw_dump(struct qed_hwfn *p_hwfn, + status = qed_nvram_read(p_hwfn, + p_ptt, + hw_dump_offset_bytes, +- hw_dump_size_bytes, dump_buf + offset); ++ hw_dump_size_bytes, ++ dump_buf + offset, ++ false); + if (status != DBG_STATUS_OK) { + DP_NOTICE(p_hwfn, + "Failed to read MCP HW Dump image from NVRAM\n"); +@@ -4123,7 +4130,9 @@ static enum dbg_status qed_mcp_trace_get_meta_info(struct qed_hwfn *p_hwfn, + return qed_find_nvram_image(p_hwfn, + p_ptt, + nvram_image_type, +- trace_meta_offset, trace_meta_size); ++ trace_meta_offset, ++ trace_meta_size, ++ true); + } + + /* Reads the MCP Trace meta data from NVRAM into the specified buffer */ +@@ -4139,7 +4148,10 @@ static enum dbg_status qed_mcp_trace_read_meta(struct qed_hwfn *p_hwfn, + /* Read meta data from NVRAM */ + status = qed_nvram_read(p_hwfn, + p_ptt, +- nvram_offset_in_bytes, size_in_bytes, buf); ++ nvram_offset_in_bytes, ++ size_in_bytes, ++ buf, ++ true); + if (status != DBG_STATUS_OK) + return status; + +diff --git a/drivers/net/ethernet/qlogic/qlcnic/qlcnic_83xx_init.c b/drivers/net/ethernet/qlogic/qlcnic/qlcnic_83xx_init.c +index dbb800769cb63..c95d56e56c59a 100644 +--- a/drivers/net/ethernet/qlogic/qlcnic/qlcnic_83xx_init.c ++++ b/drivers/net/ethernet/qlogic/qlcnic/qlcnic_83xx_init.c +@@ -2505,7 +2505,13 @@ int qlcnic_83xx_init(struct qlcnic_adapter *adapter) + goto disable_mbx_intr; + + qlcnic_83xx_clear_function_resources(adapter); +- qlcnic_dcb_enable(adapter->dcb); ++ ++ err = qlcnic_dcb_enable(adapter->dcb); ++ if (err) { ++ qlcnic_dcb_free(adapter->dcb); ++ goto disable_mbx_intr; ++ } ++ + qlcnic_83xx_initialize_nic(adapter, 1); + qlcnic_dcb_get_info(adapter->dcb); + +diff --git a/drivers/net/ethernet/qlogic/qlcnic/qlcnic_dcb.h b/drivers/net/ethernet/qlogic/qlcnic/qlcnic_dcb.h +index 7519773eaca6e..22afa2be85fdb 100644 +--- a/drivers/net/ethernet/qlogic/qlcnic/qlcnic_dcb.h ++++ b/drivers/net/ethernet/qlogic/qlcnic/qlcnic_dcb.h +@@ -41,11 +41,6 @@ struct qlcnic_dcb { + unsigned long state; + }; + +-static inline void qlcnic_clear_dcb_ops(struct qlcnic_dcb *dcb) +-{ +- kfree(dcb); +-} +- + static inline int qlcnic_dcb_get_hw_capability(struct qlcnic_dcb *dcb) + { + if (dcb && dcb->ops->get_hw_capability) +@@ -112,9 +107,8 @@ static inline void qlcnic_dcb_init_dcbnl_ops(struct qlcnic_dcb *dcb) + dcb->ops->init_dcbnl_ops(dcb); + } + +-static inline void qlcnic_dcb_enable(struct qlcnic_dcb *dcb) ++static inline int qlcnic_dcb_enable(struct qlcnic_dcb *dcb) + { +- if (dcb && qlcnic_dcb_attach(dcb)) +- qlcnic_clear_dcb_ops(dcb); ++ return dcb ? qlcnic_dcb_attach(dcb) : 0; + } + #endif +diff --git a/drivers/net/ethernet/qlogic/qlcnic/qlcnic_main.c b/drivers/net/ethernet/qlogic/qlcnic/qlcnic_main.c +index 28476b982bab6..44dac3c0908eb 100644 +--- a/drivers/net/ethernet/qlogic/qlcnic/qlcnic_main.c ++++ b/drivers/net/ethernet/qlogic/qlcnic/qlcnic_main.c +@@ -2599,7 +2599,13 @@ qlcnic_probe(struct pci_dev *pdev, const struct pci_device_id *ent) + "Device does not support MSI interrupts\n"); + + if (qlcnic_82xx_check(adapter)) { +- qlcnic_dcb_enable(adapter->dcb); ++ err = qlcnic_dcb_enable(adapter->dcb); ++ if (err) { ++ qlcnic_dcb_free(adapter->dcb); ++ dev_err(&pdev->dev, "Failed to enable DCB\n"); ++ goto err_out_free_hw; ++ } ++ + qlcnic_dcb_get_info(adapter->dcb); + err = qlcnic_setup_intr(adapter); + +diff --git a/drivers/net/phy/xilinx_gmii2rgmii.c b/drivers/net/phy/xilinx_gmii2rgmii.c +index 8dcb49ed1f3d9..7fd9fe6a602bc 100644 +--- a/drivers/net/phy/xilinx_gmii2rgmii.c ++++ b/drivers/net/phy/xilinx_gmii2rgmii.c +@@ -105,6 +105,7 @@ static int xgmiitorgmii_probe(struct mdio_device *mdiodev) + + if (!priv->phy_dev->drv) { + dev_info(dev, "Attached phy not ready\n"); ++ put_device(&priv->phy_dev->mdio.dev); + return -EPROBE_DEFER; + } + +diff --git a/drivers/net/usb/rndis_host.c b/drivers/net/usb/rndis_host.c +index f79333fe17836..7b3739b29c8f7 100644 +--- a/drivers/net/usb/rndis_host.c ++++ b/drivers/net/usb/rndis_host.c +@@ -255,7 +255,8 @@ static int rndis_query(struct usbnet *dev, struct usb_interface *intf, + + off = le32_to_cpu(u.get_c->offset); + len = le32_to_cpu(u.get_c->len); +- if (unlikely((8 + off + len) > CONTROL_BUFFER_SIZE)) ++ if (unlikely((off > CONTROL_BUFFER_SIZE - 8) || ++ (len > CONTROL_BUFFER_SIZE - 8 - off))) + goto response_error; + + if (*reply_len != -1 && len != *reply_len) +diff --git a/drivers/net/veth.c b/drivers/net/veth.c +index 466da01ba2e3e..909427d99a594 100644 +--- a/drivers/net/veth.c ++++ b/drivers/net/veth.c +@@ -974,6 +974,9 @@ static int veth_poll(struct napi_struct *napi, int budget) + xdp_set_return_frame_no_direct(); + done = veth_xdp_rcv(rq, budget, &bq, &stats); + ++ if (stats.xdp_redirect > 0) ++ xdp_do_flush(); ++ + if (done < budget && napi_complete_done(napi, done)) { + /* Write rx_notify_masked before reading ptr_ring */ + smp_store_mb(rq->rx_notify_masked, false); +@@ -987,8 +990,6 @@ static int veth_poll(struct napi_struct *napi, int budget) + + if (stats.xdp_tx > 0) + veth_xdp_flush(rq, &bq); +- if (stats.xdp_redirect > 0) +- xdp_do_flush(); + xdp_clear_return_frame_no_direct(); + + return done; +diff --git a/drivers/net/vmxnet3/vmxnet3_drv.c b/drivers/net/vmxnet3/vmxnet3_drv.c +index c28c4a654615c..c312d16f580c9 100644 +--- a/drivers/net/vmxnet3/vmxnet3_drv.c ++++ b/drivers/net/vmxnet3/vmxnet3_drv.c +@@ -1288,6 +1288,10 @@ vmxnet3_rx_csum(struct vmxnet3_adapter *adapter, + (le32_to_cpu(gdesc->dword[3]) & + VMXNET3_RCD_CSUM_OK) == VMXNET3_RCD_CSUM_OK) { + skb->ip_summed = CHECKSUM_UNNECESSARY; ++ if ((le32_to_cpu(gdesc->dword[0]) & ++ (1UL << VMXNET3_RCD_HDR_INNER_SHIFT))) { ++ skb->csum_level = 1; ++ } + WARN_ON_ONCE(!(gdesc->rcd.tcp || gdesc->rcd.udp) && + !(le32_to_cpu(gdesc->dword[0]) & + (1UL << VMXNET3_RCD_HDR_INNER_SHIFT))); +@@ -1297,6 +1301,10 @@ vmxnet3_rx_csum(struct vmxnet3_adapter *adapter, + } else if (gdesc->rcd.v6 && (le32_to_cpu(gdesc->dword[3]) & + (1 << VMXNET3_RCD_TUC_SHIFT))) { + skb->ip_summed = CHECKSUM_UNNECESSARY; ++ if ((le32_to_cpu(gdesc->dword[0]) & ++ (1UL << VMXNET3_RCD_HDR_INNER_SHIFT))) { ++ skb->csum_level = 1; ++ } + WARN_ON_ONCE(!(gdesc->rcd.tcp || gdesc->rcd.udp) && + !(le32_to_cpu(gdesc->dword[0]) & + (1UL << VMXNET3_RCD_HDR_INNER_SHIFT))); +diff --git a/drivers/net/vrf.c b/drivers/net/vrf.c +index 5df7a0abc39d5..f7f40e3fe9cce 100644 +--- a/drivers/net/vrf.c ++++ b/drivers/net/vrf.c +@@ -1385,8 +1385,8 @@ static struct sk_buff *vrf_ip6_rcv(struct net_device *vrf_dev, + + /* loopback, multicast & non-ND link-local traffic; do not push through + * packet taps again. Reset pkt_type for upper layers to process skb. +- * For strict packets with a source LLA, determine the dst using the +- * original ifindex. ++ * For non-loopback strict packets, determine the dst using the original ++ * ifindex. + */ + if (skb->pkt_type == PACKET_LOOPBACK || (need_strict && !is_ndisc)) { + skb->dev = vrf_dev; +@@ -1395,7 +1395,7 @@ static struct sk_buff *vrf_ip6_rcv(struct net_device *vrf_dev, + + if (skb->pkt_type == PACKET_LOOPBACK) + skb->pkt_type = PACKET_HOST; +- else if (ipv6_addr_type(&ipv6_hdr(skb)->saddr) & IPV6_ADDR_LINKLOCAL) ++ else + vrf_ip6_input_dst(skb, vrf_dev, orig_iif); + + goto out; +diff --git a/drivers/net/vxlan/vxlan_core.c b/drivers/net/vxlan/vxlan_core.c +index c3285242f74fb..a03752ef544f4 100644 +--- a/drivers/net/vxlan/vxlan_core.c ++++ b/drivers/net/vxlan/vxlan_core.c +@@ -2920,16 +2920,23 @@ static int vxlan_init(struct net_device *dev) + vxlan_vnigroup_init(vxlan); + + dev->tstats = netdev_alloc_pcpu_stats(struct pcpu_sw_netstats); +- if (!dev->tstats) +- return -ENOMEM; ++ if (!dev->tstats) { ++ err = -ENOMEM; ++ goto err_vnigroup_uninit; ++ } + + err = gro_cells_init(&vxlan->gro_cells, dev); +- if (err) { +- free_percpu(dev->tstats); +- return err; +- } ++ if (err) ++ goto err_free_percpu; + + return 0; ++ ++err_free_percpu: ++ free_percpu(dev->tstats); ++err_vnigroup_uninit: ++ if (vxlan->cfg.flags & VXLAN_F_VNIFILTER) ++ vxlan_vnigroup_uninit(vxlan); ++ return err; + } + + static void vxlan_fdb_delete_default(struct vxlan_dev *vxlan, __be32 vni) +diff --git a/drivers/net/wireless/ath/ath9k/htc.h b/drivers/net/wireless/ath/ath9k/htc.h +index 30f0765fb9fd8..237f4ec2cffd7 100644 +--- a/drivers/net/wireless/ath/ath9k/htc.h ++++ b/drivers/net/wireless/ath/ath9k/htc.h +@@ -327,9 +327,9 @@ static inline struct ath9k_htc_tx_ctl *HTC_SKB_CB(struct sk_buff *skb) + } + + #ifdef CONFIG_ATH9K_HTC_DEBUGFS +-#define __STAT_SAFE(hif_dev, expr) ((hif_dev)->htc_handle->drv_priv ? (expr) : 0) +-#define CAB_STAT_INC(priv) ((priv)->debug.tx_stats.cab_queued++) +-#define TX_QSTAT_INC(priv, q) ((priv)->debug.tx_stats.queue_stats[q]++) ++#define __STAT_SAFE(hif_dev, expr) do { ((hif_dev)->htc_handle->drv_priv ? (expr) : 0); } while (0) ++#define CAB_STAT_INC(priv) do { ((priv)->debug.tx_stats.cab_queued++); } while (0) ++#define TX_QSTAT_INC(priv, q) do { ((priv)->debug.tx_stats.queue_stats[q]++); } while (0) + + #define TX_STAT_INC(hif_dev, c) \ + __STAT_SAFE((hif_dev), (hif_dev)->htc_handle->drv_priv->debug.tx_stats.c++) +@@ -378,10 +378,10 @@ void ath9k_htc_get_et_stats(struct ieee80211_hw *hw, + struct ethtool_stats *stats, u64 *data); + #else + +-#define TX_STAT_INC(hif_dev, c) +-#define TX_STAT_ADD(hif_dev, c, a) +-#define RX_STAT_INC(hif_dev, c) +-#define RX_STAT_ADD(hif_dev, c, a) ++#define TX_STAT_INC(hif_dev, c) do { } while (0) ++#define TX_STAT_ADD(hif_dev, c, a) do { } while (0) ++#define RX_STAT_INC(hif_dev, c) do { } while (0) ++#define RX_STAT_ADD(hif_dev, c, a) do { } while (0) + + #define CAB_STAT_INC(priv) + #define TX_QSTAT_INC(priv, c) +diff --git a/drivers/nvme/host/core.c b/drivers/nvme/host/core.c +index 3582a28a1dcec..f06bae83e8ee0 100644 +--- a/drivers/nvme/host/core.c ++++ b/drivers/nvme/host/core.c +@@ -1069,6 +1069,18 @@ static u32 nvme_known_admin_effects(u8 opcode) + return 0; + } + ++static u32 nvme_known_nvm_effects(u8 opcode) ++{ ++ switch (opcode) { ++ case nvme_cmd_write: ++ case nvme_cmd_write_zeroes: ++ case nvme_cmd_write_uncor: ++ return NVME_CMD_EFFECTS_LBCC; ++ default: ++ return 0; ++ } ++} ++ + u32 nvme_command_effects(struct nvme_ctrl *ctrl, struct nvme_ns *ns, u8 opcode) + { + u32 effects = 0; +@@ -1076,16 +1088,24 @@ u32 nvme_command_effects(struct nvme_ctrl *ctrl, struct nvme_ns *ns, u8 opcode) + if (ns) { + if (ns->head->effects) + effects = le32_to_cpu(ns->head->effects->iocs[opcode]); ++ if (ns->head->ids.csi == NVME_CAP_CSS_NVM) ++ effects |= nvme_known_nvm_effects(opcode); + if (effects & ~(NVME_CMD_EFFECTS_CSUPP | NVME_CMD_EFFECTS_LBCC)) + dev_warn_once(ctrl->device, +- "IO command:%02x has unhandled effects:%08x\n", ++ "IO command:%02x has unusual effects:%08x\n", + opcode, effects); +- return 0; +- } + +- if (ctrl->effects) +- effects = le32_to_cpu(ctrl->effects->acs[opcode]); +- effects |= nvme_known_admin_effects(opcode); ++ /* ++ * NVME_CMD_EFFECTS_CSE_MASK causes a freeze all I/O queues, ++ * which would deadlock when done on an I/O command. Note that ++ * We already warn about an unusual effect above. ++ */ ++ effects &= ~NVME_CMD_EFFECTS_CSE_MASK; ++ } else { ++ if (ctrl->effects) ++ effects = le32_to_cpu(ctrl->effects->acs[opcode]); ++ effects |= nvme_known_admin_effects(opcode); ++ } + + return effects; + } +diff --git a/drivers/nvme/host/nvme.h b/drivers/nvme/host/nvme.h +index 70555022cb445..35352206b5dee 100644 +--- a/drivers/nvme/host/nvme.h ++++ b/drivers/nvme/host/nvme.h +@@ -872,7 +872,7 @@ static inline void nvme_trace_bio_complete(struct request *req) + { + struct nvme_ns *ns = req->q->queuedata; + +- if (req->cmd_flags & REQ_NVME_MPATH) ++ if ((req->cmd_flags & REQ_NVME_MPATH) && req->bio) + trace_block_bio_complete(ns->head->disk->queue, req->bio); + } + +diff --git a/drivers/nvme/target/admin-cmd.c b/drivers/nvme/target/admin-cmd.c +index fc8a957fad0ac..4aaa27cc8d2bd 100644 +--- a/drivers/nvme/target/admin-cmd.c ++++ b/drivers/nvme/target/admin-cmd.c +@@ -164,26 +164,29 @@ out: + + static void nvmet_get_cmd_effects_nvm(struct nvme_effects_log *log) + { +- log->acs[nvme_admin_get_log_page] = cpu_to_le32(1 << 0); +- log->acs[nvme_admin_identify] = cpu_to_le32(1 << 0); +- log->acs[nvme_admin_abort_cmd] = cpu_to_le32(1 << 0); +- log->acs[nvme_admin_set_features] = cpu_to_le32(1 << 0); +- log->acs[nvme_admin_get_features] = cpu_to_le32(1 << 0); +- log->acs[nvme_admin_async_event] = cpu_to_le32(1 << 0); +- log->acs[nvme_admin_keep_alive] = cpu_to_le32(1 << 0); +- +- log->iocs[nvme_cmd_read] = cpu_to_le32(1 << 0); +- log->iocs[nvme_cmd_write] = cpu_to_le32(1 << 0); +- log->iocs[nvme_cmd_flush] = cpu_to_le32(1 << 0); +- log->iocs[nvme_cmd_dsm] = cpu_to_le32(1 << 0); +- log->iocs[nvme_cmd_write_zeroes] = cpu_to_le32(1 << 0); ++ log->acs[nvme_admin_get_log_page] = ++ log->acs[nvme_admin_identify] = ++ log->acs[nvme_admin_abort_cmd] = ++ log->acs[nvme_admin_set_features] = ++ log->acs[nvme_admin_get_features] = ++ log->acs[nvme_admin_async_event] = ++ log->acs[nvme_admin_keep_alive] = ++ cpu_to_le32(NVME_CMD_EFFECTS_CSUPP); ++ ++ log->iocs[nvme_cmd_read] = ++ log->iocs[nvme_cmd_write] = ++ log->iocs[nvme_cmd_flush] = ++ log->iocs[nvme_cmd_dsm] = ++ log->iocs[nvme_cmd_write_zeroes] = ++ cpu_to_le32(NVME_CMD_EFFECTS_CSUPP); + } + + static void nvmet_get_cmd_effects_zns(struct nvme_effects_log *log) + { +- log->iocs[nvme_cmd_zone_append] = cpu_to_le32(1 << 0); +- log->iocs[nvme_cmd_zone_mgmt_send] = cpu_to_le32(1 << 0); +- log->iocs[nvme_cmd_zone_mgmt_recv] = cpu_to_le32(1 << 0); ++ log->iocs[nvme_cmd_zone_append] = ++ log->iocs[nvme_cmd_zone_mgmt_send] = ++ log->iocs[nvme_cmd_zone_mgmt_recv] = ++ cpu_to_le32(NVME_CMD_EFFECTS_CSUPP); + } + + static void nvmet_execute_get_log_cmd_effects_ns(struct nvmet_req *req) +diff --git a/drivers/of/fdt.c b/drivers/of/fdt.c +index 1c573e7a60bc8..f4bfaf1669fb3 100644 +--- a/drivers/of/fdt.c ++++ b/drivers/of/fdt.c +@@ -1106,7 +1106,7 @@ u64 __init dt_mem_next_cell(int s, const __be32 **cellp) + */ + int __init early_init_dt_scan_memory(void) + { +- int node; ++ int node, found_memory = 0; + const void *fdt = initial_boot_params; + + fdt_for_each_subnode(node, fdt, 0) { +@@ -1146,6 +1146,8 @@ int __init early_init_dt_scan_memory(void) + + early_init_dt_add_memory_arch(base, size); + ++ found_memory = 1; ++ + if (!hotpluggable) + continue; + +@@ -1154,7 +1156,7 @@ int __init early_init_dt_scan_memory(void) + base, base + size); + } + } +- return 0; ++ return found_memory; + } + + int __init early_init_dt_scan_chosen(char *cmdline) +diff --git a/drivers/phy/qualcomm/phy-qcom-qmp-combo.c b/drivers/phy/qualcomm/phy-qcom-qmp-combo.c +index 0feda8eb93b52..5e011520650de 100644 +--- a/drivers/phy/qualcomm/phy-qcom-qmp-combo.c ++++ b/drivers/phy/qualcomm/phy-qcom-qmp-combo.c +@@ -767,6 +767,7 @@ struct qcom_qmp { + struct regulator_bulk_data *vregs; + + struct qmp_phy **phys; ++ struct qmp_phy *usb_phy; + + struct mutex phy_mutex; + int init_count; +@@ -1607,7 +1608,7 @@ static int qcom_qmp_phy_combo_com_init(struct qmp_phy *qphy) + { + struct qcom_qmp *qmp = qphy->qmp; + const struct qmp_phy_cfg *cfg = qphy->cfg; +- void __iomem *pcs = qphy->pcs; ++ struct qmp_phy *usb_phy = qmp->usb_phy; + void __iomem *dp_com = qmp->dp_com; + int ret; + +@@ -1663,13 +1664,13 @@ static int qcom_qmp_phy_combo_com_init(struct qmp_phy *qphy) + qphy_clrbits(dp_com, QPHY_V3_DP_COM_SW_RESET, SW_RESET); + } + +- if (cfg->regs[QPHY_PCS_POWER_DOWN_CONTROL]) +- qphy_setbits(pcs, +- cfg->regs[QPHY_PCS_POWER_DOWN_CONTROL], +- cfg->pwrdn_ctrl); ++ if (usb_phy->cfg->regs[QPHY_PCS_POWER_DOWN_CONTROL]) ++ qphy_setbits(usb_phy->pcs, ++ usb_phy->cfg->regs[QPHY_PCS_POWER_DOWN_CONTROL], ++ usb_phy->cfg->pwrdn_ctrl); + else +- qphy_setbits(pcs, QPHY_V2_PCS_POWER_DOWN_CONTROL, +- cfg->pwrdn_ctrl); ++ qphy_setbits(usb_phy->pcs, QPHY_V2_PCS_POWER_DOWN_CONTROL, ++ usb_phy->cfg->pwrdn_ctrl); + + mutex_unlock(&qmp->phy_mutex); + +@@ -2576,6 +2577,8 @@ static int qcom_qmp_phy_combo_probe(struct platform_device *pdev) + goto err_node_put; + } + ++ qmp->usb_phy = qmp->phys[id]; ++ + /* + * Register the pipe clock provided by phy. + * See function description to see details of this pipe clock. +@@ -2591,6 +2594,9 @@ static int qcom_qmp_phy_combo_probe(struct platform_device *pdev) + id++; + } + ++ if (!qmp->usb_phy) ++ return -EINVAL; ++ + phy_provider = devm_of_phy_provider_register(dev, of_phy_simple_xlate); + if (!IS_ERR(phy_provider)) + dev_info(dev, "Registered Qcom-QMP phy\n"); +diff --git a/drivers/thermal/intel/int340x_thermal/processor_thermal_rfim.c b/drivers/thermal/intel/int340x_thermal/processor_thermal_rfim.c +index 8c42e76620333..92ed1213fe379 100644 +--- a/drivers/thermal/intel/int340x_thermal/processor_thermal_rfim.c ++++ b/drivers/thermal/intel/int340x_thermal/processor_thermal_rfim.c +@@ -172,6 +172,7 @@ static const struct attribute_group fivr_attribute_group = { + RFIM_SHOW(rfi_restriction_run_busy, 1) + RFIM_SHOW(rfi_restriction_err_code, 1) + RFIM_SHOW(rfi_restriction_data_rate, 1) ++RFIM_SHOW(rfi_restriction_data_rate_base, 1) + RFIM_SHOW(ddr_data_rate_point_0, 1) + RFIM_SHOW(ddr_data_rate_point_1, 1) + RFIM_SHOW(ddr_data_rate_point_2, 1) +@@ -181,11 +182,13 @@ RFIM_SHOW(rfi_disable, 1) + RFIM_STORE(rfi_restriction_run_busy, 1) + RFIM_STORE(rfi_restriction_err_code, 1) + RFIM_STORE(rfi_restriction_data_rate, 1) ++RFIM_STORE(rfi_restriction_data_rate_base, 1) + RFIM_STORE(rfi_disable, 1) + + static DEVICE_ATTR_RW(rfi_restriction_run_busy); + static DEVICE_ATTR_RW(rfi_restriction_err_code); + static DEVICE_ATTR_RW(rfi_restriction_data_rate); ++static DEVICE_ATTR_RW(rfi_restriction_data_rate_base); + static DEVICE_ATTR_RO(ddr_data_rate_point_0); + static DEVICE_ATTR_RO(ddr_data_rate_point_1); + static DEVICE_ATTR_RO(ddr_data_rate_point_2); +@@ -248,6 +251,7 @@ static struct attribute *dvfs_attrs[] = { + &dev_attr_rfi_restriction_run_busy.attr, + &dev_attr_rfi_restriction_err_code.attr, + &dev_attr_rfi_restriction_data_rate.attr, ++ &dev_attr_rfi_restriction_data_rate_base.attr, + &dev_attr_ddr_data_rate_point_0.attr, + &dev_attr_ddr_data_rate_point_1.attr, + &dev_attr_ddr_data_rate_point_2.attr, +diff --git a/drivers/usb/dwc3/dwc3-xilinx.c b/drivers/usb/dwc3/dwc3-xilinx.c +index 67b237c7a76a1..550ae64350df0 100644 +--- a/drivers/usb/dwc3/dwc3-xilinx.c ++++ b/drivers/usb/dwc3/dwc3-xilinx.c +@@ -13,6 +13,7 @@ + #include <linux/of.h> + #include <linux/platform_device.h> + #include <linux/dma-mapping.h> ++#include <linux/gpio/consumer.h> + #include <linux/of_gpio.h> + #include <linux/of_platform.h> + #include <linux/pm_runtime.h> +diff --git a/drivers/usb/dwc3/gadget.c b/drivers/usb/dwc3/gadget.c +index c2075b90f3dfe..40f75ba53e80e 100644 +--- a/drivers/usb/dwc3/gadget.c ++++ b/drivers/usb/dwc3/gadget.c +@@ -1702,6 +1702,7 @@ static int __dwc3_stop_active_transfer(struct dwc3_ep *dep, bool force, bool int + else if (!ret) + dep->flags |= DWC3_EP_END_TRANSFER_PENDING; + ++ dep->flags &= ~DWC3_EP_DELAY_STOP; + return ret; + } + +@@ -3701,8 +3702,10 @@ void dwc3_stop_active_transfer(struct dwc3_ep *dep, bool force, + if (dep->number <= 1 && dwc->ep0state != EP0_DATA_PHASE) + return; + ++ if (interrupt && (dep->flags & DWC3_EP_DELAY_STOP)) ++ return; ++ + if (!(dep->flags & DWC3_EP_TRANSFER_STARTED) || +- (dep->flags & DWC3_EP_DELAY_STOP) || + (dep->flags & DWC3_EP_END_TRANSFER_PENDING)) + return; + +diff --git a/drivers/vdpa/mlx5/net/mlx5_vnet.c b/drivers/vdpa/mlx5/net/mlx5_vnet.c +index 90913365def43..444d6572b2d05 100644 +--- a/drivers/vdpa/mlx5/net/mlx5_vnet.c ++++ b/drivers/vdpa/mlx5/net/mlx5_vnet.c +@@ -1468,11 +1468,13 @@ static int mlx5_vdpa_add_mac_vlan_rules(struct mlx5_vdpa_net *ndev, u8 *mac, + dmac_v = MLX5_ADDR_OF(fte_match_param, headers_v, outer_headers.dmac_47_16); + eth_broadcast_addr(dmac_c); + ether_addr_copy(dmac_v, mac); +- MLX5_SET(fte_match_set_lyr_2_4, headers_c, cvlan_tag, 1); ++ if (ndev->mvdev.actual_features & BIT_ULL(VIRTIO_NET_F_CTRL_VLAN)) { ++ MLX5_SET(fte_match_set_lyr_2_4, headers_c, cvlan_tag, 1); ++ MLX5_SET_TO_ONES(fte_match_set_lyr_2_4, headers_c, first_vid); ++ } + if (tagged) { + MLX5_SET(fte_match_set_lyr_2_4, headers_v, cvlan_tag, 1); +- MLX5_SET_TO_ONES(fte_match_set_lyr_2_4, headers_c, first_vid); +- MLX5_SET(fte_match_set_lyr_2_4, headers_c, first_vid, vid); ++ MLX5_SET(fte_match_set_lyr_2_4, headers_v, first_vid, vid); + } + flow_act.action = MLX5_FLOW_CONTEXT_ACTION_FWD_DEST; + dest.type = MLX5_FLOW_DESTINATION_TYPE_TIR; +@@ -1684,7 +1686,7 @@ static virtio_net_ctrl_ack handle_ctrl_mac(struct mlx5_vdpa_dev *mvdev, u8 cmd) + + /* Need recreate the flow table entry, so that the packet could forward back + */ +- mac_vlan_del(ndev, ndev->config.mac, 0, false); ++ mac_vlan_del(ndev, mac_back, 0, false); + + if (mac_vlan_add(ndev, ndev->config.mac, 0, false)) { + mlx5_vdpa_warn(mvdev, "failed to insert forward rules, try to restore\n"); +diff --git a/drivers/vdpa/vdpa_sim/vdpa_sim.c b/drivers/vdpa/vdpa_sim/vdpa_sim.c +index 225b7f5d8be35..6489f44bca1af 100644 +--- a/drivers/vdpa/vdpa_sim/vdpa_sim.c ++++ b/drivers/vdpa/vdpa_sim/vdpa_sim.c +@@ -66,8 +66,7 @@ static void vdpasim_queue_ready(struct vdpasim *vdpasim, unsigned int idx) + { + struct vdpasim_virtqueue *vq = &vdpasim->vqs[idx]; + +- vringh_init_iotlb(&vq->vring, vdpasim->dev_attr.supported_features, +- VDPASIM_QUEUE_MAX, false, ++ vringh_init_iotlb(&vq->vring, vdpasim->features, vq->num, false, + (struct vring_desc *)(uintptr_t)vq->desc_addr, + (struct vring_avail *) + (uintptr_t)vq->driver_addr, +@@ -680,7 +679,9 @@ static void vdpasim_free(struct vdpa_device *vdpa) + } + + kvfree(vdpasim->buffer); +- vhost_iotlb_free(vdpasim->iommu); ++ for (i = 0; i < vdpasim->dev_attr.nas; i++) ++ vhost_iotlb_reset(&vdpasim->iommu[i]); ++ kfree(vdpasim->iommu); + kfree(vdpasim->vqs); + kfree(vdpasim->config); + } +diff --git a/drivers/vdpa/vdpa_sim/vdpa_sim_blk.c b/drivers/vdpa/vdpa_sim/vdpa_sim_blk.c +index c8bfea3b7db23..cc0534f8ae934 100644 +--- a/drivers/vdpa/vdpa_sim/vdpa_sim_blk.c ++++ b/drivers/vdpa/vdpa_sim/vdpa_sim_blk.c +@@ -427,8 +427,10 @@ static int __init vdpasim_blk_init(void) + int ret; + + ret = device_register(&vdpasim_blk_mgmtdev); +- if (ret) ++ if (ret) { ++ put_device(&vdpasim_blk_mgmtdev); + return ret; ++ } + + ret = vdpa_mgmtdev_register(&mgmt_dev); + if (ret) +diff --git a/drivers/vdpa/vdpa_sim/vdpa_sim_net.c b/drivers/vdpa/vdpa_sim/vdpa_sim_net.c +index 886449e885026..c2e19dd064198 100644 +--- a/drivers/vdpa/vdpa_sim/vdpa_sim_net.c ++++ b/drivers/vdpa/vdpa_sim/vdpa_sim_net.c +@@ -304,8 +304,10 @@ static int __init vdpasim_net_init(void) + int ret; + + ret = device_register(&vdpasim_net_mgmtdev); +- if (ret) ++ if (ret) { ++ put_device(&vdpasim_net_mgmtdev); + return ret; ++ } + + ret = vdpa_mgmtdev_register(&mgmt_dev); + if (ret) +diff --git a/drivers/vdpa/virtio_pci/vp_vdpa.c b/drivers/vdpa/virtio_pci/vp_vdpa.c +index 04522077735b2..f4e375b1d903c 100644 +--- a/drivers/vdpa/virtio_pci/vp_vdpa.c ++++ b/drivers/vdpa/virtio_pci/vp_vdpa.c +@@ -629,7 +629,7 @@ static void vp_vdpa_remove(struct pci_dev *pdev) + mdev = vp_vdpa_mgtdev->mdev; + vp_modern_remove(mdev); + vdpa_mgmtdev_unregister(&vp_vdpa_mgtdev->mgtdev); +- kfree(&vp_vdpa_mgtdev->mgtdev.id_table); ++ kfree(vp_vdpa_mgtdev->mgtdev.id_table); + kfree(mdev); + kfree(vp_vdpa_mgtdev); + } +diff --git a/drivers/vhost/vdpa.c b/drivers/vhost/vdpa.c +index 166044642fd5c..ec32f785dfdec 100644 +--- a/drivers/vhost/vdpa.c ++++ b/drivers/vhost/vdpa.c +@@ -65,6 +65,10 @@ static DEFINE_IDA(vhost_vdpa_ida); + + static dev_t vhost_vdpa_major; + ++static void vhost_vdpa_iotlb_unmap(struct vhost_vdpa *v, ++ struct vhost_iotlb *iotlb, u64 start, ++ u64 last, u32 asid); ++ + static inline u32 iotlb_to_asid(struct vhost_iotlb *iotlb) + { + struct vhost_vdpa_as *as = container_of(iotlb, struct +@@ -135,7 +139,7 @@ static int vhost_vdpa_remove_as(struct vhost_vdpa *v, u32 asid) + return -EINVAL; + + hlist_del(&as->hash_link); +- vhost_iotlb_reset(&as->iotlb); ++ vhost_vdpa_iotlb_unmap(v, &as->iotlb, 0ULL, 0ULL - 1, asid); + kfree(as); + + return 0; +@@ -683,10 +687,20 @@ static long vhost_vdpa_unlocked_ioctl(struct file *filep, + mutex_unlock(&d->mutex); + return r; + } ++static void vhost_vdpa_general_unmap(struct vhost_vdpa *v, ++ struct vhost_iotlb_map *map, u32 asid) ++{ ++ struct vdpa_device *vdpa = v->vdpa; ++ const struct vdpa_config_ops *ops = vdpa->config; ++ if (ops->dma_map) { ++ ops->dma_unmap(vdpa, asid, map->start, map->size); ++ } else if (ops->set_map == NULL) { ++ iommu_unmap(v->domain, map->start, map->size); ++ } ++} + +-static void vhost_vdpa_pa_unmap(struct vhost_vdpa *v, +- struct vhost_iotlb *iotlb, +- u64 start, u64 last) ++static void vhost_vdpa_pa_unmap(struct vhost_vdpa *v, struct vhost_iotlb *iotlb, ++ u64 start, u64 last, u32 asid) + { + struct vhost_dev *dev = &v->vdev; + struct vhost_iotlb_map *map; +@@ -703,13 +717,13 @@ static void vhost_vdpa_pa_unmap(struct vhost_vdpa *v, + unpin_user_page(page); + } + atomic64_sub(PFN_DOWN(map->size), &dev->mm->pinned_vm); ++ vhost_vdpa_general_unmap(v, map, asid); + vhost_iotlb_map_free(iotlb, map); + } + } + +-static void vhost_vdpa_va_unmap(struct vhost_vdpa *v, +- struct vhost_iotlb *iotlb, +- u64 start, u64 last) ++static void vhost_vdpa_va_unmap(struct vhost_vdpa *v, struct vhost_iotlb *iotlb, ++ u64 start, u64 last, u32 asid) + { + struct vhost_iotlb_map *map; + struct vdpa_map_file *map_file; +@@ -718,20 +732,21 @@ static void vhost_vdpa_va_unmap(struct vhost_vdpa *v, + map_file = (struct vdpa_map_file *)map->opaque; + fput(map_file->file); + kfree(map_file); ++ vhost_vdpa_general_unmap(v, map, asid); + vhost_iotlb_map_free(iotlb, map); + } + } + + static void vhost_vdpa_iotlb_unmap(struct vhost_vdpa *v, +- struct vhost_iotlb *iotlb, +- u64 start, u64 last) ++ struct vhost_iotlb *iotlb, u64 start, ++ u64 last, u32 asid) + { + struct vdpa_device *vdpa = v->vdpa; + + if (vdpa->use_va) +- return vhost_vdpa_va_unmap(v, iotlb, start, last); ++ return vhost_vdpa_va_unmap(v, iotlb, start, last, asid); + +- return vhost_vdpa_pa_unmap(v, iotlb, start, last); ++ return vhost_vdpa_pa_unmap(v, iotlb, start, last, asid); + } + + static int perm_to_iommu_flags(u32 perm) +@@ -798,17 +813,12 @@ static void vhost_vdpa_unmap(struct vhost_vdpa *v, + const struct vdpa_config_ops *ops = vdpa->config; + u32 asid = iotlb_to_asid(iotlb); + +- vhost_vdpa_iotlb_unmap(v, iotlb, iova, iova + size - 1); ++ vhost_vdpa_iotlb_unmap(v, iotlb, iova, iova + size - 1, asid); + +- if (ops->dma_map) { +- ops->dma_unmap(vdpa, asid, iova, size); +- } else if (ops->set_map) { ++ if (ops->set_map) { + if (!v->in_batch) + ops->set_map(vdpa, asid, iotlb); +- } else { +- iommu_unmap(v->domain, iova, size); + } +- + /* If we are in the middle of batch processing, delay the free + * of AS until BATCH_END. + */ +@@ -1162,14 +1172,14 @@ static void vhost_vdpa_cleanup(struct vhost_vdpa *v) + struct vhost_vdpa_as *as; + u32 asid; + +- vhost_dev_cleanup(&v->vdev); +- kfree(v->vdev.vqs); +- + for (asid = 0; asid < v->vdpa->nas; asid++) { + as = asid_to_as(v, asid); + if (as) + vhost_vdpa_remove_as(v, asid); + } ++ ++ vhost_dev_cleanup(&v->vdev); ++ kfree(v->vdev.vqs); + } + + static int vhost_vdpa_open(struct inode *inode, struct file *filep) +diff --git a/drivers/vhost/vhost.c b/drivers/vhost/vhost.c +index 40097826cff0b..3c2359570df9d 100644 +--- a/drivers/vhost/vhost.c ++++ b/drivers/vhost/vhost.c +@@ -2053,7 +2053,7 @@ static int translate_desc(struct vhost_virtqueue *vq, u64 addr, u32 len, + struct vhost_dev *dev = vq->dev; + struct vhost_iotlb *umem = dev->iotlb ? dev->iotlb : dev->umem; + struct iovec *_iov; +- u64 s = 0; ++ u64 s = 0, last = addr + len - 1; + int ret = 0; + + while ((u64)len > s) { +@@ -2063,7 +2063,7 @@ static int translate_desc(struct vhost_virtqueue *vq, u64 addr, u32 len, + break; + } + +- map = vhost_iotlb_itree_first(umem, addr, addr + len - 1); ++ map = vhost_iotlb_itree_first(umem, addr, last); + if (map == NULL || map->start > addr) { + if (umem != dev->iotlb) { + ret = -EFAULT; +diff --git a/drivers/vhost/vringh.c b/drivers/vhost/vringh.c +index 11f59dd06a74e..828c293065657 100644 +--- a/drivers/vhost/vringh.c ++++ b/drivers/vhost/vringh.c +@@ -1102,7 +1102,7 @@ static int iotlb_translate(const struct vringh *vrh, + struct vhost_iotlb_map *map; + struct vhost_iotlb *iotlb = vrh->iotlb; + int ret = 0; +- u64 s = 0; ++ u64 s = 0, last = addr + len - 1; + + spin_lock(vrh->iotlb_lock); + +@@ -1114,8 +1114,7 @@ static int iotlb_translate(const struct vringh *vrh, + break; + } + +- map = vhost_iotlb_itree_first(iotlb, addr, +- addr + len - 1); ++ map = vhost_iotlb_itree_first(iotlb, addr, last); + if (!map || map->start > addr) { + ret = -EINVAL; + break; +diff --git a/drivers/vhost/vsock.c b/drivers/vhost/vsock.c +index 5703775af1297..10a7d23731fef 100644 +--- a/drivers/vhost/vsock.c ++++ b/drivers/vhost/vsock.c +@@ -959,7 +959,14 @@ static int __init vhost_vsock_init(void) + VSOCK_TRANSPORT_F_H2G); + if (ret < 0) + return ret; +- return misc_register(&vhost_vsock_misc); ++ ++ ret = misc_register(&vhost_vsock_misc); ++ if (ret) { ++ vsock_core_unregister(&vhost_transport.transport); ++ return ret; ++ } ++ ++ return 0; + }; + + static void __exit vhost_vsock_exit(void) +diff --git a/drivers/video/fbdev/matrox/matroxfb_base.c b/drivers/video/fbdev/matrox/matroxfb_base.c +index 68bba2688f4c1..3d1bca3bcd4fd 100644 +--- a/drivers/video/fbdev/matrox/matroxfb_base.c ++++ b/drivers/video/fbdev/matrox/matroxfb_base.c +@@ -1377,8 +1377,8 @@ static struct video_board vbG200 = { + .lowlevel = &matrox_G100 + }; + static struct video_board vbG200eW = { +- .maxvram = 0x100000, +- .maxdisplayable = 0x800000, ++ .maxvram = 0x1000000, ++ .maxdisplayable = 0x0800000, + .accelID = FB_ACCEL_MATROX_MGAG200, + .lowlevel = &matrox_G100 + }; +diff --git a/fs/btrfs/block-rsv.c b/fs/btrfs/block-rsv.c +index 06be0644dd376..6ce704d3bdd27 100644 +--- a/fs/btrfs/block-rsv.c ++++ b/fs/btrfs/block-rsv.c +@@ -424,6 +424,7 @@ void btrfs_init_root_block_rsv(struct btrfs_root *root) + case BTRFS_CSUM_TREE_OBJECTID: + case BTRFS_EXTENT_TREE_OBJECTID: + case BTRFS_FREE_SPACE_TREE_OBJECTID: ++ case BTRFS_BLOCK_GROUP_TREE_OBJECTID: + root->block_rsv = &fs_info->delayed_refs_rsv; + break; + case BTRFS_ROOT_TREE_OBJECTID: +diff --git a/fs/btrfs/ctree.h b/fs/btrfs/ctree.h +index bad06add93d7e..8e77acdecd252 100644 +--- a/fs/btrfs/ctree.h ++++ b/fs/btrfs/ctree.h +@@ -280,14 +280,9 @@ struct btrfs_super_block { + /* the UUID written into btree blocks */ + u8 metadata_uuid[BTRFS_FSID_SIZE]; + +- /* Extent tree v2 */ +- __le64 block_group_root; +- __le64 block_group_root_generation; +- u8 block_group_root_level; +- + /* future expansion */ +- u8 reserved8[7]; +- __le64 reserved[25]; ++ u8 reserved8[8]; ++ __le64 reserved[27]; + u8 sys_chunk_array[BTRFS_SYSTEM_CHUNK_ARRAY_SIZE]; + struct btrfs_root_backup super_roots[BTRFS_NUM_BACKUP_ROOTS]; + +@@ -307,7 +302,8 @@ static_assert(sizeof(struct btrfs_super_block) == BTRFS_SUPER_INFO_SIZE); + #define BTRFS_FEATURE_COMPAT_RO_SUPP \ + (BTRFS_FEATURE_COMPAT_RO_FREE_SPACE_TREE | \ + BTRFS_FEATURE_COMPAT_RO_FREE_SPACE_TREE_VALID | \ +- BTRFS_FEATURE_COMPAT_RO_VERITY) ++ BTRFS_FEATURE_COMPAT_RO_VERITY | \ ++ BTRFS_FEATURE_COMPAT_RO_BLOCK_GROUP_TREE) + + #define BTRFS_FEATURE_COMPAT_RO_SAFE_SET 0ULL + #define BTRFS_FEATURE_COMPAT_RO_SAFE_CLEAR 0ULL +@@ -2391,17 +2387,6 @@ BTRFS_SETGET_STACK_FUNCS(backup_bytes_used, struct btrfs_root_backup, + BTRFS_SETGET_STACK_FUNCS(backup_num_devices, struct btrfs_root_backup, + num_devices, 64); + +-/* +- * For extent tree v2 we overload the extent root with the block group root, as +- * we will have multiple extent roots. +- */ +-BTRFS_SETGET_STACK_FUNCS(backup_block_group_root, struct btrfs_root_backup, +- extent_root, 64); +-BTRFS_SETGET_STACK_FUNCS(backup_block_group_root_gen, struct btrfs_root_backup, +- extent_root_gen, 64); +-BTRFS_SETGET_STACK_FUNCS(backup_block_group_root_level, +- struct btrfs_root_backup, extent_root_level, 8); +- + /* struct btrfs_balance_item */ + BTRFS_SETGET_FUNCS(balance_flags, struct btrfs_balance_item, flags, 64); + +@@ -2534,13 +2519,6 @@ BTRFS_SETGET_STACK_FUNCS(super_cache_generation, struct btrfs_super_block, + BTRFS_SETGET_STACK_FUNCS(super_magic, struct btrfs_super_block, magic, 64); + BTRFS_SETGET_STACK_FUNCS(super_uuid_tree_generation, struct btrfs_super_block, + uuid_tree_generation, 64); +-BTRFS_SETGET_STACK_FUNCS(super_block_group_root, struct btrfs_super_block, +- block_group_root, 64); +-BTRFS_SETGET_STACK_FUNCS(super_block_group_root_generation, +- struct btrfs_super_block, +- block_group_root_generation, 64); +-BTRFS_SETGET_STACK_FUNCS(super_block_group_root_level, struct btrfs_super_block, +- block_group_root_level, 8); + + int btrfs_super_csum_size(const struct btrfs_super_block *s); + const char *btrfs_super_csum_name(u16 csum_type); +diff --git a/fs/btrfs/disk-io.c b/fs/btrfs/disk-io.c +index aa4bc213d301b..23bb51e46e596 100644 +--- a/fs/btrfs/disk-io.c ++++ b/fs/btrfs/disk-io.c +@@ -167,11 +167,9 @@ static bool btrfs_supported_super_csum(u16 csum_type) + * Return 0 if the superblock checksum type matches the checksum value of that + * algorithm. Pass the raw disk superblock data. + */ +-static int btrfs_check_super_csum(struct btrfs_fs_info *fs_info, +- char *raw_disk_sb) ++int btrfs_check_super_csum(struct btrfs_fs_info *fs_info, ++ const struct btrfs_super_block *disk_sb) + { +- struct btrfs_super_block *disk_sb = +- (struct btrfs_super_block *)raw_disk_sb; + char result[BTRFS_CSUM_SIZE]; + SHASH_DESC_ON_STACK(shash, fs_info->csum_shash); + +@@ -182,7 +180,7 @@ static int btrfs_check_super_csum(struct btrfs_fs_info *fs_info, + * BTRFS_SUPER_INFO_SIZE range, we expect that the unused space is + * filled with zeros and is included in the checksum. + */ +- crypto_shash_digest(shash, raw_disk_sb + BTRFS_CSUM_SIZE, ++ crypto_shash_digest(shash, (const u8 *)disk_sb + BTRFS_CSUM_SIZE, + BTRFS_SUPER_INFO_SIZE - BTRFS_CSUM_SIZE, result); + + if (memcmp(disk_sb->csum, result, fs_info->csum_size)) +@@ -1524,6 +1522,9 @@ static struct btrfs_root *btrfs_get_global_root(struct btrfs_fs_info *fs_info, + if (objectid == BTRFS_UUID_TREE_OBJECTID) + return btrfs_grab_root(fs_info->uuid_root) ? + fs_info->uuid_root : ERR_PTR(-ENOENT); ++ if (objectid == BTRFS_BLOCK_GROUP_TREE_OBJECTID) ++ return btrfs_grab_root(fs_info->block_group_root) ? ++ fs_info->block_group_root : ERR_PTR(-ENOENT); + if (objectid == BTRFS_FREE_SPACE_TREE_OBJECTID) { + struct btrfs_root *root = btrfs_global_root(fs_info, &key); + +@@ -1980,14 +1981,7 @@ static void backup_super_roots(struct btrfs_fs_info *info) + btrfs_set_backup_chunk_root_level(root_backup, + btrfs_header_level(info->chunk_root->node)); + +- if (btrfs_fs_incompat(info, EXTENT_TREE_V2)) { +- btrfs_set_backup_block_group_root(root_backup, +- info->block_group_root->node->start); +- btrfs_set_backup_block_group_root_gen(root_backup, +- btrfs_header_generation(info->block_group_root->node)); +- btrfs_set_backup_block_group_root_level(root_backup, +- btrfs_header_level(info->block_group_root->node)); +- } else { ++ if (!btrfs_fs_compat_ro(info, BLOCK_GROUP_TREE)) { + struct btrfs_root *extent_root = btrfs_extent_root(info, 0); + struct btrfs_root *csum_root = btrfs_csum_root(info, 0); + +@@ -2529,10 +2523,24 @@ static int btrfs_read_roots(struct btrfs_fs_info *fs_info) + if (ret) + return ret; + +- location.objectid = BTRFS_DEV_TREE_OBJECTID; + location.type = BTRFS_ROOT_ITEM_KEY; + location.offset = 0; + ++ if (btrfs_fs_compat_ro(fs_info, BLOCK_GROUP_TREE)) { ++ location.objectid = BTRFS_BLOCK_GROUP_TREE_OBJECTID; ++ root = btrfs_read_tree_root(tree_root, &location); ++ if (IS_ERR(root)) { ++ if (!btrfs_test_opt(fs_info, IGNOREBADROOTS)) { ++ ret = PTR_ERR(root); ++ goto out; ++ } ++ } else { ++ set_bit(BTRFS_ROOT_TRACK_DIRTY, &root->state); ++ fs_info->block_group_root = root; ++ } ++ } ++ ++ location.objectid = BTRFS_DEV_TREE_OBJECTID; + root = btrfs_read_tree_root(tree_root, &location); + if (IS_ERR(root)) { + if (!btrfs_test_opt(fs_info, IGNOREBADROOTS)) { +@@ -2602,8 +2610,8 @@ out: + * 1, 2 2nd and 3rd backup copy + * -1 skip bytenr check + */ +-static int validate_super(struct btrfs_fs_info *fs_info, +- struct btrfs_super_block *sb, int mirror_num) ++int btrfs_validate_super(struct btrfs_fs_info *fs_info, ++ struct btrfs_super_block *sb, int mirror_num) + { + u64 nodesize = btrfs_super_nodesize(sb); + u64 sectorsize = btrfs_super_sectorsize(sb); +@@ -2705,6 +2713,18 @@ static int validate_super(struct btrfs_fs_info *fs_info, + ret = -EINVAL; + } + ++ /* ++ * Artificial requirement for block-group-tree to force newer features ++ * (free-space-tree, no-holes) so the test matrix is smaller. ++ */ ++ if (btrfs_fs_compat_ro(fs_info, BLOCK_GROUP_TREE) && ++ (!btrfs_fs_compat_ro(fs_info, FREE_SPACE_TREE_VALID) || ++ !btrfs_fs_incompat(fs_info, NO_HOLES))) { ++ btrfs_err(fs_info, ++ "block-group-tree feature requires fres-space-tree and no-holes"); ++ ret = -EINVAL; ++ } ++ + if (memcmp(fs_info->fs_devices->metadata_uuid, sb->dev_item.fsid, + BTRFS_FSID_SIZE) != 0) { + btrfs_err(fs_info, +@@ -2787,7 +2807,7 @@ static int validate_super(struct btrfs_fs_info *fs_info, + */ + static int btrfs_validate_mount_super(struct btrfs_fs_info *fs_info) + { +- return validate_super(fs_info, fs_info->super_copy, 0); ++ return btrfs_validate_super(fs_info, fs_info->super_copy, 0); + } + + /* +@@ -2801,7 +2821,7 @@ static int btrfs_validate_write_super(struct btrfs_fs_info *fs_info, + { + int ret; + +- ret = validate_super(fs_info, sb, -1); ++ ret = btrfs_validate_super(fs_info, sb, -1); + if (ret < 0) + goto out; + if (!btrfs_supported_super_csum(btrfs_super_csum_type(sb))) { +@@ -2862,17 +2882,7 @@ static int load_important_roots(struct btrfs_fs_info *fs_info) + btrfs_warn(fs_info, "couldn't read tree root"); + return ret; + } +- +- if (!btrfs_fs_incompat(fs_info, EXTENT_TREE_V2)) +- return 0; +- +- bytenr = btrfs_super_block_group_root(sb); +- gen = btrfs_super_block_group_root_generation(sb); +- level = btrfs_super_block_group_root_level(sb); +- ret = load_super_root(fs_info->block_group_root, bytenr, gen, level); +- if (ret) +- btrfs_warn(fs_info, "couldn't read block group root"); +- return ret; ++ return 0; + } + + static int __cold init_tree_roots(struct btrfs_fs_info *fs_info) +@@ -2884,16 +2894,6 @@ static int __cold init_tree_roots(struct btrfs_fs_info *fs_info) + int ret = 0; + int i; + +- if (btrfs_fs_incompat(fs_info, EXTENT_TREE_V2)) { +- struct btrfs_root *root; +- +- root = btrfs_alloc_root(fs_info, BTRFS_BLOCK_GROUP_TREE_OBJECTID, +- GFP_KERNEL); +- if (!root) +- return -ENOMEM; +- fs_info->block_group_root = root; +- } +- + for (i = 0; i < BTRFS_NUM_BACKUP_ROOTS; i++) { + if (handle_error) { + if (!IS_ERR(tree_root->node)) +@@ -3281,6 +3281,114 @@ out: + return ret; + } + ++/* ++ * Do various sanity and dependency checks of different features. ++ * ++ * @is_rw_mount: If the mount is read-write. ++ * ++ * This is the place for less strict checks (like for subpage or artificial ++ * feature dependencies). ++ * ++ * For strict checks or possible corruption detection, see ++ * btrfs_validate_super(). ++ * ++ * This should be called after btrfs_parse_options(), as some mount options ++ * (space cache related) can modify on-disk format like free space tree and ++ * screw up certain feature dependencies. ++ */ ++int btrfs_check_features(struct btrfs_fs_info *fs_info, bool is_rw_mount) ++{ ++ struct btrfs_super_block *disk_super = fs_info->super_copy; ++ u64 incompat = btrfs_super_incompat_flags(disk_super); ++ const u64 compat_ro = btrfs_super_compat_ro_flags(disk_super); ++ const u64 compat_ro_unsupp = (compat_ro & ~BTRFS_FEATURE_COMPAT_RO_SUPP); ++ ++ if (incompat & ~BTRFS_FEATURE_INCOMPAT_SUPP) { ++ btrfs_err(fs_info, ++ "cannot mount because of unknown incompat features (0x%llx)", ++ incompat); ++ return -EINVAL; ++ } ++ ++ /* Runtime limitation for mixed block groups. */ ++ if ((incompat & BTRFS_FEATURE_INCOMPAT_MIXED_GROUPS) && ++ (fs_info->sectorsize != fs_info->nodesize)) { ++ btrfs_err(fs_info, ++"unequal nodesize/sectorsize (%u != %u) are not allowed for mixed block groups", ++ fs_info->nodesize, fs_info->sectorsize); ++ return -EINVAL; ++ } ++ ++ /* Mixed backref is an always-enabled feature. */ ++ incompat |= BTRFS_FEATURE_INCOMPAT_MIXED_BACKREF; ++ ++ /* Set compression related flags just in case. */ ++ if (fs_info->compress_type == BTRFS_COMPRESS_LZO) ++ incompat |= BTRFS_FEATURE_INCOMPAT_COMPRESS_LZO; ++ else if (fs_info->compress_type == BTRFS_COMPRESS_ZSTD) ++ incompat |= BTRFS_FEATURE_INCOMPAT_COMPRESS_ZSTD; ++ ++ /* ++ * An ancient flag, which should really be marked deprecated. ++ * Such runtime limitation doesn't really need a incompat flag. ++ */ ++ if (btrfs_super_nodesize(disk_super) > PAGE_SIZE) ++ incompat |= BTRFS_FEATURE_INCOMPAT_BIG_METADATA; ++ ++ if (compat_ro_unsupp && is_rw_mount) { ++ btrfs_err(fs_info, ++ "cannot mount read-write because of unknown compat_ro features (0x%llx)", ++ compat_ro); ++ return -EINVAL; ++ } ++ ++ /* ++ * We have unsupported RO compat features, although RO mounted, we ++ * should not cause any metadata writes, including log replay. ++ * Or we could screw up whatever the new feature requires. ++ */ ++ if (compat_ro_unsupp && btrfs_super_log_root(disk_super) && ++ !btrfs_test_opt(fs_info, NOLOGREPLAY)) { ++ btrfs_err(fs_info, ++"cannot replay dirty log with unsupported compat_ro features (0x%llx), try rescue=nologreplay", ++ compat_ro); ++ return -EINVAL; ++ } ++ ++ /* ++ * Artificial limitations for block group tree, to force ++ * block-group-tree to rely on no-holes and free-space-tree. ++ */ ++ if (btrfs_fs_compat_ro(fs_info, BLOCK_GROUP_TREE) && ++ (!btrfs_fs_incompat(fs_info, NO_HOLES) || ++ !btrfs_test_opt(fs_info, FREE_SPACE_TREE))) { ++ btrfs_err(fs_info, ++"block-group-tree feature requires no-holes and free-space-tree features"); ++ return -EINVAL; ++ } ++ ++ /* ++ * Subpage runtime limitation on v1 cache. ++ * ++ * V1 space cache still has some hard codeed PAGE_SIZE usage, while ++ * we're already defaulting to v2 cache, no need to bother v1 as it's ++ * going to be deprecated anyway. ++ */ ++ if (fs_info->sectorsize < PAGE_SIZE && btrfs_test_opt(fs_info, SPACE_CACHE)) { ++ btrfs_warn(fs_info, ++ "v1 space cache is not supported for page size %lu with sectorsize %u", ++ PAGE_SIZE, fs_info->sectorsize); ++ return -EINVAL; ++ } ++ ++ /* This can be called by remount, we need to protect the super block. */ ++ spin_lock(&fs_info->super_lock); ++ btrfs_set_super_incompat_flags(disk_super, incompat); ++ spin_unlock(&fs_info->super_lock); ++ ++ return 0; ++} ++ + int __cold open_ctree(struct super_block *sb, struct btrfs_fs_devices *fs_devices, + char *options) + { +@@ -3361,7 +3469,7 @@ int __cold open_ctree(struct super_block *sb, struct btrfs_fs_devices *fs_device + * We want to check superblock checksum, the type is stored inside. + * Pass the whole disk block of size BTRFS_SUPER_INFO_SIZE (4k). + */ +- if (btrfs_check_super_csum(fs_info, (u8 *)disk_super)) { ++ if (btrfs_check_super_csum(fs_info, disk_super)) { + btrfs_err(fs_info, "superblock checksum mismatch"); + err = -EINVAL; + btrfs_release_disk_super(disk_super); +@@ -3430,72 +3538,12 @@ int __cold open_ctree(struct super_block *sb, struct btrfs_fs_devices *fs_device + goto fail_alloc; + } + +- features = btrfs_super_incompat_flags(disk_super) & +- ~BTRFS_FEATURE_INCOMPAT_SUPP; +- if (features) { +- btrfs_err(fs_info, +- "cannot mount because of unsupported optional features (0x%llx)", +- features); +- err = -EINVAL; +- goto fail_alloc; +- } +- +- features = btrfs_super_incompat_flags(disk_super); +- features |= BTRFS_FEATURE_INCOMPAT_MIXED_BACKREF; +- if (fs_info->compress_type == BTRFS_COMPRESS_LZO) +- features |= BTRFS_FEATURE_INCOMPAT_COMPRESS_LZO; +- else if (fs_info->compress_type == BTRFS_COMPRESS_ZSTD) +- features |= BTRFS_FEATURE_INCOMPAT_COMPRESS_ZSTD; +- +- /* +- * Flag our filesystem as having big metadata blocks if they are bigger +- * than the page size. +- */ +- if (btrfs_super_nodesize(disk_super) > PAGE_SIZE) +- features |= BTRFS_FEATURE_INCOMPAT_BIG_METADATA; +- +- /* +- * mixed block groups end up with duplicate but slightly offset +- * extent buffers for the same range. It leads to corruptions +- */ +- if ((features & BTRFS_FEATURE_INCOMPAT_MIXED_GROUPS) && +- (sectorsize != nodesize)) { +- btrfs_err(fs_info, +-"unequal nodesize/sectorsize (%u != %u) are not allowed for mixed block groups", +- nodesize, sectorsize); +- goto fail_alloc; +- } +- +- /* +- * Needn't use the lock because there is no other task which will +- * update the flag. +- */ +- btrfs_set_super_incompat_flags(disk_super, features); +- +- features = btrfs_super_compat_ro_flags(disk_super) & +- ~BTRFS_FEATURE_COMPAT_RO_SUPP; +- if (!sb_rdonly(sb) && features) { +- btrfs_err(fs_info, +- "cannot mount read-write because of unsupported optional features (0x%llx)", +- features); +- err = -EINVAL; +- goto fail_alloc; +- } +- /* +- * We have unsupported RO compat features, although RO mounted, we +- * should not cause any metadata write, including log replay. +- * Or we could screw up whatever the new feature requires. +- */ +- if (unlikely(features && btrfs_super_log_root(disk_super) && +- !btrfs_test_opt(fs_info, NOLOGREPLAY))) { +- btrfs_err(fs_info, +-"cannot replay dirty log with unsupported compat_ro features (0x%llx), try rescue=nologreplay", +- features); +- err = -EINVAL; ++ ret = btrfs_check_features(fs_info, !sb_rdonly(sb)); ++ if (ret < 0) { ++ err = ret; + goto fail_alloc; + } + +- + if (sectorsize < PAGE_SIZE) { + struct btrfs_subpage_info *subpage_info; + +@@ -3835,7 +3883,7 @@ static void btrfs_end_super_write(struct bio *bio) + } + + struct btrfs_super_block *btrfs_read_dev_one_super(struct block_device *bdev, +- int copy_num) ++ int copy_num, bool drop_cache) + { + struct btrfs_super_block *super; + struct page *page; +@@ -3853,6 +3901,19 @@ struct btrfs_super_block *btrfs_read_dev_one_super(struct block_device *bdev, + if (bytenr + BTRFS_SUPER_INFO_SIZE >= bdev_nr_bytes(bdev)) + return ERR_PTR(-EINVAL); + ++ if (drop_cache) { ++ /* This should only be called with the primary sb. */ ++ ASSERT(copy_num == 0); ++ ++ /* ++ * Drop the page of the primary superblock, so later read will ++ * always read from the device. ++ */ ++ invalidate_inode_pages2_range(mapping, ++ bytenr >> PAGE_SHIFT, ++ (bytenr + BTRFS_SUPER_INFO_SIZE) >> PAGE_SHIFT); ++ } ++ + page = read_cache_page_gfp(mapping, bytenr >> PAGE_SHIFT, GFP_NOFS); + if (IS_ERR(page)) + return ERR_CAST(page); +@@ -3884,7 +3945,7 @@ struct btrfs_super_block *btrfs_read_dev_super(struct block_device *bdev) + * later supers, using BTRFS_SUPER_MIRROR_MAX instead + */ + for (i = 0; i < 1; i++) { +- super = btrfs_read_dev_one_super(bdev, i); ++ super = btrfs_read_dev_one_super(bdev, i, false); + if (IS_ERR(super)) + continue; + +diff --git a/fs/btrfs/disk-io.h b/fs/btrfs/disk-io.h +index 47ad8e0a2d33f..7322af63c0cc7 100644 +--- a/fs/btrfs/disk-io.h ++++ b/fs/btrfs/disk-io.h +@@ -42,14 +42,19 @@ struct extent_buffer *btrfs_find_create_tree_block( + void btrfs_clean_tree_block(struct extent_buffer *buf); + void btrfs_clear_oneshot_options(struct btrfs_fs_info *fs_info); + int btrfs_start_pre_rw_mount(struct btrfs_fs_info *fs_info); ++int btrfs_check_super_csum(struct btrfs_fs_info *fs_info, ++ const struct btrfs_super_block *disk_sb); + int __cold open_ctree(struct super_block *sb, + struct btrfs_fs_devices *fs_devices, + char *options); + void __cold close_ctree(struct btrfs_fs_info *fs_info); ++int btrfs_validate_super(struct btrfs_fs_info *fs_info, ++ struct btrfs_super_block *sb, int mirror_num); ++int btrfs_check_features(struct btrfs_fs_info *fs_info, bool is_rw_mount); + int write_all_supers(struct btrfs_fs_info *fs_info, int max_mirrors); + struct btrfs_super_block *btrfs_read_dev_super(struct block_device *bdev); + struct btrfs_super_block *btrfs_read_dev_one_super(struct block_device *bdev, +- int copy_num); ++ int copy_num, bool drop_cache); + int btrfs_commit_super(struct btrfs_fs_info *fs_info); + struct btrfs_root *btrfs_read_tree_root(struct btrfs_root *tree_root, + struct btrfs_key *key); +@@ -103,7 +108,7 @@ static inline struct btrfs_root *btrfs_grab_root(struct btrfs_root *root) + + static inline struct btrfs_root *btrfs_block_group_root(struct btrfs_fs_info *fs_info) + { +- if (btrfs_fs_incompat(fs_info, EXTENT_TREE_V2)) ++ if (btrfs_fs_compat_ro(fs_info, BLOCK_GROUP_TREE)) + return fs_info->block_group_root; + return btrfs_extent_root(fs_info, 0); + } +diff --git a/fs/btrfs/extent_io.c b/fs/btrfs/extent_io.c +index cf4f19e80e2f7..0982995177a6d 100644 +--- a/fs/btrfs/extent_io.c ++++ b/fs/btrfs/extent_io.c +@@ -2377,7 +2377,16 @@ static int repair_io_failure(struct btrfs_fs_info *fs_info, u64 ino, u64 start, + &map_length, &bioc, mirror_num); + if (ret) + goto out_counter_dec; +- BUG_ON(mirror_num != bioc->mirror_num); ++ /* ++ * This happens when dev-replace is also running, and the ++ * mirror_num indicates the dev-replace target. ++ * ++ * In this case, we don't need to do anything, as the read ++ * error just means the replace progress hasn't reached our ++ * read range, and later replace routine would handle it well. ++ */ ++ if (mirror_num != bioc->mirror_num) ++ goto out_counter_dec; + } + + sector = bioc->stripes[bioc->mirror_num - 1].physical >> 9; +diff --git a/fs/btrfs/ioctl.c b/fs/btrfs/ioctl.c +index 4fff0067bd2a9..c498d5e164eb0 100644 +--- a/fs/btrfs/ioctl.c ++++ b/fs/btrfs/ioctl.c +@@ -3750,13 +3750,10 @@ static long btrfs_ioctl_dev_info(struct btrfs_fs_info *fs_info, + di_args->bytes_used = btrfs_device_get_bytes_used(dev); + di_args->total_bytes = btrfs_device_get_total_bytes(dev); + memcpy(di_args->uuid, dev->uuid, sizeof(di_args->uuid)); +- if (dev->name) { +- strncpy(di_args->path, rcu_str_deref(dev->name), +- sizeof(di_args->path) - 1); +- di_args->path[sizeof(di_args->path) - 1] = 0; +- } else { ++ if (dev->name) ++ strscpy(di_args->path, rcu_str_deref(dev->name), sizeof(di_args->path)); ++ else + di_args->path[0] = '\0'; +- } + + out: + rcu_read_unlock(); +diff --git a/fs/btrfs/rcu-string.h b/fs/btrfs/rcu-string.h +index 5c1a617eb25de..5c2b66d155ef7 100644 +--- a/fs/btrfs/rcu-string.h ++++ b/fs/btrfs/rcu-string.h +@@ -18,7 +18,11 @@ static inline struct rcu_string *rcu_string_strdup(const char *src, gfp_t mask) + (len * sizeof(char)), mask); + if (!ret) + return ret; +- strncpy(ret->str, src, len); ++ /* Warn if the source got unexpectedly truncated. */ ++ if (WARN_ON(strscpy(ret->str, src, len) < 0)) { ++ kfree(ret); ++ return NULL; ++ } + return ret; + } + +diff --git a/fs/btrfs/super.c b/fs/btrfs/super.c +index ad3ce9700eaf3..01c381e75cdbb 100644 +--- a/fs/btrfs/super.c ++++ b/fs/btrfs/super.c +@@ -2012,14 +2012,10 @@ static int btrfs_remount(struct super_block *sb, int *flags, char *data) + if (ret) + goto restore; + +- /* V1 cache is not supported for subpage mount. */ +- if (fs_info->sectorsize < PAGE_SIZE && btrfs_test_opt(fs_info, SPACE_CACHE)) { +- btrfs_warn(fs_info, +- "v1 space cache is not supported for page size %lu with sectorsize %u", +- PAGE_SIZE, fs_info->sectorsize); +- ret = -EINVAL; ++ ret = btrfs_check_features(fs_info, !(*flags & SB_RDONLY)); ++ if (ret < 0) + goto restore; +- } ++ + btrfs_remount_begin(fs_info, old_opts, *flags); + btrfs_resize_thread_pool(fs_info, + fs_info->thread_pool_size, old_thread_pool_size); +@@ -2115,15 +2111,6 @@ static int btrfs_remount(struct super_block *sb, int *flags, char *data) + ret = -EINVAL; + goto restore; + } +- if (btrfs_super_compat_ro_flags(fs_info->super_copy) & +- ~BTRFS_FEATURE_COMPAT_RO_SUPP) { +- btrfs_err(fs_info, +- "can not remount read-write due to unsupported optional flags 0x%llx", +- btrfs_super_compat_ro_flags(fs_info->super_copy) & +- ~BTRFS_FEATURE_COMPAT_RO_SUPP); +- ret = -EINVAL; +- goto restore; +- } + if (fs_info->fs_devices->rw_devices == 0) { + ret = -EACCES; + goto restore; +@@ -2562,11 +2549,87 @@ static int btrfs_freeze(struct super_block *sb) + return btrfs_commit_transaction(trans); + } + ++static int check_dev_super(struct btrfs_device *dev) ++{ ++ struct btrfs_fs_info *fs_info = dev->fs_info; ++ struct btrfs_super_block *sb; ++ u16 csum_type; ++ int ret = 0; ++ ++ /* This should be called with fs still frozen. */ ++ ASSERT(test_bit(BTRFS_FS_FROZEN, &fs_info->flags)); ++ ++ /* Missing dev, no need to check. */ ++ if (!dev->bdev) ++ return 0; ++ ++ /* Only need to check the primary super block. */ ++ sb = btrfs_read_dev_one_super(dev->bdev, 0, true); ++ if (IS_ERR(sb)) ++ return PTR_ERR(sb); ++ ++ /* Verify the checksum. */ ++ csum_type = btrfs_super_csum_type(sb); ++ if (csum_type != btrfs_super_csum_type(fs_info->super_copy)) { ++ btrfs_err(fs_info, "csum type changed, has %u expect %u", ++ csum_type, btrfs_super_csum_type(fs_info->super_copy)); ++ ret = -EUCLEAN; ++ goto out; ++ } ++ ++ if (btrfs_check_super_csum(fs_info, sb)) { ++ btrfs_err(fs_info, "csum for on-disk super block no longer matches"); ++ ret = -EUCLEAN; ++ goto out; ++ } ++ ++ /* Btrfs_validate_super() includes fsid check against super->fsid. */ ++ ret = btrfs_validate_super(fs_info, sb, 0); ++ if (ret < 0) ++ goto out; ++ ++ if (btrfs_super_generation(sb) != fs_info->last_trans_committed) { ++ btrfs_err(fs_info, "transid mismatch, has %llu expect %llu", ++ btrfs_super_generation(sb), ++ fs_info->last_trans_committed); ++ ret = -EUCLEAN; ++ goto out; ++ } ++out: ++ btrfs_release_disk_super(sb); ++ return ret; ++} ++ + static int btrfs_unfreeze(struct super_block *sb) + { + struct btrfs_fs_info *fs_info = btrfs_sb(sb); ++ struct btrfs_device *device; ++ int ret = 0; + ++ /* ++ * Make sure the fs is not changed by accident (like hibernation then ++ * modified by other OS). ++ * If we found anything wrong, we mark the fs error immediately. ++ * ++ * And since the fs is frozen, no one can modify the fs yet, thus ++ * we don't need to hold device_list_mutex. ++ */ ++ list_for_each_entry(device, &fs_info->fs_devices->devices, dev_list) { ++ ret = check_dev_super(device); ++ if (ret < 0) { ++ btrfs_handle_fs_error(fs_info, ret, ++ "super block on devid %llu got modified unexpectedly", ++ device->devid); ++ break; ++ } ++ } + clear_bit(BTRFS_FS_FROZEN, &fs_info->flags); ++ ++ /* ++ * We still return 0, to allow VFS layer to unfreeze the fs even the ++ * above checks failed. Since the fs is either fine or read-only, we're ++ * safe to continue, without causing further damage. ++ */ + return 0; + } + +diff --git a/fs/btrfs/sysfs.c b/fs/btrfs/sysfs.c +index 00b97e6eb5078..897367ba68d2a 100644 +--- a/fs/btrfs/sysfs.c ++++ b/fs/btrfs/sysfs.c +@@ -286,6 +286,7 @@ BTRFS_FEAT_ATTR_INCOMPAT(skinny_metadata, SKINNY_METADATA); + BTRFS_FEAT_ATTR_INCOMPAT(no_holes, NO_HOLES); + BTRFS_FEAT_ATTR_INCOMPAT(metadata_uuid, METADATA_UUID); + BTRFS_FEAT_ATTR_COMPAT_RO(free_space_tree, FREE_SPACE_TREE); ++BTRFS_FEAT_ATTR_COMPAT_RO(block_group_tree, BLOCK_GROUP_TREE); + BTRFS_FEAT_ATTR_INCOMPAT(raid1c34, RAID1C34); + #ifdef CONFIG_BLK_DEV_ZONED + BTRFS_FEAT_ATTR_INCOMPAT(zoned, ZONED); +@@ -317,6 +318,7 @@ static struct attribute *btrfs_supported_feature_attrs[] = { + BTRFS_FEAT_ATTR_PTR(metadata_uuid), + BTRFS_FEAT_ATTR_PTR(free_space_tree), + BTRFS_FEAT_ATTR_PTR(raid1c34), ++ BTRFS_FEAT_ATTR_PTR(block_group_tree), + #ifdef CONFIG_BLK_DEV_ZONED + BTRFS_FEAT_ATTR_PTR(zoned), + #endif +diff --git a/fs/btrfs/transaction.c b/fs/btrfs/transaction.c +index 0bec10740ad39..8fab3b2749571 100644 +--- a/fs/btrfs/transaction.c ++++ b/fs/btrfs/transaction.c +@@ -1912,14 +1912,6 @@ static void update_super_roots(struct btrfs_fs_info *fs_info) + super->cache_generation = 0; + if (test_bit(BTRFS_FS_UPDATE_UUID_TREE_GEN, &fs_info->flags)) + super->uuid_tree_generation = root_item->generation; +- +- if (btrfs_fs_incompat(fs_info, EXTENT_TREE_V2)) { +- root_item = &fs_info->block_group_root->root_item; +- +- super->block_group_root = root_item->bytenr; +- super->block_group_root_generation = root_item->generation; +- super->block_group_root_level = root_item->level; +- } + } + + int btrfs_transaction_in_commit(struct btrfs_fs_info *info) +diff --git a/fs/btrfs/tree-defrag.c b/fs/btrfs/tree-defrag.c +index b6cf39f4e7e48..072ab9a1374b5 100644 +--- a/fs/btrfs/tree-defrag.c ++++ b/fs/btrfs/tree-defrag.c +@@ -31,8 +31,10 @@ int btrfs_defrag_leaves(struct btrfs_trans_handle *trans, + goto out; + + path = btrfs_alloc_path(); +- if (!path) +- return -ENOMEM; ++ if (!path) { ++ ret = -ENOMEM; ++ goto out; ++ } + + level = btrfs_header_level(root->node); + +diff --git a/fs/btrfs/volumes.c b/fs/btrfs/volumes.c +index 6f006430115a3..55c8bf9a5c890 100644 +--- a/fs/btrfs/volumes.c ++++ b/fs/btrfs/volumes.c +@@ -2029,7 +2029,7 @@ void btrfs_scratch_superblocks(struct btrfs_fs_info *fs_info, + struct page *page; + int ret; + +- disk_super = btrfs_read_dev_one_super(bdev, copy_num); ++ disk_super = btrfs_read_dev_one_super(bdev, copy_num, false); + if (IS_ERR(disk_super)) + continue; + +diff --git a/fs/ceph/caps.c b/fs/ceph/caps.c +index 02b5c0ac56547..af8dbcf932ab1 100644 +--- a/fs/ceph/caps.c ++++ b/fs/ceph/caps.c +@@ -2910,7 +2910,7 @@ int ceph_get_caps(struct file *filp, int need, int want, loff_t endoff, int *got + + while (true) { + flags &= CEPH_FILE_MODE_MASK; +- if (atomic_read(&fi->num_locks)) ++ if (vfs_inode_has_locks(inode)) + flags |= CHECK_FILELOCK; + _got = 0; + ret = try_get_cap_refs(inode, need, want, endoff, +diff --git a/fs/ceph/locks.c b/fs/ceph/locks.c +index 3e2843e86e274..b191426bf880c 100644 +--- a/fs/ceph/locks.c ++++ b/fs/ceph/locks.c +@@ -32,18 +32,14 @@ void __init ceph_flock_init(void) + + static void ceph_fl_copy_lock(struct file_lock *dst, struct file_lock *src) + { +- struct ceph_file_info *fi = dst->fl_file->private_data; + struct inode *inode = file_inode(dst->fl_file); + atomic_inc(&ceph_inode(inode)->i_filelock_ref); +- atomic_inc(&fi->num_locks); + } + + static void ceph_fl_release_lock(struct file_lock *fl) + { +- struct ceph_file_info *fi = fl->fl_file->private_data; + struct inode *inode = file_inode(fl->fl_file); + struct ceph_inode_info *ci = ceph_inode(inode); +- atomic_dec(&fi->num_locks); + if (atomic_dec_and_test(&ci->i_filelock_ref)) { + /* clear error when all locks are released */ + spin_lock(&ci->i_ceph_lock); +diff --git a/fs/ceph/super.h b/fs/ceph/super.h +index 40630e6f691c7..ae4126f634101 100644 +--- a/fs/ceph/super.h ++++ b/fs/ceph/super.h +@@ -788,7 +788,6 @@ struct ceph_file_info { + struct list_head rw_contexts; + + u32 filp_gen; +- atomic_t num_locks; + }; + + struct ceph_dir_file_info { +diff --git a/fs/cifs/sess.c b/fs/cifs/sess.c +index 5d93154572c01..4ef2d08de5b65 100644 +--- a/fs/cifs/sess.c ++++ b/fs/cifs/sess.c +@@ -292,9 +292,10 @@ cifs_chan_update_iface(struct cifs_ses *ses, struct TCP_Server_Info *server) + continue; + } + kref_get(&iface->refcount); ++ break; + } + +- if (!list_entry_is_head(iface, &ses->iface_list, iface_head)) { ++ if (list_entry_is_head(iface, &ses->iface_list, iface_head)) { + rc = 1; + iface = NULL; + cifs_dbg(FYI, "unable to find a suitable iface\n"); +diff --git a/fs/cifs/smb2ops.c b/fs/cifs/smb2ops.c +index 74052b51655ec..05c9c75360fab 100644 +--- a/fs/cifs/smb2ops.c ++++ b/fs/cifs/smb2ops.c +@@ -530,7 +530,6 @@ parse_server_interfaces(struct network_interface_info_ioctl_rsp *buf, + p = buf; + + spin_lock(&ses->iface_lock); +- ses->iface_count = 0; + /* + * Go through iface_list and do kref_put to remove + * any unused ifaces. ifaces in use will be removed +@@ -540,6 +539,7 @@ parse_server_interfaces(struct network_interface_info_ioctl_rsp *buf, + iface_head) { + iface->is_active = 0; + kref_put(&iface->refcount, release_iface); ++ ses->iface_count--; + } + spin_unlock(&ses->iface_lock); + +@@ -617,6 +617,7 @@ parse_server_interfaces(struct network_interface_info_ioctl_rsp *buf, + /* just get a ref so that it doesn't get picked/freed */ + iface->is_active = 1; + kref_get(&iface->refcount); ++ ses->iface_count++; + spin_unlock(&ses->iface_lock); + goto next_iface; + } else if (ret < 0) { +diff --git a/fs/ext4/super.c b/fs/ext4/super.c +index 2eae6e038f38a..ac083526c1155 100644 +--- a/fs/ext4/super.c ++++ b/fs/ext4/super.c +@@ -5063,30 +5063,31 @@ static int __ext4_fill_super(struct fs_context *fc, struct super_block *sb) + ext4_has_feature_journal_needs_recovery(sb)) { + ext4_msg(sb, KERN_ERR, "required journal recovery " + "suppressed and not mounted read-only"); +- goto failed_mount_wq; ++ goto failed_mount3a; + } else { + /* Nojournal mode, all journal mount options are illegal */ +- if (test_opt2(sb, EXPLICIT_JOURNAL_CHECKSUM)) { +- ext4_msg(sb, KERN_ERR, "can't mount with " +- "journal_checksum, fs mounted w/o journal"); +- goto failed_mount_wq; +- } + if (test_opt(sb, JOURNAL_ASYNC_COMMIT)) { + ext4_msg(sb, KERN_ERR, "can't mount with " + "journal_async_commit, fs mounted w/o journal"); +- goto failed_mount_wq; ++ goto failed_mount3a; ++ } ++ ++ if (test_opt2(sb, EXPLICIT_JOURNAL_CHECKSUM)) { ++ ext4_msg(sb, KERN_ERR, "can't mount with " ++ "journal_checksum, fs mounted w/o journal"); ++ goto failed_mount3a; + } + if (sbi->s_commit_interval != JBD2_DEFAULT_MAX_COMMIT_AGE*HZ) { + ext4_msg(sb, KERN_ERR, "can't mount with " + "commit=%lu, fs mounted w/o journal", + sbi->s_commit_interval / HZ); +- goto failed_mount_wq; ++ goto failed_mount3a; + } + if (EXT4_MOUNT_DATA_FLAGS & + (sbi->s_mount_opt ^ sbi->s_def_mount_opt)) { + ext4_msg(sb, KERN_ERR, "can't mount with " + "data=, fs mounted w/o journal"); +- goto failed_mount_wq; ++ goto failed_mount3a; + } + sbi->s_def_mount_opt &= ~EXT4_MOUNT_JOURNAL_CHECKSUM; + clear_opt(sb, JOURNAL_CHECKSUM); +diff --git a/fs/hfs/inode.c b/fs/hfs/inode.c +index a0746be3c1de7..80d17c520d0ba 100644 +--- a/fs/hfs/inode.c ++++ b/fs/hfs/inode.c +@@ -458,15 +458,16 @@ int hfs_write_inode(struct inode *inode, struct writeback_control *wbc) + /* panic? */ + return -EIO; + ++ res = -EIO; + if (HFS_I(main_inode)->cat_key.CName.len > HFS_NAMELEN) +- return -EIO; ++ goto out; + fd.search_key->cat = HFS_I(main_inode)->cat_key; + if (hfs_brec_find(&fd)) +- /* panic? */ + goto out; + + if (S_ISDIR(main_inode->i_mode)) { +- WARN_ON(fd.entrylength < sizeof(struct hfs_cat_dir)); ++ if (fd.entrylength < sizeof(struct hfs_cat_dir)) ++ goto out; + hfs_bnode_read(fd.bnode, &rec, fd.entryoffset, + sizeof(struct hfs_cat_dir)); + if (rec.type != HFS_CDR_DIR || +@@ -479,6 +480,8 @@ int hfs_write_inode(struct inode *inode, struct writeback_control *wbc) + hfs_bnode_write(fd.bnode, &rec, fd.entryoffset, + sizeof(struct hfs_cat_dir)); + } else if (HFS_IS_RSRC(inode)) { ++ if (fd.entrylength < sizeof(struct hfs_cat_file)) ++ goto out; + hfs_bnode_read(fd.bnode, &rec, fd.entryoffset, + sizeof(struct hfs_cat_file)); + hfs_inode_write_fork(inode, rec.file.RExtRec, +@@ -486,7 +489,8 @@ int hfs_write_inode(struct inode *inode, struct writeback_control *wbc) + hfs_bnode_write(fd.bnode, &rec, fd.entryoffset, + sizeof(struct hfs_cat_file)); + } else { +- WARN_ON(fd.entrylength < sizeof(struct hfs_cat_file)); ++ if (fd.entrylength < sizeof(struct hfs_cat_file)) ++ goto out; + hfs_bnode_read(fd.bnode, &rec, fd.entryoffset, + sizeof(struct hfs_cat_file)); + if (rec.type != HFS_CDR_FIL || +@@ -503,9 +507,10 @@ int hfs_write_inode(struct inode *inode, struct writeback_control *wbc) + hfs_bnode_write(fd.bnode, &rec, fd.entryoffset, + sizeof(struct hfs_cat_file)); + } ++ res = 0; + out: + hfs_find_exit(&fd); +- return 0; ++ return res; + } + + static struct dentry *hfs_file_lookup(struct inode *dir, struct dentry *dentry, +diff --git a/fs/ksmbd/auth.c b/fs/ksmbd/auth.c +index c5a5c7b90d727..93b2290addd59 100644 +--- a/fs/ksmbd/auth.c ++++ b/fs/ksmbd/auth.c +@@ -322,7 +322,8 @@ int ksmbd_decode_ntlmssp_auth_blob(struct authenticate_message *authblob, + dn_off = le32_to_cpu(authblob->DomainName.BufferOffset); + dn_len = le16_to_cpu(authblob->DomainName.Length); + +- if (blob_len < (u64)dn_off + dn_len || blob_len < (u64)nt_off + nt_len) ++ if (blob_len < (u64)dn_off + dn_len || blob_len < (u64)nt_off + nt_len || ++ nt_len < CIFS_ENCPWD_SIZE) + return -EINVAL; + + /* TODO : use domain name that imported from configuration file */ +diff --git a/fs/ksmbd/connection.c b/fs/ksmbd/connection.c +index 756ad631c019a..eab9950b5a683 100644 +--- a/fs/ksmbd/connection.c ++++ b/fs/ksmbd/connection.c +@@ -310,9 +310,12 @@ int ksmbd_conn_handler_loop(void *p) + + /* 4 for rfc1002 length field */ + size = pdu_size + 4; +- conn->request_buf = kvmalloc(size, GFP_KERNEL); ++ conn->request_buf = kvmalloc(size, ++ GFP_KERNEL | ++ __GFP_NOWARN | ++ __GFP_NORETRY); + if (!conn->request_buf) +- continue; ++ break; + + memcpy(conn->request_buf, hdr_buf, sizeof(hdr_buf)); + if (!ksmbd_smb_request(conn)) +diff --git a/fs/ksmbd/smb2pdu.c b/fs/ksmbd/smb2pdu.c +index 7a9497a7b0a30..a71a7cc0e5762 100644 +--- a/fs/ksmbd/smb2pdu.c ++++ b/fs/ksmbd/smb2pdu.c +@@ -1926,13 +1926,13 @@ int smb2_tree_connect(struct ksmbd_work *work) + if (conn->posix_ext_supported) + status.tree_conn->posix_extensions = true; + +-out_err1: + rsp->StructureSize = cpu_to_le16(16); ++ inc_rfc1001_len(work->response_buf, 16); ++out_err1: + rsp->Capabilities = 0; + rsp->Reserved = 0; + /* default manual caching */ + rsp->ShareFlags = SMB2_SHAREFLAG_MANUAL_CACHING; +- inc_rfc1001_len(work->response_buf, 16); + + if (!IS_ERR(treename)) + kfree(treename); +@@ -1965,6 +1965,9 @@ out_err1: + rsp->hdr.Status = STATUS_ACCESS_DENIED; + } + ++ if (status.ret != KSMBD_TREE_CONN_STATUS_OK) ++ smb2_set_err_rsp(work); ++ + return rc; + } + +diff --git a/fs/ksmbd/transport_tcp.c b/fs/ksmbd/transport_tcp.c +index 143bba4e4db81..434891db42a2c 100644 +--- a/fs/ksmbd/transport_tcp.c ++++ b/fs/ksmbd/transport_tcp.c +@@ -295,6 +295,7 @@ static int ksmbd_tcp_readv(struct tcp_transport *t, struct kvec *iov_orig, + struct msghdr ksmbd_msg; + struct kvec *iov; + struct ksmbd_conn *conn = KSMBD_TRANS(t)->conn; ++ int max_retry = 2; + + iov = get_conn_iovec(t, nr_segs); + if (!iov) +@@ -321,9 +322,11 @@ static int ksmbd_tcp_readv(struct tcp_transport *t, struct kvec *iov_orig, + } else if (conn->status == KSMBD_SESS_NEED_RECONNECT) { + total_read = -EAGAIN; + break; +- } else if (length == -ERESTARTSYS || length == -EAGAIN) { ++ } else if ((length == -ERESTARTSYS || length == -EAGAIN) && ++ max_retry) { + usleep_range(1000, 2000); + length = 0; ++ max_retry--; + continue; + } else if (length <= 0) { + total_read = -EAGAIN; +diff --git a/fs/locks.c b/fs/locks.c +index 607f94a0e789f..7dc129cc1a267 100644 +--- a/fs/locks.c ++++ b/fs/locks.c +@@ -2669,6 +2669,29 @@ int vfs_cancel_lock(struct file *filp, struct file_lock *fl) + } + EXPORT_SYMBOL_GPL(vfs_cancel_lock); + ++/** ++ * vfs_inode_has_locks - are any file locks held on @inode? ++ * @inode: inode to check for locks ++ * ++ * Return true if there are any FL_POSIX or FL_FLOCK locks currently ++ * set on @inode. ++ */ ++bool vfs_inode_has_locks(struct inode *inode) ++{ ++ struct file_lock_context *ctx; ++ bool ret; ++ ++ ctx = smp_load_acquire(&inode->i_flctx); ++ if (!ctx) ++ return false; ++ ++ spin_lock(&ctx->flc_lock); ++ ret = !list_empty(&ctx->flc_posix) || !list_empty(&ctx->flc_flock); ++ spin_unlock(&ctx->flc_lock); ++ return ret; ++} ++EXPORT_SYMBOL_GPL(vfs_inode_has_locks); ++ + #ifdef CONFIG_PROC_FS + #include <linux/proc_fs.h> + #include <linux/seq_file.h> +diff --git a/fs/nfsd/nfs4xdr.c b/fs/nfsd/nfs4xdr.c +index 2960d0a8e8f9a..355164a527540 100644 +--- a/fs/nfsd/nfs4xdr.c ++++ b/fs/nfsd/nfs4xdr.c +@@ -3528,6 +3528,17 @@ nfsd4_encode_dirent(void *ccdv, const char *name, int namlen, + case nfserr_noent: + xdr_truncate_encode(xdr, start_offset); + goto skip_entry; ++ case nfserr_jukebox: ++ /* ++ * The pseudoroot should only display dentries that lead to ++ * exports. If we get EJUKEBOX here, then we can't tell whether ++ * this entry should be included. Just fail the whole READDIR ++ * with NFS4ERR_DELAY in that case, and hope that the situation ++ * will resolve itself by the client's next attempt. ++ */ ++ if (cd->rd_fhp->fh_export->ex_flags & NFSEXP_V4ROOT) ++ goto fail; ++ fallthrough; + default: + /* + * If the client requested the RDATTR_ERROR attribute, +diff --git a/fs/nfsd/nfssvc.c b/fs/nfsd/nfssvc.c +index 4bb5baa17040f..011c556caa1e7 100644 +--- a/fs/nfsd/nfssvc.c ++++ b/fs/nfsd/nfssvc.c +@@ -447,8 +447,8 @@ static void nfsd_shutdown_net(struct net *net) + { + struct nfsd_net *nn = net_generic(net, nfsd_net_id); + +- nfsd_file_cache_shutdown_net(net); + nfs4_state_shutdown_net(net); ++ nfsd_file_cache_shutdown_net(net); + if (nn->lockd_up) { + lockd_down(net); + nn->lockd_up = false; +diff --git a/fs/ntfs3/file.c b/fs/ntfs3/file.c +index 4f2ffc7ef296f..f31c0389a2e7d 100644 +--- a/fs/ntfs3/file.c ++++ b/fs/ntfs3/file.c +@@ -486,10 +486,10 @@ static int ntfs_truncate(struct inode *inode, loff_t new_size) + + new_valid = ntfs_up_block(sb, min_t(u64, ni->i_valid, new_size)); + +- ni_lock(ni); +- + truncate_setsize(inode, new_size); + ++ ni_lock(ni); ++ + down_write(&ni->file.run_lock); + err = attr_set_size(ni, ATTR_DATA, NULL, 0, &ni->file.run, new_size, + &new_valid, ni->mi.sbi->options->prealloc, NULL); +diff --git a/fs/udf/inode.c b/fs/udf/inode.c +index b9a83820e1adf..3c380140515da 100644 +--- a/fs/udf/inode.c ++++ b/fs/udf/inode.c +@@ -600,7 +600,7 @@ static void udf_do_extend_final_block(struct inode *inode, + */ + if (new_elen <= (last_ext->extLength & UDF_EXTENT_LENGTH_MASK)) + return; +- added_bytes = (last_ext->extLength & UDF_EXTENT_LENGTH_MASK) - new_elen; ++ added_bytes = new_elen - (last_ext->extLength & UDF_EXTENT_LENGTH_MASK); + last_ext->extLength += added_bytes; + UDF_I(inode)->i_lenExtents += added_bytes; + +diff --git a/include/linux/dsa/tag_qca.h b/include/linux/dsa/tag_qca.h +index b1b5720d89a59..ee657452f122a 100644 +--- a/include/linux/dsa/tag_qca.h ++++ b/include/linux/dsa/tag_qca.h +@@ -45,8 +45,8 @@ struct sk_buff; + QCA_HDR_MGMT_COMMAND_LEN + \ + QCA_HDR_MGMT_DATA1_LEN) + +-#define QCA_HDR_MGMT_DATA2_LEN 12 /* Other 12 byte for the mdio data */ +-#define QCA_HDR_MGMT_PADDING_LEN 34 /* Padding to reach the min Ethernet packet */ ++#define QCA_HDR_MGMT_DATA2_LEN 28 /* Other 28 byte for the mdio data */ ++#define QCA_HDR_MGMT_PADDING_LEN 18 /* Padding to reach the min Ethernet packet */ + + #define QCA_HDR_MGMT_PKT_LEN (QCA_HDR_MGMT_HEADER_LEN + \ + QCA_HDR_LEN + \ +diff --git a/include/linux/efi.h b/include/linux/efi.h +index f87b2f5db9f83..4f51616f01b21 100644 +--- a/include/linux/efi.h ++++ b/include/linux/efi.h +@@ -1139,8 +1139,6 @@ void efi_check_for_embedded_firmwares(void); + static inline void efi_check_for_embedded_firmwares(void) { } + #endif + +-efi_status_t efi_random_get_seed(void); +- + #define arch_efi_call_virt(p, f, args...) ((p)->f(args)) + + /* +diff --git a/include/linux/fs.h b/include/linux/fs.h +index 8e79a761c56c5..17a1a57adbe00 100644 +--- a/include/linux/fs.h ++++ b/include/linux/fs.h +@@ -1170,6 +1170,7 @@ extern int locks_delete_block(struct file_lock *); + extern int vfs_test_lock(struct file *, struct file_lock *); + extern int vfs_lock_file(struct file *, unsigned int, struct file_lock *, struct file_lock *); + extern int vfs_cancel_lock(struct file *filp, struct file_lock *fl); ++bool vfs_inode_has_locks(struct inode *inode); + extern int locks_lock_inode_wait(struct inode *inode, struct file_lock *fl); + extern int __break_lease(struct inode *inode, unsigned int flags, unsigned int type); + extern void lease_get_mtime(struct inode *, struct timespec64 *time); +@@ -1284,6 +1285,11 @@ static inline int vfs_cancel_lock(struct file *filp, struct file_lock *fl) + return 0; + } + ++static inline bool vfs_inode_has_locks(struct inode *inode) ++{ ++ return false; ++} ++ + static inline int locks_lock_inode_wait(struct inode *inode, struct file_lock *fl) + { + return -ENOLCK; +diff --git a/include/linux/mlx5/device.h b/include/linux/mlx5/device.h +index b5f58fd37a0f7..4b00221f57e26 100644 +--- a/include/linux/mlx5/device.h ++++ b/include/linux/mlx5/device.h +@@ -1088,6 +1088,11 @@ enum { + MLX5_VPORT_ADMIN_STATE_AUTO = 0x2, + }; + ++enum { ++ MLX5_VPORT_CVLAN_INSERT_WHEN_NO_CVLAN = 0x1, ++ MLX5_VPORT_CVLAN_INSERT_ALWAYS = 0x3, ++}; ++ + enum { + MLX5_L3_PROT_TYPE_IPV4 = 0, + MLX5_L3_PROT_TYPE_IPV6 = 1, +diff --git a/include/linux/mlx5/mlx5_ifc.h b/include/linux/mlx5/mlx5_ifc.h +index 4acd5610e96bc..e640c27b1b6df 100644 +--- a/include/linux/mlx5/mlx5_ifc.h ++++ b/include/linux/mlx5/mlx5_ifc.h +@@ -877,7 +877,8 @@ struct mlx5_ifc_e_switch_cap_bits { + u8 vport_svlan_insert[0x1]; + u8 vport_cvlan_insert_if_not_exist[0x1]; + u8 vport_cvlan_insert_overwrite[0x1]; +- u8 reserved_at_5[0x2]; ++ u8 reserved_at_5[0x1]; ++ u8 vport_cvlan_insert_always[0x1]; + u8 esw_shared_ingress_acl[0x1]; + u8 esw_uplink_ingress_acl[0x1]; + u8 root_ft_on_other_esw[0x1]; +diff --git a/include/linux/netfilter/ipset/ip_set.h b/include/linux/netfilter/ipset/ip_set.h +index ada1296c87d50..72f5ebc5c97a9 100644 +--- a/include/linux/netfilter/ipset/ip_set.h ++++ b/include/linux/netfilter/ipset/ip_set.h +@@ -197,7 +197,7 @@ struct ip_set_region { + }; + + /* Max range where every element is added/deleted in one step */ +-#define IPSET_MAX_RANGE (1<<20) ++#define IPSET_MAX_RANGE (1<<14) + + /* The max revision number supported by any set type + 1 */ + #define IPSET_REVISION_MAX 9 +diff --git a/include/linux/sunrpc/rpc_pipe_fs.h b/include/linux/sunrpc/rpc_pipe_fs.h +index cd188a527d169..3b35b6f6533aa 100644 +--- a/include/linux/sunrpc/rpc_pipe_fs.h ++++ b/include/linux/sunrpc/rpc_pipe_fs.h +@@ -92,6 +92,11 @@ extern ssize_t rpc_pipe_generic_upcall(struct file *, struct rpc_pipe_msg *, + char __user *, size_t); + extern int rpc_queue_upcall(struct rpc_pipe *, struct rpc_pipe_msg *); + ++/* returns true if the msg is in-flight, i.e., already eaten by the peer */ ++static inline bool rpc_msg_is_inflight(const struct rpc_pipe_msg *msg) { ++ return (msg->copied != 0 && list_empty(&msg->list)); ++} ++ + struct rpc_clnt; + extern struct dentry *rpc_create_client_dir(struct dentry *, const char *, struct rpc_clnt *); + extern int rpc_remove_client_dir(struct rpc_clnt *); +diff --git a/include/net/netfilter/nf_tables.h b/include/net/netfilter/nf_tables.h +index cdb7db9b0e252..1daededfa75ed 100644 +--- a/include/net/netfilter/nf_tables.h ++++ b/include/net/netfilter/nf_tables.h +@@ -311,17 +311,29 @@ struct nft_set_iter { + /** + * struct nft_set_desc - description of set elements + * ++ * @ktype: key type + * @klen: key length ++ * @dtype: data type + * @dlen: data length ++ * @objtype: object type ++ * @flags: flags + * @size: number of set elements ++ * @policy: set policy ++ * @gc_int: garbage collector interval + * @field_len: length of each field in concatenation, bytes + * @field_count: number of concatenated fields in element + * @expr: set must support for expressions + */ + struct nft_set_desc { ++ u32 ktype; + unsigned int klen; ++ u32 dtype; + unsigned int dlen; ++ u32 objtype; + unsigned int size; ++ u32 policy; ++ u32 gc_int; ++ u64 timeout; + u8 field_len[NFT_REG32_COUNT]; + u8 field_count; + bool expr; +@@ -580,7 +592,9 @@ void *nft_set_catchall_gc(const struct nft_set *set); + + static inline unsigned long nft_set_gc_interval(const struct nft_set *set) + { +- return set->gc_int ? msecs_to_jiffies(set->gc_int) : HZ; ++ u32 gc_int = READ_ONCE(set->gc_int); ++ ++ return gc_int ? msecs_to_jiffies(gc_int) : HZ; + } + + /** +@@ -1551,6 +1565,9 @@ struct nft_trans_rule { + struct nft_trans_set { + struct nft_set *set; + u32 set_id; ++ u32 gc_int; ++ u64 timeout; ++ bool update; + bool bound; + }; + +@@ -1560,6 +1577,12 @@ struct nft_trans_set { + (((struct nft_trans_set *)trans->data)->set_id) + #define nft_trans_set_bound(trans) \ + (((struct nft_trans_set *)trans->data)->bound) ++#define nft_trans_set_update(trans) \ ++ (((struct nft_trans_set *)trans->data)->update) ++#define nft_trans_set_timeout(trans) \ ++ (((struct nft_trans_set *)trans->data)->timeout) ++#define nft_trans_set_gc_int(trans) \ ++ (((struct nft_trans_set *)trans->data)->gc_int) + + struct nft_trans_chain { + bool update; +diff --git a/include/uapi/linux/btrfs.h b/include/uapi/linux/btrfs.h +index 7ada84e4a3ed1..5655e89b962be 100644 +--- a/include/uapi/linux/btrfs.h ++++ b/include/uapi/linux/btrfs.h +@@ -290,6 +290,12 @@ struct btrfs_ioctl_fs_info_args { + #define BTRFS_FEATURE_COMPAT_RO_FREE_SPACE_TREE_VALID (1ULL << 1) + #define BTRFS_FEATURE_COMPAT_RO_VERITY (1ULL << 2) + ++/* ++ * Put all block group items into a dedicated block group tree, greatly ++ * reducing mount time for large filesystem due to better locality. ++ */ ++#define BTRFS_FEATURE_COMPAT_RO_BLOCK_GROUP_TREE (1ULL << 3) ++ + #define BTRFS_FEATURE_INCOMPAT_MIXED_BACKREF (1ULL << 0) + #define BTRFS_FEATURE_INCOMPAT_DEFAULT_SUBVOL (1ULL << 1) + #define BTRFS_FEATURE_INCOMPAT_MIXED_GROUPS (1ULL << 2) +diff --git a/io_uring/io_uring.c b/io_uring/io_uring.c +index b8a39be3bcb4c..9c49a1a4cedaa 100644 +--- a/io_uring/io_uring.c ++++ b/io_uring/io_uring.c +@@ -2206,7 +2206,7 @@ int io_run_task_work_sig(void) + /* when returns >0, the caller should retry */ + static inline int io_cqring_wait_schedule(struct io_ring_ctx *ctx, + struct io_wait_queue *iowq, +- ktime_t timeout) ++ ktime_t *timeout) + { + int ret; + unsigned long check_cq; +@@ -2224,7 +2224,7 @@ static inline int io_cqring_wait_schedule(struct io_ring_ctx *ctx, + if (check_cq & BIT(IO_CHECK_CQ_DROPPED_BIT)) + return -EBADR; + } +- if (!schedule_hrtimeout(&timeout, HRTIMER_MODE_ABS)) ++ if (!schedule_hrtimeout(timeout, HRTIMER_MODE_ABS)) + return -ETIME; + return 1; + } +@@ -2289,7 +2289,7 @@ static int io_cqring_wait(struct io_ring_ctx *ctx, int min_events, + } + prepare_to_wait_exclusive(&ctx->cq_wait, &iowq.wq, + TASK_INTERRUPTIBLE); +- ret = io_cqring_wait_schedule(ctx, &iowq, timeout); ++ ret = io_cqring_wait_schedule(ctx, &iowq, &timeout); + cond_resched(); + } while (ret > 0); + +@@ -3725,8 +3725,6 @@ static int __io_uring_register(struct io_ring_ctx *ctx, unsigned opcode, + return -EEXIST; + + if (ctx->restricted) { +- if (opcode >= IORING_REGISTER_LAST) +- return -EINVAL; + opcode = array_index_nospec(opcode, IORING_REGISTER_LAST); + if (!test_bit(opcode, ctx->restrictions.register_op)) + return -EACCES; +@@ -3882,6 +3880,9 @@ SYSCALL_DEFINE4(io_uring_register, unsigned int, fd, unsigned int, opcode, + long ret = -EBADF; + struct fd f; + ++ if (opcode >= IORING_REGISTER_LAST) ++ return -EINVAL; ++ + f = fdget(fd); + if (!f.file) + return -EBADF; +diff --git a/kernel/bpf/trampoline.c b/kernel/bpf/trampoline.c +index 41b67eb83ab3f..2fb6d8e196e69 100644 +--- a/kernel/bpf/trampoline.c ++++ b/kernel/bpf/trampoline.c +@@ -501,6 +501,10 @@ again: + /* reset fops->func and fops->trampoline for re-register */ + tr->fops->func = NULL; + tr->fops->trampoline = 0; ++ ++ /* reset im->image memory attr for arch_prepare_bpf_trampoline */ ++ set_memory_nx((long)im->image, 1); ++ set_memory_rw((long)im->image, 1); + goto again; + } + #endif +diff --git a/net/9p/client.c b/net/9p/client.c +index 8464d95805d08..1f50dce8765d5 100644 +--- a/net/9p/client.c ++++ b/net/9p/client.c +@@ -425,7 +425,7 @@ void p9_client_cb(struct p9_client *c, struct p9_req_t *req, int status) + * the status change is visible to another thread + */ + smp_wmb(); +- req->status = status; ++ WRITE_ONCE(req->status, status); + + wake_up(&req->wq); + p9_debug(P9_DEBUG_MUX, "wakeup: %d\n", req->tc.tag); +@@ -587,7 +587,7 @@ static int p9_client_flush(struct p9_client *c, struct p9_req_t *oldreq) + /* if we haven't received a response for oldreq, + * remove it from the list + */ +- if (oldreq->status == REQ_STATUS_SENT) { ++ if (READ_ONCE(oldreq->status) == REQ_STATUS_SENT) { + if (c->trans_mod->cancelled) + c->trans_mod->cancelled(c, oldreq); + } +@@ -672,7 +672,8 @@ p9_client_rpc(struct p9_client *c, int8_t type, const char *fmt, ...) + } + again: + /* Wait for the response */ +- err = wait_event_killable(req->wq, req->status >= REQ_STATUS_RCVD); ++ err = wait_event_killable(req->wq, ++ READ_ONCE(req->status) >= REQ_STATUS_RCVD); + + /* Make sure our req is coherent with regard to updates in other + * threads - echoes to wmb() in the callback +@@ -686,7 +687,7 @@ again: + goto again; + } + +- if (req->status == REQ_STATUS_ERROR) { ++ if (READ_ONCE(req->status) == REQ_STATUS_ERROR) { + p9_debug(P9_DEBUG_ERROR, "req_status error %d\n", req->t_err); + err = req->t_err; + } +@@ -699,7 +700,7 @@ again: + p9_client_flush(c, req); + + /* if we received the response anyway, don't signal error */ +- if (req->status == REQ_STATUS_RCVD) ++ if (READ_ONCE(req->status) == REQ_STATUS_RCVD) + err = 0; + } + recalc_sigpending: +@@ -768,7 +769,7 @@ static struct p9_req_t *p9_client_zc_rpc(struct p9_client *c, int8_t type, + if (err != -ERESTARTSYS) + goto recalc_sigpending; + } +- if (req->status == REQ_STATUS_ERROR) { ++ if (READ_ONCE(req->status) == REQ_STATUS_ERROR) { + p9_debug(P9_DEBUG_ERROR, "req_status error %d\n", req->t_err); + err = req->t_err; + } +@@ -781,7 +782,7 @@ static struct p9_req_t *p9_client_zc_rpc(struct p9_client *c, int8_t type, + p9_client_flush(c, req); + + /* if we received the response anyway, don't signal error */ +- if (req->status == REQ_STATUS_RCVD) ++ if (READ_ONCE(req->status) == REQ_STATUS_RCVD) + err = 0; + } + recalc_sigpending: +diff --git a/net/9p/trans_fd.c b/net/9p/trans_fd.c +index 080b5de3e1ed8..a2eb1363d293b 100644 +--- a/net/9p/trans_fd.c ++++ b/net/9p/trans_fd.c +@@ -202,11 +202,11 @@ static void p9_conn_cancel(struct p9_conn *m, int err) + + list_for_each_entry_safe(req, rtmp, &m->req_list, req_list) { + list_move(&req->req_list, &cancel_list); +- req->status = REQ_STATUS_ERROR; ++ WRITE_ONCE(req->status, REQ_STATUS_ERROR); + } + list_for_each_entry_safe(req, rtmp, &m->unsent_req_list, req_list) { + list_move(&req->req_list, &cancel_list); +- req->status = REQ_STATUS_ERROR; ++ WRITE_ONCE(req->status, REQ_STATUS_ERROR); + } + + spin_unlock(&m->req_lock); +@@ -467,7 +467,7 @@ static void p9_write_work(struct work_struct *work) + + req = list_entry(m->unsent_req_list.next, struct p9_req_t, + req_list); +- req->status = REQ_STATUS_SENT; ++ WRITE_ONCE(req->status, REQ_STATUS_SENT); + p9_debug(P9_DEBUG_TRANS, "move req %p\n", req); + list_move_tail(&req->req_list, &m->req_list); + +@@ -676,7 +676,7 @@ static int p9_fd_request(struct p9_client *client, struct p9_req_t *req) + return m->err; + + spin_lock(&m->req_lock); +- req->status = REQ_STATUS_UNSENT; ++ WRITE_ONCE(req->status, REQ_STATUS_UNSENT); + list_add_tail(&req->req_list, &m->unsent_req_list); + spin_unlock(&m->req_lock); + +@@ -703,7 +703,7 @@ static int p9_fd_cancel(struct p9_client *client, struct p9_req_t *req) + + if (req->status == REQ_STATUS_UNSENT) { + list_del(&req->req_list); +- req->status = REQ_STATUS_FLSHD; ++ WRITE_ONCE(req->status, REQ_STATUS_FLSHD); + p9_req_put(client, req); + ret = 0; + } +@@ -732,7 +732,7 @@ static int p9_fd_cancelled(struct p9_client *client, struct p9_req_t *req) + * remove it from the list. + */ + list_del(&req->req_list); +- req->status = REQ_STATUS_FLSHD; ++ WRITE_ONCE(req->status, REQ_STATUS_FLSHD); + spin_unlock(&m->req_lock); + + p9_req_put(client, req); +diff --git a/net/9p/trans_rdma.c b/net/9p/trans_rdma.c +index d817d3745238b..d8b0a6f3b15e5 100644 +--- a/net/9p/trans_rdma.c ++++ b/net/9p/trans_rdma.c +@@ -507,7 +507,7 @@ dont_need_post_recv: + * because doing if after could erase the REQ_STATUS_RCVD + * status in case of a very fast reply. + */ +- req->status = REQ_STATUS_SENT; ++ WRITE_ONCE(req->status, REQ_STATUS_SENT); + err = ib_post_send(rdma->qp, &wr, NULL); + if (err) + goto send_error; +@@ -517,7 +517,7 @@ dont_need_post_recv: + + /* Handle errors that happened during or while preparing the send: */ + send_error: +- req->status = REQ_STATUS_ERROR; ++ WRITE_ONCE(req->status, REQ_STATUS_ERROR); + kfree(c); + p9_debug(P9_DEBUG_ERROR, "Error %d in rdma_request()\n", err); + +diff --git a/net/9p/trans_virtio.c b/net/9p/trans_virtio.c +index b84d35cf68994..947c038a0470c 100644 +--- a/net/9p/trans_virtio.c ++++ b/net/9p/trans_virtio.c +@@ -263,7 +263,7 @@ p9_virtio_request(struct p9_client *client, struct p9_req_t *req) + + p9_debug(P9_DEBUG_TRANS, "9p debug: virtio request\n"); + +- req->status = REQ_STATUS_SENT; ++ WRITE_ONCE(req->status, REQ_STATUS_SENT); + req_retry: + spin_lock_irqsave(&chan->lock, flags); + +@@ -469,7 +469,7 @@ p9_virtio_zc_request(struct p9_client *client, struct p9_req_t *req, + inlen = n; + } + } +- req->status = REQ_STATUS_SENT; ++ WRITE_ONCE(req->status, REQ_STATUS_SENT); + req_retry_pinned: + spin_lock_irqsave(&chan->lock, flags); + +@@ -532,9 +532,10 @@ req_retry_pinned: + spin_unlock_irqrestore(&chan->lock, flags); + kicked = 1; + p9_debug(P9_DEBUG_TRANS, "virtio request kicked\n"); +- err = wait_event_killable(req->wq, req->status >= REQ_STATUS_RCVD); ++ err = wait_event_killable(req->wq, ++ READ_ONCE(req->status) >= REQ_STATUS_RCVD); + // RERROR needs reply (== error string) in static data +- if (req->status == REQ_STATUS_RCVD && ++ if (READ_ONCE(req->status) == REQ_STATUS_RCVD && + unlikely(req->rc.sdata[4] == P9_RERROR)) + handle_rerror(req, in_hdr_len, offs, in_pages); + +diff --git a/net/9p/trans_xen.c b/net/9p/trans_xen.c +index 0f862d5a59601..a103aed854658 100644 +--- a/net/9p/trans_xen.c ++++ b/net/9p/trans_xen.c +@@ -157,7 +157,7 @@ again: + &masked_prod, masked_cons, + XEN_9PFS_RING_SIZE(ring)); + +- p9_req->status = REQ_STATUS_SENT; ++ WRITE_ONCE(p9_req->status, REQ_STATUS_SENT); + virt_wmb(); /* write ring before updating pointer */ + prod += size; + ring->intf->out_prod = prod; +@@ -212,7 +212,7 @@ static void p9_xen_response(struct work_struct *work) + dev_warn(&priv->dev->dev, + "requested packet size too big: %d for tag %d with capacity %zd\n", + h.size, h.tag, req->rc.capacity); +- req->status = REQ_STATUS_ERROR; ++ WRITE_ONCE(req->status, REQ_STATUS_ERROR); + goto recv_error; + } + +diff --git a/net/caif/cfctrl.c b/net/caif/cfctrl.c +index 2809cbd6b7f74..d8cb4b2a076b4 100644 +--- a/net/caif/cfctrl.c ++++ b/net/caif/cfctrl.c +@@ -269,11 +269,15 @@ int cfctrl_linkup_request(struct cflayer *layer, + default: + pr_warn("Request setup of bad link type = %d\n", + param->linktype); ++ cfpkt_destroy(pkt); + return -EINVAL; + } + req = kzalloc(sizeof(*req), GFP_KERNEL); +- if (!req) ++ if (!req) { ++ cfpkt_destroy(pkt); + return -ENOMEM; ++ } ++ + req->client_layer = user_layer; + req->cmd = CFCTRL_CMD_LINK_SETUP; + req->param = *param; +diff --git a/net/core/filter.c b/net/core/filter.c +index 3aae1885b9702..50d685be517d5 100644 +--- a/net/core/filter.c ++++ b/net/core/filter.c +@@ -3182,15 +3182,18 @@ static int bpf_skb_generic_push(struct sk_buff *skb, u32 off, u32 len) + + static int bpf_skb_generic_pop(struct sk_buff *skb, u32 off, u32 len) + { ++ void *old_data; ++ + /* skb_ensure_writable() is not needed here, as we're + * already working on an uncloned skb. + */ + if (unlikely(!pskb_may_pull(skb, off + len))) + return -ENOMEM; + +- skb_postpull_rcsum(skb, skb->data + off, len); +- memmove(skb->data + len, skb->data, off); ++ old_data = skb->data; + __skb_pull(skb, len); ++ skb_postpull_rcsum(skb, old_data + off, len); ++ memmove(skb->data, old_data, off); + + return 0; + } +diff --git a/net/ipv4/inet_connection_sock.c b/net/ipv4/inet_connection_sock.c +index 971969cc7e17f..fb01211a255b0 100644 +--- a/net/ipv4/inet_connection_sock.c ++++ b/net/ipv4/inet_connection_sock.c +@@ -1037,12 +1037,26 @@ void inet_csk_prepare_forced_close(struct sock *sk) + } + EXPORT_SYMBOL(inet_csk_prepare_forced_close); + ++static int inet_ulp_can_listen(const struct sock *sk) ++{ ++ const struct inet_connection_sock *icsk = inet_csk(sk); ++ ++ if (icsk->icsk_ulp_ops && !icsk->icsk_ulp_ops->clone) ++ return -EINVAL; ++ ++ return 0; ++} ++ + int inet_csk_listen_start(struct sock *sk) + { + struct inet_connection_sock *icsk = inet_csk(sk); + struct inet_sock *inet = inet_sk(sk); + int err; + ++ err = inet_ulp_can_listen(sk); ++ if (unlikely(err)) ++ return err; ++ + reqsk_queue_alloc(&icsk->icsk_accept_queue); + + sk->sk_ack_backlog = 0; +diff --git a/net/ipv4/tcp_ulp.c b/net/ipv4/tcp_ulp.c +index 9ae50b1bd8444..05b6077b9f2c3 100644 +--- a/net/ipv4/tcp_ulp.c ++++ b/net/ipv4/tcp_ulp.c +@@ -139,6 +139,10 @@ static int __tcp_set_ulp(struct sock *sk, const struct tcp_ulp_ops *ulp_ops) + if (sk->sk_socket) + clear_bit(SOCK_SUPPORT_ZC, &sk->sk_socket->flags); + ++ err = -EINVAL; ++ if (!ulp_ops->clone && sk->sk_state == TCP_LISTEN) ++ goto out_err; ++ + err = ulp_ops->init(sk); + if (err) + goto out_err; +diff --git a/net/mptcp/protocol.c b/net/mptcp/protocol.c +index 42d5e0a7952ae..a2cc25cca33e1 100644 +--- a/net/mptcp/protocol.c ++++ b/net/mptcp/protocol.c +@@ -2310,7 +2310,7 @@ static void __mptcp_close_ssk(struct sock *sk, struct sock *ssk, + /* otherwise tcp will dispose of the ssk and subflow ctx */ + if (ssk->sk_state == TCP_LISTEN) { + tcp_set_state(ssk, TCP_CLOSE); +- mptcp_subflow_queue_clean(ssk); ++ mptcp_subflow_queue_clean(sk, ssk); + inet_csk_listen_stop(ssk); + } + __tcp_close(ssk, 0); +diff --git a/net/mptcp/protocol.h b/net/mptcp/protocol.h +index c1eaa16855921..df6937c8cf544 100644 +--- a/net/mptcp/protocol.h ++++ b/net/mptcp/protocol.h +@@ -610,7 +610,7 @@ void mptcp_close_ssk(struct sock *sk, struct sock *ssk, + struct mptcp_subflow_context *subflow); + void __mptcp_subflow_send_ack(struct sock *ssk); + void mptcp_subflow_reset(struct sock *ssk); +-void mptcp_subflow_queue_clean(struct sock *ssk); ++void mptcp_subflow_queue_clean(struct sock *sk, struct sock *ssk); + void mptcp_sock_graft(struct sock *sk, struct socket *parent); + struct socket *__mptcp_nmpc_socket(const struct mptcp_sock *msk); + bool __mptcp_close(struct sock *sk, long timeout); +diff --git a/net/mptcp/subflow.c b/net/mptcp/subflow.c +index 613f515fedf0a..9d3701fdb2937 100644 +--- a/net/mptcp/subflow.c ++++ b/net/mptcp/subflow.c +@@ -1733,7 +1733,7 @@ static void subflow_state_change(struct sock *sk) + } + } + +-void mptcp_subflow_queue_clean(struct sock *listener_ssk) ++void mptcp_subflow_queue_clean(struct sock *listener_sk, struct sock *listener_ssk) + { + struct request_sock_queue *queue = &inet_csk(listener_ssk)->icsk_accept_queue; + struct mptcp_sock *msk, *next, *head = NULL; +@@ -1782,8 +1782,23 @@ void mptcp_subflow_queue_clean(struct sock *listener_ssk) + + do_cancel_work = __mptcp_close(sk, 0); + release_sock(sk); +- if (do_cancel_work) ++ if (do_cancel_work) { ++ /* lockdep will report a false positive ABBA deadlock ++ * between cancel_work_sync and the listener socket. ++ * The involved locks belong to different sockets WRT ++ * the existing AB chain. ++ * Using a per socket key is problematic as key ++ * deregistration requires process context and must be ++ * performed at socket disposal time, in atomic ++ * context. ++ * Just tell lockdep to consider the listener socket ++ * released here. ++ */ ++ mutex_release(&listener_sk->sk_lock.dep_map, _RET_IP_); + mptcp_cancel_work(sk); ++ mutex_acquire(&listener_sk->sk_lock.dep_map, ++ SINGLE_DEPTH_NESTING, 0, _RET_IP_); ++ } + sock_put(sk); + } + +diff --git a/net/netfilter/ipset/ip_set_core.c b/net/netfilter/ipset/ip_set_core.c +index 6b31746f9be3b..751ac89b07a56 100644 +--- a/net/netfilter/ipset/ip_set_core.c ++++ b/net/netfilter/ipset/ip_set_core.c +@@ -1698,9 +1698,10 @@ call_ad(struct net *net, struct sock *ctnl, struct sk_buff *skb, + ret = set->variant->uadt(set, tb, adt, &lineno, flags, retried); + ip_set_unlock(set); + retried = true; +- } while (ret == -EAGAIN && +- set->variant->resize && +- (ret = set->variant->resize(set, retried)) == 0); ++ } while (ret == -ERANGE || ++ (ret == -EAGAIN && ++ set->variant->resize && ++ (ret = set->variant->resize(set, retried)) == 0)); + + if (!ret || (ret == -IPSET_ERR_EXIST && eexist)) + return 0; +diff --git a/net/netfilter/ipset/ip_set_hash_ip.c b/net/netfilter/ipset/ip_set_hash_ip.c +index 75d556d71652d..24adcdd7a0b16 100644 +--- a/net/netfilter/ipset/ip_set_hash_ip.c ++++ b/net/netfilter/ipset/ip_set_hash_ip.c +@@ -98,11 +98,11 @@ static int + hash_ip4_uadt(struct ip_set *set, struct nlattr *tb[], + enum ipset_adt adt, u32 *lineno, u32 flags, bool retried) + { +- const struct hash_ip4 *h = set->data; ++ struct hash_ip4 *h = set->data; + ipset_adtfn adtfn = set->variant->adt[adt]; + struct hash_ip4_elem e = { 0 }; + struct ip_set_ext ext = IP_SET_INIT_UEXT(set); +- u32 ip = 0, ip_to = 0, hosts; ++ u32 ip = 0, ip_to = 0, hosts, i = 0; + int ret = 0; + + if (tb[IPSET_ATTR_LINENO]) +@@ -147,14 +147,14 @@ hash_ip4_uadt(struct ip_set *set, struct nlattr *tb[], + + hosts = h->netmask == 32 ? 1 : 2 << (32 - h->netmask - 1); + +- /* 64bit division is not allowed on 32bit */ +- if (((u64)ip_to - ip + 1) >> (32 - h->netmask) > IPSET_MAX_RANGE) +- return -ERANGE; +- + if (retried) + ip = ntohl(h->next.ip); +- for (; ip <= ip_to;) { ++ for (; ip <= ip_to; i++) { + e.ip = htonl(ip); ++ if (i > IPSET_MAX_RANGE) { ++ hash_ip4_data_next(&h->next, &e); ++ return -ERANGE; ++ } + ret = adtfn(set, &e, &ext, &ext, flags); + if (ret && !ip_set_eexist(ret, flags)) + return ret; +diff --git a/net/netfilter/ipset/ip_set_hash_ipmark.c b/net/netfilter/ipset/ip_set_hash_ipmark.c +index 153de3457423e..a22ec1a6f6ec8 100644 +--- a/net/netfilter/ipset/ip_set_hash_ipmark.c ++++ b/net/netfilter/ipset/ip_set_hash_ipmark.c +@@ -97,11 +97,11 @@ static int + hash_ipmark4_uadt(struct ip_set *set, struct nlattr *tb[], + enum ipset_adt adt, u32 *lineno, u32 flags, bool retried) + { +- const struct hash_ipmark4 *h = set->data; ++ struct hash_ipmark4 *h = set->data; + ipset_adtfn adtfn = set->variant->adt[adt]; + struct hash_ipmark4_elem e = { }; + struct ip_set_ext ext = IP_SET_INIT_UEXT(set); +- u32 ip, ip_to = 0; ++ u32 ip, ip_to = 0, i = 0; + int ret; + + if (tb[IPSET_ATTR_LINENO]) +@@ -148,13 +148,14 @@ hash_ipmark4_uadt(struct ip_set *set, struct nlattr *tb[], + ip_set_mask_from_to(ip, ip_to, cidr); + } + +- if (((u64)ip_to - ip + 1) > IPSET_MAX_RANGE) +- return -ERANGE; +- + if (retried) + ip = ntohl(h->next.ip); +- for (; ip <= ip_to; ip++) { ++ for (; ip <= ip_to; ip++, i++) { + e.ip = htonl(ip); ++ if (i > IPSET_MAX_RANGE) { ++ hash_ipmark4_data_next(&h->next, &e); ++ return -ERANGE; ++ } + ret = adtfn(set, &e, &ext, &ext, flags); + + if (ret && !ip_set_eexist(ret, flags)) +diff --git a/net/netfilter/ipset/ip_set_hash_ipport.c b/net/netfilter/ipset/ip_set_hash_ipport.c +index 7303138e46be1..10481760a9b25 100644 +--- a/net/netfilter/ipset/ip_set_hash_ipport.c ++++ b/net/netfilter/ipset/ip_set_hash_ipport.c +@@ -105,11 +105,11 @@ static int + hash_ipport4_uadt(struct ip_set *set, struct nlattr *tb[], + enum ipset_adt adt, u32 *lineno, u32 flags, bool retried) + { +- const struct hash_ipport4 *h = set->data; ++ struct hash_ipport4 *h = set->data; + ipset_adtfn adtfn = set->variant->adt[adt]; + struct hash_ipport4_elem e = { .ip = 0 }; + struct ip_set_ext ext = IP_SET_INIT_UEXT(set); +- u32 ip, ip_to = 0, p = 0, port, port_to; ++ u32 ip, ip_to = 0, p = 0, port, port_to, i = 0; + bool with_ports = false; + int ret; + +@@ -173,17 +173,18 @@ hash_ipport4_uadt(struct ip_set *set, struct nlattr *tb[], + swap(port, port_to); + } + +- if (((u64)ip_to - ip + 1)*(port_to - port + 1) > IPSET_MAX_RANGE) +- return -ERANGE; +- + if (retried) + ip = ntohl(h->next.ip); + for (; ip <= ip_to; ip++) { + p = retried && ip == ntohl(h->next.ip) ? ntohs(h->next.port) + : port; +- for (; p <= port_to; p++) { ++ for (; p <= port_to; p++, i++) { + e.ip = htonl(ip); + e.port = htons(p); ++ if (i > IPSET_MAX_RANGE) { ++ hash_ipport4_data_next(&h->next, &e); ++ return -ERANGE; ++ } + ret = adtfn(set, &e, &ext, &ext, flags); + + if (ret && !ip_set_eexist(ret, flags)) +diff --git a/net/netfilter/ipset/ip_set_hash_ipportip.c b/net/netfilter/ipset/ip_set_hash_ipportip.c +index 334fb1ad0e86c..39a01934b1536 100644 +--- a/net/netfilter/ipset/ip_set_hash_ipportip.c ++++ b/net/netfilter/ipset/ip_set_hash_ipportip.c +@@ -108,11 +108,11 @@ static int + hash_ipportip4_uadt(struct ip_set *set, struct nlattr *tb[], + enum ipset_adt adt, u32 *lineno, u32 flags, bool retried) + { +- const struct hash_ipportip4 *h = set->data; ++ struct hash_ipportip4 *h = set->data; + ipset_adtfn adtfn = set->variant->adt[adt]; + struct hash_ipportip4_elem e = { .ip = 0 }; + struct ip_set_ext ext = IP_SET_INIT_UEXT(set); +- u32 ip, ip_to = 0, p = 0, port, port_to; ++ u32 ip, ip_to = 0, p = 0, port, port_to, i = 0; + bool with_ports = false; + int ret; + +@@ -180,17 +180,18 @@ hash_ipportip4_uadt(struct ip_set *set, struct nlattr *tb[], + swap(port, port_to); + } + +- if (((u64)ip_to - ip + 1)*(port_to - port + 1) > IPSET_MAX_RANGE) +- return -ERANGE; +- + if (retried) + ip = ntohl(h->next.ip); + for (; ip <= ip_to; ip++) { + p = retried && ip == ntohl(h->next.ip) ? ntohs(h->next.port) + : port; +- for (; p <= port_to; p++) { ++ for (; p <= port_to; p++, i++) { + e.ip = htonl(ip); + e.port = htons(p); ++ if (i > IPSET_MAX_RANGE) { ++ hash_ipportip4_data_next(&h->next, &e); ++ return -ERANGE; ++ } + ret = adtfn(set, &e, &ext, &ext, flags); + + if (ret && !ip_set_eexist(ret, flags)) +diff --git a/net/netfilter/ipset/ip_set_hash_ipportnet.c b/net/netfilter/ipset/ip_set_hash_ipportnet.c +index 7df94f437f600..5c6de605a9fb7 100644 +--- a/net/netfilter/ipset/ip_set_hash_ipportnet.c ++++ b/net/netfilter/ipset/ip_set_hash_ipportnet.c +@@ -160,12 +160,12 @@ static int + hash_ipportnet4_uadt(struct ip_set *set, struct nlattr *tb[], + enum ipset_adt adt, u32 *lineno, u32 flags, bool retried) + { +- const struct hash_ipportnet4 *h = set->data; ++ struct hash_ipportnet4 *h = set->data; + ipset_adtfn adtfn = set->variant->adt[adt]; + struct hash_ipportnet4_elem e = { .cidr = HOST_MASK - 1 }; + struct ip_set_ext ext = IP_SET_INIT_UEXT(set); + u32 ip = 0, ip_to = 0, p = 0, port, port_to; +- u32 ip2_from = 0, ip2_to = 0, ip2; ++ u32 ip2_from = 0, ip2_to = 0, ip2, i = 0; + bool with_ports = false; + u8 cidr; + int ret; +@@ -253,9 +253,6 @@ hash_ipportnet4_uadt(struct ip_set *set, struct nlattr *tb[], + swap(port, port_to); + } + +- if (((u64)ip_to - ip + 1)*(port_to - port + 1) > IPSET_MAX_RANGE) +- return -ERANGE; +- + ip2_to = ip2_from; + if (tb[IPSET_ATTR_IP2_TO]) { + ret = ip_set_get_hostipaddr4(tb[IPSET_ATTR_IP2_TO], &ip2_to); +@@ -282,9 +279,15 @@ hash_ipportnet4_uadt(struct ip_set *set, struct nlattr *tb[], + for (; p <= port_to; p++) { + e.port = htons(p); + do { ++ i++; + e.ip2 = htonl(ip2); + ip2 = ip_set_range_to_cidr(ip2, ip2_to, &cidr); + e.cidr = cidr - 1; ++ if (i > IPSET_MAX_RANGE) { ++ hash_ipportnet4_data_next(&h->next, ++ &e); ++ return -ERANGE; ++ } + ret = adtfn(set, &e, &ext, &ext, flags); + + if (ret && !ip_set_eexist(ret, flags)) +diff --git a/net/netfilter/ipset/ip_set_hash_net.c b/net/netfilter/ipset/ip_set_hash_net.c +index 1422739d9aa25..ce0a9ce5a91f1 100644 +--- a/net/netfilter/ipset/ip_set_hash_net.c ++++ b/net/netfilter/ipset/ip_set_hash_net.c +@@ -136,11 +136,11 @@ static int + hash_net4_uadt(struct ip_set *set, struct nlattr *tb[], + enum ipset_adt adt, u32 *lineno, u32 flags, bool retried) + { +- const struct hash_net4 *h = set->data; ++ struct hash_net4 *h = set->data; + ipset_adtfn adtfn = set->variant->adt[adt]; + struct hash_net4_elem e = { .cidr = HOST_MASK }; + struct ip_set_ext ext = IP_SET_INIT_UEXT(set); +- u32 ip = 0, ip_to = 0, ipn, n = 0; ++ u32 ip = 0, ip_to = 0, i = 0; + int ret; + + if (tb[IPSET_ATTR_LINENO]) +@@ -188,19 +188,16 @@ hash_net4_uadt(struct ip_set *set, struct nlattr *tb[], + if (ip + UINT_MAX == ip_to) + return -IPSET_ERR_HASH_RANGE; + } +- ipn = ip; +- do { +- ipn = ip_set_range_to_cidr(ipn, ip_to, &e.cidr); +- n++; +- } while (ipn++ < ip_to); +- +- if (n > IPSET_MAX_RANGE) +- return -ERANGE; + + if (retried) + ip = ntohl(h->next.ip); + do { ++ i++; + e.ip = htonl(ip); ++ if (i > IPSET_MAX_RANGE) { ++ hash_net4_data_next(&h->next, &e); ++ return -ERANGE; ++ } + ip = ip_set_range_to_cidr(ip, ip_to, &e.cidr); + ret = adtfn(set, &e, &ext, &ext, flags); + if (ret && !ip_set_eexist(ret, flags)) +diff --git a/net/netfilter/ipset/ip_set_hash_netiface.c b/net/netfilter/ipset/ip_set_hash_netiface.c +index 9810f5bf63f5e..0310732862362 100644 +--- a/net/netfilter/ipset/ip_set_hash_netiface.c ++++ b/net/netfilter/ipset/ip_set_hash_netiface.c +@@ -202,7 +202,7 @@ hash_netiface4_uadt(struct ip_set *set, struct nlattr *tb[], + ipset_adtfn adtfn = set->variant->adt[adt]; + struct hash_netiface4_elem e = { .cidr = HOST_MASK, .elem = 1 }; + struct ip_set_ext ext = IP_SET_INIT_UEXT(set); +- u32 ip = 0, ip_to = 0, ipn, n = 0; ++ u32 ip = 0, ip_to = 0, i = 0; + int ret; + + if (tb[IPSET_ATTR_LINENO]) +@@ -256,19 +256,16 @@ hash_netiface4_uadt(struct ip_set *set, struct nlattr *tb[], + } else { + ip_set_mask_from_to(ip, ip_to, e.cidr); + } +- ipn = ip; +- do { +- ipn = ip_set_range_to_cidr(ipn, ip_to, &e.cidr); +- n++; +- } while (ipn++ < ip_to); +- +- if (n > IPSET_MAX_RANGE) +- return -ERANGE; + + if (retried) + ip = ntohl(h->next.ip); + do { ++ i++; + e.ip = htonl(ip); ++ if (i > IPSET_MAX_RANGE) { ++ hash_netiface4_data_next(&h->next, &e); ++ return -ERANGE; ++ } + ip = ip_set_range_to_cidr(ip, ip_to, &e.cidr); + ret = adtfn(set, &e, &ext, &ext, flags); + +diff --git a/net/netfilter/ipset/ip_set_hash_netnet.c b/net/netfilter/ipset/ip_set_hash_netnet.c +index 3d09eefe998a7..c07b70bf32db4 100644 +--- a/net/netfilter/ipset/ip_set_hash_netnet.c ++++ b/net/netfilter/ipset/ip_set_hash_netnet.c +@@ -163,13 +163,12 @@ static int + hash_netnet4_uadt(struct ip_set *set, struct nlattr *tb[], + enum ipset_adt adt, u32 *lineno, u32 flags, bool retried) + { +- const struct hash_netnet4 *h = set->data; ++ struct hash_netnet4 *h = set->data; + ipset_adtfn adtfn = set->variant->adt[adt]; + struct hash_netnet4_elem e = { }; + struct ip_set_ext ext = IP_SET_INIT_UEXT(set); + u32 ip = 0, ip_to = 0; +- u32 ip2 = 0, ip2_from = 0, ip2_to = 0, ipn; +- u64 n = 0, m = 0; ++ u32 ip2 = 0, ip2_from = 0, ip2_to = 0, i = 0; + int ret; + + if (tb[IPSET_ATTR_LINENO]) +@@ -245,19 +244,6 @@ hash_netnet4_uadt(struct ip_set *set, struct nlattr *tb[], + } else { + ip_set_mask_from_to(ip2_from, ip2_to, e.cidr[1]); + } +- ipn = ip; +- do { +- ipn = ip_set_range_to_cidr(ipn, ip_to, &e.cidr[0]); +- n++; +- } while (ipn++ < ip_to); +- ipn = ip2_from; +- do { +- ipn = ip_set_range_to_cidr(ipn, ip2_to, &e.cidr[1]); +- m++; +- } while (ipn++ < ip2_to); +- +- if (n*m > IPSET_MAX_RANGE) +- return -ERANGE; + + if (retried) { + ip = ntohl(h->next.ip[0]); +@@ -270,7 +256,12 @@ hash_netnet4_uadt(struct ip_set *set, struct nlattr *tb[], + e.ip[0] = htonl(ip); + ip = ip_set_range_to_cidr(ip, ip_to, &e.cidr[0]); + do { ++ i++; + e.ip[1] = htonl(ip2); ++ if (i > IPSET_MAX_RANGE) { ++ hash_netnet4_data_next(&h->next, &e); ++ return -ERANGE; ++ } + ip2 = ip_set_range_to_cidr(ip2, ip2_to, &e.cidr[1]); + ret = adtfn(set, &e, &ext, &ext, flags); + if (ret && !ip_set_eexist(ret, flags)) +diff --git a/net/netfilter/ipset/ip_set_hash_netport.c b/net/netfilter/ipset/ip_set_hash_netport.c +index 09cf72eb37f8d..d1a0628df4ef3 100644 +--- a/net/netfilter/ipset/ip_set_hash_netport.c ++++ b/net/netfilter/ipset/ip_set_hash_netport.c +@@ -154,12 +154,11 @@ static int + hash_netport4_uadt(struct ip_set *set, struct nlattr *tb[], + enum ipset_adt adt, u32 *lineno, u32 flags, bool retried) + { +- const struct hash_netport4 *h = set->data; ++ struct hash_netport4 *h = set->data; + ipset_adtfn adtfn = set->variant->adt[adt]; + struct hash_netport4_elem e = { .cidr = HOST_MASK - 1 }; + struct ip_set_ext ext = IP_SET_INIT_UEXT(set); +- u32 port, port_to, p = 0, ip = 0, ip_to = 0, ipn; +- u64 n = 0; ++ u32 port, port_to, p = 0, ip = 0, ip_to = 0, i = 0; + bool with_ports = false; + u8 cidr; + int ret; +@@ -236,14 +235,6 @@ hash_netport4_uadt(struct ip_set *set, struct nlattr *tb[], + } else { + ip_set_mask_from_to(ip, ip_to, e.cidr + 1); + } +- ipn = ip; +- do { +- ipn = ip_set_range_to_cidr(ipn, ip_to, &cidr); +- n++; +- } while (ipn++ < ip_to); +- +- if (n*(port_to - port + 1) > IPSET_MAX_RANGE) +- return -ERANGE; + + if (retried) { + ip = ntohl(h->next.ip); +@@ -255,8 +246,12 @@ hash_netport4_uadt(struct ip_set *set, struct nlattr *tb[], + e.ip = htonl(ip); + ip = ip_set_range_to_cidr(ip, ip_to, &cidr); + e.cidr = cidr - 1; +- for (; p <= port_to; p++) { ++ for (; p <= port_to; p++, i++) { + e.port = htons(p); ++ if (i > IPSET_MAX_RANGE) { ++ hash_netport4_data_next(&h->next, &e); ++ return -ERANGE; ++ } + ret = adtfn(set, &e, &ext, &ext, flags); + if (ret && !ip_set_eexist(ret, flags)) + return ret; +diff --git a/net/netfilter/ipset/ip_set_hash_netportnet.c b/net/netfilter/ipset/ip_set_hash_netportnet.c +index 19bcdb3141f6e..005a7ce87217e 100644 +--- a/net/netfilter/ipset/ip_set_hash_netportnet.c ++++ b/net/netfilter/ipset/ip_set_hash_netportnet.c +@@ -173,17 +173,26 @@ hash_netportnet4_kadt(struct ip_set *set, const struct sk_buff *skb, + return adtfn(set, &e, &ext, &opt->ext, opt->cmdflags); + } + ++static u32 ++hash_netportnet4_range_to_cidr(u32 from, u32 to, u8 *cidr) ++{ ++ if (from == 0 && to == UINT_MAX) { ++ *cidr = 0; ++ return to; ++ } ++ return ip_set_range_to_cidr(from, to, cidr); ++} ++ + static int + hash_netportnet4_uadt(struct ip_set *set, struct nlattr *tb[], + enum ipset_adt adt, u32 *lineno, u32 flags, bool retried) + { +- const struct hash_netportnet4 *h = set->data; ++ struct hash_netportnet4 *h = set->data; + ipset_adtfn adtfn = set->variant->adt[adt]; + struct hash_netportnet4_elem e = { }; + struct ip_set_ext ext = IP_SET_INIT_UEXT(set); + u32 ip = 0, ip_to = 0, p = 0, port, port_to; +- u32 ip2_from = 0, ip2_to = 0, ip2, ipn; +- u64 n = 0, m = 0; ++ u32 ip2_from = 0, ip2_to = 0, ip2, i = 0; + bool with_ports = false; + int ret; + +@@ -285,19 +294,6 @@ hash_netportnet4_uadt(struct ip_set *set, struct nlattr *tb[], + } else { + ip_set_mask_from_to(ip2_from, ip2_to, e.cidr[1]); + } +- ipn = ip; +- do { +- ipn = ip_set_range_to_cidr(ipn, ip_to, &e.cidr[0]); +- n++; +- } while (ipn++ < ip_to); +- ipn = ip2_from; +- do { +- ipn = ip_set_range_to_cidr(ipn, ip2_to, &e.cidr[1]); +- m++; +- } while (ipn++ < ip2_to); +- +- if (n*m*(port_to - port + 1) > IPSET_MAX_RANGE) +- return -ERANGE; + + if (retried) { + ip = ntohl(h->next.ip[0]); +@@ -310,13 +306,19 @@ hash_netportnet4_uadt(struct ip_set *set, struct nlattr *tb[], + + do { + e.ip[0] = htonl(ip); +- ip = ip_set_range_to_cidr(ip, ip_to, &e.cidr[0]); ++ ip = hash_netportnet4_range_to_cidr(ip, ip_to, &e.cidr[0]); + for (; p <= port_to; p++) { + e.port = htons(p); + do { ++ i++; + e.ip[1] = htonl(ip2); +- ip2 = ip_set_range_to_cidr(ip2, ip2_to, +- &e.cidr[1]); ++ if (i > IPSET_MAX_RANGE) { ++ hash_netportnet4_data_next(&h->next, ++ &e); ++ return -ERANGE; ++ } ++ ip2 = hash_netportnet4_range_to_cidr(ip2, ++ ip2_to, &e.cidr[1]); + ret = adtfn(set, &e, &ext, &ext, flags); + if (ret && !ip_set_eexist(ret, flags)) + return ret; +diff --git a/net/netfilter/nf_tables_api.c b/net/netfilter/nf_tables_api.c +index 7977f0422ecf6..e0c156bb0b172 100644 +--- a/net/netfilter/nf_tables_api.c ++++ b/net/netfilter/nf_tables_api.c +@@ -465,8 +465,9 @@ static int nft_delrule_by_chain(struct nft_ctx *ctx) + return 0; + } + +-static int nft_trans_set_add(const struct nft_ctx *ctx, int msg_type, +- struct nft_set *set) ++static int __nft_trans_set_add(const struct nft_ctx *ctx, int msg_type, ++ struct nft_set *set, ++ const struct nft_set_desc *desc) + { + struct nft_trans *trans; + +@@ -474,17 +475,28 @@ static int nft_trans_set_add(const struct nft_ctx *ctx, int msg_type, + if (trans == NULL) + return -ENOMEM; + +- if (msg_type == NFT_MSG_NEWSET && ctx->nla[NFTA_SET_ID] != NULL) { ++ if (msg_type == NFT_MSG_NEWSET && ctx->nla[NFTA_SET_ID] && !desc) { + nft_trans_set_id(trans) = + ntohl(nla_get_be32(ctx->nla[NFTA_SET_ID])); + nft_activate_next(ctx->net, set); + } + nft_trans_set(trans) = set; ++ if (desc) { ++ nft_trans_set_update(trans) = true; ++ nft_trans_set_gc_int(trans) = desc->gc_int; ++ nft_trans_set_timeout(trans) = desc->timeout; ++ } + nft_trans_commit_list_add_tail(ctx->net, trans); + + return 0; + } + ++static int nft_trans_set_add(const struct nft_ctx *ctx, int msg_type, ++ struct nft_set *set) ++{ ++ return __nft_trans_set_add(ctx, msg_type, set, NULL); ++} ++ + static int nft_delset(const struct nft_ctx *ctx, struct nft_set *set) + { + int err; +@@ -3732,8 +3744,7 @@ static bool nft_set_ops_candidate(const struct nft_set_type *type, u32 flags) + static const struct nft_set_ops * + nft_select_set_ops(const struct nft_ctx *ctx, + const struct nlattr * const nla[], +- const struct nft_set_desc *desc, +- enum nft_set_policies policy) ++ const struct nft_set_desc *desc) + { + struct nftables_pernet *nft_net = nft_pernet(ctx->net); + const struct nft_set_ops *ops, *bops; +@@ -3762,7 +3773,7 @@ nft_select_set_ops(const struct nft_ctx *ctx, + if (!ops->estimate(desc, flags, &est)) + continue; + +- switch (policy) { ++ switch (desc->policy) { + case NFT_SET_POL_PERFORMANCE: + if (est.lookup < best.lookup) + break; +@@ -3997,8 +4008,10 @@ static int nf_tables_fill_set_concat(struct sk_buff *skb, + static int nf_tables_fill_set(struct sk_buff *skb, const struct nft_ctx *ctx, + const struct nft_set *set, u16 event, u16 flags) + { +- struct nlmsghdr *nlh; ++ u64 timeout = READ_ONCE(set->timeout); ++ u32 gc_int = READ_ONCE(set->gc_int); + u32 portid = ctx->portid; ++ struct nlmsghdr *nlh; + struct nlattr *nest; + u32 seq = ctx->seq; + int i; +@@ -4034,13 +4047,13 @@ static int nf_tables_fill_set(struct sk_buff *skb, const struct nft_ctx *ctx, + nla_put_be32(skb, NFTA_SET_OBJ_TYPE, htonl(set->objtype))) + goto nla_put_failure; + +- if (set->timeout && ++ if (timeout && + nla_put_be64(skb, NFTA_SET_TIMEOUT, +- nf_jiffies64_to_msecs(set->timeout), ++ nf_jiffies64_to_msecs(timeout), + NFTA_SET_PAD)) + goto nla_put_failure; +- if (set->gc_int && +- nla_put_be32(skb, NFTA_SET_GC_INTERVAL, htonl(set->gc_int))) ++ if (gc_int && ++ nla_put_be32(skb, NFTA_SET_GC_INTERVAL, htonl(gc_int))) + goto nla_put_failure; + + if (set->policy != NFT_SET_POL_PERFORMANCE) { +@@ -4341,15 +4354,94 @@ static int nf_tables_set_desc_parse(struct nft_set_desc *desc, + return err; + } + ++static int nft_set_expr_alloc(struct nft_ctx *ctx, struct nft_set *set, ++ const struct nlattr * const *nla, ++ struct nft_expr **exprs, int *num_exprs, ++ u32 flags) ++{ ++ struct nft_expr *expr; ++ int err, i; ++ ++ if (nla[NFTA_SET_EXPR]) { ++ expr = nft_set_elem_expr_alloc(ctx, set, nla[NFTA_SET_EXPR]); ++ if (IS_ERR(expr)) { ++ err = PTR_ERR(expr); ++ goto err_set_expr_alloc; ++ } ++ exprs[0] = expr; ++ (*num_exprs)++; ++ } else if (nla[NFTA_SET_EXPRESSIONS]) { ++ struct nlattr *tmp; ++ int left; ++ ++ if (!(flags & NFT_SET_EXPR)) { ++ err = -EINVAL; ++ goto err_set_expr_alloc; ++ } ++ i = 0; ++ nla_for_each_nested(tmp, nla[NFTA_SET_EXPRESSIONS], left) { ++ if (i == NFT_SET_EXPR_MAX) { ++ err = -E2BIG; ++ goto err_set_expr_alloc; ++ } ++ if (nla_type(tmp) != NFTA_LIST_ELEM) { ++ err = -EINVAL; ++ goto err_set_expr_alloc; ++ } ++ expr = nft_set_elem_expr_alloc(ctx, set, tmp); ++ if (IS_ERR(expr)) { ++ err = PTR_ERR(expr); ++ goto err_set_expr_alloc; ++ } ++ exprs[i++] = expr; ++ (*num_exprs)++; ++ } ++ } ++ ++ return 0; ++ ++err_set_expr_alloc: ++ for (i = 0; i < *num_exprs; i++) ++ nft_expr_destroy(ctx, exprs[i]); ++ ++ return err; ++} ++ ++static bool nft_set_is_same(const struct nft_set *set, ++ const struct nft_set_desc *desc, ++ struct nft_expr *exprs[], u32 num_exprs, u32 flags) ++{ ++ int i; ++ ++ if (set->ktype != desc->ktype || ++ set->dtype != desc->dtype || ++ set->flags != flags || ++ set->klen != desc->klen || ++ set->dlen != desc->dlen || ++ set->field_count != desc->field_count || ++ set->num_exprs != num_exprs) ++ return false; ++ ++ for (i = 0; i < desc->field_count; i++) { ++ if (set->field_len[i] != desc->field_len[i]) ++ return false; ++ } ++ ++ for (i = 0; i < num_exprs; i++) { ++ if (set->exprs[i]->ops != exprs[i]->ops) ++ return false; ++ } ++ ++ return true; ++} ++ + static int nf_tables_newset(struct sk_buff *skb, const struct nfnl_info *info, + const struct nlattr * const nla[]) + { +- u32 ktype, dtype, flags, policy, gc_int, objtype; + struct netlink_ext_ack *extack = info->extack; + u8 genmask = nft_genmask_next(info->net); + u8 family = info->nfmsg->nfgen_family; + const struct nft_set_ops *ops; +- struct nft_expr *expr = NULL; + struct net *net = info->net; + struct nft_set_desc desc; + struct nft_table *table; +@@ -4357,10 +4449,11 @@ static int nf_tables_newset(struct sk_buff *skb, const struct nfnl_info *info, + struct nft_set *set; + struct nft_ctx ctx; + size_t alloc_size; +- u64 timeout; ++ int num_exprs = 0; + char *name; + int err, i; + u16 udlen; ++ u32 flags; + u64 size; + + if (nla[NFTA_SET_TABLE] == NULL || +@@ -4371,10 +4464,10 @@ static int nf_tables_newset(struct sk_buff *skb, const struct nfnl_info *info, + + memset(&desc, 0, sizeof(desc)); + +- ktype = NFT_DATA_VALUE; ++ desc.ktype = NFT_DATA_VALUE; + if (nla[NFTA_SET_KEY_TYPE] != NULL) { +- ktype = ntohl(nla_get_be32(nla[NFTA_SET_KEY_TYPE])); +- if ((ktype & NFT_DATA_RESERVED_MASK) == NFT_DATA_RESERVED_MASK) ++ desc.ktype = ntohl(nla_get_be32(nla[NFTA_SET_KEY_TYPE])); ++ if ((desc.ktype & NFT_DATA_RESERVED_MASK) == NFT_DATA_RESERVED_MASK) + return -EINVAL; + } + +@@ -4399,17 +4492,17 @@ static int nf_tables_newset(struct sk_buff *skb, const struct nfnl_info *info, + return -EOPNOTSUPP; + } + +- dtype = 0; ++ desc.dtype = 0; + if (nla[NFTA_SET_DATA_TYPE] != NULL) { + if (!(flags & NFT_SET_MAP)) + return -EINVAL; + +- dtype = ntohl(nla_get_be32(nla[NFTA_SET_DATA_TYPE])); +- if ((dtype & NFT_DATA_RESERVED_MASK) == NFT_DATA_RESERVED_MASK && +- dtype != NFT_DATA_VERDICT) ++ desc.dtype = ntohl(nla_get_be32(nla[NFTA_SET_DATA_TYPE])); ++ if ((desc.dtype & NFT_DATA_RESERVED_MASK) == NFT_DATA_RESERVED_MASK && ++ desc.dtype != NFT_DATA_VERDICT) + return -EINVAL; + +- if (dtype != NFT_DATA_VERDICT) { ++ if (desc.dtype != NFT_DATA_VERDICT) { + if (nla[NFTA_SET_DATA_LEN] == NULL) + return -EINVAL; + desc.dlen = ntohl(nla_get_be32(nla[NFTA_SET_DATA_LEN])); +@@ -4424,34 +4517,34 @@ static int nf_tables_newset(struct sk_buff *skb, const struct nfnl_info *info, + if (!(flags & NFT_SET_OBJECT)) + return -EINVAL; + +- objtype = ntohl(nla_get_be32(nla[NFTA_SET_OBJ_TYPE])); +- if (objtype == NFT_OBJECT_UNSPEC || +- objtype > NFT_OBJECT_MAX) ++ desc.objtype = ntohl(nla_get_be32(nla[NFTA_SET_OBJ_TYPE])); ++ if (desc.objtype == NFT_OBJECT_UNSPEC || ++ desc.objtype > NFT_OBJECT_MAX) + return -EOPNOTSUPP; + } else if (flags & NFT_SET_OBJECT) + return -EINVAL; + else +- objtype = NFT_OBJECT_UNSPEC; ++ desc.objtype = NFT_OBJECT_UNSPEC; + +- timeout = 0; ++ desc.timeout = 0; + if (nla[NFTA_SET_TIMEOUT] != NULL) { + if (!(flags & NFT_SET_TIMEOUT)) + return -EINVAL; + +- err = nf_msecs_to_jiffies64(nla[NFTA_SET_TIMEOUT], &timeout); ++ err = nf_msecs_to_jiffies64(nla[NFTA_SET_TIMEOUT], &desc.timeout); + if (err) + return err; + } +- gc_int = 0; ++ desc.gc_int = 0; + if (nla[NFTA_SET_GC_INTERVAL] != NULL) { + if (!(flags & NFT_SET_TIMEOUT)) + return -EINVAL; +- gc_int = ntohl(nla_get_be32(nla[NFTA_SET_GC_INTERVAL])); ++ desc.gc_int = ntohl(nla_get_be32(nla[NFTA_SET_GC_INTERVAL])); + } + +- policy = NFT_SET_POL_PERFORMANCE; ++ desc.policy = NFT_SET_POL_PERFORMANCE; + if (nla[NFTA_SET_POLICY] != NULL) +- policy = ntohl(nla_get_be32(nla[NFTA_SET_POLICY])); ++ desc.policy = ntohl(nla_get_be32(nla[NFTA_SET_POLICY])); + + if (nla[NFTA_SET_DESC] != NULL) { + err = nf_tables_set_desc_parse(&desc, nla[NFTA_SET_DESC]); +@@ -4483,6 +4576,8 @@ static int nf_tables_newset(struct sk_buff *skb, const struct nfnl_info *info, + return PTR_ERR(set); + } + } else { ++ struct nft_expr *exprs[NFT_SET_EXPR_MAX] = {}; ++ + if (info->nlh->nlmsg_flags & NLM_F_EXCL) { + NL_SET_BAD_ATTR(extack, nla[NFTA_SET_NAME]); + return -EEXIST; +@@ -4490,13 +4585,29 @@ static int nf_tables_newset(struct sk_buff *skb, const struct nfnl_info *info, + if (info->nlh->nlmsg_flags & NLM_F_REPLACE) + return -EOPNOTSUPP; + +- return 0; ++ err = nft_set_expr_alloc(&ctx, set, nla, exprs, &num_exprs, flags); ++ if (err < 0) ++ return err; ++ ++ err = 0; ++ if (!nft_set_is_same(set, &desc, exprs, num_exprs, flags)) { ++ NL_SET_BAD_ATTR(extack, nla[NFTA_SET_NAME]); ++ err = -EEXIST; ++ } ++ ++ for (i = 0; i < num_exprs; i++) ++ nft_expr_destroy(&ctx, exprs[i]); ++ ++ if (err < 0) ++ return err; ++ ++ return __nft_trans_set_add(&ctx, NFT_MSG_NEWSET, set, &desc); + } + + if (!(info->nlh->nlmsg_flags & NLM_F_CREATE)) + return -ENOENT; + +- ops = nft_select_set_ops(&ctx, nla, &desc, policy); ++ ops = nft_select_set_ops(&ctx, nla, &desc); + if (IS_ERR(ops)) + return PTR_ERR(ops); + +@@ -4536,18 +4647,18 @@ static int nf_tables_newset(struct sk_buff *skb, const struct nfnl_info *info, + set->table = table; + write_pnet(&set->net, net); + set->ops = ops; +- set->ktype = ktype; ++ set->ktype = desc.ktype; + set->klen = desc.klen; +- set->dtype = dtype; +- set->objtype = objtype; ++ set->dtype = desc.dtype; ++ set->objtype = desc.objtype; + set->dlen = desc.dlen; + set->flags = flags; + set->size = desc.size; +- set->policy = policy; ++ set->policy = desc.policy; + set->udlen = udlen; + set->udata = udata; +- set->timeout = timeout; +- set->gc_int = gc_int; ++ set->timeout = desc.timeout; ++ set->gc_int = desc.gc_int; + + set->field_count = desc.field_count; + for (i = 0; i < desc.field_count; i++) +@@ -4557,43 +4668,11 @@ static int nf_tables_newset(struct sk_buff *skb, const struct nfnl_info *info, + if (err < 0) + goto err_set_init; + +- if (nla[NFTA_SET_EXPR]) { +- expr = nft_set_elem_expr_alloc(&ctx, set, nla[NFTA_SET_EXPR]); +- if (IS_ERR(expr)) { +- err = PTR_ERR(expr); +- goto err_set_expr_alloc; +- } +- set->exprs[0] = expr; +- set->num_exprs++; +- } else if (nla[NFTA_SET_EXPRESSIONS]) { +- struct nft_expr *expr; +- struct nlattr *tmp; +- int left; +- +- if (!(flags & NFT_SET_EXPR)) { +- err = -EINVAL; +- goto err_set_expr_alloc; +- } +- i = 0; +- nla_for_each_nested(tmp, nla[NFTA_SET_EXPRESSIONS], left) { +- if (i == NFT_SET_EXPR_MAX) { +- err = -E2BIG; +- goto err_set_expr_alloc; +- } +- if (nla_type(tmp) != NFTA_LIST_ELEM) { +- err = -EINVAL; +- goto err_set_expr_alloc; +- } +- expr = nft_set_elem_expr_alloc(&ctx, set, tmp); +- if (IS_ERR(expr)) { +- err = PTR_ERR(expr); +- goto err_set_expr_alloc; +- } +- set->exprs[i++] = expr; +- set->num_exprs++; +- } +- } ++ err = nft_set_expr_alloc(&ctx, set, nla, set->exprs, &num_exprs, flags); ++ if (err < 0) ++ goto err_set_destroy; + ++ set->num_exprs = num_exprs; + set->handle = nf_tables_alloc_handle(table); + + err = nft_trans_set_add(&ctx, NFT_MSG_NEWSET, set); +@@ -4607,7 +4686,7 @@ static int nf_tables_newset(struct sk_buff *skb, const struct nfnl_info *info, + err_set_expr_alloc: + for (i = 0; i < set->num_exprs; i++) + nft_expr_destroy(&ctx, set->exprs[i]); +- ++err_set_destroy: + ops->destroy(set); + err_set_init: + kfree(set->name); +@@ -5960,7 +6039,7 @@ static int nft_add_set_elem(struct nft_ctx *ctx, struct nft_set *set, + return err; + } else if (set->flags & NFT_SET_TIMEOUT && + !(flags & NFT_SET_ELEM_INTERVAL_END)) { +- timeout = set->timeout; ++ timeout = READ_ONCE(set->timeout); + } + + expiration = 0; +@@ -6061,7 +6140,7 @@ static int nft_add_set_elem(struct nft_ctx *ctx, struct nft_set *set, + if (err < 0) + goto err_parse_key_end; + +- if (timeout != set->timeout) { ++ if (timeout != READ_ONCE(set->timeout)) { + err = nft_set_ext_add(&tmpl, NFT_SET_EXT_TIMEOUT); + if (err < 0) + goto err_parse_key_end; +@@ -8977,14 +9056,20 @@ static int nf_tables_commit(struct net *net, struct sk_buff *skb) + nft_flow_rule_destroy(nft_trans_flow_rule(trans)); + break; + case NFT_MSG_NEWSET: +- nft_clear(net, nft_trans_set(trans)); +- /* This avoids hitting -EBUSY when deleting the table +- * from the transaction. +- */ +- if (nft_set_is_anonymous(nft_trans_set(trans)) && +- !list_empty(&nft_trans_set(trans)->bindings)) +- trans->ctx.table->use--; ++ if (nft_trans_set_update(trans)) { ++ struct nft_set *set = nft_trans_set(trans); + ++ WRITE_ONCE(set->timeout, nft_trans_set_timeout(trans)); ++ WRITE_ONCE(set->gc_int, nft_trans_set_gc_int(trans)); ++ } else { ++ nft_clear(net, nft_trans_set(trans)); ++ /* This avoids hitting -EBUSY when deleting the table ++ * from the transaction. ++ */ ++ if (nft_set_is_anonymous(nft_trans_set(trans)) && ++ !list_empty(&nft_trans_set(trans)->bindings)) ++ trans->ctx.table->use--; ++ } + nf_tables_set_notify(&trans->ctx, nft_trans_set(trans), + NFT_MSG_NEWSET, GFP_KERNEL); + nft_trans_destroy(trans); +@@ -9206,6 +9291,10 @@ static int __nf_tables_abort(struct net *net, enum nfnl_abort_action action) + nft_trans_destroy(trans); + break; + case NFT_MSG_NEWSET: ++ if (nft_trans_set_update(trans)) { ++ nft_trans_destroy(trans); ++ break; ++ } + trans->ctx.table->use--; + if (nft_trans_set_bound(trans)) { + nft_trans_destroy(trans); +diff --git a/net/nfc/netlink.c b/net/nfc/netlink.c +index 7c62417ccfd78..32a08ae9ad117 100644 +--- a/net/nfc/netlink.c ++++ b/net/nfc/netlink.c +@@ -1497,6 +1497,7 @@ static int nfc_genl_se_io(struct sk_buff *skb, struct genl_info *info) + u32 dev_idx, se_idx; + u8 *apdu; + size_t apdu_len; ++ int rc; + + if (!info->attrs[NFC_ATTR_DEVICE_INDEX] || + !info->attrs[NFC_ATTR_SE_INDEX] || +@@ -1510,25 +1511,37 @@ static int nfc_genl_se_io(struct sk_buff *skb, struct genl_info *info) + if (!dev) + return -ENODEV; + +- if (!dev->ops || !dev->ops->se_io) +- return -ENOTSUPP; ++ if (!dev->ops || !dev->ops->se_io) { ++ rc = -EOPNOTSUPP; ++ goto put_dev; ++ } + + apdu_len = nla_len(info->attrs[NFC_ATTR_SE_APDU]); +- if (apdu_len == 0) +- return -EINVAL; ++ if (apdu_len == 0) { ++ rc = -EINVAL; ++ goto put_dev; ++ } + + apdu = nla_data(info->attrs[NFC_ATTR_SE_APDU]); +- if (!apdu) +- return -EINVAL; ++ if (!apdu) { ++ rc = -EINVAL; ++ goto put_dev; ++ } + + ctx = kzalloc(sizeof(struct se_io_ctx), GFP_KERNEL); +- if (!ctx) +- return -ENOMEM; ++ if (!ctx) { ++ rc = -ENOMEM; ++ goto put_dev; ++ } + + ctx->dev_idx = dev_idx; + ctx->se_idx = se_idx; + +- return nfc_se_io(dev, se_idx, apdu, apdu_len, se_io_cb, ctx); ++ rc = nfc_se_io(dev, se_idx, apdu, apdu_len, se_io_cb, ctx); ++ ++put_dev: ++ nfc_put_device(dev); ++ return rc; + } + + static int nfc_genl_vendor_cmd(struct sk_buff *skb, +@@ -1551,14 +1564,21 @@ static int nfc_genl_vendor_cmd(struct sk_buff *skb, + subcmd = nla_get_u32(info->attrs[NFC_ATTR_VENDOR_SUBCMD]); + + dev = nfc_get_device(dev_idx); +- if (!dev || !dev->vendor_cmds || !dev->n_vendor_cmds) ++ if (!dev) + return -ENODEV; + ++ if (!dev->vendor_cmds || !dev->n_vendor_cmds) { ++ err = -ENODEV; ++ goto put_dev; ++ } ++ + if (info->attrs[NFC_ATTR_VENDOR_DATA]) { + data = nla_data(info->attrs[NFC_ATTR_VENDOR_DATA]); + data_len = nla_len(info->attrs[NFC_ATTR_VENDOR_DATA]); +- if (data_len == 0) +- return -EINVAL; ++ if (data_len == 0) { ++ err = -EINVAL; ++ goto put_dev; ++ } + } else { + data = NULL; + data_len = 0; +@@ -1573,10 +1593,14 @@ static int nfc_genl_vendor_cmd(struct sk_buff *skb, + dev->cur_cmd_info = info; + err = cmd->doit(dev, data, data_len); + dev->cur_cmd_info = NULL; +- return err; ++ goto put_dev; + } + +- return -EOPNOTSUPP; ++ err = -EOPNOTSUPP; ++ ++put_dev: ++ nfc_put_device(dev); ++ return err; + } + + /* message building helper */ +diff --git a/net/sched/cls_tcindex.c b/net/sched/cls_tcindex.c +index 742c7d49a9581..8d1ef858db87d 100644 +--- a/net/sched/cls_tcindex.c ++++ b/net/sched/cls_tcindex.c +@@ -332,7 +332,7 @@ tcindex_set_parms(struct net *net, struct tcf_proto *tp, unsigned long base, + struct tcindex_filter_result *r, struct nlattr **tb, + struct nlattr *est, u32 flags, struct netlink_ext_ack *extack) + { +- struct tcindex_filter_result new_filter_result, *old_r = r; ++ struct tcindex_filter_result new_filter_result; + struct tcindex_data *cp = NULL, *oldp; + struct tcindex_filter *f = NULL; /* make gcc behave */ + struct tcf_result cr = {}; +@@ -401,7 +401,7 @@ tcindex_set_parms(struct net *net, struct tcf_proto *tp, unsigned long base, + err = tcindex_filter_result_init(&new_filter_result, cp, net); + if (err < 0) + goto errout_alloc; +- if (old_r) ++ if (r) + cr = r->res; + + err = -EBUSY; +@@ -478,14 +478,6 @@ tcindex_set_parms(struct net *net, struct tcf_proto *tp, unsigned long base, + tcf_bind_filter(tp, &cr, base); + } + +- if (old_r && old_r != r) { +- err = tcindex_filter_result_init(old_r, cp, net); +- if (err < 0) { +- kfree(f); +- goto errout_alloc; +- } +- } +- + oldp = p; + r->res = cr; + tcf_exts_change(&r->exts, &e); +diff --git a/net/sched/sch_atm.c b/net/sched/sch_atm.c +index 816fd0d7ba38a..28e1897e0da70 100644 +--- a/net/sched/sch_atm.c ++++ b/net/sched/sch_atm.c +@@ -397,10 +397,13 @@ static int atm_tc_enqueue(struct sk_buff *skb, struct Qdisc *sch, + result = tcf_classify(skb, NULL, fl, &res, true); + if (result < 0) + continue; ++ if (result == TC_ACT_SHOT) ++ goto done; ++ + flow = (struct atm_flow_data *)res.class; + if (!flow) + flow = lookup_flow(sch, res.classid); +- goto done; ++ goto drop; + } + } + flow = NULL; +diff --git a/net/sched/sch_cbq.c b/net/sched/sch_cbq.c +index ba99ce05cd527..5d9f4f259d693 100644 +--- a/net/sched/sch_cbq.c ++++ b/net/sched/sch_cbq.c +@@ -230,6 +230,8 @@ cbq_classify(struct sk_buff *skb, struct Qdisc *sch, int *qerr) + result = tcf_classify(skb, NULL, fl, &res, true); + if (!fl || result < 0) + goto fallback; ++ if (result == TC_ACT_SHOT) ++ return NULL; + + cl = (void *)res.class; + if (!cl) { +@@ -250,8 +252,6 @@ cbq_classify(struct sk_buff *skb, struct Qdisc *sch, int *qerr) + case TC_ACT_TRAP: + *qerr = NET_XMIT_SUCCESS | __NET_XMIT_STOLEN; + fallthrough; +- case TC_ACT_SHOT: +- return NULL; + case TC_ACT_RECLASSIFY: + return cbq_reclassify(skb, cl); + } +diff --git a/net/sunrpc/auth_gss/auth_gss.c b/net/sunrpc/auth_gss/auth_gss.c +index 7bb247c51e2f6..2d7b1e03110ae 100644 +--- a/net/sunrpc/auth_gss/auth_gss.c ++++ b/net/sunrpc/auth_gss/auth_gss.c +@@ -302,7 +302,7 @@ __gss_find_upcall(struct rpc_pipe *pipe, kuid_t uid, const struct gss_auth *auth + list_for_each_entry(pos, &pipe->in_downcall, list) { + if (!uid_eq(pos->uid, uid)) + continue; +- if (auth && pos->auth->service != auth->service) ++ if (pos->auth->service != auth->service) + continue; + refcount_inc(&pos->count); + return pos; +@@ -686,6 +686,21 @@ out: + return err; + } + ++static struct gss_upcall_msg * ++gss_find_downcall(struct rpc_pipe *pipe, kuid_t uid) ++{ ++ struct gss_upcall_msg *pos; ++ list_for_each_entry(pos, &pipe->in_downcall, list) { ++ if (!uid_eq(pos->uid, uid)) ++ continue; ++ if (!rpc_msg_is_inflight(&pos->msg)) ++ continue; ++ refcount_inc(&pos->count); ++ return pos; ++ } ++ return NULL; ++} ++ + #define MSG_BUF_MAXSIZE 1024 + + static ssize_t +@@ -732,7 +747,7 @@ gss_pipe_downcall(struct file *filp, const char __user *src, size_t mlen) + err = -ENOENT; + /* Find a matching upcall */ + spin_lock(&pipe->lock); +- gss_msg = __gss_find_upcall(pipe, uid, NULL); ++ gss_msg = gss_find_downcall(pipe, uid); + if (gss_msg == NULL) { + spin_unlock(&pipe->lock); + goto err_put_ctx; +diff --git a/sound/soc/intel/boards/bytcr_rt5640.c b/sound/soc/intel/boards/bytcr_rt5640.c +index fb9d9e271845d..ddd2625bed90d 100644 +--- a/sound/soc/intel/boards/bytcr_rt5640.c ++++ b/sound/soc/intel/boards/bytcr_rt5640.c +@@ -570,6 +570,21 @@ static const struct dmi_system_id byt_rt5640_quirk_table[] = { + BYT_RT5640_SSP0_AIF1 | + BYT_RT5640_MCLK_EN), + }, ++ { ++ /* Advantech MICA-071 */ ++ .matches = { ++ DMI_EXACT_MATCH(DMI_SYS_VENDOR, "Advantech"), ++ DMI_EXACT_MATCH(DMI_PRODUCT_NAME, "MICA-071"), ++ }, ++ /* OVCD Th = 1500uA to reliable detect head-phones vs -set */ ++ .driver_data = (void *)(BYT_RT5640_IN3_MAP | ++ BYT_RT5640_JD_SRC_JD2_IN4N | ++ BYT_RT5640_OVCD_TH_1500UA | ++ BYT_RT5640_OVCD_SF_0P75 | ++ BYT_RT5640_MONO_SPEAKER | ++ BYT_RT5640_DIFF_MIC | ++ BYT_RT5640_MCLK_EN), ++ }, + { + .matches = { + DMI_EXACT_MATCH(DMI_SYS_VENDOR, "ARCHOS"), +diff --git a/sound/soc/sof/core.c b/sound/soc/sof/core.c +index c99b5e6c026c1..694a2d94a2228 100644 +--- a/sound/soc/sof/core.c ++++ b/sound/soc/sof/core.c +@@ -472,19 +472,10 @@ EXPORT_SYMBOL(snd_sof_device_remove); + int snd_sof_device_shutdown(struct device *dev) + { + struct snd_sof_dev *sdev = dev_get_drvdata(dev); +- struct snd_sof_pdata *pdata = sdev->pdata; + + if (IS_ENABLED(CONFIG_SND_SOC_SOF_PROBE_WORK_QUEUE)) + cancel_work_sync(&sdev->probe_work); + +- /* +- * make sure clients and machine driver(s) are unregistered to force +- * all userspace devices to be closed prior to the DSP shutdown sequence +- */ +- sof_unregister_clients(sdev); +- +- snd_sof_machine_unregister(sdev, pdata); +- + if (sdev->fw_state == SOF_FW_BOOT_COMPLETE) + return snd_sof_shutdown(sdev); + +diff --git a/sound/soc/sof/intel/hda-dsp.c b/sound/soc/sof/intel/hda-dsp.c +index eddfd77ad90f4..0ab111814f1c5 100644 +--- a/sound/soc/sof/intel/hda-dsp.c ++++ b/sound/soc/sof/intel/hda-dsp.c +@@ -901,6 +901,78 @@ int hda_dsp_suspend(struct snd_sof_dev *sdev, u32 target_state) + return snd_sof_dsp_set_power_state(sdev, &target_dsp_state); + } + ++static unsigned int hda_dsp_check_for_dma_streams(struct snd_sof_dev *sdev) ++{ ++ struct hdac_bus *bus = sof_to_bus(sdev); ++ struct hdac_stream *s; ++ unsigned int active_streams = 0; ++ int sd_offset; ++ u32 val; ++ ++ list_for_each_entry(s, &bus->stream_list, list) { ++ sd_offset = SOF_STREAM_SD_OFFSET(s); ++ val = snd_sof_dsp_read(sdev, HDA_DSP_HDA_BAR, ++ sd_offset); ++ if (val & SOF_HDA_SD_CTL_DMA_START) ++ active_streams |= BIT(s->index); ++ } ++ ++ return active_streams; ++} ++ ++static int hda_dsp_s5_quirk(struct snd_sof_dev *sdev) ++{ ++ int ret; ++ ++ /* ++ * Do not assume a certain timing between the prior ++ * suspend flow, and running of this quirk function. ++ * This is needed if the controller was just put ++ * to reset before calling this function. ++ */ ++ usleep_range(500, 1000); ++ ++ /* ++ * Take controller out of reset to flush DMA ++ * transactions. ++ */ ++ ret = hda_dsp_ctrl_link_reset(sdev, false); ++ if (ret < 0) ++ return ret; ++ ++ usleep_range(500, 1000); ++ ++ /* Restore state for shutdown, back to reset */ ++ ret = hda_dsp_ctrl_link_reset(sdev, true); ++ if (ret < 0) ++ return ret; ++ ++ return ret; ++} ++ ++int hda_dsp_shutdown_dma_flush(struct snd_sof_dev *sdev) ++{ ++ unsigned int active_streams; ++ int ret, ret2; ++ ++ /* check if DMA cleanup has been successful */ ++ active_streams = hda_dsp_check_for_dma_streams(sdev); ++ ++ sdev->system_suspend_target = SOF_SUSPEND_S3; ++ ret = snd_sof_suspend(sdev->dev); ++ ++ if (active_streams) { ++ dev_warn(sdev->dev, ++ "There were active DSP streams (%#x) at shutdown, trying to recover\n", ++ active_streams); ++ ret2 = hda_dsp_s5_quirk(sdev); ++ if (ret2 < 0) ++ dev_err(sdev->dev, "shutdown recovery failed (%d)\n", ret2); ++ } ++ ++ return ret; ++} ++ + int hda_dsp_shutdown(struct snd_sof_dev *sdev) + { + sdev->system_suspend_target = SOF_SUSPEND_S3; +diff --git a/sound/soc/sof/intel/hda.h b/sound/soc/sof/intel/hda.h +index 5ef3e8775e364..554891e78cca5 100644 +--- a/sound/soc/sof/intel/hda.h ++++ b/sound/soc/sof/intel/hda.h +@@ -578,6 +578,7 @@ int hda_dsp_resume(struct snd_sof_dev *sdev); + int hda_dsp_runtime_suspend(struct snd_sof_dev *sdev); + int hda_dsp_runtime_resume(struct snd_sof_dev *sdev); + int hda_dsp_runtime_idle(struct snd_sof_dev *sdev); ++int hda_dsp_shutdown_dma_flush(struct snd_sof_dev *sdev); + int hda_dsp_shutdown(struct snd_sof_dev *sdev); + int hda_dsp_set_hw_params_upon_resume(struct snd_sof_dev *sdev); + void hda_dsp_dump(struct snd_sof_dev *sdev, u32 flags); +diff --git a/sound/soc/sof/intel/tgl.c b/sound/soc/sof/intel/tgl.c +index 6dfb4786c7824..0173e5b255daa 100644 +--- a/sound/soc/sof/intel/tgl.c ++++ b/sound/soc/sof/intel/tgl.c +@@ -60,7 +60,7 @@ int sof_tgl_ops_init(struct snd_sof_dev *sdev) + memcpy(&sof_tgl_ops, &sof_hda_common_ops, sizeof(struct snd_sof_dsp_ops)); + + /* probe/remove/shutdown */ +- sof_tgl_ops.shutdown = hda_dsp_shutdown; ++ sof_tgl_ops.shutdown = hda_dsp_shutdown_dma_flush; + + if (sdev->pdata->ipc_type == SOF_IPC) { + /* doorbell */ +diff --git a/sound/soc/sof/mediatek/mtk-adsp-common.c b/sound/soc/sof/mediatek/mtk-adsp-common.c +index 1e0769c668a7b..de8dbe27cd0de 100644 +--- a/sound/soc/sof/mediatek/mtk-adsp-common.c ++++ b/sound/soc/sof/mediatek/mtk-adsp-common.c +@@ -60,7 +60,7 @@ void mtk_adsp_dump(struct snd_sof_dev *sdev, u32 flags) + { + char *level = (flags & SOF_DBG_DUMP_OPTIONAL) ? KERN_DEBUG : KERN_ERR; + struct sof_ipc_dsp_oops_xtensa xoops; +- struct sof_ipc_panic_info panic_info; ++ struct sof_ipc_panic_info panic_info = {}; + u32 stack[MTK_ADSP_STACK_DUMP_SIZE]; + u32 status; + +diff --git a/tools/perf/builtin-lock.c b/tools/perf/builtin-lock.c +index ea40ae52cd2c7..2bc9231d86b66 100644 +--- a/tools/perf/builtin-lock.c ++++ b/tools/perf/builtin-lock.c +@@ -1539,6 +1539,7 @@ static int __cmd_report(bool display_info) + + /* for lock function check */ + symbol_conf.sort_by_name = true; ++ symbol_conf.allow_aliases = true; + symbol__init(&session->header.env); + + if (!perf_session__has_traces(session, "lock record")) +@@ -1613,6 +1614,7 @@ static int __cmd_contention(int argc, const char **argv) + + /* for lock function check */ + symbol_conf.sort_by_name = true; ++ symbol_conf.allow_aliases = true; + symbol__init(&session->header.env); + + if (use_bpf) { +diff --git a/tools/perf/util/bpf_counter_cgroup.c b/tools/perf/util/bpf_counter_cgroup.c +index 3c2df7522f6fc..1c82377ed78b9 100644 +--- a/tools/perf/util/bpf_counter_cgroup.c ++++ b/tools/perf/util/bpf_counter_cgroup.c +@@ -116,27 +116,19 @@ static int bperf_load_program(struct evlist *evlist) + + /* open single copy of the events w/o cgroup */ + err = evsel__open_per_cpu(evsel, evsel->core.cpus, -1); +- if (err) { +- pr_err("Failed to open first cgroup events\n"); +- goto out; +- } ++ if (err == 0) ++ evsel->supported = true; + + map_fd = bpf_map__fd(skel->maps.events); + perf_cpu_map__for_each_cpu(cpu, j, evsel->core.cpus) { + int fd = FD(evsel, j); + __u32 idx = evsel->core.idx * total_cpus + cpu.cpu; + +- err = bpf_map_update_elem(map_fd, &idx, &fd, +- BPF_ANY); +- if (err < 0) { +- pr_err("Failed to update perf_event fd\n"); +- goto out; +- } ++ bpf_map_update_elem(map_fd, &idx, &fd, BPF_ANY); + } + + evsel->cgrp = leader_cgrp; + } +- evsel->supported = true; + + if (evsel->cgrp == cgrp) + continue; +diff --git a/tools/perf/util/cgroup.c b/tools/perf/util/cgroup.c +index e99b41f9be45a..cd978c240e0dd 100644 +--- a/tools/perf/util/cgroup.c ++++ b/tools/perf/util/cgroup.c +@@ -224,6 +224,19 @@ static int add_cgroup_name(const char *fpath, const struct stat *sb __maybe_unus + return 0; + } + ++static int check_and_add_cgroup_name(const char *fpath) ++{ ++ struct cgroup_name *cn; ++ ++ list_for_each_entry(cn, &cgroup_list, list) { ++ if (!strcmp(cn->name, fpath)) ++ return 0; ++ } ++ ++ /* pretend if it's added by ftw() */ ++ return add_cgroup_name(fpath, NULL, FTW_D, NULL); ++} ++ + static void release_cgroup_list(void) + { + struct cgroup_name *cn; +@@ -242,7 +255,7 @@ static int list_cgroups(const char *str) + struct cgroup_name *cn; + char *s; + +- /* use given name as is - for testing purpose */ ++ /* use given name as is when no regex is given */ + for (;;) { + p = strchr(str, ','); + e = p ? p : eos; +@@ -253,13 +266,13 @@ static int list_cgroups(const char *str) + s = strndup(str, e - str); + if (!s) + return -1; +- /* pretend if it's added by ftw() */ +- ret = add_cgroup_name(s, NULL, FTW_D, NULL); ++ ++ ret = check_and_add_cgroup_name(s); + free(s); +- if (ret) ++ if (ret < 0) + return -1; + } else { +- if (add_cgroup_name("", NULL, FTW_D, NULL) < 0) ++ if (check_and_add_cgroup_name("/") < 0) + return -1; + } + +diff --git a/tools/perf/util/data.c b/tools/perf/util/data.c +index a7f68c309545d..fc16299c915f9 100644 +--- a/tools/perf/util/data.c ++++ b/tools/perf/util/data.c +@@ -132,6 +132,7 @@ int perf_data__open_dir(struct perf_data *data) + file->size = st.st_size; + } + ++ closedir(dir); + if (!files) + return -EINVAL; + +@@ -140,6 +141,7 @@ int perf_data__open_dir(struct perf_data *data) + return 0; + + out_err: ++ closedir(dir); + close_dir(files, nr); + return ret; + } +diff --git a/tools/perf/util/dwarf-aux.c b/tools/perf/util/dwarf-aux.c +index 609ca16715018..623527edeac1e 100644 +--- a/tools/perf/util/dwarf-aux.c ++++ b/tools/perf/util/dwarf-aux.c +@@ -308,26 +308,13 @@ static int die_get_attr_udata(Dwarf_Die *tp_die, unsigned int attr_name, + { + Dwarf_Attribute attr; + +- if (dwarf_attr(tp_die, attr_name, &attr) == NULL || ++ if (dwarf_attr_integrate(tp_die, attr_name, &attr) == NULL || + dwarf_formudata(&attr, result) != 0) + return -ENOENT; + + return 0; + } + +-/* Get attribute and translate it as a sdata */ +-static int die_get_attr_sdata(Dwarf_Die *tp_die, unsigned int attr_name, +- Dwarf_Sword *result) +-{ +- Dwarf_Attribute attr; +- +- if (dwarf_attr(tp_die, attr_name, &attr) == NULL || +- dwarf_formsdata(&attr, result) != 0) +- return -ENOENT; +- +- return 0; +-} +- + /** + * die_is_signed_type - Check whether a type DIE is signed or not + * @tp_die: a DIE of a type +@@ -467,9 +454,9 @@ int die_get_data_member_location(Dwarf_Die *mb_die, Dwarf_Word *offs) + /* Get the call file index number in CU DIE */ + static int die_get_call_fileno(Dwarf_Die *in_die) + { +- Dwarf_Sword idx; ++ Dwarf_Word idx; + +- if (die_get_attr_sdata(in_die, DW_AT_call_file, &idx) == 0) ++ if (die_get_attr_udata(in_die, DW_AT_call_file, &idx) == 0) + return (int)idx; + else + return -ENOENT; +@@ -478,9 +465,9 @@ static int die_get_call_fileno(Dwarf_Die *in_die) + /* Get the declared file index number in CU DIE */ + static int die_get_decl_fileno(Dwarf_Die *pdie) + { +- Dwarf_Sword idx; ++ Dwarf_Word idx; + +- if (die_get_attr_sdata(pdie, DW_AT_decl_file, &idx) == 0) ++ if (die_get_attr_udata(pdie, DW_AT_decl_file, &idx) == 0) + return (int)idx; + else + return -ENOENT; +diff --git a/tools/testing/selftests/net/arp_ndisc_evict_nocarrier.sh b/tools/testing/selftests/net/arp_ndisc_evict_nocarrier.sh +index b5af08af85595..4a110bb01e53e 100755 +--- a/tools/testing/selftests/net/arp_ndisc_evict_nocarrier.sh ++++ b/tools/testing/selftests/net/arp_ndisc_evict_nocarrier.sh +@@ -18,14 +18,15 @@ readonly V4_ADDR1=10.0.10.2 + readonly V6_ADDR0=2001:db8:91::1 + readonly V6_ADDR1=2001:db8:91::2 + nsid=100 ++ret=0 + + cleanup_v6() + { + ip netns del me + ip netns del peer + +- sysctl -w net.ipv4.conf.veth0.ndisc_evict_nocarrier=1 >/dev/null 2>&1 +- sysctl -w net.ipv4.conf.all.ndisc_evict_nocarrier=1 >/dev/null 2>&1 ++ sysctl -w net.ipv6.conf.veth1.ndisc_evict_nocarrier=1 >/dev/null 2>&1 ++ sysctl -w net.ipv6.conf.all.ndisc_evict_nocarrier=1 >/dev/null 2>&1 + } + + create_ns() +@@ -61,7 +62,7 @@ setup_v6() { + if [ $? -ne 0 ]; then + cleanup_v6 + echo "failed" +- exit ++ exit 1 + fi + + # Set veth2 down, which will put veth1 in NOCARRIER state +@@ -88,7 +89,7 @@ setup_v4() { + if [ $? -ne 0 ]; then + cleanup_v4 + echo "failed" +- exit ++ exit 1 + fi + + # Set veth1 down, which will put veth0 in NOCARRIER state +@@ -115,6 +116,7 @@ run_arp_evict_nocarrier_enabled() { + + if [ $? -eq 0 ];then + echo "failed" ++ ret=1 + else + echo "ok" + fi +@@ -134,6 +136,7 @@ run_arp_evict_nocarrier_disabled() { + echo "ok" + else + echo "failed" ++ ret=1 + fi + + cleanup_v4 +@@ -164,6 +167,7 @@ run_ndisc_evict_nocarrier_enabled() { + + if [ $? -eq 0 ];then + echo "failed" ++ ret=1 + else + echo "ok" + fi +@@ -182,6 +186,7 @@ run_ndisc_evict_nocarrier_disabled() { + echo "ok" + else + echo "failed" ++ ret=1 + fi + + cleanup_v6 +@@ -198,6 +203,7 @@ run_ndisc_evict_nocarrier_disabled_all() { + echo "ok" + else + echo "failed" ++ ret=1 + fi + + cleanup_v6 +@@ -218,3 +224,4 @@ if [ "$(id -u)" -ne 0 ];then + fi + + run_all_tests ++exit $ret |