lkml.org 
[lkml]   [2023]   [Jan]   [12]   [last100]   RSS Feed
Views: [wrap][no wrap]   [headers]  [forward] 
 
Messages in this thread
    Patch in this message
    /
    From
    SubjectRe: Linux 6.0.19
    Date
    diff --git a/Makefile b/Makefile
    index 0104f69d30bb..b978809a1c7c 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 aecc403b2880..7f092cb55a41 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 01c132bc33d5..4d06de77d92a 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 855450bed9f5..ec0cab9fbddd 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 cb6ff7dccb92..de8474146a9b 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 06ad95ae78ce..2d6915fe7385 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 9730c88530fc..305514431f26 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 ff04e9290715..f46c87ef951d 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 31a8715d3a4d..ebb5c846d826 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 dd9a05174726..53931fcef0d5 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 e553ccadbcbc..e5876286828b 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 a06decee51e0..a6e9968a2ddc 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 b0ae0a454404..0ce2bf4b8b58 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 33ab56769595..f85d2c066877 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 238f3210970c..bc5660f61c57 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 d597e2656c47..2fb7bf47f41a 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 647220a8762d..30f145dc8724 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 6659630303a3..ba5a09c2b3ce 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 379e65ea8afb..adb369bb7295 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 bfe0fc258fc1..60ab2d952d5c 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 6c83a519b3a1..febf0e9f7af1 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 3f0a4a415907..35a9b702508a 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 895bbd20dd07..68f2eb215e81 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 9f1c209d9251..e08ed0e9f165 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 ce0eb03709c3..80c60754a5c1 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 d6fe94cd0fdb..8342d95f56cb 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 ea5f594955df..4b05f310071c 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 d4b907889a21..cd399b0b7181 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 8065ca5d8de9..4f55961848a8 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 2fa5afe21288..919e6cc04982 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 293e799e2fe8..3c812fbd126f 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 8088d5fd8480..ad2877eeeccd 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 945758f39523..3e1272695d99 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 40d9410ec303..cf953d23d18d 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 e58a1e0cadd2..9270977e6c7f 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 771f2a533d3f..7807113e0910 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 7a2445a34eb7..e3181d5471df 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 300c9345ee2b..3587f75807d0 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 e36ecc9777f4..342e9d945dfb 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 8c8b4c88c7de..451c3a1b6255 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 39242c5a1729..108506721bcf 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 41c821348476..413714f373ff 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 1bdce99bf688..2cb141079474 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 f342bb853189..2ee2cd4a1e35 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 22d4fc547a0a..a9ccc4258ee5 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 4e97b4869522..0c5c1b155683 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 57cabe20aa12..1b38295254e2 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 d5fa43cfe524..02741d499bf4 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 c3065ec0a479..36d5202c0aee 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 505911ae095d..ea430d6961df 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 7d4ae467f3ad..abcd7877f7d2 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 44d4265f109a..d5d7fae354e7 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 7e8a60f2401c..d2dde3f1fb88 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 18caddd541f8..14473e29fe03 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 e1012f7f9b73..04ff9bf12185 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(&param->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(&param->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(&param->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(&param->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(&param->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(&param->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(&param->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(&param);

    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 26f87330173e..c551508e6932 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 056c904b83cc..79fa65d1cf20 100644
    --- a/drivers/net/ethernet/intel/ice/ice_xsk.c
    +++ b/drivers/net/ethernet/intel/ice/ice_xsk.c
    @@ -772,7 +772,7 @@ int ice_clean_rx_irq_zc(struct ice_rx_ring *rx_ring, int budget)
    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 9c2baa437c23..2926d754ade8 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 66c6a7017695..97e9ec44a759 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 864ce0c393e6..f01f7dfdbcf8 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 @@ mlx5_tc_ct_init_check_support(struct mlx5e_priv *priv,
    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 ff73d25bc6eb..2aaf8ab857b8 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 f5b26f5a7de4..054d80c4e65c 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 6cf6a81775a8..5c16efb8be81 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 60a73990017c..6b4c9ffad95b 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 b1a5199260f6..093ed86a0acd 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 59cffa49e4b5..940e893f3f09 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 5ceed4e6c658..03080e8161cb 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 2cf2c9948446..0ed239eadf39 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 c02b7b08fb4c..2032d5c0ad86 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 bbe810f3b373..c142011d2097 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 ac178796e484..0a2f23a7082a 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 @@ static int mlx5_init_once(struct mlx5_core_dev *dev)
    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 f141644e4372..26c5cdf373c4 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 e58de119186a..a2d0631f7ac7 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 86ecb080b153..cdcead614e9f 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 dbb800769cb6..c95d56e56c59 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 7519773eaca6..22afa2be85fd 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 28476b982bab..44dac3c0908e 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 8dcb49ed1f3d..7fd9fe6a602b 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 f79333fe1783..7b3739b29c8f 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 466da01ba2e3..909427d99a59 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 c28c4a654615..c312d16f580c 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 5df7a0abc39d..f7f40e3fe9cc 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 c3285242f74f..a03752ef544f 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 30f0765fb9fd..237f4ec2cffd 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 3582a28a1dce..f06bae83e8ee 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 70555022cb44..35352206b5de 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 fc8a957fad0a..4aaa27cc8d2b 100644
    --- a/drivers/nvme/target/admin-cmd.c
    +++ b/drivers/nvme/target/admin-cmd.c
    @@ -164,26 +164,29 @@ static void nvmet_execute_get_log_page_smart(struct nvmet_req *req)

    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 1c573e7a60bc..f4bfaf1669fb 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 0feda8eb93b5..5e011520650d 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 8c42e7662033..92ed1213fe37 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 67b237c7a76a..550ae64350df 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 c2075b90f3df..40f75ba53e80 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 90913365def4..444d6572b2d0 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 225b7f5d8be3..6489f44bca1a 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 c8bfea3b7db2..cc0534f8ae93 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 886449e88502..c2e19dd06419 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 04522077735b..f4e375b1d903 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 166044642fd5..ec32f785dfde 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 40097826cff0..3c2359570df9 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 11f59dd06a74..828c29306565 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 5703775af129..10a7d23731fe 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 68bba2688f4c..3d1bca3bcd4f 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 06be0644dd37..6ce704d3bdd2 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 bad06add93d7..8e77acdecd25 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 aa4bc213d301..23bb51e46e59 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 @@ static int btrfs_read_roots(struct btrfs_fs_info *fs_info)
    * 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 @@ int btrfs_start_pre_rw_mount(struct btrfs_fs_info *fs_info)
    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 47ad8e0a2d33..7322af63c0cc 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 cf4f19e80e2f..0982995177a6 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 4fff0067bd2a..c498d5e164eb 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 5c1a617eb25d..5c2b66d155ef 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 ad3ce9700eaf..01c381e75cdb 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 00b97e6eb507..897367ba68d2 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 0bec10740ad3..8fab3b274957 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 b6cf39f4e7e4..072ab9a1374b 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 6f006430115a..55c8bf9a5c89 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 02b5c0ac5654..af8dbcf932ab 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 3e2843e86e27..b191426bf880 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 40630e6f691c..ae4126f63410 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 5d93154572c0..4ef2d08de5b6 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 74052b51655e..05c9c75360fa 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 2eae6e038f38..ac083526c115 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 a0746be3c1de..80d17c520d0b 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 c5a5c7b90d72..93b2290addd5 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 756ad631c019..eab9950b5a68 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 7a9497a7b0a3..a71a7cc0e576 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 @@ int smb2_tree_connect(struct ksmbd_work *work)
    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 143bba4e4db8..434891db42a2 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 607f94a0e789..7dc129cc1a26 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 2960d0a8e8f9..355164a52754 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 4bb5baa17040..011c556caa1e 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 4f2ffc7ef296..f31c0389a2e7 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 b9a83820e1ad..3c380140515d 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 b1b5720d89a5..ee657452f122 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 f87b2f5db9f8..4f51616f01b2 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 8e79a761c56c..17a1a57adbe0 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 b5f58fd37a0f..4b00221f57e2 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 4acd5610e96b..e640c27b1b6d 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 ada1296c87d5..72f5ebc5c97a 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 cd188a527d16..3b35b6f6533a 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 cdb7db9b0e25..1daededfa75e 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 7ada84e4a3ed..5655e89b962b 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 b8a39be3bcb4..9c49a1a4ceda 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 41b67eb83ab3..2fb6d8e196e6 100644
    --- a/kernel/bpf/trampoline.c
    +++ b/kernel/bpf/trampoline.c
    @@ -501,6 +501,10 @@ static int bpf_trampoline_update(struct bpf_trampoline *tr, bool lock_direct_mut
    /* 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 8464d95805d0..1f50dce8765d 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 @@ p9_client_rpc(struct p9_client *c, int8_t type, const char *fmt, ...)
    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 @@ p9_client_rpc(struct p9_client *c, int8_t type, const char *fmt, ...)
    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 080b5de3e1ed..a2eb1363d293 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 d817d3745238..d8b0a6f3b15e 100644
    --- a/net/9p/trans_rdma.c
    +++ b/net/9p/trans_rdma.c
    @@ -507,7 +507,7 @@ static int rdma_request(struct p9_client *client, struct p9_req_t *req)
    * 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 @@ static int rdma_request(struct p9_client *client, struct p9_req_t *req)

    /* 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 b84d35cf6899..947c038a0470 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 @@ p9_virtio_zc_request(struct p9_client *client, struct p9_req_t *req,
    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 0f862d5a5960..a103aed85465 100644
    --- a/net/9p/trans_xen.c
    +++ b/net/9p/trans_xen.c
    @@ -157,7 +157,7 @@ static int p9_xen_request(struct p9_client *client, struct p9_req_t *p9_req)
    &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 2809cbd6b7f7..d8cb4b2a076b 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 3aae1885b970..50d685be517d 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 971969cc7e17..fb01211a255b 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 9ae50b1bd844..05b6077b9f2c 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 42d5e0a7952a..a2cc25cca33e 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 c1eaa1685592..df6937c8cf54 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 613f515fedf0..9d3701fdb293 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 6b31746f9be3..751ac89b07a5 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 75d556d71652..24adcdd7a0b1 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 153de3457423..a22ec1a6f6ec 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 7303138e46be..10481760a9b2 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 334fb1ad0e86..39a01934b153 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 7df94f437f60..5c6de605a9fb 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 1422739d9aa2..ce0a9ce5a91f 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 9810f5bf63f5..031073286236 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 3d09eefe998a..c07b70bf32db 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 09cf72eb37f8..d1a0628df4ef 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 19bcdb3141f6..005a7ce87217 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 7977f0422ecf..e0c156bb0b17 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 7c62417ccfd7..32a08ae9ad11 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 742c7d49a958..8d1ef858db87 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 816fd0d7ba38..28e1897e0da7 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 ba99ce05cd52..5d9f4f259d69 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 7bb247c51e2f..2d7b1e03110a 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 @@ gss_create_upcall(struct gss_auth *gss_auth, struct gss_cred *gss_cred)
    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 fb9d9e271845..ddd2625bed90 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 c99b5e6c026c..694a2d94a222 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 eddfd77ad90f..0ab111814f1c 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 5ef3e8775e36..554891e78cca 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 6dfb4786c782..0173e5b255da 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 1e0769c668a7..de8dbe27cd0d 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 ea40ae52cd2c..2bc9231d86b6 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 3c2df7522f6f..1c82377ed78b 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 e99b41f9be45..cd978c240e0d 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 a7f68c309545..fc16299c915f 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 609ca1671501..623527edeac1 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 b5af08af8559..4a110bb01e53 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
    \
     
     \ /
      Last update: 2023-03-26 23:37    [W:2.817 / U:1.132 seconds]
    ©2003-2020 Jasper Spaans|hosted at Digital Ocean and TransIP|Read the blog|Advertise on this site